1use std::collections::BTreeSet;
2
3#[derive(Copy, Clone, Debug, Eq, PartialEq)]
5pub enum ModelTopology {
6 ScalarChain,
8 SetResourceOutput,
10}
11
12#[derive(Clone, Debug, Eq, PartialEq)]
14pub enum ModelStep {
15 SetMembers(BTreeSet<u8>),
17 RebaselineOutput,
19 ClosePrimaryScope,
21}
22
23#[derive(Clone, Debug, Eq, PartialEq)]
25pub struct ModelScript {
26 pub topology: ModelTopology,
28 pub steps: Vec<ModelStep>,
30}
31
32#[derive(Clone, Debug)]
34pub struct ModelGenerator {
35 state: u64,
36}
37
38impl ModelGenerator {
39 pub const fn new(seed: u64) -> Self {
41 Self { state: seed }
42 }
43
44 pub fn script(&mut self, step_count: usize) -> ModelScript {
46 let topology = if self.next_u8().is_multiple_of(2) {
47 ModelTopology::ScalarChain
48 } else {
49 ModelTopology::SetResourceOutput
50 };
51 let mut steps = Vec::with_capacity(step_count);
52 let close_at = step_count.saturating_sub(1);
53 for index in 0..step_count {
54 let roll = self.next_u8();
55 let step = if index == close_at && step_count > 2 && roll.is_multiple_of(5) {
56 ModelStep::ClosePrimaryScope
57 } else if roll.is_multiple_of(7) {
58 ModelStep::RebaselineOutput
59 } else {
60 ModelStep::SetMembers(self.members())
61 };
62 steps.push(step);
63 }
64 ModelScript { topology, steps }
65 }
66
67 fn members(&mut self) -> BTreeSet<u8> {
68 let width = usize::from(self.next_u8() % 4);
69 let mut members = BTreeSet::new();
70 for _ in 0..width {
71 members.insert(self.next_u8() % 6);
72 }
73 members
74 }
75
76 fn next_u8(&mut self) -> u8 {
77 self.state = self
78 .state
79 .wrapping_mul(6_364_136_223_846_793_005)
80 .wrapping_add(1);
81 (self.state >> 32) as u8
82 }
83}