This commit is contained in:
Kilton937342 2022-06-11 23:39:03 +02:00
parent 60a2197970
commit 035af2a3b7
303 changed files with 10913 additions and 846 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
/backend/env
/backend/venv
/frontend/node_modules

View File

@ -18,7 +18,7 @@ def parseCorrection(calc, replacer='...'):
return calc
def Generateur(path, quantity, key):
def Generateur(path, quantity, key, forcedCorrection = False):
spec = importlib.util.spec_from_file_location(
"tmp", path)
tmp = importlib.util.module_from_spec(spec)
@ -47,5 +47,5 @@ def Generateur(path, quantity, key):
main_result = main_func()
main = {**default_object, **main_result}
op_list.append({'calcul': parseCorrection(main[
object_key], replacer) if (key != 'web' and main['correction'] == False) else main[object_key], 'correction': main[correction_key]})
object_key], replacer) if (forcedCorrection or (key != 'web' and main['correction'] == False)) else main[object_key], 'correction': main[correction_key]})
return op_list

View File

@ -39,15 +39,26 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
#3rd party
# 3rd party
'rest_framework',
'corsheaders',
'channels',
"rest_framework.authtoken",
'dj_rest_auth', # new
'django.contrib.sites', # new
'allauth', # new
'allauth.account', # new
'allauth.socialaccount', # new
'rest_auth.registration', # new
"django_filters",
#local
# local
'exercices',
'room',
"users"
]
@ -70,7 +81,7 @@ MIDDLEWARE = [
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
#CORS
# 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',
'http://127.0.0.1:8002', 'http://localhost:8001', 'http://192.168.1.18:8000']
CSRF_TRUSTED_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',
@ -169,7 +180,7 @@ STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
MEDIA_ROOT= os.path.join(BASE_DIR)
MEDIA_ROOT = os.path.join(BASE_DIR)
# Default primary key field type
@ -186,3 +197,27 @@ CHANNEL_LAYERS = {
},
},
}
AUTH_USER_MODEL = 'users.CustomUser'
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
AUTHENTICATION_BACKENDS = ("django.contrib.auth.backends.ModelBackend", "allauth.account.auth_backends.AuthenticationBackend",
)
SITE_ID = 1
ACCOUNT_USERNAME_REQUIRED = True
ACCOUNT_SESSION_REMEMBER = True
ACCOUNT_AUTHENTICATION_METHOD = 'username'
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_UNIQUE_USERNAME = True
REST_FRAMEWORK = {
'DATETIME_FORMAT': "%m/%d/%Y %I:%M%P", 'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PAGINATION_CLASS': 'exercices.paginations.CustomPagination',
'PAGE_SIZE': 20
}

View File

@ -20,5 +20,6 @@ urlpatterns = [
path('api/admin/', admin.site.urls),
path('api/exos/', include('exercices.urls')),
path('api/room/', include('room.urls')),
path('api/users/', include("users.urls"))
#path('api/users/', include('users.urls'))
]

Binary file not shown.

View File

@ -0,0 +1,30 @@
import django_filters
from .models import Exercice
class ExosFilter(django_filters.FilterSet):
class Meta:
model = Exercice
fields = ['name']
@property
def qs(self):
parent = super().qs
search = self.request.get('search', '')
tags = self.request.getlist('tags[]', [])
if len(tags) == 0:
withT = []
withAllTags = []
withAllTagsQ = parent
else:
withT = parent.filter(tags__id_code__in=tags).distinct() #les exos possedants au moins un des tags
withAllTags = list(filter(lambda t: all(
i in [t.id_code for t in t.tags.all()] for i in tags ), withT))
withAllTagsQ = parent.filter(id_code__in = [e.id_code for e in withAllTags])
print('WIRHA', withAllTagsQ)
return withAllTagsQ.filter(name__icontains=search)

View File

@ -0,0 +1,25 @@
# Generated by Django 4.0 on 2022-05-20 13:52
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
('exercices', '0004_alter_exercice_exemple_alter_exercice_exo_model'),
]
operations = [
migrations.AddField(
model_name='exercice',
name='author',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='users.customuser'),
),
migrations.AddField(
model_name='exercice',
name='private',
field=models.BooleanField(default=True),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.0 on 2022-05-21 08:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('exercices', '0005_exercice_author_exercice_private'),
]
operations = [
migrations.AlterField(
model_name='exercice',
name='private',
field=models.BooleanField(default=False),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.0 on 2022-05-30 15:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('exercices', '0006_alter_exercice_private'),
]
operations = [
migrations.AddField(
model_name='exercice',
name='origin',
field=models.CharField(default='', max_length=20, null=True),
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 4.0 on 2022-05-30 16:15
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('exercices', '0007_exercice_origin'),
]
operations = [
migrations.RemoveField(
model_name='exercice',
name='origin',
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 4.0 on 2022-05-30 16:15
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('exercices', '0008_remove_exercice_origin'),
]
operations = [
migrations.AddField(
model_name='exercice',
name='origin',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='exercices.exercice'),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 4.0 on 2022-05-30 16:25
from django.db import migrations, models
import exercices.models
class Migration(migrations.Migration):
dependencies = [
('exercices', '0009_exercice_origin'),
]
operations = [
migrations.AlterField(
model_name='exercice',
name='id_code',
field=models.CharField(default=exercices.models.generate_unique_code_step, max_length=50, null=True, unique=True),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 4.0 on 2022-05-30 16:30
from django.db import migrations, models
import exercices.models
class Migration(migrations.Migration):
dependencies = [
('exercices', '0010_alter_exercice_id_code'),
]
operations = [
migrations.AlterField(
model_name='exercice',
name='id_code',
field=models.CharField(default=exercices.models.generate_unique_code_step, max_length=50, unique=True),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 4.0 on 2022-05-30 16:53
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('exercices', '0011_alter_exercice_id_code'),
]
operations = [
migrations.AlterField(
model_name='exercice',
name='origin',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='exercices.exercice'),
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 4.0 on 2022-06-04 06:54
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0010_alter_customuser_id_code'),
('exercices', '0012_alter_exercice_origin'),
]
operations = [
migrations.AddField(
model_name='tag',
name='user',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='users.customuser'),
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 4.0 on 2022-06-04 07:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('exercices', '0013_tag_user'),
]
operations = [
migrations.RemoveField(
model_name='exercice',
name='tags',
),
migrations.AddField(
model_name='exercice',
name='tags',
field=models.ManyToManyField(to='exercices.Tag'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.0 on 2022-06-06 19:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('exercices', '0014_remove_exercice_tags_exercice_tags'),
]
operations = [
migrations.AddField(
model_name='exercice',
name='original',
field=models.BooleanField(default=True),
),
]

View File

@ -5,6 +5,7 @@ import string
from django.db.models.fields import CharField, IntegerField, TextField, BooleanField
from django.db.models.fields.json import JSONField
from users.models import CustomUser
# Create your models here.
@ -34,6 +35,7 @@ class Tag(models.Model):
color = CharField(max_length=50, default='')
id_code = CharField(max_length=50, unique=True,
default=generate_unique_code_tag)
user = models.ForeignKey('users.CustomUser', null=True, on_delete=models.CASCADE)
name = CharField(max_length=25, default='')
@ -55,13 +57,20 @@ class Exercice(models.Model):
unique=True, max_length=50, default=generate_unique_code_step)
exo_model = models.FileField(upload_to=exo_code)
consigne = CharField(max_length=100, default='', blank=True)
tags = JSONField(default=list)
tags = models.ManyToManyField(Tag)
exemple = JSONField(default=dict)
isPdf = BooleanField(default=True)
isCsv = BooleanField(default=True)
isWeb = BooleanField(default=True)
original = BooleanField(default=True)
origin = models.ForeignKey('self', null=True, on_delete = models.SET_NULL)
private = BooleanField(default=False)
author = models.ForeignKey(CustomUser, null=True, on_delete=models.CASCADE)
objects = ExerciceManager()
def delete(self, using=None, keep_parents=False):

View File

@ -0,0 +1,21 @@
from rest_framework import pagination
from rest_framework.response import Response
class CustomPagination(pagination.PageNumberPagination):
page_size_query_param='s'
page_query_param='p'
page_size=20
def get_paginated_response(self, data):
return Response({
'links': {
'next': self.get_next_link(),
'previous': self.get_previous_link()
},
'count': self.page.paginator.count,
'page_size': self.page.paginator.per_page,
'pages': self.page.paginator.num_pages,
'page_number': self.page.number,
'results': data
})

View File

@ -2,6 +2,9 @@ import os
import tempfile
from django.forms import ValidationError
from rest_framework import serializers
from users.models import CustomUser
from users.serializers import UserSerializer
from .models import Exercice, Tag
from api.Generateur import Generateur
import importlib.util
@ -9,19 +12,38 @@ from .utils import checkExoModelObject
class ExerciceSerializer(serializers.ModelSerializer):
exo_model = ''
tags = serializers.SerializerMethodField()
author = serializers.SerializerMethodField()
origin = serializers.SerializerMethodField()
class Meta:
model = Exercice
fields = ('id', 'name', 'id_code', 'consigne',
'exemple', 'tags', 'isPdf', 'isCsv', 'isWeb')
fields = ('name', 'id_code', 'consigne', 'author',
'exemple', 'tags', 'isPdf', 'isCsv', 'isWeb', "private", 'tags', 'origin')
def get_author(self, obj):
return UserSerializer(obj.author).data
''' def get_exo_model(self,obj):
pass '''
def get_tags(self, obj):
try:
user = CustomUser.objects.filter(
id_code=self.context['user_id'])[0]
return [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in obj.tags.all() if t.user == user]
except:
return []
def get_origin(self,obj):
return obj.origin if obj.origin == None else {'id_code': obj.origin.id_code}
class ExerciceCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Exercice
fields = ('name', 'consigne', 'exo_model')
fields = ('name', 'consigne', 'exo_model', 'private')
def validate_exo_model(self, value):
@ -50,38 +72,14 @@ class ExerciceCreateSerializer(serializers.ModelSerializer):
exoCategory = checkExoModelObject(result_object)
if not exoCategory['isPdf'] and not exoCategory['isCsv'] and not exoCategory['isWeb']:
raise serializers.ValidationError('object invalid', code= 'invalid')
raise serializers.ValidationError(
'object invalid', code='invalid')
return {
**exoCategory,
'file': value
}
''' code = value.split(CODE_SEPARATOR)
if(len(code) == 1 or code[1] == ""):
raise serializers.ValidationError('This field may not be blank', code="blank")
if(len(code) == 2 and code[0] == 'python'):
# Generateur(value, 1)
try:
Generateur(value, 1)
except KeyError as e:
if e.args[0] == 'calcul' or e.args[0] == "result":
raise serializers.ValidationError(
f'Verifiez que l\'objet correspond à ce qui ai demandé ({e} manquant)', code="invalid")
if e.args[0] == 'main':
raise serializers.ValidationError(
'Code non conforme (fonction "main" requise)', code="invalid")
else:
raise serializers.ValidationError(
'Code non conforme', code="invalid")
except TypeError:
raise serializers.ValidationError('Il y a eu une erreur (vérifiez que la fontion main renvoie l\'objet demandé)')
return value '''
def create(self, validated_data, **kwargs):
exo_model = validated_data.pop('exo_model')

View File

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

View File

@ -1,3 +1,9 @@
from django.db.models import Q
from rest_framework.pagination import PageNumberPagination
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.core.files.base import ContentFile
from rest_framework.decorators import api_view, permission_classes
import base64
from cmath import inf
import csv
@ -16,8 +22,14 @@ from rest_framework import status
from django.template.loader import get_template
import sympy
from .filters import ExosFilter
from .paginations import CustomPagination
from .pdfmaker import pdf_settings
from .models import generate_unique_code_step
from .utils import TexError, checkExoModelObject
import requests
@ -26,60 +38,97 @@ from api.Generateur import Csv_generator, Generateur
from .models import Exercice, Tag
from .serializers import ExerciceCreateSerializer, ExerciceSerializer, TagSerializer
from users.serializers import UserSerializer
from rest_framework import permissions
# Create your views here.
class ExerciceAPI(APIView):
pagination_class = CustomPagination
def get(self, request, format=None):
steps = Exercice.objects.all()
code_separ = '<@!code>\r\n'
steps = Exercice.objects.filter(private=False)
userExos = []
if request.user.is_authenticated:
steps = [s for s in steps if s.author.id != request.user.id]
userExos = request.user.exercice_set.all()
code = request.GET.get('code')
nb_in_page = 24
if code == 'pdf':
stepsListSorted = [s for s in steps if s.isPdf == True]
userExosListSorted = [s for s in userExos if s.isPdf == True]
elif code == 'web':
stepsListSorted = [s for s in steps if s.isWeb == True]
userExosListSorted = [s for s in userExos if s.isWeb == True]
if code == 'all':
return Response({"data": list(map(lambda ex: {**ExerciceSerializer(ex).data, 'exo_model': {'filename': ex.exo_model.name.split('/')[-1], "data": open(ex.exo_model.name, 'r').read()}, "tags": list(map(lambda t: {**TagSerializer(Tag.objects.filter(id_code=t)[0]).data, 'value': Tag.objects.filter(id_code=t)[0].id_code, 'label': Tag.objects.filter(id_code=t)[0].name}, ex.tags))}, steps))}, status=status.HTTP_200_OK)
elif code == "pdf":
return Response({"data": list(map(lambda ex: {**ExerciceSerializer(ex).data, 'exo_model': {'filename': ex.exo_model.name.split('/')[-1], "data": open(ex.exo_model.name, 'r').read()}, "tags": list(map(lambda t: {**TagSerializer(Tag.objects.filter(id_code=t)[0]).data, 'value': Tag.objects.filter(id_code=t)[0].id_code, 'label': Tag.objects.filter(id_code=t)[0].name}, ex.tags))}, list(filter(lambda s:s.isPdf == True, steps))))}, status=status.HTTP_200_OK)
elif code == "web":
return Response({"data": list(map(lambda ex: {**ExerciceSerializer(ex).data, 'exo_model': {'filename': ex.exo_model.name.split('/')[-1], "data": open(ex.exo_model.name, 'r').read()}, "tags": list(map(lambda t: {**TagSerializer(Tag.objects.filter(id_code=t)[0]).data, 'value': Tag.objects.filter(id_code=t)[0].id_code, 'label': Tag.objects.filter(id_code=t)[0].name}, ex.tags))}, list(filter(lambda s:s.isWeb == True, steps))))}, status=status.HTTP_200_OK)
elif code != 'all' and code != 'pdf' and code != "web":
exo = Exercice.objects.filter(id_code=code)[0]
print(open(exo.exo_model.name, 'r').read())
return Response({"data": {**ExerciceSerializer(exo).data, 'exo_model': {'filename': exo.exo_model.name.split('/')[-1], "data": open(exo.exo_model.name, 'r').read()}, "tags": list(map(lambda t: {**TagSerializer(Tag.objects.filter(id_code=t)[0]).data, 'value': Tag.objects.filter(id_code=t)[0].id_code, 'label': Tag.objects.filter(id_code=t)[0].name}, exo.tags))}}, status=status.HTTP_200_OK)
stepsListSorted = steps
userExosListSorted = userExos
else:
return Response({"data": list(map(lambda ex: {**ExerciceSerializer(ex).data, 'exo_model': {'filename': ex.exo_model.name.split('/')[-1], "data": open(ex.exo_model.name, 'r').read()}, "tags": list(map(lambda t: {**TagSerializer(Tag.objects.filter(id_code=t)[0]).data, 'value': Tag.objects.filter(id_code=t)[0].id_code, 'label': Tag.objects.filter(id_code=t)[0].name}, ex.tags))}, steps))}, status=status.HTTP_200_OK)
stepsListSorted = steps
userExosListSorted = userExos
if code != 'all' and code != 'pdf' and code != "web":
exo = Exercice.objects.filter(id_code=code)[0]
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)
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(
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)
def post(self, request, format=None):
file = request.FILES['file']
name = request.data.get('name')
private = request.data.get('private')
consigne = request.data.get('consigne')
create_serializer = ExerciceCreateSerializer(
data={'exo_model': file, "consigne": consigne, "name": name}, context={'request': request})
data={'exo_model': file, "consigne": consigne, "name": name, 'private': private}, context={'request': request})
if create_serializer.is_valid():
print(create_serializer.validated_data['exo_model'])
author = request.user if request.user.is_authenticated else None
new_exo = Exercice(consigne=consigne,
exo_model=create_serializer.validated_data['exo_model']['file'], name=name)
new_exo.exemple = [] # Generateur(exo_model, 5)
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']
new_exo.save()
new_exo.exemple = {
# 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)
return Response({"status": "200", "errors": {}, "data": ExerciceSerializer(new_exo).data}, status=status.HTTP_200_OK)
return Response({"status": "200", "errors": {}, "data": {**ExerciceSerializer(new_exo).data, "author": UserSerializer(new_exo.author).data if new_exo.author != None else None, 'exo_model': {'filename': new_exo.exo_model.name.split('/')[-1], "data": open(new_exo.exo_model.name, 'r').read()}, "tags": [{**TagSerializer(t).data, 'value': t.id_code, 'label': t.name} for t in new_exo.tags.all()]}}, status=status.HTTP_200_OK)
print(create_serializer.errors, 'errs')
return Response({"status": "400", "errors": create_serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
@method_decorator(login_required)
def put(self, request, format=None):
file = request.FILES['file']
name = request.data.get('name')
consigne = request.data.get('consigne')
exo_model = request.data.get('exo_model')
id_code = request.data.get('id_code')
exo = Exercice.objects.filter(id_code=id_code)[0]
exo = Exercice.objects.filter(id_code=id_code)
if len(exo) == 0:
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)
serializer = ExerciceCreateSerializer(
data={'exo_model': file, "consigne": consigne, "name": name})
@ -89,61 +138,207 @@ class ExerciceAPI(APIView):
exo.name = name
exo.consigne = consigne
exo.exo_model = serializer.validated_data['exo_model']['file']
exo.exemple =[]
exo.isPdf = serializer.validated_data['exo_model']['isPdf']
exo.isCsv = serializer.validated_data['exo_model']['isCsv']
exo.isWeb = serializer.validated_data['exo_model']['isWeb']
exo.save()
exo.exemple = {
# f'{"Csv" if new_exo.isCsv == True else ""}{"Web" if new_exo.isWeb == True else ""}',
'type': 'Csv' if exo.isCsv == True else 'Web' if exo.isWeb == True else None,
'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)[0]
exo = Exercice.objects.filter(id_code=id_code)
if len(exo) == 0:
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)
exo.delete()
# sleep(2)
return Response({'status': "200", "data": id_code}, status=status.HTTP_200_OK)
@api_view(['GET'])
def getPublicList(request):
''' paginator = PageNumberPagination()
paginator.page_size = 10
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)
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]
elif code == 'web':
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 = ExosFilter(request=request.GET, queryset=exos).qs
result_page = paginator.paginate_queryset(exos, 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)
code = request.query_params.get('code')
if code == 'pdf':
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]
elif code == 'csv':
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)
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]
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'])
@permission_classes([permissions.IsAuthenticated])
def fav(request):
code = request.data.get('code')
exo = Exercice.objects.filter(id_code=code)
if len(exo) == 0:
return Response({'data': {'msg': 'Not found'}}, status=status.HTTP_404_NOT_FOUND)
originExo = exo[0]
exo = exo[0]
with open(exo.exo_model.path, 'r') as f:
print(f.name.split('/')[-1])
exo.pk = None
exo.id = None
exo.id_code = generate_unique_code_step()
exo.author = request.user
exo.original = False
exo.origin = Exercice.objects.filter(id_code=code)[0]
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)
class TagsAPI(APIView):
@method_decorator(login_required)
def get(self, request, format=None):
tags = Tag.objects.all()
tags = request.user.tag_set.all()
return Response({"data": list(map(lambda tag: {**TagSerializer(tag).data, 'label': tag.name, "value": tag.id_code}, tags))}, status=status.HTTP_200_OK)
@method_decorator(login_required)
def post(self, request, format=None):
options = request.data.get('tags')
step = request.data.get('step')
step = Exercice.objects.filter(id_code=step)[0]
id_code = request.data.get('step')
exo = Exercice.objects.filter(id_code=id_code)
if len(exo) == 0:
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'])
newTag = Tag(name=o['label'], color=o['color'], user = request.user)
newTag.save()
oldTags = step.tags
step.tags = [*oldTags, newTag.id_code]
step.save()
exo.tags.add(newTag)
exo.save()
tagsList.append(
{'name': o['label'], 'color': o['color'], 'id_code': newTag.id_code})
else:
tagId = o['value']
tag = Tag.objects.filter(id_code=tagId)[0]
oldTags = step.tags
step.tags = [*oldTags, tag.id_code]
step.save()
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]
exo.tags.add(tag)
exo.save()
tagsList.append(
{'name': o['label'], 'color': o['color'], 'id_code': tag.id_code})
return Response({'tags': tagsList}, status=status.HTTP_200_OK)
return Response({'id_code': exo.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)
@method_decorator(login_required)
def delete(self, request, format=None):
tag = request.data.get('tag')
step = Exercice.objects.filter(id_code=request.data.get('step'))[0]
step.tags = list(filter(lambda t: t != tag, step.tags))
step.save()
tagObj = Tag.objects.filter(id_code=tag)[0]
return Response({"data": {"name": tagObj.name}}, status=status.HTTP_200_OK)
tagId = request.data.get('tag')
id_code = request.data.get('step')
exo = Exercice.objects.filter(id_code=id_code)
if len(exo) == 0:
return Response({'status': "404", "data": {}},
status=status.HTTP_404_NOT_FOUND)
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]
exo = exo[0]
if request.user != exo.author:
if tag.user != request.user:
return Response({'status': "401", "data": {}},
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)
class Editor(APIView):
@ -171,7 +366,6 @@ class CSV_Generator(APIView):
if ex.isCsv == False:
return Response({'error': "Bah non en fait"}, status=status.HTTP_401_UNAUTHORIZED)
model = ex.exo_model.name
consigne = ex.consigne
@ -296,7 +490,7 @@ class Test(APIView):
class ExoModelApi(APIView):
def get(self, request, format=None):
code = request.GET.get('code')
code = request.GET.get('id_code')
exo = Exercice.objects.filter(id_code=code)[0]
print(exo.exo_model.name)
model = open(exo.exo_model.name, 'rb')

View File

@ -3,9 +3,9 @@ import json
from uuid import uuid4
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from .models import Room
class RoomConsumer(AsyncWebsocketConsumer):
async def connect(self):
@ -25,39 +25,44 @@ class RoomConsumer(AsyncWebsocketConsumer):
print('closed')
await self.close()
async def receive(self, text_data):
text_data_json = json.loads(text_data)
type = text_data_json['data']['type']
print(text_data_json)
if type == "login":
print('LOF', self.scope['user'])
participants = await self.get_participants()
if self.scope['user'].is_anonymous:
nick = text_data_json['data']['nick']
else:
nick = self.scope['user'].username
if nick in list(map(lambda p: p['nick'], participants)):
print('Nooope', nick, nick in list(
map(lambda p: p['nick'], participants)))
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é"}))
else:
if self.room.private == True:
waiter = await self.add_waiter_db(nick)
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)
if waiter != None:
self.waiter = True
self.waiter_code = waiter['code']
await self.send(json.dumps({'type': "waitingRoom", "nick": nick, 'id_code': self.room_id}))
await self.channel_layer.group_add(f'waiter__{waiter["code"]}', self.channel_name)
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "add_waiter", "code": waiter['code'], "nick": nick,})
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "add_waiter", "code": waiter['code'], "nick": waiter['nick'], "status": waiter['status']})
else:
await self.send(json.dumps({'type': 'loginResponse', "error": "USER_INPUT", "description": "Pseudo déjà utilisé"}))
else:
await self.channel_layer.group_add(self.room_id, self.channel_name)
if self.scope['user'].is_anonymous:
new_participant = await self.add_participant(nick, self.clientId)
self.user = new_participant
print('new_participant')
else:
new_participant = await self.add_user(nick, self.scope['user'])
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.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']})
@ -65,26 +70,43 @@ class RoomConsumer(AsyncWebsocketConsumer):
elif type == "acceptParticipant":
code = text_data_json['data']['code']
nick = text_data_json['data']['nick']
status = text_data_json['data']['status']
self.waiter = False
if status == 'anonymous':
new_participant = await self.add_participant(nick, str(uuid4()))
else:
new_participant = await self.add_user(code)
print(new_participant)
await self.del_waiter_db(code)
await self.channel_layer.group_send(f'waiter__{code}', {"type": "accept_room", 'id_code': self.room_id, 'code': new_participant['code']})
elif type == "refusedParticipant":
code = text_data_json['data']['code']
await self.del_waiter_db(code)
await self.channel_layer.group_send(f'waiter__{code}', {"type": "refused_participant"})
elif type == "logAcceptedWaiter":
code = text_data_json['data']['code']
participants = await self.get_participants()
if not self.scope['user'].is_anonymous:
await self.channel_layer.group_discard(f'waiter__{code}', self.channel_name)
await self.channel_layer.group_add(self.room_id, self.channel_name)
self.clientId = self.scope['user'].clientId
if code in list(map(lambda p: p['code'], participants)):
self.user = {
'nick': self.scope['user'].username, 'code': self.scope['user'].id_code, 'clientId':self.scope['user'].clientId, "owner": False} #à continuer dsl
self.waiter = False
self.waiter_code = None
await self.send(json.dumps({'type': "roomJoined", "clientId": self.clientId, 'id_code': self.room_id, 'identity': self.user}))
await self.channel_layer.group_send(self.room_id, {"type": "join.event", "nick": self.user['nick'], "owner": False, "online": True, "code": ''})
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "join.event", "nick": self.user['nick'], "owner": False, "online": True, "code": self.user['code']})
elif code in list(map(lambda p: p['code'], participants)):
participant = list(
filter(lambda p: p['code'] == code, participants))[0]
await self.channel_layer.group_discard(f'waiter__{code}', self.channel_name)
@ -100,13 +122,33 @@ class RoomConsumer(AsyncWebsocketConsumer):
await self.channel_layer.group_send(self.room_id, {"type": "join.event", "nick": participant['nick'], "owner": False, "online": True, "code": ''})
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "join.event", "nick": participant['nick'], "owner": False, "online": True, "code": participant['code']})
elif type == 'relogin':
if not self.scope['user'].is_anonymous:
userInRoom = await self.userInRoom()
if not userInRoom:
await self.send(json.dumps({"type": "reloginError"}))
else:
isOwner = self.scope['user'].clientId == self.room.owner[
'clientId'] and self.scope['user'].id_code == self.room.owner['code']
self.clientId = self.scope['user'].clientId
if isOwner:
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)
self.user = {
'nick': self.scope['user'].username, 'code': self.scope['user'].id_code, 'clientId': self.scope['user'].clientId, "owner": False}
await self.connect_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']})
code = text_data_json['data']['code']
participants = await self.get_participants()
print('participants', code, participants)
if code in list(map(lambda p: p['code'], participants)):
participant = list(filter(lambda p: p['code'] == code, participants))[0]
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']:
@ -126,15 +168,39 @@ class RoomConsumer(AsyncWebsocketConsumer):
else:
await self.send(json.dumps({"type": "reloginError"}))
elif type == "reconnect":
client = text_data_json['data']['clientId']
print(self.scope['user'].is_anonymous)
if not self.scope['user'].is_anonymous:
userInRoom = await self.userInRoom()
if not userInRoom:
await self.send(json.dumps({"type": "reconnectError", 'id_code': self.room_id}))
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:
await self.channel_layer.group_add(self.room_id, self.channel_name)
self.user = {
'code': self.scope['user'].id_code, 'nick': self.scope['user'].username, "clientId": self.scope['user'].clientId, 'online': True, 'owner': self.scope['user'].clientId == self.room.owner['clientId'] and self.scope['user'].id_code == self.room.owner['code']}
await self.connect_participant()
self.clientId = self.scope['user'].clientId
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']})
else:
participants = await self.get_participants()
if client in list(map(lambda p: p['clientId'], participants)):
self.clientId = client
participant = list(filter(lambda p: p['clientId'] == client, participants))[0]
participant = list(
filter(lambda p: p['clientId'] == client, participants))[0]
if participant['clientId'] == self.room.owner['clientId'] and participant['code'] == self.room.owner['code']:
print('add in admin')
@ -154,24 +220,26 @@ class RoomConsumer(AsyncWebsocketConsumer):
elif type == 'ban':
code = text_data_json['data']["code"]
nick = text_data_json['data']["nick"]
status = text_data_json['data']["status"]
if status == 'anonymous':
await self.del_participant(code)
else:
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"]}))
async def accept_room(self, event):
await self.send(json.dumps({'type': 'accept_room', 'id_code': self.room_id, 'code':event["code"]}))
await self.send(json.dumps({'type': 'accept_room', 'id_code': self.room_id, 'code': event["code"]}))
async def accept_waiter(self, event):
await self.send(json.dumps({'type': 'joined', 'nick': event['nick'], "owner": event['owner'], "online": event['online'], "code": event["code"]}))
async def add_waiter(self, event):
await self.send(json.dumps({'type': 'add_waiter', 'nick': event['nick'], "code": event["code"], }))
await self.send(json.dumps({'type': 'add_waiter', 'nick': event['nick'], "code": event["code"], "status": event['status']}))
async def new_parcours(self, event):
await self.send(json.dumps({'type': "add_parcours", "parcours": event['parcours']}))
@ -184,23 +252,30 @@ class RoomConsumer(AsyncWebsocketConsumer):
@database_sync_to_async
def get_participants(self):
return Room.objects.filter(id_code = self.room_id)[0].participants
return Room.objects.filter(id_code=self.room_id)[0].anonymousMembers
@database_sync_to_async
def get_room(self):
return Room.objects.filter(id_code = self.room_id)[0]
return Room.objects.filter(id_code=self.room_id)[0]
@database_sync_to_async
def add_participant(self, new, id):
return Room.objects.add_participant(self.room_id, new, id, False, True)
@database_sync_to_async
def del_participant(self, code):
return Room.objects.del_participant(self.room_id, code)
def add_user(self, code):
return Room.objects.add_user(self.room_id, code, False, True)
@database_sync_to_async
def add_waiter_db(self, new):
return Room.objects.add_waiter(self.room_id, new)
def del_participant(self, code):
return Room.objects.del_participant(self.room_id, code)
@database_sync_to_async
def del_user(self, code):
return Room.objects.del_user(self.room_id, code)
@database_sync_to_async
def add_waiter_db(self, new, isUser, code):
return Room.objects.add_waiter(self.room_id, new, isUser, code)
@database_sync_to_async
def del_waiter_db(self, code):
@ -208,11 +283,23 @@ class RoomConsumer(AsyncWebsocketConsumer):
@database_sync_to_async
def disconnect_participant(self):
if self.scope['user'].is_anonymous:
return Room.objects.disconnect(self.room_id, self.user['code'])
else:
return Room.objects.disconnect(self.room_id, self.scope['user'].id_code)
@database_sync_to_async
def connect_participant(self):
return Room.objects.connect(self.room_id, self.user['code'])
@database_sync_to_async
def userInRoom(self):
if self.scope['user'].is_anonymous:
return None
return len(self.scope['user'].room_set.filter(
id_code=self.room.id_code)) != 0
async def disconnect(self, close_code):
if self.waiter == False and self.user != None:
await self.disconnect_participant()
@ -234,8 +321,6 @@ class RoomConsumer(AsyncWebsocketConsumer):
async def del_waiter(self, event):
await self.send(json.dumps({"type": 'del_waiter', "code": event['code']}))
async def challenge_parcours(self, event):
await self.send(json.dumps({**event}))
@ -244,7 +329,3 @@ class RoomConsumer(AsyncWebsocketConsumer):
async def edit_parcours(self, event):
await self.send(json.dumps({**event}))

View File

@ -0,0 +1,25 @@
# Generated by Django 4.0 on 2022-05-21 15:35
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('room', '0004_alter_tempcorrection_id_code'),
]
operations = [
migrations.RenameField(
model_name='room',
old_name='participants',
new_name='anonymousMembers',
),
migrations.AddField(
model_name='room',
name='userMembers',
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 4.0 on 2022-05-21 15:44
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('room', '0005_rename_participants_room_anonymousmembers_and_more'),
]
operations = [
migrations.AlterField(
model_name='room',
name='userMembers',
field=models.ManyToManyField(null=True, to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 4.0 on 2022-05-21 15:44
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('room', '0006_alter_room_usermembers'),
]
operations = [
migrations.AlterField(
model_name='room',
name='userMembers',
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.0 on 2022-05-21 15:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('room', '0007_alter_room_usermembers'),
]
operations = [
migrations.AlterField(
model_name='room',
name='anonymousMembers',
field=models.JSONField(default=list, null=True),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.0 on 2022-05-21 17:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('room', '0008_alter_room_anonymousmembers'),
]
operations = [
migrations.AddField(
model_name='room',
name='online',
field=models.JSONField(default=list),
),
]

View File

@ -6,6 +6,8 @@ import string
from django.db import models
import pytz
from .utils import getNow
from users.models import CustomUser
# Create your models here.
@ -29,6 +31,7 @@ def generate_unique_code_parcours():
break
return code
def generate_unique_code_corr():
length = 6
@ -42,7 +45,7 @@ def generate_unique_code_corr():
class RoomManager(models.Manager):
def add_participant(self, room, new_name, clientId, owner, online):
room = self.get_queryset().filter(id_code=room)[0]
participants = room.participants
participants = room.anonymousMembers
if new_name in list(map(lambda p: p['nick'], participants)):
return None
code = None
@ -52,15 +55,45 @@ class RoomManager(models.Manager):
break
new_participant = {'nick': new_name, 'code': code,
'clientId': clientId, "owner": owner, "online": online}
room.participants = [*participants, new_participant]
room.anonymousMembers = [*participants, new_participant]
room.save()
return new_participant
def add_user(self, room, code, owner, online):
room = self.get_queryset().filter(id_code=room)[0]
try:
user = CustomUser.objects.filter(id_code = code)[0]
except IndexError:
return None
room.userMembers.add(user)
new_participant = {'nick': user.username, 'code': user.id_code,
'clientId': user.clientId, "owner": owner, "online": online}
room.online = [*room.online, user.id_code]
room.save()
return new_participant
def del_user(self, room, code):
room = self.get_queryset().filter(id_code=room)[0]
try:
user = CustomUser.objects.filter(id_code=code)[0]
except IndexError:
return None
room.userMembers.remove(user)
parcours = room.parcours_set.all()
for parc in parcours:
challenger = parc.challenger
parc.challenger = list(
filter(lambda c: c['code'] != code, challenger))
parc.save()
room.save()
return code
def del_participant(self, room, code):
room = self.get_queryset().filter(id_code=room)[0]
participants = room.participants
participants = room.anonymousMembers
room.participants = list(
room.anonymousMembers = list(
filter(lambda c: c['code'] != code, participants))
print('parcours', room.parcours_set)
parcours = room.parcours_set.all()
@ -72,21 +105,20 @@ class RoomManager(models.Manager):
room.save()
return code
def add_waiter(self, room, new_name):
def add_waiter(self, room, new_name, isUser, code = None):
room = self.get_queryset().filter(id_code=room)[0]
participants = room.participants
if new_name in list(map(lambda p: p['nick'], participants)):
participants = room.anonymousMembers
if new_name in list(map(lambda p: p['nick'], participants)) and isUser:
return None
waiters = room.waiters
if new_name in list(map(lambda p: p['nick'], waiters)):
return None
code = None
if code == None:
while True:
code = ''.join(random.choices(string.ascii_uppercase, k=6))
if code not in list(map(lambda p: p['code'], waiters)):
break
new_waiter = {'nick': new_name, 'code': code, }
new_waiter = {'nick': new_name, 'code': code, "status": 'user' if isUser == True else 'anonymous'}
room.waiters = [*waiters, new_waiter]
room.save()
return new_waiter
@ -100,50 +132,61 @@ class RoomManager(models.Manager):
def disconnect(self, room_code, code):
room = self.get_queryset().filter(id_code=room_code)[0]
participants = room.participants
participant = list(
filter(lambda p: p['code'] == code, participants))[0]
participant['online'] = False
room.participants = [
*list(filter(lambda p: p['code'] != code, participants)), participant]
online = room.online
room.online = [
o for o in online if o != code]
room.save()
return True
def connect(self, room_code, code):
room = self.get_queryset().filter(id_code=room_code)[0]
participants = room.participants
participant = list(
filter(lambda p: p['code'] == code, participants))[0]
participant['online'] = True
room.participants = [
*list(filter(lambda p: p['code'] != code, participants)), participant]
online = room.online
room.online = [*online, code]
room.save()
return True
def connectUser(self, room_code, code):
room = self.get_queryset().filter(id_code=room_code)[0]
online = room.online
room.online = [*online, code]
room.save()
return True
class Room(models.Model):
name = models.CharField(max_length=50)
id_code = models.CharField(max_length=50, default=generate_unique_code_room)
participants = models.JSONField(default=list)
id_code = models.CharField(
max_length=50, default=generate_unique_code_room)
anonymousMembers = models.JSONField(default=list, null=True)
userMembers = models.ManyToManyField("users.CustomUser")
waiters = models.JSONField(default=list)
created_at = models.DateTimeField(auto_now_add=True)
owner = models.JSONField(default=dict)
public_result = models.BooleanField(default=False)
online = models.JSONField(default=list)
private = models.BooleanField(default=True)
objects = RoomManager()
class ParcoursManager(models.Manager):
def challenge(self, parcours_code, user_code, result):
def challenge(self, parcours_code, user_code, result, isUser):
parcours = self.get_queryset().filter(id_code=parcours_code)[0]
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.participants))[0]
filter(lambda p: p['code'] == user_code, parcours.room.anonymousMembers))[0]
else:
user = CustomUser.objects.filter(id_code = user_code)[0]
challenger = {'nick': user.username, "code": user.id_code, 'clientId': user.clientId}
validate = None
date = getNow()
@ -153,7 +196,7 @@ class ParcoursManager(models.Manager):
result['note']['total'] >= condition else False
code = ''.join(random.choices(string.ascii_uppercase, k=6))
parcours.challenger = [*parcours.challenger,
{**challenger, 'exos': [{**result, 'endAt': date, 'code':code}], "validate": validate}]
{**challenger, 'exos': [{**result, 'endAt': date, 'code': code}], "validate": validate}]
else:
validate = False
@ -166,13 +209,13 @@ class ParcoursManager(models.Manager):
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:
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}]
parcours.save()
return {'validate': validate}
return {'validate': validate, 'code': code}
class Parcours(models.Model):
@ -189,6 +232,8 @@ class Parcours(models.Model):
objects = ParcoursManager()
class TempCorrection(models.Model):
correction = models.JSONField(default=list)
id_code = models.CharField(max_length=50, default = generate_unique_code_corr)
id_code = models.CharField(
max_length=50, default=generate_unique_code_corr)

View File

@ -6,7 +6,7 @@ class RoomSerializer(serializers.ModelSerializer):
class Meta:
model = Room
fields = ('id', 'name', 'id_code', 'participants')
fields = ('id', 'name', 'id_code', 'anonymousMembers')
class ParcoursSerializer(serializers.ModelSerializer):

View File

@ -25,13 +25,23 @@ from .utils import getNow
class RoomAPI(APIView):
def post(self, request, format=None):
name = request.data.get('name')
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)
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}, participants=[{'nick': nick, 'owner': True, 'code': code, "clientId": clientId}]
room = Room(name=name, owner={'name': nick, 'code': code, "clientId": clientId}, anonymousMembers=[{'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)
@ -40,22 +50,31 @@ class RoomAPI(APIView):
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
participants = room.anonymousMembers
users = room.userMembers.all()
print(room.userMembers.all())
if clientId not in list(map(lambda p: p['clientId'], participants)):
userInRoom = False
if request.user.is_authenticated:
userInRoom = len(request.user.room_set.filter(
id_code=room.id_code)) != 0
if clientId not in [p['clientId'] for p in participants] and not userInRoom:
return Response({'error': 'Non autorisé', 'code': '401'}, status=status.HTTP_401_UNAUTHORIZED)
admin = False
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": 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)
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)
def delete(self, request, format=None):
code = request.data.get('code')
@ -105,7 +124,13 @@ class RoomAPI(APIView):
@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)
userInRoom = False
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
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)
@ -153,9 +178,13 @@ class ChallengeAPI(APIView):
room = parcours.room
participants = list(
filter(lambda p: p['code'] == user_code, room.participants))
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
if(len(participants) == 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
@ -200,6 +229,8 @@ class ChallengeAPI(APIView):
exos = request.data.get('exos')
parcours_id = request.data.get('id_code')
user_code = request.data.get('user_code')
if request.user.is_authenticated:
user_code = request.user.id_code
correct_code = request.data.get('correct_code')
parcours = Parcours.objects.filter(id_code=parcours_id)
@ -214,14 +245,18 @@ class ChallengeAPI(APIView):
correctionDB = corrections[0]
participants = list(
filter(lambda p: p['code'] == user_code, room.participants))
if(len(participants) == 0):
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
if len(participants) == 0 and not userInRoom:
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(
@ -234,7 +269,8 @@ class ChallengeAPI(APIView):
correctInputs = exoCorrect['inputs']
print('correcti', correctInputs)
studentsInput = sorted(a['inputs'], key=lambda i: i.get('order'))
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]
@ -244,25 +280,24 @@ class ChallengeAPI(APIView):
corriged = list((map(corrige, student_answer)))
#l6 = uniquement les isCorrect
# 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})
parcours_id, user_code, {"result": corriged, "timer": exos['timer'], "note": note}, request.user.is_authenticated)
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']}})
'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']}})
return Response({"data": {"exos": corriged, "note": note}}, status=status.HTTP_200_OK)
def put(self, request, format=None):
@ -300,10 +335,11 @@ class ChallengeAPI(APIView):
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}]}]
*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):
@ -394,9 +430,12 @@ class ParcoursAPI(APIView):
room = parcours.room
participants = list(
filter(lambda p: p['code'] == user_code, room.participants))
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
if(len(participants) == 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

View File

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

View File

@ -0,0 +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():
return {"calcul": "", "result": None}

View File

@ -0,0 +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():
return {"calcul": "", "result": None}

View File

@ -0,0 +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():
return {"calcul": "", "result": None}

View File

@ -0,0 +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():
return {"calcul": "", "result": None}

View File

@ -0,0 +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():
return {"calcul": "", "result": None}

View File

@ -0,0 +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():
return {"calcul": "", "result": None}

View File

@ -0,0 +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():
return {"calcul": "", "result": None}

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