Enhance exam review summary to include dominant score for top submitted answers

This commit is contained in:
Ross
2025-11-10 10:38:13 +00:00
parent d0609e4f8e
commit ecf67e3c2b
2 changed files with 45 additions and 5 deletions
@@ -67,9 +67,20 @@
{% if top_answers %}
<ul class="list-group">
{% for a in top_answers %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div>{{ a.answer_compare }}</div>
<div class="small text-muted">{{ a.count }}</div>
<li class="list-group-item d-flex justify-content-between align-items-center">
<div class="flex-grow-1">{{ a.answer_compare }}</div>
<div class="d-flex align-items-center">
{% if a.dominant_score == '2' %}
<span class="badge bg-success">Correct</span>
{% elif a.dominant_score == '1' %}
<span class="badge bg-warning text-dark">Half</span>
{% elif a.dominant_score == '0' %}
<span class="badge bg-danger">Incorrect</span>
{% else %}
<span class="badge bg-secondary">Unmarked</span>
{% endif %}
<div class="small text-muted me-2">{{ a.count }}</div>
</div>
</li>
{% endfor %}
</ul>
+31 -2
View File
@@ -316,8 +316,37 @@ def exam_review_question_summary(request, pk: int, q_index: int):
# simpler: compute via values and normalise unmarked -> 'empty'
score_counts = {str(row["score"]) if row["score"] is not None else "empty": row["count"] for row in ua_qs.values("score").annotate(count=Count("id"))}
# top submitted answers (by answer_compare)
top_answers = list(ua_qs.values("answer_compare").annotate(count=Count("id")).order_by("-count")[:10])
# top submitted answers (by answer_compare) with dominant score per answer
# First, get counts grouped by answer_compare and score
grouped = ua_qs.values("answer_compare", "score").annotate(count=Count("id"))
# Aggregate totals and score breakdown per answer_compare
answer_map = {}
for row in grouped:
ans = row["answer_compare"]
sc = str(row["score"]) if row["score"] is not None else "empty"
cnt = row["count"]
if ans not in answer_map:
answer_map[ans] = {"total": 0, "score_counts": {}}
answer_map[ans]["total"] += cnt
answer_map[ans]["score_counts"][sc] = answer_map[ans]["score_counts"].get(sc, 0) + cnt
# Build list sorted by total count desc, and choose a dominant score per answer
top_answers = []
for ans, meta in answer_map.items():
# pick dominant score by highest count; tie-break prefer higher numeric score
score_counts = meta["score_counts"]
# sort by (count desc, score desc) where 'empty' maps to -1
def score_key(item):
s, c = item
s_val = -1 if s == "empty" else int(s)
return (c, s_val)
dominant = max(score_counts.items(), key=score_key)[0]
top_answers.append({"answer_compare": ans, "count": meta["total"], "dominant_score": dominant})
top_answers.sort(key=lambda x: x["count"], reverse=True)
top_answers = top_answers[:10]
correct_count = None
correct_pct = None