Refactor physics exam review scoring to count true/false sub-questions individually and improve accuracy of correct answer calculations
This commit is contained in:
+45
-9
@@ -1283,17 +1283,53 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
# If we have responses, iterate and count fully-correct answers using
|
# If we have responses, iterate and count fully-correct answers using
|
||||||
# the model's get_answer_score() which encapsulates per-app logic.
|
# the model's get_answer_score() which encapsulates per-app logic.
|
||||||
if total_responses:
|
if total_responses:
|
||||||
cnt = 0
|
# Special-case physics: count each true/false sub-question individually.
|
||||||
for ua in ua_qs:
|
if self.app_name == "physics":
|
||||||
|
# Determine number of sub-items per question
|
||||||
try:
|
try:
|
||||||
score = ua.get_answer_score()
|
n_sub = len(q.get_questions())
|
||||||
except Exception:
|
except Exception:
|
||||||
# If get_answer_score fails for any answer, skip it
|
n_sub = None
|
||||||
continue
|
|
||||||
if score == per_question_max:
|
total_subitems = 0
|
||||||
cnt += 1
|
correct_subitems = 0
|
||||||
correct_count = cnt
|
for ua in ua_qs:
|
||||||
correct_pct = round(100.0 * correct_count / total_responses, 1) if total_responses else 0.0
|
try:
|
||||||
|
score = ua.get_answer_score()
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
# score is expected to be iterable (tuple/list) for physics
|
||||||
|
if isinstance(score, (list, tuple)) and score:
|
||||||
|
# count numeric-typed positive/1 values as correct
|
||||||
|
for s in score:
|
||||||
|
if isinstance(s, (int, float)) and s > 0:
|
||||||
|
correct_subitems += 1
|
||||||
|
total_subitems += len(score)
|
||||||
|
else:
|
||||||
|
# fallback: treat scalar score as single subitem
|
||||||
|
if isinstance(score, (int, float)):
|
||||||
|
if score > 0:
|
||||||
|
correct_subitems += 1
|
||||||
|
total_subitems += 1
|
||||||
|
|
||||||
|
# Compute percent over all subitems seen
|
||||||
|
correct_count = correct_subitems
|
||||||
|
if total_subitems:
|
||||||
|
correct_pct = round(100.0 * correct_subitems / total_subitems, 1)
|
||||||
|
else:
|
||||||
|
correct_pct = 0.0
|
||||||
|
else:
|
||||||
|
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
|
||||||
else:
|
else:
|
||||||
correct_count = 0
|
correct_count = 0
|
||||||
correct_pct = 0.0
|
correct_pct = 0.0
|
||||||
|
|||||||
+19
-14
@@ -522,27 +522,32 @@ def exam_review_question_summary(request, pk: int, q_index: int):
|
|||||||
correct_count = None
|
correct_count = None
|
||||||
correct_pct = None
|
correct_pct = None
|
||||||
try:
|
try:
|
||||||
# per-question max for physics is 5 (see generic.get_max_score mapping)
|
# For physics, count true/false sub-questions individually rather than
|
||||||
per_question_max = 5
|
# requiring a full-match across all parts.
|
||||||
if total_responses:
|
if total_responses:
|
||||||
cnt = 0
|
correct_subitems = 0
|
||||||
|
total_subitems = 0
|
||||||
for ua in ua_qs:
|
for ua in ua_qs:
|
||||||
try:
|
try:
|
||||||
score = ua.get_answer_score()
|
score = ua.get_answer_score()
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
if isinstance(score, (list, tuple)):
|
if isinstance(score, (list, tuple)) and score:
|
||||||
try:
|
for s in score:
|
||||||
ssum = sum([s for s in score if isinstance(s, (int, float))])
|
if isinstance(s, (int, float)) and s > 0:
|
||||||
except Exception:
|
correct_subitems += 1
|
||||||
continue
|
total_subitems += len(score)
|
||||||
if ssum == per_question_max:
|
|
||||||
cnt += 1
|
|
||||||
else:
|
else:
|
||||||
if isinstance(score, (int, float)) and score == per_question_max:
|
if isinstance(score, (int, float)):
|
||||||
cnt += 1
|
if score > 0:
|
||||||
correct_count = cnt
|
correct_subitems += 1
|
||||||
correct_pct = round(100.0 * correct_count / total_responses, 1) if total_responses else 0.0
|
total_subitems += 1
|
||||||
|
|
||||||
|
correct_count = correct_subitems
|
||||||
|
if total_subitems:
|
||||||
|
correct_pct = round(100.0 * correct_subitems / total_subitems, 1)
|
||||||
|
else:
|
||||||
|
correct_pct = 0.0
|
||||||
else:
|
else:
|
||||||
correct_count = 0
|
correct_count = 0
|
||||||
correct_pct = 0.0
|
correct_pct = 0.0
|
||||||
|
|||||||
Reference in New Issue
Block a user