from collections import defaultdict
|
|
from fastapi import APIRouter, Depends, HTTPException
|
from sqlalchemy import select
|
from sqlalchemy.orm import Session
|
|
from app.auth import get_current_user
|
from app.database import get_db
|
from app.grader_scope import assert_subject_allowed
|
from app.models import (
|
ExamPaperMap,
|
ExaminationExamExaminee,
|
ExaminationExaminee,
|
ExaminationExamineeExamAnswerItem,
|
ExaminationPaperItem,
|
ExaminationPaperSource,
|
ImportBatch,
|
User,
|
)
|
from app.schemas import AttemptDetail, PartGroup, QuestionDetail
|
|
router = APIRouter(prefix="/api", tags=["attempts"])
|
|
|
@router.get("/attempts/{attempt_id}", response_model=AttemptDetail)
|
def get_attempt(
|
attempt_id: str,
|
db: Session = Depends(get_db),
|
user: User = Depends(get_current_user),
|
):
|
try:
|
attempt_pk = int(attempt_id)
|
except ValueError:
|
raise HTTPException(404, detail="记录不存在")
|
attempt = db.get(ExaminationExamExaminee, attempt_pk)
|
if not attempt:
|
raise HTTPException(404, detail="记录不存在")
|
examinee = db.get(ExaminationExaminee, attempt.examinee_id)
|
batch = db.get(ImportBatch, attempt.import_batch_id)
|
assert_subject_allowed(db, user, batch.subject_name if batch else None)
|
pmap = db.scalar(
|
select(ExamPaperMap).where(ExamPaperMap.exam_id == attempt.exam_id)
|
)
|
paper_id = pmap.paper_source_id if pmap else (batch.paper_source_id if batch else None)
|
paper = db.get(ExaminationPaperSource, paper_id) if paper_id else None
|
|
items = list(
|
db.scalars(
|
select(ExaminationPaperItem)
|
.where(ExaminationPaperItem.paper_source_id == paper_id)
|
.order_by(ExaminationPaperItem.part_ref, ExaminationPaperItem.item_order)
|
)
|
) if paper else []
|
|
answer_items = {
|
ai.external_item_id: ai
|
for ai in db.scalars(
|
select(ExaminationExamineeExamAnswerItem).where(
|
ExaminationExamineeExamAnswerItem.exam_examinee_id == attempt_pk
|
)
|
)
|
}
|
|
groups: dict[str, list[QuestionDetail]] = defaultdict(list)
|
part_order: list[str] = []
|
for it in items:
|
pn = it.part_name or "题目"
|
if pn not in part_order:
|
part_order.append(pn)
|
ai = answer_items.get(it.external_item_id)
|
groups[pn].append(
|
QuestionDetail(
|
external_item_id=it.external_item_id,
|
part_name=it.part_name,
|
item_type=it.item_type,
|
item_order=it.item_order,
|
title_html=it.title_html,
|
detail_json=it.detail_json,
|
max_score=it.max_score,
|
reference_answer=it.reference_answer,
|
user_answer=ai.answer_raw if ai else None,
|
is_correct=ai.is_correct if ai else False,
|
score=ai.score if ai else 0,
|
)
|
)
|
|
return AttemptDetail(
|
attempt_id=str(attempt.id),
|
examinee_name=examinee.nickname if examinee else None,
|
id_card=examinee.id_card if examinee else None,
|
score=attempt.score,
|
paper_total_score=paper.total_score if paper else None,
|
paper_name=paper.paper_name if paper else None,
|
subject_name=batch.subject_name if batch else None,
|
room_id=attempt.room_id,
|
seat_number=attempt.seat_number,
|
start_time=attempt.start_time,
|
end_time=attempt.end_time,
|
parts=[PartGroup(part_name=p, questions=groups[p]) for p in part_order],
|
)
|