Skip to content

Commit

Permalink
Merge pull request #4 from DCUSnSLab/DCUC-7_LectureContestExit
Browse files Browse the repository at this point in the history
DCUC-7 시험 종료 기능 구현(ContestUser 테이블 추가, ContestExitSerializer 생성, migr…
  • Loading branch information
junhp1234 authored Apr 13, 2022
2 parents 3437ead + faf1571 commit c686b5f
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 15 deletions.
24 changes: 24 additions & 0 deletions contest/migrations/0003_contestsubmituser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 2.1.7 on 2022-03-24 06:59

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contest', '0002_contest_private'),
]

operations = [
migrations.CreateModel(
name='ContestSubmitUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('contest', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='contest.Contest')),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
36 changes: 36 additions & 0 deletions contest/migrations/0004_auto_20220329_0334.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 2.1.7 on 2022-03-29 03:34

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contest', '0003_contestsubmituser'),
]

operations = [
migrations.CreateModel(
name='ContestUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_submitted', models.BooleanField(default=False)),
('contest', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='contest.Contest')),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.RemoveField(
model_name='contestsubmituser',
name='contest',
),
migrations.RemoveField(
model_name='contestsubmituser',
name='user',
),
migrations.DeleteModel(
name='ContestSubmitUser',
),
]
27 changes: 27 additions & 0 deletions contest/migrations/0005_auto_20220407_0908.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 2.1.7 on 2022-04-07 09:08

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('contest', '0004_auto_20220329_0334'),
]

operations = [
migrations.RemoveField(
model_name='contestuser',
name='is_submitted',
),
migrations.AddField(
model_name='contestuser',
name='end_time',
field=models.DateTimeField(auto_now_add=True, null=True),
),
migrations.AddField(
model_name='contestuser',
name='start_time',
field=models.DateTimeField(auto_now_add=True, null=True),
),
]
23 changes: 23 additions & 0 deletions contest/migrations/0006_auto_20220407_0910.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 2.1.7 on 2022-04-07 09:10

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('contest', '0005_auto_20220407_0908'),
]

operations = [
migrations.AlterField(
model_name='contestuser',
name='end_time',
field=models.DateTimeField(null=True),
),
migrations.AlterField(
model_name='contestuser',
name='start_time',
field=models.DateTimeField(null=True),
),
]
7 changes: 7 additions & 0 deletions contest/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ class Meta:
ordering = ("-start_time",)


class ContestUser(models.Model): # 대회 및 사용자 간 관계형 테이블 생성 (working by soojung)
contest = models.ForeignKey(Contest, null=True, on_delete=models.CASCADE)
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
start_time = models.DateTimeField(null=True)
end_time = models.DateTimeField(null=True)


class AbstractContestRank(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
contest = models.ForeignKey(Contest, on_delete=models.CASCADE)
Expand Down
1 change: 0 additions & 1 deletion contest/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from problem.models import Problem
from .models import ACMContestRank, OIContestRank


class CreateContestSeriaizer(serializers.Serializer):
title = serializers.CharField(max_length=128)
description = serializers.CharField()
Expand Down
2 changes: 2 additions & 0 deletions contest/urls/oj.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from ..views.oj import ContestPasswordVerifyAPI, ContestAccessAPI
from ..views.oj import ContestListAPI, ContestAPI
from ..views.oj import ContestRankAPI
from ..views.oj import ContestExitAPI # working by soojung

urlpatterns = [
url(r"^contests/?$", ContestListAPI.as_view(), name="contest_list_api"),
Expand All @@ -12,4 +13,5 @@
url(r"^contest/announcement/?$", ContestAnnouncementListAPI.as_view(), name="contest_announcement_api"),
url(r"^contest/access/?$", ContestAccessAPI.as_view(), name="contest_access_api"),
url(r"^contest_rank/?$", ContestRankAPI.as_view(), name="contest_rank_api"),
url(r"^contest/exit/?$", ContestExitAPI.as_view(), name="contest_exit_api") # working by soojung
]
85 changes: 75 additions & 10 deletions contest/views/oj.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@
from account.decorators import login_required, check_contest_permission

from utils.constants import ContestRuleType, ContestStatus
from ..models import ContestAnnouncement, Contest, OIContestRank, ACMContestRank
from ..models import ContestAnnouncement, Contest, OIContestRank, ACMContestRank, ContestUser
from ..serializers import ContestAnnouncementSerializer
from ..serializers import ContestSerializer, ContestPasswordVerifySerializer
from ..serializers import OIContestRankSerializer, ACMContestRankSerializer


class ContestAnnouncementListAPI(APIView):
@check_contest_permission(check_type="announcements")
def get(self, request):
Expand All @@ -36,6 +35,7 @@ def get(self, request):

class ContestAPI(APIView):
def get(self, request):
print("ContestAPI Called")
id = request.GET.get("id")

if not id or not check_is_id(id):
Expand All @@ -49,34 +49,50 @@ def get(self, request):
#print("lid = ",contest.lecture_id)
lecsign = LU.getSignupList(request.user.id, lid=contest.lecture_id)
#print("lid = ", contest.lecture)
if not contest.lecture:
if contest.private:
if request.user.is_super_admin():
if not contest.lecture: # 강의가 아닌 경우
if contest.private: # 비공개 대회인 경우
if request.user.is_super_admin(): # 관리자인 경우 True
contest.visible = True
elif request.user.is_student() or request.user.is_semi_admin():
elif request.user.is_student() or request.user.is_semi_admin(): # 학생이나 준관리자인 경우 True
PermitToCont = signup_class.objects.filter(user=request.user, contest=contest)
if PermitToCont.exists():
contest.visible = True
else:
return self.error("등록되지 않은 사용자 입니다.")
else:
else: # 아무 권한도 아닌 경우 False
contest.visible = False
else:
contest.visible = True
elif contest.lecture and len(lecsign) != 0 and lecsign[0].isallow:
elif contest.lecture and len(lecsign) != 0 and lecsign[0].isallow: # 강의가 맞고 & 강의 내 등록된 학생인 경우 True
#print("Lecture allow : ", lecsign[0].isallow)
contest.visible = True
else:
if request.user.is_admin_role(): # 문제 접근을 위한 visible 값 수정
contest.visible = True
else:
contest.visible = False
# tuple 생성
if contest.lecture_contest_type == '대회':
user = ContestUser.objects.filter(contest_id=id, user_id=request.user.id)
if not user:
ContestUser.objects.create(contest_id=id, user_id=request.user.id)

# working by soojung
# try: # 이미 제출한 사용자인지 확인하고, 있는 경우 contest.visible을 False로 변경한다.
# user = ContestUser.objects.get(contest_id=contest, user_id=request.user.id)
# if user:
# if user.is_submitted:
# contest.visible = False
# else:
# contest.visible = True
# except:
# self.error("Contest %s doesn't exist" % contest)

data = ContestSerializer(contest).data
data["now"] = datetime2str(now())
return self.success(data)

class ContestListAPI(APIView):
def get(self, request):
print("ContestListAPI Called")
# contests = Contest.objects.get(lecture=request.get('lecture_id'))
# return self.success(self.paginate_data(request, contests, ContestSerializer))
lectureid = request.GET.get('lectureid')
Expand Down Expand Up @@ -144,6 +160,54 @@ def get(self, request):
return self.success({"access": int(contest_id) in request.session.get("accessible_contests", [])})


class ContestExitAPI(APIView): # working by soojung
def get(self, request):
print("User info : ")
print(request.user)
print("User id : ")
print(request.user.id)
contest_id = request.GET.get("contest_id")
if not contest_id:
return self.error("Invalid parameter, contest_id is required")
# is_submitted 칼럼 값을 True 변경
user = ContestUser.objects.get(contest_id=contest_id, user_id=request.user.id)
if user.end_time is None:
ContestUser.objects.filter(contest_id=contest_id, user_id=request.user.id).update(end_time=now())
return self.success(True)
#
# contest_id = request.GET.get("contest_id")
# if not contest_id:
# return self.error()
# return self.success({"access": int(contest_id) in request.session.get("accessible_contests", [])})
#
# data = request.data
# data["created_by"] = request.user
# lecture = Lecture.objects.create(**data)
# signup_class.objects.create(lecture_id=data["lecture_id"], user=request.user)
# return self.success(ContestAnnouncementSerializer(data, many=True).data)
# def get(self, request):
# print("User info : ")
# print(request.user)
# print("User id : ")
# print(request.user.id)
#
#
# data = request.data
# data["created_by"] = request.user
# contest = Contest.objects.create(**data)
# ContestSubmitUser.objects.create(contest=contest, user=request.user)
# return self.success(LectureAdminSerializer(lecture).data)
#
# # try:
# # csu = ContestSubmitUser.objects.filter(user_id=request.user.id)
# # if csu:
# # print(csu)
# # else:
# # print("해당 학생은 제출하지 않았습니다.")
# # except ContestSubmitUser.DoesNotExist:
# # return self.error("아무도 제출하지 않았습니다.")


class ContestRankAPI(APIView):
def get_rank(self):
if self.contest.rule_type == ContestRuleType.ACM:
Expand All @@ -165,6 +229,7 @@ def column_string(self, n):
return string

@check_contest_permission(check_type="ranks")

def get(self, request):
download_csv = request.GET.get("download_csv")
force_refresh = request.GET.get("force_refresh")
Expand Down
3 changes: 2 additions & 1 deletion lecture/views/oj.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def get(self, request):
class LectureListAPI(APIView):
def get(self, request):
print("LectureListAPI Called")
print("LectureListAPI Called 2")
from datetime import datetime
year = datetime.today().year
semester = (8>datetime.today().month>=3) and 1 or ((3>datetime.today().month>=1) and 3 or 2)
Expand Down Expand Up @@ -93,7 +94,7 @@ def get(self, request):
return self.success(self.paginate_data(request, signuplist, SignupClassSerializer))
except:
print(self.error())
return self.error("no lecture exist")
return self.error("no lecture exist!!") # error !!

try:
# signuplist = signup_class.objects.all()
Expand Down
5 changes: 5 additions & 0 deletions problem/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
from .models import Problem, ProblemRuleType, ProblemTag, ProblemIOMode
from .utils import parse_problem_template
from contest.serializers import ContestSerializer
from contest.models import ContestUser

class ContestExitSerializer(serializers.ModelSerializer): # working by soojung
class Meta:
model = ContestUser
fields = "__all__"

class TestCaseUploadForm(forms.Form):
spj = forms.CharField(max_length=12)
Expand Down
3 changes: 2 additions & 1 deletion problem/urls/oj.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from django.conf.urls import url

from ..views.oj import ProblemTagAPI, ProblemAPI, ContestProblemAPI, PickOneAPI, ProblemResponsibility
from ..views.oj import ProblemTagAPI, ProblemAPI, ContestExitAccessAPI, ContestProblemAPI, PickOneAPI, ProblemResponsibility

urlpatterns = [
url(r"^problem/tags/?$", ProblemTagAPI.as_view(), name="problem_tag_list_api"),
url(r"^problem/?$", ProblemAPI.as_view(), name="problem_api"),
url(r"^problem/contest_exit_access/?$", ContestExitAccessAPI.as_view(), name="problem_contest_exit_access_api"), # working by soojung
url(r"^problemResponsible/?$", ProblemResponsibility.as_view(), name="problem_api"),
url(r"^pickone/?$", PickOneAPI.as_view(), name="pick_one_api"),
url(r"^contest/problem/?$", ContestProblemAPI.as_view(), name="contest_problem_api"),
Expand Down
24 changes: 22 additions & 2 deletions problem/views/oj.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
from ..models import ProblemTag, Problem, ProblemRuleType
from contest.models import Contest
from lecture.models import signup_class
from ..serializers import ProblemSerializer, TagSerializer, ProblemSafeSerializer
from contest.models import ContestRuleType
from ..serializers import ProblemSerializer, TagSerializer, ProblemSafeSerializer, ContestExitSerializer # working by soojung
from contest.models import ContestRuleType, ContestUser
from django.utils.timezone import now


class ProblemTagAPI(APIView):
Expand Down Expand Up @@ -46,6 +47,10 @@ def _add_problem_status(request, queryset_values):
def get(self, request):
# 问题详情页
problem_id = request.GET.get("problem_id")
print()
print(problem_id)
print()

if problem_id:
try:
problem = Problem.objects.select_related("created_by").get(_id=problem_id, contest_id__isnull=True, visible=True)
Expand Down Expand Up @@ -116,6 +121,21 @@ def get(self, request):
data = ProblemSafeSerializer(contest_problems, many=True).data
return self.success(data)

class ContestExitAccessAPI(APIView): # working by soojung
def get(self, request):
print("ContestExitAccessAPI called")
contest_id = request.GET.get("contest_id")
if not contest_id:
return self.error("Invalid parameter, contest_id is required")
try:
user = ContestUser.objects.get(contest_id=contest_id, user_id=request.user.id)
if user:
if user.start_time is None:
ContestUser.objects.filter(contest_id=contest_id, user_id=request.user.id).update(start_time=now())
return self.success(ContestExitSerializer(user).data)
except:
self.error("Contest %s doesn't exist" % contest)

class ProblemResponsibility(APIView):
def get(self, request):
if not request.GET.get("problem_id"):
Expand Down

0 comments on commit c686b5f

Please sign in to comment.