diff --git a/gen.py b/gen.py index ef05b01..1c92363 100644 --- a/gen.py +++ b/gen.py @@ -27,24 +27,24 @@ from rota.workers import ( suspend_on_finish = True solve = True -time_to_run = 258500 +time_to_run = 458500 #time_to_run = 2660000 #time_to_run = 458500 # allow = 5000 -ratio = 0.001 +ratio = 0.05 #ratio = 0.9 -start_date = datetime.date(2022, 9, 5) +start_date = datetime.date(2023, 3, 6) #start_date = start_date + datetime.timedelta(weeks=13) # start_date = datetime.date(2022, 10, 10) -Rota = RotaBuilder(start_date, weeks_to_rota=26) +Rota = RotaBuilder(start_date, weeks_to_rota=26, balance_offset_modifier=1) Rota.constraint_options["balance_weekends"] = True -Rota.constraint_options["max_night_frequency"] = 3 -Rota.constraint_options["max_night_frequency_week_exclusions"] = [1,2,3,4,5,6] +Rota.constraint_options["max_night_frequency"] = 3 # 3 +Rota.constraint_options["max_night_frequency_week_exclusions"] = [] Rota.constraint_options["max_weekend_frequency"] = 2 -Rota.constraint_options["hard_constrain_pair_separation"] = True +Rota.constraint_options["hard_constrain_pair_separation"] = False # Rota.constraint_options["avoid_st2_first_month"] = True Rota.add_shifts( @@ -57,7 +57,7 @@ Rota.add_shifts( constraint=[ { "name": "max_shifts_per_week", - "options": 2, + "options": 1, } ], ), @@ -152,7 +152,7 @@ Rota.add_shifts( bank_holidays_only=True, ), SingleShift( - sites=(sites), + sites=sites, name="night_weekday", length=12.25, days=days[:4], @@ -193,11 +193,11 @@ Rota.add_shifts( ), ) -Rota.add_grade_constraint_by_week([2], [1, 2], ["night_weekday", "night_weekend"]) +#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()) +#Rota.add_grade_constraint_by_week([2], [1], Rota.get_shift_names()) if load_leave: import leave @@ -211,7 +211,12 @@ if load_leave: w = workers[worker] site = w["site"] grade = w["grade"] - fte = float(w["fte"]) * 100 + try: + fte = float(w["fte"]) * 100 + except ValueError: + print(f"{worker} has invalid fte: {fte}") + raise ValueError + nwd = w["nwd"] end_date = w["end_date"] start_date = w["start_date"] @@ -244,7 +249,21 @@ if load_leave: ) # nwds = [i.strip()[:3].capitalize() for i in nwd.split("/")] if nwd else None end_date = end_date if end_date else None - oop = oop.split("-") if oop else None + + + if oop: + formatted_oops = [] + for dates in oop.split(","): + s, e = dates.split("-") + formatted_oops.append( + {"start_date": datetime.datetime.strptime(s, "%d/%m/%y").date(), "end_date": datetime.datetime.strptime(e, "%d/%m/%y").date()} + ) + + oop = formatted_oops + else: + oop = [] + + print(f"{worker} OOP {oop}") previous_shifts = {} # if twi: @@ -276,8 +295,7 @@ if load_leave: work_requests = w["requests"] site_pref = w["site_pref"] - Rota.add_worker( - Worker( + w = Worker( name=worker_name, site=site.lower(), grade=int(grade[2]), @@ -286,7 +304,7 @@ if load_leave: nwds=nwds, start_date=start_date, end_date=end_date, - opp=oop, + oop=oop, not_available_to_work=leave_requests, work_requests=work_requests, remote_site=site_pref, @@ -295,12 +313,16 @@ if load_leave: shift_balance_extra=w["shift_balance_extra"], bank_holiday_extra=w["bank_holiday_extra"], ) - ) + + print(w) + + Rota.add_worker(w) + # Rota.build_workers() # Rota.build_model() -solver_options = {"ratio": ratio, "seconds": time_to_run, "threads": 11} +solver_options = {"ratio": ratio, "seconds": time_to_run, "threads": 10} start_time = time.time() Rota.build_and_solve(solver_options) diff --git a/leave.py b/leave.py index a0eaab0..9d2e600 100644 --- a/leave.py +++ b/leave.py @@ -16,7 +16,7 @@ def load_leave(Rota): workers = {} - download = s.get("https://docs.google.com/spreadsheets/d/e/2PACX-1vS49eVS0f86wUJIhXMq7tMPZfAEJZatER09JLu0xnlTjDBkC-54DkAPT3I0JVXDQXNG6AIh_fVeIRS3/pub?gid=0&single=true&output=csv") + download = s.get("https://docs.google.com/spreadsheets/d/e/2PACX-1vR18crGluN4wrL9n1sBdZ2u-JsvaLtQ6hr-R5CPUBOaKpL7_hBbhemyPSrFOhDuWxKlrjh-QUM0HrcD/pub?gid=0&single=true&output=csv") decoded_content = download.content.decode('utf-8') reader = csv.reader(decoded_content.splitlines(), delimiter=',') @@ -100,7 +100,7 @@ def load_leave(Rota): elif row_title == "Pair": if lower_item == "": - worker["pair"] = 0 + worker["pair"] = None else: worker["pair"] = int(lower_item) diff --git a/rota/workers.py b/rota/workers.py index 689a680..395dde6 100644 --- a/rota/workers.py +++ b/rota/workers.py @@ -121,6 +121,7 @@ class Worker(BaseModel): if self.name == "Steph bailey": print(self.start_date, self.end_date) + print(self.oop) # if no start date default to the start of the rota if self.start_date is None: @@ -187,6 +188,7 @@ class Worker(BaseModel): start_oop_date = Rota.start_date oop_length = (end_oop_date - start_oop_date).days + print(f"oop length {oop_length}") days_to_work = days_to_work - oop_length days_until_oop = (start_oop_date - Rota.start_date).days @@ -280,18 +282,19 @@ class Worker(BaseModel): ) def __str__(self) -> str: + return f"{self.name}, {self.site}, {self.oop}" - nwds = ( - ", ".join([str(i) for i, start, end in self.non_working_day_list]) - if self.non_working_day_list is not None - else "" - ) - return "{} {} [{}] REMOTE SITE:{}".format( - self.name, - (self.site, self.grade, self.fte_adj), - nwds, - self.remote_site, - ) + #nwds = ( + # ", ".join([str(i) for i, start, end in self.non_working_day_list]) + # if self.non_working_day_list is not None + # else "" + #) + #return "{} {} [{}] REMOTE SITE:{}".format( + # self.name, + # (self.site, self.grade, self.fte_adj), + # nwds, + # self.remote_site, + #) def get_details(self) -> str: return "{} {} {}".format(self.id, self.site[0], self.grade)