最近的几天时间内,主要是进一步开发SDUVJ
的contest
的其他功能中,并在最终完成了contest
的基本的开发,并实现了基本的代码提交界面,接下来需要进一步完善其功能并改善性能。
Contest的实现代码####
在views.py
中完成了了 对contest
前端请求进行处理的函数
def contest(req):
search = req.GET.get('search')
if search:
query = Contest.objects.filter(Q(name__icontains=search) | Q(uid__username__icontains=search))
else:
query = Contest.objects.all()
pg = req.GET.get('pg')
if not pg:
pg = 1
pg = int(pg)
max_cnt = query.count()
start = max(pg - PAGE_NUMBER_EVERY_PAGE, 1)
end = min(pg + PAGE_NUMBER_EVERY_PAGE, max_cnt)
lst = query[(pg - 1) * LIST_NUMBER_EVERY_PAGE:pg * LIST_NUMBER_EVERY_PAGE]
return ren2res('contest.html', req, {'page': range(start, end + 1), 'list': lst})
@login_required
def contest_detail(req, cid):
contest = Contest.objects.get(id=cid)
# time = datetime.datetime.now(pytz.timezone(pytz.country_timezones('cn')[0]))
# time = datetime.datetime.now()
time = timezone.now()
if time > contest.start_time:
start = True
else:
start = False
if contest.private:
#print(problems)
# print('contest.accounts')
# print(contest.accounts.all())
if req.user.info not in contest.accounts.all():
return ren2res("contest/contest.html", req, {'contest': contest, 'err': "You do not have access to this contest."})
if start:
problems = contest.get_problem_list()
length = len(problems)
problems_status = [0 for i in range(length)]
for i in range(length):
problems[i].append(len(Status.objects.filter(user = req.user).filter(pro = problems[i][2]).filter(result = 'Accepted')))#changes
return ren2res("contest/contest.html", req, {'contest': contest, 'problems': problems, 'problem': problems[0][2]})
else:
return ren2res("contest/contest.html", req, {'contest': contest, 'err': "Just wait."})
@login_required
def contest_get_problem(req, cid):
if req.is_ajax():
contest = Contest.objects.get(id=cid)
pid = req.GET.get('pid')
t = loader.get_template('contest/contest_problem.html')
problem = Problem.objects.get(proid=pid)
if contest.private:
if req.user.info not in contest.accounts.all():
problem = []
content_html = t.render(Context({'problem': problem, 'user' : req.user}))
return HttpResponse(content_html)
@login_required
def contest_status(req, cid):#has understood
if req.is_ajax():
contest = Contest.objects.get(id=cid)
t = loader.get_template('contest/contest_status.html')
status_list = Status.objects.filter(cid=cid).order_by('-time')#need change
if contest.private:
if req.user.info not in contest.accounts.all():
status_list = []
pg = req.GET.get('pg')
if not pg:
pg = 1
pg = int(pg)
max_cnt = status_list.count() // 20 + 1
start = max(pg - PAGE_NUMBER_EVERY_PAGE, 1)
end = min(pg + PAGE_NUMBER_EVERY_PAGE, max_cnt)
lst = status_list[(pg - 1) * LIST_NUMBER_EVERY_PAGE:pg * LIST_NUMBER_EVERY_PAGE]
content_html = t.render(Context({'status_list': lst, 'page': range(start, end + 1), 'contest_id': cid, 'user': req.user}))
return HttpResponse(content_html)
else:
raise Http404
@login_required
def contest_submit(req, cid):
contest = Contest.objects.get(id=cid)
time = datetime.datetime.now(pytz.timezone(pytz.country_timezones('cn')[0]))
if time > contest.start_time + contest.duration_time:
finish = True
else:
finish = False
if contest.private:
if req.user.info not in contest.accounts.all():
return HttpResponseRedirect("/contest/" + cid + "/")
if req.method == 'GET':
return ren2res("contest/contest_submit.html", req, {'contest': contest, 'problems': contest.get_problem_list()})
elif req.method == 'POST':
pid = req.POST.get('pid')
#need change start
sub = Status(pro=Problem.objects.get(proid=pid), user=req.user, lang=req.POST.get('lang'))
if not finish:
sub.cid = contest.id
else:
sub.cid = -1
sub.save()
if req.POST.get('code'):
content_file = ContentFile(req.POST.get('code'))
elif req.FILES:
content_file = ContentFile(req.FILES['file'].read())
else:
return ren2res("contest/contest_submit.html", req,
{'contest': contest, 'problems': contest.get_problem_list(), 'err': 'No Submit!'})
sub.source_code.save(name=str(sub.id), content=content_file)
sub.save()
#judger.Judger(sub)
result=judge_delay.delay(sub)
if not finish:
return HttpResponseRedirect("/contest/" + cid + "/")
else:
return HttpResponseRedirect("/contest/"+cid+"/status?pid=" + pid)
#need change end
def contest_time(req, cid):#don't need change
if req.is_ajax():
contest = Contest.objects.get(id = cid)
startTime = contest.start_time.strftime('%Y-%m-%d %H:%M:%S UTC')
days = contest.duration_time.days
seconds = contest.duration_time.seconds
durationTime = days * 3600 * 24 + seconds;
timeData = {'start' : startTime,
'duration' : durationTime}
print(timeData)
return JsonResponse(timeData)
@login_required
def contest_rank(req, cid):
if req.is_ajax():
contest = Contest.objects.get(id = cid)
if contest.private:
if req.user.info not in contest.accounts.all():
return JsonResponse("{}")
rank_cache = contest.rank
# print("rank_cache:")
# print(rank_cache)
status_list = Status.objects.filter(cid = cid).filter(id__gt = contest.last_submit_id).order_by("time")
# print("status_list")
# print(status_list)
rank_dict = json.loads(rank_cache)
# print("rank_dict")
# print(rank_dict)
statsinfo = {}
pos = 0
problem_list = contest.get_problem_list()
length = len(problem_list)
if contest.last_submit_id==0:
rank_dict["statsinfo"] = [{} for i in range(length)]
for item in problem_list:
rank_dict["statsinfo"][pos] = {"probid" : chr(pos + 65) ,"acNum" : 0, "tryNum" : 0}
statsinfo[item[2].title] = {"pos" : pos}
pos += 1
else:
for item in problem_list:
statsinfo[item[2].title] = {"pos" : pos}
pos += 1
for item in status_list:
if item.uid.is_staff :
continue
name = item.uid.username
contest.last_submit_id = max(contest.last_submit_id, item.id)
if name not in rank_dict.keys():
rank_dict[name] = {"name" : name, "solved":0, "penalty":0, "probs" : [{"failNum" : 0, "acNum" : 0, "acTime" : 0} for i in range(length)]}
pos = statsinfo[item.pid.title]["pos"]
if item.status == 3: #Waiting
break
if item.status == 0: #Accepted
rank_dict["statsinfo"][pos]["acNum"] += 1
rank_dict["statsinfo"][pos]["tryNum"] += 1
if rank_dict[name]["probs"][pos]["acNum"] == 0:
if item.status == 0:
rank_dict[name]["probs"][pos]["acNum"] += 1
rank_dict[name]["probs"][pos]["acTime"] = dateToInt(item.time - contest.start_time, 1)
rank_dict[name]["penalty"] += 20 * rank_dict[name]["probs"][pos]["failNum"] + dateToInt(item.time - contest.start_time, 0)
rank_dict[name]["solved"] += 1
else:
rank_dict[name]["probs"][pos]["failNum"] += 1
contest.rank = json.dumps(rank_dict)
# print("contest.rank")
# print(contest.rank)
contest.save()
return JsonResponse(rank_dict)
同时,contest
的界面如下,已经可以实现在contest中显示问题的详细说明界面:
contest.submit
的界面如下: