|
@@ -20,6 +20,8 @@ from apps.examination.exampaper.models import ExamPaper, ExamPaperDetail, ExamQu
|
|
|
from apps.examination.exampaper.filters import ExamPaperFilter
|
|
|
from apps.examination.exampaper.serializers import StaffExamPaperSerializer
|
|
|
from apps.examination.examquestion.models import ExamQuestionOption, ExamQuestionFill
|
|
|
+from apps.practise.errorbook.models import ErrorBook
|
|
|
+
|
|
|
|
|
|
class ExamPaperViewSet(CustomModelViewSet):
|
|
|
permission_classes = [IsStaff, ]
|
|
@@ -40,6 +42,23 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
queryset = queryset.filter(user=self.request.user)
|
|
|
return queryset
|
|
|
|
|
|
+ def retrieve(self, request, *args, **kwargs):
|
|
|
+ instance = self.get_object()
|
|
|
+ serializer = StaffExamLogRetrieveSerializer(instance)
|
|
|
+ answer_log = []
|
|
|
+ answer_logs = ExamAnswerLog.objects.filter(main=instance).order_by('detail__order')
|
|
|
+ for al in answer_logs:
|
|
|
+ item = {
|
|
|
+ 'id':al.id,
|
|
|
+ 'status':al.status,
|
|
|
+ }
|
|
|
+ answer_log.append(item)
|
|
|
+ result = {
|
|
|
+ 'question': serializer.data,
|
|
|
+ 'answer_log': answer_log,
|
|
|
+ }
|
|
|
+ return response_ok(result)
|
|
|
+
|
|
|
def create(self, request, *args, **kwargs):
|
|
|
exampaper_id = request.data.get('exampaper')
|
|
|
|
|
@@ -47,7 +66,6 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
with transaction.atomic():
|
|
|
exampaper = ExamPaper.getById(exampaper_id)
|
|
|
data = {
|
|
|
- 'subject': exampaper.subject.id,
|
|
|
'type': ExamPaper.MOCK,
|
|
|
'exampaper': exampaper_id,
|
|
|
'user': request.user.id,
|
|
@@ -69,6 +87,7 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
now_practise = request.data.get('now_practise') # 当前提交的模拟考试明细id。第一题或继续答题时,该参数为空
|
|
|
answers = json.loads(request.data.get('answers')) # 答案, 第一题或继续答题时,该参数为空
|
|
|
next_practise = request.data.get('next_practise') # 下一题id,首次加载第一题,传空
|
|
|
+
|
|
|
try:
|
|
|
with transaction.atomic():
|
|
|
instance = self.get_object()
|
|
@@ -80,60 +99,32 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
now_question = detail.question
|
|
|
if len(answers) > 0:
|
|
|
answer_log, create = ExamAnswerLog.objects.get_or_create(main=instance,
|
|
|
- detail=detail,)
|
|
|
- if now_question.type == ExamQuestion.SINGLE:
|
|
|
- # 单选
|
|
|
- ExamAnswerOptionLog.objects.filter(main=answer_log).delete()
|
|
|
- answer = answers[0]
|
|
|
- ExamAnswerOptionLog.objects.create(main=answer_log, option_id=answer)
|
|
|
- right = ExamQuestionOption.objects.filter(main=now_question, id=answer, right=True,
|
|
|
- delete=False)
|
|
|
- if right:
|
|
|
- answer_log.status = ExamAnswerLog.RIGHT
|
|
|
- else:
|
|
|
- answer_log.status = ExamAnswerLog.WRONG
|
|
|
- elif now_question.type == ExamQuestion.MULTIPLE:
|
|
|
- # 多选
|
|
|
+ detail=detail, )
|
|
|
+ if now_question.type <= ExamQuestion.MULTIPLE:
|
|
|
+ # 单选、多选
|
|
|
answers.sort()
|
|
|
ExamAnswerOptionLog.objects.filter(main=answer_log).delete()
|
|
|
for a in answers:
|
|
|
ExamAnswerOptionLog.objects.create(main=answer_log, option_id=a)
|
|
|
- right = ExamQuestionOption.objects.filter(main=now_question, right=True,
|
|
|
- delete=False).values_list('id', flat=True)
|
|
|
- list(right).sort()
|
|
|
- if answers == right:
|
|
|
- answer_log.status = ExamAnswerLog.RIGHT
|
|
|
- else:
|
|
|
- answer_log.status = ExamAnswerLog.WRONG
|
|
|
elif now_question.type == ExamQuestion.FILL:
|
|
|
# 填空
|
|
|
answers_len = len(answers)
|
|
|
- right = 1
|
|
|
ExamAnswerFillLog.objects.filter(main=answer_log).delete()
|
|
|
for a in range(0, answers_len):
|
|
|
ExamAnswerFillLog.objects.create(main=answer_log, content=answers[a], order=a + 1)
|
|
|
- right_answer = ExamQuestionFill.objects.filter(main=now_question, content=answers[a],
|
|
|
- order=a + 1)
|
|
|
- if not right_answer:
|
|
|
- # 有一个填空错误,整题错误
|
|
|
- right = 0
|
|
|
- if right:
|
|
|
- answer_log.status = ExamAnswerLog.RIGHT
|
|
|
- else:
|
|
|
- answer_log.status = ExamAnswerLog.WRONG
|
|
|
else:
|
|
|
# 判断
|
|
|
- if now_question.judgment == (answers[0] == 1):
|
|
|
+ if answers[0] == 1:
|
|
|
answer_log.status = ExamAnswerLog.RIGHT
|
|
|
else:
|
|
|
answer_log.status = ExamAnswerLog.WRONG
|
|
|
- answer_log.save()
|
|
|
+ answer_log.save()
|
|
|
else:
|
|
|
try:
|
|
|
- answer_log = ExamAnswerLog.objects.get(main=instance, question=now_question, )
|
|
|
+ answer_log = ExamAnswerLog.objects.get(main=instance, detail=detail)
|
|
|
ExamAnswerOptionLog.objects.filter(main=answer_log).delete()
|
|
|
ExamAnswerFillLog.objects.filter(main=answer_log).delete()
|
|
|
- answer_log.status = None
|
|
|
+ answer_log.status = ExamAnswerLog.NOTDONE
|
|
|
answer_log.save()
|
|
|
except ExamAnswerLog.DoesNotExist:
|
|
|
# traceback.print_exc()
|
|
@@ -142,7 +133,8 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
question_data = {}
|
|
|
# 返回下一题
|
|
|
if next_practise:
|
|
|
- detail = ExamPaperDetail.objects.filter(id=next_practise, main=instance.exampaper, delete=False).first()
|
|
|
+ detail = ExamPaperDetail.objects.filter(id=next_practise, main=instance.exampaper,
|
|
|
+ delete=False).first()
|
|
|
else:
|
|
|
detail = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False).first()
|
|
|
|
|
@@ -192,11 +184,11 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
|
|
|
# 右侧习题类别列表
|
|
|
# 单选、多选、填空。选择答案后,可能会把答案清空,得加上NOTDONE过滤
|
|
|
- questions = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False).values_list('id', flat=True)
|
|
|
+ questions = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False).values_list('id',
|
|
|
+ flat=True)
|
|
|
single_questions_list = []
|
|
|
for single in questions.filter(question__type=ExamQuestion.SINGLE):
|
|
|
- answer_log = ExamAnswerLog.objects.filter(main=instance, detail=single).exclude(
|
|
|
- status=ExamAnswerLog.NOTDONE)
|
|
|
+ answer_log = ExamAnswerLog.objects.filter(main=instance, detail=single)
|
|
|
single_questions_list.append(
|
|
|
{
|
|
|
'question_id': single,
|
|
@@ -206,8 +198,7 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
# 多选题
|
|
|
multiple_questions_list = []
|
|
|
for multiple in questions.filter(question__type=ExamQuestion.MULTIPLE):
|
|
|
- answer_log = ExamAnswerLog.objects.filter(main=instance, detail=multiple).exclude(
|
|
|
- status=ExamAnswerLog.NOTDONE)
|
|
|
+ answer_log = ExamAnswerLog.objects.filter(main=instance, detail=multiple)
|
|
|
multiple_questions_list.append(
|
|
|
{
|
|
|
'question_id': multiple,
|
|
@@ -217,8 +208,7 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
# 填空题
|
|
|
fill_questions_list = []
|
|
|
for fill in questions.filter(question__type=ExamQuestion.FILL):
|
|
|
- answer_log = ExamAnswerLog.objects.filter(main=instance, detail=fill).exclude(
|
|
|
- status=ExamAnswerLog.NOTDONE)
|
|
|
+ answer_log = ExamAnswerLog.objects.filter(main=instance, detail=fill)
|
|
|
fill_questions_list.append(
|
|
|
{
|
|
|
'question_id': fill,
|
|
@@ -228,8 +218,7 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
# 判断题
|
|
|
judgment_questions_list = []
|
|
|
for judgment in questions.filter(question__type=ExamQuestion.JUDGMENT):
|
|
|
- answer_log = ExamAnswerLog.objects.filter(main=instance, detail=judgment).exclude(
|
|
|
- status=ExamAnswerLog.NOTDONE)
|
|
|
+ answer_log = ExamAnswerLog.objects.filter(main=instance, detail=judgment)
|
|
|
judgment_questions_list.append(
|
|
|
{
|
|
|
'question_id': judgment,
|
|
@@ -257,51 +246,84 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
instance = self.get_object()
|
|
|
|
|
|
with transaction.atomic():
|
|
|
- answer_logs = ExamAnswerLog.objects.filter(main=instance)
|
|
|
- for answer_log in answer_logs:
|
|
|
- question = answer_log.detail.question
|
|
|
+ paper_details = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False)
|
|
|
+ for detail in paper_details:
|
|
|
+ # 创建模拟考试未答题记录,如果没有找到答案记录,则该题保留未答状态
|
|
|
+ answer_log, create = ExamAnswerLog.objects.get_or_create(main=instance, detail=detail)
|
|
|
+ # answer_logs = ExamAnswerLog.objects.filter(main=instance)
|
|
|
+ # for answer_log in answer_logs:
|
|
|
+ question = detail.question
|
|
|
if question.type == ExamQuestion.SINGLE:
|
|
|
# 单选
|
|
|
answers = ExamAnswerOptionLog.objects.filter(main=answer_log).first()
|
|
|
if answers:
|
|
|
if answers.option.right:
|
|
|
answer_log.status = ExamAnswerLog.RIGHT
|
|
|
+ instance.single_answer_count += 1
|
|
|
else:
|
|
|
answer_log.status = ExamAnswerLog.WRONG
|
|
|
+ ErrorBook.add_error(question, request.user, answer_log)
|
|
|
elif question.type == ExamQuestion.MULTIPLE:
|
|
|
# 多选
|
|
|
- answers = ExamAnswerOptionLog.objects.filter(main=answer_log).order_by('option_id').values_list('option_id', flat=True)
|
|
|
- right = ExamQuestionOption.objects.filter(main=question, right=True,
|
|
|
- delete=False).values_list('id', flat=True)
|
|
|
- if list(answers) == list(right):
|
|
|
- answer_log.status = ExamAnswerLog.RIGHT
|
|
|
- else:
|
|
|
- answer_log.status = ExamAnswerLog.WRONG
|
|
|
+ answers = ExamAnswerOptionLog.objects.filter(main=answer_log).order_by('option_id').values_list(
|
|
|
+ 'option_id', flat=True)
|
|
|
+ if answers:
|
|
|
+ right = ExamQuestionOption.objects.filter(main=question, right=True,
|
|
|
+ delete=False).values_list('id', flat=True)
|
|
|
+ if list(answers) == list(right):
|
|
|
+ answer_log.status = ExamAnswerLog.RIGHT
|
|
|
+ instance.multiple_answer_count += 1
|
|
|
+ else:
|
|
|
+ answer_log.status = ExamAnswerLog.WRONG
|
|
|
+ ErrorBook.add_error(question, request.user, answer_log)
|
|
|
elif question.type == ExamQuestion.FILL:
|
|
|
# 填空
|
|
|
fill_logs = ExamAnswerFillLog.objects.filter(main=answer_log)
|
|
|
right = True
|
|
|
- for fill_log in fill_logs:
|
|
|
- right_answer = ExamQuestionFill.objects.filter(main=question, content=fill_log.content,
|
|
|
- order=fill_log.order, delete=False)
|
|
|
- if not right_answer:
|
|
|
- right = False
|
|
|
- break
|
|
|
- if right:
|
|
|
- answer_log.status = ExamAnswerLog.RIGHT
|
|
|
- else:
|
|
|
- answer_log.status = ExamAnswerLog.WRONG
|
|
|
+ if fill_logs:
|
|
|
+ for fill_log in fill_logs:
|
|
|
+ right_answer = ExamQuestionFill.objects.filter(main=question, content=fill_log.content,
|
|
|
+ order=fill_log.order, delete=False)
|
|
|
+ if not right_answer:
|
|
|
+ right = False
|
|
|
+ break
|
|
|
+ if right:
|
|
|
+ answer_log.status = ExamAnswerLog.RIGHT
|
|
|
+ instance.fill_answer_count += 1
|
|
|
+ else:
|
|
|
+ answer_log.status = ExamAnswerLog.WRONG
|
|
|
+ ErrorBook.add_error(question, request.user, answer_log)
|
|
|
else:
|
|
|
# 判断
|
|
|
- if question.judgment == (answer_log.status == ExamAnswerLog.RIGHT):
|
|
|
- answer_log.status = ExamAnswerLog.RIGHT
|
|
|
- else:
|
|
|
- answer_log.status = ExamAnswerLog.WRONG
|
|
|
+ if answer_log.status != ExamAnswerLog.NOTDONE:
|
|
|
+ if question.judgment == (answer_log.status == ExamAnswerLog.RIGHT):
|
|
|
+ answer_log.status = ExamAnswerLog.RIGHT
|
|
|
+ instance.judgment_answer_count += 1
|
|
|
+ else:
|
|
|
+ answer_log.status = ExamAnswerLog.WRONG
|
|
|
+ ErrorBook.add_error(question, request.user, answer_log)
|
|
|
answer_log.save()
|
|
|
|
|
|
instance.submit_time = timezone.now()
|
|
|
+ use_time = instance.exam_time - instance.submit_time
|
|
|
+ instance.use_time = use_time.seconds
|
|
|
+
|
|
|
+ single_answer_scores = instance.single_answer_count * instance.exampaper.single_scores
|
|
|
+ multiple_answer_scores = instance.multiple_answer_count * instance.exampaper.multiple_scores
|
|
|
+ fill_answer_scores = instance.fill_answer_count * instance.exampaper.fill_scores
|
|
|
+ judgment_answer_scores = instance.judgment_answer_count * instance.exampaper.judgment_scores
|
|
|
+
|
|
|
+ instance.single_answer_scores = single_answer_scores
|
|
|
+ instance.multiple_answer_scores = multiple_answer_scores
|
|
|
+ instance.fill_answer_scores = fill_answer_scores
|
|
|
+ instance.judgment_answer_scores = judgment_answer_scores
|
|
|
+ instance.scores = single_answer_scores + judgment_answer_scores + multiple_answer_scores + fill_answer_scores
|
|
|
instance.save()
|
|
|
- SysLog.objects.addnew(request.user, SysLog.INSERT, u"提交模拟考试题答案,id=%d" % (instance.id))
|
|
|
+
|
|
|
+ instance.exampaper.did_count += 1
|
|
|
+ instance.exampaper.save()
|
|
|
+
|
|
|
+ SysLog.objects.addnew(request.user, SysLog.INSERT, u"提交模拟考试题,id=%d" % (instance.id))
|
|
|
except CustomError as e:
|
|
|
return response_error(e.get_error_msg())
|
|
|
except Exception as e:
|
|
@@ -309,6 +331,7 @@ class ExamLogViewSet(CustomModelViewSet):
|
|
|
return response_error(str(e))
|
|
|
return response_ok()
|
|
|
|
|
|
+
|
|
|
class DictView(APIView):
|
|
|
permission_classes = [IsStaff, ]
|
|
|
|