///|
fn append_if_some(target : Array[Finding], item : Finding?) -> Unit {
match item {
Some(value) => target.push(value)
None => ()
}
}
///|
pub fn inspect(
observations : Array[Observation],
config : RuleConfig,
) -> QcSummary {
let findings : Array[Finding] = []
for i, observation in observations {
append_if_some(findings, check_missing(observation, config))
append_if_some(findings, check_range(observation, config))
append_if_some(findings, check_climate(observation, config))
if i > 0 {
let previous = observations[i - 1]
append_if_some(findings, check_delta(previous, observation, config))
append_if_some(findings, check_interval(previous, observation, config))
append_if_some(findings, check_spatial(previous, observation, config))
append_if_some(findings, check_duplicate(previous, observation, config))
}
}
let bad = findings.filter(fn(item) { item.flag == Bad }).length()
let missing = findings.filter(fn(item) { item.flag == Missing }).length()
let suspect = findings.filter(fn(item) { item.flag == Suspect }).length()
{
total: observations.length(),
good: observations.length() - bad - missing - suspect,
missing,
suspect,
bad,
findings,
}
}
///|
pub fn render_report(summary : QcSummary) -> String {
let out = StringBuilder::new()
out.write_string("MoonBit Ocean QC report\n")
out <+
"total=\{summary.total} good=\{summary.good} suspect=\{summary.suspect} missing=\{summary.missing} bad=\{summary.bad}\n"
for item in summary.findings {
out <+ "- \{item.observation_id} [\{Repr(item.rule)}] \{item.reason}\n"
}
out.to_string()
}