use std::collections::BTreeMap;
use kernel::{AxError, EventRecord, RunId};
use serde_json::json;
use wire::Turn;
use super::arrange::{Entry, NodeKey};
use super::follow::Row;
pub(super) type Rounds = BTreeMap<RunId, Result<Vec<Turn>, AxError>>;
pub(super) fn fold(run: RunId, rows: &[Row]) -> Result<Vec<Turn>, AxError> {
let records = rows
.iter()
.filter(|row| row.run == run)
.map(|row| EventRecord::parse_line(row.line.as_bytes()))
.collect::<Result<Vec<_>, _>>()?;
Ok(accounting::views::turns(&records))
}
pub(super) fn leaf_mark(rounds: &Rounds, key: &NodeKey) -> char {
match key {
NodeKey::Run(run) if !rounds.contains_key(run) => '+',
NodeKey::City
| NodeKey::Building(_)
| NodeKey::Room(_)
| NodeKey::Session(..)
| NodeKey::Run(_)
| NodeKey::Round(..)
| NodeKey::Call(..) => ' ',
}
}
pub(super) fn append_below(
entries: &mut Vec<Entry>,
at: usize,
folded: &Result<Vec<Turn>, AxError>,
) {
let Some((NodeKey::Run(run), depth, seq)) = entries
.get(at)
.map(|entry| (entry.key.clone(), entry.depth.saturating_add(1), entry.seq))
else {
return;
};
let turns = match folded {
Ok(turns) => turns,
Err(failure) => {
entries.push(Entry {
key: NodeKey::Round(run, 0),
depth,
parent: Some(at),
seq,
label: format!("rounds unreadable: {failure}"),
detail: serde_json::to_value(failure).unwrap_or_else(unserializable),
});
return;
}
};
for turn in turns {
let round_at = entries.len();
entries.push(Entry {
key: NodeKey::Round(run, turn.number),
depth,
parent: Some(at),
seq: turn.opened,
label: format!("round {} @{}", turn.number, turn.opened.value()),
detail: serde_json::to_value(turn).unwrap_or_else(unserializable),
});
entries.extend(turn.calls.iter().map(|call| Entry {
key: NodeKey::Call(run, call.at),
depth: depth.saturating_add(1),
parent: Some(round_at),
seq: call.at,
label: call.subject.as_ref().map_or_else(
|| call.tool.clone(),
|subject| format!("{} {subject}", call.tool),
),
detail: serde_json::to_value(call).unwrap_or_else(unserializable),
}));
}
}
fn unserializable(failure: serde_json::Error) -> serde_json::Value {
json!({ "error": failure.to_string() })
}