///|
/// Human-facing simulation report.
pub(all) struct SimulationReport {
name : String
size : Size
steps : Int
mass : Double
max_speed : Double
kinetic_energy : Double
density_variation : Double
stable : Bool
health_pass : Bool
} derive(Debug)
///|
/// Build a report from a reusable simulation.
pub fn Simulation::report(
self : Simulation,
name? : String = "simulation",
) -> SimulationReport {
let stability = self.stability()
let health = self.health()
{
name,
size: self.size,
steps: self.step_count,
mass: stability.mass,
max_speed: stability.max_speed,
kinetic_energy: self.kinetic_energy(),
density_variation: self.density_variation(),
stable: stability.recommended,
health_pass: health.pass,
}
}
///|
/// Format a report as CSV.
pub fn SimulationReport::to_csv(self : SimulationReport) -> String {
"\{self.name},\{self.size.width},\{self.size.height},\{self.steps},\{self.mass},\{self.max_speed},\{self.kinetic_energy},\{self.density_variation},\{self.stable},\{self.health_pass}\n"
}
///|
/// Format a report as a Markdown table row.
pub fn SimulationReport::to_markdown(self : SimulationReport) -> String {
"| \{self.name} | \{self.size.width}x\{self.size.height} | \{self.steps} | \{self.mass} | \{self.max_speed} | \{self.kinetic_energy} | \{self.density_variation} | \{self.stable} | \{self.health_pass} |"
}
///|
/// Format a report as a small JSON object.
pub fn SimulationReport::to_json(self : SimulationReport) -> String {
"{\"name\":\"\{self.name}\",\"width\":\{self.size.width},\"height\":\{self.size.height},\"steps\":\{self.steps},\"mass\":\{self.mass},\"max_speed\":\{self.max_speed},\"kinetic_energy\":\{self.kinetic_energy},\"stable\":\{self.stable},\"health_pass\":\{self.health_pass}}"
}
///|
/// Report CSV header.
pub fn simulation_report_header() -> String {
"name,width,height,steps,mass,max_speed,kinetic_energy,density_variation,stable,health_pass\n"
}
///|
/// Combine several reports into a Markdown table.
pub fn reports_to_markdown(reports : ArrayView[SimulationReport]) -> String {
let builder = StringBuilder(size_hint=256 + reports.length() * 128)
builder.write_string(
"| name | size | steps | mass | max speed | energy | density variation | stable | health |\n",
)
builder.write_string("|---|---:|---:|---:|---:|---:|---:|:---:|:---:|\n")
for report in reports {
builder.write_string(report.to_markdown())
builder.write_char('\n')
}
builder.to_string()
}
///|
/// Return true when every report passes its numerical health gate.
pub fn reports_are_healthy(reports : ArrayView[SimulationReport]) -> Bool {
let mut result = true
for report in reports {
result = result && report.health_pass
}
result
}