///|
/// Named demonstration scenarios distributed with the package.
pub(all) enum DemoScenario {
CommunityCare
CampusVolunteers
SuddenAbsence
} derive(Debug, Eq)
///|
/// Parse a scenario name accepted by the CLI.
pub fn parse_demo_scenario(name : String) -> DemoScenario? {
match name.to_lower() {
"community" | "community-care" | "care" => Some(CommunityCare)
"campus" | "campus-volunteers" | "volunteers" => Some(CampusVolunteers)
"absence" | "sudden-absence" | "reschedule" => Some(SuddenAbsence)
_ => None
}
}
///|
/// Stable name for a demonstration scenario.
pub fn demo_scenario_name(value : DemoScenario) -> String {
match value {
CommunityCare => "community-care"
CampusVolunteers => "campus-volunteers"
SuddenAbsence => "sudden-absence"
}
}
///|
fn demo_place(id : String, x : Int, y : Int, zone : String) -> Location {
location(id, x, y, zone)
}
///|
fn demo_worker(
id : String,
name : String,
kind : WorkerKind,
home : Location,
skills : Array[Skill],
availability : Array[TimeWindow],
) -> Worker {
{
..worker(id, name, kind, home),
skills,
availability,
max_minutes: 360,
max_visits: 6,
min_break_minutes: 10,
}
}
///|
fn community_workers() -> Array[Worker] {
[
demo_worker(
"w-lin",
"Lin",
CareWorker,
demo_place("lin-home", 0, 0, "central"),
[skill("companionship", 3), skill("meal", 2), skill("mobility", 2)],
[time_window(480, 1020)],
),
demo_worker(
"w-chen",
"Chen",
Volunteer,
demo_place("chen-home", 6, 1, "east"),
[skill("companionship", 2), skill("shopping", 3), skill("digital", 2)],
[time_window(540, 1080)],
),
demo_worker(
"w-zhao",
"Zhao",
Volunteer,
demo_place("zhao-home", -3, 2, "west"),
[skill("companionship", 2), skill("meal", 1), skill("driving", 2)],
[time_window(480, 840), time_window(900, 1140)],
),
]
}
///|
fn community_visits() -> Array[Visit] {
[
{
..visit(
"visit-breakfast",
"resident-a",
"Breakfast preparation",
demo_place("resident-a", 1, 0, "central"),
time_window(510, 630),
45,
),
required_skills: [skill("meal", 1)],
priority: High,
continuity_group: Some("resident-a"),
},
{
..visit(
"visit-walk",
"resident-a",
"Mobility walk",
demo_place("resident-a", 1, 0, "central"),
time_window(660, 840),
60,
),
required_skills: [skill("mobility", 2)],
priority: Normal,
preferred_worker_ids: ["w-lin"],
continuity_group: Some("resident-a"),
},
{
..visit(
"visit-shopping",
"resident-b",
"Grocery shopping",
demo_place("market-east", 7, 2, "east"),
time_window(600, 900),
75,
),
required_skills: [skill("shopping", 2)],
priority: Normal,
preferred_worker_ids: ["w-chen"],
},
{
..visit(
"visit-video-call",
"resident-c",
"Family video call setup",
demo_place("resident-c", 5, 0, "east"),
time_window(840, 1020),
45,
),
required_skills: [skill("digital", 1)],
priority: Low,
required: false,
},
{
..visit(
"visit-clinic",
"resident-d",
"Clinic transport accompaniment",
demo_place("clinic-west", -5, 2, "west"),
time_window(900, 1080),
90,
),
required_skills: [skill("driving", 2), skill("companionship", 1)],
priority: Critical,
preferred_worker_ids: ["w-zhao"],
},
]
}
///|
fn campus_workers() -> Array[Worker] {
[
demo_worker(
"student-a",
"Student A",
Volunteer,
demo_place("dorm-a", 0, 0, "north-campus"),
[skill("registration", 2), skill("guidance", 1)],
[time_window(480, 780)],
),
demo_worker(
"student-b",
"Student B",
Volunteer,
demo_place("dorm-b", 3, 1, "north-campus"),
[skill("registration", 1), skill("first_aid", 2)],
[time_window(480, 900)],
),
demo_worker(
"student-c",
"Student C",
Volunteer,
demo_place("dorm-c", 8, 0, "south-campus"),
[skill("guidance", 3), skill("logistics", 2)],
[time_window(540, 960)],
),
]
}
///|
fn campus_visits() -> Array[Visit] {
[
{
..visit(
"campus-registration",
"event-office",
"Registration desk",
demo_place("hall", 2, 1, "north-campus"),
time_window(510, 630),
90,
),
required_skills: [skill("registration", 2)],
priority: Critical,
},
{
..visit(
"campus-guide-a",
"visitor-group-a",
"Campus guidance",
demo_place("gate", 5, 0, "central-campus"),
time_window(600, 780),
60,
),
required_skills: [skill("guidance", 1)],
priority: High,
},
{
..visit(
"campus-first-aid",
"event-office",
"First aid post",
demo_place("sports-field", 9, 1, "south-campus"),
time_window(660, 900),
120,
),
required_skills: [skill("first_aid", 2)],
priority: Critical,
},
{
..visit(
"campus-logistics",
"event-office",
"Material delivery",
demo_place("warehouse", 10, 2, "south-campus"),
time_window(540, 840),
75,
),
required_skills: [skill("logistics", 2)],
priority: Normal,
},
]
}
///|
/// Build a complete request for a named scenario.
pub fn demo_request(scenario : DemoScenario) -> ScheduleRequest {
match scenario {
CommunityCare | SuddenAbsence =>
schedule_request(community_workers(), community_visits())
CampusVolunteers => schedule_request(campus_workers(), campus_visits())
}
}
///|
/// Solve one built-in demonstration.
pub fn run_demo(scenario : DemoScenario) -> Schedule {
solve(demo_request(scenario))
}
///|
/// Run the absence demonstration and return its impact report.
pub fn run_absence_demo() -> RescheduleReport {
let request = demo_request(SuddenAbsence)
let baseline = solve(request)
reschedule(baseline, request, [
WorkerAbsent(worker_id="w-lin", from_minute=480, to_minute=1140),
])
}