///|
pub fn default_cutoffs() -> Array[Int] {
  [1, 3, 5, 10]
}

///|
pub fn EvalConfig::default() -> EvalConfig {
  {
    cutoffs: default_cutoffs(),
    relevant_threshold: 1,
    gain_scheme: Linear,
    missing_relevance: 0,
  }
}

///|
pub fn EvalConfig::new(
  cutoffs~ : Array[Int],
  relevant_threshold? : Int = 1,
  gain_scheme? : GainScheme = Linear,
  missing_relevance? : Int = 0,
) -> EvalConfig {
  { cutoffs, relevant_threshold, gain_scheme, missing_relevance }
}

///|
pub fn GainScheme::linear() -> GainScheme {
  Linear
}

///|
pub fn GainScheme::exp2() -> GainScheme {
  Exp2
}

///|
pub fn NegativeSampleConfig::default() -> NegativeSampleConfig {
  {
    per_query: 5,
    relevant_threshold: 1,
    skip_judged: true,
    strategy: HardWindow(50),
  }
}

///|
pub fn NegativeStrategy::tail(window : Int) -> NegativeStrategy {
  Tail(window)
}

///|
pub fn NegativeStrategy::hard_window(window : Int) -> NegativeStrategy {
  HardWindow(window)
}

///|
pub fn NegativeStrategy::stride(step : Int) -> NegativeStrategy {
  Stride(step)
}

///|
pub fn NegativeSampleConfig::new(
  per_query~ : Int,
  relevant_threshold? : Int = 1,
  skip_judged? : Bool = true,
  strategy? : NegativeStrategy = HardWindow(50),
) -> NegativeSampleConfig {
  { per_query, relevant_threshold, skip_judged, strategy }
}