use solverforge_core::score::SoftScore;
use solverforge_core::{ConstraintRef, ImpactType};
use crate::api::constraint_set::IncrementalConstraint;
use crate::constraint::if_exists::{ExistenceMode, IfExistsUniConstraint};
#[derive(Clone)]
struct Task {
_id: usize,
assignee: Option<usize>,
}
#[derive(Clone)]
struct Worker {
id: usize,
available: bool,
}
#[derive(Clone)]
struct TaskSchedule {
tasks: Vec<Task>,
workers: Vec<Worker>,
}
fn tasks(s: &TaskSchedule) -> &[Task] {
s.tasks.as_slice()
}
#[test]
fn test_if_exists_penalizes_assigned_to_unavailable() {
let constraint = IfExistsUniConstraint::new(
ConstraintRef::new("", "Unavailable worker"),
ImpactType::Penalty,
ExistenceMode::Exists,
tasks,
|s: &TaskSchedule| s.workers.iter().filter(|w| !w.available).cloned().collect(),
|t: &Task| t.assignee,
|w: &Worker| Some(w.id),
|_s: &TaskSchedule, t: &Task| t.assignee.is_some(),
|_t: &Task| SoftScore::of(1),
false,
);
let schedule = TaskSchedule {
tasks: vec![
Task {
_id: 0,
assignee: Some(0),
}, Task {
_id: 1,
assignee: Some(1),
}, Task {
_id: 2,
assignee: None,
}, ],
workers: vec![
Worker {
id: 0,
available: false,
},
Worker {
id: 1,
available: true,
},
],
};
assert_eq!(constraint.evaluate(&schedule), SoftScore::of(-1));
assert_eq!(constraint.match_count(&schedule), 1);
}
#[test]
fn test_if_not_exists_penalizes_unassigned() {
let constraint = IfExistsUniConstraint::new(
ConstraintRef::new("", "No available worker"),
ImpactType::Penalty,
ExistenceMode::NotExists,
tasks,
|s: &TaskSchedule| s.workers.iter().filter(|w| w.available).cloned().collect(),
|t: &Task| t.assignee,
|w: &Worker| Some(w.id),
|_s: &TaskSchedule, t: &Task| t.assignee.is_some(),
|_t: &Task| SoftScore::of(1),
false,
);
let schedule = TaskSchedule {
tasks: vec![
Task {
_id: 0,
assignee: Some(0),
}, Task {
_id: 1,
assignee: Some(1),
}, Task {
_id: 2,
assignee: None,
}, ],
workers: vec![
Worker {
id: 0,
available: false,
},
Worker {
id: 1,
available: true,
},
],
};
assert_eq!(constraint.evaluate(&schedule), SoftScore::of(-1));
assert_eq!(constraint.match_count(&schedule), 1);
}