glacier-web-cli 0.5.0

Command-line tool for creating and running Glacier applications.
{# axes: the qualities, in a fixed order (5 to 8); series: (name, one score per axis), at most three; all on 0..max. #}
{% props label: String, axes: Vec<String>, series: Vec<(String, Vec<f64>)>, max: f64 = 100.0 %}
{%- let n = axes.len().max(1) as f64 %}
{%- let at = |i: usize, f: f64| { let a = -std::f64::consts::FRAC_PI_2 + std::f64::consts::TAU * i as f64 / n; (150.0 + a.cos() * 92.0 * f, 120.0 + a.sin() * 92.0 * f) } %}
{%- let ring = |f: f64| (0..axes.len()).map(|i| { let (px, py) = at(i, f); format!("{px:.1},{py:.1}") }).collect::<Vec<_>>().join(" ") %}
{%- let shape = |values: &[f64]| values.iter().enumerate().map(|(i, v)| { let (px, py) = at(i, (v / max).clamp(0.0, 1.0)); format!("{px:.1},{py:.1}") }).collect::<Vec<_>>().join(" ") %}
{%- let num = |v: f64| if v.fract() == 0.0 { format!("{}", v as i64) } else { format!("{v:.1}") } %}
{%- if series.len() > 1 %}
<ul class="ui-chart-legend">{% for (j, (name, _)) in series.iter().enumerate() %}<li class="s{{ j + 1 }}"><span class="ui-chart-swatch"></span>{{ name }}</li>{% end %}</ul>
{%- end %}
<div class="ui-chart">
  <svg viewBox="0 0 300 240" role="img" aria-label="{{ label }}">
    <g class="grid">
      {%- for k in 1..=4 %}<polygon points="{{ ring(k as f64 / 4.0) }}"/>{% end %}
      {%- for i in 0..axes.len() %}{% let (px, py) = at(i, 1.0) %}<line x1="150" y1="120" x2="{{ format!("{px:.1}") }}" y2="{{ format!("{py:.1}") }}"/>{% end %}
    </g>
    {%- for (j, (_, values)) in series.iter().enumerate() %}
    <g class="s{{ j + 1 }}"><polygon class="radar" points="{{ shape(values) }}"/></g>
    {%- end %}
    <g class="axis">
      {%- for (i, axis) in axes.iter().enumerate() %}
      {%- let (px, py) = at(i, 1.13) %}
      {%- let anchor = if (px - 150.0).abs() < 8.0 { "middle" } else if px > 150.0 { "start" } else { "end" } %}
      <text x="{{ format!("{px:.1}") }}" y="{{ format!("{:.1}", py + 4.0) }}" text-anchor="{{ anchor }}">{{ axis }}</text>
      {%- end %}
    </g>
  </svg>
</div>
<details class="ui-details">
  <summary><svg class="ui-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m9 18 6-6-6-6"/></svg>View as table</summary>
  <div class="ui-table-wrap"><table class="ui-table">
    <thead><tr><th>Quality</th>{% for (name, _) in series.iter() %}<th class="ui-num">{{ name }}</th>{% end %}</tr></thead>
    <tbody>{% for (i, axis) in axes.iter().enumerate() %}<tr><td>{{ axis }}</td>{% for (_, values) in series.iter() %}<td class="ui-num">{{ values.get(i).map(|v| num(*v)).unwrap_or_default() }}</td>{% end %}</tr>{% end %}</tbody>
  </table></div>
</details>