add grade

This commit is contained in:
2026-06-25 23:49:35 -06:00
parent 4f288a1fef
commit c4196e61e9
3 changed files with 33 additions and 3 deletions

View File

@@ -40,6 +40,19 @@ def _grade_for_rank(rank: int, student_count: int) -> str:
return "E" return "E"
def _assessment_grade_for_rank(rank: int, student_count: int) -> str:
# 考核等级A10% B20% C40% D20% E10%,按单题最高分排名
if rank <= ceil(0.10 * student_count):
return "A"
if rank <= ceil(0.30 * student_count):
return "B"
if rank <= ceil(0.70 * student_count):
return "C"
if rank <= ceil(0.90 * student_count):
return "D"
return "E"
def _task_sort_key(task): def _task_sort_key(task):
type_order = 0 if task.task_type == TaskTypeChoices.TUTORIAL else 1 type_order = 0 if task.task_type == TaskTypeChoices.TUTORIAL else 1
return (type_order, task.display, task.id) return (type_order, task.display, task.id)
@@ -152,6 +165,7 @@ def build_gradebook(filters: GradebookFilters):
scores = {} scores = {}
tutorial_total = 0.0 tutorial_total = 0.0
challenge_total = 0.0 challenge_total = 0.0
best_submission_score = 0.0
submitted_task_count = 0 submitted_task_count = 0
missing_task_count = 0 missing_task_count = 0
@@ -176,6 +190,8 @@ def build_gradebook(filters: GradebookFilters):
continue continue
if submission: if submission:
submitted_task_count += 1 submitted_task_count += 1
if cell_score > best_submission_score:
best_submission_score = cell_score
else: else:
missing_task_count += 1 missing_task_count += 1
if task["task_type"] == TaskTypeChoices.TUTORIAL: if task["task_type"] == TaskTypeChoices.TUTORIAL:
@@ -196,6 +212,8 @@ def build_gradebook(filters: GradebookFilters):
"classname": student.classname, "classname": student.classname,
"rank": 0, "rank": 0,
"grade": "E", "grade": "E",
"assessment_grade": "E",
"best_submission_score": _score(best_submission_score),
"scores": scores, "scores": scores,
"tutorial_total": tutorial_total, "tutorial_total": tutorial_total,
"challenge_total": challenge_total, "challenge_total": challenge_total,
@@ -211,6 +229,13 @@ def build_gradebook(filters: GradebookFilters):
row["rank"] = index row["rank"] = index
row["grade"] = _grade_for_rank(index, student_count) row["grade"] = _grade_for_rank(index, student_count)
# 考核等级:按单题最高分单独排名后定级(不改变上面的总分排名)
assessment_order = sorted(
rows, key=lambda row: (-row["best_submission_score"], row["username"])
)
for index, row in enumerate(assessment_order, start=1):
row["assessment_grade"] = _assessment_grade_for_rank(index, student_count)
username = filters.username.strip().lower() if filters.username else "" username = filters.username.strip().lower() if filters.username else ""
if username: if username:
rows = [row for row in rows if username in row["username"].lower()] rows = [row for row in rows if username in row["username"].lower()]
@@ -232,6 +257,7 @@ def gradebook_csv_rows(gradebook):
yield [ yield [
"排名", "排名",
"等级", "等级",
"考核等级",
"用户名", "用户名",
"班级", "班级",
*[_task_csv_header(task) for task in tasks], *[_task_csv_header(task) for task in tasks],
@@ -247,6 +273,7 @@ def gradebook_csv_rows(gradebook):
yield [ yield [
row["rank"], row["rank"],
row["grade"], row["grade"],
row["assessment_grade"],
row["username"], row["username"],
row["classname"], row["classname"],
*[_csv_number(row["scores"][task["id"]]["score"]) for task in tasks], *[_csv_number(row["scores"][task["id"]]["score"]) for task in tasks],

View File

@@ -182,6 +182,8 @@ class GradebookRow(Schema):
classname: str classname: str
rank: int rank: int
grade: Literal["A", "B", "C", "D", "E"] grade: Literal["A", "B", "C", "D", "E"]
assessment_grade: Literal["A", "B", "C", "D", "E"]
best_submission_score: float
scores: dict[int, GradebookCell] scores: dict[int, GradebookCell]
tutorial_total: float tutorial_total: float
challenge_total: float challenge_total: float

View File

@@ -548,6 +548,7 @@ class GradebookApiTest(TestCase):
[ [
"排名", "排名",
"等级", "等级",
"考核等级",
"用户名", "用户名",
"班级", "班级",
"教程1-Intro", "教程1-Intro",
@@ -559,9 +560,9 @@ class GradebookApiTest(TestCase):
"未提交任务数", "未提交任务数",
], ],
) )
self.assertEqual(rows[1][2], "alice") self.assertEqual(rows[1][3], "alice")
self.assertEqual(rows[1][4], "4") self.assertEqual(rows[1][5], "4")
self.assertEqual(rows[1][7], "4") self.assertEqual(rows[1][8], "4")
class RandomForRatingApiTest(TestCase): class RandomForRatingApiTest(TestCase):