///|
/// A compact audit report for one behavior tree run.
pub(all) struct AuditReport {
name : String
run : RunSummary
coverage : TraceCoverage
profile : ProfileReport
lint : LintReport
visual_assets : Int
} derive(Debug, Eq)
///|
pub fn AuditReport::ok(self : AuditReport) -> Bool {
self.run.ok && self.lint.ok
}
///|
pub fn AuditReport::summary(self : AuditReport) -> String {
self.name +
": ok=" +
(if self.ok() { "true" } else { "false" }) +
", " +
self.run.final_status.to_text() +
", " +
self.coverage.summary() +
", profile_events=" +
self.profile.total_events.to_string() +
", visual_assets=" +
self.visual_assets.to_string()
}
///|
pub fn AuditReport::markdown(self : AuditReport) -> String {
let lines = Array::new()
lines.push("# MoonBTKit Audit: " + self.name)
lines.push("")
lines.push("## Summary")
lines.push("")
lines.push("- " + self.summary())
lines.push("- run: " + self.run.to_line())
lines.push("- lint: " + self.lint.summary())
lines.push("")
lines.push("## Coverage")
lines.push("")
let coverage_lines = self.coverage.lines()
let mut c = 0
while c < coverage_lines.length() {
lines.push("- " + coverage_lines[c])
c = c + 1
}
lines.push("")
lines.push("## Hotspots")
lines.push("")
let hot = self.profile.hotspot_lines(5)
let mut h = 0
while h < hot.length() {
lines.push("- " + hot[h])
h = h + 1
}
if !self.lint.ok {
lines.push("")
lines.push("## Lint")
lines.push("")
let lint_lines = self.lint.lines()
let mut l = 0
while l < lint_lines.length() {
lines.push("- " + lint_lines[l])
l = l + 1
}
}
join_strings(lines, "\n")
}
///|
pub(all) struct CatalogAudit {
reports : Array[AuditReport]
} derive(Debug, Eq)
///|
pub fn CatalogAudit::passed(self : CatalogAudit) -> Int {
let mut count = 0
let mut i = 0
while i < self.reports.length() {
if self.reports[i].ok() {
count = count + 1
}
i = i + 1
}
count
}
///|
pub fn CatalogAudit::failed(self : CatalogAudit) -> Int {
self.reports.length() - self.passed()
}
///|
pub fn CatalogAudit::summary(self : CatalogAudit) -> String {
"audits=" +
self.reports.length().to_string() +
", passed=" +
self.passed().to_string() +
", failed=" +
self.failed().to_string()
}
///|
pub fn CatalogAudit::lines(self : CatalogAudit) -> Array[String] {
let out = Array::new()
out.push(self.summary())
let mut i = 0
while i < self.reports.length() {
out.push(self.reports[i].summary())
i = i + 1
}
out
}
///|
pub fn audit_fixture(name : String) -> Result[AuditReport, BtError] {
match load_fixture(name) {
Ok(doc) => {
let run = smoke_run(name, doc.tree, doc.blackboard, Success, max_ticks=32)
let engine = new_engine(doc.tree, blackboard=doc.blackboard)
match engine.run_until_done(max_ticks=32) {
Ok(_) => {
let coverage = coverage_from_trace(doc.tree, engine.trace)
let profile = profile_trace(name, engine.trace)
let lint = lint_tree(doc.tree)
let visuals = visualization_bundle(doc.tree, engine.trace)
Ok({
name,
run,
coverage,
profile,
lint,
visual_assets: visuals.length(),
})
}
Err(err) => Err(InvalidTree(err.message()))
}
}
Err(err) => Err(err)
}
}
///|
pub fn audit_fixture_catalog() -> CatalogAudit {
let specs = fixture_catalog()
let reports = Array::new()
let mut i = 0
while i < specs.length() {
match audit_fixture(specs[i].name) {
Ok(report) => reports.push(report)
Err(_) => ()
}
i = i + 1
}
{ reports, }
}
///|
pub fn audit_catalog_markdown() -> String {
let audit = audit_fixture_catalog()
let lines = Array::new()
lines.push("# MoonBTKit Catalog Audit")
lines.push("")
lines.push("- " + audit.summary())
lines.push("")
let raw = audit.lines()
let mut i = 0
while i < raw.length() {
lines.push("- " + raw[i])
i = i + 1
}
join_strings(lines, "\n")
}