2022-10-10 01:34:38 +02:00
|
|
|
from services.database import generate_unique_code
|
|
|
|
from services.io import add_fast_api_root
|
|
|
|
from generateur.generateur_main import generate_from_path, parseGeneratorOut, parseOut
|
|
|
|
from database.exercices.models import Exercice
|
|
|
|
from database.room.crud import CorrigedChallenge, change_correction, corrige_challenge, create_parcours_db, delete_parcours_db, create_room_db, get_member_dep, check_room, serialize_room, update_parcours_db, get_parcours, get_room, check_admin, get_exercices, get_challenge, get_correction, create_tmp_correction, create_challenge, change_challenge
|
2022-09-26 10:04:02 +02:00
|
|
|
|
2022-09-18 22:43:04 +02:00
|
|
|
from pydantic import BaseModel
|
|
|
|
from typing import Any, Callable, Dict, List, Optional
|
2022-10-10 01:34:38 +02:00
|
|
|
from fastapi import APIRouter, Depends, WebSocket, status, Query, Body
|
2022-09-18 22:43:04 +02:00
|
|
|
from config import ALGORITHM, SECRET_KEY
|
|
|
|
from database.auth.crud import get_user_from_clientId_db
|
|
|
|
from database.auth.models import User
|
|
|
|
from database.db import get_session
|
2022-09-25 22:32:19 +02:00
|
|
|
|
2022-10-10 01:34:38 +02:00
|
|
|
from sqlmodel import Session, col, select
|
|
|
|
from database.room.models import Challenge, ChallengeRead, Challenges, CorrigedGeneratorOut, Member, Note, Parcours, ParcoursCreate, ParcoursRead, ParcoursReadShort, ParsedGeneratorOut, Room, RoomConnectionInfos, RoomCreate, RoomAndMember, RoomInfo, TmpCorrection
|
2022-09-26 10:04:02 +02:00
|
|
|
from routes.room.consumer import RoomConsumer
|
|
|
|
from routes.room.manager import RoomManager
|
2022-09-18 22:43:04 +02:00
|
|
|
from services.auth import get_current_user_optional
|
|
|
|
from fastapi.exceptions import HTTPException
|
2022-09-26 10:04:02 +02:00
|
|
|
from database.auth.crud import get_user_from_token
|
|
|
|
from services.websocket import Consumer
|
2022-10-10 01:34:38 +02:00
|
|
|
from services.misc import noteOn20, stripKeyDict
|
2022-09-16 21:50:55 +02:00
|
|
|
router = APIRouter(tags=["room"])
|
2022-10-10 01:34:38 +02:00
|
|
|
manager = RoomManager()
|
|
|
|
|
2022-09-16 21:50:55 +02:00
|
|
|
|
2022-10-10 01:34:38 +02:00
|
|
|
def get_manager():
|
|
|
|
return manager
|
2022-09-18 22:43:04 +02:00
|
|
|
|
2022-10-10 01:34:38 +02:00
|
|
|
@router.post('/room', response_model=RoomConnectionInfos)
|
2022-09-18 22:43:04 +02:00
|
|
|
def create_room(room: RoomCreate, username: Optional[str] = Query(default=None, max_length=20), user: User | None = Depends(get_current_user_optional), db: Session = Depends(get_session)):
|
|
|
|
room_obj = create_room_db(room=room, user=user, username=username, db=db)
|
2022-10-10 01:34:38 +02:00
|
|
|
return {'room': room_obj['room'].id_code, "member": getattr(room_obj['member'].anonymous, "reconnect_code", None)}
|
2022-09-18 22:43:04 +02:00
|
|
|
|
|
|
|
|
2022-10-10 01:34:38 +02:00
|
|
|
@router.get('/room/{room_id}', response_model=RoomInfo)
|
|
|
|
def get_room_route(room: Room = Depends(get_room), member: Member = Depends(get_member_dep), db: Session = Depends(get_session)):
|
|
|
|
return serialize_room(room, member, db)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post('/room/{room_id}/parcours', response_model=ParcoursRead)
|
|
|
|
async def create_parcours(*, parcours: ParcoursCreate, room_id: str, member: Member = Depends(check_admin), m: RoomManager = Depends(get_manager), db: Session = Depends(get_session)):
|
|
|
|
parcours_obj = create_parcours_db(parcours, member.room_id, db)
|
|
|
|
if type(parcours_obj) == str:
|
|
|
|
raise HTTPException(
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail=parcours_obj)
|
|
|
|
await m.broadcast({"type": "add_parcours", "data": {"parcours": ParcoursReadShort(**parcours_obj.dict(exclude_unset=True)).dict()}}, room_id)
|
|
|
|
return parcours_obj
|
|
|
|
|
|
|
|
|
|
|
|
@router.get('/room/{room_id}/parcours/{parcours_id}', response_model=ParcoursRead)
|
|
|
|
async def get_parcours_route(*, parcours: Parcours = Depends(get_parcours), member: Member = Depends(get_member_dep), db: Session = Depends(get_session)):
|
|
|
|
if member.is_admin == False:
|
|
|
|
return {**parcours.dict(), "challenges": [Challenges(**{**chall.dict(), "challenger": member.id_code, "canCorrige": chall.data != []}) for chall in parcours.challenges if chall.challenger.id_code == member.id_code]}
|
|
|
|
|
|
|
|
if member.is_admin == True:
|
|
|
|
return {**parcours.dict(), "challenges": [Challenges(**{**chall.dict(), "challenger": member.id_code, "canCorrige": chall.data != []}) for chall in parcours.challenges]}
|
|
|
|
|
|
|
|
|
|
|
|
@router.put('/room/{room_id}/parcours/{parcours_id}', response_model=ParcoursRead, dependencies=[Depends(check_admin)])
|
|
|
|
async def update_parcours(*, room_id: str, parcours: ParcoursCreate, parcours_old: Parcours = Depends(get_parcours), m: RoomManager = Depends(get_manager), db: Session = Depends(get_session)):
|
|
|
|
parcours_obj = update_parcours_db(parcours, parcours_old, db)
|
|
|
|
if type(parcours_obj) == str:
|
|
|
|
raise HTTPException(
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail=parcours_obj)
|
|
|
|
short = ParcoursReadShort(
|
|
|
|
**parcours_obj.dict(exclude_unset=True), id_code=parcours_obj.id_code)
|
|
|
|
await m.broadcast({"type": "update_parcours", "data": {"parcours": short.dict()}}, room_id)
|
|
|
|
return parcours_obj
|
|
|
|
|
|
|
|
|
|
|
|
@router.delete('/room/{room_id}/parcours/{parcours_id}', dependencies=[Depends(check_admin)])
|
|
|
|
async def delete_parcours(parcours: Parcours = Depends(get_parcours), m: RoomManager = Depends(get_manager), db: Session = Depends(get_session)):
|
|
|
|
delete_parcours_db(parcours, db)
|
|
|
|
await m.broadcast({"type": "del_parcours", "data": {"parcours_id": parcours.id_code}}, parcours.room.id_code)
|
|
|
|
return "ok"
|
|
|
|
|
|
|
|
|
|
|
|
class Exos(BaseModel):
|
|
|
|
exercice: Exercice
|
|
|
|
quantity: int
|
|
|
|
|
|
|
|
@router.get('/room/{room_id}/challenge/{parcours_id}')
|
|
|
|
def challenge_route(parcours_id: str, exercices: List[Exos] = Depends(get_exercices), member: Member = Depends(get_member_dep), db: Session = Depends(get_session)):
|
|
|
|
correction = [parseGeneratorOut(generate_from_path(add_fast_api_root(
|
|
|
|
e['exercice'].exo_source), e['quantity'], "web")) for e in exercices]
|
|
|
|
sending = [[{**c, 'inputs': [stripKeyDict(i, "correction")
|
|
|
|
for i in c['inputs']]} for c in e] for e in correction]
|
|
|
|
tmpCorr = create_tmp_correction(correction, parcours_id, member, db)
|
|
|
|
|
|
|
|
return {'challenge': sending, "id_code": tmpCorr.id_code}
|
|
|
|
|
|
|
|
|
|
|
|
@router.post('/room/{room_id}/challenge/{parcours_id}/{correction_id}', response_model=ChallengeRead)
|
|
|
|
async def send_challenge(*, challenge: List[List[ParsedGeneratorOut]], correction: TmpCorrection = Depends(get_correction), time: int = Body(), db: Session = Depends(get_session), m: RoomManager = Depends(get_manager),):
|
|
|
|
parcours = correction.parcours
|
|
|
|
member = correction.member
|
|
|
|
data = corrige_challenge(challenge, correction)
|
|
|
|
if data is None:
|
|
|
|
raise HTTPException(
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail={"challenge_error":"Object does not correspond to correction"})
|
|
|
|
chall = create_challenge(**data, challenger=member,
|
|
|
|
parcours=parcours, time=time, db=db)
|
|
|
|
|
|
|
|
await m.broadcast({"type": "challenge", "data": Challenges(**{**chall.dict(), "challenger": member.id_code, "canCorrige": chall.data != []}).dict()}, parcours.id_code)
|
|
|
|
db.delete(correction)
|
|
|
|
db.commit()
|
|
|
|
return chall
|
|
|
|
|
|
|
|
|
|
|
|
@router.get('/room/{room_id}/challenge/{parcours_id}/{challenge_id}', response_model=ChallengeRead, dependencies=[Depends(get_member_dep)])
|
|
|
|
async def challenge_read(*, challenge: Challenge = Depends(get_challenge)):
|
|
|
|
return challenge
|
|
|
|
|
|
|
|
|
|
|
|
@router.put('/room/{room_id}/challenge/{parcours_id}/{challenge_id}', response_model=ChallengeRead, dependencies=[Depends(check_admin)])
|
|
|
|
async def corrige(*, correction: List[List[CorrigedGeneratorOut]], challenge: Challenge = Depends(get_challenge), db: Session = Depends(get_session), m: RoomManager = Depends(get_manager),):
|
|
|
|
parcours = challenge.parcours
|
|
|
|
member = challenge.challenger
|
|
|
|
data = change_correction(correction, challenge)
|
|
|
|
if data is None:
|
|
|
|
raise HTTPException(
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail={"correction_error": "Object does not correspond to challenge"})
|
|
|
|
challenge = change_challenge(challenge, data, db)
|
|
|
|
|
|
|
|
await m.broadcast({"type": "challenge_change", "data": Challenges(**{**challenge.dict(), "challenger": member.id_code, "canCorrige": challenge.data != []}).dict()}, parcours.id_code)
|
|
|
|
return challenge
|
2022-09-21 22:31:50 +02:00
|
|
|
|
2022-09-26 10:04:02 +02:00
|
|
|
|
2022-09-18 22:43:04 +02:00
|
|
|
@router.websocket('/ws/room/{room_id}')
|
2022-10-10 01:34:38 +02:00
|
|
|
async def room_ws(ws: WebSocket, room: Room | None = Depends(check_room), db: Session = Depends(get_session), m: RoomManager = Depends(get_manager)):
|
2022-09-18 22:43:04 +02:00
|
|
|
if room is None:
|
|
|
|
raise HTTPException(
|
|
|
|
status_code=status.HTTP_404_NOT_FOUND, detail='Room not found')
|
2022-10-10 01:34:38 +02:00
|
|
|
consumer = RoomConsumer(ws=ws, room=room, manager=m, db=db)
|
2022-09-18 22:43:04 +02:00
|
|
|
await consumer.run()
|