use crate::{Channel, Message, Platform};
struct Rng(u64);
impl Rng {
fn next(&mut self) -> u64 {
let mut x = self.0;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
self.0 = x;
x
}
fn below(&mut self, n: u64) -> u64 {
self.next() % n.max(1)
}
fn pick<'a, T>(&mut self, xs: &'a [T]) -> &'a T {
&xs[self.below(xs.len() as u64) as usize]
}
fn unit(&mut self) -> f64 {
(self.next() >> 11) as f64 / (1u64 << 53) as f64
}
}
const USERS: &[&str] = &[
"forsen",
"nymn",
"pajlada",
"supibot",
"mel",
"kkona",
"wide",
"peeposit",
"gigachad",
"monkas",
"widepeepo",
"hasanabi",
"vedal",
"neuro",
"anon",
];
const WORDS: &[&str] = &[
"GAMBA",
"OMEGALUL",
"Sadge",
"PepeLaugh",
"gigachad moment",
"actual clip",
"no way",
"chat is this real",
"COPIUM",
"based",
"ratio",
"Nerd",
"KEKW",
"this is peak",
"mods asleep",
"PogU",
"sptvJAM",
"Aware",
];
struct Seed {
name: &'static str,
platform: Platform,
activity: f64,
}
const SEEDS: &[Seed] = &[
Seed {
name: "xqc",
platform: Platform::Twitch,
activity: 7.0,
},
Seed {
name: "forsen",
platform: Platform::Twitch,
activity: 2.5,
},
Seed {
name: "hasanabi",
platform: Platform::Twitch,
activity: 1.0,
},
Seed {
name: "trainwreckstv",
platform: Platform::Kick,
activity: 11.0,
},
Seed {
name: "adin",
platform: Platform::Kick,
activity: 0.4,
},
];
pub fn channels() -> Vec<Channel> {
SEEDS
.iter()
.map(|s| Channel::new(s.name, s.platform, 200))
.collect()
}
pub struct Driver {
rng: Rng,
clock_ms: u64,
activity: Vec<f64>,
}
impl Default for Driver {
fn default() -> Driver {
Driver::new()
}
}
impl Driver {
pub fn new() -> Driver {
Driver {
rng: Rng(0x9E3779B97F4A7C15),
clock_ms: 1,
activity: SEEDS.iter().map(|s| s.activity).collect(),
}
}
pub fn tick(&mut self, channels: &mut [Channel]) {
self.clock_ms += 350;
let now = self.clock_ms;
for (i, ch) in channels.iter_mut().enumerate() {
ch.cool(now);
let spike = self.rng.unit() < 0.03;
let mult = if spike { 6.0 } else { 1.0 };
let mut budget = self.activity.get(i).copied().unwrap_or(1.0) * mult;
while budget > 0.0 {
if self.rng.unit() < budget.min(1.0) {
let user = self.rng.pick(USERS).to_string();
let text = self.rng.pick(WORDS).to_string();
ch.record(
Message {
user,
text,
color: None,
heat: 0.0,
},
now,
);
}
budget -= 1.0;
}
}
}
}