///|
pub(all) struct PersonWorkload {
person_id : PersonId
assigned_minutes : Int
target_minutes : Int
difference : Int
assignment_count : Int
preference_score : Int
} derive(Debug, Eq)
///|
pub(all) struct CoverageSummary {
total_slots : Int
covered_slots : Int
uncovered_slots : Int
coverage_percent : Int
people_used : Int
total_minutes : Int
} derive(Debug, Eq)
///|
pub fn workload_for(
problem : ScheduleProblem,
assignments : Array[Assignment],
person : Person,
) -> PersonWorkload {
let mut count = 0
let mut prefs = 0
for assignment in assignments {
if assignment.person_id == person.id {
count = count + 1
prefs = prefs + preference_for(person, assignment.shift_id)
}
}
let minutes = assigned_minutes(problem, assignments, person.id)
{
person_id: person.id,
assigned_minutes: minutes,
target_minutes: person.target_minutes,
difference: minutes - person.target_minutes,
assignment_count: count,
preference_score: prefs,
}
}
///|
pub fn all_workloads(
problem : ScheduleProblem,
assignments : Array[Assignment],
) -> Array[PersonWorkload] {
let values : Array[PersonWorkload] = []
for person in problem.people {
values.push(workload_for(problem, assignments, person))
}
values.sort_by((a, b) => {
if a.assigned_minutes == b.assigned_minutes {
a.person_id.compare(b.person_id)
} else {
b.assigned_minutes - a.assigned_minutes
}
})
values
}
///|
pub fn coverage_summary(
problem : ScheduleProblem,
assignments : Array[Assignment],
) -> CoverageSummary {
let mut total = 0
for shift in problem.shifts {
total = total + shift.required_people
}
let uncovered = count_uncovered(problem, assignments)
let covered = total - uncovered
let mut used = 0
for person in problem.people {
let mut found = false
for assignment in assignments {
if assignment.person_id == person.id {
found = true
}
}
if found {
used = used + 1
}
}
{
total_slots: total,
covered_slots: covered,
uncovered_slots: uncovered,
coverage_percent: if total == 0 {
100
} else {
covered * 100 / total
},
people_used: used,
total_minutes: total_scheduled_minutes(problem, assignments),
}
}
///|
pub fn busiest_person(
problem : ScheduleProblem,
assignments : Array[Assignment],
) -> PersonId? {
let workloads = all_workloads(problem, assignments)
if workloads.length() == 0 {
None
} else {
Some(workloads[0].person_id)
}
}
///|
pub fn average_minutes(
problem : ScheduleProblem,
assignments : Array[Assignment],
) -> Int {
if problem.people.length() == 0 {
0
} else {
total_scheduled_minutes(problem, assignments) / problem.people.length()
}
}
///|
pub fn maximum_workload_gap(
problem : ScheduleProblem,
assignments : Array[Assignment],
) -> Int {
if problem.people.length() < 2 {
return 0
}
let mut minimum = 2147483647
let mut maximum = 0
for person in problem.people {
let minutes = assigned_minutes(problem, assignments, person.id)
if minutes < minimum {
minimum = minutes
}
if minutes > maximum {
maximum = minutes
}
}
maximum - minimum
}