feat: complete exam lifecycle — AI generation, submission, student session, and results
- Backend: AI generation fallbacks when OpenAI not configured, full exam submission saving all params (difficulty, rubric, entity, grading system, approval workflow) and creating linked question records per section - Backend: new exam session controller with get_session, autosave, submit, status, and results endpoints; student attempt/answer/score models - Backend: new controllers for entities, approval workflows, exam schedules - Frontend: exam session split-layout with passage panel, question types (MCQ, T/F/NG, gap-fill, writing, speaking), timer, and review dialog - Frontend: results page with percentage score, per-answer breakdown table - Frontend: generation page dynamic dropdowns, full payload submission - Frontend: updated types for ExamSessionSection, ExamQuestion options Made-with: Cursor
This commit is contained in:
@@ -186,21 +186,38 @@ class EncoachExamSessionController(http.Controller):
|
||||
q_dict = _question_to_student_dict(q)
|
||||
q_dict['saved_answer'] = saved_answers.get(q.id, '')
|
||||
questions.append(q_dict)
|
||||
sections.append({
|
||||
sec_dict = {
|
||||
'id': sec.id,
|
||||
'title': sec.title,
|
||||
'skill': sec.skill or '',
|
||||
'difficulty': sec.difficulty or '',
|
||||
'time_limit_min': sec.time_limit_min or 0,
|
||||
'total_marks': sec.total_marks or 0,
|
||||
'scoring_method': sec.scoring_method or 'auto',
|
||||
'sequence': sec.sequence,
|
||||
'questions': questions,
|
||||
})
|
||||
}
|
||||
if sec.passage_text:
|
||||
sec_dict['passage_text'] = sec.passage_text
|
||||
if sec.instructions_text:
|
||||
sec_dict['instructions_text'] = sec.instructions_text
|
||||
if sec.content_json:
|
||||
try:
|
||||
sec_dict['content'] = json.loads(sec.content_json)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
pass
|
||||
sections.append(sec_dict)
|
||||
|
||||
return _json_response({
|
||||
'attempt_id': attempt.id,
|
||||
'exam_id': exam.id,
|
||||
'exam_title': exam.title,
|
||||
'exam_mode': exam.exam_mode or 'official',
|
||||
'total_time_min': exam.total_time_min or 0,
|
||||
'total_marks': exam.total_marks or 0,
|
||||
'grading_system': exam.grading_system or 'ielts',
|
||||
'access_type': exam.access_type or 'private',
|
||||
'randomize_questions': exam.randomize_questions or False,
|
||||
'status': attempt.status,
|
||||
'started_at': attempt.started_at,
|
||||
'sections': sections,
|
||||
|
||||
Reference in New Issue
Block a user