lin_ / timing_lin.py
Zelyanoth's picture
jk
aa1cf8a
import pandas as pd
from datetime import datetime, timedelta
import bisect
JOUR_OFFSET = {
'Monday': 0, 'Tuesday': 1, 'Wednesday': 2, 'Thursday': 3,
'Friday': 4, 'Saturday': 5, 'Sunday': 6
}
BASE_DATE = datetime(2025, 1, 6)
def parse_slot(slot_str):
jour, horaire = slot_str.split()
horaire = horaire.replace(';', ':')
h, m = map(int, horaire.split(':'))
date = BASE_DATE + timedelta(days=JOUR_OFFSET[jour])
return datetime(date.year, date.month, date.day, h, m)
def format_slot(dt):
return f"{dt.strftime('%A')} {dt.strftime('%H:%M')}"
def add_request(df_fixed, new_slot_str):
new_dt = parse_slot(new_slot_str)
desired_dt = new_dt - timedelta(minutes=5)
# on récupère les adjusted existants triés
slots_dt = sorted(parse_slot(s) for s in df_fixed['adjusted_time'])
# on commence par placer final_dt = desired_dt, puis on recule au besoin
final_dt = desired_dt
# boucle tant que final_dt viole au moins une contrainte d'espacement
while True:
conflict = False
# 1) avec le schedule_time
if new_dt - final_dt < timedelta(minutes=5):
# on recule pour avoir exactement 7mi d'avance
final_dt = new_dt - timedelta(minutes=5)
conflict = True
# 2) avec chaque adjusted existant
for slot in slots_dt:
if abs((slot - final_dt).total_seconds()) < 5*60:
# on recule de 7min par rapport à cet adjusted
# si slot > final, on repousse final à slot -7min
# sinon (slot < final), on recule encore de 7min
if slot > final_dt:
final_dt = slot - timedelta(minutes=5)
else:
final_dt = slot - timedelta(minutes=5)
conflict = True
break
if not conflict:
break # on a trouvé un créneau valide
final_str = format_slot(final_dt)
df_fixed = pd.concat([
df_fixed,
pd.DataFrame([{
'schedule_time': new_slot_str,
'adjusted_time': final_str
}])
], ignore_index=True)
return df_fixed.sort_values('adjusted_time').reset_index(drop=True),final_str