1use crate::{Channel, Message, Platform};
7
8struct Rng(u64);
9impl Rng {
10 fn next(&mut self) -> u64 {
11 let mut x = self.0;
12 x ^= x << 13;
13 x ^= x >> 7;
14 x ^= x << 17;
15 self.0 = x;
16 x
17 }
18 fn below(&mut self, n: u64) -> u64 {
19 self.next() % n.max(1)
20 }
21 fn pick<'a, T>(&mut self, xs: &'a [T]) -> &'a T {
22 &xs[self.below(xs.len() as u64) as usize]
23 }
24 fn unit(&mut self) -> f64 {
25 (self.next() >> 11) as f64 / (1u64 << 53) as f64
26 }
27}
28
29const USERS: &[&str] = &[
30 "forsen",
31 "nymn",
32 "pajlada",
33 "supibot",
34 "mel",
35 "kkona",
36 "wide",
37 "peeposit",
38 "gigachad",
39 "monkas",
40 "widepeepo",
41 "hasanabi",
42 "vedal",
43 "neuro",
44 "anon",
45];
46
47const WORDS: &[&str] = &[
48 "GAMBA",
49 "OMEGALUL",
50 "Sadge",
51 "PepeLaugh",
52 "gigachad moment",
53 "actual clip",
54 "no way",
55 "chat is this real",
56 "COPIUM",
57 "based",
58 "ratio",
59 "Nerd",
60 "KEKW",
61 "this is peak",
62 "mods asleep",
63 "PogU",
64 "sptvJAM",
65 "Aware",
66];
67
68struct Seed {
70 name: &'static str,
71 platform: Platform,
72 activity: f64,
73}
74
75const SEEDS: &[Seed] = &[
76 Seed {
77 name: "xqc",
78 platform: Platform::Twitch,
79 activity: 7.0,
80 },
81 Seed {
82 name: "forsen",
83 platform: Platform::Twitch,
84 activity: 2.5,
85 },
86 Seed {
87 name: "hasanabi",
88 platform: Platform::Twitch,
89 activity: 1.0,
90 },
91 Seed {
92 name: "trainwreckstv",
93 platform: Platform::Kick,
94 activity: 11.0,
95 },
96 Seed {
97 name: "adin",
98 platform: Platform::Kick,
99 activity: 0.4,
100 },
101];
102
103pub fn channels() -> Vec<Channel> {
105 SEEDS
106 .iter()
107 .map(|s| Channel::new(s.name, s.platform, 200))
108 .collect()
109}
110
111pub struct Driver {
113 rng: Rng,
114 clock_ms: u64,
115 activity: Vec<f64>,
116}
117
118impl Default for Driver {
119 fn default() -> Driver {
120 Driver::new()
121 }
122}
123
124impl Driver {
125 pub fn new() -> Driver {
126 Driver {
127 rng: Rng(0x9E3779B97F4A7C15),
128 clock_ms: 1,
129 activity: SEEDS.iter().map(|s| s.activity).collect(),
130 }
131 }
132
133 pub fn tick(&mut self, channels: &mut [Channel]) {
136 self.clock_ms += 350;
137 let now = self.clock_ms;
138 for (i, ch) in channels.iter_mut().enumerate() {
139 ch.cool(now);
140 let spike = self.rng.unit() < 0.03;
141 let mult = if spike { 6.0 } else { 1.0 };
142 let mut budget = self.activity.get(i).copied().unwrap_or(1.0) * mult;
143 while budget > 0.0 {
144 if self.rng.unit() < budget.min(1.0) {
145 let user = self.rng.pick(USERS).to_string();
146 let text = self.rng.pick(WORDS).to_string();
147 ch.record(
148 Message {
149 user,
150 text,
151 color: None,
152 heat: 0.0,
153 },
154 now,
155 );
156 }
157 budget -= 1.0;
158 }
159 }
160 }
161}