diff --git a/backend/db/crud.py b/backend/db/crud.py index 784e5f20d8374b0fa932739d35d618dee898a436..8a1ee26c6bc9b7d116812e66e3a3f9cb837557dc 100644 --- a/backend/db/crud.py +++ b/backend/db/crud.py @@ -13,8 +13,8 @@ from db import models, schemas def get_waiting_time(place: str, db: Session): """ Get the last estimated waiting time for the given place """ - date = datetime.now(tz=pytz.timezone("Europe/Paris")) - weekday, current_time = date.weekday(), date.time() + current_date = datetime.now(tz=pytz.timezone("Europe/Paris")) + weekday, current_time = current_date.weekday(), date.time() first_timeslot = get_timeslot(place, weekday, True, db) if first_timeslot and current_time < first_timeslot[0]: return first_timeslot[0].hour, first_timeslot[0].minute @@ -44,7 +44,7 @@ def get_waiting_time(place: str, db: Session): return None, None -def get_stats(place: str, weekday: int, min_time: time, max_time: time, interval: timedelta, db: Session): +def get_avg_graph_points(place: str, weekday: int, min_time: time, max_time: time, interval: timedelta, db: Session): """ Get the average waiting time for each interval between two time steps """ def shift_time(t: time, delta: timedelta): @@ -87,6 +87,82 @@ def get_stats(place: str, weekday: int, min_time: time, max_time: time, interval return stats +def get_next_avg_graph(place: str, db: Session): + """ Get the average waiting time for each interval between two time steps, + for the current or next available timeslot""" + current_date = datetime.now(tz=pytz.timezone("Europe/Paris")) + weekday, current_time = current_date.weekday(), current_date.time() + first_timeslot = get_timeslot(place, weekday, True, db) + if first_timeslot and current_time <= first_timeslot[1]: + return get_avg_graph_points(place, weekday, first_timeslot[0], first_timeslot[1], timedelta(minutes=5), db) + second_timeslot = get_timeslot(place, weekday, False, db) + if second_timeslot and current_time <= second_timeslot[1]: + return get_avg_graph_points(place, weekday, second_timeslot[0], second_timeslot[1], timedelta(minutes=5), db) + return None + + +def get_current_graph_points(place: str, current_date: date, min_time: time, max_time: time, interval: timedelta, db: Session): + """ Get the waiting time for each interval between two time steps for the current timeslot """ + + def shift_time(t: time, delta: timedelta): + return (datetime.combine(date(1, 1, 1), t) + delta).time() + + def avg_time_query(start_time, end_time): + records = db.query( + (func.round( + func.avg( + 3600 * func.extract('HOUR', models.Records.waiting_time) + + 60 * func.extract('MINUTE', models.Records.waiting_time) + + func.extract('SECOND', models.Records.waiting_time)) + )) / 60 + ).filter( + models.Records.place == place, + func.extract('YEAR', models.Records.date) == current_date.year, + func.extract('MONTH', models.Records.date) == current_date.month, + func.extract('DAY', models.Records.date) == current_date.day, + (func.extract('HOUR', models.Records.date) > start_time.hour) | + ((func.extract('HOUR', models.Records.date) == start_time.hour) & + (func.extract('MINUTE', models.Records.date) >= start_time.minute)), + (func.extract('HOUR', models.Records.date) < end_time.hour) | + ((func.extract('HOUR', models.Records.date) == end_time.hour) & + (func.extract('MINUTE', models.Records.date) < end_time.minute)), + ).one() + if records[0]: + return int(records[0]) + return None + + def add_slot(slots_list, start_time, end_time): + average_waiting_time = avg_time_query(start_time, end_time) + if average_waiting_time: + name = f'{start_time.hour:02}h{start_time.minute:02}' + slots_list.append({'name': name, 'time': average_waiting_time}) + + stats = [] + start_time, end_time = min_time, shift_time(min_time, interval) + while start_time < max_time: + add_slot(stats, start_time, end_time) + start_time, end_time = end_time, shift_time(end_time, interval) + + return stats + + +def get_current_graph(place: str, db: Session): + """ Get the waiting_time_graph for the current timeslot""" + current_date = datetime.now(tz=pytz.timezone("Europe/Paris")) + weekday, day, current_time = current_date.weekday(), current_date.date(), current_date.time() + first_timeslot = get_timeslot(place, weekday, True, db) + if first_timeslot and current_time <= first_timeslot[0]: + return None + elif first_timeslot and current_time <= first_timeslot[1]: + return get_current_graph_points(place, day, first_timeslot[0], current_time, timedelta(minutes=5), db) + second_timeslot = get_timeslot(place, weekday, False, db) + if second_timeslot and current_time <= second_timeslot[0]: + return None + elif second_timeslot and current_time <= second_timeslot[1]: + return get_current_graph_points(place, day, second_timeslot[0], current_time, timedelta(minutes=5), db) + return None + + # Define CRUD operation for the comments def get_comments(place: str, page: int, db: Session): diff --git a/backend/routers/stats.py b/backend/routers/stats.py index b3887930fc4b9bbcd6676176d30edda71724c8d7..52efe45f0d85d23530e65ea810f8a1f7ef265869 100644 --- a/backend/routers/stats.py +++ b/backend/routers/stats.py @@ -1,6 +1,5 @@ from fastapi import APIRouter, Depends from sqlalchemy.orm import Session -from datetime import timedelta, time from db import crud from db.database import get_db @@ -14,6 +13,6 @@ async def waiting_time(place: str, db: Session = Depends(get_db)): return crud.get_waiting_time(place, db) -@router.get('/{place}/stats/{day}/{min_time}/{max_time}/{interval}', response_model=list) -async def stats(place: str, day: int, min_time: time, max_time: time, interval: timedelta, db: Session = Depends(get_db)): - return crud.get_stats(place, day, min_time, max_time, interval, db) +@router.get('/{place}/stats/avg_graph', response_model=list) +async def stats(place: str, db: Session = Depends(get_db)): + return crud.get_avg_graph(place, db)