Explainable community care and volunteer scheduling engine
let request = @neighbor_rota.demo_request(@neighbor_rota.CommunityCare)
let schedule = @neighbor_rota.solve(request)
println(@neighbor_rota.schedule_summary(schedule))pub(all) enum AssignmentChange {
Added(assignment~ : Assignment)
Removed(assignment~ : Assignment)
Reassigned(before~ : Assignment, after~ : Assignment)
Retimed(before~ : Assignment, after~ : Assignment)
ReassignedAndRetimed(before~ : Assignment, after~ : Assignment)
Unchanged(assignment~ : Assignment)
} derive(Eq, Debug)pub(all) struct ConstraintFailure {
code : ConstraintCode
message : String
worker_id : String
visit_id : String
} derive(Eq, Debug)pub(all) struct Diagnostic {
level : DiagnosticLevel
code : String
message : String
entity_id : String?
field : String?
} derive(Eq, Debug)pub(all) struct FeasibilityResult {
feasible : Bool
failures : Array[ConstraintFailure]
travel_before_minutes : Int
travel_after_minutes : Int
} derive(Eq, Debug)pub(all) struct RescheduleReport {
baseline : Schedule
updated : Schedule
events : Array[ScheduleEvent]
changes : Array[AssignmentChange]
diagnostics : Array[Diagnostic]
changed_assignments : Int
preserved_assignments : Int
newly_unassigned : Int
score_change : Int
} derive(Eq, Debug)pub(all) struct Schedule {
schema : String
assignments : Array[Assignment]
unassigned : Array[UnassignedVisit]
diagnostics : Array[Diagnostic]
score : ScheduleScore
feasible : Bool
} derive(Eq, Debug)pub(all) struct ScheduleAnalytics {
total_visits : Int
required_visits : Int
assigned_visits : Int
assigned_required_visits : Int
optional_unassigned : Int
required_unassigned : Int
coverage_percent : Int
required_coverage_percent : Int
total_service_minutes : Int
total_travel_minutes : Int
travel_share_percent : Int
average_worker_utilization_percent : Int
busiest_worker_id : String?
busiest_worker_minutes : Int
zones_served : Array[String]
reason_counts : Array[ReasonCount]
} derive(Eq, Debug)pub(all) enum ScheduleEvent {
WorkerAbsent(worker_id~ : String, from_minute~ : Int, to_minute~ : Int)
VisitCancelled(visit_id~ : String)
VisitDelayed(visit_id~ : String, delay_minutes~ : Int)
EmergencyVisit(visit~ : Visit)
WorkerCapacityChanged(worker_id~ : String, max_minutes~ : Int, max_visits~ : Int)
} derive(Eq, Debug)pub(all) struct SchedulePolicy {
travel_minutes_per_unit : Int
cross_zone_penalty_minutes : Int
priority_weight : Int
preference_weight : Int
continuity_weight : Int
travel_weight : Int
fairness_weight : Int
disruption_weight : Int
allow_optional_unassigned : Bool
local_search_rounds : Int
} derive(Eq, Debug)pub(all) struct Visit {
id : String
recipient_id : String
title : String
location : Location
window : TimeWindow
duration_minutes : Int
required_skills : Array[Skill]
priority : Priority
preferred_worker_ids : Array[String]
forbidden_worker_ids : Array[String]
continuity_group : String?
required : Bool
} derive(Eq, Debug)pub(all) struct Worker {
id : String
display_name : String
kind : WorkerKind
skills : Array[Skill]
availability : Array[TimeWindow]
home : Location
max_minutes : Int
max_visits : Int
min_break_minutes : Int
preferred_zones : Array[String]
unavailable : Bool
} derive(Eq, Debug)fn abs_int(value : Int) -> Intfn apply_events(request : ScheduleRequest, events : Array[ScheduleEvent]) -> (ScheduleRequest, Array[Diagnostic])fn candidate_reasons(worker : Worker, visit : Visit, feasibility : FeasibilityResult) -> Array[String]fn candidate_score(worker : Worker, visit : Visit, start_minute : Int, feasibility : FeasibilityResult, assignments : Array[Assignment], policy : SchedulePolicy) -> Intfn clamp_int(value : Int, lower : Int, upper : Int) -> Intfn evaluate_feasibility(worker : Worker, visit : Visit, start_minute : Int, assignments : Array[Assignment], visits : Array[Visit], policy : SchedulePolicy) -> FeasibilityResultfn interval_conflicts(assignments : Array[Assignment], worker_id : String, interval : TimeWindow) -> Boolfn next_assignment(assignments : Array[Assignment], worker_id : String, end_minute : Int) -> Assignment?fn parse_csv_int(input : String) -> Int?fn previous_assignment(assignments : Array[Assignment], worker_id : String, start_minute : Int) -> Assignment?fn replace_assignment(assignments : Array[Assignment], replacement : Assignment) -> Array[Assignment]fn request_from_csv(workers_csv : String, visits_csv : String) -> (ScheduleRequest, Array[Diagnostic])fn reschedule(baseline : Schedule, request : ScheduleRequest, events : Array[ScheduleEvent]) -> RescheduleReportfn score_schedule(assignments : Array[Assignment], workers : Array[Worker], visits : Array[Visit], policy : SchedulePolicy, baseline : Schedule?) -> ScheduleScorefn search_candidates(visit : Visit, workers : Array[Worker], assignments : Array[Assignment], visits : Array[Visit], policy : SchedulePolicy) -> CandidateSearchfn travel_before_candidate(worker : Worker, visit : Visit, assignments : Array[Assignment], visits : Array[Visit], policy : SchedulePolicy, start_minute : Int) -> Intfn travel_leg(worker_id : String, from : Location, to : Location, depart_minute : Int, policy : SchedulePolicy) -> TravelLegfn validate_time_window(window : TimeWindow, entity_id : String, field : String) -> Array[Diagnostic]fn visit(id : String, recipient_id : String, title : String, location : Location, window : TimeWindow, duration_minutes : Int) -> VisitExplainable community care and volunteer scheduling engine