Project-2 baseline

This commit is contained in:
2026-10-04 21:19:23 -04:00
parent 0f04889edf
commit 213eb3c403
861 changed files with 1710 additions and 3363322 deletions

View File

@@ -18,9 +18,11 @@ the grader agent score each atomic rubric criterion independently and write
certain_dealbreaker=5 (Critical), possible_dealbreaker=2 (Major),
unlikely_dealbreaker=1 (Minor); dodged_bullet criteria are weighted by
their severity like every other category. Criteria whose manifest
category is extra_credit carry weight 1 and are included only when their
value is > 0 (fulfilled extra credit joins the weighted mean; unfulfilled
extra credit is excluded rather than penalized). A non-extra-credit
category is extra_credit carry weight 1 scaled by how far they were
fulfilled, and enter the mean at full value: a pass joins at weight 1, a
partial at weight 0.5, a scalar score s at weight s, and unfulfilled extra
credit is left out. Extra credit therefore only ever raises the reward. A
non-extra-credit
criterion with a null/missing severity falls back to
unlikely_dealbreaker (weight 1) with a warning on stderr,
4. rewrites rubric-grade.json in normalized form (generator stamp).
@@ -49,7 +51,7 @@ import os
import sys
from typing import Any, Dict, List
RENDER_RUBRIC_GRADE_VERSION = "render-rubric-grade/2.0.0"
RENDER_RUBRIC_GRADE_VERSION = "render-rubric-grade/2.1.0"
SCHEMA_VERSION = 1
FORMS = ("trinary", "scalar")
@@ -244,30 +246,41 @@ def aggregate(grade: Dict[str, Any], expected: List[Dict[str, Any]]) -> Dict[str
"""Severity-weighted mean over criteria in cents.
reward_cents = round_half_up(sum(weight_i * cents_i) / sum(weight_i))
over included criteria. extra_credit (weight 1) is included only when its
value is > 0; every other criterion is always included at its severity
weight.
over included criteria. Every criterion other than extra_credit is always
included at its severity weight. An extra_credit criterion with value > 0
is included at full value (100 cents) with its weight scaled by its value,
so a partial counts as a pass at half weight and extra credit can only
raise the reward; one with value 0 is left out.
Sums are kept in hundredths of a weight unit so the arithmetic stays exact.
"""
weighted_cents = 0
total_weight = 0
weighted = 0 # sum of weight * cents, in hundredths of a weight unit
total = 0 # sum of weight, in hundredths of a weight unit
n_included = 0
excluded_extra_credit = 0
partial_extra_credit = 0
for criterion in expected:
entry = grade["by_id"][criterion["id"]]
if criterion["category"] == "extra_credit" and entry["_cents"] == 0:
excluded_extra_credit += 1
cents = entry["_cents"]
if criterion["category"] == "extra_credit":
if cents == 0:
excluded_extra_credit += 1
continue
if cents < 100:
partial_extra_credit += 1
n_included += 1
weighted += criterion["weight"] * cents * 100
total += criterion["weight"] * cents
continue
n_included += 1
weighted_cents += criterion["weight"] * entry["_cents"]
total_weight += criterion["weight"]
if total_weight:
reward_cents = _round_half_up(weighted_cents, total_weight)
else:
reward_cents = 0
weighted += criterion["weight"] * cents * 100
total += criterion["weight"] * 100
reward_cents = _round_half_up(weighted, total) if total else 0
return {
"n_included": n_included,
"n_excluded_extra_credit": excluded_extra_credit,
"total_weight": total_weight,
"n_partial_extra_credit": partial_extra_credit,
"total_weight": total / 100.0,
"reward_cents": reward_cents,
}
@@ -292,6 +305,13 @@ def render_markdown(
excluded,
"on" if excluded == 1 else "a",
)
partial = agg["n_partial_extra_credit"]
if partial:
detail += "; %d partly fulfilled extra-credit criteri%s counted at %s" % (
partial,
"on" if partial == 1 else "a",
"half weight" if form == "trinary" else "a weight equal to the score",
)
sections = ["Rubric score (%s): %s (%s)" % (form, _fmt(agg["reward_cents"]), detail)]
for criterion in expected:
@@ -380,8 +400,16 @@ def main() -> int:
f.write(normalized_json(grade, expected, args.form))
print(
"render-rubric-grade: ok reward=%s form=%s criteria=%d excluded_extra_credit=%d total_weight=%d"
% (reward, args.form, agg["n_included"], agg["n_excluded_extra_credit"], agg["total_weight"])
"render-rubric-grade: ok reward=%s form=%s criteria=%d excluded_extra_credit=%d "
"partial_extra_credit=%d total_weight=%g"
% (
reward,
args.form,
agg["n_included"],
agg["n_excluded_extra_credit"],
agg["n_partial_extra_credit"],
agg["total_weight"],
)
)
return 0