Generateurv2/backend/api/room/views.py
2022-05-18 10:15:54 +02:00

417 lines
19 KiB
Python

from sys import api_version
from rest_framework.decorators import api_view
from datetime import datetime
import random
from shutil import register_unpack_format
import string
from uuid import uuid4
from django.shortcuts import render
import pytz
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
from .models import Room, Parcours, TempCorrection
from .serializers import RoomSerializer, ParcoursSerializer
from django.contrib.sessions.models import Session
from api.Generateur import Generateur
from exercices.models import Exercice
from exercices.serializers import ExerciceSerializer
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
from .utils import getNow
# Create your views here.
class RoomAPI(APIView):
def post(self, request, format=None):
name = request.data.get('name')
nick = request.data.get('nick')
code = ''.join(
random.choices(string.ascii_uppercase, k=6))
clientId = str(uuid4())
room = Room(name=name, owner={'name': nick, 'code': code, "clientId": clientId}, participants=[{'nick': nick, 'owner': True, 'code': code, "clientId": clientId}]
)
room.save()
return Response({"data": {'id_code': room.id_code, "clientId": clientId, "code": code}}, status=status.HTTP_200_OK)
def get(self, request, format=None):
code = request.GET.get('code')
room = None
try:
room = Room.objects.filter(id_code=code)[0]
except IndexError:
return Response({'error': 'Aucune salle trouvée', 'code': '4044'}, status=status.HTTP_404_NOT_FOUND)
clientId = request.GET.get('clientId')
participants = room.participants
if clientId not in list(map(lambda p: p['clientId'], participants)):
return Response({'error': 'Non autorisé', 'code': '401'}, status=status.HTTP_401_UNAUTHORIZED)
admin = False
if clientId == room.owner['clientId']:
admin = True
# "challenger": list(map(lambda c: {'nick': p['nick'], "validate": c['validate'], 'exos': list(map(lambda e: {'endAt': e['endAt'], 'note': e['note']}, p['exos']))}, p.challenger))
return Response({"data": {"room": {**RoomSerializer(room).data, "waiters": room.waiters if admin == True else [], "participants": list(map(lambda p: {'nick': p['nick'], 'owner': p['owner'], 'online': p['online'], "code": p['code'] if admin == True else ""}, participants)), 'parcours': list(map(lambda p: {**ParcoursSerializer(p).data}, room.parcours_set.all()))}}}, status=status.HTTP_200_OK)
def delete(self, request, format=None):
code = request.data.get('code')
room = Room.objects.filter(id_code=code)[0]
room.delete()
return Response({"data": ''}, status=status.HTTP_200_OK)
def patch(self, request, format=None):
code = request.data.get('pin')
nick = request.data.get('nick')
room = None
try:
room = Room.objects.filter(id_code=code)[0]
except IndexError:
return Response({'error': 'No room'}, status=status.HTTP_502_BAD_GATEWAY)
# print(room)
if 'roomsJoined' not in request.session:
request.session['roomsJoined'] = []
elif 'roomsJoined' in request.session:
request.session['roomsJoined'] = list(
filter(lambda s: len(Room.objects.filter(id_code=s['id_code'])) != 0, request.session['roomsJoined']))
if room.id_code not in list(map(lambda r: r['id_code'], request.session['roomsJoined'])):
code = ''.join(
random.choices(string.ascii_uppercase, k=6))
while code in list(map(lambda p: p['code'], room.participants)):
code = ''.join(
random.choices(string.ascii_uppercase, k=6))
room.participants = [*room.participants, {
'nick': nick,
'owner': False,
'code': code
}]
try:
request.session['roomsJoined'] = [*request.session['roomsJoined'], {'id_code': room.id_code, 'nick': nick,
'owner': False,
'code': code}]
except:
request.session['roomsJoined'] = [{'id_code': room.id_code, 'nick': nick,
'owner': False,
'code': code}]
room.save()
return Response({"data": {'id_code': room.id_code}}, status=status.HTTP_200_OK)
@api_view(['GET'])
def RoomExist(request, id_code):
if Room.objects.filter(id_code=id_code).count() > 0:
return Response({'data': {"id_code": id_code}}, status=status.HTTP_200_OK)
else:
return Response({'error': 'Aucune salle trouvée', 'code': '4044'}, status=status.HTTP_404_NOT_FOUND)
@api_view(['GET'])
def getCorrectionInfo(request):
parcours_id = request.query_params['parcours_id']
user_code = request.query_params['user_code']
correct_code = request.query_params['correct_code']
parcours = Parcours.objects.filter(id_code=parcours_id)
if len(parcours) == 0:
return Response({'error': 'Pas de parcours lol'}, status=status.HTTP_404_NOT_FOUND)
parcours = parcours[0]
challenger = list(
filter(lambda p: p['code'] == user_code, parcours.challenger))
if(len(challenger) == 0):
return Response({'error': 'Vous n\'êtes pas un participant'}, status=status.HTTP_401_UNAUTHORIZED)
trys = challenger[0]['exos']
challenge = list(filter(lambda c: c['code'] == correct_code, trys))
if(len(challenge) == 0):
return Response({'error': 'Not found'}, status=status.HTTP_404_NOT_FOUND)
challenge = challenge[0]
return Response({'data': {**challenge, "parcours_id": parcours.id_code, 'user_code': user_code}}, status=status.HTTP_200_OK)
class ChallengeAPI(APIView):
def get(self, request, format=None):
id_code = request.GET.get('code')
user_code = request.GET.get('user_code')
parcours = Parcours.objects.filter(id_code=id_code)
if len(parcours) == 0:
return Response({'error': 'Pas de parcours lol'}, status=status.HTTP_404_NOT_FOUND)
parcours = parcours[0]
room = parcours.room
participants = list(
filter(lambda p: p['code'] == user_code, room.participants))
if(len(participants) == 0):
return Response({'error': 'Vous n\'êtes pas un participant'}, status=status.HTTP_401_UNAUTHORIZED)
exos = parcours.exercices
exos = list(map(lambda e: Generateur(Exercice.objects.filter(
id_code=e['id_code'])[0].exo_model.name, e['number'], 'web'), exos))
def parseCorrection(calcul):
"""Fait en sorte de séparer la correction présente dans le calcul"""
calculEx = calcul['calcul'].replace('[', ' [').replace(']', '] ')
splitted = calculEx.split()
if len(list(filter(lambda e: e.startswith("[") and e.endswith(']'), splitted))) == 0:
splitted.append('[]')
inputs = []
for i in range(len(splitted)):
c = splitted[i]
if c.startswith('[') and c.endswith(']'):
corr = c.replace('[', '').replace(']', '')
splitted[i] = f'[{len(inputs)}]'
inputs.append(
{'order': len(inputs), 'correction': corr, 'value': ""})
calculEx = ' '.join(splitted)
return {'calcul': calculEx, 'inputs': inputs}
exosWcorrection = []
for i in range(len(exos)):
ex = exos[i]
tempsExs = list(map(parseCorrection, ex))
tmp = {'order': i, 'exos': [{'order': ind, **e}
for ind, e in enumerate(tempsExs)]}
exosWcorrection.append(tmp)
#exos[i] = {'order': i, 'exos': list(map(lambda e, id: {'order': id,'calcul': e['calcul'], 'inputs': list(map(lambda i :{'order': i['order'],'value':i['value']}, e['inputs']))}, tempsExs))}
#exos[i] = list(map(lambda e: {'calcul': e['calcul'], 'inputs': list(map(lambda i :{'order': i['order'],'value':i['value']}, e['inputs']))}, tempsExs))
exos[i] = {'order': i, 'exos': [{'order': ind, 'calcul': e['calcul'], 'inputs': [
{'value': inp['value'], 'order': inp['order'], 'correction': ""} for inp in e['inputs']]} for ind, e in enumerate(tempsExs)]}
tempCorr = TempCorrection(correction=exosWcorrection)
tempCorr.save()
return Response({"data": {**ParcoursSerializer(parcours).data, "exos": exos, 'correctId': tempCorr.id_code}}, status=status.HTTP_200_OK)
def post(self, request, format=None):
exos = request.data.get('exos')
parcours_id = request.data.get('id_code')
user_code = request.data.get('user_code')
correct_code = request.data.get('correct_code')
parcours = Parcours.objects.filter(id_code=parcours_id)
if len(parcours) == 0:
return Response({'error': 'Pas de parcours lol'}, status=status.HTTP_404_NOT_FOUND)
parcours = parcours[0]
room = parcours.room
corrections = TempCorrection.objects.filter(id_code=correct_code)
if len(corrections) == 0:
return Response({'error': 'Correction indisponible !'}, status=status.HTTP_404_NOT_FOUND)
correctionDB = corrections[0]
participants = list(
filter(lambda p: p['code'] == user_code, room.participants))
if(len(participants) == 0):
return Response({'error': 'Vous n\'êtes pas un participant'}, status=status.HTTP_401_UNAUTHORIZED)
# Corriger selon la correction les exos envoyé dans exos.exos
student_answer = exos['result']
correction = correctionDB.correction
inpppp = 0
def corrige(ans):
correctionExos = list(
filter(lambda c: c['order'] == ans['order'], correction))[0]
corrigedList = []
for a in ans['exos']:
#a = ans['exos'][i]
exoCorrect = list(
filter(lambda c: c['order'] == a['order'], correctionExos['exos']))[0]
correctInputs = exoCorrect['inputs']
print('correcti', correctInputs)
studentsInput = sorted(a['inputs'], key=lambda i: i.get('order'))
print('correctiinnnn\n\n', studentsInput)
corrigedInputs = [{**inp, "value": studentsInput[inp['order']]['value'], "isCorrect": (str(studentsInput[inp['order']]['value']) == str(
inp['correction'])) if inp['correction'] != "" else None} for inp in correctInputs]
corrigedList.append({**a, 'inputs': corrigedInputs})
return {**ans, "exos": corrigedList}
corriged = list((map(corrige, student_answer)))
#l6 = uniquement les isCorrect
l2 = [exs['exos'] for exs in corriged]
l4 = [ex['inputs'] for exs in l2 for ex in exs]
l5 = [ex for exs in l4 for ex in exs]
l6 = [e['isCorrect'] for e in l5]
note = {
"total": len(l6),
"value": l6.count(True),
"isTrust": l6.count(None) == 0
}
adding_challenger = Parcours.objects.challenge(
parcours_id, user_code, {"result": corriged, "timer": exos['timer'], "note": note})
correctionDB.delete()
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(f"owner__{room.id_code}", {
'type': "challenge_parcours", 'id_code': parcours_id, "participant": participants[0], "validate": adding_challenger['validate'], 'exos': {'note': note, 'endAt': getNow(), "timer": exos['timer']}})
return Response({"data": {"exos": corriged, "note": note}}, status=status.HTTP_200_OK)
def put(self, request, format=None):
parcours_id = request.data.get('parcours_id')
result = request.data.get('result')
challenge_code = request.data.get('challenge_code')
clientId = request.data.get('clientId')
user_code = request.data.get('user_code')
note = request.data.get('note')
print(f'PARCOURS: {parcours_id}')
parcours = Parcours.objects.filter(id_code=parcours_id)
if len(parcours) == 0:
return Response({'error': 'Pas de parcours lol'}, status=status.HTTP_404_NOT_FOUND)
parcours = parcours[0]
room = parcours.room
print(f'CLIENTID COMPARE: {room.owner["clientId"]}\n{clientId}')
if room.owner['clientId'] != clientId:
return Response({'error': 'Pas les droits'}, status=status.HTTP_401_UNAUTHORIZED)
challenger = list(
filter(lambda p: p['code'] == user_code, parcours.challenger))
if(len(challenger) == 0):
return Response({'error': 'Not found'}, status=status.HTTP_401_UNAUTHORIZED)
trys = challenger[0]['exos']
challenge = list(filter(lambda c: c['code'] == challenge_code, trys))
if(len(challenge) == 0):
return Response({'error': 'Not found'}, status=status.HTTP_404_NOT_FOUND)
challenge = challenge[0]
date = getNow()
condition = parcours.success_condition
parcours.challenger = [
*list(filter(lambda p: p['code'] != user_code, parcours.challenger)), {**challenger[0], "validate": date if note['value'] * 20 / note['total'] >= condition else False ,"exos": [*list(filter(lambda c: c['code'] != challenge_code, trys)), {**challenge, "result": result, "note": note}]}]
parcours.save()
return Response({"data": {}}, status=status.HTTP_200_OK)
class ParcoursAPI(APIView):
def delete(self, request, format=None):
id_code = request.data.get('id_code')
code = request.data.get('code')
print(f'id_code={id_code};code={code}')
parcours = Parcours.objects.filter(id_code=id_code)
if len(parcours) == 0:
return Response({'error': 'Pas de parcours lol'}, status=status.HTTP_404_NOT_FOUND)
parcours = parcours[0]
room = parcours.room
if room.owner['code'] != code:
return Response({'error': 'Pas owner'}, status=status.HTTP_401_UNAUTHORIZED)
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(parcours.room.id_code,
{'type': 'delete_parcours', "id_code": id_code})
parcours.delete()
return Response({'data': {'id_code': id_code}}, status=status.HTTP_200_OK)
def post(self, request, format=None):
name = request.data.get('name')
# ...futur: pour admin quand j'aurais fait la création de room "clean"
code = request.data.get('code')
room_code = request.data.get('room_code')
exos = request.data.get('exos')
timer = request.data.get('timer')
# print(exos, name, room_code)
try:
room = Room.objects.filter(id_code=room_code)[0]
except:
return Response({'error': ""}, status=status.HTTP_404_NOT_FOUND)
if room.owner['code'] != code:
return Response({'error': ''}, status=status.HTTP_401_UNAUTHORIZED)
parcours = Parcours(name=name, room=room, timer=timer, exercices=exos)
parcours.save()
layer = get_channel_layer()
async_to_sync(layer.group_send)(room_code, {
'type': 'new_parcours', 'parcours': ParcoursSerializer(parcours).data})
layer = get_channel_layer()
return Response({"data": {'id_code': parcours.id_code}}, status=status.HTTP_200_OK)
def put(self, request, format=None):
name = request.data.get('name')
# ...futur: pour admin quand j'aurais fait la création de room "clean"
code = request.data.get('code')
id_code = request.data.get('id_code')
exos = request.data.get('exos')
timer = request.data.get('timer')
# print(exos, name, room_code)
try:
parcours = Parcours.objects.filter(id_code=id_code)[0]
except:
return Response({'error': ""}, status=status.HTTP_404_NOT_FOUND)
room = parcours.room
if code != room.owner['code']:
return Response({'error': ''}, status=status.HTTP_401_UNAUTHORIZED)
parcours.challenger = []
parcours.name = name
parcours.timer = timer
parcours.exercices = exos
parcours.save()
layer = get_channel_layer()
async_to_sync(layer.group_send)(room.id_code, {
'type': 'edit_parcours', 'parcours': ParcoursSerializer(parcours).data})
layer = get_channel_layer()
return Response({"data": {'id_code': parcours.id_code}}, status=status.HTTP_200_OK)
def get(self, request, format=None):
id_code = request.GET.get('code')
user_code = request.GET.get('user_code')
parcours = Parcours.objects.filter(id_code=id_code)
if len(parcours) == 0:
return Response({'error': 'Pas de parcours lol'}, status=status.HTTP_404_NOT_FOUND)
parcours = parcours[0]
room = parcours.room
participants = list(
filter(lambda p: p['code'] == user_code, room.participants))
if(len(participants) == 0):
return Response({'error': 'Vous n\'êtes pas un participant'}, status=status.HTTP_401_UNAUTHORIZED)
exos = parcours.exercices
exos = list(map(lambda e: ExerciceSerializer(Exercice.objects.filter(
id_code=e['id_code'])[0]).data, exos))
challenger_data = parcours.challenger
if user_code == parcours.room.owner['code']:
return Response({"data": {**ParcoursSerializer(parcours).data, "challenger": list(map(lambda r: {**r, 'exos': list(map(lambda e: {'endAt': e['endAt'], 'note': e['note'], "timer": e['timer'], "code": e['code']}, r['exos']))}, parcours.challenger)), "exercices": exos}}, status=status.HTTP_200_OK)
else:
challenger_filtered = list(
filter(lambda c: c['code'] == user_code, challenger_data))
if parcours.room.public_result == False:
return Response({"data": {**ParcoursSerializer(parcours).data, "challenger": list(map(lambda r: {**r, 'exos': list(map(lambda e: {'endAt': e['endAt'], 'note': e['note'], "code": e['code'], "timer": e['timer']}, r['exos']))}, challenger_filtered)), "exercices": exos}}, status=status.HTTP_200_OK)
else:
return Response({"data": {**ParcoursSerializer(parcours).data, "challenger": list(map(lambda r: {**r, "code": "", 'exos': list(map(lambda e: {'endAt': e['endAt'], "code": e['code'], 'note': e['note'], "timer": e['timer']}, r['exos']))}, parcours.challenger)), "exercices": exos}}, status=status.HTTP_200_OK)