///|
pub(all) enum IncidentSeverity {
Info
Warning
Critical
} derive(Eq, Debug)
///|
pub(all) struct Incident {
id : String
started_minute : Int
ended_minute : Int
severity : IncidentSeverity
title : String
impact_bp : Int
} derive(Eq, Debug)
///|
pub fn Incident::new(
id : String,
started_minute : Int,
ended_minute : Int,
severity : IncidentSeverity,
title : String,
impact_bp : Int,
) -> Incident {
{
id,
started_minute,
ended_minute: if ended_minute >= started_minute {
ended_minute
} else {
started_minute
},
severity,
title,
impact_bp: if impact_bp < 0 {
0
} else if impact_bp > 10000 {
10000
} else {
impact_bp
},
}
}
///|
pub fn Incident::duration(self : Incident) -> Int {
self.ended_minute - self.started_minute + 1
}
///|
pub fn Incident::active_at(self : Incident, minute : Int) -> Bool {
minute >= self.started_minute && minute <= self.ended_minute
}
///|
pub fn Incident::severity_name(self : Incident) -> String {
match self.severity {
Info => "info"
Warning => "warning"
Critical => "critical"
}
}
///|
pub(all) struct IncidentTimeline {
incidents : Array[Incident]
} derive(Eq, Debug)
///|
pub fn IncidentTimeline::new() -> IncidentTimeline {
{ incidents: [] }
}
///|
pub fn IncidentTimeline::record(
self : IncidentTimeline,
incident : Incident,
) -> IncidentTimeline {
self.incidents.push(incident)
self
}
///|
pub fn IncidentTimeline::count(self : IncidentTimeline) -> Int {
self.incidents.length()
}
///|
pub fn IncidentTimeline::active_count(
self : IncidentTimeline,
minute : Int,
) -> Int {
let mut count = 0
for incident in self.incidents {
if incident.active_at(minute) {
count = count + 1
}
}
count
}
///|
pub fn IncidentTimeline::active_at(
self : IncidentTimeline,
minute : Int,
) -> Bool {
self.active_count(minute) > 0
}
///|
pub fn IncidentTimeline::impact_at(
self : IncidentTimeline,
minute : Int,
) -> Int {
let mut impact = 0
for incident in self.incidents {
if incident.active_at(minute) && incident.impact_bp > impact {
impact = incident.impact_bp
}
}
impact
}
///|
pub fn IncidentTimeline::severity_at(
self : IncidentTimeline,
minute : Int,
) -> IncidentSeverity {
let mut severity = Info
for incident in self.incidents {
if incident.active_at(minute) {
match incident.severity {
Critical => return Critical
Warning => if severity == Info { severity = Warning }
Info => ()
}
}
}
severity
}
///|
pub fn IncidentTimeline::overlap_count(
self : IncidentTimeline,
start_minute : Int,
end_minute : Int,
) -> Int {
let mut count = 0
for incident in self.incidents {
if incident.ended_minute >= start_minute &&
incident.started_minute <= end_minute {
count = count + 1
}
}
count
}
///|
pub fn IncidentTimeline::impact_average(
self : IncidentTimeline,
start_minute : Int,
end_minute : Int,
) -> Int {
let mut total = 0
let mut count = 0
for minute in start_minute..<=end_minute {
let impact = self.impact_at(minute)
total = total + impact
count = count + 1
}
if count == 0 {
0
} else {
total / count
}
}
///|
pub fn IncidentTimeline::to_json(self : IncidentTimeline) -> String {
let result = StringBuilder()
result.write_string("[")
for i, incident in self.incidents {
if i > 0 {
result.write_string(",")
}
result.write_string(
"{\"id\":\"\{escape_json(incident.id)}\",\"start\":\{incident.started_minute},\"end\":\{incident.ended_minute},\"severity\":\"\{incident.severity_name()}\",\"title\":\"\{escape_json(incident.title)}\",\"impact_bp\":\{incident.impact_bp}}",
)
}
result.write_string("]")
result.to_string()
}