///|
fn simultaneous(a : Note, b : Note) -> Bool {
  a.onset == b.onset
}

///|
fn min_int(a : Int, b : Int) -> Int {
  if a < b {
    a
  } else {
    b
  }
}

///|
fn add_vertical_findings(
  cantus : Array[Note],
  counter : Array[Note],
  options : AnalysisOptions,
  out : Array[Finding],
) -> Unit {
  let n = min_int(cantus.length(), counter.length())
  for i in 0.. Unit {
  let n = min_int(cantus.length(), counter.length())
  if n < 2 {
    return
  }
  for i in 1.. Unit {
  let n = min_int(cantus.length(), counter.length())
  if n < 2 {
    return
  }
  let final_interval = interval_class(
    harmonic_interval(cantus[n - 1], counter[n - 1]),
  )
  if final_interval != 0 && final_interval != 7 {
    out.push(
      Finding::warning(
        rule=CadenceShape,
        index=n - 1,
        message="final sonority is expected to be octave/unison or fifth",
      ),
    )
  }
}

///|
pub fn analyze_harmony(
  cantus : Array[Note],
  counter : Array[Note],
  options : AnalysisOptions,
) -> Array[Finding] {
  let out : Array[Finding] = []
  add_vertical_findings(cantus, counter, options, out)
  add_motion_findings(cantus, counter, out)
  if options.strict_cadence {
    add_cadence_finding(cantus, counter, out)
  }
  out
}