diff --git a/.gitignore b/.gitignore index cc669d7..f0794a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,15 @@ .dist/ __pycache__ -api/sandbox/testcases/*.txt +api/sandbox/section*/testcases/*.txt +api/sandbox/section*/runner* runner.py +@/* env/ .env -[0-9]*.txt +# [0-9]*.txt media/testfile media/topic @@ -20,5 +22,4 @@ media/resource tempCodeRunnerFile.py *.sqlite3 -*.exe - +*.exe \ No newline at end of file diff --git a/Backend/settings.py b/Backend/settings.py index e9cf8a6..8553696 100644 --- a/Backend/settings.py +++ b/Backend/settings.py @@ -40,10 +40,14 @@ CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", + "http://localhost:4000", + "http://localhost:5173", + "http://localhost:5174", "http://localhost:3001", "http://192.168.216.250:3000", "http://192.168.0.2:3000", "http://192.168.0.5:3000", + "http://192.168.0.11:5173", FRONEND_URL ] diff --git a/api/admin.py b/api/admin.py index a26be80..7edf398 100644 --- a/api/admin.py +++ b/api/admin.py @@ -16,8 +16,8 @@ class ProblemAdmin(admin.ModelAdmin): list_filter = ['language'] class AccountAdmin(admin.ModelAdmin): - list_display = ['account_id','username','email','is_admin','is_active'] - list_filter = ['is_admin','is_active'] + list_display = ['account_id','username','email','is_active'] + list_filter = ['is_active'] admin.site.register(Problem,ProblemAdmin) admin.site.register(Account,AccountAdmin) \ No newline at end of file diff --git a/api/controllers/account/create_account.py b/api/controllers/account/create_account.py new file mode 100644 index 0000000..c35521c --- /dev/null +++ b/api/controllers/account/create_account.py @@ -0,0 +1,18 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def create_account(request): + request.data['password'] = passwordEncryption(request.data['password']) + try: + account = Account.objects.create(**request.data) + except Exception as e: + return Response({'message':str(e)},status=status.HTTP_400_BAD_REQUEST) + serialize = AccountSerializer(account) + return Response(serialize.data,status=status.HTTP_201_CREATED) diff --git a/api/controllers/account/get_account.py b/api/controllers/account/get_account.py new file mode 100644 index 0000000..275d3f9 --- /dev/null +++ b/api/controllers/account/get_account.py @@ -0,0 +1,17 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_account(account_id:str): + try: + account = Account.objects.get(account_id=account_id) + serialize = AccountSerializer(account) + return Response(serialize.data,status=status.HTTP_200_OK) + except: + return Response({'message':'Account not found!'},status=status.HTTP_404_NOT_FOUND) diff --git a/api/controllers/account/get_all_accounts.py b/api/controllers/account/get_all_accounts.py new file mode 100644 index 0000000..2b74578 --- /dev/null +++ b/api/controllers/account/get_all_accounts.py @@ -0,0 +1,16 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_all_accounts(): + accounts = Account.objects.all() + serialize = AccountSecureSerializer(accounts,many=True) + return Response({ + "accounts": serialize.data + },status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/auth/authorization.py b/api/controllers/auth/authorization.py new file mode 100644 index 0000000..0434dae --- /dev/null +++ b/api/controllers/auth/authorization.py @@ -0,0 +1,21 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * +from time import time + +def authorization(request): + try: + account = Account.objects.get(account_id=request.data['account_id']) + account_dict = model_to_dict(account) + if account_dict['token_expire'] >= time() and account_dict['token'] == request.data['token']: + return Response({'result':True},status=status.HTTP_200_OK) + return Response({'result':False},status=status.HTTP_200_OK) + except Account.DoesNotExist: + return Response({'result':False},status=status.HTTP_200_OK) + # return Response({'message':"User doesn't exists!"},status=status.HTTP_404_NOT_FOUND) diff --git a/api/controllers/auth/login.py b/api/controllers/auth/login.py new file mode 100644 index 0000000..502a855 --- /dev/null +++ b/api/controllers/auth/login.py @@ -0,0 +1,29 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * +from decouple import config +from uuid import uuid4 +from time import time + +TOKEN_LIFETIME = int(config('TOKEN_LIFETIME_SECOND')) # (Second) + +def login(request): + try: + account = Account.objects.get(username=request.data['username']) + account_dict = model_to_dict(account) + + if passwordEncryption(request.data['password']) == account_dict['password']: + account.token = uuid4().hex + account.token_expire = int(time()+TOKEN_LIFETIME) + account.save() + return Response(model_to_dict(account),status=status.HTTP_202_ACCEPTED) + else: + return Response({'message':"Incorrect password!"},status=status.HTTP_406_NOT_ACCEPTABLE) + except Account.DoesNotExist: + return Response({'message':"User doesn't exists!"},status=status.HTTP_404_NOT_FOUND) diff --git a/api/controllers/auth/logout.py b/api/controllers/auth/logout.py new file mode 100644 index 0000000..9bbd0fa --- /dev/null +++ b/api/controllers/auth/logout.py @@ -0,0 +1,24 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * +from decouple import config +from uuid import uuid4 +from time import time + +def logout(request): + try: + account = Account.objects.get(account_id=request.data['account_id']) + if account.token == request.data['token']: + account.token = None + account.save() + return Response(model_to_dict(account),status=status.HTTP_200_OK) + else: + return Response({'message':"Invalid token!"},status=status.HTTP_200_OK) + except Account.DoesNotExist: + return Response({'message':"User doesn't exists!"},status=status.HTTP_404_NOT_FOUND) diff --git a/api/controllers/collection/add_problems_to_collection.py b/api/controllers/collection/add_problems_to_collection.py new file mode 100644 index 0000000..6ac7f98 --- /dev/null +++ b/api/controllers/collection/add_problems_to_collection.py @@ -0,0 +1,38 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def add_problems_to_collection(collection:Collection,request): + populated_problems = [] + + index = 0 + for problem_id in request.data['problem_ids']: + + problem = Problem.objects.get(problem_id=problem_id) + + alreadyExist = CollectionProblem.objects.filter(problem=problem,collection=collection) + if alreadyExist: + alreadyExist.delete() + + collection_problem = CollectionProblem( + problem=problem, + collection=collection, + order=index + ) + collection_problem.save() + index += 1 + populated_problems.append(collection_problem) + collection.updated_date = timezone.now() + problem_serialize = CollectionProblemPopulateProblemSecureSerializer(populated_problems,many=True) + collection_serialize = CollectionSerializer(collection) + + return Response({ + **collection_serialize.data, + 'problems': problem_serialize.data + },status=status.HTTP_201_CREATED) \ No newline at end of file diff --git a/api/controllers/collection/create_collection.py b/api/controllers/collection/create_collection.py new file mode 100644 index 0000000..f5541bc --- /dev/null +++ b/api/controllers/collection/create_collection.py @@ -0,0 +1,20 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def create_collection(account_id:str,request): + + request.data['creator'] = account_id + serialize = CollectionSerializer(data=request.data) + + if serialize.is_valid(): + serialize.save() + return Response(serialize.data,status=status.HTTP_201_CREATED) + else: + return Response(serialize.errors,status=status.HTTP_400_BAD_REQUEST) diff --git a/api/controllers/collection/delete_collection.py b/api/controllers/collection/delete_collection.py new file mode 100644 index 0000000..67cba72 --- /dev/null +++ b/api/controllers/collection/delete_collection.py @@ -0,0 +1,13 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def delete_collection(collection:Collection): + collection.delete() + return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/api/controllers/collection/get_all_collections.py b/api/controllers/collection/get_all_collections.py new file mode 100644 index 0000000..ff1a53f --- /dev/null +++ b/api/controllers/collection/get_all_collections.py @@ -0,0 +1,37 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_all_collections(request): + collections = Collection.objects.all() + + account_id = request.query_params.get('account_id',0) + + if account_id: + collections = collections.filter(creator_id=account_id) + + populated_collections = [] + for collection in collections: + con_probs = CollectionProblem.objects.filter(collection=collection) + + populated_cp = [] + for cp in con_probs: + prob_serialize = ProblemSerializer(cp.problem) + cp_serialize = CollectionProblemSerializer(cp) + populated_cp.append({**cp_serialize.data,**prob_serialize.data}) + + serialize = CollectionSerializer(collection) + collection_data = serialize.data + collection_data['problems'] = populated_cp + + populated_collections.append(collection_data) + + return Response({ + 'collections': populated_collections + },status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/collection/get_all_collections_by_account.py b/api/controllers/collection/get_all_collections_by_account.py new file mode 100644 index 0000000..7cd16fb --- /dev/null +++ b/api/controllers/collection/get_all_collections_by_account.py @@ -0,0 +1,34 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def populated_problems(collections: Collection): + problemCollections = CollectionProblem.objects.filter(collection__in=collections) + + populated_collections = [] + for collection in collections: + collection.problems = problemCollections.filter(collection=collection) + populated_collections.append(collection) + + return populated_collections + +def get_all_collections_by_account(account:Account): + + collections = Collection.objects.filter(creator=account).order_by('-updated_date') + collections = populated_problems(collections) + serialize = CollectionPopulateCollectionProblemsPopulateProblemSerializer(collections,many=True) + + manageableCollections = Collection.objects.filter(collectiongrouppermission__permission_manage_collections=True,collectiongrouppermission__group__in=GroupMember.objects.filter(account=account).values_list("group",flat=True)).order_by('-updated_date') + manageableCollections = populated_problems(manageableCollections) + manageableSerialize = CollectionPopulateCollectionProblemsPopulateProblemSerializer(manageableCollections,many=True) + + return Response({ + 'collections': serialize.data, + 'manageable_collections': manageableSerialize.data + },status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/collection/get_collection.py b/api/controllers/collection/get_collection.py new file mode 100644 index 0000000..8e87013 --- /dev/null +++ b/api/controllers/collection/get_collection.py @@ -0,0 +1,23 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_collection(collection:Collection): + + collection.problems = CollectionProblem.objects.filter(collection=collection).order_by('order') + collection.group_permissions = CollectionGroupPermission.objects.filter(collection=collection) + + for cp in collection.problems: + cp.problem.testcases = Testcase.objects.filter(problem=cp.problem,deprecated=False) + cp.problem.group_permissions = ProblemGroupPermission.objects.filter(problem=cp.problem) + + serializer = CollectionPopulateCollectionProblemsPopulateProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupAndCollectionGroupPermissionsPopulateGroupSerializer(collection) + + + return Response(serializer.data ,status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/collection/remove_problems_from_collection.py b/api/controllers/collection/remove_problems_from_collection.py new file mode 100644 index 0000000..1f0a6d6 --- /dev/null +++ b/api/controllers/collection/remove_problems_from_collection.py @@ -0,0 +1,14 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def remove_problems_from_collection(collection:Collection,request): + CollectionProblem.objects.filter(collection=collection,problem_id__in=request.data['problem_ids']).delete() + collection.updated_date = timezone.now() + return Response(status=status.HTTP_204_NO_CONTENT) \ No newline at end of file diff --git a/api/controllers/collection/update_collection.py b/api/controllers/collection/update_collection.py new file mode 100644 index 0000000..ae33e25 --- /dev/null +++ b/api/controllers/collection/update_collection.py @@ -0,0 +1,22 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def update_collection(collection:Collection,request): + + collection.name = request.data.get('name',collection.name) + collection.description = request.data.get('description',collection.description) + collection.is_private = request.data.get('is_private',collection.is_private) + collection.is_active = request.data.get('is_active',collection.is_active) + collection.updated_date = timezone.now() + + collection.save() + collection_ser = CollectionSerializer(collection) + + return Response(collection_ser.data,status=status.HTTP_200_OK) diff --git a/api/controllers/collection/update_group_permissions_collection.py b/api/controllers/collection/update_group_permissions_collection.py new file mode 100644 index 0000000..58577ab --- /dev/null +++ b/api/controllers/collection/update_group_permissions_collection.py @@ -0,0 +1,32 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def update_group_permissions_collection(collection:Collection,request): + + CollectionGroupPermission.objects.filter(collection=collection).delete() + + print(request.data['groups']) + + collection_group_permissions = [] + for collection_request in request.data['groups']: + group = Group.objects.get(group_id=collection_request['group_id']) + collection_group_permissions.append( + CollectionGroupPermission( + collection=collection, + group=group, + **collection_request + )) + + CollectionGroupPermission.objects.bulk_create(collection_group_permissions) + + collection.group_permissions = collection_group_permissions + serialize = CollectionPopulateCollectionGroupPermissionsPopulateGroupSerializer(collection) + + return Response(serialize.data,status=status.HTTP_202_ACCEPTED) \ No newline at end of file diff --git a/api/controllers/collection/update_problems_to_collection.py b/api/controllers/collection/update_problems_to_collection.py new file mode 100644 index 0000000..12fee32 --- /dev/null +++ b/api/controllers/collection/update_problems_to_collection.py @@ -0,0 +1,35 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def update_problems_to_collection(collection:Collection,request): + CollectionProblem.objects.filter(collection=collection).delete() + + collection_problems = [] + order = 0 + for problem_id in request.data['problem_ids']: + problem = Problem.objects.get(problem_id=problem_id) + collection_problem = CollectionProblem( + problem=problem, + collection=collection, + order=order + ) + collection_problems.append(collection_problem) + order += 1 + + CollectionProblem.objects.bulk_create(collection_problems) + collection.updated_date = timezone.now() + collection.save() + problem_serialize = CollectionProblemPopulateProblemSecureSerializer(collection_problems,many=True) + collection_serialize = CollectionSerializer(collection) + + return Response({ + **collection_serialize.data, + 'problems': problem_serialize.data + },status=status.HTTP_201_CREATED) \ No newline at end of file diff --git a/api/controllers/copypasta.py b/api/controllers/copypasta.py new file mode 100644 index 0000000..b625536 --- /dev/null +++ b/api/controllers/copypasta.py @@ -0,0 +1,9 @@ +# from api.utility import passwordEncryption +# from rest_framework.response import Response +# from rest_framework.decorators import api_view +# from api.sandbox.grader import PythonGrader +# from ...constant import GET,POST,PUT,DELETE +# from ...models import * +# from rest_framework import status +# from django.forms.models import model_to_dict +# from ...serializers import * \ No newline at end of file diff --git a/api/controllers/group/create_group.py b/api/controllers/group/create_group.py new file mode 100644 index 0000000..d4e734d --- /dev/null +++ b/api/controllers/group/create_group.py @@ -0,0 +1,24 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def create_group(account:Account,request): + + # print(request.headers["Authorization"]) + + serialize = GroupSerializer(data={ + 'creator':account.account_id, + **request.data + }) + + if serialize.is_valid(): + serialize.save() + return Response(serialize.data,status=status.HTTP_201_CREATED) + else: + return Response(serialize.errors,status=status.HTTP_400_BAD_REQUEST) \ No newline at end of file diff --git a/api/controllers/group/delete_group.py b/api/controllers/group/delete_group.py new file mode 100644 index 0000000..145b084 --- /dev/null +++ b/api/controllers/group/delete_group.py @@ -0,0 +1,13 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def delete_group(group:Group,request): + group.delete() + return Response(status=status.HTTP_204_NO_CONTENT) \ No newline at end of file diff --git a/api/controllers/group/get_all_groups_by_account.py b/api/controllers/group/get_all_groups_by_account.py new file mode 100644 index 0000000..b9b1f05 --- /dev/null +++ b/api/controllers/group/get_all_groups_by_account.py @@ -0,0 +1,28 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_all_groups_by_account(account:Account,request): + + print("GET ALL") + + # Get request headers + headers = request.headers + + groups = Group.objects.filter(creator=account).order_by('-updated_date') + + populate_members = request.GET.get('populate_members',False) + + if populate_members: + for group in groups: + group.members = GroupMember.objects.filter(group=group) + serialize = GroupPopulateGroupMemberPopulateAccountSecureSerializer(groups,many=True) + else: + serialize = GroupSerializer(groups,many=True) + return Response({"groups":serialize.data},status=status.HTTP_200_OK) diff --git a/api/controllers/group/get_group.py b/api/controllers/group/get_group.py new file mode 100644 index 0000000..c506ece --- /dev/null +++ b/api/controllers/group/get_group.py @@ -0,0 +1,20 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_group(group:Group,request): + + populate_members = request.GET.get('populate_members',False) + + if populate_members: + group.members = GroupMember.objects.filter(group=group) + serialize = GroupPopulateGroupMemberPopulateAccountSecureSerializer(group) + else: + serialize = GroupSerializer(group) + return Response(serialize.data,status=status.HTTP_200_OK) diff --git a/api/controllers/group/update_group.py b/api/controllers/group/update_group.py new file mode 100644 index 0000000..80bc9f7 --- /dev/null +++ b/api/controllers/group/update_group.py @@ -0,0 +1,23 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * +from datetime import datetime + +def update_group(group:Group,request): + + serializer = GroupSerializer(group,data={ + **request.data, + 'updated_date': timezone.now() + },partial=True) + + if serializer.is_valid(): + serializer.save() + return Response(serializer.data,status=status.HTTP_200_OK) + else: + return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST) \ No newline at end of file diff --git a/api/controllers/group/update_members_to_group.py b/api/controllers/group/update_members_to_group.py new file mode 100644 index 0000000..99a05cd --- /dev/null +++ b/api/controllers/group/update_members_to_group.py @@ -0,0 +1,26 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def update_members_to_group(group:Group,request): + GroupMember.objects.filter(group=group).delete() + + group_members = [] + for accountId in request.data['account_ids']: + account = Account.objects.get(account_id=accountId) + group_members.append(GroupMember( + group=group, + account=account + )) + + GroupMember.objects.bulk_create(group_members) + group.members = group_members + + serialize = GroupPopulateGroupMemberPopulateAccountSecureSerializer(group) + return Response(serialize.data,status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/problem/create_problem.py b/api/controllers/problem/create_problem.py new file mode 100644 index 0000000..efcf4f6 --- /dev/null +++ b/api/controllers/problem/create_problem.py @@ -0,0 +1,45 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader,RuntimeResult +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def create_problem(account_id:str,request): + account = Account.objects.get(account_id=account_id) + + running_result = PythonGrader(request.data['solution'],request.data['testcases'],1,1.5).generate_output() + + # if not running_result.runnable: + # return Response({'detail': 'Error during creating. Your code may has an error/timeout!','output': running_result.getResult()},status=status.HTTP_406_NOT_ACCEPTABLE) + + problem = Problem( + language = request.data['language'], + creator = account, + title = request.data['title'], + description = request.data['description'], + solution = request.data['solution'], + time_limit = request.data['time_limit'], + allowed_languages = request.data['allowed_languages'], + ) + problem.save() + + testcases_result = [] + for unit in running_result.data: + testcases_result.append( + Testcase( + problem = problem, + input = unit.input, + output = unit.output, + runtime_status = unit.runtime_status + )) + + Testcase.objects.bulk_create(testcases_result) + + problem_serialize = ProblemSerializer(problem) + testcases_serialize = TestcaseSerializer(testcases_result,many=True) + + return Response({**problem_serialize.data,'testcases': testcases_serialize.data},status=status.HTTP_201_CREATED) diff --git a/api/controllers/problem/delete_problem.py b/api/controllers/problem/delete_problem.py new file mode 100644 index 0000000..fe057f1 --- /dev/null +++ b/api/controllers/problem/delete_problem.py @@ -0,0 +1,20 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def delete_problem(problem:Problem): + # try: + # problem = Problem.objects.get(problem_id=problem_id) + # except Problem.DoesNotExist: + # return Response({'detail': "Problem doesn't exist!"},status=status.HTTP_404_NOT_FOUND) + testcases = Testcase.objects.filter(problem_id=problem_id) + + problem.delete() + testcases.delete() + return Response(status=status.HTTP_204_NO_CONTENT) \ No newline at end of file diff --git a/api/controllers/problem/get_all_problem_with_best_submission.py b/api/controllers/problem/get_all_problem_with_best_submission.py new file mode 100644 index 0000000..679fac0 --- /dev/null +++ b/api/controllers/problem/get_all_problem_with_best_submission.py @@ -0,0 +1,30 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_all_problem_with_best_submission(account_id:str): + + problems = Problem.objects.all().order_by('-updated_date') + + for problem in problems: + best_submission = Submission.objects.filter(problem=problem).order_by('-passed_ratio','-submission_id').first() + print(problem.problem_id,problem.title) + if not (best_submission is None): + testcases = SubmissionTestcase.objects.filter(submission=best_submission) + print(testcases) + best_submission.runtime_output = testcases + problem.best_submission = best_submission + else: + problem.best_submission = None + + problem_ser = ProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer(problems,many=True) + return Response({"problems":problem_ser.data},status=status.HTTP_200_OK) + + + # return Response({"problems":problem_ser.data},status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/problem/get_all_problems.py b/api/controllers/problem/get_all_problems.py new file mode 100644 index 0000000..2737a20 --- /dev/null +++ b/api/controllers/problem/get_all_problems.py @@ -0,0 +1,30 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_all_problems(request): + problem = Problem.objects.all() + + get_private = int(request.query_params.get("private",0)) + get_deactive = int(request.query_params.get("deactive",0)) + account_id = str(request.query_params.get("account_id","")) + + if not get_private: + problem = problem.filter(is_private=False) + if not get_deactive: + problem = problem.filter(is_active=True) + if account_id != "": + problem = problem.filter(creator_id=account_id) + + problem = problem.order_by('-problem_id') + + serialize = ProblemPopulateAccountSerializer(problem,many=True) + + return Response({'problems':serialize.data},status=status.HTTP_200_OK) + \ No newline at end of file diff --git a/api/controllers/problem/get_all_problems_by_account.py b/api/controllers/problem/get_all_problems_by_account.py new file mode 100644 index 0000000..d6210d6 --- /dev/null +++ b/api/controllers/problem/get_all_problems_by_account.py @@ -0,0 +1,24 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_all_problems_by_account(account:Account): + personalProblems = Problem.objects.filter(creator=account).order_by('-updated_date') + for problem in personalProblems: + problem.testcases = Testcase.objects.filter(problem=problem,deprecated=False) + + manageableProblems = Problem.objects.filter(problemgrouppermission__permission_manage_problems=True,problemgrouppermission__group__in=GroupMember.objects.filter(account=account).values_list("group",flat=True)).order_by('-updated_date') + for problem in manageableProblems: + problem.testcases = Testcase.objects.filter(problem=problem,deprecated=False) + + # problem_ser = ProblemPopulateTestcaseSerializer(problems,many=True) + personalSerialize = ProblemPopulateTestcaseSerializer(personalProblems,many=True) + manageableSerialize = ProblemPopulateTestcaseSerializer(manageableProblems,many=True) + + return Response({"problems":personalSerialize.data,"manageable_problems":manageableSerialize.data},status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/problem/get_problem.py b/api/controllers/problem/get_problem.py new file mode 100644 index 0000000..0f30ab8 --- /dev/null +++ b/api/controllers/problem/get_problem.py @@ -0,0 +1,27 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_problem(problem:Problem): + # try: + # problem = Problem.objects.get(problem_id=problem_id) + # except Problem.DoesNotExist: + # return Response({'detail': "Problem doesn't exist!"},status=status.HTTP_404_NOT_FOUND) + # testcases = Testcase.objects.filter(problem_id=problem_id,deprecated=False) + # problem_serialize = ProblemPopulateAccountSerializer(problem) + # testcases_serialize = TestcaseSerializer(testcases,many=True) + + problem.testcases = Testcase.objects.filter(problem=problem,deprecated=False) + problem.group_permissions = ProblemGroupPermission.objects.filter(problem=problem) + + serialize = ProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupSerializer(problem) + + + return Response(serialize.data,status=status.HTTP_200_OK) + \ No newline at end of file diff --git a/api/controllers/problem/get_problem_in_topic_with_best_submission.py b/api/controllers/problem/get_problem_in_topic_with_best_submission.py new file mode 100644 index 0000000..d708d21 --- /dev/null +++ b/api/controllers/problem/get_problem_in_topic_with_best_submission.py @@ -0,0 +1,31 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_problem_in_topic_with_best_submission(account_id:str,topic_id:str,problem:int): + + account = Account.objects.get(account_id=account_id) + problem = Problem.objects.get(problem_id=problem) + topic = Topic.objects.get(topic_id=topic_id) + + best_submission = BestSubmission.objects.filter(problem=problem,topic=topic,account=account).first() + # print(problem.problem_id,problem.title) + if not (best_submission is None): + testcases = SubmissionTestcase.objects.filter(submission=best_submission.submission) + print(testcases) + best_submission.runtime_output = testcases + problem.best_submission = best_submission + else: + problem.best_submission = None + + serialize = ProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer(problem) + return Response(serialize.data,status=status.HTTP_200_OK) + + + # return Response({"problems":problem_ser.data},status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/problem/get_problem_public.py b/api/controllers/problem/get_problem_public.py new file mode 100644 index 0000000..8dd5e6a --- /dev/null +++ b/api/controllers/problem/get_problem_public.py @@ -0,0 +1,14 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_problem_public(problem:Problem): + serialize = ProblemPopulateAccountSecureSerializer(problem) + return Response(serialize.data,status=status.HTTP_200_OK) + \ No newline at end of file diff --git a/api/controllers/problem/remove_bulk_problems.py b/api/controllers/problem/remove_bulk_problems.py new file mode 100644 index 0000000..a116836 --- /dev/null +++ b/api/controllers/problem/remove_bulk_problems.py @@ -0,0 +1,16 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def remove_bulk_problems(request): + target = request.data.get("problem",[]) + problems = Problem.objects.filter(problem_id__in=target) + problems.delete() + return Response(status=status.HTTP_204_NO_CONTENT) + \ No newline at end of file diff --git a/api/controllers/problem/update_group_permission_to_problem.py b/api/controllers/problem/update_group_permission_to_problem.py new file mode 100644 index 0000000..7002fda --- /dev/null +++ b/api/controllers/problem/update_group_permission_to_problem.py @@ -0,0 +1,30 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def update_group_permission_to_problem(problem:Problem,request): + ProblemGroupPermission.objects.filter(problem=problem).delete() + + problem_group_permissions = [] + for group_request in request.data['groups']: + group = Group.objects.get(group_id=group_request['group_id']) + problem_group_permissions.append( + ProblemGroupPermission( + problem=problem, + group=group, + **group_request + )) + + ProblemGroupPermission.objects.bulk_create(problem_group_permissions) + + problem.group_permissions = problem_group_permissions + problem.testcases = Testcase.objects.filter(problem=problem) + + serialize = ProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupSerializer(problem) + return Response(serialize.data,status=status.HTTP_202_ACCEPTED) \ No newline at end of file diff --git a/api/controllers/problem/update_problem.py b/api/controllers/problem/update_problem.py new file mode 100644 index 0000000..cd4a1a5 --- /dev/null +++ b/api/controllers/problem/update_problem.py @@ -0,0 +1,63 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * +from django.utils import timezone + +def update_problem(problem:Problem,request): + # try: + # problem = Problem.objects.get(problem_id=problem_id) + # except Problem.DoesNotExist: + # return Response({'detail': "Problem doesn't exist!"},status=status.HTTP_404_NOT_FOUND) + testcases = Testcase.objects.filter(problem=problem,deprecated=False) + + problem.title = request.data.get("title",problem.title) + problem.language = request.data.get("language",problem.language) + problem.description = request.data.get("description",problem.description) + problem.solution = request.data.get("solution",problem.solution) + problem.time_limit = request.data.get("time_limit",problem.time_limit) + problem.is_private = request.data.get("is_private",problem.is_private) + problem.allowed_languages = request.data.get("allowed_languages",problem.allowed_languages) + + problem.updated_date = timezone.now() + + if 'testcases' in request.data: + running_result = PythonGrader(problem.solution,request.data['testcases'],1,1.5).generate_output() + + # if not running_result.runnable: + # return Response({'detail': 'Error during editing. Your code may has an error/timeout!'},status=status.HTTP_406_NOT_ACCEPTABLE) + for testcase in testcases: + testcase.deprecated = True + testcase.save() + testcase_result = [] + for unit in running_result.data: + testcase2 = Testcase( + problem = problem, + input = unit.input, + output = unit.output, + runtime_status = unit.runtime_status + ) + testcase2.save() + testcase_result.append(testcase2) + problem.save() + problem_serialize = ProblemSerializer(problem) + testcases_serialize = TestcaseSerializer(testcase_result,many=True) + + return Response({**problem_serialize.data,'testcases': testcases_serialize.data},status=status.HTTP_201_CREATED) + + if 'solution' in request.data: + testcases = Testcase.objects.filter(problem=problem,deprecated=False) + program_input = [i.input for i in testcases] + running_result = PythonGrader(problem.solution,program_input,1,1.5).generate_output() + + if not running_result.runnable: + return Response({'detail': 'Error during editing. Your code may has an error/timeout!'},status=status.HTTP_406_NOT_ACCEPTABLE) + + problem.save() + problem_serialize = ProblemSerializer(problem) + return Response(problem_serialize.data,status=status.HTTP_201_CREATED) diff --git a/api/controllers/problem/validate_program.py b/api/controllers/problem/validate_program.py new file mode 100644 index 0000000..d8298e8 --- /dev/null +++ b/api/controllers/problem/validate_program.py @@ -0,0 +1,23 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import Grader,ProgramGrader,RuntimeResultList +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def validate_program(request): + grader:ProgramGrader = Grader[request.data['language']] + result:RuntimeResultList = grader(request.data['source_code'],request.data['testcases'],1,request.data['time_limited']).generate_output() + + print(result.getResult()) + print(result.runnable) + + return Response({ + 'runnable': result.runnable, + 'has_error': result.has_error, + 'has_timeout': result.has_timeout, + 'runtime_results': result.getResult(), + },status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/script/generate_failed_submission_status.py b/api/controllers/script/generate_failed_submission_status.py new file mode 100644 index 0000000..7370b9f --- /dev/null +++ b/api/controllers/script/generate_failed_submission_status.py @@ -0,0 +1,21 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict + +def generate_failed_submission_status(request): + submissionTestcases = SubmissionTestcase.objects.all() + + total = len(submissionTestcases) + count = 0 + for testcase in submissionTestcases: + if testcase.runtime_status == "OK" and (not testcase.is_passed): + testcase.runtime_status = "FAILED" + testcase.save() + count += 1 + + print(f"({count}/{total})") + return Response({'message': 'Success!'},status=status.HTTP_201_CREATED) diff --git a/api/controllers/script/generate_submission_score.py b/api/controllers/script/generate_submission_score.py new file mode 100644 index 0000000..dad390f --- /dev/null +++ b/api/controllers/script/generate_submission_score.py @@ -0,0 +1,20 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict + +def generate_submission_score(request): + submissions = Submission.objects.all() + total = len(submissions) + count = 0 + for submission in submissions: + submission.score = submission.result.count('P') + submission.max_score = len(submission.result) + submission.passed_ratio = submission.score/submission.max_score + submission.save() + count += 1 + print(f"({count}/{total})") + return Response({'message': 'Success!'},status=status.HTTP_201_CREATED) \ No newline at end of file diff --git a/api/controllers/script/replace_collections_empty_description.py b/api/controllers/script/replace_collections_empty_description.py new file mode 100644 index 0000000..1dc31e8 --- /dev/null +++ b/api/controllers/script/replace_collections_empty_description.py @@ -0,0 +1,14 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict + +def replace_collections_empty_description(request): + collections = Collection.objects.all() + for collection in collections: + collection.description = '[{"id":"1","type":"p","children":[{"text":"Just course"}]}]' + collection.save() + return Response({'message': 'Success!'},status=status.HTTP_201_CREATED) diff --git a/api/controllers/script/replace_topic_empty_description.py b/api/controllers/script/replace_topic_empty_description.py new file mode 100644 index 0000000..e1fc519 --- /dev/null +++ b/api/controllers/script/replace_topic_empty_description.py @@ -0,0 +1,18 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict + +def replace_topic_empty_description(request): + topics = Topic.objects.all() + for topic in topics: + if len(topic.description) == 0: + topic.description = f'[{{"id": "1","type": ELEMENT_PARAGRAPH,"children": [{{ "text": "" }}]}}]' + topic.save() + elif topic.description[0] != '[': + topic.description = f'[{{"id": "1","type": ELEMENT_PARAGRAPH,"children": [{{ "text": "{topic.description}" }}]}}]' + topic.save() + return Response({'message': 'Success!'},status=status.HTTP_201_CREATED) \ No newline at end of file diff --git a/api/controllers/submission/get_submission_by_quries.py b/api/controllers/submission/get_submission_by_quries.py new file mode 100644 index 0000000..7fb5401 --- /dev/null +++ b/api/controllers/submission/get_submission_by_quries.py @@ -0,0 +1,53 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_submission_by_quries(request): + submissions = Submission.objects.all() + + # Query params + problem_id = str(request.query_params.get("problem_id", "")) + account_id = str(request.query_params.get("account_id", "")) + topic_id = str(request.query_params.get("topic_id", "")) + passed = int(request.query_params.get("passed", -1)) + sort_score = int(request.query_params.get("sort_score", 0)) + sort_date = int(request.query_params.get("sort_date", 0)) + start = int(request.query_params.get("start", -1)) + end = int(request.query_params.get("end", -1)) + + if problem_id != "": + submissions = submissions.filter(problem_id=problem_id) + if account_id != "": + submissions = submissions.filter(account_id=account_id) + if topic_id != "": + submissions = submissions.filter(problem__topic_id=topic_id) + + if passed == 0: + submissions = submissions.filter(is_passed=False) + elif passed == 1: + submissions = submissions.filter(is_passed=True) + + if sort_score == -1: + submissions = submissions.order_by('passed_ratio') + elif sort_score == 1: + submissions = submissions.order_by('-passed_ratio') + + if sort_date == -1: + submissions = submissions.order_by('date') + elif sort_date == 1: + submissions = submissions.order_by('-date') + + if start != -1 and end != -1: + submissions = submissions[start:end] + + for submission in submissions: + submission.runtime_output = SubmissionTestcase.objects.filter(submission=submission) + + serialize = SubmissionPopulateSubmissionTestcaseAndProblemSecureSerializer(submissions,many=True) + return Response({"submissions": serialize.data},status=status.HTTP_200_OK) diff --git a/api/controllers/submission/get_submissions_by_account_problem.py b/api/controllers/submission/get_submissions_by_account_problem.py new file mode 100644 index 0000000..7c98e32 --- /dev/null +++ b/api/controllers/submission/get_submissions_by_account_problem.py @@ -0,0 +1,35 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_submissions_by_account_problem(account_id:str,problem_id:str): + submissions = Submission.objects.filter(account=account_id,problem=problem_id) + + if submissions.count() == 0: + return Response({"best_submission": None,"submissions": []},status=status.HTTP_204_NO_CONTENT) + + submissions = submissions.order_by('-date') + + best_submission_id = submissions.order_by('-passed_ratio','-date').first().submission_id + + best_submission = None + result = [] + + for submission in submissions: + submission_testcases = SubmissionTestcase.objects.filter(submission=submission) + submission.runtime_output = submission_testcases + result.append(submission) + + if submission.submission_id == best_submission_id: + best_submission = submission + + best_submission_serializer = SubmissionPopulateSubmissionTestcaseSecureSerializer(best_submission) + submissions_serializer = SubmissionPopulateSubmissionTestcaseSecureSerializer(result,many=True) + + return Response({"best_submission": best_submission_serializer.data,"submissions": submissions_serializer.data},status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/submission/get_submissions_by_account_problem_in_topic.py b/api/controllers/submission/get_submissions_by_account_problem_in_topic.py new file mode 100644 index 0000000..5c96f49 --- /dev/null +++ b/api/controllers/submission/get_submissions_by_account_problem_in_topic.py @@ -0,0 +1,36 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_submissions_by_account_problem_in_topic(account_id:str,problem_id:str,topic_id:str): + submissions = Submission.objects.filter(account=account_id,problem=problem_id,topic_id=topic_id) + + if submissions.count() == 0: + return Response({"best_submission": None,"submissions": []},status=status.HTTP_204_NO_CONTENT) + + submissions = submissions.order_by('-date') + + result = [] + + for submission in submissions: + submission_testcases = SubmissionTestcase.objects.filter(submission=submission) + submission.runtime_output = submission_testcases + result.append(submission) + + best_submission = BestSubmission.objects.filter(problem=problem_id,topic=topic_id,account=account_id).first() + if best_submission: + best_submission.submission.runtime_output = SubmissionTestcase.objects.filter(submission=best_submission.submission) + best_submission_serializer = SubmissionPopulateSubmissionTestcaseSecureSerializer(best_submission.submission) + best_submission_result = best_submission_serializer.data + else: + best_submission_result = None + + submissions_serializer = SubmissionPopulateSubmissionTestcaseSecureSerializer(result,many=True) + + return Response({"best_submission": best_submission_result,"submissions": submissions_serializer.data},status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/submission/submit_problem.py b/api/controllers/submission/submit_problem.py new file mode 100644 index 0000000..9d1e9be --- /dev/null +++ b/api/controllers/submission/submit_problem.py @@ -0,0 +1,105 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader,Grader,ProgramGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * +from ...utility import regexMatching +from time import sleep + +QUEUE = [0,0,0,0,0,0,0,0,0,0] + +def avaliableQueue(): + global QUEUE + for i in range(len(QUEUE)): + if QUEUE[i] == 0: + return i + return -1 + +def submit_problem_function(account_id:str,problem_id:str,topic_id:str,request): + global QUEUE + problem = Problem.objects.get(problem_id=problem_id) + testcases = Testcase.objects.filter(problem=problem,deprecated=False) + account = Account.objects.get(account_id=account_id) + + submission_code = request.data['submission_code'] + solution_input = [model_to_dict(i)['input'] for i in testcases] + solution_output = [model_to_dict(i)['output'] for i in testcases] + + if not regexMatching(problem.submission_regex,submission_code): + grading_result = '-'*len(solution_input) + else: + empty_queue = avaliableQueue() + while empty_queue == -1: + empty_queue = avaliableQueue() + sleep(5) + + QUEUE[empty_queue] = 1 + # grading_result = grader.grading(empty_queue+1,submission_code,solution_input,solution_output) + grader: ProgramGrader = Grader[request.data['language']] + grading_result = grader(submission_code,solution_input,empty_queue+1,1.5).grading(solution_output) + QUEUE[empty_queue] = 0 + + total_score = sum([i.is_passed for i in grading_result.data if i.is_passed]) + max_score = len(grading_result.data) + + submission = Submission( + problem = problem, + account = account, + language = request.data['language'], + submission_code = request.data['submission_code'], + is_passed = grading_result.is_passed, + score = total_score, + max_score = max_score, + passed_ratio = total_score/max_score + ) + + if topic_id: + submission.topic = Topic.objects.get(topic_id=topic_id) + + submission.save() + + # Best Submission + try: + best_submission = None + if topic_id: + best_submission = BestSubmission.objects.get(problem=problem,account=account,topic=Topic.objects.get(topic_id=topic_id)) + else: + best_submission = BestSubmission.objects.get(problem=problem,account=account) + except: + best_submission = BestSubmission( + problem = problem, + account = account, + topic = Topic.objects.get(topic_id=topic_id) if topic_id else None, + submission = submission + ) + best_submission.save() + else: + if submission.passed_ratio >= best_submission.submission.passed_ratio: + best_submission.submission = submission + best_submission.save() + + # End Best Submission + + submission_testcases = [] + for i in range(len(grading_result.data)): + submission_testcases.append(SubmissionTestcase( + submission = submission, + testcase = testcases[i], + output = grading_result.data[i].output, + is_passed = grading_result.data[i].is_passed, + runtime_status = grading_result.data[i].runtime_status + )) + + SubmissionTestcase.objects.bulk_create(submission_testcases) + + submission.runtime_output = submission_testcases + testser = SubmissionPopulateSubmissionTestcaseSecureSerializer(submission) + + return Response(testser.data,status=status.HTTP_201_CREATED) + +def submit_problem(account_id:str,problem_id:str,request): + return submit_problem_function(account_id,problem_id,None,request) \ No newline at end of file diff --git a/api/controllers/submission/submit_problem_on_topic.py b/api/controllers/submission/submit_problem_on_topic.py new file mode 100644 index 0000000..5d7d93f --- /dev/null +++ b/api/controllers/submission/submit_problem_on_topic.py @@ -0,0 +1,15 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader,Grader,ProgramGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * +from ...utility import regexMatching +from time import sleep +from .submit_problem import * + +def submit_problem_on_topic(account_id:str,problem_id:str,topic_id:str,request): + return submit_problem_function(account_id,problem_id,topic_id,request) \ No newline at end of file diff --git a/api/controllers/topic/add_collections_to_topic.py b/api/controllers/topic/add_collections_to_topic.py new file mode 100644 index 0000000..936e05f --- /dev/null +++ b/api/controllers/topic/add_collections_to_topic.py @@ -0,0 +1,36 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def add_collections_to_topic(topic_id:str,request): + topic = Topic.objects.get(topic_id=topic_id) + populated_collections = [] + + index = 0 + for collection_id in request.data['collection_ids']: + collection = Collection.objects.get(collection_id=collection_id) + + alreadyExist = TopicCollection.objects.filter(topic_id=topic.topic_id,collection_id=collection.collection_id) + if alreadyExist: + alreadyExist.delete() + + topicCollection = TopicCollection( + topic=topic, + collection=collection, + order=index + ) + topicCollection.save() + index += 1 + tc_serialize = TopicCollectionSerializer(topicCollection) + populated_collections.append(tc_serialize.data) + + return Response({ + **TopicSerializer(topic).data, + "collections": populated_collections + },status=status.HTTP_201_CREATED) diff --git a/api/controllers/topic/create_topic.py b/api/controllers/topic/create_topic.py new file mode 100644 index 0000000..12557ce --- /dev/null +++ b/api/controllers/topic/create_topic.py @@ -0,0 +1,19 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def create_topic(account_id:str,request): + request.data._mutable=True + request.data['creator'] = account_id + serializer = TopicSerializer(data=request.data) + + if serializer.is_valid(): + serializer.save() + return Response(serializer.data,status=status.HTTP_201_CREATED) + return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST) diff --git a/api/controllers/topic/delete_topic.py b/api/controllers/topic/delete_topic.py new file mode 100644 index 0000000..622c052 --- /dev/null +++ b/api/controllers/topic/delete_topic.py @@ -0,0 +1,13 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def delete_topic(topic:Topic): + topic.delete() + return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/api/controllers/topic/get_all_accessed_topics_by_account.py b/api/controllers/topic/get_all_accessed_topics_by_account.py new file mode 100644 index 0000000..8d6cd87 --- /dev/null +++ b/api/controllers/topic/get_all_accessed_topics_by_account.py @@ -0,0 +1,23 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * +from django.db.models import Q + +def get_all_accessed_topics_by_account(account:Account): + groups = [gm.group for gm in GroupMember.objects.filter(account=account)] + accessedTopics = TopicGroupPermission.objects.filter(Q(group__in=groups) & (Q(permission_view_topics=True) | Q(permission_manage_topics=True))) + + topics = [] + for at in accessedTopics: + if at.topic not in topics: + topics.append(at.topic) + + serialize = TopicSerializer(topics,many=True) + + return Response({'topics':serialize.data},status=status.HTTP_200_OK) diff --git a/api/controllers/topic/get_all_topics.py b/api/controllers/topic/get_all_topics.py new file mode 100644 index 0000000..9c149f5 --- /dev/null +++ b/api/controllers/topic/get_all_topics.py @@ -0,0 +1,23 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_all_topics(request): + topics = Topic.objects.all() + + account_id = request.query_params.get('account_id',0) + + if account_id: + topics = topics.filter(creator_id=account_id) + + serializer = TopicSerializer(topics,many=True) + + return Response({ + 'topics': serializer.data + },status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/topic/get_all_topics_by_account.py b/api/controllers/topic/get_all_topics_by_account.py new file mode 100644 index 0000000..417424f --- /dev/null +++ b/api/controllers/topic/get_all_topics_by_account.py @@ -0,0 +1,32 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def populated_collections(topics:Topic): + topicCollections = TopicCollection.objects.filter(topic__in=topics) + populated_topics = [] + for topic in topics: + topic.collections = topicCollections.filter(topic=topic) + populated_topics.append(topic) + return populated_topics + +def get_all_topics_by_account(account:Account,request): + personalTopics = Topic.objects.filter(creator=account).order_by('-updated_date') + populatedPersonalTopics = populated_collections(personalTopics) + personalSerialize = TopicPopulateTopicCollectionPopulateCollectionSerializer(populatedPersonalTopics,many=True) + + # print(GroupMember.objects.all().values_list("group",flat=True)) + manageableTopics = Topic.objects.filter(topicgrouppermission__permission_manage_topics=True,topicgrouppermission__group__in=GroupMember.objects.filter(account=account).values_list("group",flat=True)).order_by('-updated_date') + populatedmanageableTopics = populated_collections(manageableTopics) + manageableSerialize = TopicPopulateTopicCollectionPopulateCollectionSerializer(populatedmanageableTopics,many=True) + + return Response({ + 'topics': personalSerialize.data, + 'manageable_topics': manageableSerialize.data + },status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/topic/get_topic.py b/api/controllers/topic/get_topic.py new file mode 100644 index 0000000..53f6e86 --- /dev/null +++ b/api/controllers/topic/get_topic.py @@ -0,0 +1,54 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def get_topic(topic:Topic): + topic.group_permissions = TopicGroupPermission.objects.filter(topic=topic) + + topic.collections = TopicCollection.objects.filter(topic=topic).order_by('order') + + for tp in topic.collections: + tp.collection.problems = CollectionProblem.objects.filter(collection=tp.collection) + tp.collection.group_permissions = CollectionGroupPermission.objects.filter(collection=tp.collection) + + serialize = TopicPopulateTopicCollectionPopulateCollectionPopulateCollectionProblemsPopulateProblemAndCollectionGroupPermissionsPopulateGroupAndTopicGroupPermissionPopulateGroupSerializer(topic) + + return Response(serialize.data,status=status.HTTP_200_OK) + + + + # topic = Topic.objects.get(topic_id=topic_id) + # topicCollections = TopicCollection.objects.filter(topic_id=topic_id) + # # accessedAccounts = Account.objects.filter(topicaccountaccess__topic_id=topic_id) + + # topic_ser = TopicSerializer(topic) + # populate_collections = [] + + # for top_col in topicCollections: + # collection_serialize = CollectionSerializer(top_col.collection) + # collection_data = collection_serialize.data + + # populate_problems = [] + # collection_problems = CollectionProblem.objects.filter(collection=top_col.collection) + # for col_prob in collection_problems: + # prob_serialize = ProblemSerializer(col_prob.problem) + # col_prob_serialize = CollectionProblemSerializer(col_prob) + # populate_problems.append({**col_prob_serialize.data,**prob_serialize.data}) + + # collection_data['problems'] = populate_problems + # top_col_serialize = TopicCollectionSerializer(top_col) + # populate_collections.append({**top_col_serialize.data,**collection_data}) + + # # accessedAccountsSerialize = AccountSecureSerializer(accessedAccounts,many=True) + + # return Response({ + # **topic_ser.data, + # "collections": sorted(populate_collections,key=lambda collection: collection['order']), + # # "accessed_accounts": accessedAccountsSerialize.data + # },status=status.HTTP_200_OK) \ No newline at end of file diff --git a/api/controllers/topic/get_topic_public.py b/api/controllers/topic/get_topic_public.py new file mode 100644 index 0000000..36476b2 --- /dev/null +++ b/api/controllers/topic/get_topic_public.py @@ -0,0 +1,61 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * +from django.db.models import Q + +def get_topic_public(topic_id:str,request): + + account_id = request.query_params.get('account_id',None) + + topic = Topic.objects.get(topic_id=topic_id) + account = Account.objects.get(account_id=account_id) + + + topicCollections = TopicCollection.objects.filter( + topic=topic, + collection__in= + CollectionGroupPermission.objects.filter( + Q(group__in=GroupMember.objects.filter(account=account).values_list("group",flat=True)) & + ( + Q(permission_view_collections=True) | Q(permission_manage_collections=True) + ) + ).values_list("collection",flat=True)) + + for tp in topicCollections: + # tp.collection.problems = CollectionProblem.objects.filter(collection=tp.collection) + + # viewPermission = CollectionGroupPermission.objects.filter(collection=tp.collection,group__in=GroupMember.objects.filter(account=account).values_list("group",flat=True),permission_view_collections=True) + # print(len(viewPermission)) + # if len(viewPermission) == 0: + # tp.collection.problems = [] + # continue + collectionProblems = CollectionProblem.objects.filter( + collection=tp.collection, + problem__in=ProblemGroupPermission.objects.filter( + Q(group__in=GroupMember.objects.filter(account=account).values_list("group",flat=True)) & + (Q(permission_view_problems=True) | + Q(permission_manage_problems=True)) + ).values_list("problem",flat=True)) + + for cp in collectionProblems: + try: + best_submission = BestSubmission.objects.get(problem=cp.problem,account=account,topic=topic) + best_submission = best_submission.submission + best_submission.runtime_output = SubmissionTestcase.objects.filter(submission=best_submission) + except: + best_submission = None + cp.problem.best_submission = best_submission + + tp.collection.problems = collectionProblems + + topic.collections = topicCollections + + serialize = TopicPopulateTopicCollectionPopulateCollectionPopulateCollectionProblemPopulateProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer(topic) + + return Response(serialize.data,status=status.HTTP_200_OK) diff --git a/api/controllers/topic/remove_collections_from_topic.py b/api/controllers/topic/remove_collections_from_topic.py new file mode 100644 index 0000000..74ac26e --- /dev/null +++ b/api/controllers/topic/remove_collections_from_topic.py @@ -0,0 +1,16 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def remove_collections_from_topic(topic_id:str,request): + TopicCollection.objects.filter(topic_id=topic_id,collection_id__in=request.data['collection_ids']).delete() + # collections = Collection.objects.filter(collection_id__in=request.data['collection_ids']) + # problems = Problem.objects.filter(problem_id__in=request.data['problems_id']) + # TopicProblem.objects.filter(topic_id=topic,problem_id__in=problems).delete() + return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/api/controllers/topic/update_collections_to_topic.py b/api/controllers/topic/update_collections_to_topic.py new file mode 100644 index 0000000..4bb3e81 --- /dev/null +++ b/api/controllers/topic/update_collections_to_topic.py @@ -0,0 +1,36 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def update_collections_to_topic(topic:Topic,request): + TopicCollection.objects.filter(topic=topic).delete() + + topic_collections = [] + order = 0 + for collection_id in request.data['collection_ids']: + collection = Collection.objects.get(collection_id=collection_id) + topic_collection = TopicCollection( + collection=collection, + topic=topic, + order=order + ) + topic_collections.append(topic_collection) + order += 1 + + TopicCollection.objects.bulk_create(topic_collections) + topic.updated_date = timezone.now() + topic.save() + + collection_serialize = TopicCollectionPopulateCollectionSerializer(topic_collections,many=True) + topic_serialize = TopicSerializer(topic) + + return Response({ + **topic_serialize.data, + 'collections': collection_serialize.data + },status=status.HTTP_201_CREATED) \ No newline at end of file diff --git a/api/controllers/topic/update_groups_permission_to_topic.py b/api/controllers/topic/update_groups_permission_to_topic.py new file mode 100644 index 0000000..608791b --- /dev/null +++ b/api/controllers/topic/update_groups_permission_to_topic.py @@ -0,0 +1,31 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def update_groups_permission_to_topic(topic:Topic,request): + + TopicGroupPermission.objects.filter(topic=topic).delete() + + topic_group_permissions = [] + for group_request in request.data['groups']: + print(group_request) + group = Group.objects.get(group_id=group_request['group_id']) + topic_group_permissions.append( + TopicGroupPermission( + topic=topic, + group=group, + **group_request + )) + + TopicGroupPermission.objects.bulk_create(topic_group_permissions) + + topic.group_permissions = topic_group_permissions + serialize = TopicPopulateTopicGroupPermissionsSerializer(topic) + + return Response(serialize.data,status=status.HTTP_202_ACCEPTED) \ No newline at end of file diff --git a/api/controllers/topic/update_topic.py b/api/controllers/topic/update_topic.py new file mode 100644 index 0000000..1d95c9f --- /dev/null +++ b/api/controllers/topic/update_topic.py @@ -0,0 +1,18 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ...constant import GET,POST,PUT,DELETE +from ...models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ...serializers import * + +def update_topic(topic:Topic,request): + topic_ser = TopicSerializer(topic,data=request.data,partial=True) + if topic_ser.is_valid(): + topic_ser.save() + return Response(topic_ser.data,status=status.HTTP_200_OK) + print(topic_ser.errors) + return Response(topic_ser.errors,status=status.HTTP_400_BAD_REQUEST) + \ No newline at end of file diff --git a/api/migrations/0029_remove_account_is_admin_remove_collection_owner_and_more.py b/api/migrations/0029_remove_account_is_admin_remove_collection_owner_and_more.py new file mode 100644 index 0000000..94d36f3 --- /dev/null +++ b/api/migrations/0029_remove_account_is_admin_remove_collection_owner_and_more.py @@ -0,0 +1,48 @@ +# Generated by Django 4.1.2 on 2023-11-24 05:23 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0028_alter_problem_language'), + ] + + operations = [ + migrations.RemoveField( + model_name='account', + name='is_admin', + ), + migrations.RemoveField( + model_name='collection', + name='owner', + ), + migrations.RemoveField( + model_name='problem', + name='account', + ), + migrations.RemoveField( + model_name='topic', + name='account', + ), + migrations.AddField( + model_name='collection', + name='creator', + field=models.ForeignKey(db_column='creator_id', default=4, on_delete=django.db.models.deletion.CASCADE, to='api.account'), + preserve_default=False, + ), + migrations.AddField( + model_name='problem', + name='creator', + field=models.ForeignKey(db_column='creator_id', default=4, on_delete=django.db.models.deletion.CASCADE, to='api.account'), + preserve_default=False, + ), + migrations.AddField( + model_name='topic', + name='creator', + field=models.ForeignKey(db_column='creator_id', default=4, on_delete=django.db.models.deletion.CASCADE, to='api.account'), + preserve_default=False, + ), + ] diff --git a/api/migrations/0030_testcase_runtime_status.py b/api/migrations/0030_testcase_runtime_status.py new file mode 100644 index 0000000..e3f7f56 --- /dev/null +++ b/api/migrations/0030_testcase_runtime_status.py @@ -0,0 +1,19 @@ +# Generated by Django 4.1.2 on 2023-12-02 08:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0029_remove_account_is_admin_remove_collection_owner_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='testcase', + name='runtime_status', + field=models.CharField(default='OK', max_length=10), + preserve_default=False, + ), + ] diff --git a/api/migrations/0031_problem_created_date_problem_updated_date.py b/api/migrations/0031_problem_created_date_problem_updated_date.py new file mode 100644 index 0000000..1e59ee1 --- /dev/null +++ b/api/migrations/0031_problem_created_date_problem_updated_date.py @@ -0,0 +1,24 @@ +# Generated by Django 4.1.2 on 2023-12-02 17:00 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0030_testcase_runtime_status'), + ] + + operations = [ + migrations.AddField( + model_name='problem', + name='created_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AddField( + model_name='problem', + name='updated_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/api/migrations/0032_submission_language.py b/api/migrations/0032_submission_language.py new file mode 100644 index 0000000..2b040a3 --- /dev/null +++ b/api/migrations/0032_submission_language.py @@ -0,0 +1,19 @@ +# Generated by Django 4.1.2 on 2023-12-03 13:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0031_problem_created_date_problem_updated_date'), + ] + + operations = [ + migrations.AddField( + model_name='submission', + name='language', + field=models.CharField(default='python', max_length=15), + preserve_default=False, + ), + ] diff --git a/api/migrations/0033_alter_submissiontestcase_testcase.py b/api/migrations/0033_alter_submissiontestcase_testcase.py new file mode 100644 index 0000000..cd38403 --- /dev/null +++ b/api/migrations/0033_alter_submissiontestcase_testcase.py @@ -0,0 +1,19 @@ +# Generated by Django 4.1.2 on 2023-12-10 03:59 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0032_submission_language'), + ] + + operations = [ + migrations.AlterField( + model_name='submissiontestcase', + name='testcase', + field=models.ForeignKey(db_column='testcase_id', null=True, on_delete=django.db.models.deletion.SET_NULL, to='api.testcase'), + ), + ] diff --git a/api/migrations/0034_alter_submissiontestcase_testcase.py b/api/migrations/0034_alter_submissiontestcase_testcase.py new file mode 100644 index 0000000..8ad6b26 --- /dev/null +++ b/api/migrations/0034_alter_submissiontestcase_testcase.py @@ -0,0 +1,20 @@ +# Generated by Django 4.1.2 on 2023-12-10 04:00 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0033_alter_submissiontestcase_testcase'), + ] + + operations = [ + migrations.AlterField( + model_name='submissiontestcase', + name='testcase', + field=models.ForeignKey(db_column='testcase_id', default=1, on_delete=django.db.models.deletion.CASCADE, to='api.testcase'), + preserve_default=False, + ), + ] diff --git a/api/migrations/0035_testcase_depricated.py b/api/migrations/0035_testcase_depricated.py new file mode 100644 index 0000000..098108d --- /dev/null +++ b/api/migrations/0035_testcase_depricated.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.2 on 2023-12-11 09:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0034_alter_submissiontestcase_testcase'), + ] + + operations = [ + migrations.AddField( + model_name='testcase', + name='depricated', + field=models.BooleanField(blank=True, default=False), + ), + ] diff --git a/api/migrations/0036_rename_depricated_testcase_deprecated.py b/api/migrations/0036_rename_depricated_testcase_deprecated.py new file mode 100644 index 0000000..fb93e28 --- /dev/null +++ b/api/migrations/0036_rename_depricated_testcase_deprecated.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.2 on 2023-12-11 09:26 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0035_testcase_depricated'), + ] + + operations = [ + migrations.RenameField( + model_name='testcase', + old_name='depricated', + new_name='deprecated', + ), + ] diff --git a/api/migrations/0037_alter_testcase_output.py b/api/migrations/0037_alter_testcase_output.py new file mode 100644 index 0000000..3f7f773 --- /dev/null +++ b/api/migrations/0037_alter_testcase_output.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.2 on 2023-12-12 06:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0036_rename_depricated_testcase_deprecated'), + ] + + operations = [ + migrations.AlterField( + model_name='testcase', + name='output', + field=models.CharField(max_length=100000, null=True), + ), + ] diff --git a/api/migrations/0038_collection_created_date_collection_updated_date.py b/api/migrations/0038_collection_created_date_collection_updated_date.py new file mode 100644 index 0000000..4fa8a37 --- /dev/null +++ b/api/migrations/0038_collection_created_date_collection_updated_date.py @@ -0,0 +1,24 @@ +# Generated by Django 4.1.2 on 2023-12-14 07:52 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0037_alter_testcase_output'), + ] + + operations = [ + migrations.AddField( + model_name='collection', + name='created_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AddField( + model_name='collection', + name='updated_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/api/migrations/0039_topic_created_date_topic_updated_date.py b/api/migrations/0039_topic_created_date_topic_updated_date.py new file mode 100644 index 0000000..04d4abb --- /dev/null +++ b/api/migrations/0039_topic_created_date_topic_updated_date.py @@ -0,0 +1,24 @@ +# Generated by Django 4.1.2 on 2023-12-16 04:27 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0038_collection_created_date_collection_updated_date'), + ] + + operations = [ + migrations.AddField( + model_name='topic', + name='created_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AddField( + model_name='topic', + name='updated_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/api/migrations/0040_submission_topic.py b/api/migrations/0040_submission_topic.py new file mode 100644 index 0000000..a22e553 --- /dev/null +++ b/api/migrations/0040_submission_topic.py @@ -0,0 +1,19 @@ +# Generated by Django 4.1.2 on 2023-12-19 05:21 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0039_topic_created_date_topic_updated_date'), + ] + + operations = [ + migrations.AddField( + model_name='submission', + name='topic', + field=models.ForeignKey(db_column='topic_id', null=True, on_delete=django.db.models.deletion.CASCADE, to='api.topic'), + ), + ] diff --git a/api/migrations/0041_bestsubmission.py b/api/migrations/0041_bestsubmission.py new file mode 100644 index 0000000..b50c3db --- /dev/null +++ b/api/migrations/0041_bestsubmission.py @@ -0,0 +1,24 @@ +# Generated by Django 4.1.2 on 2023-12-19 08:49 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0040_submission_topic'), + ] + + operations = [ + migrations.CreateModel( + name='BestSubmission', + fields=[ + ('best_submission_id', models.AutoField(primary_key=True, serialize=False)), + ('account', models.ForeignKey(db_column='account_id', on_delete=django.db.models.deletion.CASCADE, to='api.account')), + ('problem', models.ForeignKey(db_column='problem_id', on_delete=django.db.models.deletion.CASCADE, to='api.problem')), + ('submission', models.ForeignKey(db_column='submission_id', on_delete=django.db.models.deletion.CASCADE, to='api.submission')), + ('topic', models.ForeignKey(db_column='topic_id', null=True, on_delete=django.db.models.deletion.CASCADE, to='api.topic')), + ], + ), + ] diff --git a/api/migrations/0042_alter_collection_description_and_more.py b/api/migrations/0042_alter_collection_description_and_more.py new file mode 100644 index 0000000..8912bbd --- /dev/null +++ b/api/migrations/0042_alter_collection_description_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 4.1.2 on 2023-12-20 08:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0041_bestsubmission'), + ] + + operations = [ + migrations.AlterField( + model_name='collection', + name='description', + field=models.CharField(blank=True, default=None, max_length=100000, null=True), + ), + migrations.AlterField( + model_name='problem', + name='description', + field=models.CharField(max_length=100000), + ), + migrations.AlterField( + model_name='topic', + name='description', + field=models.CharField(blank=True, default=None, max_length=100000, null=True), + ), + ] diff --git a/api/migrations/0043_group_groupmember.py b/api/migrations/0043_group_groupmember.py new file mode 100644 index 0000000..68b0739 --- /dev/null +++ b/api/migrations/0043_group_groupmember.py @@ -0,0 +1,34 @@ +# Generated by Django 4.1.2 on 2023-12-25 11:30 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0042_alter_collection_description_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='Group', + fields=[ + ('group_id', models.AutoField(primary_key=True, serialize=False)), + ('name', models.CharField(max_length=100)), + ('description', models.CharField(blank=True, default=None, max_length=100000, null=True)), + ('creator', models.ForeignKey(db_column='creator_id', on_delete=django.db.models.deletion.CASCADE, to='api.account')), + ], + ), + migrations.CreateModel( + name='GroupMember', + fields=[ + ('group_member_id', models.AutoField(primary_key=True, serialize=False)), + ('created_date', models.DateTimeField(default=django.utils.timezone.now)), + ('updated_date', models.DateTimeField(default=django.utils.timezone.now)), + ('account', models.ForeignKey(db_column='account_id', on_delete=django.db.models.deletion.CASCADE, to='api.account')), + ('group', models.ForeignKey(db_column='group_id', on_delete=django.db.models.deletion.CASCADE, to='api.group')), + ], + ), + ] diff --git a/api/migrations/0044_remove_groupmember_updated_date_group_color_and_more.py b/api/migrations/0044_remove_groupmember_updated_date_group_color_and_more.py new file mode 100644 index 0000000..1a32570 --- /dev/null +++ b/api/migrations/0044_remove_groupmember_updated_date_group_color_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 4.1.2 on 2023-12-25 11:55 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0043_group_groupmember'), + ] + + operations = [ + migrations.RemoveField( + model_name='groupmember', + name='updated_date', + ), + migrations.AddField( + model_name='group', + name='color', + field=models.CharField(blank=True, default=None, max_length=10, null=True), + ), + migrations.AddField( + model_name='group', + name='created_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AddField( + model_name='group', + name='updated_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/api/migrations/0045_collection_sharing_and_more.py b/api/migrations/0045_collection_sharing_and_more.py new file mode 100644 index 0000000..ccd65f3 --- /dev/null +++ b/api/migrations/0045_collection_sharing_and_more.py @@ -0,0 +1,95 @@ +# Generated by Django 4.1.2 on 2023-12-30 13:02 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0044_remove_groupmember_updated_date_group_color_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='collection', + name='sharing', + field=models.BooleanField(blank=True, default=False), + ), + migrations.AddField( + model_name='group', + name='permission_manage_collections', + field=models.BooleanField(blank=True, default=False), + ), + migrations.AddField( + model_name='group', + name='permission_manage_problems', + field=models.BooleanField(blank=True, default=False), + ), + migrations.AddField( + model_name='group', + name='permission_manage_topics', + field=models.BooleanField(blank=True, default=False), + ), + migrations.AddField( + model_name='group', + name='permission_view_collections', + field=models.BooleanField(blank=True, default=False), + ), + migrations.AddField( + model_name='group', + name='permission_view_problems', + field=models.BooleanField(blank=True, default=False), + ), + migrations.AddField( + model_name='group', + name='permission_view_topics', + field=models.BooleanField(blank=True, default=False), + ), + migrations.AddField( + model_name='group', + name='permission_view_topics_log', + field=models.BooleanField(blank=True, default=False), + ), + migrations.AddField( + model_name='problem', + name='sharing', + field=models.BooleanField(blank=True, default=False), + ), + migrations.AddField( + model_name='topic', + name='sharing', + field=models.BooleanField(blank=True, default=False), + ), + migrations.CreateModel( + name='TopicGroupPermission', + fields=[ + ('topic_group_permission_id', models.AutoField(primary_key=True, serialize=False)), + ('permission_manage_topics', models.BooleanField(blank=True, default=False)), + ('permission_view_topics', models.BooleanField(blank=True, default=False)), + ('permission_view_topics_log', models.BooleanField(blank=True, default=False)), + ('group', models.ForeignKey(db_column='group_id', on_delete=django.db.models.deletion.CASCADE, to='api.group')), + ('topic', models.ForeignKey(db_column='topic_id', on_delete=django.db.models.deletion.CASCADE, to='api.topic')), + ], + ), + migrations.CreateModel( + name='ProblemGroupPermission', + fields=[ + ('problem_group_permission_id', models.AutoField(primary_key=True, serialize=False)), + ('permission_manage_problems', models.BooleanField(blank=True, default=False)), + ('permission_view_problems', models.BooleanField(blank=True, default=False)), + ('group', models.ForeignKey(db_column='group_id', on_delete=django.db.models.deletion.CASCADE, to='api.group')), + ('problem', models.ForeignKey(db_column='problem_id', on_delete=django.db.models.deletion.CASCADE, to='api.problem')), + ], + ), + migrations.CreateModel( + name='CollectionGroupPermission', + fields=[ + ('collection_group_permission_id', models.AutoField(primary_key=True, serialize=False)), + ('permission_manage_collections', models.BooleanField(blank=True, default=False)), + ('permission_view_collections', models.BooleanField(blank=True, default=False)), + ('collection', models.ForeignKey(db_column='collection_id', on_delete=django.db.models.deletion.CASCADE, to='api.collection')), + ('group', models.ForeignKey(db_column='group_id', on_delete=django.db.models.deletion.CASCADE, to='api.group')), + ], + ), + ] diff --git a/api/migrations/0046_alter_account_account_id_and_more.py b/api/migrations/0046_alter_account_account_id_and_more.py new file mode 100644 index 0000000..d3ba1d2 --- /dev/null +++ b/api/migrations/0046_alter_account_account_id_and_more.py @@ -0,0 +1,78 @@ +# Generated by Django 4.1.2 on 2023-12-31 06:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0045_collection_sharing_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='account', + name='account_id', + field=models.IntegerField(blank=True, default=21169482018841058607917871046905516796, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='bestsubmission', + name='best_submission_id', + field=models.IntegerField(blank=True, default=149805424067452344256336652203968127971, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='collection', + name='collection_id', + field=models.IntegerField(blank=True, default=268667638844507429395683049205342878308, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='collectiongrouppermission', + name='collection_group_permission_id', + field=models.IntegerField(blank=True, default=109233292530947572577678851192443289212, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='group', + name='group_id', + field=models.IntegerField(blank=True, default=122445526515845715335481945122286027175, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='groupmember', + name='group_member_id', + field=models.IntegerField(blank=True, default=166402800061360647258671358541528594815, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='problem', + name='problem_id', + field=models.IntegerField(blank=True, default=319367364084708849680820356972231050063, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='problemgrouppermission', + name='problem_group_permission_id', + field=models.IntegerField(blank=True, default=287900638121684221482942373316315838568, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='submission', + name='submission_id', + field=models.IntegerField(blank=True, default=333913260807308465398586534607890822150, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='submissiontestcase', + name='submission_testcase_id', + field=models.IntegerField(blank=True, default=60359747276246222989657681614453318391, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='testcase', + name='testcase_id', + field=models.IntegerField(blank=True, default=67781662549803771653563714324350833289, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='topic', + name='topic_id', + field=models.IntegerField(blank=True, default=277680624917405823307023916753225961537, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='topicgrouppermission', + name='topic_group_permission_id', + field=models.IntegerField(blank=True, default=268422871249108757857865287128153578738, primary_key=True, serialize=False, unique=True), + ), + ] diff --git a/api/migrations/0047_alter_account_account_id_and_more.py b/api/migrations/0047_alter_account_account_id_and_more.py new file mode 100644 index 0000000..5d7eb2f --- /dev/null +++ b/api/migrations/0047_alter_account_account_id_and_more.py @@ -0,0 +1,78 @@ +# Generated by Django 4.1.2 on 2023-12-31 06:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0046_alter_account_account_id_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='account', + name='account_id', + field=models.IntegerField(blank=True, default=255025766878975110361680320380373860653, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='bestsubmission', + name='best_submission_id', + field=models.IntegerField(blank=True, default=258922610152306027347722825318799690393, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='collection', + name='collection_id', + field=models.IntegerField(blank=True, default=99617119408089154479842742330779925899, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='collectiongrouppermission', + name='collection_group_permission_id', + field=models.IntegerField(blank=True, default=81014014139093807433038406409328592680, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='group', + name='group_id', + field=models.IntegerField(blank=True, default=16555706619906256397756149457406660852, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='groupmember', + name='group_member_id', + field=models.IntegerField(blank=True, default=327764340289070410599813626795123765411, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='problem', + name='problem_id', + field=models.IntegerField(blank=True, default=158188918196591434367913126653525869241, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='problemgrouppermission', + name='problem_group_permission_id', + field=models.IntegerField(blank=True, default=253268741446266731297890328391178611475, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='submission', + name='submission_id', + field=models.IntegerField(blank=True, default=24540818810954611023886936486853063157, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='submissiontestcase', + name='submission_testcase_id', + field=models.IntegerField(blank=True, default=264396448540576706768031613977560334190, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='testcase', + name='testcase_id', + field=models.IntegerField(blank=True, default=85088409562075225550176092152049933143, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='topic', + name='topic_id', + field=models.IntegerField(blank=True, default=326588415083665992335616674836859249347, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='topicgrouppermission', + name='topic_group_permission_id', + field=models.IntegerField(blank=True, default=224958087767984655481777651457017521859, primary_key=True, serialize=False, unique=True), + ), + ] diff --git a/api/migrations/0048_alter_account_account_id_and_more.py b/api/migrations/0048_alter_account_account_id_and_more.py new file mode 100644 index 0000000..356111b --- /dev/null +++ b/api/migrations/0048_alter_account_account_id_and_more.py @@ -0,0 +1,78 @@ +# Generated by Django 4.1.2 on 2023-12-31 06:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0047_alter_account_account_id_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='account', + name='account_id', + field=models.CharField(blank=True, default='4256b03cc08048ef9aa3c0348b3271ce', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='bestsubmission', + name='best_submission_id', + field=models.CharField(blank=True, default='a6a17c8c118947ddbe19ead82fadcf13', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='collection', + name='collection_id', + field=models.CharField(blank=True, default='0826e62bc2eb485bac000c5a6874354e', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='collectiongrouppermission', + name='collection_group_permission_id', + field=models.CharField(blank=True, default='99f216a4857a47bebf46585de5ba10b4', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='group', + name='group_id', + field=models.CharField(blank=True, default='cc530cb9f1ee4852b1eecd54edbc1ca0', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='groupmember', + name='group_member_id', + field=models.CharField(blank=True, default='4a87ce6643ea4e46ba7a5949f80a9bfe', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='problem', + name='problem_id', + field=models.CharField(blank=True, default='b8f79eec56bd42a78a993888721d2966', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='problemgrouppermission', + name='problem_group_permission_id', + field=models.CharField(blank=True, default='d91f4c61dda94f2b93728feccb8441d5', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='submission', + name='submission_id', + field=models.CharField(blank=True, default='c494a2d002af4c439c258553ab41fd32', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='submissiontestcase', + name='submission_testcase_id', + field=models.CharField(blank=True, default='092f2c6cd8004cd68f8ae138b65d6c8e', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='testcase', + name='testcase_id', + field=models.CharField(blank=True, default='2f39f938182542d6b7d5df70a4c275a2', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='topic', + name='topic_id', + field=models.CharField(blank=True, default='9c5390db0ce942ac9562ec3422222b32', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='topicgrouppermission', + name='topic_group_permission_id', + field=models.CharField(blank=True, default='35981bc9854a45dd9456f4958332466b', max_length=32, primary_key=True, serialize=False, unique=True), + ), + ] diff --git a/api/migrations/0049_alter_account_account_id_and_more.py b/api/migrations/0049_alter_account_account_id_and_more.py new file mode 100644 index 0000000..efa9328 --- /dev/null +++ b/api/migrations/0049_alter_account_account_id_and_more.py @@ -0,0 +1,88 @@ +# Generated by Django 4.1.2 on 2023-12-31 06:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0048_alter_account_account_id_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='account', + name='account_id', + field=models.CharField(blank=True, default='fe492e8f6bbd4df3b7d8518d66cc4141', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='bestsubmission', + name='best_submission_id', + field=models.CharField(blank=True, default='fb2ee51251b144e0980aaaab7de3e2ed', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='collection', + name='collection_id', + field=models.CharField(blank=True, default='f70ffe44bd84425480ea4c73cc1eccf3', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='collectiongrouppermission', + name='collection_group_permission_id', + field=models.CharField(blank=True, default='e32d76e246844cf1834c711ac1d9f2c3', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='collectionproblem', + name='id', + field=models.CharField(blank=True, default='9df47ab61f73413da2667553854563a7', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='group', + name='group_id', + field=models.CharField(blank=True, default='eeb90b4a7ee046e1be3e26967ed815b6', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='groupmember', + name='group_member_id', + field=models.CharField(blank=True, default='b046b347361a4e839828ff8dc64fbf1c', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='problem', + name='problem_id', + field=models.CharField(blank=True, default='9926855227344794b60bf52d107012c7', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='problemgrouppermission', + name='problem_group_permission_id', + field=models.CharField(blank=True, default='b5eeb3a47121426e930587793bfe173f', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='submission', + name='submission_id', + field=models.CharField(blank=True, default='bafecc07aa194ca8a292f387c21af764', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='submissiontestcase', + name='submission_testcase_id', + field=models.CharField(blank=True, default='0188a3eb130c480d95504eae32e1b912', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='testcase', + name='testcase_id', + field=models.CharField(blank=True, default='e47da5f04bdf4b599a6d59d439508e22', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='topic', + name='topic_id', + field=models.CharField(blank=True, default='9d84e241dd0643479412cac53c408657', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='topiccollection', + name='id', + field=models.CharField(blank=True, default='823d76779a1d4455aa3437ae7157fde3', max_length=32, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='topicgrouppermission', + name='topic_group_permission_id', + field=models.CharField(blank=True, default='9ade2833620640cda259dbc40d3638ac', max_length=32, primary_key=True, serialize=False, unique=True), + ), + ] diff --git a/api/migrations/0050_alter_account_account_id_and_more.py b/api/migrations/0050_alter_account_account_id_and_more.py new file mode 100644 index 0000000..c3087be --- /dev/null +++ b/api/migrations/0050_alter_account_account_id_and_more.py @@ -0,0 +1,88 @@ +# Generated by Django 4.1.2 on 2023-12-31 07:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0049_alter_account_account_id_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='account', + name='account_id', + field=models.CharField(blank=True, default='c61cc4ec15424865814d8403791fe7de', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='bestsubmission', + name='best_submission_id', + field=models.CharField(blank=True, default='5de4232945d34426a0b7dc51c1671cbc', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='collection', + name='collection_id', + field=models.CharField(blank=True, default='c178f001e1e5408fa42263289589c1ae', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='collectiongrouppermission', + name='collection_group_permission_id', + field=models.CharField(blank=True, default='f504bf60f7d3421389bd8f939dd49caf', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='collectionproblem', + name='id', + field=models.CharField(blank=True, default='2a36719d3b224b62ad031c94da0d253d', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='group', + name='group_id', + field=models.CharField(blank=True, default='497e3357fd344fe5bdd31788c211f5e7', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='groupmember', + name='group_member_id', + field=models.CharField(blank=True, default='9fe857f7c4bf41aca173f07320779da4', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='problem', + name='problem_id', + field=models.CharField(blank=True, default='1851825ec238474dabb80d4a03a05d2d', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='problemgrouppermission', + name='problem_group_permission_id', + field=models.CharField(blank=True, default='8adfff7ea11645d88a5b97cb56979165', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='submission', + name='submission_id', + field=models.CharField(blank=True, default='0ec695421ff341e086c9a37a662be3e1', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='submissiontestcase', + name='submission_testcase_id', + field=models.CharField(blank=True, default='9bbd6f2b00234676b0b661e74768a830', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='testcase', + name='testcase_id', + field=models.CharField(blank=True, default='81fd1d215c6e41a5b5d99608ab580c7b', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='topic', + name='topic_id', + field=models.CharField(blank=True, default='950c695bdef043c0b52e79bda497423e', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='topiccollection', + name='id', + field=models.CharField(blank=True, default='0ddc6a8372ef4db59adf00aa24b39429', max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='topicgrouppermission', + name='topic_group_permission_id', + field=models.CharField(blank=True, default='8fdc25dc2fcf40588e76e71c1bed234b', max_length=32, primary_key=True, serialize=False), + ), + ] diff --git a/api/migrations/0051_alter_account_account_id_and_more.py b/api/migrations/0051_alter_account_account_id_and_more.py new file mode 100644 index 0000000..feb04e6 --- /dev/null +++ b/api/migrations/0051_alter_account_account_id_and_more.py @@ -0,0 +1,89 @@ +# Generated by Django 4.1.2 on 2023-12-31 07:30 + +import api.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0050_alter_account_account_id_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='account', + name='account_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='bestsubmission', + name='best_submission_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='collection', + name='collection_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='collectiongrouppermission', + name='collection_group_permission_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='collectionproblem', + name='id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='group', + name='group_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='groupmember', + name='group_member_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='problem', + name='problem_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='problemgrouppermission', + name='problem_group_permission_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='submission', + name='submission_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='submissiontestcase', + name='submission_testcase_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='testcase', + name='testcase_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='topic', + name='topic_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='topiccollection', + name='id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='topicgrouppermission', + name='topic_group_permission_id', + field=models.CharField(blank=True, default=api.models.generate_uuid4_hex, max_length=32, primary_key=True, serialize=False), + ), + ] diff --git a/api/migrations/0052_problem_allowed_languages.py b/api/migrations/0052_problem_allowed_languages.py new file mode 100644 index 0000000..7f940c1 --- /dev/null +++ b/api/migrations/0052_problem_allowed_languages.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.2 on 2024-01-12 05:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0051_alter_account_account_id_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='problem', + name='allowed_languages', + field=models.CharField(blank=True, default='', max_length=1000), + ), + ] diff --git a/api/models.py b/api/models.py index 7baa5b4..e30c9a1 100644 --- a/api/models.py +++ b/api/models.py @@ -7,6 +7,10 @@ from django.utils import timezone from django.contrib.auth.base_user import AbstractBaseUser,BaseUserManager from .utility import uploadTopic +from uuid import uuid4 + +def generate_uuid4_hex(): + return uuid4().hex # Create your models here. class ProgrammingLanguage(models.TextChoices): @@ -15,68 +19,72 @@ class ProgrammingLanguage(models.TextChoices): CPP = 'cpp',_('C++') class Account(models.Model): - account_id = models.AutoField(primary_key=True) + account_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) email = models.EmailField(max_length=50,unique=True,null=True) username = models.CharField(max_length=32,unique=True) password = models.CharField(max_length=128) token = models.CharField(max_length=256,null=True,default=None) token_expire = models.IntegerField(null=True,default=None) - is_admin = models.BooleanField(default=False) + # is_admin = models.BooleanField(default=False) is_active = models.BooleanField(default=True) is_private = models.BooleanField(default=True) class Problem(models.Model): - problem_id = models.AutoField(primary_key=True) - account = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="account_id") + problem_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) + creator = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="creator_id") language = models.CharField(max_length=15) # ,choices=ProgrammingLanguage.choices,default=ProgrammingLanguage.PYTHON) title = models.CharField(max_length=50) - description = models.CharField(max_length=10000) + description = models.CharField(max_length=100000) solution = models.CharField(max_length=20000) time_limit = models.FloatField(default=1.5,blank=True) is_active = models.BooleanField(default=True,blank=True) is_private = models.BooleanField(default=False,blank=True) submission_regex = models.CharField(max_length=1000,null=True,blank=True,default=".*") + created_date = models.DateTimeField(default=timezone.now) + updated_date = models.DateTimeField(default=timezone.now) + sharing = models.BooleanField(default=False,blank=True) + allowed_languages = models.CharField(max_length=1000,blank=True,default="") class Testcase(models.Model): - testcase_id = models.AutoField(primary_key=True) + testcase_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) problem = models.ForeignKey(Problem,on_delete=models.CASCADE,db_column="problem_id") input = models.CharField(max_length=100000) - output = models.CharField(max_length=100000) - -class Submission(models.Model): - submission_id = models.AutoField(primary_key=True) - problem = models.ForeignKey(Problem,on_delete=models.CASCADE,db_column="problem_id") - account = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="account_id") - submission_code = models.CharField(max_length=20000) - is_passed = models.BooleanField() - date = models.DateTimeField(default=timezone.now) - score = models.IntegerField(default=0) - max_score = models.IntegerField(default=0) - passed_ratio = models.FloatField(default=0) + output = models.CharField(max_length=100000,null=True) + runtime_status = models.CharField(max_length=10) + deprecated = models.BooleanField(default=False,blank=True) class Collection(models.Model): - collection_id = models.AutoField(primary_key=True) - owner = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="owner_id") + collection_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) + creator = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="creator_id") name = models.CharField(max_length=100) - description = models.CharField(max_length=1000,null=True,blank=True,default=None) + description = models.CharField(max_length=100000,null=True,blank=True,default=None) is_active = models.BooleanField(default=True,blank=True) is_private = models.BooleanField(default=False,blank=True) + created_date = models.DateTimeField(default=timezone.now) + updated_date = models.DateTimeField(default=timezone.now) + sharing = models.BooleanField(default=False,blank=True) + class Topic(models.Model): - topic_id = models.AutoField(primary_key=True) - account = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="account_id") + topic_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) + creator = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="creator_id") name = models.CharField(max_length=100) - description = models.CharField(max_length=1000,null=True,blank=True,default=None) + description = models.CharField(max_length=100000,null=True,blank=True,default=None) image_url = models.ImageField(upload_to='topic/',null=True,blank=True,default=None) is_active = models.BooleanField(default=True,blank=True) is_private = models.BooleanField(default=False,blank=True) + created_date = models.DateTimeField(default=timezone.now) + updated_date = models.DateTimeField(default=timezone.now) + sharing = models.BooleanField(default=False,blank=True) class TopicCollection(models.Model): + id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) topic = models.ForeignKey(Topic,on_delete=models.CASCADE,db_column="topic_id") collection = models.ForeignKey(Collection,on_delete=models.CASCADE,db_column="collection_id") order = models.IntegerField(blank=True,default=0) class CollectionProblem(models.Model): + id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) collection = models.ForeignKey(Collection,on_delete=models.CASCADE,db_column="collection_id") problem = models.ForeignKey(Problem,on_delete=models.CASCADE,db_column="problem_id") order = models.IntegerField(blank=True,default=0) @@ -90,10 +98,90 @@ class TopicAccountAccess(models.Model): topic = models.ForeignKey(Topic,on_delete=models.CASCADE,db_column="topic_id") account = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="account_id") +class Submission(models.Model): + submission_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) + problem = models.ForeignKey(Problem,on_delete=models.CASCADE,db_column="problem_id") + topic = models.ForeignKey(Topic,on_delete=models.CASCADE,db_column="topic_id",null=True) + account = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="account_id") + language = models.CharField(max_length=15) + submission_code = models.CharField(max_length=20000) + is_passed = models.BooleanField() + date = models.DateTimeField(default=timezone.now) + score = models.IntegerField(default=0) + max_score = models.IntegerField(default=0) + passed_ratio = models.FloatField(default=0) + class SubmissionTestcase(models.Model): - submission_testcase_id = models.AutoField(primary_key=True) + submission_testcase_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) submission = models.ForeignKey(Submission,on_delete=models.CASCADE,db_column="submission_id") testcase = models.ForeignKey(Testcase,on_delete=models.CASCADE,db_column="testcase_id") output = models.CharField(max_length=100000,blank=True,null=True) is_passed = models.BooleanField(default=False,blank=True) - runtime_status = models.CharField(max_length=10) \ No newline at end of file + runtime_status = models.CharField(max_length=10) + +class BestSubmission(models.Model): + best_submission_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) + problem = models.ForeignKey(Problem,on_delete=models.CASCADE,db_column="problem_id") + topic = models.ForeignKey(Topic,on_delete=models.CASCADE,db_column="topic_id",null=True) + account = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="account_id") + submission = models.ForeignKey(Submission,on_delete=models.CASCADE,db_column="submission_id") + +class Group(models.Model): + group_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) + creator = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="creator_id") + name = models.CharField(max_length=100) + description = models.CharField(max_length=100000,null=True,blank=True,default=None) + color = models.CharField(max_length=10,null=True,blank=True,default=None) + created_date = models.DateTimeField(default=timezone.now) + updated_date = models.DateTimeField(default=timezone.now) + + permission_manage_topics = models.BooleanField(default=False,blank=True) + permission_view_topics = models.BooleanField(default=False,blank=True) + permission_view_topics_log = models.BooleanField(default=False,blank=True) + permission_manage_collections = models.BooleanField(default=False,blank=True) + permission_view_collections = models.BooleanField(default=False,blank=True) + permission_manage_problems = models.BooleanField(default=False,blank=True) + permission_view_problems = models.BooleanField(default=False,blank=True) + +class GroupMember(models.Model): + group_member_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) + group = models.ForeignKey(Group,on_delete=models.CASCADE,db_column="group_id") + account = models.ForeignKey(Account,on_delete=models.CASCADE,db_column="account_id") + created_date = models.DateTimeField(default=timezone.now) + +class ProblemGroupPermission(models.Model): + problem_group_permission_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) + problem = models.ForeignKey(Problem,on_delete=models.CASCADE,db_column="problem_id") + group = models.ForeignKey(Group,on_delete=models.CASCADE,db_column="group_id") + permission_manage_problems = models.BooleanField(default=False,blank=True) + permission_view_problems = models.BooleanField(default=False,blank=True) + +class CollectionGroupPermission(models.Model): + collection_group_permission_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) + collection = models.ForeignKey(Collection,on_delete=models.CASCADE,db_column="collection_id") + group = models.ForeignKey(Group,on_delete=models.CASCADE,db_column="group_id") + permission_manage_collections = models.BooleanField(default=False,blank=True) + permission_view_collections = models.BooleanField(default=False,blank=True) + +class TopicGroupPermission(models.Model): + topic_group_permission_id = models.CharField(primary_key=True,blank=True,default=generate_uuid4_hex,max_length=32) + topic = models.ForeignKey(Topic,on_delete=models.CASCADE,db_column="topic_id") + group = models.ForeignKey(Group,on_delete=models.CASCADE,db_column="group_id") + permission_manage_topics = models.BooleanField(default=False,blank=True) + permission_view_topics = models.BooleanField(default=False,blank=True) + permission_view_topics_log = models.BooleanField(default=False,blank=True) + +# class TopicGroupPermission(models.Model): +# topic = models.ForeignKey(Topic,on_delete=models.CASCADE,db_column="topic_id") +# group = models.ForeignKey(Group,on_delete=models.CASCADE,db_column="group_id") +# permission_access = models.BooleanField(default=False,blank=True) +# # สามารถเข้าถึง Course นี้ได้ โดยสามารถดูโจทย์ ส่งโจทย์ได้ + +# permission_view_problems = models.BooleanField(default=False,blank=True) +# # เข้าถึงโจทย์เชิงลึกแบบดู Testcases ได้ +# permission_manage_collections = models.BooleanField(default=False,blank=True) +# # จัดการเพิ่ม/ลบ โจทย์ออกจาก Collection ได้ +# permission_manage_topic = models.BooleanField(default=False,blank=True) +# # สามารถแก้ไข +# permission_manage_members = models.BooleanField(default=False,blank=True) + \ No newline at end of file diff --git a/api/permissions/topic.py b/api/permissions/topic.py new file mode 100644 index 0000000..ee389cc --- /dev/null +++ b/api/permissions/topic.py @@ -0,0 +1,6 @@ +from ..models import * +def canManageTopic(topic:Topic,account:Account): + is_creator = topic.creator.account_id == account.account_id + has_permission = len(TopicGroupPermission.objects.filter(permission_manage_topics=True,topic=topic,group__in=[gm.group for gm in GroupMember.objects.filter(account=account)])) > 0 + print(TopicGroupPermission.objects.filter(topic=topic,group__in=[gm.group for gm in GroupMember.objects.filter(account=account)])) + return is_creator or has_permission \ No newline at end of file diff --git a/api/sandbox/grader.py b/api/sandbox/grader.py index c46c5f3..4555f90 100644 --- a/api/sandbox/grader.py +++ b/api/sandbox/grader.py @@ -1,52 +1,17 @@ import subprocess +""" +Usecases: +- Create problem +- Update code +- Update testcases +- Submit problem +""" + def forgiveableFormat(string:str)->str: return string.replace('\r','') # return string -# def checker(section:int,code:str,testcases:list,timeout=1.5)->dict: -# result = [] -# hasError = False -# hasTimeout = False -# for i in range(len(testcases)): -# with open(f'./api/sandbox/section{section}/testcases/{i}.txt','w') as f: -# f.write(testcases[i]) - -# with open(f'./api/sandbox/section{section}/runner.py','w') as f: -# f.write(code) - -# for i in range(len(testcases)): -# try: -# runner = subprocess.check_output(['python',f'./api/sandbox/section{section}/runner.py'],stdin=open(f'./api/sandbox/section{section}/testcases/{i}.txt','r'),stderr=subprocess.DEVNULL,timeout=float(timeout)) -# result.append({'input':testcases[i],'output':runner.decode(),'runtime_status':'OK'}) -# except subprocess.CalledProcessError: -# hasError = True -# result.append({'input':testcases[i],'output':None,'runtime_status':'ERROR'}) -# except subprocess.TimeoutExpired: -# hasTimeout = True -# result.append({'input':testcases[i],'output':None,'runtime_status':'TIMEOUT'}) - -# return {'result':result,'has_error':hasError,'has_timeout':hasTimeout} - -# def grading(section:int,code:str,input:list,output:list,timeout=1.5)->str: -# score = '' -# graded = checker(section,code,input,timeout) -# graded_result = graded['result'] - -# for i in range(len(output)): -# if graded_result[i]['runtime_status'] == 'OK': -# if forgiveableFormat(graded_result[i]['output']) == forgiveableFormat(output[i]): -# score += 'P' -# else: -# score += '-' -# elif graded_result[i]['runtime_status'] == 'TIMEOUT': -# score += 'T' -# else: -# score += 'E' - -# return score - - class RuntimeResult: RUNTIME_STATUS = [ @@ -87,6 +52,28 @@ def __str__(self) -> str: return str(dict(self)) +class RuntimeResultList: + def __init__(self,runtimeResult:list[RuntimeResult]) -> None: + self.data = runtimeResult + self.has_error = len([res for res in runtimeResult if res.runtime_status == "ERROR"]) > 0 + self.has_timeout = len([res for res in runtimeResult if res.runtime_status == "TIMEOUT"]) > 0 + self.runnable = not (self.has_error or self.has_timeout) + + def getResult(self) -> list[dict]: + return [dict(i) for i in self.data] + +class GradingResultList: + def __init__(self,gradingResult:list[GradingResult]) -> None: + self.data = gradingResult + self.has_error = len([res for res in gradingResult if res.runtime_status == "ERROR"]) > 0 + self.has_timeout = len([res for res in gradingResult if res.runtime_status == "TIMEOUT"]) > 0 + self.runnable = not (self.has_error or self.has_timeout) + self.is_passed = len([res for res in gradingResult if res.is_passed]) == len(gradingResult) + + def getResult(self) -> list[dict]: + return [dict(i) for i in self.data] + + class ProgramGrader: def __init__(self,code:str,testcases:list[str],section:int,timeout:float) -> None: self.code = code @@ -112,15 +99,21 @@ def compile(self) -> None: def runtime(self) -> list[RuntimeResult]: pass - def generate_output(self) -> list[RuntimeResult]: - self.setup() - self.compile() - return self.runtime() - - def grading(self,expected_output:list[str]) -> list[GradingResult]: - self.setup() - self.compile() - runtime_result = self.runtime() + def generate_output(self) -> RuntimeResultList: + try: + self.setup() + self.compile() + return RuntimeResultList(self.runtime()) + except Exception as e: + return RuntimeResultList([RuntimeResult(testcase,None,"ERROR") for testcase in self.testcases]) + + def grading(self,expected_output:list[str]) -> GradingResultList: + try: + self.setup() + self.compile() + runtime_result = self.runtime() + except: + runtime_result = [RuntimeResult(testcase,None,"ERROR") for testcase in self.testcases] if len(runtime_result) != len(expected_output): raise Exception("Length of expected output and runtime result is not equal") @@ -136,6 +129,8 @@ def grading(self,expected_output:list[str]) -> list[GradingResult]: output = runtime_result[i].output if forgiveableFormat(runtime_result[i].output) == forgiveableFormat(expected_output[i]): is_passed = True + else: + runtime_result[i].runtime_status = "FAILED" grading_result.append(GradingResult( runtime_result[i].input, @@ -145,8 +140,7 @@ def grading(self,expected_output:list[str]) -> list[GradingResult]: is_passed )) - return grading_result - + return GradingResultList(grading_result) class PythonGrader(ProgramGrader): @@ -283,4 +277,4 @@ def runtime(self) -> list[RuntimeResult]: grader = Grader['python'] result = grader(adder,test,1,1.5).grading(pyresult) -print(result) \ No newline at end of file +# print(result.getResult()) \ No newline at end of file diff --git a/api/serializers.py b/api/serializers.py index 4f847b0..a4f9030 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -25,6 +25,7 @@ def update(self,instance,validate_data): instance.image_url = validate_data.get('image_url',instance.image_url) instance.is_active = validate_data.get('is_active',instance.is_active) instance.is_private = validate_data.get('is_private',instance.is_private) + instance.updated_date = timezone.now() instance.save() return instance @@ -43,22 +44,51 @@ class Meta: model = Problem fields = "__all__" +problem_secure_fields = ['problem_id','title','description','is_active','is_private','updated_date','created_date'] +class ProblemSecureSerializer(serializers.ModelSerializer): + class Meta: + model = Problem + exclude = ['solution','submission_regex','is_private','is_active','sharing'] + class ProblemPopulateAccountSerializer(serializers.ModelSerializer): - account = AccountSecureSerializer() + creator = AccountSecureSerializer() class Meta: model = Problem fields = "__all__" + +class ProblemPopulateAccountSecureSerializer(serializers.ModelSerializer): + creator = AccountSecureSerializer() + class Meta: + model = Problem + exclude = ['solution','submission_regex','is_private','is_active','sharing'] + + + class TopicCollectionSerializer(serializers.ModelSerializer): class Meta: model = TopicCollection fields = "__all__" + + class CollectionProblemSerializer(serializers.ModelSerializer): class Meta: model = CollectionProblem fields = "__all__" +class CollectionProblemPopulateProblemSerializer(serializers.ModelSerializer): + problem = ProblemSerializer() + class Meta: + model = CollectionProblem + fields = "__all__" + +class CollectionProblemPopulateProblemSecureSerializer(serializers.ModelSerializer): + problem = ProblemSecureSerializer() + class Meta: + model = CollectionProblem + fields = "__all__" + class CollectionSerializer(serializers.ModelSerializer): class Meta: model = Collection @@ -95,4 +125,259 @@ class Meta: class TestcaseSerializer(serializers.ModelSerializer): class Meta: model = Testcase - fields = "__all__" \ No newline at end of file + fields = "__all__" + +class ProblemPopulateTestcaseSerializer(serializers.ModelSerializer): + testcases = TestcaseSerializer(many=True) + class Meta: + model = Problem + fields = [ + 'problem_id', + 'language', + 'title', + 'description', + 'solution', + 'time_limit', + 'is_active', + 'is_private', + 'submission_regex', + 'created_date', + 'updated_date', + 'creator', + 'testcases' + ] + +# class ProblemPopulateAccountSecureSerializer(serializers.ModelSerializer): +# creator = AccountSecureSerializer() +# class Meta: +# model = Problem +# fields = ['problem_id','title','description','creator'] + +class SubmissionPoplulateProblemSecureSerializer(serializers.ModelSerializer): + problem = ProblemPopulateAccountSecureSerializer() + class Meta: + model = Submission + fields = "__all__" + +class SubmissionTestcaseSecureSerializer(serializers.ModelSerializer): + class Meta: + model = SubmissionTestcase + fields = ['is_passed','runtime_status'] + +class SubmissionPopulateSubmissionTestcaseSecureSerializer(serializers.ModelSerializer): + # Add testcases field + runtime_output = SubmissionTestcaseSecureSerializer(many=True) + class Meta: + model = Submission + fields = ['submission_id','account','problem','topic','language','submission_code','is_passed','date','score','max_score','passed_ratio','runtime_output'] + +class SubmissionPopulateSubmissionTestcaseAndProblemSecureSerializer(serializers.ModelSerializer): + # Add testcases field + runtime_output = SubmissionTestcaseSecureSerializer(many=True) + problem = ProblemSecureSerializer() + class Meta: + model = Submission + fields = ['submission_id','account','problem','topic','language','submission_code','is_passed','date','score','max_score','passed_ratio','runtime_output'] + +class ProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer(serializers.ModelSerializer): + # Add testcases field + creator = AccountSecureSerializer() + best_submission = SubmissionPopulateSubmissionTestcaseSecureSerializer() + class Meta: + model = Problem + fields = problem_secure_fields + ['best_submission','creator'] + +class ProblemPopulatSubmissionPopulateSubmissionTestcasesSecureSerializer(serializers.ModelSerializer): + best_submission = SubmissionPopulateSubmissionTestcaseSecureSerializer() + class Meta: + model = Problem + fields = problem_secure_fields + ['best_submission'] +class TopicCollectionPopulateCollectionSerializer(serializers.ModelSerializer): + collection = CollectionSerializer() + class Meta: + model = TopicCollection + fields = "__all__" + +class TopicCollectionPopulateCollectionProblemPopulateProblemSerializer(serializers.ModelSerializer): + collection = CollectionProblemPopulateProblemSerializer() + class Meta: + model = TopicCollection + fields = "__all__" + +class TopicPopulateTopicCollectionPopulateCollectionSerializer(serializers.ModelSerializer): + collections = TopicCollectionPopulateCollectionSerializer(many=True) + class Meta: + model = Topic + fields = "__all__" + include = ['collections'] + + +class TopicPopulateTopicCollectionPopulateCollectionProblemPopulateProblemSerializer(serializers.ModelSerializer): + collections = CollectionProblemPopulateProblemSerializer(many=True) + class Meta: + model = Topic + fields = ['topic_id','name','description','image_url','is_active','is_private','created_date','updated_date','collections'] + +class CollectionProblemPopulateProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer(serializers.ModelSerializer): + problem = ProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer() + class Meta: + model = CollectionProblem + fields = "__all__" +class CollectionPopulateCollectionProblemPopulateProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer(serializers.ModelSerializer): + problems = CollectionProblemPopulateProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer(many=True) + class Meta: + model = Collection + fields = "__all__" + +class TopicCollectionPopulateCollectionPopulateCollectionProblemPopulateProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer(serializers.ModelSerializer): + collection = CollectionPopulateCollectionProblemPopulateProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer() + class Meta: + model = TopicCollection + fields = "__all__" + +class TopicPopulateTopicCollectionPopulateCollectionPopulateCollectionProblemPopulateProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer(serializers.ModelSerializer): + collections = TopicCollectionPopulateCollectionPopulateCollectionProblemPopulateProblemPopulateAccountAndSubmissionPopulateSubmissionTestcasesSecureSerializer(many=True) + class Meta: + model = Topic + fields = ['topic_id','name','description','image_url','created_date','updated_date','collections'] + +class GroupSerializer(serializers.ModelSerializer): + class Meta: + model = Group + fields = "__all__" + +class GroupMemberSerializer(serializers.ModelSerializer): + class Meta: + model = GroupMember + fields = "__all__" +class GroupMemberPopulateAccountSecureSerializer(serializers.ModelSerializer): + account = AccountSecureSerializer() + class Meta: + model = GroupMember + fields = "__all__" + +class GroupPopulateGroupMemberPopulateAccountSecureSerializer(serializers.ModelSerializer): + members = GroupMemberPopulateAccountSecureSerializer(many=True) + class Meta: + model = Group + fields = "__all__" + include = ['members'] + +class TopicGroupPermissionsSerializer(serializers.ModelSerializer): + class Meta: + model = TopicGroupPermission + fields = "__all__" + +class TopicGroupPermissionPopulateGroupSerializer(serializers.ModelSerializer): + group = GroupSerializer() + class Meta: + model = TopicGroupPermission + fields = "__all__" + +class TopicPopulateTopicGroupPermissionsSerializer(serializers.ModelSerializer): + group_permissions = TopicGroupPermissionsSerializer(many=True) + class Meta: + model = Topic + fields = "__all__" + include = ['group_permissions'] + +class TopicPopulateTopicCollectionPopulateCollectionAndTopicGroupPermissionPopulateGroupSerializer(serializers.ModelSerializer): + collections = TopicCollectionPopulateCollectionSerializer(many=True) + group_permissions = TopicGroupPermissionPopulateGroupSerializer(many=True) + class Meta: + model = Topic + fields = "__all__" + include = ['collections','group_permissions'] + +class CollectionPopulateCollectionProblemPopulateProblemSerializer(serializers.ModelSerializer): + problems = CollectionProblemPopulateProblemSerializer(many=True) + class Meta: + model = Collection + fields = "__all__" + +class TopicCollectionPopulateCollectionPopulateCollectionProblemPopulateProblemSerializer(serializers.ModelSerializer): + collection = CollectionPopulateCollectionProblemPopulateProblemSerializer() + class Meta: + model = TopicCollection + fields = "__all__" + +class TopicPopulateTopicCollectionPopulateCollectionPopulateCollectionProblemPopulateProblemAndTopicGroupPermissionPopulateGroupSerializer(serializers.ModelSerializer): + collections = TopicCollectionPopulateCollectionPopulateCollectionProblemPopulateProblemSerializer(many=True) + group_permissions = TopicGroupPermissionPopulateGroupSerializer(many=True) + + class Meta: + model = Topic + fields = "__all__" + include = ['collections','group_permissions'] + +class CollectionGroupPermissionPopulateGroupSerializer(serializers.ModelSerializer): + group = GroupSerializer() + class Meta: + model = CollectionGroupPermission + fields = "__all__" +class CollectionPopulateCollectionGroupPermissionsPopulateGroupSerializer(serializers.ModelSerializer): + group_permissions = CollectionGroupPermissionPopulateGroupSerializer(many=True) + class Meta: + model = Collection + fields = "__all__" + include = ['group_permissions'] + +class CollectionPopulateCollectionProblemsPopulateProblemAndCollectionGroupPermissionsPopulateGroupSerializer(serializers.ModelSerializer): + problems = CollectionProblemPopulateProblemSerializer(many=True) + group_permissions = CollectionGroupPermissionPopulateGroupSerializer(many=True) + class Meta: + model = Collection + fields = "__all__" + include = ['problems','group_permissions'] + + + +class CollectionPopulateCollectionProblemsPopulateProblemSerializer(serializers.ModelSerializer): + problems = CollectionProblemPopulateProblemSerializer(many=True) + class Meta: + model = Collection + fields = "__all__" + include = ['problems'] + +class TopicCollectionPopulateCollectionPopulateCollectionProblemsPopulateProblemAndCollectionGroupPermissionsPopulateGroupSerializer(serializers.ModelSerializer): + collection = CollectionPopulateCollectionProblemsPopulateProblemAndCollectionGroupPermissionsPopulateGroupSerializer() + class Meta: + model = TopicCollection + fields = "__all__" +class TopicPopulateTopicCollectionPopulateCollectionPopulateCollectionProblemsPopulateProblemAndCollectionGroupPermissionsPopulateGroupAndTopicGroupPermissionPopulateGroupSerializer(serializers.ModelSerializer): + collections = TopicCollectionPopulateCollectionPopulateCollectionProblemsPopulateProblemAndCollectionGroupPermissionsPopulateGroupSerializer(many=True) + group_permissions = TopicGroupPermissionPopulateGroupSerializer(many=True) + + class Meta: + model = Topic + fields = "__all__" + include = ['collections','group_permissions'] + +class ProblemGroupPermissionsPopulateGroupSerializer(serializers.ModelSerializer): + group = GroupSerializer() + class Meta: + model = ProblemGroupPermission + fields = "__all__" + +class ProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupSerializer(serializers.ModelSerializer): + creator = AccountSecureSerializer() + group_permissions = ProblemGroupPermissionsPopulateGroupSerializer(many=True) + testcases = TestcaseSerializer(many=True) + class Meta: + model = Problem + fields = "__all__" + include = ['creator','group_permissions','testcases'] + + +class CollectionProblemsPopulateProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupSerializer(serializers.ModelSerializer): + problem = ProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupSerializer() + class Meta: + model = CollectionProblem + fields = "__all__" +class CollectionPopulateCollectionProblemsPopulateProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupAndCollectionGroupPermissionsPopulateGroupSerializer(serializers.ModelSerializer): + problems = CollectionProblemsPopulateProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupSerializer(many=True) + group_permissions = CollectionGroupPermissionPopulateGroupSerializer(many=True) + class Meta: + model = Collection + fields = "__all__" + include = ['problems','group_permissions'] \ No newline at end of file diff --git a/api/urls.py b/api/urls.py index 286bf15..f4c9a13 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,34 +1,54 @@ from django.urls import path -from .views import account,auth,problem, script,submission,topic,collection +from .views import account,auth,problem, script,submission,topic,collection,group urlpatterns = [ - path("login",auth.login), - path("logout",auth.logout), - path('token',auth.get_authorization), - - path("accounts",account.account_collection), - path("accounts/",account.get_account), - path("accounts//daily-submissions",account.get_daily_submission), - path("accounts//password",account.change_password), - - path('accounts//problems',problem.create_problem), - path('problems',problem.all_problem), - path('problems/',problem.one_problem), - - path('problems//',submission.submit_problem), - path('submissions',submission.view_all_submission), - - path('accounts//topics',topic.create_topic), - path('topics',topic.all_topic), - path('topics/',topic.one_topic), - path('topics//access',topic.account_access), - path('topics//collections/',topic.topic_collection), - - path('accounts//collections',collection.create_collections), - path('collections',collection.all_collections), - path('collections/',collection.one_collection), - path('collections//problems/',collection.collection_problems), + path("login",auth.login_view), + path("logout",auth.logout_view), + path('token',auth.authorization_view), + + path("accounts",account.all_accounts_view), + path("accounts/",account.one_creator_view), + path("accounts//daily-submissions",account.get_daily_submission), + path("accounts//password",account.change_password), + + path('accounts//problems',problem.all_problems_creator_view), + path('accounts//problems/',problem.one_problem_creator_view), + path('accounts//problems//groups',problem.problem_group_view), + path("accounts//problems//submissions",submission.account_problem_submission_view), + path("accounts//topics//problems//submissions",submission.topic_account_problem_submission_view), + + path('accounts//collections',collection.all_collections_creator_view), + path('accounts//collections/',collection.one_collection_creator_view), + path('accounts//collections//groups',collection.collection_groups_view), + + path('accounts//topics',topic.all_topics_creator_view), + path('accounts//topics/',topic.one_topic_creator_view), + path('accounts//topics//groups',topic.topic_groups_view), + + path('accounts//access/topics',topic.all_topics_access_view), + + path('accounts//groups',group.all_groups_creator_view), + + path('problems',problem.all_problems_view), + path('problems/validate',problem.validation_view), + path('problems/',problem.one_problem_view), + path('topics//problems//accounts/',problem.problem_in_topic_account_view), + + path('collections',collection.all_collections_view), + path('collections/',collection.one_collection_view), + path('collections//problems/',collection.collection_problems_view), + + path('topics',topic.all_topics_view), + path('topics/',topic.one_topic_view), + path('topics//access',topic.account_access), + path('topics//collections/',topic.topic_collections_view), + + path('groups/',group.one_group_view), + path('groups//members',group.group_members_view), + + path('submissions',submission.all_submission_view), + path('script',script.run_script), ] \ No newline at end of file diff --git a/api/views/account.py b/api/views/account.py index 85b688c..41785b9 100644 --- a/api/views/account.py +++ b/api/views/account.py @@ -7,33 +7,20 @@ from rest_framework import status from django.forms.models import model_to_dict from ..serializers import * +from ..controllers.account.create_account import * +from ..controllers.account.get_account import * +from ..controllers.account.get_all_accounts import * @api_view([GET,POST]) -def account_collection(request): +def all_accounts_view(request): if request.method == GET: - accounts = Account.objects.all() - serialize = AccountSecureSerializer(accounts,many=True) - return Response({ - "accounts": serialize.data - },status=status.HTTP_200_OK) - + return get_all_accounts() elif request.method == POST: - request.data['password'] = passwordEncryption(request.data['password']) - try: - account = Account.objects.create(**request.data) - except Exception as e: - return Response({'message':str(e)},status=status.HTTP_400_BAD_REQUEST) - serialize = AccountSerializer(account) - return Response(serialize.data,status=status.HTTP_201_CREATED) + return create_account(request) @api_view([GET]) -def get_account(request,account_id): - try: - account = Account.objects.get(account_id=account_id) - serialize = AccountSerializer(account) - return Response(serialize.data,status=status.HTTP_200_OK) - except: - return Response({'message':'Account not found!'},status=status.HTTP_404_NOT_FOUND) +def one_creator_view(request,account_id): + return get_account(account_id) @api_view([PUT]) def change_password(request,account_id): @@ -44,7 +31,7 @@ def change_password(request,account_id): return Response({'message':"Your password has been changed"}) @api_view([GET]) -def get_daily_submission(request,account_id:int): +def get_daily_submission(request,account_id:str): submissions = Submission.objects.filter(account_id=account_id) serializes = SubmissionSerializer(submissions,many=True) @@ -60,8 +47,3 @@ def get_daily_submission(request,account_id:int): return Response({"submissions_by_date": submission_by_date}) -# @api_view([GET]) -# def get_passed_submission(request,account_id:int): -# submissions = Submission.objects.filter(account_id=account_id,is_passed=True) - -# serialize = SubmissionSerializer(submissions,many=True) diff --git a/api/views/auth.py b/api/views/auth.py index 150631d..ed93aa8 100644 --- a/api/views/auth.py +++ b/api/views/auth.py @@ -10,65 +10,20 @@ from time import time from decouple import config +from ..controllers.auth.authorization import * +from ..controllers.auth.login import * +from ..controllers.auth.logout import * + TOKEN_LIFETIME = int(config('TOKEN_LIFETIME_SECOND')) # (Second) @api_view([POST]) -def login(request): - try: - account = Account.objects.get(username=request.data['username']) - account_dict = model_to_dict(account) - - if passwordEncryption(request.data['password']) == account_dict['password']: - account.token = uuid4().hex - account.token_expire = int(time()+TOKEN_LIFETIME) - account.save() - return Response(model_to_dict(account),status=status.HTTP_202_ACCEPTED) - else: - return Response({'detail':"Incorrect password!"},status=status.HTTP_406_NOT_ACCEPTABLE) - except Account.DoesNotExist: - return Response({'detail':"User doesn't exists!"},status=status.HTTP_404_NOT_FOUND) +def login_view(request): + return login(request) @api_view([POST]) -def logout(request): - try: - account = Account.objects.get(account_id=request.data['account_id']) - if account.token == request.data['token']: - account.token = None - account.save() - return Response(model_to_dict(account),status=status.HTTP_200_OK) - else: - return Response({'detail':"Invalid token!"},status=status.HTTP_200_OK) - except Account.DoesNotExist: - return Response({'detail':"User doesn't exists!"},status=status.HTTP_404_NOT_FOUND) +def logout_view(request): + return logout(request) @api_view([PUT]) -def get_authorization(request): - try: - account = Account.objects.get(account_id=request.data['account_id']) - account_dict = model_to_dict(account) - if account_dict['token_expire'] >= time() and account_dict['token'] == request.data['token']: - return Response({'result':True,'is_admin':account.is_admin},status=status.HTTP_200_OK) - return Response({'result':False,'is_admin':False},status=status.HTTP_200_OK) - except Account.DoesNotExist: - return Response({'result':False,'is_admin':False},status=status.HTTP_200_OK) - # return Response({'detail':"User doesn't exists!"},status=status.HTTP_404_NOT_FOUND) - -# @api_view([GET]) -# def get_token(request): -# try: -# account = Account.objects.get(username=request.data['username']) -# account_dict = model_to_dict(account) - -# if account_dict['token_expire'] < time(): -# return Response({'detail':"Login timeout!"},status=status.HTTP_200_OK) -# elif account_dict['token'] == request.data['token'] - -# if passwordEncryption(request.data['password']) == account_dict['password']: -# account.token = uuid4().hex -# account.token_expire = int(time()+60) -# account.save() -# return Response(model_to_dict(account),status=status.HTTP_202_ACCEPTED) -# else: -# return Response({'detail':"Incorrect password!"},status=status.HTTP_200_OK) -# except Account.DoesNotExist: -# return Response({'detail':"User doesn't exists!"},status=status.HTTP_404_NOT_FOUND) \ No newline at end of file +def authorization_view(request): + return authorization(request) \ No newline at end of file diff --git a/api/views/collection.py b/api/views/collection.py index bac5146..424050c 100644 --- a/api/views/collection.py +++ b/api/views/collection.py @@ -8,112 +8,63 @@ from django.forms.models import model_to_dict from ..serializers import * -@api_view([POST]) -def create_collections(request,account_id:int): - request.data['owner'] = account_id - - serialize = CollectionSerializer(data=request.data) +from ..controllers.collection.create_collection import * +from ..controllers.collection.get_collection import * +from ..controllers.collection.get_all_collections import * +from ..controllers.collection.update_collection import * +from ..controllers.collection.delete_collection import * +from ..controllers.collection.add_problems_to_collection import * +from ..controllers.collection.remove_problems_from_collection import * +from ..controllers.collection.get_all_collections_by_account import * +from ..controllers.collection.update_problems_to_collection import * +from ..controllers.collection.update_group_permissions_collection import * + + + +@api_view([POST,GET]) +def all_collections_creator_view(request,account_id:str): + if request.method == POST: + return create_collection(account_id,request) + if request.method == GET: + return get_all_collections_by_account(account_id) - if serialize.is_valid(): - serialize.save() - return Response(serialize.data,status=status.HTTP_201_CREATED) - else: - return Response(serialize.errors,status=status.HTTP_400_BAD_REQUEST) +@api_view([GET,PUT,DELETE]) +def one_collection_creator_view(request,account_id:int,collection_id:str): + collection = Collection.objects.get(collection_id=collection_id) + if request.method == GET: + return get_collection(collection) + if request.method == PUT: + return update_collection(collection,request) + if request.method == DELETE: + return delete_collection(collection) @api_view([GET]) -def all_collections(request): - collections = Collection.objects.all() - - account_id = request.query_params.get('account_id',0) - - if account_id: - collections = collections.filter(owner_id=account_id) - - populated_collections = [] - for collection in collections: - con_probs = CollectionProblem.objects.filter(collection=collection) - - populated_cp = [] - for cp in con_probs: - prob_serialize = ProblemSerializer(cp.problem) - cp_serialize = CollectionProblemSerializer(cp) - populated_cp.append({**cp_serialize.data,**prob_serialize.data}) - - serialize = CollectionSerializer(collection) - collection_data = serialize.data - collection_data['problems'] = populated_cp - - populated_collections.append(collection_data) - - return Response({ - 'collections': populated_collections - },status=status.HTTP_200_OK) +def all_collections_view(request): + return get_all_collections(request) @api_view([GET,PUT,DELETE]) -def one_collection(request,collection_id:int): - collection = Collection.objects.get(collection_id=collection_id) - problems = Problem.objects.filter(collectionproblem__collection_id=collection_id) - collectionProblems = CollectionProblem.objects.filter(collection=collection) - +def one_collection_view(request,collection_id:str): if request.method == GET: - collection_ser = CollectionSerializer(collection) - - populated_problems = [] - for col_prob in collectionProblems: - col_prob_serialize = CollectionProblemSerializer(col_prob) - prob_serialize = ProblemSerializer(col_prob.problem) - populated_problems.append({**col_prob_serialize.data,**prob_serialize.data}) - - return Response({ - **collection_ser.data, - 'problems': sorted(populated_problems,key=lambda problem: problem['order']) - } ,status=status.HTTP_200_OK) - + return get_collection(collection_id) if request.method == PUT: - collection_ser = CollectionSerializer(collection,data=request.data,partial=True) - if collection_ser.is_valid(): - collection_ser.save() - return Response(collection_ser.data,status=status.HTTP_200_OK) - else: - return Response(collection_ser.errors,status=status.HTTP_400_BAD_REQUEST) - + return update_collection(collection_id,request) if request.method == DELETE: - collection.delete() - return Response(status=status.HTTP_204_NO_CONTENT) + return delete_collection(collection_id) @api_view([PUT]) -def collection_problems(request,collection_id:int,method:str): +def collection_problems_view(request,collection_id:str,method:str): + collection = Collection.objects.get(collection_id=collection_id) if method == "add": - populated_problems = [] - - index = 0 - for problem_id in request.data['problem_ids']: - - problem = Problem.objects.get(problem_id=problem_id) - - alreadyExist = CollectionProblem.objects.filter(problem=problem,collection=collection) - if alreadyExist: - alreadyExist.delete() - - collection_problem = CollectionProblem( - problem=problem, - collection=collection, - order=index - ) - collection_problem.save() - index += 1 - cp_serialize = CollectionProblemSerializer(collection_problem) - populated_problems.append(cp_serialize.data) - - collection_serialize = CollectionSerializer(collection) - - return Response({ - **collection_serialize.data, - 'problems': populated_problems - },status=status.HTTP_201_CREATED) - + return add_problems_to_collection(collection,request) if method == "remove": - CollectionProblem.objects.filter(collection=collection,problem_id__in=request.data['problem_ids']).delete() - return Response(status=status.HTTP_204_NO_CONTENT) \ No newline at end of file + return remove_problems_from_collection(collection,request) + if method == "update": + return update_problems_to_collection(collection,request) + +@api_view([PUT]) +def collection_groups_view(request,account_id:int,collection_id:str): + collection = Collection.objects.get(collection_id=collection_id) + if request.method == PUT: + return update_group_permissions_collection(collection,request) \ No newline at end of file diff --git a/api/views/group.py b/api/views/group.py new file mode 100644 index 0000000..9e2aa0d --- /dev/null +++ b/api/views/group.py @@ -0,0 +1,39 @@ +from api.utility import passwordEncryption +from rest_framework.response import Response +from rest_framework.decorators import api_view +from api.sandbox.grader import PythonGrader +from ..constant import GET,POST,PUT,DELETE +from ..models import * +from rest_framework import status +from django.forms.models import model_to_dict +from ..serializers import * +from ..controllers.group.create_group import create_group +from ..controllers.group.update_group import update_group +from ..controllers.group.delete_group import delete_group +from ..controllers.group.update_members_to_group import update_members_to_group +from ..controllers.group.get_group import get_group +from ..controllers.group.get_all_groups_by_account import get_all_groups_by_account + +@api_view([POST,GET]) +def all_groups_creator_view(request,account_id:str): + account = Account.objects.get(account_id=account_id) + if request.method == POST: + return create_group(account,request) + elif request.method == GET: + return get_all_groups_by_account(account,request) + +@api_view([PUT,DELETE,GET]) +def one_group_view(request,group_id:str): + group = Group.objects.get(group_id=group_id) + if request.method == PUT: + return update_group(group,request) + elif request.method == DELETE: + return delete_group(group,request) + elif request.method == GET: + return get_group(group,request) + +@api_view([PUT]) +def group_members_view(request,group_id:str): + group = Group.objects.get(group_id=group_id) + if request.method == PUT: + return update_members_to_group(group,request) \ No newline at end of file diff --git a/api/views/problem.py b/api/views/problem.py index 382ca88..7016010 100644 --- a/api/views/problem.py +++ b/api/views/problem.py @@ -8,125 +8,67 @@ from django.forms.models import model_to_dict from ..serializers import * -# Create your views here. -@api_view([POST]) -def create_problem(request,account_id): - account = Account.objects.get(account_id=account_id) - - program_output = PythonGrader(request.data['solution'],request.data['testcases'],1,1.5).generate_output() - for result in program_output: - if result.runtime_status != "OK": - return Response({'detail': 'Error during creating. Your code may has an error/timeout!','output': [dict(i) for i in program_output]},status=status.HTTP_406_NOT_ACCEPTABLE) - - problem = Problem( - language = request.data['language'], - account = account, - title = request.data['title'], - description = request.data['description'], - solution = request.data['solution'], - time_limit = request.data['time_limit'] - ) - problem.save() - - testcases_result = [] - for unit in program_output: - testcases_result.append( - Testcase( - problem = problem, - input = unit.input, - output = unit.output - )) +from ..controllers.problem.create_problem import * +from ..controllers.problem.update_problem import * +from ..controllers.problem.delete_problem import * +from ..controllers.problem.get_problem import * +from ..controllers.problem.get_all_problems import * +from ..controllers.problem.remove_bulk_problems import * +from ..controllers.problem.get_all_problems_by_account import * +from ..controllers.problem.validate_program import * +from ..controllers.problem.get_all_problem_with_best_submission import * +from ..controllers.problem.get_problem_in_topic_with_best_submission import * +from ..controllers.problem.update_group_permission_to_problem import * +from ..controllers.problem.get_problem_public import * - Testcase.objects.bulk_create(testcases_result) - problem_serialize = ProblemSerializer(problem) - testcases_serialize = TestcaseSerializer(testcases_result,many=True) +# Create your views here. +@api_view([POST,GET]) +def all_problems_creator_view(request,account_id): + if request.method == POST: + return create_problem(account_id,request) + if request.method == GET: + return get_all_problems_by_account(account_id) - return Response({**problem_serialize.data,'testcases': testcases_serialize.data},status=status.HTTP_201_CREATED) +@api_view([GET,PUT,DELETE]) +def one_problem_creator_view(request,problem_id:str,account_id:str): + problem = Problem.objects.get(problem_id=problem_id) + if request.method == GET: + return get_problem(problem) + elif request.method == PUT: + return update_problem(problem,request) + elif request.method == DELETE: + return delete_problem(problem) @api_view([GET,DELETE]) -def all_problem(request): +def all_problems_view(request): if request.method == GET: - - problem = Problem.objects.all() - - get_private = int(request.query_params.get("private",0)) - get_deactive = int(request.query_params.get("deactive",0)) - account_id = int(request.query_params.get("account_id",0)) - - if not get_private: - problem = problem.filter(is_private=False) - if not get_deactive: - problem = problem.filter(is_active=True) - if account_id != 0: - problem = problem.filter(account_id=account_id) - - problem = problem.order_by('-problem_id') - - serialize = ProblemPopulateAccountSerializer(problem,many=True) - - result = [model_to_dict(i) for i in problem] - - for i in result: - i['creator'] = model_to_dict(Account.objects.get(account_id=i['account'])) - - return Response({'problems':serialize.data},status=status.HTTP_200_OK) + return get_all_problem_with_best_submission(request) elif request.method == DELETE: - target = request.data.get("problem",[]) - problems = Problem.objects.filter(problem_id__in=target) - problems.delete() - return Response(status=status.HTTP_204_NO_CONTENT) + return remove_bulk_problems(request) - @api_view([GET,PUT,DELETE]) -def one_problem(request,problem_id: int): - try: - problem = Problem.objects.get(problem_id=problem_id) - except Problem.DoesNotExist: - return Response({'detail': "Problem doesn't exist!"},status=status.HTTP_404_NOT_FOUND) - testcases = Testcase.objects.filter(problem_id=problem_id) - +def one_problem_view(request,problem_id: int): + problem = Problem.objects.get(problem_id=problem_id) if request.method == GET: - problem_serialize = ProblemPopulateAccountSerializer(problem) - testcases_serialize = TestcaseSerializer(testcases,many=True) - return Response({**problem_serialize.data,'testcases': testcases_serialize.data},status=status.HTTP_200_OK) + return get_problem_public(problem) elif request.method == PUT: - - problem.title = request.data.get("title",problem.title) - problem.language = request.data.get("language",problem.language) - problem.description = request.data.get("description",problem.description) - problem.solution = request.data.get("solution",problem.solution) - problem.time_limit = request.data.get("time_limit",problem.time_limit) - problem.is_private = request.data.get("is_private",problem.is_private) - - if 'testcases' in request.data: - program_output = PythonGrader(problem.solution,request.data['testcases'],1,1.5).generate_output() - - if sum([1 for i in program_output if i.runtime_status != "OK"]) > 0: - return Response({'detail': 'Error during editing. Your code may has an error/timeout!'},status=status.HTTP_406_NOT_ACCEPTABLE) - - testcases.delete() - testcase_result = [] - for unit in program_output: - testcase = Testcase( - problem = problem, - input = unit.input, - output = unit.output - ) - testcase.save() - testcase_result.append(testcase) - problem.save() - - problem_serialize = ProblemSerializer(problem) - testcases_serialize = TestcaseSerializer(testcase_result,many=True) - - return Response({**problem_serialize.data,'testcases': testcases_serialize.data},status=status.HTTP_201_CREATED) - - problem.save() - problem_serialize = ProblemSerializer(problem) - return Response(problem_serialize.data,status=status.HTTP_201_CREATED) - + return update_problem(problem_id,request) elif request.method == DELETE: - problem.delete() - testcases.delete() - return Response(status=status.HTTP_204_NO_CONTENT) \ No newline at end of file + return delete_problem(problem_id) + +@api_view([POST]) +def validation_view(request): + if request.method == POST: + return validate_program(request) + +@api_view([GET]) +def problem_in_topic_account_view(request,account_id:str,topic_id:str,problem_id:str): + if request.method == GET: + return get_problem_in_topic_with_best_submission(account_id,topic_id,problem_id) + +@api_view([PUT]) +def problem_group_view(request,account_id:int,problem_id:int): + problem = Problem.objects.get(problem_id=problem_id) + if request.method == PUT: + return update_group_permission_to_problem(problem,request) \ No newline at end of file diff --git a/api/views/script.py b/api/views/script.py index 50c338b..63aebd4 100644 --- a/api/views/script.py +++ b/api/views/script.py @@ -6,18 +6,58 @@ from rest_framework import status from django.forms.models import model_to_dict from ..serializers import * +from ..controllers.script.generate_submission_score import generate_submission_score +# @api_view([POST]) +# def run_script(request): +# submissions = Submission.objects.all() +# total = len(submissions) +# count = 0 +# for submission in submissions: +# submission.score = submission.result.count('P') +# submission.max_score = len(submission.result) +# submission.passed_ratio = submission.score/submission.max_score +# submission.save() +# count += 1 +# print(f"({count}/{total})") +# return Response({'message': 'Success!'},status=status.HTTP_201_CREATED) + +# @api_view([POST]) +# def run_script(request): +# submissionTestcases = SubmissionTestcase.objects.all() + +# total = len(submissionTestcases) +# count = 0 +# for testcase in submissionTestcases: +# if testcase.runtime_status == "OK" and (not testcase.is_passed): +# testcase.runtime_status = "FAILED" +# testcase.save() +# count += 1 + +# print(f"({count}/{total})") +# return Response({'message': 'Success!'},status=status.HTTP_201_CREATED) + +# @api_view([POST]) +# def run_script(request): +# topics = Topic.objects.all() +# for topic in topics: +# if len(topic.description) == 0: +# topic.description = f'[{{"id": "1","type": ELEMENT_PARAGRAPH,"children": [{{ "text": "" }}]}}]' +# topic.save() +# elif topic.description[0] != '[': +# topic.description = f'[{{"id": "1","type": ELEMENT_PARAGRAPH,"children": [{{ "text": "{topic.description}" }}]}}]' +# topic.save() +# return Response({'message': 'Success!'},status=status.HTTP_201_CREATED) @api_view([POST]) def run_script(request): - submissions = Submission.objects.all() - total = len(submissions) - count = 0 - for submission in submissions: - submission.score = submission.result.count('P') - submission.max_score = len(submission.result) - submission.passed_ratio = submission.score/submission.max_score - submission.save() - count += 1 - print(f"({count}/{total})") - return Response({'message': 'Success!'},status=status.HTTP_201_CREATED) \ No newline at end of file + # collections = Collection.objects.all() + # for collection in collections: + # collection.description = '[{"id":"1","type":"p","children":[{"text":"Just course"}]}]' + # collection.save() + # generate_submission_score(request) + problems = Problem.objects.all() + for problem in problems: + problem.allowed_languages = "python,c,cpp" + problem.save() + return Response({'message': 'Success!'},status=status.HTTP_201_CREATED) diff --git a/api/views/submission.py b/api/views/submission.py index 576b745..4672259 100644 --- a/api/views/submission.py +++ b/api/views/submission.py @@ -11,111 +11,31 @@ from time import sleep from ..utility import regexMatching -QUEUE = [0,0,0,0,0,0,0,0,0,0] +from ..controllers.submission.submit_problem import * +from ..controllers.submission.get_submission_by_quries import * +from ..controllers.submission.get_submissions_by_account_problem import * +from ..controllers.submission.submit_problem_on_topic import * +from ..controllers.submission.get_submissions_by_account_problem_in_topic import * -def avaliableQueue(): - global QUEUE - for i in range(len(QUEUE)): - if QUEUE[i] == 0: - return i - return -1 -@api_view([POST]) -def submit_problem(request,problem_id,account_id): - global QUEUE - problem = Problem.objects.get(problem_id=problem_id) - testcases = Testcase.objects.filter(problem=problem) - - submission_code = request.data['submission_code'] - solution_input = [model_to_dict(i)['input'] for i in testcases] - solution_output = [model_to_dict(i)['output'] for i in testcases] - - if not regexMatching(problem.submission_regex,submission_code): - grading_result = '-'*len(solution_input) - else: - empty_queue = avaliableQueue() - while empty_queue == -1: - empty_queue = avaliableQueue() - sleep(5) - - QUEUE[empty_queue] = 1 - # grading_result = grader.grading(empty_queue+1,submission_code,solution_input,solution_output) - grading_result = PythonGrader(submission_code,solution_input,empty_queue+1,1.5).grading(solution_output) - QUEUE[empty_queue] = 0 - - is_passed = True - for result in grading_result: - if not result.is_passed: - is_passed = False - break - - total_score = sum([i.is_passed for i in grading_result if i.is_passed]) - max_score = len(grading_result) - - submission = Submission( - problem = problem, - account = Account.objects.get(account_id=account_id), - submission_code = request.data['submission_code'], - is_passed = is_passed, - score = total_score, - max_score = max_score, - passed_ratio = total_score/max_score - ) - submission.save() - - submission_testcases = [] - for i in range(len(grading_result)): - submission_testcases.append(SubmissionTestcase( - submission = submission, - testcase = testcases[i], - output = grading_result[i].output, - is_passed = grading_result[i].is_passed, - runtime_status = grading_result[i].runtime_status - )) - - SubmissionTestcase.objects.bulk_create(submission_testcases) - - submission_serialize = SubmissionPoplulateProblemSerializer(submission) - testcases_serialize = SubmissionTestcaseSerializer(submission_testcases,many=True) - - return Response({ - **submission_serialize.data, - "runtime_output": testcases_serialize.data - },status=status.HTTP_201_CREATED) +@api_view([POST,GET]) +def account_problem_submission_view(request,problem_id,account_id): + if request.method == POST: + return submit_problem(account_id,problem_id,request) + if request.method == GET: + return get_submissions_by_account_problem(account_id,problem_id) @api_view([GET]) -def view_all_submission(request): - submission = Submission.objects.all() - - # Query params - problem_id = int(request.query_params.get("problem_id", 0)) - account_id = int(request.query_params.get("account_id", 0)) - topic_id = int(request.query_params.get("topic_id", 0)) - passed = int(request.query_params.get("passed", -1)) - sort_score = int(request.query_params.get("sort_score", 0)) - sort_date = int(request.query_params.get("sort_date", 0)) - - if problem_id != 0: - submission = submission.filter(problem_id=problem_id) - if account_id != 0: - submission = submission.filter(account_id=account_id) - if topic_id != 0: - submission = submission.filter(problem__topic_id=topic_id) - - if passed == 0: - submission = submission.filter(is_passed=False) - elif passed == 1: - submission = submission.filter(is_passed=True) - - if sort_score == -1: - submission = submission.order_by('passed_ratio') - elif sort_score == 1: - submission = submission.order_by('-passed_ratio') - - if sort_date == -1: - submission = submission.order_by('date') - elif sort_date == 1: - submission = submission.order_by('-date') - - serialize = SubmissionPoplulateProblemSerializer(submission,many=True) - return Response({"submissions": serialize.data},status=status.HTTP_200_OK) \ No newline at end of file +def all_submission_view(request): + return get_submission_by_quries(request) + +@api_view([POST,GET]) +def topic_account_problem_submission_view(request,topic_id,account_id,problem_id): + if request.method == POST: + return submit_problem_on_topic(account_id,problem_id,topic_id,request) + if request.method == GET: + return get_submissions_by_account_problem_in_topic(account_id,problem_id,topic_id) + +# @api_view([GET]) +# def submission_account_problem_view(request,account_id:str,problem_id:str): +# return get_submissions_by_account_problem(account_id,problem_id) \ No newline at end of file diff --git a/api/views/topic.py b/api/views/topic.py index 1d25201..55be2bf 100644 --- a/api/views/topic.py +++ b/api/views/topic.py @@ -8,114 +8,69 @@ from django.forms.models import model_to_dict from ..serializers import * -@api_view([POST]) +from ..controllers.topic.create_topic import * +from ..controllers.topic.get_topic import * +from ..controllers.topic.get_all_topics import * +from ..controllers.topic.update_topic import * +from ..controllers.topic.delete_topic import * +from ..controllers.topic.add_collections_to_topic import * +from ..controllers.topic.remove_collections_from_topic import * +from ..controllers.topic.get_all_topics_by_account import * +from ..controllers.topic.update_collections_to_topic import * +from ..controllers.topic.get_topic_public import * +from ..controllers.topic.update_groups_permission_to_topic import * +from ..controllers.topic.get_all_accessed_topics_by_account import * +from ..permissions.topic import * + +@api_view([POST,GET]) @parser_classes([MultiPartParser,FormParser]) -def create_topic(request,account_id :int): - request.data._mutable=True - request.data['account'] = account_id - serializer = TopicSerializer(data=request.data) - - if serializer.is_valid(): - serializer.save() - return Response(serializer.data,status=status.HTTP_201_CREATED) - return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST) - -@api_view([GET]) -def all_topic(request): - topics = Topic.objects.all() - - account_id = request.query_params.get('account_id',0) - - if account_id: - topics = topics.filter(account_id=account_id) - - serializer = TopicSerializer(topics,many=True) - - return Response({ - 'topics': serializer.data - },status=status.HTTP_200_OK) +def all_topics_creator_view(request,account_id :int): + account = Account.objects.get(account_id=account_id) + if request.method == POST: + return create_topic(account_id,request) + elif request.method == GET: + return get_all_topics_by_account(account,request) @api_view([GET,PUT,DELETE]) -def one_topic(request,topic_id:int): +def one_topic_creator_view(request,account_id:str,topic_id:str): topic = Topic.objects.get(topic_id=topic_id) - topicCollections = TopicCollection.objects.filter(topic_id=topic_id) - accessedAccounts = Account.objects.filter(topicaccountaccess__topic_id=topic_id) - + account = Account.objects.get(account_id=account_id) + if not canManageTopic(topic,account): + return Response(status=status.HTTP_401_UNAUTHORIZED) if request.method == GET: - topic_ser = TopicSerializer(topic) - populate_collections = [] - - for top_col in topicCollections: - collection_serialize = CollectionSerializer(top_col.collection) - collection_data = collection_serialize.data - - populate_problems = [] - collection_problems = CollectionProblem.objects.filter(collection=top_col.collection) - for col_prob in collection_problems: - prob_serialize = ProblemSerializer(col_prob.problem) - col_prob_serialize = CollectionProblemSerializer(col_prob) - populate_problems.append({**col_prob_serialize.data,**prob_serialize.data}) - - collection_data['problems'] = populate_problems - top_col_serialize = TopicCollectionSerializer(top_col) - populate_collections.append({**top_col_serialize.data,**collection_data}) + return get_topic(topic) + elif request.method == PUT: + return update_topic(topic,request) + elif request.method == DELETE: + return delete_topic(topic) - accessedAccountsSerialize = AccountSecureSerializer(accessedAccounts,many=True) +@api_view([GET]) +def all_topics_view(request): + return get_all_topics(request) - return Response({ - **topic_ser.data, - "collections": sorted(populate_collections,key=lambda collection: collection['order']), - "accessed_accounts": accessedAccountsSerialize.data - },status=status.HTTP_200_OK) +@api_view([GET,PUT,DELETE]) +def one_topic_view(request,topic_id:str): + if request.method == GET: + return get_topic_public(topic_id,request) elif request.method == PUT: - topic_ser = TopicSerializer(topic,data=request.data,partial=True) - if topic_ser.is_valid(): - topic_ser.save() - return Response(topic_ser.data,status=status.HTTP_200_OK) - return Response(topic_ser.errors,status=status.HTTP_400_BAD_REQUEST) + return update_topic(topic_id,request) elif request.method == DELETE: - topic.delete() - return Response(status=status.HTTP_204_NO_CONTENT) + return delete_topic(topic_id) @api_view([PUT]) -def topic_collection(request,topic_id:int,method:str): +def topic_collections_view(request,topic_id:str,method:str): + topic = Topic.objects.get(topic_id=topic_id) if method == "add": - populated_collections = [] - - index = 0 - for collection_id in request.data['collection_ids']: - collection = Collection.objects.get(collection_id=collection_id) - - alreadyExist = TopicCollection.objects.filter(topic_id=topic.topic_id,collection_id=collection.collection_id) - if alreadyExist: - alreadyExist.delete() - - topicCollection = TopicCollection( - topic=topic, - collection=collection, - order=index - ) - topicCollection.save() - index += 1 - tc_serialize = TopicCollectionSerializer(topicCollection) - populated_collections.append(tc_serialize.data) - - return Response({ - **TopicSerializer(topic).data, - "collections": populated_collections - },status=status.HTTP_201_CREATED) - + return add_collections_to_topic(topic_id,request) elif method == "remove": - TopicCollection.objects.filter(topic_id=topic_id,collection_id__in=request.data['collection_ids']).delete() - # collections = Collection.objects.filter(collection_id__in=request.data['collection_ids']) - # problems = Problem.objects.filter(problem_id__in=request.data['problems_id']) - # TopicProblem.objects.filter(topic_id=topic,problem_id__in=problems).delete() - return Response(status=status.HTTP_204_NO_CONTENT) + return remove_collections_from_topic(topic_id,request) + elif method == "update": + return update_collections_to_topic(topic,request) @api_view([POST,PUT]) -def account_access(request,topic_id:int): +def account_access(request,topic_id:str): topic = Topic.objects.get(topic_id=topic_id) target_accounts = Account.objects.filter(account_id__in=request.data['account_ids']) @@ -139,3 +94,13 @@ def account_access(request,topic_id:int): topicAccountAccesses = TopicAccountAccess.objects.filter(account_id__in=request.data['account_ids']) topicAccountAccesses.delete() return Response(status=status.HTTP_204_NO_CONTENT) + +@api_view([PUT]) +def topic_groups_view(request,account_id:int,topic_id:str): + topic = Topic.objects.get(topic_id=topic_id) + return update_groups_permission_to_topic(topic,request) + +@api_view([GET]) +def all_topics_access_view(request,account_id:str): + account = Account.objects.get(account_id=account_id) + return get_all_accessed_topics_by_account(account) \ No newline at end of file diff --git a/tests/many_line_program.py b/tests/many_line_program.py new file mode 100644 index 0000000..5724282 --- /dev/null +++ b/tests/many_line_program.py @@ -0,0 +1,22 @@ +text = input("Text: ") +h = int(input("Height: ")) + +for i in range(h): + print(f"{' '*i}{text}") + +''' +asdfghjkl +10 +::: +kheeojg +7 +::: +aaaaaaaaaaaa +5 +::: +oiuhnmkij +20 +::: +z +99 +''' diff --git a/tests/one_line.c b/tests/one_line.c new file mode 100644 index 0000000..e1b4f7c --- /dev/null +++ b/tests/one_line.c @@ -0,0 +1 @@ +int main(){int x;scanf("%d", &x);printf("%d\n", x);return 0;} \ No newline at end of file diff --git a/tests/program1.py b/tests/program1.py new file mode 100644 index 0000000..c224d67 --- /dev/null +++ b/tests/program1.py @@ -0,0 +1,11 @@ +x = input() +print(x) + + +''' +1 +::: +2 +::: +3 +''' \ No newline at end of file diff --git a/tests/tempCodeRunnerFile.c b/tests/tempCodeRunnerFile.c new file mode 100644 index 0000000..e1b4f7c --- /dev/null +++ b/tests/tempCodeRunnerFile.c @@ -0,0 +1 @@ +int main(){int x;scanf("%d", &x);printf("%d\n", x);return 0;} \ No newline at end of file diff --git a/tests/tst.py b/tests/tst.py index a66cad1..9cc5be1 100644 --- a/tests/tst.py +++ b/tests/tst.py @@ -1,11 +1,13 @@ -n = int(input("n: ")) +x,y,z = 0 -if n == 1: - print("1 is not a Prime Number") +if x > 0: + i = 2 + if y > 1: + k = 2 else: - for i in range(2,n): - if n % i == 0: - print(f"{n} is not a Prime Number") - break - else: - print(f"{n} is a Prime Number") + if z < 10: + k = 5 + if y > 5: + k = x+y + else: + k = x-y