///|
pub(all) struct TimelineFrame {
tick : Int
events : Array[TickEvent]
} derive(Debug, Eq)
///|
pub fn TimelineFrame::summary(self : TimelineFrame) -> String {
"tick=" + self.tick.to_string() + ", events=" + self.events.length().to_string()
}
///|
pub fn TimelineFrame::lines(self : TimelineFrame) -> Array[String] {
let lines = Array::new()
lines.push(self.summary())
let mut i = 0
while i < self.events.length() {
lines.push(" " + self.events[i].to_line())
i = i + 1
}
lines
}
///|
pub fn timeline_from_trace(events : Array[TickEvent]) -> Array[TimelineFrame] {
let frames = Array::new()
let mut i = 0
while i < events.length() {
let tick = events[i].tick
match frame_index(frames, tick) {
Some(idx) => frames[idx].events.push(events[i])
None => frames.push({ tick, events: [events[i]] })
}
i = i + 1
}
frames
}
///|
pub fn timeline_text(events : Array[TickEvent]) -> String {
let frames = timeline_from_trace(events)
let lines = Array::new()
let mut i = 0
while i < frames.length() {
let frame_lines = frames[i].lines()
let mut j = 0
while j < frame_lines.length() {
lines.push(frame_lines[j])
j = j + 1
}
i = i + 1
}
join_strings(lines, "\n")
}
///|
pub fn filter_trace_by_node(
events : Array[TickEvent],
node_id : String,
) -> Array[TickEvent] {
let out = Array::new()
let mut i = 0
while i < events.length() {
if events[i].node_id == node_id {
out.push(events[i])
}
i = i + 1
}
out
}
///|
pub fn filter_trace_by_status(
events : Array[TickEvent],
status : BtStatus,
) -> Array[TickEvent] {
let out = Array::new()
let mut i = 0
while i < events.length() {
if events[i].status == status {
out.push(events[i])
}
i = i + 1
}
out
}
///|
pub(all) struct TraceSummary {
total : Int
success : Int
failure : Int
running : Int
unique_nodes : Int
} derive(Debug, Eq)
///|
pub fn TraceSummary::to_line(self : TraceSummary) -> String {
"total=" +
self.total.to_string() +
", success=" +
self.success.to_string() +
", failure=" +
self.failure.to_string() +
", running=" +
self.running.to_string() +
", unique_nodes=" +
self.unique_nodes.to_string()
}
///|
pub fn summarize_trace(events : Array[TickEvent]) -> TraceSummary {
let nodes = Array::new()
let mut success = 0
let mut failure = 0
let mut running = 0
let mut i = 0
while i < events.length() {
match events[i].status {
Success => success = success + 1
Failure => failure = failure + 1
Running => running = running + 1
}
if !string_array_contains(nodes, events[i].node_id) {
nodes.push(events[i].node_id)
}
i = i + 1
}
{
total: events.length(),
success,
failure,
running,
unique_nodes: nodes.length(),
}
}
///|
pub fn compact_trace(events : Array[TickEvent]) -> Array[String] {
let out = Array::new()
let mut i = 0
while i < events.length() {
let event = events[i]
out.push(
event.tick.to_string() +
":" +
event.node_id +
"=" +
event.status.to_text(),
)
i = i + 1
}
out
}
///|
pub fn last_event_for_node(
events : Array[TickEvent],
node_id : String,
) -> TickEvent? {
let mut i = events.length() - 1
while i >= 0 {
if events[i].node_id == node_id {
return Some(events[i])
}
if i == 0 {
return None
}
i = i - 1
}
None
}
///|
fn frame_index(frames : Array[TimelineFrame], tick : Int) -> Int? {
let mut i = 0
while i < frames.length() {
if frames[i].tick == tick {
return Some(i)
}
i = i + 1
}
None
}
///|
fn string_array_contains(values : Array[String], item : String) -> Bool {
let mut i = 0
while i < values.length() {
if values[i] == item {
return true
}
i = i + 1
}
false
}