Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • main
1 result

Target

Select target project
  • raptornythorink/eatfast-website
1 result
Select Git revision
  • main
1 result
Show changes
Commits on Source (9)
Showing
with 219 additions and 248 deletions
......@@ -4,6 +4,7 @@ Module to interact with the database
from datetime import date, datetime, time, timedelta
from sqlalchemy.orm import Session
from sqlalchemy.sql import func
from sqlalchemy import Time, Date, cast
from uuid import uuid4
import secrets
import pytz
......@@ -17,87 +18,60 @@ def get_waiting_time(place: str, db: Session):
""" Get the last estimated waiting time for the given place """
current_date = datetime.now(tz=pytz.timezone("Europe/Paris"))
weekday, current_time = current_date.weekday(), current_date.time()
data = {"status": False, "waiting_time": None, "next_timetable": None}
first_timeslot = get_timeslot(place, weekday, True, db)
if first_timeslot and current_time < first_timeslot[0]:
data["next_timetable"] = "{:d}h{:02d}".format(
first_timeslot[0].hour, first_timeslot[0].minute)
return data
elif first_timeslot and current_time <= first_timeslot[1]:
last_record = db.query(
models.Records.waiting_time
).filter(
models.Records.place == place
).order_by(
models.Records.date.desc()
).first()
if last_record:
waiting_time = last_record.waiting_time
waiting_time = round(waiting_time.total_seconds() / 60)
data["status"] = True
data["waiting_time"] = waiting_time
return data
second_timeslot = get_timeslot(place, weekday, False, db)
if second_timeslot and current_time < second_timeslot[0]:
data["next_timetable"] = "{:d}h{:02d}".format(
second_timeslot[0].hour, second_timeslot[0].minute)
return data
elif second_timeslot and current_time <= second_timeslot[1]:
last_record = db.query(
models.Records.waiting_time
).filter(
models.Records.place == place
).order_by(
models.Records.date.desc()
).first()
opening_hours = db.query(models.OpeningHours.open_time, models.OpeningHours.close_time).filter(
models.OpeningHours.place == place, models.OpeningHours.day == weekday).all()
for time_slot in opening_hours:
if current_time < time_slot.open_time:
return schemas.WaitingTime(next_timetable=time_slot.open_time.strftime('%Hh%M'))
elif current_time <= time_slot.close_time:
limit = datetime.combine(date.today(), time_slot.open_time)
last_record = db.query(models.Records.waiting_time).filter(models.Records.place == place).filter(
models.Records.date >= limit).order_by(models.Records.date.desc()).first()
waiting_time = None
if last_record:
waiting_time = last_record.waiting_time
waiting_time = round(waiting_time.total_seconds() / 60)
data["status"] = True
data["waiting_time"] = waiting_time
return data
return data
waiting_time = round(
last_record.waiting_time.total_seconds() / 60)
return schemas.WaitingTime(status=True, waiting_time=waiting_time)
return schemas.WaitingTime()
# Define some utils function
def shift_time(t: time, delta: timedelta):
return (datetime.combine(date(1, 1, 1), t) + delta).time()
def add_slot(slots_list, start_time, end_time, function):
average_waiting_time = function(start_time, end_time)
if average_waiting_time:
name = 60 * start_time.hour + start_time.minute
slots_list.append(schemas.RecordRead(name=name, time=average_waiting_time))
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):
return (datetime.combine(date(1, 1, 1), t) + delta).time()
def avg_time_query(start_time, end_time):
records = db.query(
(func.round(
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
60 * func.extract('HOUR', models.Records.waiting_time) +
func.extract('MINUTE', models.Records.waiting_time))
)
).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]:
cast(models.Records.date, Time) >= start_time,
cast(models.Records.date, Time) <= end_time,
).first()
if records[0] or records[0] == 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 = 60 * start_time.hour + start_time.minute
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)
add_slot(stats, start_time, end_time, avg_time_query)
start_time, end_time = end_time, shift_time(end_time, interval)
return stats
......@@ -108,13 +82,12 @@ def get_avg_graph(place: str, db: Session):
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)
opening_hours = db.query(models.OpeningHours.open_time, models.OpeningHours.close_time).filter(
models.OpeningHours.place == place, models.OpeningHours.day == weekday).order_by(models.OpeningHours.open_time).all()
for time_slot in opening_hours:
if current_time <= time_slot.close_time:
return get_avg_graph_points(place, weekday, time_slot.open_time, time_slot.close_time, timedelta(minutes=5), db)
return []
......@@ -122,43 +95,27 @@ 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):
def current_time_query(start_time, end_time):
records = db.query(
(func.round(
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
60 * func.extract('HOUR', models.Records.waiting_time) +
func.extract('MINUTE', models.Records.waiting_time))
)
).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]:
cast(models.Records.date, Date) == current_date,
cast(models.Records.date, Time) >= start_time,
cast(models.Records.date, Time) <= end_time
).first()
if records[0] or records[0] == 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 = 60 * start_time.hour + start_time.minute
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)
add_slot(stats, start_time, end_time, current_time_query)
start_time, end_time = end_time, shift_time(end_time, interval)
return stats
......@@ -169,23 +126,17 @@ def get_current_graph(place: str, db: Session):
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, None
elif first_timeslot and current_time <= first_timeslot[1]:
points = get_current_graph_points(place, day, first_timeslot[0], current_time, timedelta(minutes=5), db)
start_time = 60 * first_timeslot[0].hour + first_timeslot[0].minute
end_time = 60 * first_timeslot[1].hour + first_timeslot[1].minute
return points, start_time, end_time
second_timeslot = get_timeslot(place, weekday, False, db)
if second_timeslot and current_time <= second_timeslot[0]:
return [], None, None
elif second_timeslot and current_time <= second_timeslot[1]:
points = get_current_graph_points(place, day, second_timeslot[0], current_time, timedelta(minutes=5), db)
start_time = 60 * second_timeslot[0].hour + second_timeslot[0].minute
end_time = 60 * second_timeslot[1].hour + second_timeslot[1].minute
return points, start_time, end_time
return [], None, None
opening_hours = db.query(models.OpeningHours.open_time, models.OpeningHours.close_time).filter(
models.OpeningHours.place == place, models.OpeningHours.day == weekday).all()
for time_slot in opening_hours:
if time_slot.open_time <= current_time <= time_slot.close_time:
points = get_current_graph_points(
place, day, time_slot.open_time, current_time, timedelta(minutes=5), db)
start_time = 60 * time_slot.open_time.hour + time_slot.open_time.minute
end_time = 60 * time_slot.close_time.hour + time_slot.close_time.minute
return schemas.Graph(data=points, start=start_time, end=end_time)
return schemas.Graph(data=[])
# Define CRUD operation for the comments
......@@ -210,13 +161,17 @@ def get_comments(place: str, page: int, db: Session):
20,
page *
20).all()
return list(schemas.Comment(**comment.__dict__, username=username) for comment, username in comments)
comments_list = list(schemas.Comment(
**comment.__dict__, username=username) for comment, username in comments)
comments_list.reverse()
return comments_list
def create_comment(user: schemas.User, place: str, new_comments: schemas.CommentBase, db: Session):
""" Add a new comment to the database """
date = datetime.now(tz=pytz.timezone("Europe/Paris"))
db_comment = models.Comments(**new_comments.dict(), published_at=date, place=place, user_id=user.id)
db_comment = models.Comments(
**new_comments.dict(), published_at=date, place=place, user_id=user.id)
db.add(db_comment)
db.commit()
db.refresh(db_comment)
......@@ -271,24 +226,11 @@ def get_opening_hours(place: str, db: Session):
).filter(
models.OpeningHours.place == place
).order_by(
models.OpeningHours.day, models.OpeningHours.timeslot.desc()
models.OpeningHours.day, models.OpeningHours.open_time
).all()
return opening_hours
def get_timeslot(place: str, day: int, timeslot: bool, db: Session):
""" Get the opening hours for the given place and timeslot"""
opening_hours = db.query(
models.OpeningHours.open_time,
models.OpeningHours.close_time,
).filter(
models.OpeningHours.place == place,
models.OpeningHours.day == day,
models.OpeningHours.timeslot == timeslot
).first()
return opening_hours
def create_opening_hours(
new_opening_hours: schemas.OpeningHoursBase, db: Session):
""" Add opening hours to the database """
......@@ -313,56 +255,19 @@ def delete_opening_hours(id: int, db: Session):
# Restaurants information
def get_restaurants(db: Session):
current_date = datetime.now(tz=pytz.timezone("Europe/Paris"))
weekday, current_time = current_date.weekday(), current_date.time()
restaurant_names = [
r.place for r in db.query(
models.OpeningHours.place).distinct()]
weekday = datetime.now(tz=pytz.timezone("Europe/Paris")).weekday()
places = db.query(models.OpeningHours.place).distinct()
restaurants = []
for name in restaurant_names:
restaurant = {}
restaurant["name"] = name
first_timeslot = get_timeslot(name, weekday, True, db)
second_timeslot = get_timeslot(name, weekday, False, db)
if (first_timeslot and first_timeslot[0] <= current_time < first_timeslot[1]) or (
second_timeslot and second_timeslot[0] <= current_time < second_timeslot[1]):
restaurant["status"] = True
else:
restaurant["status"] = False
if first_timeslot and second_timeslot:
restaurant["timetable"] = (
f"{first_timeslot[0].hour:{'0'}{2}}h{first_timeslot[0].minute:{'0'}{2}}-"
f"{first_timeslot[1].hour:{'0'}{2}}h{first_timeslot[1].minute:{'0'}{2}} / "
f"{second_timeslot[0].hour:{'0'}{2}}h{second_timeslot[0].minute:{'0'}{2}}-"
f"{second_timeslot[1].hour:{'0'}{2}}h{second_timeslot[1].minute:{'0'}{2}}")
elif first_timeslot:
restaurant["timetable"] = (
f"{first_timeslot[0].hour:{'0'}{2}}h{first_timeslot[0].minute:{'0'}{2}}-"
f"{first_timeslot[1].hour:{'0'}{2}}h{first_timeslot[1].minute:{'0'}{2}}")
else:
restaurant["timeslot"] = "-"
if restaurant["status"]:
last_record = db.query(
models.Records
).filter(
models.Records.place == name
).order_by(
models.Records.date.desc()
).first()
if last_record:
waiting_time = last_record.waiting_time
restaurant["waiting_time"] = round(
waiting_time.total_seconds() / 60)
else:
restaurant["waiting_time"] = None
else:
restaurant["waiting_time"] = None
restaurants.append(restaurant)
for place in places:
opening_hours = db.query(models.OpeningHours).filter(
models.OpeningHours.place == place.place, models.OpeningHours.day == weekday).all()
opening_hours_formated = [
f"{row.open_time.strftime('%Hh%M')}-{row.close_time.strftime('%Hh%M')}" for row in opening_hours]
timetable = "/".join(opening_hours_formated)
infos = get_waiting_time(place.place, db)
restaurants.append(schemas.Restaurant(
**infos.dict(), name=place.place, timetable=timetable))
return restaurants
......@@ -373,8 +278,10 @@ def init_user(db: Session):
""" Add a news to the database """
cookie = uuid4()
state = secrets.token_urlsafe(30)
expiration_date = datetime.now(tz=pytz.timezone("Europe/Paris")) + timedelta(minutes=10)
db_user = models.Users(state=state, cookie=cookie, expiration_date=expiration_date)
expiration_date = datetime.now(tz=pytz.timezone(
"Europe/Paris")) + timedelta(minutes=10)
db_user = models.Users(state=state, cookie=cookie,
expiration_date=expiration_date)
db.add(db_user)
db.commit()
db.refresh(db_user)
......@@ -398,8 +305,10 @@ def delete_state(user: schemas.User, db: Session):
def update_user(user: schemas.User, user_info: dict, db: Session):
full_name = f"{user_info['firstName']} {user_info['lastName']}"
expiration_date = datetime.now(tz=pytz.timezone("Europe/Paris")) + timedelta(days=3)
existing_user = db.query(models.Users).filter(models.Users.username == full_name).first()
expiration_date = datetime.now(
tz=pytz.timezone("Europe/Paris")) + timedelta(days=3)
existing_user = db.query(models.Users).filter(
models.Users.username == full_name).first()
if existing_user:
existing_user.cookie = user.cookie
existing_user.expiration_date = expiration_date
......
......@@ -48,7 +48,6 @@ class OpeningHours(Base):
id = Column(Integer, primary_key=True, index=True)
place = Column(String(30))
day = Column(Integer)
timeslot = Column(Boolean)
open_time = Column(Time)
close_time = Column(Time)
......
"""
Pydantic schemas for the magasin app
"""
from typing import Optional
from typing import List, Optional
from datetime import datetime, timedelta, time
from pydantic import BaseModel, Field
# Records data structure
class RecordBase(BaseModel):
"""Records base schema"""
place: str = Field(...,
......@@ -24,6 +25,13 @@ class Record(RecordBase):
orm_mode = True
class RecordRead(BaseModel):
""" Data structure for record in graph """
name: int
time: int
# Comments Data structure
class CommentBase(BaseModel):
"""Comments base schema"""
content: str = Field(..., title="Content of the comment posted")
......@@ -40,6 +48,7 @@ class Comment(CommentBase):
orm_mode = True
# News data structure
class NewsBase(BaseModel):
"""News sql table model"""
title: str = Field(..., title="Title of the news")
......@@ -57,13 +66,19 @@ class News(NewsBase):
orm_mode = True
# Stats data structure
class WaitingTime(BaseModel):
"""Waiting time schema for reading"""
status: bool = Field(default=False, title="Status of the restaurant for the current hour")
waiting_time: Optional[timedelta] = Field(default=None, title="Waiting time for the restaurant")
next_timetable: Optional[str] = Field(default=None, title="Next time the restaurant will be open")
class OpeningHoursBase(BaseModel):
"""Database opening_hours base schema"""
place: str = Field(...,
title="Name of the RU corresponding the given record")
day: int = Field(..., title="Day of the week")
timeslot: bool = Field(...,
title="Service slot (True for midday, False for evening)")
open_time: time = Field(..., title="Opening time")
close_time: time = Field(..., title="Closing time")
......@@ -76,6 +91,22 @@ class OpeningHours(OpeningHoursBase):
orm_mode = True
class Restaurant(BaseModel):
"""Restaurant schema for reading"""
name: str
status: bool
waiting_time: Optional[timedelta] = Field(default=None, title="Waiting time for the restaurant")
timetable: str
class Graph(BaseModel):
""" Data structure for current graph display """
data: List[RecordRead] = Field(title="Last records list for the restaurant")
start: Optional[int] = Field(default=None, title="Opening of the RU")
end: Optional[int] = Field(default=None, title="Closure of the RU")
# User data structure
class User(BaseModel):
"""Database user base schema"""
id: int
......
......@@ -2,14 +2,14 @@ from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from dotenv import load_dotenv
import os
from db.database import get_db
from fastapi import Depends
from sqlalchemy.orm import Session
from db import schemas
from typing import List
from threading import Thread
import json
from db import database, models
from db import database, models, schemas
from db.database import get_db
from routers import *
from video_capture import handle_cameras
......@@ -44,6 +44,7 @@ app.include_router(stats.router)
app.include_router(comments.router)
app.include_router(news.router)
app.include_router(authentication.router)
app.include_router(websocket.router)
@app.get('/api/records', response_model=List[schemas.Record])
......@@ -58,6 +59,7 @@ async def post_records(record: schemas.RecordBase, db: Session = Depends(get_db)
db.add(db_record)
db.commit()
db.refresh(db_record)
await websocket.manager.broadcast(json.dumps({"type": "data"}))
return db_record
......
from . import authentication
from . import comments
from . import news
from . import opening_hours
from . import stats
from . import websocket
......@@ -74,6 +74,8 @@ async def login(code: Optional[str] = None, state: Optional[str] = None, connect
@router.get("/logout")
async def delete_session(connect_id: str = Cookie(...), db: Session = Depends(get_db)):
response = RedirectResponse(f"{os.getenv('AUTH_ROOT')}/logout?{urlencode({'redirect_logout': os.getenv('WEB_ROOT')})}")
try:
response.delete_cookie(key="connect_id")
crud.end_session(connect_id, db)
finally:
return response
from fastapi import APIRouter, Body, Cookie, Depends
from sqlalchemy.orm import Session
from typing import List
import json
from db import schemas, crud
from db.database import get_db
from routers.websocket import manager
router = APIRouter(prefix="/api", tags=["comments"])
......@@ -18,7 +20,9 @@ async def get_comments(place: str, page: int = 1, db: Session = Depends(get_db))
async def create_comment(place: str, connect_id: str = Cookie(...), comment: schemas.CommentBase = Body(...), db: Session = Depends(get_db)):
user = crud.get_user(connect_id, db)
if user:
return crud.create_comment(user, place, comment, db)
saved_comment = crud.create_comment(user, place, comment, db)
await manager.broadcast(json.dumps({"type": "comment", "comment": saved_comment.dict()}, default=str))
return saved_comment
else:
raise Exception
......
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from typing import List
import json
from db import schemas, crud
from db.database import get_db
from .websocket import manager
router = APIRouter(prefix="/api", tags=["news"])
......@@ -16,7 +18,9 @@ async def get_news(place: str, db: Session = Depends(get_db)):
@router.post('/news', response_model=schemas.News)
async def create_news(news: schemas.NewsBase, db: Session = Depends(get_db)):
return crud.create_news(news, db)
saved_news = crud.create_news(news, db)
await manager.broadcast(json.dumps({"type": "news", "comment": saved_news.__dict__}, default=str))
return saved_news
@router.delete('/news/{id}', response_model=None)
......
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from typing import List, Tuple
from typing import List
from db import schemas, crud
from db.database import get_db
router = APIRouter(prefix="/api", tags=["stats"])
router = APIRouter(prefix="/api")
@router.get('/{place}/waiting_time', response_model=dict)
@router.get('/{place}/waiting_time', response_model=schemas.WaitingTime, tags=["stats"])
async def waiting_time(place: str, db: Session = Depends(get_db)):
return crud.get_waiting_time(place, db)
@router.get('/{place}/stats/avg_graph', response_model=list)
@router.get('/{place}/stats/avg_graph', response_model=list, tags=["stats"])
async def stats(place: str, db: Session = Depends(get_db)):
return crud.get_avg_graph(place, db)
@router.get('/{place}/stats/current_graph', response_model=Tuple[list, int, int])
@router.get('/{place}/stats/current_graph', response_model=schemas.Graph, tags=["stats"])
async def stats(place: str, db: Session = Depends(get_db)):
return crud.get_current_graph(place, db)
@router.get('/{place}/opening_hours',
response_model=List[schemas.OpeningHours])
response_model=List[schemas.OpeningHours], tags=["timetable"])
async def get_opening_hours(place: str, db: Session = Depends(get_db)):
return crud.get_opening_hours(place, db)
@router.get('/{place}/opening_hours/{day}/{timeslot}',
response_model=List[schemas.OpeningHours])
async def get_timeslot(place: str, day: int, timeslot: bool, db: Session = Depends(get_db)):
return crud.get_timeslot(place, day, timeslot, db)
@router.post('/opening_hours', response_model=schemas.OpeningHours)
@router.post('/opening_hours', response_model=schemas.OpeningHours, tags=["timetable"])
async def create_opening_hours(opening_hours: schemas.OpeningHoursBase, db: Session = Depends(get_db)):
return crud.create_opening_hours(opening_hours, db)
@router.delete('/opening_hours/{id}', response_model=None)
@router.delete('/opening_hours/{id}', response_model=None, tags=["timetable"])
async def delete_opening_hours(id: int, db: Session = Depends(get_db)):
return crud.delete_opening_hours(id, db)
@router.get('/restaurants', response_model=List[dict])
@router.get('/restaurants', response_model=List[schemas.Restaurant], tags=["timetable"])
async def get_restaurants(db: Session = Depends(get_db)):
return crud.get_restaurants(db)
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from typing import List
class ConnectionManager:
def __init__(self):
self.active_connections: List[WebSocket] = []
async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)
def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)
async def send_personal_message(self, message: str, websocket: WebSocket):
await websocket.send_text(message)
async def broadcast(self, message: str):
for connection in self.active_connections:
try:
await connection.send_text(message)
except WebSocketDisconnect:
manager.disconnect(connection)
manager = ConnectionManager()
router = APIRouter(tags=["websocket"])
@router.websocket("/api/ws")
async def websocket_endpoint(websocket: WebSocket):
await manager.connect(websocket)
try:
while True:
await websocket.receive_text()
except WebSocketDisconnect:
manager.disconnect(websocket)
......@@ -3,11 +3,13 @@ from datetime import datetime, timedelta
import numpy as np
import keras
from utils.preprocessing import fix_singular_shape, norm_by_imagenet
from db import models
from dotenv import load_dotenv
import json
import os
from db import models
from db.database import SessionLocal
from routers.websocket import manager
def handle_cameras():
......@@ -56,7 +58,6 @@ def handle_cameras():
axis=0)
pred_map = np.squeeze(model.predict(input_image))
count_prediction = np.sum(pred_map)
print(count_prediction)
waiting_time = timedelta(
seconds=camera['b_factor'] +
int(count_prediction) *
......@@ -68,7 +69,7 @@ def handle_cameras():
waiting_time=waiting_time)
db.add(db_record)
db.commit()
db.refresh(db_record)
manager.broadcast(json.dumps({"type": "data"}))
camera['count'] += 1
else:
camera["cap"] = cv2.VideoCapture(
......
REACT_APP_BASE_URL_BACK=http://localhost:3001/api
REACT_APP_SOCKET_URL=ws://localhost:3001/api
\ No newline at end of file
......@@ -22,6 +22,7 @@
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"react-spring": "^9.4.5",
"react-use-websocket": "^4.2.0",
"recharts": "^2.1.12"
},
"devDependencies": {
......@@ -17521,6 +17522,15 @@
"react-dom": ">=16.6.0"
}
},
"node_modules/react-use-websocket": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-4.2.0.tgz",
"integrity": "sha512-ZovaTlc/tWX6a590fi3kMWImhyoWj46BWJWvO5oucZJzRnVVhYtes2D9g+5MKXjSdR7Es3456hB89v4/1pcBKg==",
"peerDependencies": {
"react": ">= 18.0.0",
"react-dom": ">= 18.0.0"
}
},
"node_modules/react-zdog": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/react-zdog/-/react-zdog-1.0.11.tgz",
......@@ -34103,6 +34113,12 @@
"prop-types": "^15.6.2"
}
},
"react-use-websocket": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-4.2.0.tgz",
"integrity": "sha512-ZovaTlc/tWX6a590fi3kMWImhyoWj46BWJWvO5oucZJzRnVVhYtes2D9g+5MKXjSdR7Es3456hB89v4/1pcBKg==",
"requires": {}
},
"react-zdog": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/react-zdog/-/react-zdog-1.0.11.tgz",
......@@ -17,6 +17,7 @@
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"react-spring": "^9.4.5",
"react-use-websocket": "^4.2.0",
"recharts": "^2.1.12"
},
"scripts": {
......
frontend/public/favicon.ico

3.08 KiB

......@@ -2,19 +2,13 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="%PUBLIC_URL%/thumbnail_violet.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
content="Web site developed by ViaRézo"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
......@@ -24,7 +18,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>Eatfast</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
......
frontend/public/logo192.png

5.22 KiB

frontend/public/logo512.png

9.44 KiB

{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
frontend/public/thumbnail_violet.png

86.7 KiB