///|
pub(all) struct RepairRequest {
unavailable_people : Array[PersonId]
removed_shifts : Array[ShiftId]
unlocked_shifts : Array[ShiftId]
preserve_unaffected : Bool
} derive(Debug, Eq)
///|
pub fn RepairRequest::empty() -> RepairRequest {
{
unavailable_people: [],
removed_shifts: [],
unlocked_shifts: [],
preserve_unaffected: true,
}
}
///|
fn contains_person(ids : Array[PersonId], id : PersonId) -> Bool {
for item in ids {
if item == id {
return true
}
}
false
}
///|
fn contains_shift(ids : Array[ShiftId], id : ShiftId) -> Bool {
for item in ids {
if item == id {
return true
}
}
false
}
///|
pub fn apply_repair_request(
problem : ScheduleProblem,
request : RepairRequest,
) -> ScheduleProblem {
let people : Array[Person] = []
for person in problem.people {
if !contains_person(request.unavailable_people, person.id) {
people.push(person)
}
}
let shifts : Array[Shift] = []
for shift in problem.shifts {
if !contains_shift(request.removed_shifts, shift.id) {
shifts.push(shift)
}
}
let existing : Array[Assignment] = []
for assignment in problem.existing {
if !contains_person(request.unavailable_people, assignment.person_id) &&
!contains_shift(request.removed_shifts, assignment.shift_id) {
let should_lock = request.preserve_unaffected &&
!contains_shift(request.unlocked_shifts, assignment.shift_id)
existing.push({ ..assignment, locked: should_lock })
}
}
{ ..problem, people, shifts, existing }
}
///|
pub fn repair(
problem : ScheduleProblem,
request : RepairRequest,
options? : SearchOptions = SearchOptions::default(),
) -> ScheduleResult {
let adjusted = apply_repair_request(problem, request)
solve(adjusted, options~)
}
///|
pub fn changed_assignments(
before : Array[Assignment],
after : Array[Assignment],
) -> Array[Assignment] {
let changed : Array[Assignment] = []
for item in after {
let mut same = false
for old in before {
if same_assignment(item, old) {
same = true
}
}
if !same {
changed.push(item)
}
}
changed
}
///|
pub fn removed_assignments(
before : Array[Assignment],
after : Array[Assignment],
) -> Array[Assignment] {
let removed : Array[Assignment] = []
for item in before {
let mut same = false
for fresh in after {
if same_assignment(item, fresh) {
same = true
}
}
if !same {
removed.push(item)
}
}
removed
}