///|
/// A scenario can be unstable without aborting an otherwise valid sweep.
/// Malformed or numerically unrepresentable inputs still raise QueueError.
pub(all) struct QueueScenario {
  arrival : Double
  stable : Bool
  metrics : QueueMetrics?
  wait_tail : Double?
} derive(Debug, ToJson)

///|
pub fn mmc_sweep(
  service : Double,
  server_count : Int,
  arrivals : Array[Double],
  wait_threshold : Double,
) -> Array[QueueScenario] raise QueueError {
  rate(service, "sweep service")
  positive(service, "sweep service")
  servers(server_count)
  nonnegative(wait_threshold, "sweep threshold")
  if arrivals.is_empty() || arrivals.length() > 128 {
    raise Limit("sweep needs 1..128 arrivals")
  }
  for arrival in arrivals {
    rate(arrival, "scenario arrival")
  }
  let output = []
  for arrival in arrivals {
    if arrival >= service * server_count.to_double() {
      output.push({ arrival, stable: false, metrics: None, wait_tail: None, })
    } else {
      let q : Mmc = { arrival, service, servers: server_count, }
      output.push({
        arrival,
        stable: true,
        metrics: Some(q.analyze()),
        wait_tail: Some(q.wait_survival(wait_threshold)),
      })
    }
  }
  output
}

///|
pub extend QueueScenario with Debug::{to_repr}

///|
pub extend QueueScenario with ToJson::{to_json}