247 lines
9.8 KiB
Python
247 lines
9.8 KiB
Python
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
|
|||
|
|
import datetime
|
|||
|
|
import random
|
|||
|
|
|
|||
|
|
from django.db import transaction
|
|||
|
|
from django.views.decorators.csrf import csrf_exempt
|
|||
|
|
|
|||
|
|
from account.models import Profile, UserInfo
|
|||
|
|
from competition.models import (BankInfo, ChoiceInfo, CompetitionKindInfo,
|
|||
|
|
CompetitionQAInfo, FillInBlankInfo)
|
|||
|
|
from TimeConvert import TimeConvert as tc
|
|||
|
|
|
|||
|
|
from utils.check_utils import check_correct_num
|
|||
|
|
from utils.decorators import check_copstatus, check_login
|
|||
|
|
from utils.errors import BankInfoNotFound, CompetitionError, ProfileError
|
|||
|
|
from utils.redis.rprofile import enter_userinfo
|
|||
|
|
from utils.redis.rrank import add_to_rank
|
|||
|
|
from utils.response import json_response
|
|||
|
|
|
|||
|
|
|
|||
|
|
@check_login
|
|||
|
|
@check_copstatus
|
|||
|
|
@transaction.atomic
|
|||
|
|
def get_questions(request):
|
|||
|
|
"""
|
|||
|
|
获取题目信息接口
|
|||
|
|
:param request: 请求对象
|
|||
|
|
:return: 返回json数据: user_info: 用户信息;kind_info: 比赛信息;qa_id: 比赛答题记录;questions: 比赛随机后的题目;
|
|||
|
|
"""
|
|||
|
|
kind_id = request.GET.get('kind_id', '') # 获取kind_id
|
|||
|
|
uid = request.GET.get('uid', '') # 获取uid
|
|||
|
|
try: # 获取比赛信息
|
|||
|
|
kind_info = CompetitionKindInfo.objects.select_for_update().get(kind_id=kind_id)
|
|||
|
|
except CompetitionKindInfo.DoesNotExist: # 未获取到,返回错误码100001
|
|||
|
|
return json_response(*CompetitionError.CompetitionNotFound)
|
|||
|
|
try: # 获取题库信息
|
|||
|
|
bank_info = BankInfo.objects.get(bank_id=kind_info.bank_id)
|
|||
|
|
except BankInfo.DoesNotExist: # 未获取到,返回错误码100004
|
|||
|
|
return json_response(*CompetitionError.BankInfoNotFound)
|
|||
|
|
try: # 获取用户信息
|
|||
|
|
profile = Profile.objects.get(uid=uid)
|
|||
|
|
except Profile.DoesNotExist: # 未获取到,返回错误码200001
|
|||
|
|
return json_response(*ProfileError.ProfileNotFound)
|
|||
|
|
qc = ChoiceInfo.objects.filter(bank_id=kind_info.bank_id) # 选择题
|
|||
|
|
qf = FillInBlankInfo.objects.filter(bank_id=kind_info.bank_id) # 填空题
|
|||
|
|
questions = [] # 将两种题型放到同一个列表中
|
|||
|
|
for i in qc.iterator():
|
|||
|
|
questions.append(i.data)
|
|||
|
|
for i in qf.iterator():
|
|||
|
|
questions.append(i.data)
|
|||
|
|
question_num = kind_info.question_num # 出题数
|
|||
|
|
q_count = bank_info.total_question_num # 总题数
|
|||
|
|
if q_count < question_num: # 出题数大于总题数,返回错误码100005
|
|||
|
|
return json_response(CompetitionError.QuestionNotSufficient)
|
|||
|
|
qs = random.sample(questions, question_num) # 随机分配题目
|
|||
|
|
qa_info = CompetitionQAInfo.objects.select_for_update().create( # 创建答题log数据
|
|||
|
|
kind_id=kind_id,
|
|||
|
|
uid=uid,
|
|||
|
|
qsrecord=[q['question'] for q in qs],
|
|||
|
|
asrecord=[q['answer'] for q in qs],
|
|||
|
|
total_num=question_num,
|
|||
|
|
started_stamp=tc.utc_timestamp(ms=True, milli=True), # 设置开始时间戳
|
|||
|
|
started=True
|
|||
|
|
)
|
|||
|
|
for i in qs: # 剔除答案信息
|
|||
|
|
i.pop('answer')
|
|||
|
|
return json_response(200, 'OK', { # 返回JSON数据,包括题目信息,答题log信息等
|
|||
|
|
'kind_info': kind_info.data,
|
|||
|
|
'user_info': profile.data,
|
|||
|
|
'qa_id': qa_info.qa_id,
|
|||
|
|
'questions': qs
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
@csrf_exempt
|
|||
|
|
@check_login
|
|||
|
|
@check_copstatus
|
|||
|
|
@transaction.atomic
|
|||
|
|
def submit_answer(request):
|
|||
|
|
"""
|
|||
|
|
提交答案接口
|
|||
|
|
:param request: 请求对象
|
|||
|
|
:return: 返回json数据: user_info: 用户信息; qa_id: 比赛答题记录标识; kind_id: 比赛唯一标识
|
|||
|
|
"""
|
|||
|
|
stop_stamp = tc.utc_timestamp(ms=True, milli=True) # 结束时间戳
|
|||
|
|
qa_id = request.POST.get('qa_id', '') # 获取qa_id
|
|||
|
|
uid = request.POST.get('uid', '') # 获取uid
|
|||
|
|
kind_id = request.POST.get('kind_id', '') # 获取kind_id
|
|||
|
|
answer = request.POST.get('answer', '') # 获取answer
|
|||
|
|
try: # 获取比赛信息
|
|||
|
|
kind_info = CompetitionKindInfo.objects.get(kind_id=kind_id)
|
|||
|
|
except CompetitionKindInfo.DoesNotExist: # 未获取到,返回错误码100001
|
|||
|
|
return json_response(*CompetitionError.CompetitionNotFound)
|
|||
|
|
try: # 获取题库信息
|
|||
|
|
bank_info = BankInfo.objects.get(bank_id=kind_info.bank_id)
|
|||
|
|
except BankInfo.DoesNotExist: # 未获取到返回错误码100004
|
|||
|
|
return json_response(*CompetitionError.BankInfoNotFound)
|
|||
|
|
try: # 获取用户信息
|
|||
|
|
profile = Profile.objects.get(uid=uid)
|
|||
|
|
except Profile.DoesNotExist: # 未获取到,返回错误码200001
|
|||
|
|
return json_response(*ProfileError.ProfileNotFound)
|
|||
|
|
try: # 获取答题log信息
|
|||
|
|
qa_info = CompetitionQAInfo.objects.select_for_update().get(qa_id=qa_id)
|
|||
|
|
except CompetitionQAInfo.DoesNotExist: # 未获取到,返回错误码100006
|
|||
|
|
return json_response(*CompetitionError.QuestionNotFound)
|
|||
|
|
|
|||
|
|
answer = answer.rstrip('#').split('#') # 处理答案数据
|
|||
|
|
total, correct, wrong = check_correct_num(answer) # 检查答题情况
|
|||
|
|
qa_info.aslogrecord = answer
|
|||
|
|
qa_info.finished_stamp = stop_stamp
|
|||
|
|
qa_info.expend_time = stop_stamp - qa_info.started_stamp
|
|||
|
|
qa_info.finished = True
|
|||
|
|
qa_info.correct_num = correct if total == qa_info.total_num else 0
|
|||
|
|
qa_info.incorrect_num = wrong if total == qa_info.total_num else qa_info.total_num
|
|||
|
|
qa_info.save() # 保存答题log
|
|||
|
|
if qa_info.correct_num == kind_info.question_num: # 得分处理
|
|||
|
|
score = kind_info.total_score
|
|||
|
|
elif not qa_info.correct_num:
|
|||
|
|
score = 0
|
|||
|
|
else:
|
|||
|
|
score = round((kind_info.total_score / kind_info.question_num) * correct, 3)
|
|||
|
|
qa_info.score = score # 继续保存答题log
|
|||
|
|
qa_info.save()
|
|||
|
|
kind_info.total_partin_num += 1 # 保存比赛数据
|
|||
|
|
kind_info.save() # 比赛答题次数
|
|||
|
|
bank_info.partin_num += 1
|
|||
|
|
bank_info.save() # 题库答题次数
|
|||
|
|
if (kind_info.period_time > 0) and (qa_info.expend_time > kind_info.period_time * 60 * 1000): # 超时,不加入排行榜
|
|||
|
|
qa_info.status = CompetitionQAInfo.OVERTIME
|
|||
|
|
qa_info.save()
|
|||
|
|
else: # 正常完成,加入排行榜
|
|||
|
|
add_to_rank(uid, kind_id, qa_info.score, qa_info.expend_time)
|
|||
|
|
qa_info.status = CompetitionQAInfo.COMPLETED
|
|||
|
|
qa_info.save()
|
|||
|
|
return json_response(200, 'OK', { # 返回JSON数据
|
|||
|
|
'qa_id': qa_id,
|
|||
|
|
'user_info': profile.data,
|
|||
|
|
'kind_id': kind_id,
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
|
|||
|
|
@csrf_exempt
|
|||
|
|
@check_login
|
|||
|
|
@check_copstatus
|
|||
|
|
@transaction.atomic
|
|||
|
|
def userinfo_entry(request):
|
|||
|
|
"""
|
|||
|
|
用户表单提交接口
|
|||
|
|
:param request: 请求对象
|
|||
|
|
:return: 返回json数据: user_info: 用户信息; kind_info: 比赛信息
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
uid = request.POST.get('uid', '')
|
|||
|
|
kind_id = request.POST.get('kind_id', '')
|
|||
|
|
result = request.POST.get('result', '')
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
profile = Profile.objects.get(uid=uid)
|
|||
|
|
except Profile.DoesNotExist:
|
|||
|
|
return json_response(*ProfileError.ProfileNotFound)
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
kind_info = CompetitionKindInfo.objects.get(kind_id=kind_id)
|
|||
|
|
except CompetitionKindInfo.DoesNotExist:
|
|||
|
|
return json_response(*CompetitionError.CompetitionNotFound)
|
|||
|
|
|
|||
|
|
rl = [i.split(',') for i in result.rstrip('#').split('#')]
|
|||
|
|
|
|||
|
|
ui, _ = UserInfo.objects.select_for_update().get_or_create(
|
|||
|
|
uid=uid,
|
|||
|
|
kind_id=kind_id
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
for i in rl:
|
|||
|
|
if hasattr(UserInfo, i[0]):
|
|||
|
|
setattr(ui, i[0], i[1])
|
|||
|
|
ui.save()
|
|||
|
|
|
|||
|
|
enter_userinfo(kind_id, uid)
|
|||
|
|
|
|||
|
|
return json_response(200, 'OK', {
|
|||
|
|
'user_info': profile.data,
|
|||
|
|
'kind_info': kind_info.data
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
@csrf_exempt
|
|||
|
|
def games(request, s):
|
|||
|
|
"""
|
|||
|
|
获取所有比赛接口
|
|||
|
|
:param request: 请求对象
|
|||
|
|
:param s: 请求关键字
|
|||
|
|
:return: 返回该请求关键字对应的所有比赛类别
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
if s == 'hot':
|
|||
|
|
# 筛选条件: 完成时间大于当前时间;根据参与人数降序排序;根据创建时间降序排序;筛选10个
|
|||
|
|
kinds = CompetitionKindInfo.objects.filter(
|
|||
|
|
cop_finishat__gt=datetime.datetime.now(tz=datetime.timezone.utc),
|
|||
|
|
).order_by('-total_partin_num').order_by('-created_at')[:10]
|
|||
|
|
|
|||
|
|
elif s == 'tech':
|
|||
|
|
kinds = CompetitionKindInfo.objects.filter(
|
|||
|
|
kind_type=CompetitionKindInfo.IT_ISSUE,
|
|||
|
|
cop_finishat__gt=datetime.datetime.now(tz=datetime.timezone.utc)
|
|||
|
|
).order_by('-total_partin_num').order_by('-created_at')
|
|||
|
|
|
|||
|
|
elif s == 'edu':
|
|||
|
|
kinds = CompetitionKindInfo.objects.filter(
|
|||
|
|
kind_type=CompetitionKindInfo.EDUCATION,
|
|||
|
|
cop_finishat__gt=datetime.datetime.now(tz=datetime.timezone.utc)
|
|||
|
|
).order_by('-total_partin_num').order_by('-created_at')
|
|||
|
|
|
|||
|
|
elif s == 'culture':
|
|||
|
|
kinds = CompetitionKindInfo.objects.filter(
|
|||
|
|
kind_type=CompetitionKindInfo.CULTURE,
|
|||
|
|
cop_finishat__gt=datetime.datetime.now(tz=datetime.timezone.utc)
|
|||
|
|
).order_by('-total_partin_num').order_by('-created_at')
|
|||
|
|
|
|||
|
|
elif s == 'sport':
|
|||
|
|
kinds = CompetitionKindInfo.objects.filter(
|
|||
|
|
kind_type=CompetitionKindInfo.SPORT,
|
|||
|
|
cop_finishat__gt=datetime.datetime.now(tz=datetime.timezone.utc)
|
|||
|
|
).order_by('-total_partin_num').order_by('-created_at')
|
|||
|
|
|
|||
|
|
elif s == 'general':
|
|||
|
|
kinds = CompetitionKindInfo.objects.filter(
|
|||
|
|
kind_type=CompetitionKindInfo.GENERAL,
|
|||
|
|
cop_finishat__gt=datetime.datetime.now(tz=datetime.timezone.utc)
|
|||
|
|
).order_by('-total_partin_num').order_by('-created_at')
|
|||
|
|
|
|||
|
|
elif s == 'interview':
|
|||
|
|
kinds = CompetitionKindInfo.objects.filter(
|
|||
|
|
kind_type=CompetitionKindInfo.INTERVIEW,
|
|||
|
|
cop_finishat__gt=datetime.datetime.now(tz=datetime.timezone.utc)
|
|||
|
|
).order_by('-total_partin_num').order_by('-created_at')
|
|||
|
|
|
|||
|
|
else:
|
|||
|
|
kinds = None
|
|||
|
|
|
|||
|
|
uid = request.session.get('uid', '')
|
|||
|
|
return json_response(200, 'OK', {
|
|||
|
|
'kinds': [i.data for i in kinds],
|
|||
|
|
'uid' : uid
|
|||
|
|
})
|