nice_dice/
html.rs

1//! HTML formatting for dice expressions and distributions, mostly distributions.
2
3use crate::Distribution;
4
5/// A table showing the various distributions as bar charts.
6pub fn table_multi_dist(inputs: &[(impl AsRef<str>, Distribution)]) -> maud::PreEscaped<String> {
7    // We need to know the minimum value, maximum value, and maximum frequency.
8    let min = inputs
9        .iter()
10        .fold(isize::MAX, |acc, (_, dist)| std::cmp::min(acc, dist.min()));
11    let max = inputs
12        .iter()
13        .fold(isize::MIN, |acc, (_, dist)| std::cmp::max(acc, dist.max()));
14    let rows = (min..=max)
15        .map(|value| -> (isize, Vec<f64>) {
16            (
17                value,
18                inputs
19                    .iter()
20                    .map(|(_, distr)| distr.probability_f64(value))
21                    .collect(),
22            )
23        })
24        .collect::<Vec<_>>();
25    let max = rows
26        .iter()
27        .flat_map(|(_, v)| v.iter())
28        .fold(0.0, |acc, v| if acc > *v { acc } else { *v });
29
30    // TODO: Add charts.css colors
31    maud::html! {
32        table class="charts-css bar [ show-data-on-hover data-start ] multiple show-heading show-labels" style="--labels-size: 16pt"{
33            thead {
34                @for (name, _) in inputs { th scope="col" { (name.as_ref()) } }
35            }
36            @for (value, row) in rows.into_iter() {
37                tr {
38                    th scope="row" { (value) }
39                    @for freq in row {
40                        @let size = freq / max;
41                        td style=(format!("--size: {}", size)) { span class="data" { (format!("{:.1}%", freq * 100.0)) }}
42                    }
43                }
44            }
45        }
46    }
47}