pickems/reporting/
basic.rs1use std::{
2 iter::Sum,
3 ops::{Add, AddAssign},
4};
5
6use crate::{
7 reporting::Report,
8 simulation::{Simulation, SwissSystem},
9};
10
11#[derive(Debug, Clone, Copy, Default)]
13pub struct BasicStats {
14 pub three_zero: u64,
16 pub advancing: u64,
18 pub zero_three: u64,
20}
21
22impl AddAssign for BasicStats {
23 fn add_assign(&mut self, rhs: Self) {
24 self.three_zero += rhs.three_zero;
25 self.advancing += rhs.advancing;
26 self.zero_three += rhs.zero_three;
27 }
28}
29
30#[derive(Debug, Clone, Copy, Default)]
32pub struct BasicReport {
33 pub stats: [BasicStats; 16],
35}
36
37impl BasicReport {
38 pub(super) fn calculate_probabilities(&self, sim: &Simulation) -> [[f32; 16]; 3] {
40 let n = sim.iterations as f32;
41 let [mut three_zero, mut advancing, mut zero_three] = [[0.0; 16]; 3];
42
43 for seed in 0..16 {
44 three_zero[seed] += self.stats[seed].three_zero as f32;
45 advancing[seed] += self.stats[seed].advancing as f32;
46 zero_three[seed] += self.stats[seed].zero_three as f32;
47 }
48
49 for seed in 0..16 {
50 three_zero[seed] /= n;
51 advancing[seed] /= n;
52 zero_three[seed] /= n;
53 }
54
55 [three_zero, advancing, zero_three]
56 }
57}
58
59impl Add for BasicReport {
60 type Output = Self;
61
62 fn add(mut self, rhs: Self) -> Self::Output {
63 for i in 0..self.stats.len() {
64 self.stats[i] += rhs.stats[i];
65 }
66
67 self
68 }
69}
70
71impl Sum for BasicReport {
72 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
73 iter.fold(Self::default(), |acc, report| acc + report)
74 }
75}
76
77impl Report for BasicReport {
78 fn update(&mut self, ss: &SwissSystem) {
79 for (seed, result) in self.stats.iter_mut().enumerate() {
80 match (ss.wins[seed], ss.losses[seed]) {
81 (3, 0) => result.three_zero += 1,
82 (3, _) => result.advancing += 1,
83 (0, 3) => result.zero_three += 1,
84 _ => {}
85 }
86 }
87 }
88
89 fn format(&self, sim: &Simulation) -> String {
90 let probabilities = self.calculate_probabilities(sim);
91 let mut out = Vec::new();
92
93 let fields: [(usize, &str); 3] = [(0, "3-0"), (1, "3-1 or 3-2"), (2, "0-3")];
95
96 for (index, title) in fields {
98 out.push(format!("\nMost likely to {title}:"));
99
100 let mut results = sim
101 .teams
102 .names
103 .iter()
104 .zip(probabilities[index])
105 .collect::<Vec<_>>();
106
107 results.sort_by(|(_, a), (_, b)| b.total_cmp(a));
108
109 for (i, (name, result)) in results.into_iter().enumerate() {
111 out.push(format!(
112 "{num:<4}{name:<20}{percent:>6.1}%",
113 num = format!("{}.", i + 1),
114 name = name,
115 percent = (result * 1000.0).round() / 10.0
116 ));
117 }
118 }
119
120 out.join("\n")
121 }
122}