use solverforge_core::score::SoftScore;
use solverforge_core::{ConstraintRef, ImpactType};
use crate::constraint::incremental::IncrementalUniConstraint;
use crate::director::score_director::ScoreDirector;
use crate::director::shadow_aware::ShadowVariableSupport;
use solverforge_test::shadow::ShadowSolution;
impl ShadowVariableSupport for ShadowSolution {
fn update_entity_shadows(&mut self, _entity_index: usize) {
self.cached_sum = self.values.iter().sum();
}
fn update_all_shadows(&mut self) {
self.cached_sum = self.values.iter().sum();
}
}
fn make_sum_constraint() -> IncrementalUniConstraint<
ShadowSolution,
i32,
fn(&ShadowSolution) -> &[i32],
fn(&ShadowSolution, &i32) -> bool,
fn(&i32) -> SoftScore,
SoftScore,
> {
fn extract(s: &ShadowSolution) -> &[i32] {
std::slice::from_ref(&s.cached_sum)
}
fn filter(_s: &ShadowSolution, &sum: &i32) -> bool {
sum > 100
}
fn score(&sum: &i32) -> SoftScore {
SoftScore::of((sum - 100) as i64)
}
IncrementalUniConstraint::new(
ConstraintRef::new("", "SumLimit"),
ImpactType::Penalty,
extract as fn(&ShadowSolution) -> &[i32],
filter as fn(&ShadowSolution, &i32) -> bool,
score as fn(&i32) -> SoftScore,
false,
)
}
fn create_director(
values: Vec<i32>,
) -> ScoreDirector<
ShadowSolution,
(
IncrementalUniConstraint<
ShadowSolution,
i32,
fn(&ShadowSolution) -> &[i32],
fn(&ShadowSolution, &i32) -> bool,
fn(&i32) -> SoftScore,
SoftScore,
>,
),
> {
let solution = ShadowSolution::new(values);
let constraint = make_sum_constraint();
ScoreDirector::new(solution, (constraint,))
}
#[test]
fn test_shadow_update_called_on_variable_change() {
let mut director = create_director(vec![10, 20, 30]);
director.calculate_score();
assert_eq!(director.working_solution().cached_sum, 0);
director.before_variable_changed(0, 0);
director.working_solution_mut().values[0] = 50;
director.after_variable_changed_with_shadows(0, 0);
assert_eq!(director.working_solution().cached_sum, 100); }
#[test]
fn test_director_is_not_initialized_before_calculate() {
let director = create_director(vec![1, 2, 3]);
assert!(!director.is_initialized());
}
#[test]
fn test_take_solution_after_use() {
let director = create_director(vec![1]);
let solution = director.take_solution();
assert_eq!(solution.values.len(), 1);
}