1use crate::report;
4use anyhow::{Context, Result};
5use serde_json::Value;
6use std::{fmt::Write as _, path::Path};
7
8pub(crate) fn cell(value: &str) -> String {
9 value
10 .replace('&', "&")
11 .replace('<', "<")
12 .replace('>', ">")
13 .replace('|', "|")
14 .replace(['\n', '\r'], " ")
15}
16
17pub(crate) fn link(path: &Path) -> String {
18 path.to_string_lossy()
19 .replace('%', "%25")
20 .replace(' ', "%20")
21 .replace('#', "%23")
22 .replace('?', "%3F")
23 .replace('(', "%28")
24 .replace(')', "%29")
25}
26
27pub(crate) fn answers(data: &Value) -> Result<String> {
28 let mut rows = String::new();
29
30 for run in data["runs"].as_array().context("runs")? {
31 let Some(output) = run["output"].as_str() else {
32 continue;
33 };
34
35 writeln!(
36 rows,
37 "| [{}]({}) | {} |",
38 cell(report::text(&run["id"])),
39 link(Path::new(output)),
40 cell(report::text(&run["status"]))
41 )?;
42 }
43
44 if rows.is_empty() {
45 return Ok(rows);
46 }
47
48 Ok(format!(
49 "\n## Answers\n\n| Sample | Status |\n| --- | --- |\n{rows}"
50 ))
51}
52
53pub(crate) fn label(config: &Value) -> &str {
54 if config["id"] == "misses-2bit" {
55 return "4-bit / 2-bit misses + cut";
56 }
57
58 report::text(&config["label"])
59}
60
61pub(crate) fn drawings(data: &Value, directory: &Path) -> Result<String> {
62 let runs = data["runs"].as_array().context("runs")?;
63 let mut images = Vec::new();
64
65 for config in data["configurations"]
66 .as_array()
67 .context("configurations")?
68 {
69 let run = runs.iter().rev().find(|r| {
70 r["configuration"] == config["id"] && r["status"] == "ok" && r["svg"].is_string()
71 });
72 let Some(run) = run else {
73 continue;
74 };
75 let title = cell(label(config));
76 let path = link(&directory.join(run["svg"].as_str().unwrap()));
77
78 images.push((title, format!("")));
79 }
80
81 let mut text = String::new();
82
83 for pair in images.chunks(2) {
84 writeln!(
85 text,
86 "| {} |",
87 pair.iter()
88 .map(|p| p.0.as_str())
89 .collect::<Vec<_>>()
90 .join(" | ")
91 )?;
92 writeln!(text, "| {} |", vec!["---"; pair.len()].join(" | "))?;
93 writeln!(
94 text,
95 "| {} |\n",
96 pair.iter()
97 .map(|p| p.1.as_str())
98 .collect::<Vec<_>>()
99 .join(" | ")
100 )?;
101 }
102
103 Ok(text)
104}