use std::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use solverforge_core::score::{ParseableScore, Score};
use crate::{
active_dynamic_score_family, scoped_dynamic_score_family, DynamicScore, DynamicScoreFamily,
};
fn hash_of(score: DynamicScore) -> u64 {
let mut hasher = DefaultHasher::new();
score.hash(&mut hasher);
hasher.finish()
}
#[test]
fn dynamic_score_keeps_static_three_level_score_contract() {
let score = DynamicScore::of(-1, 2, 3);
assert_eq!(DynamicScore::levels_count(), 3);
assert!(!score.is_feasible());
assert_eq!(score.to_level_numbers(), vec![-1, 2, 3]);
assert_eq!(score.family_levels(DynamicScoreFamily::Soft), vec![3]);
assert_eq!(
score.family_levels(DynamicScoreFamily::HardSoft),
vec![-1, 3]
);
}
#[test]
fn dynamic_score_displays_the_active_family() {
let display =
|family, score: DynamicScore| scoped_dynamic_score_family(family, || score.to_string());
assert_eq!(
display(DynamicScoreFamily::Soft, DynamicScore::soft(3)),
"3"
);
assert_eq!(
display(DynamicScoreFamily::HardSoft, DynamicScore::hard_soft(-1, 3)),
"-1hard/3soft"
);
assert_eq!(
display(
DynamicScoreFamily::HardSoftDecimal,
DynamicScore::hard_soft(-100_000, 150_500)
),
"-1hard/1.505soft"
);
assert_eq!(
display(
DynamicScoreFamily::HardMediumSoft,
DynamicScore::of(-1, 2, 3)
),
"-1hard/2medium/3soft"
);
}
#[test]
fn dynamic_score_family_scope_restores_the_previous_family() {
scoped_dynamic_score_family(DynamicScoreFamily::Soft, || {
scoped_dynamic_score_family(DynamicScoreFamily::HardSoft, || {
assert_eq!(active_dynamic_score_family(), DynamicScoreFamily::HardSoft);
});
assert_eq!(active_dynamic_score_family(), DynamicScoreFamily::Soft);
});
assert_eq!(
active_dynamic_score_family(),
DynamicScoreFamily::HardMediumSoft
);
}
#[test]
fn dynamic_score_parses_standard_score_strings() {
assert_eq!(
DynamicScore::parse("-1hard/2medium/3soft").unwrap(),
DynamicScore::of(-1, 2, 3)
);
assert_eq!(
DynamicScore::parse("-1hard/3soft").unwrap(),
DynamicScore::hard_soft(-1, 3)
);
assert_eq!(
DynamicScore::parse("-1hard/1.505soft").unwrap(),
DynamicScore::hard_soft(-100_000, 150_500)
);
assert_eq!(DynamicScore::parse("3").unwrap(), DynamicScore::soft(3));
}
#[test]
fn dynamic_score_equality_agrees_with_ordering() {
let declared = DynamicScore::hard_soft(0, 0);
assert_eq!(declared.cmp(&DynamicScore::ZERO), Ordering::Equal);
assert_eq!(declared, DynamicScore::ZERO);
assert_eq!(hash_of(declared), hash_of(DynamicScore::ZERO));
assert!(DynamicScore::of(0, 0, 0) > DynamicScore::of(-1, 100, 100));
}
#[test]
fn dynamic_score_zero_does_not_depend_on_the_calling_thread() {
let solve_thread_zero = scoped_dynamic_score_family(DynamicScoreFamily::HardSoft, || {
<DynamicScore as Score>::zero()
});
assert_eq!(solve_thread_zero, <DynamicScore as Score>::zero());
}
#[test]
fn dynamic_score_parse_inverts_display_for_decimal_models() {
scoped_dynamic_score_family(DynamicScoreFamily::HardSoftDecimal, || {
let limit = DynamicScore::parse("0hard/-5soft").unwrap();
assert_eq!((limit.hard, limit.soft), (0, -500_000));
assert_eq!(limit.to_string(), "0hard/-5soft");
});
}