///|
fn html_escape(value : String) -> String {
  value
  .replace_all(old="&", new="&")
  .replace_all(old="<", new="<")
  .replace_all(old=">", new=">")
  .replace_all(old="\"", new=""")
}

///|
pub fn render_html_report(report : BenchmarkReport) -> String {
  let builder = StringBuilder()
  builder.write_string("")
  builder.write_string("MoonRAGBench report")
  builder.write_string("

MoonRAGBench

") builder.write_string("

Queries: \{report.query_count}

") builder.write_string( "", ) for metric in report.summary { builder.write_string( "", ) } builder.write_string("
MetricMeanMinMax
\{html_escape(metric.name)}\{format_metric(metric.mean)}\{format_metric(metric.min)}\{format_metric(metric.max)}
") builder.write_string( "

Queries

", ) for query in report.queries { builder.write_string( "", ) } builder.write_string("
QueryRelevantRetrieved
\{html_escape(query.query_id)}\{query.relevant_total}\{query.retrieved_total}
") builder.to_string() } ///| pub fn render_query_buckets_markdown(buckets : Array[QueryBucket]) -> String { let builder = StringBuilder() builder.write_string("| Query | Bucket | Score |\n") builder.write_string("| --- | --- | ---: |\n") for bucket in buckets { builder.write_string( "| \{bucket.query_id} | \{bucket.label} | \{format_metric(bucket.score)} |\n", ) } builder.to_string() } ///| pub fn render_distribution_markdown( name : String, distribution : MetricDistribution, ) -> String { let lines : Array[String] = [ "### \{name}", "", "| Count | Mean | Min | P25 | Median | P75 | Max | Stddev |", "| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |", "| \{distribution.count} | \{format_metric(distribution.mean)} | \{format_metric(distribution.min)} | \{format_metric(distribution.p25)} | \{format_metric(distribution.median)} | \{format_metric(distribution.p75)} | \{format_metric(distribution.max)} | \{format_metric(distribution.stddev)} |", ] lines.join("\n") } ///| pub fn render_statistics_markdown( qrels : Array[JudgedDoc], run : Array[RetrievedDoc], ) -> String { let profile = profile_dataset(qrels, run) let stats = query_statistics(qrels, run) let builder = StringBuilder() builder.write_string("# Dataset diagnostics\n\n") builder.write_string(render_profile_text(profile)) builder.write_string("\n\n") builder.write_string(query_statistics_markdown(stats)) builder.to_string() } ///| pub fn render_validation_and_profile( qrels : Array[JudgedDoc], run : Array[RetrievedDoc], ) -> String { let validation = validate_dataset(qrels, run) let profile = profile_dataset(qrels, run) let builder = StringBuilder() builder.write_string(render_validation_report(validation)) builder.write_string("\n\n---\n\n") builder.write_string(render_profile_text(profile)) builder.to_string() }