///|
/// A group of steps executed in one lifecycle phase.
pub(all) struct ExecutionPhase {
phase : PlanPhase
steps : Array[MeasurementStep]
device_id : String
}
///|
fn phase_for_step(step : MeasurementStep) -> PlanPhase {
if step.direction == "datum-aligned" {
PlanPhase::EstablishDatum
} else {
PlanPhase::Measure
}
}
///|
/// Group plan steps into stable datum and measurement phases.
pub fn execution_phases(plan : MeasurementPlan) -> Array[ExecutionPhase] {
let datum_steps = []
let measurement_steps = []
for step in plan.steps {
if phase_for_step(step) == PlanPhase::EstablishDatum {
datum_steps.push(step)
} else {
measurement_steps.push(step)
}
}
let result = []
if datum_steps.length() > 0 {
result.push({
phase: PlanPhase::EstablishDatum,
steps: datum_steps,
device_id: datum_steps[0].device_id,
})
}
if measurement_steps.length() > 0 {
result.push({
phase: PlanPhase::Measure,
steps: measurement_steps,
device_id: measurement_steps[0].device_id,
})
}
result
}
///|
/// Return a stable datum-first sequence while grouping adjacent device steps.
pub fn grouped_execution_order(
plan : MeasurementPlan,
) -> Array[MeasurementStep] {
let ordered = execution_order(plan)
let result = []
let device_ids = []
for step in ordered {
let mut seen = false
for device_id in device_ids {
if device_id == step.device_id {
seen = true
}
}
if !seen {
device_ids.push(step.device_id)
}
}
for device_id in device_ids {
for step in ordered {
if step.device_id == device_id {
result.push(step)
}
}
}
result
}
///|
/// Count device changes in an already ordered sequence.
pub fn device_switch_count(steps : Array[MeasurementStep]) -> Int {
if steps.length() < 2 {
0
} else {
let mut result = 0
for i in 1..