From aa575cf4f6a9ea7c171fd69fc4a300f569b5496f Mon Sep 17 00:00:00 2001
From: Aymeric Chaumont <aymeric.chaumont@student-cs.fr>
Date: Wed, 6 Jul 2022 14:17:54 +0200
Subject: [PATCH] add route to get waiting time stats

---
 backend/db/crud.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++
 backend/main.py    |  7 ++++++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/backend/db/crud.py b/backend/db/crud.py
index 02e961e..dcb87c4 100644
--- a/backend/db/crud.py
+++ b/backend/db/crud.py
@@ -1,7 +1,11 @@
 """
 Module to interact with the database
 """
+from datetime import date, datetime, time, timedelta
+from numpy import average
 from sqlalchemy.orm import Session
+from sqlalchemy.sql import func
+
 from db import models, schemas
 
 
@@ -24,3 +28,47 @@ def get_waiting_time(place: str, db: Session):
     """ Get the last estimated waiting time for the given place """
     db_record = db.query(models.Records).filter(models.Records.place == place).order_by(models.Records.date.desc()).one()
     return db_record.waiting_time
+
+
+def get_stats(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):
+        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.weekday(models.Records.date) == weekday,
+                (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(dic, start_time, end_time):
+        average_waiting_time = avg_time_query(start_time, end_time)
+        if average_waiting_time:
+            key = f'{start_time.hour:02}-{start_time.minute:02}-{end_time.hour:02}-{end_time.minute:02}'
+            dic[key] = 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
diff --git a/backend/main.py b/backend/main.py
index 4418ddd..7b7b899 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -1,4 +1,4 @@
-from datetime import timedelta
+from datetime import datetime, time, timedelta
 from typing import List
 from fastapi import Body, Depends, FastAPI
 from fastapi.middleware.cors import CORSMiddleware
@@ -57,6 +57,11 @@ async def waiting_time(place: str, db: Session = Depends(get_db)):
     return crud.get_waiting_time(place, db)
 
 
+@app.get('/api/{place}/stats/{day}/{start_time}/{end_time}/{interval}', response_model=int)
+async def stats(place: str, day: int, start_time: time, end_time: time, interval: timedelta, db: Session = Depends(get_db)):
+    return crud.get_stats(place, day, start_time, end_time, interval, db)
+
+
 """
 import cv2
 import numpy as np
-- 
GitLab