Add primary answer display to exam review question fragment and ensure safe rendering of question text
This commit is contained in:
+78
-18
@@ -1214,15 +1214,44 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
else:
|
||||
pcts = {k: 0.0 for k in counts.keys()}
|
||||
|
||||
# Compute percent correct where a best_answer exists
|
||||
# Compute percent correct using per-answer scoring when available.
|
||||
# Different apps use different scoring scales (e.g. anatomy/rapids=2, longs=8,
|
||||
# physics/shorts=5, sbas=1). We determine the per-question maximum based on
|
||||
# the app and count user answers whose get_answer_score() equals that max.
|
||||
correct_pct = None
|
||||
correct_count = None
|
||||
if hasattr(q, "best_answer") and getattr(q, "best_answer", None):
|
||||
try:
|
||||
correct_count = ua_qs.filter(answer=q.best_answer).count()
|
||||
try:
|
||||
# Determine per-question maximum score for this app
|
||||
if self.app_name in ("rapids", "anatomy"):
|
||||
per_question_max = 2
|
||||
elif self.app_name == "longs":
|
||||
per_question_max = 8
|
||||
elif self.app_name in ("physics", "shorts"):
|
||||
per_question_max = 5
|
||||
else:
|
||||
per_question_max = 1
|
||||
|
||||
# If we have responses, iterate and count fully-correct answers using
|
||||
# the model's get_answer_score() which encapsulates per-app logic.
|
||||
if total_responses:
|
||||
cnt = 0
|
||||
for ua in ua_qs:
|
||||
try:
|
||||
score = ua.get_answer_score()
|
||||
except Exception:
|
||||
# If get_answer_score fails for any answer, skip it
|
||||
continue
|
||||
if score == per_question_max:
|
||||
cnt += 1
|
||||
correct_count = cnt
|
||||
correct_pct = round(100.0 * correct_count / total_responses, 1) if total_responses else 0.0
|
||||
except Exception:
|
||||
correct_pct = None
|
||||
else:
|
||||
correct_count = 0
|
||||
correct_pct = 0.0
|
||||
except Exception:
|
||||
# Best-effort: fall back to None if something unexpected happens
|
||||
correct_pct = None
|
||||
correct_count = None
|
||||
|
||||
# Percent answered relative to candidate pool (if known)
|
||||
answered_pct = None
|
||||
@@ -1343,20 +1372,51 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
for k in counts.keys():
|
||||
pcts[k] = 0.0
|
||||
|
||||
# If the question exposes a best_answer, compute correct count
|
||||
# Compute correct count using per-answer scoring when available.
|
||||
# Different apps use different scoring scales (e.g. anatomy/rapids=2,
|
||||
# longs=8, physics/shorts=5, sbas=1). Determine per-question max
|
||||
# and count answers where get_answer_score() equals that max.
|
||||
correct_count = None
|
||||
if hasattr(question, "best_answer") and question.best_answer:
|
||||
correct_count = ua_qs.filter(answer=question.best_answer).count()
|
||||
else:
|
||||
correct_count = None
|
||||
|
||||
# percent correct
|
||||
correct_pct = None
|
||||
if correct_count is not None and total_responses:
|
||||
try:
|
||||
correct_pct = round(100.0 * correct_count / total_responses, 1)
|
||||
except Exception:
|
||||
correct_pct = None
|
||||
try:
|
||||
if self.app_name in ("rapids", "anatomy"):
|
||||
per_question_max = 2
|
||||
elif self.app_name == "longs":
|
||||
per_question_max = 8
|
||||
elif self.app_name in ("physics", "shorts"):
|
||||
per_question_max = 5
|
||||
else:
|
||||
per_question_max = 1
|
||||
|
||||
if total_responses:
|
||||
cnt = 0
|
||||
for ua in ua_qs:
|
||||
try:
|
||||
score = ua.get_answer_score()
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# Handle tuple/list scores (physics) by summing parts
|
||||
if isinstance(score, (list, tuple)):
|
||||
try:
|
||||
ssum = sum([s for s in score if isinstance(s, (int, float))])
|
||||
except Exception:
|
||||
continue
|
||||
if ssum == per_question_max:
|
||||
cnt += 1
|
||||
else:
|
||||
# Numeric scores only; skip 'unmarked' / None
|
||||
if isinstance(score, (int, float)) and score == per_question_max:
|
||||
cnt += 1
|
||||
|
||||
correct_count = cnt
|
||||
correct_pct = round(100.0 * correct_count / total_responses, 1) if total_responses else 0.0
|
||||
else:
|
||||
correct_count = 0
|
||||
correct_pct = 0.0
|
||||
except Exception:
|
||||
correct_count = None
|
||||
correct_pct = None
|
||||
|
||||
context.update(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user