///|
pub fn resolve_metric_name(prefix : String, cutoff : Int) -> String {
  match prefix.to_lower() {
    "r" | "recall" => metric_name("recall", cutoff)
    "p" | "precision" => metric_name("precision", cutoff)
    "f1" => metric_name("f1", cutoff)
    "mrr" => metric_name("mrr", cutoff)
    "map" => metric_name("map", cutoff)
    "ndcg" => metric_name("ndcg", cutoff)
    "err" => metric_name("err", cutoff)
    "rbp" => metric_name("rbp", cutoff)
    "bpref" => metric_name("bpref", cutoff)
    _ => metric_name(prefix.to_lower(), cutoff)
  }
}

///|
pub fn supported_output_formats() -> Array[String] {
  ["text", "markdown", "json", "csv", "jsonl"]
}

///|
pub fn is_supported_output_format(format : String) -> Bool {
  supported_output_formats().contains(format.to_lower())
}

///|
pub fn canonical_output_format(format : String) -> Result[CliFormat, String] {
  match format.to_lower() {
    "text" => Ok(CliFormat::Text)
    "markdown" | "md" => Ok(CliFormat::Markdown)
    "json" => Ok(CliFormat::Json)
    "csv" => Ok(CliFormat::Csv)
    "jsonl" | "ndjson" => Ok(CliFormat::JsonLines)
    _ => Err("unsupported output format '\{format}'")
  }
}

///|
pub fn metric_aliases() -> Map[String, String] {
  let aliases : Map[String, String] = Map([])
  aliases["R"] = "recall"
  aliases["P"] = "precision"
  aliases["nDCG"] = "ndcg"
  aliases["MRR"] = "mrr"
  aliases["MAP"] = "map"
  aliases["F1"] = "f1"
  aliases["ERR"] = "err"
  aliases["RBP"] = "rbp"
  aliases["BPref"] = "bpref"
  aliases
}