///|
pub struct ReportBuilder {
value : ChemReport
history : Array[String]
} derive(Debug, Eq)
///|
pub fn report_builder(value : ChemReport) -> ReportBuilder {
{ value, history: ["created"] }
}
///|
fn ReportBuilder::record(
self : ReportBuilder,
event : String,
value : ChemReport,
) -> ReportBuilder {
let history = self.history.copy()
history.push(event)
{ value, history }
}
///|
pub fn ReportBuilder::add_assumption(
self : ReportBuilder,
statement : String,
impact : String,
) -> ReportBuilder {
let assumptions = self.value.assumptions.copy()
assumptions.push({ statement, impact })
self.record("assumption-added", { ..self.value, assumptions, })
}
///|
pub fn ReportBuilder::add_input(
self : ReportBuilder,
name : String,
value : String,
unit : String?,
note : String?,
) -> ReportBuilder {
let inputs = self.value.inputs.copy()
inputs.push({ name, value, unit, note })
self.record("input-added", { ..self.value, inputs, })
}
///|
pub fn ReportBuilder::add_formula(
self : ReportBuilder,
name : String,
expression : String,
explanation : String,
) -> ReportBuilder {
let formulas = self.value.formulas.copy()
formulas.push({ name, expression, explanation })
self.record("formula-added", { ..self.value, formulas, })
}
///|
pub fn ReportBuilder::add_result(
self : ReportBuilder,
name : String,
value : String,
unit : String?,
status : ResultStatus,
note : String?,
) -> ReportBuilder {
let results = self.value.results.copy()
results.push({ name, value, unit, status, note })
self.record("result-added", { ..self.value, results, })
}
///|
pub fn ReportBuilder::add_warning(
self : ReportBuilder,
code : String,
severity : WarningSeverity,
summary : String,
action : String,
) -> ReportBuilder {
let warnings = self.value.warnings.copy()
warnings.push({ code, severity, summary, action })
self.record("warning-added", { ..self.value, warnings, })
}
///|
pub fn ReportBuilder::add_source(
self : ReportBuilder,
label : String,
kind : SourceKind,
url : String?,
license : String?,
note : String?,
) -> ReportBuilder {
let sources = self.value.sources.copy()
sources.push({ label, kind, url, license, note })
self.record("source-added", { ..self.value, sources, })
}
///|
pub fn ReportBuilder::add_section(
self : ReportBuilder,
title : String,
kind : SectionKind,
body : String,
) -> ReportBuilder {
let sections = self.value.sections.copy()
sections.push({ title, kind, body })
self.record("section-added", { ..self.value, sections, })
}
///|
pub fn ReportBuilder::tag(self : ReportBuilder, tag : String) -> ReportBuilder {
self.record("tag-added", self.value.with_tag(tag))
}
///|
pub fn ReportBuilder::summary(
self : ReportBuilder,
text : String,
) -> ReportBuilder {
self.record("summary-updated", { ..self.value, summary: text })
}
///|
pub fn ReportBuilder::build(self : ReportBuilder) -> ChemReport {
self.value
}
///|
pub fn ReportBuilder::events(self : ReportBuilder) -> Array[String] {
self.history
}
///|
pub fn ReportBuilder::is_ready(self : ReportBuilder) -> Bool {
self.value.is_publish_ready()
}
///|
pub fn ReportBuilder::quality(self : ReportBuilder) -> QualityGate {
quality_gate(self.value)
}
///|
pub fn ChemReport::with_summary(
self : ChemReport,
summary : String,
) -> ChemReport {
{ ..self, summary, }
}
///|
pub fn ChemReport::with_metadata(
self : ChemReport,
metadata : ReportMetadata,
) -> ChemReport {
{ ..self, metadata, }
}
///|
pub fn ChemReport::with_results(
self : ChemReport,
results : Array[ResultValue],
) -> ChemReport {
{ ..self, results, }
}
///|
pub fn ChemReport::with_warnings(
self : ChemReport,
warnings : Array[WarningNote],
) -> ChemReport {
{ ..self, warnings, }
}
///|
pub fn ChemReport::with_sources(
self : ChemReport,
sources : Array[SourceRef],
) -> ChemReport {
{ ..self, sources, }
}
///|
pub fn ChemReport::format(self : ChemReport, format : String) -> String {
match format.trim() {
"markdown" | "md" => self.to_markdown()
"html" => self.to_html()
"json" => self.to_json()
_ => self.to_markdown()
}
}
///|
pub fn ChemReport::format_names(_self : ChemReport) -> Array[String] {
["markdown", "html", "json"]
}
///|
pub fn ChemReport::export_table(self : ChemReport) -> ReportTable {
let rows : Array[Array[String]] = []
for item in self.results {
rows.push([
item.name,
item.value,
item.unit.unwrap_or(""),
result_status_name(item.status),
])
}
table(["result", "value", "unit", "status"], rows)
}
///|
pub fn ChemReport::warning_table(self : ChemReport) -> ReportTable {
let rows : Array[Array[String]] = []
for item in self.warnings {
rows.push([
item.code,
severity_name(item.severity),
item.summary,
item.action,
])
}
table(["code", "severity", "summary", "action"], rows)
}
///|
pub fn ChemReport::source_table(self : ChemReport) -> ReportTable {
let rows : Array[Array[String]] = []
for item in self.sources {
rows.push([
item.label,
source_kind_name(item.kind),
item.url.unwrap_or(""),
item.license.unwrap_or(""),
])
}
table(["label", "kind", "url", "license"], rows)
}
///|
pub struct BatchReport {
reports : Array[ChemReport]
labels : Array[String]
} derive(Debug, Eq)
///|
pub fn batch_report(
reports : Array[ChemReport],
labels : Array[String],
) -> BatchReport {
{ reports, labels }
}
///|
pub fn BatchReport::count(self : BatchReport) -> Int {
self.reports.length()
}
///|
pub fn BatchReport::valid_count(self : BatchReport) -> Int {
let mut count = 0
for report in self.reports {
if report.is_publish_ready() {
count = count + 1
}
}
count
}
///|
pub fn BatchReport::invalid_count(self : BatchReport) -> Int {
self.count() - self.valid_count()
}
///|
pub fn BatchReport::all_formats(self : BatchReport) -> Array[ExportBundle] {
self.reports.map(fn(report) { report.render_all_formats() })
}
///|
pub fn BatchReport::benchmark(
self : BatchReport,
iterations : Int,
) -> BenchmarkResult {
benchmark_exports(self.reports, iterations)
}
///|
pub fn BatchReport::result_count(self : BatchReport) -> Int {
let mut count = 0
for report in self.reports {
count = count + report.results.length()
}
count
}
///|
pub fn BatchReport::warning_count(self : BatchReport) -> Int {
let mut count = 0
for report in self.reports {
count = count + report.warnings.length()
}
count
}
///|
pub fn BatchReport::critical_count(self : BatchReport) -> Int {
let mut count = 0
for report in self.reports {
count = count + report.warning_count(Critical)
}
count
}
///|
pub fn BatchReport::summary(self : BatchReport) -> String {
"reports=\{self.count()}, valid=\{self.valid_count()}, invalid=\{self.invalid_count()}, results=\{self.result_count()}, warnings=\{self.warning_count()}"
}
///|
pub fn BatchReport::to_markdown(self : BatchReport) -> String {
let rows : Array[Array[String]] = []
for index, report in self.reports {
rows.push([
self.labels.get(index).unwrap_or(""),
report.metadata.title,
report.metadata.process_unit,
if report.is_publish_ready() {
"ready"
} else {
"invalid"
},
"{report.results.length()}",
"{report.warnings.length()}",
])
}
table(
["label", "title", "process unit", "status", "results", "warnings"],
rows,
).to_markdown()
}
///|
pub fn BatchReport::to_json(self : BatchReport) -> String {
"[" + self.reports.map(fn(report) { report.to_json() }).join(",") + "]"
}
///|
pub fn merge_reports(left : ChemReport, right : ChemReport) -> ChemReport {
let assumptions = left.assumptions.copy()
assumptions.append(right.assumptions)
let inputs = left.inputs.copy()
inputs.append(right.inputs)
let formulas = left.formulas.copy()
formulas.append(right.formulas)
let results = left.results.copy()
results.append(right.results)
let warnings = left.warnings.copy()
warnings.append(right.warnings)
let sources = left.sources.copy()
sources.append(right.sources)
let sections = left.sections.copy()
sections.append(right.sections)
let tags = left.tags.copy()
for tag in right.tags {
if !tags.contains(tag) {
tags.push(tag)
}
}
{
..left,
assumptions,
inputs,
formulas,
results,
warnings,
sources,
sections,
tags,
summary: left.summary + "\n\n" + right.summary,
}
}