update rota
This commit is contained in:
+196
@@ -0,0 +1,196 @@
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from rota.shifts import NoWorkers, RotaBuilder, SingleShift, WorkerRequirement, days
|
||||
import typer
|
||||
import subprocess
|
||||
|
||||
from rota.workers import (
|
||||
Worker,
|
||||
NotAvailableToWork,
|
||||
NonWorkingDays,
|
||||
WorkRequests,
|
||||
PreferenceNotToWork,
|
||||
OutOfProgramme,
|
||||
)
|
||||
|
||||
|
||||
app = typer.Typer()
|
||||
|
||||
|
||||
sites = ("rota a", "rota b", "rota c")
|
||||
|
||||
|
||||
@app.command()
|
||||
def main(
|
||||
suspend: bool = False,
|
||||
solve: bool = True,
|
||||
time_to_run: int = 60 * 60,
|
||||
ratio: float = 0.001,
|
||||
start_date: datetime.datetime = "2025-09-01",
|
||||
weeks: int = 16,
|
||||
bom: int = 1,
|
||||
):
|
||||
rota_start_date = start_date.date()
|
||||
suspend_on_finish = suspend
|
||||
|
||||
Rota = RotaBuilder(
|
||||
rota_start_date,
|
||||
weeks_to_rota=weeks,
|
||||
balance_offset_modifier=bom,
|
||||
name="cons rota",
|
||||
)
|
||||
# Rota = RotaBuilder(start_date, weeks_to_rota=20, balance_offset_modifier=1)
|
||||
Rota.constraint_options["balance_shifts"] = False
|
||||
Rota.constraint_options["balance_shifts_quadratic"] = True
|
||||
Rota.constraint_options["balance_weekends"] = True
|
||||
Rota.constraint_options["max_night_frequency"] = 3 # 3
|
||||
Rota.constraint_options["max_night_frequency_week_exclusions"] = []
|
||||
Rota.constraint_options["max_weekend_frequency"] = 4
|
||||
Rota.constraint_options["hard_constrain_pair_separation"] = True
|
||||
Rota.constraint_options["max_shifts_per_week"] = 3
|
||||
# Rota.constraint_options["avoid_st2_first_month"] = True
|
||||
|
||||
Rota.add_shifts(
|
||||
SingleShift(
|
||||
sites=("rota a",),
|
||||
name="oncall weekday",
|
||||
length=12.5,
|
||||
days=days[:4],
|
||||
balance_offset=2,
|
||||
constraint=[
|
||||
{
|
||||
"name": "max_shifts_per_week",
|
||||
"options": 3,
|
||||
}
|
||||
],
|
||||
),
|
||||
SingleShift(
|
||||
sites=("rota a",),
|
||||
name="Oncall weekend",
|
||||
length=12.5,
|
||||
days=days[4:],
|
||||
balance_offset=2,
|
||||
assign_as_block=True,
|
||||
constraint=[
|
||||
{
|
||||
"name": "max_shifts_per_week",
|
||||
"options": 3,
|
||||
},
|
||||
{"name": "pre", "options": 2},
|
||||
{"name": "post", "options": 2},
|
||||
],
|
||||
),
|
||||
SingleShift(
|
||||
sites=("rota a",),
|
||||
name="weekend a",
|
||||
workers_required=1,
|
||||
length=12.5,
|
||||
days=days[5:],
|
||||
balance_offset=2,
|
||||
constraint=[
|
||||
{"name": "pre", "options": 2},
|
||||
{"name": "post", "options": 2},
|
||||
],
|
||||
display_char="a",
|
||||
),
|
||||
SingleShift(
|
||||
sites=("rota b", "rota c"),
|
||||
name="weekend b",
|
||||
workers_required=1,
|
||||
length=12.5,
|
||||
days=days[5:],
|
||||
balance_offset=2,
|
||||
constraint=[
|
||||
{"name": "pre", "options": 2},
|
||||
{"name": "post", "options": 2},
|
||||
],
|
||||
display_char="b",
|
||||
),
|
||||
SingleShift(
|
||||
sites=(
|
||||
"rota a",
|
||||
"rota b",
|
||||
),
|
||||
name="evening",
|
||||
workers_required=1,
|
||||
length=12.5,
|
||||
days=days[:5],
|
||||
balance_offset=2,
|
||||
constraint=[],
|
||||
),
|
||||
)
|
||||
|
||||
# Rota.add_grade_constraint_by_week([2], [1, 2], ["night_weekday", "night_weekend"])
|
||||
|
||||
load_leave = True
|
||||
Rota.build_shifts()
|
||||
# Rota.add_grade_constraint_by_week([2], [1], Rota.get_shift_names())
|
||||
|
||||
for w in range(1, 12):
|
||||
w = Worker(name=f"A{w:02d}", site="rota a", grade=1)
|
||||
|
||||
print(w)
|
||||
|
||||
Rota.add_worker(w)
|
||||
|
||||
for w in range(12, 21):
|
||||
w = Worker(
|
||||
name=f"B{w}",
|
||||
site="rota b",
|
||||
grade=1,
|
||||
nwds=[
|
||||
NonWorkingDays(
|
||||
day="Fri",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
print(w)
|
||||
|
||||
Rota.add_worker(w)
|
||||
|
||||
# Rota.build_workers()
|
||||
# Rota.build_model()
|
||||
|
||||
solver_options = {"ratio": ratio, "seconds": time_to_run, "threads": 10}
|
||||
# solver_options = {"seconds": time_to_run, "threads": 10}
|
||||
|
||||
# start_time = time.time()
|
||||
Rota.build_and_solve(solver_options, export=True, solve=solve, solver="appsi_highs")
|
||||
|
||||
# Rota.solve_shifts_by_block(solver_options, block_length=13)
|
||||
# Rota.solve_shifts_individually(solver_options)
|
||||
# Rota.solve_model(options=solver_options)
|
||||
# end_time = time.time()
|
||||
|
||||
# print(f"Time taken {end_time-start_time}")
|
||||
|
||||
# print(Rota.get_worker_details())
|
||||
|
||||
# optimizer = SolverFactory('cbc')
|
||||
# result = optimizer.solve(prob,tee=True)
|
||||
# result.Solver.Status = SolverStatus.warning
|
||||
# prob.solutions.load_from(result)
|
||||
|
||||
# ResultsHolder = RotaResults(Rota)
|
||||
|
||||
# worker_timetable_brief = ResultsHolder.get_worker_timetable_brief(
|
||||
# show_prefs=False, show_unavailable=False
|
||||
# )
|
||||
#
|
||||
# print(worker_timetable_brief)
|
||||
|
||||
# Rota.export_rota_to_html("proc_rota")
|
||||
# Rota.export_rota_to_csv("rota")
|
||||
subprocess.run(
|
||||
["scp", Rota.exported_rota_file, "ross@46.101.13.46:proc/proc-rota/output/"]
|
||||
)
|
||||
|
||||
if suspend_on_finish:
|
||||
os.system("systemctl suspend")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app()
|
||||
Reference in New Issue
Block a user