///|
/// Kind of discontinuity between adjacent record segments.
pub(all) enum SegmentKind {
Gap
Overlap
Duplicate
RateChange
} derive(Eq, Debug)
///|
pub(all) struct SegmentIssue {
kind : SegmentKind
at : @time.Time
detail : String
} derive(Eq, Debug)
///|
pub fn SegmentIssue::kind(self : SegmentIssue) -> SegmentKind {
self.kind
}
///|
pub fn SegmentIssue::at(self : SegmentIssue) -> @time.Time {
self.at
}
///|
pub fn SegmentIssue::detail(self : SegmentIssue) -> String {
self.detail
}
///|
pub(all) struct SegmentReport {
gap_count : Int
overlap_count : Int
duplicate_count : Int
rate_change_count : Int
total_gap_seconds : Double
issues : Array[SegmentIssue]
} derive(Eq, Debug)
///|
pub fn SegmentReport::gap_count(self : SegmentReport) -> Int {
self.gap_count
}
///|
pub fn SegmentReport::overlap_count(self : SegmentReport) -> Int {
self.overlap_count
}
///|
pub fn SegmentReport::duplicate_count(self : SegmentReport) -> Int {
self.duplicate_count
}
///|
pub fn SegmentReport::rate_change_count(self : SegmentReport) -> Int {
self.rate_change_count
}
///|
pub fn SegmentReport::total_gap_seconds(self : SegmentReport) -> Double {
self.total_gap_seconds
}
///|
pub fn SegmentReport::issues(self : SegmentReport) -> Array[SegmentIssue] {
self.issues
}
///|
/// Inspect adjacent records independently for each SID.
pub fn inspect_segments(records : Array[@record.Record]) -> SegmentReport {
let issues : Array[SegmentIssue] = []
let mut gap_seconds = 0.0
let traces = build_traces(records)
for trace in traces {
let group = trace.records()
let mut i = 1
while i < group.length() {
let previous = group[i - 1]
let current = group[i]
let at = current.start_time()
if previous.start_time().to_epoch_ns() == at.to_epoch_ns() {
issues.push({ kind: Duplicate, at, detail: "same SID and start time" })
} else {
match previous.end_time() {
Some(previous_end) => {
let delta = at.diff_secs(previous_end)
let tolerance = if previous.header().rate_hz() > 0.0 {
0.5 / previous.header().rate_hz()
} else {
0.0
}
if delta > tolerance {
issues.push({ kind: Gap, at, detail: "gap of \{delta} seconds" })
gap_seconds = gap_seconds + delta
} else if delta < -tolerance {
issues.push({
kind: Overlap,
at,
detail: "overlap of \{-delta} seconds",
})
}
}
None => ()
}
}
if previous.header().rate_hz() != current.header().rate_hz() {
issues.push({ kind: RateChange, at, detail: "sample rate changed" })
}
i = i + 1
}
}
let mut gaps = 0
let mut overlaps = 0
let mut duplicates = 0
let mut rate_changes = 0
for issue in issues {
match issue.kind {
Gap => gaps = gaps + 1
Overlap => overlaps = overlaps + 1
Duplicate => duplicates = duplicates + 1
RateChange => rate_changes = rate_changes + 1
}
}
{
gap_count: gaps,
overlap_count: overlaps,
duplicate_count: duplicates,
rate_change_count: rate_changes,
total_gap_seconds: gap_seconds,
issues,
}
}