ajout des room, plus qu'à test

This commit is contained in:
Kilton937342 2022-06-24 13:42:16 +02:00
parent 035af2a3b7
commit 0e147e1a98
264 changed files with 5892 additions and 10098 deletions

View File

@ -33,7 +33,6 @@ def Generateur(path, quantity, key, forcedCorrection = False):
'web': False, 'correction': False} # les valeurs par défaut
# Si l'utilisateur n'a pas entré une valeur, elle est définie à False
result_object = {**default_object, **main_result}
print(result_object)
object_key = getObjectKey(result_object, key)
correction_key = getCorrectionKey(result_object, key)

View File

@ -79,7 +79,7 @@ MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
#SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
# CORS
CORS_ALLOWED_ORIGINS = ['http://localhost:8000', 'http://141.136.42.178:8001', 'http://141.136.42.178:8002', 'http://141.136.42.178:80', 'http://lilandco42.com',
@ -160,6 +160,7 @@ AUTH_PASSWORD_VALIDATORS = [
]
# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/
@ -212,6 +213,9 @@ ACCOUNT_AUTHENTICATION_METHOD = 'username'
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_UNIQUE_USERNAME = True
OLD_PASSWORD_FIELD_ENABLED = False
LOGOUT_ON_PASSWORD_CHANGE = False
REST_FRAMEWORK = {
'DATETIME_FORMAT': "%m/%d/%Y %I:%M%P", 'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentication.TokenAuthentication',

Binary file not shown.

View File

@ -7,7 +7,6 @@ class ExosFilter(django_filters.FilterSet):
model = Exercice
fields = ['name']
@property
def qs(self):

View File

@ -0,0 +1,20 @@
# Generated by Django 4.0 on 2022-06-24 08:44
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('exercices', '0015_exercice_original'),
]
operations = [
migrations.AddField(
model_name='exercice',
name='last_update',
field=models.DateField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.0 on 2022-06-24 08:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('exercices', '0016_exercice_last_update'),
]
operations = [
migrations.AlterField(
model_name='exercice',
name='last_update',
field=models.DateTimeField(auto_now_add=True),
),
]

View File

@ -3,7 +3,7 @@ from django.db import models
import random
import string
from django.db.models.fields import CharField, IntegerField, TextField, BooleanField
from django.db.models.fields import CharField, IntegerField, TextField, BooleanField, DateTimeField
from django.db.models.fields.json import JSONField
from users.models import CustomUser
# Create your models here.
@ -64,6 +64,8 @@ class Exercice(models.Model):
isCsv = BooleanField(default=True)
isWeb = BooleanField(default=True)
last_update = DateTimeField(auto_now_add=True)
original = BooleanField(default=True)
origin = models.ForeignKey('self', null=True, on_delete = models.SET_NULL)

View File

@ -11,7 +11,8 @@ class CustomPagination(pagination.PageNumberPagination):
return Response({
'links': {
'next': self.get_next_link(),
'previous': self.get_previous_link()
'previous': self.get_previous_link(),
},
'count': self.page.paginator.count,
'page_size': self.page.paginator.per_page,

View File

@ -3,14 +3,8 @@ from fontTools.ttLib import TTFont
from fontTools.ttLib.tables._c_m_a_p import CmapSubtable
def pdf_settings(path, police, number_in_serie, number_exo, start_index, consigne):
size = {
'10': 94,
'12': 78,
'14': 67,
'16': 59,
'18': 52
}
def pdf_settings(path, number_in_serie, consigne):
font = TTFont(
'/usr/share/fonts/truetype/liberation/LiberationSerif-Regular.ttf')
@ -28,6 +22,7 @@ def pdf_settings(path, police, number_in_serie, number_exo, start_index, consign
total += s['.notdef'].width
total = total*float(pointSize)/units_per_em
return total
exemple_exo = sorted(Generateur(path, 5, 'pdf'),
key=len, reverse=True)

View File

@ -15,18 +15,28 @@ class ExerciceSerializer(serializers.ModelSerializer):
tags = serializers.SerializerMethodField()
author = serializers.SerializerMethodField()
origin = serializers.SerializerMethodField()
isUser = serializers.SerializerMethodField()
class Meta:
model = Exercice
fields = ('name', 'id_code', 'consigne', 'author',
'exemple', 'tags', 'isPdf', 'isCsv', 'isWeb', "private", 'tags', 'origin')
'exemple', 'tags', 'isPdf', 'isCsv', 'isWeb', "private", 'tags', 'origin', 'isUser', 'last_update')
def get_author(self, obj):
return UserSerializer(obj.author).data
''' def get_exo_model(self,obj):
pass '''
def get_isUser(self, obj):
try:
user = CustomUser.objects.filter(
id_code=self.context['user_id'])[0]
return obj.author == user
except:
return False
def get_tags(self, obj):
try:
user = CustomUser.objects.filter(

View File

@ -1,5 +1,5 @@
from django.urls import path
from .views import PDF, CSV_Generator, Editor, ExerciceAPI, TagsAPI, Test, ExoModelApi, fav, getExoModelFile, getPublicList, getUserExosList
from .views import PDF, CSV_Generator, Editor, ExerciceAPI, TagsAPI, Test, ExoModelApi, fav, getExoModelFile, getPublicList, getUserExosList, pdfGen
urlpatterns = [
@ -8,7 +8,7 @@ urlpatterns = [
path('editor/', Editor.as_view()),
path('test/', Test.as_view()),
path('csv/<str:code>', CSV_Generator.as_view()),
path('pdf/', PDF.as_view()),
path('pdf/', pdfGen),
path('fav/', fav),
path('model/', getExoModelFile),
path('exercices/public', getPublicList),

View File

@ -44,10 +44,9 @@ from rest_framework import permissions
# Create your views here.
class ExerciceAPI(APIView):
pagination_class = CustomPagination
def get(self, request, format=None):
steps = Exercice.objects.filter(private=False)
userExos = []
@ -55,8 +54,8 @@ class ExerciceAPI(APIView):
steps = [s for s in steps if s.author.id != request.user.id]
userExos = request.user.exercice_set.all()
code = request.GET.get('code')
code = request.GET.get('id')
if code == 'pdf':
stepsListSorted = [s for s in steps if s.isPdf == True]
userExosListSorted = [s for s in userExos if s.isPdf == True]
@ -71,16 +70,17 @@ class ExerciceAPI(APIView):
userExosListSorted = userExos
if code != 'all' and code != 'pdf' and code != "web":
exo = Exercice.objects.filter(id_code=code)[0]
exo = Exercice.objects.get(id_code=code)
isUser = False
if request.user == exo.author:
isUser = True
return Response({"data": {**ExerciceSerializer(exo).data, "isUser": isUser, "original": exo.origin.id_code if exo.origin != None else None, "author": UserSerializer(exo.author).data if exo.author != None else None, 'exo_model': { 'filename': exo.exo_model.name.split('/')[-1], "data": open(exo.exo_model.name, 'r').read()}, "tags": [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in [tt for tt in exo.tags.all() if tt.user == request.user]]}}, status=status.HTTP_200_OK)
return Response({"data": {**ExerciceSerializer(exo).data, "isUser": isUser, "original": exo.origin.id_code if exo.origin != None else None, "author": UserSerializer(exo.author).data if exo.author != None else None, 'exo_model': {'filename': exo.exo_model.name.split('/')[-1], "data": open(exo.exo_model.name, 'r').read()}, "tags": [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in [tt for tt in exo.tags.all() if tt.user == request.user]]}}, status=status.HTTP_200_OK)
else:
return Response({"data": {
"userExos": [{**ExerciceSerializer(ex).data,'isUser': True ,"original": ex.origin.id_code if ex.origin != None else None, "author": UserSerializer(ex.author).data if ex.author != None else None, "exo_model": {"filename": ex.exo_model.name.split('/')[-1], "data": open(
ex.exo_model.name, 'r').read()}, "tags": [{**TagSerializer(t).data, 'value': t.id_code, 'label':t.name} for t in ex.tags.all()]} for ex in userExosListSorted],
"publicList": [{**ExerciceSerializer(ex).data,'isUser': False, 'isRegistered': len(request.user.registeredExos.filter(id_code=ex.id_code)) != 0 if request.user.is_authenticated else None, "author": UserSerializer(ex.author).data if ex.author != None else None, "exo_model": {"filename": ex.exo_model.name.split('/')[-1], "data": open(
"userExos": [{**ExerciceSerializer(ex).data, 'isUser': True, "original": ex.origin.id_code if ex.origin != None else None, "author": UserSerializer(ex.author).data if ex.author != None else None, "exo_model": {"filename": ex.exo_model.name.split('/')[-1], "data": open(
ex.exo_model.name, 'r').read()}, "tags": [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in ex.tags.all()]} for ex in userExosListSorted],
"publicList": [{**ExerciceSerializer(ex).data, 'isUser': False, 'isRegistered': len(request.user.registeredExos.filter(id_code=ex.id_code)) != 0 if request.user.is_authenticated else None, "author": UserSerializer(ex.author).data if ex.author != None else None, "exo_model": {"filename": ex.exo_model.name.split('/')[-1], "data": open(
ex.exo_model.name, 'r').read()}, "original": ex.origin.id_code if ex.origin != None else None,
"tags": [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in [tt for tt in ex.tags.all() if tt.user == request.user]]} for ex in stepsListSorted],
}}, status=status.HTTP_200_OK)
@ -97,7 +97,7 @@ class ExerciceAPI(APIView):
new_exo = Exercice(consigne=consigne,
exo_model=create_serializer.validated_data['exo_model']['file'], name=name, author=author, private=create_serializer.validated_data['private'])
# Generateur(exo_model, 5)
new_exo.isPdf = create_serializer.validated_data['exo_model']['isPdf']
new_exo.isCsv = create_serializer.validated_data['exo_model']['isCsv']
new_exo.isWeb = create_serializer.validated_data['exo_model']['isWeb']
@ -106,7 +106,7 @@ class ExerciceAPI(APIView):
# f'{"Csv" if new_exo.isCsv == True else ""}{"Web" if new_exo.isWeb == True else ""}',
'type': 'Csv' if new_exo.isCsv == True else 'Web' if new_exo.isWeb == True else None,
'data': Generateur(new_exo.exo_model.name, 5, 'csv' if new_exo.isCsv == True else 'web' if new_exo.isWeb == True else None, True) if new_exo.isCsv == True or new_exo.isWeb == True else None
}
}
new_exo.save()
# sleep(2)
@ -120,6 +120,7 @@ class ExerciceAPI(APIView):
name = request.data.get('name')
consigne = request.data.get('consigne')
id_code = request.data.get('id_code')
private = request.data.get('private')
exo = Exercice.objects.filter(id_code=id_code)
if len(exo) == 0:
@ -131,14 +132,15 @@ class ExerciceAPI(APIView):
status=status.HTTP_401_UNAUTHORIZED)
serializer = ExerciceCreateSerializer(
data={'exo_model': file, "consigne": consigne, "name": name})
data={'exo_model': file, "consigne": consigne, "name": name, "private": private})
errors = []
if serializer.is_valid():
exo.name = name
exo.consigne = consigne
exo.exo_model = serializer.validated_data['exo_model']['file']
exo.private = serializer.validated_data['private']
exo.isPdf = serializer.validated_data['exo_model']['isPdf']
exo.isCsv = serializer.validated_data['exo_model']['isCsv']
exo.isWeb = serializer.validated_data['exo_model']['isWeb']
@ -149,29 +151,28 @@ class ExerciceAPI(APIView):
'data': Generateur(exo.exo_model.name, 5, 'csv' if exo.isCsv == True else 'web' if exo.isWeb == True else None, True) if exo.isCsv == True or exo.isWeb == True else None
}
exo.save()
return Response({"status": "200", "errors": {}, "data": ExerciceSerializer(exo).data}, status=status.HTTP_200_OK)
return Response({"status": "400", "errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
@method_decorator(login_required)
def delete(self, request, format=None):
id_code = request.data.get('id_code')
exo = Exercice.objects.filter(id_code=id_code)
if len(exo) == 0:
return Response({'status': "404", "data": {}},
status=status.HTTP_404_NOT_FOUND)
status=status.HTTP_404_NOT_FOUND)
exo = exo[0]
if request.user != exo.author:
return Response({'status': "401", "data": {}},
status=status.HTTP_401_UNAUTHORIZED)
status=status.HTTP_401_UNAUTHORIZED)
exo.delete()
return Response({'status': "200", "data": id_code}, status=status.HTTP_200_OK)
@api_view(['GET'])
def getPublicList(request):
''' paginator = PageNumberPagination()
@ -179,76 +180,73 @@ def getPublicList(request):
person_objects = Exercice.objects.all()
result_page = paginator.paginate_queryset(person_objects, request) '''
#exos = Exercice.objects.all()
#return Response({'data': ExerciceSerializer(exos[8], context={'user_id': request.user.id_code if not request.user.is_anonymous else ''}).data}, status=status.HTTP_200_OK)
# return Response({'data': ExerciceSerializer(exos[8], context={'user_id': request.user.id_code if not request.user.is_anonymous else ''}).data}, status=status.HTTP_200_OK)
paginator = CustomPagination()
paginator.page_size = 22
exos = Exercice.objects.filter(private=False).filter(original=True)
if not request.user.is_anonymous:
# [ex for ex in exos if ex.author.id != request.user.id]
exos = exos.filter(~Q(author__id=request.user.id))
code = request.query_params.get('code')
if code == 'pdf':
exos = exos.filter(isPdf = True)#[s for s in exos if s.isPdf == True]
exos = exos.filter(isPdf=True) # [s for s in exos if s.isPdf == True]
elif code == 'web':
exos = exos.filter(isWeb = True)#[s for s in exos if s.isWeb == True]
exos = exos.filter(isWeb=True) # [s for s in exos if s.isWeb == True]
elif code == 'csv':
exos = exos.filter(isCsv = True)#[s for s in exos if s.isCsv == True]
exos = exos.filter(isCsv=True) # [s for s in exos if s.isCsv == True]
exos = ExosFilter(request=request.GET, queryset=exos).qs
result_page = paginator.paginate_queryset(exos, request)
result_page = paginator.paginate_queryset(
exos.order_by('-last_update'), request)
serializer = ExerciceSerializer(result_page, many=True, context={
'user_id': request.user.id_code if not request.user.is_anonymous else ''})
return paginator.get_paginated_response(serializer.data)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def getUserExosList(request):
paginator = CustomPagination()
paginator.page_size = 22
exos = request.user.exercice_set.all()# Exercice.objects.filter(private=False).filter(original=True)
# Exercice.objects.filter(private=False).filter(original=True)
exos = request.user.exercice_set.all()
code = request.query_params.get('code')
if code == 'pdf':
exos = exos.filter(isPdf = True)#[s for s in exos if s.isPdf == True]
exos = exos.filter(isPdf=True) # [s for s in exos if s.isPdf == True]
elif code == 'web':
exos = exos.filter(isWeb = True)#[s for s in exos if s.isWeb == True]
exos = exos.filter(isWeb=True) # [s for s in exos if s.isWeb == True]
elif code == 'csv':
exos = exos.filter(isCsv = True)#[s for s in exos if s.isCsv == True]
exos = exos.filter(isCsv=True) # [s for s in exos if s.isCsv == True]
exos = ExosFilter(request=request.GET, queryset=exos).qs
result_page = paginator.paginate_queryset(exos, request)
result_page = paginator.paginate_queryset(
exos.order_by('-last_update'), request)
serializer = ExerciceSerializer(result_page, many=True, context={
'user_id': request.user.id_code if not request.user.is_anonymous else ''})
return paginator.get_paginated_response(serializer.data)
@api_view(['GET'])
def getExoModelFile(request):
id_code = request.query_params['id_code']
exo = Exercice.objects.filter(id_code=id_code)
if len(exo) == 0:
return Response({'errors': 'Not found'}, status=status.HTTP_404_NOT_FOUND)
exo = exo[0]
exo = exo[0]
model = exo.exo_model
print(model.name)
with open(model.name, 'r') as f:
response = HttpResponse(f.read(), content_type='text/x-python')
response['Content-Disposition'] = f'attachment;filename={model.name.split("/")[-1]}'
return response
@api_view(['POST'])
@ -271,7 +269,6 @@ def fav(request):
exo.exo_model.save(f.name.split('/')[-1], ContentFile(f.read()))
exo._state.adding = True
exo.save()
return Response({'data': {'isRegistered': False}}, status=status.HTTP_200_OK)
@ -291,15 +288,13 @@ class TagsAPI(APIView):
return Response({'status': "404", "data": {}},
status=status.HTTP_404_NOT_FOUND)
exo = exo[0]
''' if request.user != exo.author:
return Response({'status': "401", "data": {}},
status=status.HTTP_401_UNAUTHORIZED) '''
tagsList = []
for o in options:
# print(o)
if o['value'].startswith('new_opt'):
newTag = Tag(name=o['label'], color=o['color'], user = request.user)
newTag = Tag(name=o['label'],
color=o['color'], user=request.user)
newTag.save()
exo.tags.add(newTag)
exo.save()
@ -310,7 +305,7 @@ class TagsAPI(APIView):
tag = request.user.tag_set.filter(id_code=tagId)
if len(tag) == 0:
return Response({'errors': ''}, status=status.HTTP_400_BAD_REQUEST)
tag= tag[0]
tag = tag[0]
exo.tags.add(tag)
exo.save()
tagsList.append(
@ -333,12 +328,11 @@ class TagsAPI(APIView):
if request.user != exo.author:
if tag.user != request.user:
return Response({'status': "401", "data": {}},
status=status.HTTP_401_UNAUTHORIZED)
status=status.HTTP_401_UNAUTHORIZED)
exo.tags.remove(tag)
exo.save()
return Response({'id_code': exo.id_code,'name': tag.name, 'tagId': tag.id_code,'tags': [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in exo.tags.all() if t.user == request.user]}, status=status.HTTP_200_OK)
return Response({'id_code': exo.id_code, 'name': tag.name, 'tagId': tag.id_code, 'tags': [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in exo.tags.all() if t.user == request.user]}, status=status.HTTP_200_OK)
class Editor(APIView):
@ -380,9 +374,92 @@ class CSV_Generator(APIView):
return response
@api_view(['POST'])
def pdfGen(request):
exos = [pdf_settings(Exercice.objects.get(id_code=ex['id_code']).exo_model.name, int(ex['numberInExo']), Exercice.objects.get(id_code=ex['id_code']).consigne)
for ex in request.data.get('exos')]
for e in range(len(exos)):
for exo in range(len(exos[e]['exos'])):
# print(exos[e]['exos'][exo])
exos[e]['exos'][exo]['calcul'] = sympy.latex(
exos[e]['exos'][exo]['calcul'])
exos[e]['exos'][exo]['calcul'] = exos[e]['exos'][exo]['calcul'].replace(
'', '\\ensuremath{\\simeq}')
exos[e]['exos'][exo]['calcul'] = exos[e]['exos'][exo]['calcul'].replace(
'', '\\ensurmath{\approx}')
exos[e]['exos'][exo]['calcul'] = exos[e]['exos'][exo]['calcul'].replace(
'', '\\ensuremath{\neq}')
exos[e]['exos'][exo]['correction'] = sympy.latex(
exos[e]['exos'][exo]['correction'])
exos[e]['exos'][exo]['correction'] = exos[e]['exos'][exo]['correction'].replace(
'', '\\ensuremath{\\simeq}')
exos[e]['exos'][exo]['correction'] = exos[e]['exos'][exo]['correction'].replace(
'', '\\ensurmath{\approx}')
exos[e]['exos'][exo]['correction'] = exos[e]['exos'][exo]['correction'].replace(
'', '\\ensuremath{\neq}')
exp_list = re.findall(
r'\[([A-Za-z0-9_]+)\]', exos[e]['exos'][exo]['correction'])
red = '{red}'
for exp in exp_list:
exos[e]['exos'][exo]['correction'] = exos[e]['exos'][exo]['correction'].replace(
f'[{exp}]', f'\\textcolor{red}{{{exp}}}')
context = {'exos': exos, 'title': request.data.get(
'title'), 'police': request.data.get('police')}
template = get_template('test.tex')
latex = template.render(context)
with tempfile.TemporaryDirectory() as tempdir:
direct = tempdir
with open(os.path.join(direct, 'tmp.tex'), 'x', encoding='utf-8') as f:
f.write(latex)
command = f'xelatex -interaction=batchmode tmp.tex'
try:
subprocess.run(command, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=True,
cwd=direct)
except TexError:
raise TexError(log=log, source=latex,
template_name='test.tex')
try:
subprocess.run(command, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=True,
cwd=direct)
except TexError:
raise TexError(log=log, source=latex,
template_name='test.tex')
with open(os.path.join(direct, 'tmp.pdf'), 'rb') as out:
pdf = out.read()
buffer = io.BytesIO(out.read())
fich_name = request.data.get('file')
if fich_name.count('.') >= 1:
ext = fich_name.split('.')[-1]
# print(ext)
if ext == 'pdf':
fich_name = fich_name
elif ext != 'pdf':
# print('nipe')
fich_name = fich_name.replace(f'.{ext}', '.pdf')
else:
fich_name = fich_name + '.pdf'
return Response({'pdf': base64.b64encode(pdf), 'filename': fich_name}, status=status.HTTP_200_OK)
class PDF(APIView):
def post(self, request, format=None):
print('exos', request.data.get('exos'))
exos = list(map(lambda ex: pdf_settings(
Exercice.objects.filter(id_code=ex['id_code'])[0].exo_model.name, 14, int(ex['numberInExo']), int(ex['numberOfExo']), 1, ex['consigne']), request.data.get('exos')))

Binary file not shown.

View File

@ -3,6 +3,8 @@ import json
from uuid import uuid4
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from users.serializers import UserSerializer
from .models import Room
@ -28,8 +30,8 @@ class RoomConsumer(AsyncWebsocketConsumer):
async def receive(self, text_data):
text_data_json = json.loads(text_data)
type = text_data_json['data']['type']
print(text_data_json)
print("EVENT", type)
print('USER', self.scope['user'])
if type == "login":
print('LOF', self.scope['user'])
participants = await self.get_participants()
@ -37,10 +39,16 @@ class RoomConsumer(AsyncWebsocketConsumer):
nick = text_data_json['data']['nick']
else:
nick = self.scope['user'].username
if len(nick) == 0:
await self.send(json.dumps({'type': 'loginResponse', "error": "USER_INPUT", "description": "Pseudo non valide"}))
return
if nick in list(map(lambda p: p['nick'], participants)) and self.scope['user'].is_anonymous:
await self.send(json.dumps({'type': 'loginResponse', "error": "USER_INPUT", "description": "Pseudo déjà utilisé"}))
return
elif len(nick) > 30:
await self.send(json.dumps({'type': 'loginResponse', "error": "USER_INPUT", "description": "Pseudo trop long"}))
return
else:
if self.room.private == True:
waiter = await self.add_waiter_db(nick, self.scope['user'].is_anonymous == False, None if self.scope['user'].is_anonymous else self.scope['user'].id_code)
@ -60,10 +68,10 @@ class RoomConsumer(AsyncWebsocketConsumer):
new_participant = await self.add_participant(nick, self.clientId)
self.user = new_participant
else:
new_participant = await self.add_user(nick, self.scope['user'])
new_participant = await self.add_user(self.scope['user'].id_code)
self.user = new_participant
await self.send(json.dumps({'type': "roomJoined", "clientId": new_participant.clientId, 'id_code': self.room_id, 'identity': new_participant}))
await self.send(json.dumps({'type': "roomJoined", "clientId": new_participant['clientId'], 'id_code': self.room_id, 'identity': new_participant}))
await self.channel_layer.group_send(self.room_id, {'type': 'join.event', "nick": nick, "owner": False, "online": True, "code": ""})
await self.channel_layer.group_send(f'owner__{self.room_id}', {'type': 'join.event', "nick": nick, "owner": False, "online": True, "code": new_participant['code']})
@ -143,34 +151,35 @@ class RoomConsumer(AsyncWebsocketConsumer):
await self.channel_layer.group_send(self.room_id, {"type": "reconnect.event", 'nick': self.user['nick']})
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "reconnect.event", 'nick': self.user['nick']})
else:
code = text_data_json['data']['code']
participants = await self.get_participants()
code = text_data_json['data']['code']
participants = await self.get_participants()
if code in list(map(lambda p: p['code'], participants)):
participant = list(
filter(lambda p: p['code'] == code, participants))[0]
self.clientId = participant['clientId']
if code in list(map(lambda p: p['code'], participants)):
participant = list(
filter(lambda p: p['code'] == code, participants))[0]
self.clientId = participant['clientId']
if participant['clientId'] == self.room.owner['clientId'] and participant['code'] == self.room.owner['code']:
await self.channel_layer.group_add(f'owner__{self.room_id}', self.channel_name)
else:
await self.channel_layer.group_add(self.room_id, self.channel_name)
participant['online'] = True
self.user = participant
await self.connect_participant()
await self.send(json.dumps({'type': "reloged", "clientId": self.clientId, 'id_code': self.room_id, 'identity': participant}))
await self.channel_layer.group_send(self.room_id, {"type": "reconnect.event", 'nick': self.user['nick']})
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "reconnect.event", 'nick': self.user['nick']})
if participant['clientId'] == self.room.owner['clientId'] and participant['code'] == self.room.owner['code']:
await self.channel_layer.group_add(f'owner__{self.room_id}', self.channel_name)
else:
await self.channel_layer.group_add(self.room_id, self.channel_name)
participant['online'] = True
self.user = participant
await self.connect_participant()
await self.send(json.dumps({'type': "reloged", "clientId": self.clientId, 'id_code': self.room_id, 'identity': participant}))
await self.channel_layer.group_send(self.room_id, {"type": "reconnect.event", 'nick': self.user['nick']})
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "reconnect.event", 'nick': self.user['nick']})
else:
await self.send(json.dumps({"type": "reloginError"}))
await self.send(json.dumps({"type": "reloginError"}))
elif type == "reconnect":
client = text_data_json['data']['clientId']
print(self.scope['user'].is_anonymous)
print("reconeect", self.scope['user'].is_anonymous)
if not self.scope['user'].is_anonymous:
userInRoom = await self.userInRoom()
if not userInRoom:
@ -178,6 +187,7 @@ class RoomConsumer(AsyncWebsocketConsumer):
else:
isOwner = self.scope['user'].clientId == self.room.owner[
'clientId'] and self.scope['user'].id_code == self.room.owner['code']
if isOwner:
await self.channel_layer.group_add(f'owner__{self.room_id}', self.channel_name)
else:
@ -189,6 +199,7 @@ class RoomConsumer(AsyncWebsocketConsumer):
await self.connect_participant()
self.clientId = self.scope['user'].clientId
print('SENDING')
await self.send(json.dumps({'type': "reconnected", "clientId": self.scope['user'].clientId, 'id_code': self.room_id, 'identity': self.user}))
await self.channel_layer.group_send(self.room_id, {"type": "reconnect.event", 'nick': self.user['nick']})
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "reconnect.event", 'nick': self.user['nick']})
@ -228,6 +239,32 @@ class RoomConsumer(AsyncWebsocketConsumer):
await self.channel_layer.group_send(self.room_id, {'type': "ban_participant", "code": code, "nick": nick})
await self.channel_layer.group_send(f'owner__{self.room_id}', {'type': "ban_participant", "code": code, "nick": nick})
elif type == 'leave':
code = text_data_json['data']["code"]
nick = text_data_json['data']["nick"]
clientId = text_data_json['data']["clientId"]
status = 'anonymous' if len(code) == 6 else 'user'
print('EST')
if status == 'anonymous':
participants = await self.get_participants()
participant = [p for p in participants if p['code'] == code]
print('PARTICIPANR', participant)
if len(participant) == 0:
pass
else:
if clientId == participant[0]['clientId']:
await self.del_participant(code)
await self.channel_layer.group_send(self.room_id, {'type': "ban_participant", "code": code, "nick": nick})
await self.channel_layer.group_send(f'owner__{self.room_id}', {'type': "ban_participant", "code": code, "nick": nick})
else:
user = await self.get_user(code)
print('USER', user, code)
if self.scope['user'] == user:
await self.del_user(code)
await self.channel_layer.group_send(self.room_id, {'type': "ban_participant", "code": code, "nick": nick})
await self.channel_layer.group_send(f'owner__{self.room_id}', {'type': "ban_participant", "code": code, "nick": nick})
async def join_event(self, event):
await self.send(json.dumps({'type': 'joined', 'nick': event['nick'], "owner": event['owner'], "online": event['online'], "code": event["code"]}))
@ -253,6 +290,14 @@ class RoomConsumer(AsyncWebsocketConsumer):
@database_sync_to_async
def get_participants(self):
return Room.objects.filter(id_code=self.room_id)[0].anonymousMembers
@database_sync_to_async
def get_users(self):
return [UserSerializer(u).data for u in Room.objects.filter(id_code=self.room_id)[0].userMembers.all()]
@database_sync_to_async
def get_user(self, code):
return Room.objects.filter(id_code=self.room_id)[0].userMembers.get(id_code = code)
@database_sync_to_async
def get_room(self):
@ -301,6 +346,7 @@ class RoomConsumer(AsyncWebsocketConsumer):
id_code=self.room.id_code)) != 0
async def disconnect(self, close_code):
print('Disconnect')
if self.waiter == False and self.user != None:
await self.disconnect_participant()
await self.channel_layer.group_discard(self.room_id, self.channel_name)
@ -314,6 +360,9 @@ class RoomConsumer(AsyncWebsocketConsumer):
async def disconnect_event(self, event):
await self.send(json.dumps({'type': 'disconnect_participant', "nick": event['nick']}))
async def room_deleted(self, event):
await self.send(json.dumps({'type': 'room_deleted'}))
async def reconnect_event(self, event):
await self.send(json.dumps({'type': 'reconnect_participant', "nick": event['nick']}))

View File

View File

@ -0,0 +1,34 @@
from django.core.management.base import BaseCommand, CommandError
from room.models import Room
import string
import random
import faker
import uuid
class Command(BaseCommand):
help = 'Closes the specified poll for voting'
def add_arguments(self, parser):
parser.add_argument('roomId', nargs='+', type=str)
parser.add_argument('number', nargs='+', type=int)
def handle(self, *args, **options):
try:
room = Room.objects.get(id_code = options['roomId'][0])
except:
raise CommandError(f'Room "{options["roomId"][0]}" does not exist')
newMembers = []
for i in range(options['number'][0]):
while True:
code = ''.join(random.choices(string.ascii_uppercase, k=6))
if code not in [p['code'] for p in room.anonymousMembers]:
break
while True:
uid = uuid.uuid4()
if uid not in [p['clientId'] for p in room.anonymousMembers]:
break
fake = faker.Faker()
newMembers.append({'nick': fake.name(), 'clientId': str(uid), 'code': code, 'owner': False, 'online': True})
room.anonymousMembers = [*newMembers, *room.anonymousMembers]
room.save()
self.stdout.write(self.style.SUCCESS(
f'Successfully added {options["number"][0]} participants to room {options["roomId"][0]}'))

View File

@ -0,0 +1,59 @@
from datetime import datetime
import functools
from django.core.management.base import BaseCommand, CommandError
import faker
import pytz
from room.models import Room, Parcours
import string
import random
import uuid
class Command(BaseCommand):
help = 'Closes the specified poll for voting'
def add_arguments(self, parser):
parser.add_argument('parcoursId', nargs='+', type=str)
parser.add_argument('number', nargs='+', type=int)
def handle(self, *args, **options):
try:
parcours = Parcours.objects.get(id_code=options['parcoursId'][0])
except:
raise CommandError(f'Parcours "{options["parcoursId"][0]}" does not exist')
participants = [*parcours.room.anonymousMembers, *
[{'code': u.id_code, 'nick': u.username, 'clientId': u.clientId} for u in parcours.room.userMembers.all()]]
new_challengers = parcours.challenger
if len(parcours.exercices) != 1:
maxNote = functools.reduce(lambda a, b:{'number': a['number'] + b['number']}, parcours.exercices )['number']
else:
maxNote = parcours.exercices[0]['number']
for i in range(options['number'][0]):
challenger = random.choice(participants)
if challenger['code'] in [n['code'] for n in new_challengers]:
index = [i for i, n in enumerate(
new_challengers) if n['code'] == challenger['code']][0]
while True:
code = ''.join(random.choices(string.ascii_uppercase, k=6))
if code not in [p['code'] for p in new_challengers[index]['exos']]:
break
now = datetime.now()
date = str(now.astimezone(pytz.timezone('Europe/Berlin')))
fake = faker.Faker()
date = str(fake.date_time_this_month())
new_challengers[index] = {
**new_challengers[index], 'exos': [*new_challengers[index]['exos'], {'result': [], 'endAt': date, 'timer': random.randint(1, parcours.timer * 60), 'note': {'value': random.randint(0, maxNote), 'total': maxNote, 'isTrust': True}, 'code': code}]}
else:
code = ''.join(random.choices(string.ascii_uppercase, k=6))
now = datetime.now()
date = str(now.astimezone(pytz.timezone('Europe/Berlin')))
fake = faker.Faker()
date = str(fake.date_time_this_month())
new_challengers.append({**challenger, 'validate': False, 'exos': [{'result': [], 'endAt': date, 'timer': random.randint(
1, parcours.timer * 60), 'note': {'value': random.randint(0, maxNote), 'total': maxNote, 'isTrust': True, }, 'code': code}]})
parcours.challenger = new_challengers
parcours.save()
self.stdout.write(self.style.SUCCESS(
f'Successfully added {options["number"][0]} challenges to parcours {options["parcoursId"][0]}'))

View File

@ -0,0 +1,23 @@
# Generated by Django 4.0 on 2022-06-14 20:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('exercices', '0015_exercice_original'),
('room', '0009_room_online'),
]
operations = [
migrations.RemoveField(
model_name='parcours',
name='exercices',
),
migrations.AddField(
model_name='parcours',
name='exercices',
field=models.ManyToManyField(to='exercices.Exercice'),
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 4.0 on 2022-06-14 20:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('room', '0010_remove_parcours_exercices_parcours_exercices'),
]
operations = [
migrations.RemoveField(
model_name='parcours',
name='exercices',
),
migrations.AddField(
model_name='parcours',
name='exercices',
field=models.JSONField(default=list),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.0 on 2022-06-19 14:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('room', '0011_remove_parcours_exercices_parcours_exercices'),
]
operations = [
migrations.AlterField(
model_name='room',
name='name',
field=models.CharField(max_length=30),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.0 on 2022-06-20 09:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('room', '0012_alter_room_name'),
]
operations = [
migrations.AlterField(
model_name='parcours',
name='name',
field=models.CharField(max_length=30),
),
]

View File

@ -1,5 +1,6 @@
from datetime import datetime
from email.policy import default
import functools
from pyexpat import model
import random
import string
@ -54,7 +55,8 @@ class RoomManager(models.Manager):
if code not in list(map(lambda p: p['code'], participants)):
break
new_participant = {'nick': new_name, 'code': code,
'clientId': clientId, "owner": owner, "online": online}
'clientId': clientId, "owner": owner}
room.online = [*room.online, code]
room.anonymousMembers = [*participants, new_participant]
room.save()
return new_participant
@ -107,12 +109,18 @@ class RoomManager(models.Manager):
def add_waiter(self, room, new_name, isUser, code = None):
room = self.get_queryset().filter(id_code=room)[0]
participants = room.anonymousMembers
if new_name in list(map(lambda p: p['nick'], participants)) and isUser:
return None
waiters = room.waiters
print('NEWNAME', new_name, new_name in list(
map(lambda p: p['nick'], waiters)), list(map(lambda p: p['nick'], waiters)), waiters)
if new_name in list(map(lambda p: p['nick'], waiters)):
return None
print('PASSED')
if code == None:
while True:
code = ''.join(random.choices(string.ascii_uppercase, k=6))
@ -159,7 +167,7 @@ class RoomManager(models.Manager):
class Room(models.Model):
name = models.CharField(max_length=50)
name = models.CharField(max_length=30)
id_code = models.CharField(
max_length=50, default=generate_unique_code_room)
anonymousMembers = models.JSONField(default=list, null=True)
@ -181,6 +189,7 @@ class ParcoursManager(models.Manager):
challengers = list(
filter(lambda c: c['code'] == user_code, parcours.challenger))
if not isUser:
challenger = list(
filter(lambda p: p['code'] == user_code, parcours.room.anonymousMembers))[0]
@ -189,37 +198,48 @@ class ParcoursManager(models.Manager):
challenger = {'nick': user.username, "code": user.id_code, 'clientId': user.clientId}
validate = None
date = getNow()
now = datetime.now()
date = str(now.astimezone(pytz.timezone('Europe/Berlin')))
if len(challengers) == 0:
condition = parcours.success_condition
validate = date if result['note']['value'] * 20 / \
result['note']['total'] >= condition else False
validate = result['note']['value'] * 20 / \
result['note']['total'] >= condition
code = ''.join(random.choices(string.ascii_uppercase, k=6))
parcours.challenger = [*parcours.challenger,
{**challenger, 'exos': [{**result, 'endAt': date, 'code': code}], "validate": validate}]
else:
validate = False
if challengers[0]['validate'] != False:
validate = challenger[0]['validate']
else:
condition = parcours.success_condition
validate = date if result['note']['value'] * 20 / \
result['note']['total'] >= condition else False
oldChallenger = challengers[0]['exos']
while True:
code = ''.join(random.choices(string.ascii_uppercase, k=6))
if len(list(filter(lambda c: c['code'] == code, oldChallenger))) == 0:
break
parcours.challenger = [*list(filter(lambda c: c['code'] != challenger['code'], parcours.challenger)),
{**challenger, 'exos': [*challengers[0]['exos'], {**result, 'endAt': date, "code": code}], "validate": validate}]
condition = parcours.success_condition
moyenne = self.getAverage(parcours.id_code, challenger['code'])
validate = moyenne['value'] * 20 / \
moyenne['total'] >= condition
oldChallenger = challengers[0]['exos']
while True:
code = ''.join(random.choices(string.ascii_uppercase, k=6))
if len(list(filter(lambda c: c['code'] == code, oldChallenger))) == 0:
break
exos = challengers[0]['exos']
if len(exos) > 6:
exos = [{**e, 'result':[] if i < (len(exos) - 6) and e['note']['isTrust'] == True else e['result']} for i, e in enumerate(exos)]
parcours.challenger = [*list(filter(lambda c: c['code'] != challenger['code'], parcours.challenger)),
{**challenger, 'exos': [*exos, {**result, 'endAt': date, "code": code}], "validate": validate}]
parcours.save()
return {'validate': validate, 'code': code}
def getAverage(self, parcours_code, user_code):
parcours = self.get_queryset().filter(id_code=parcours_code)[0]
challengers = parcours.challenger
challengers = [c for c in challengers if c['code'] == user_code]
if len(challengers) == 0:
print('NOPE', user_code)
return None
c = challengers[0]
return {'value': round(functools.reduce(lambda a, b: a+b, [e['note']['value'] for e in c['exos']])/len(c['exos']), 2), 'total': c['exos'][0]['note']['total']}
class Parcours(models.Model):
name = models.CharField(max_length=50)
name = models.CharField(max_length=30)
id_code = models.CharField(
max_length=50, default=generate_unique_code_parcours)
challenger = models.JSONField(default=list)

View File

@ -1,18 +1,111 @@
import functools
from rest_framework import serializers
from users.models import CustomUser
from .models import Room, Parcours
class RoomSerializer(serializers.ModelSerializer):
exo_model = ''
exo_model = ''
class Meta:
model = Room
fields = ('id', 'name', 'id_code', 'anonymousMembers')
class Meta:
model = Room
fields = ('id', 'name', 'id_code', 'anonymousMembers', 'private', 'public_result')
class CreateRoomSerializer(serializers.ModelSerializer):
exo_model = ''
nick = serializers.SerializerMethodField()
class Meta:
model = Room
fields = ( 'name', 'anonymousMembers', 'private', "public_result", 'nick')
def validate_nick(self, value):
if value != '':
if len(value) > 30:
raise serializers.ValidationError('Trop long')
return value
raise serializers.ValidationError(code='blank')
def get_nick(self, obj):
return ''
class RoomUserSerializer(serializers.ModelSerializer):
status = serializers.SerializerMethodField()
class Meta:
model = Room
fields = ('id', 'name', 'id_code', 'status')
def get_status(self, obj):
try:
user = CustomUser.objects.get(
id_code=self.context['userId'])
return 'administrateur' if user.id_code == obj.owner['code'] else 'membre'
except:
return None
class ParcoursFullSerializer(serializers.ModelSerializer):
is_validate = serializers.SerializerMethodField()
challenger = serializers.SerializerMethodField()
class Meta:
model = Parcours
fields = ('id', 'name', 'id_code',
'timer', 'exercices', 'success_condition', 'is_validate', 'challenger') # + challenger ?
def get_is_validate(self, obj):
clientId = self.context.get('clientId', None)
if clientId != None:
challenger = [
p for p in obj.challenger if p['clientId'] == clientId]
if len(challenger) == 0:
return False
else:
return challenger[0]['validate']
return None
def get_challenger(self, obj):
user_code = self.context.get('user_code', None)
challengers = obj.challenger
if user_code != None:
challengers = [c for c in challengers if c['code'] == user_code]
if len(challengers) == 0:
return []
return [{**c, 'moyenne': Parcours.objects.getAverage(obj.id_code, c['code']), 'exos': [{'endAt': e['endAt'], 'note': e['note'], "code": e['code'], "timer": e['timer'], 'canCorrige': len(e['result']) != 0} for e in c['exos']]} for c in challengers]
class ParcoursSerializer(serializers.ModelSerializer):
exo_model = ''
is_validate = serializers.SerializerMethodField()
class Meta:
model = Parcours
fields = ('id', 'name', 'id_code',
'timer', 'exercices', 'success_condition') # + challenger ?
class Meta:
model = Parcours
fields = ('id', 'name', 'id_code',
'timer', 'exercices', 'success_condition', 'is_validate') # + challenger ?
def get_is_validate(self, obj):
clientId = self.context.get('clientId', None)
if clientId != None:
challenger = [
p for p in obj.challenger if p['clientId'] == clientId]
if len(challenger) == 0:
return False
else:
return challenger[0]['validate']
return None
class ParcoursCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Parcours
fields = ('name', 'room',
'timer', 'exercices', 'success_condition') # + challenger ?
def validate_exercices(self, value):
print('EXOS', value)
if len(value) == 0:
raise serializers.ValidationError('Aucun exercice séléctioné')
return value

View File

@ -1,3 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,10 +1,14 @@
from django.conf.urls import include
from django.urls import path
from .views import RoomAPI, ParcoursAPI, RoomExist, ChallengeAPI, getCorrectionInfo
from .views import RoomAPI, ParcoursAPI, RoomExist, ChallengeAPI, changeRoomName, getCorrectionInfo, getEditParcours, lockRoom, publicResultToggler
urlpatterns = [
path('room/', RoomAPI.as_view()),
path('parcours/', ParcoursAPI.as_view()),
path('room/<str:id_code>', RoomExist),
path('correct/', getCorrectionInfo),
path('challenge/', ChallengeAPI.as_view())
path('edit/', getEditParcours),
path('lock/', lockRoom),
path('public/', publicResultToggler),
path('change_name/', changeRoomName),
path('challenge/', ChallengeAPI.as_view()),
]

View File

@ -1,3 +1,4 @@
import functools
from sys import api_version
from rest_framework.decorators import api_view
from datetime import datetime
@ -12,7 +13,7 @@ from rest_framework.views import APIView
from rest_framework import status
from .models import Room, Parcours, TempCorrection
from .serializers import RoomSerializer, ParcoursSerializer
from .serializers import CreateRoomSerializer, ParcoursCreateSerializer, RoomSerializer, ParcoursFullSerializer, ParcoursSerializer
from django.contrib.sessions.models import Session
from api.Generateur import Generateur
from exercices.models import Exercice
@ -28,22 +29,36 @@ class RoomAPI(APIView):
def post(self, request, format=None):
name = request.data.get('name')
private = request.data.get('private')
results = request.data.get('results')
if request.user.is_authenticated:
room = Room(name=name, owner={
"name": request.user.username, 'code': request.user.id_code, 'clientId': request.user.clientId})
room.save()
clientId = request.user.clientId
code = request.user.id_code
room.userMembers.add(request.user)
serial = CreateRoomSerializer(data={'name': name, 'private': private, 'nick':request.user.username, 'public_results': results })
if serial.is_valid():
room = Room(name=name,private= private, public_result=results,owner={
"name": request.user.username, 'code': request.user.id_code, 'clientId': request.user.clientId})
room.save()
clientId = request.user.clientId
code = request.user.id_code
room.userMembers.add(request.user)
else:
return Response({'error': serial.errors}, status=status.HTTP_400_BAD_REQUEST)
else:
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}, anonymousMembers=[{'nick': nick, 'owner': True, 'code': code, "clientId": clientId}]
)
room.save()
serial = CreateRoomSerializer(
data={'name': name, 'private': private, 'nick': nick, 'public_results': results})
if serial.is_valid():
code = ''.join(
random.choices(string.ascii_uppercase, k=6))
clientId = str(uuid4())
room = Room(name=name, private=private, public_result=results, owner={'name': nick, 'code': code, "clientId": clientId}, anonymousMembers=[{'nick': nick, 'owner': True, 'code': code, "clientId": clientId}]
)
room.online=[code]
room.save()
else:
return Response({'error': serial.errors}, status=status.HTTP_400_BAD_REQUEST)
return Response({"data": {'id_code': room.id_code, "clientId": clientId, "code": code}}, status=status.HTTP_200_OK)
def get(self, request, format=None):
@ -59,7 +74,6 @@ class RoomAPI(APIView):
clientId = request.GET.get('clientId')
participants = room.anonymousMembers
users = room.userMembers.all()
print(room.userMembers.all())
userInRoom = False
if request.user.is_authenticated:
@ -73,13 +87,31 @@ class RoomAPI(APIView):
if clientId == room.owner['clientId']:
admin = True
online = room.online
# "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": [{'nick': p['nick'], 'owner': p['clientId'] == room.owner['clientId'], 'online': p['code'] in online, "code": p['code'] if admin == True else "", 'status': "anonymous"} for p in participants] + [{"status": "user", 'nick': u.username, 'owner': u.clientId == room.owner['clientId'], 'online': u.id_code in online, 'code': u.id_code if admin == True else ""} for u in users], 'parcours': [ParcoursSerializer(p).data for p in room.parcours_set.all()]}}}, status=status.HTTP_200_OK)
return Response({"data": {"room": {**RoomSerializer(room).data, "waiters": room.waiters if admin == True else [], "participants": [{'nick': p['nick'], 'owner': p['clientId'] == room.owner['clientId'], 'online': p['code'] in online, "code": p['code'] if admin == True else "", 'status': "anonymous"} for p in participants] + [{"status": "user", 'nick': u.username, 'owner': u.clientId == room.owner['clientId'], 'online': u.id_code in online, 'code': u.id_code if admin == True else ""} for u in users], 'parcours': [ParcoursSerializer(p, context={'clientId': clientId}).data for p in 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()
code = request.data.get('id_code')
clientId = request.data.get('clientId')
try:
room = Room.objects.filter(id_code=code)[0]
except:
return Response({'error': 'Not found'}, status=status.HTTP_404_NOT_FOUND)
if request.user.is_authenticated:
if request.user.id_code == room.owner['code'] and request.user.clientId == room.owner['clientId']:
room.delete()
else:
return Response({'error': 'Unauthorized'}, status=status.HTTP_401_UNAUTHORIZED)
else:
print('CLIENTID', clientId, room.owner)
if clientId == room.owner['clientId']:
room.delete()
else:
return Response({'error': 'Unauthorized'}, status=status.HTTP_401_UNAUTHORIZED)
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(room.id_code, {
'type': "room_deleted"})
return Response({"data": ''}, status=status.HTTP_200_OK)
def patch(self, request, format=None):
@ -125,11 +157,16 @@ class RoomAPI(APIView):
def RoomExist(request, id_code):
if Room.objects.filter(id_code=id_code).count() > 0:
userInRoom = False
clientId = request.query_params.get('clientId', None)
if request.user.is_authenticated:
room = Room.objects.filter(id_code=id_code)[0]
userInRoom = len(request.user.room_set.filter(
id_code=room.id_code)) != 0
else:
room = Room.objects.filter(id_code=id_code)[0]
userInRoom = len([p for p in room.anonymousMembers if p['clientId'] == clientId]) != 0
return Response({'data': {"id_code": id_code, 'is_auth': userInRoom}}, status=status.HTTP_200_OK)
else:
return Response({'error': 'Aucune salle trouvée', 'code': '4044'}, status=status.HTTP_404_NOT_FOUND)
@ -162,7 +199,97 @@ def getCorrectionInfo(request):
challenge = challenge[0]
return Response({'data': {**challenge, "parcours_id": parcours.id_code, 'user_code': user_code}}, status=status.HTTP_200_OK)
return Response({'data': {**challenge, "parcours_id": parcours.id_code, "success_condition": parcours.success_condition, 'user_code': user_code, 'parcours_name': parcours.name, 'challenger_name': challenger[0]['nick']}}, status=status.HTTP_200_OK)
@api_view(['GET'])
def getEditParcours(request):
parcours_id = request.query_params['id_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]
exos = parcours.exercices
exosList = []
for e in exos:
exo = Exercice.objects.filter(id_code=e['id_code'])
if len(exo) != 0:
exosList.append(
{**ExerciceSerializer(exo[0]).data, 'number': e['number']})
return Response({'data': {**ParcoursSerializer(parcours).data, 'exercices': exosList}}, status=status.HTTP_200_OK)
@api_view(['POST'])
def lockRoom(request):
print('DATA', request.data)
room_id = request.data['id_code']
if request.user.is_authenticated:
clientId = request.user.clientId
else:
clientId = request.data['clientId']
room = Room.objects.filter(id_code=room_id)
if len(room) == 0:
return Response({'error': 'Pas de parcours lol'}, status=status.HTTP_404_NOT_FOUND)
room = room[0]
if room.owner['clientId'] != clientId:
return Response({'error': 'Pas autorisé en fait'}, status = status.HTTP_401_UNAUTHORIZED)
room.private = room.private == False
room.save()
return Response({'data': {'private': room.private}}, status=status.HTTP_200_OK)
@api_view(['POST'])
def publicResultToggler(request):
print('DATA', request.data)
room_id = request.data['id_code']
if request.user.is_authenticated:
clientId = request.user.clientId
else:
clientId = request.data['clientId']
room = Room.objects.filter(id_code=room_id)
if len(room) == 0:
return Response({'error': 'Pas de parcours lol'}, status=status.HTTP_404_NOT_FOUND)
room = room[0]
if room.owner['clientId'] != clientId:
return Response({'error': 'Pas autorisé en fait'}, status = status.HTTP_401_UNAUTHORIZED)
room.public_result = room.public_result == False
room.save()
return Response({'data': {'private': room.public_result}}, status=status.HTTP_200_OK)
@api_view(['POST'])
def changeRoomName(request):
print('DATA', request.data)
room_id = request.data['id_code']
if request.user.is_authenticated:
clientId = request.user.clientId
else:
clientId = request.data['clientId']
room = Room.objects.filter(id_code=room_id)
if len(room) == 0:
return Response({'error': 'Pas de parcours lol'}, status=status.HTTP_404_NOT_FOUND)
room = room[0]
if room.owner['clientId'] != clientId:
return Response({'error': 'Pas autorisé en fait'}, status = status.HTTP_401_UNAUTHORIZED)
name = request.data['name']
if name == '':
return Response({'error': 'Not null pls'}, status = status.HTTP_400_BAD_REQUEST)
if len(name) > 30:
return Response({'error': 'TRop long frr'}, status = status.HTTP_400_BAD_REQUEST)
room.name = name
room.save()
return Response({'data': {'name':name}}, status=status.HTTP_200_OK)
class ChallengeAPI(APIView):
@ -193,6 +320,7 @@ class ChallengeAPI(APIView):
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:
@ -294,10 +422,12 @@ class ChallengeAPI(APIView):
adding_challenger = Parcours.objects.challenge(
parcours_id, user_code, {"result": corriged, "timer": exos['timer'], "note": note}, request.user.is_authenticated)
correctionDB.delete()
now = datetime.now()
now = str(now.astimezone(pytz.timezone('Europe/Berlin')))
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] if not request.user.is_authenticated else {'nick': request.user.username,'code': request.user.id_code,'clientId': request.user.clientId}, "validate": adding_challenger['validate'], 'exos': {'note': note,"code": adding_challenger['code'], 'endAt': getNow(), "timer": exos['timer']}})
'type': "challenge_parcours", 'id_code': parcours_id, 'moyenne': Parcours.objects.getAverage(parcours.id_code, participants[0]['code'] if not request.user.is_authenticated else request.user.id_code), "participant": participants[0] if not request.user.is_authenticated else {'nick': request.user.username, 'code': request.user.id_code, 'clientId': request.user.clientId}, "validate": adding_challenger['validate'], 'exos': {'note': note, "code": adding_challenger['code'], 'canCorrige': True, 'endAt': now, "timer": exos['timer']}})
return Response({"data": {"exos": corriged, "note": note}}, status=status.HTTP_200_OK)
def put(self, request, format=None):
@ -308,36 +438,46 @@ class ChallengeAPI(APIView):
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))
challenger = [p for p in parcours.challenger if p['code'] == user_code]
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))
challenge = [c for c in trys if c['code'] == challenge_code]
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.challenger = [p if p['code'] != user_code else {
**p, "exos": [e if e['code'] != challenge_code else {**e, "result": result, "note": note} for e in p['exos']]} for p in parcours.challenger]
parcours.save()
return Response({"data": {}}, status=status.HTTP_200_OK)
moyenne = Parcours.objects.getAverage(
parcours.id_code, challenger[0]['code'])
parcours.challenger = [p if p['code'] != user_code else {
**p, 'validate': moyenne['value'] * 20 / moyenne['total'] >= condition} for p in parcours.challenger]
parcours.save()
challenger = [p for p in parcours.challenger if p['code'] == user_code]
trys = challenger[0]['exos']
challenge = [c for c in trys if c['code'] == challenge_code]
challenge = challenge[0]
return Response({'data': {**challenge, "parcours_id": parcours.id_code, 'user_code': user_code, 'parcours_name': parcours.name, 'challenger_name': challenger[0]['nick']}}, status=status.HTTP_200_OK)
class ParcoursAPI(APIView):
@ -366,25 +506,31 @@ class ParcoursAPI(APIView):
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)
success = request.data.get('success_condition')
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()
serial = ParcoursCreateSerializer(
data={'name': name, 'room': room.id, 'timer': timer, 'exercices': exos, 'success_condition': success})
if not serial.is_valid():
return Response(serial.errors, status=status.HTTP_400_BAD_REQUEST)
parcours = serial.create(serial.validated_data)
print('PARCOURS', parcours)
layer = get_channel_layer()
async_to_sync(layer.group_send)(room_code, {
'type': 'new_parcours', 'parcours': ParcoursSerializer(parcours).data})
'type': 'new_parcours', 'parcours': ParcoursFullSerializer(parcours).data})
layer = get_channel_layer()
return Response({"data": {'id_code': parcours.id_code}}, status=status.HTTP_200_OK)
@ -396,7 +542,8 @@ class ParcoursAPI(APIView):
id_code = request.data.get('id_code')
exos = request.data.get('exos')
timer = request.data.get('timer')
# print(exos, name, room_code)
success_condition = request.data.get('success_condition')
try:
parcours = Parcours.objects.filter(id_code=id_code)[0]
except:
@ -410,11 +557,12 @@ class ParcoursAPI(APIView):
parcours.name = name
parcours.timer = timer
parcours.exercices = exos
parcours.success_condition = success_condition
parcours.save()
layer = get_channel_layer()
async_to_sync(layer.group_send)(room.id_code, {
'type': 'edit_parcours', 'parcours': ParcoursSerializer(parcours).data})
'type': 'edit_parcours', 'parcours': ParcoursFullSerializer(parcours).data})
layer = get_channel_layer()
return Response({"data": {'id_code': parcours.id_code}}, status=status.HTTP_200_OK)
@ -433,23 +581,19 @@ class ParcoursAPI(APIView):
filter(lambda p: p['code'] == user_code, room.anonymousMembers))
userInRoom = True
if request.user.is_authenticated:
userInRoom = len(request.user.room_set.filter(id_code = room.id_code)) != 0
userInRoom = len(request.user.room_set.filter(
id_code=room.id_code)) != 0
if len(participants) == 0 and not userInRoom:
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)
return Response({"data": ParcoursFullSerializer(parcours).data}, 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)
return Response({"data": ParcoursFullSerializer(parcours, context={'user_code': user_code}).data, }, 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)
return Response({"data": ParcoursFullSerializer(parcours).data, }, status=status.HTTP_200_OK)

View File

@ -1,6 +0,0 @@
import random
def main():
return {'calcul': f'1 + [3] = 4'}
print('test')

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,6 +0,0 @@
import random
def main():
return {'calcul': f'1 + [3] = 4', 'csv': None}
print('test')

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,6 +0,0 @@
import random
def main():
return {'calcul': f'1 + [3] = 4', 'csv': None}
print('test')

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,6 +0,0 @@
import random
def main():
return {'calcul': f'1 + [3] = 4', 'csv': None}
print('test')

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +1,10 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +1,10 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

View File

@ -1,10 +0,0 @@
import random
"""
Fonction main() qui doit renvoyer un objet avec:
calcul: le calcul a afficher
result: la correction du calcul (pas de correction -> mettre None)
"""
def main():
return {"calcul": "", "result": None}

Some files were not shown because too many files have changed in this diff Show More