From ae32732cf6290973366b23c6625e17200b4c0c69 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Thu, 25 Jun 2026 23:55:48 -0600 Subject: [PATCH] add grade --- submission/gradebook.py | 33 +++++++++++++++++++++++++++++++++ submission/schemas.py | 1 + submission/tests.py | 7 ++++--- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/submission/gradebook.py b/submission/gradebook.py index 4f92002..7fb4612 100644 --- a/submission/gradebook.py +++ b/submission/gradebook.py @@ -1,3 +1,4 @@ +from collections import defaultdict from dataclasses import dataclass from math import ceil from typing import Literal @@ -53,6 +54,24 @@ def _assessment_grade_for_rank(rank: int, student_count: int) -> str: return "E" +# 考核分数:各等级对应的分数段(高分→低分),段内按名次线性铺开 +ASSESSMENT_SCORE_BANDS = { + "A": (92, 100), + "B": (84, 91), + "C": (76, 83), + "D": (68, 75), + "E": (60, 67), +} + + +def _assessment_score(index_in_grade: int, grade_size: int, grade: str) -> int: + low, high = ASSESSMENT_SCORE_BANDS[grade] + if grade_size <= 1: + return high + # index_in_grade 从 0 开始:段内第 1 名拿段顶,最后 1 名拿段底 + return round(high - (index_in_grade / (grade_size - 1)) * (high - low)) + + def _task_sort_key(task): type_order = 0 if task.task_type == TaskTypeChoices.TUTORIAL else 1 return (type_order, task.display, task.id) @@ -213,6 +232,7 @@ def build_gradebook(filters: GradebookFilters): "rank": 0, "grade": "E", "assessment_grade": "E", + "assessment_score": 60, "best_submission_score": _score(best_submission_score), "scores": scores, "tutorial_total": tutorial_total, @@ -236,6 +256,17 @@ def build_gradebook(filters: GradebookFilters): for index, row in enumerate(assessment_order, start=1): row["assessment_grade"] = _assessment_grade_for_rank(index, student_count) + # 考核分数:在各等级段内按名次(沿用单题最高分排序)线性铺开到对应分数段 + grade_groups = defaultdict(list) + for row in assessment_order: + grade_groups[row["assessment_grade"]].append(row) + for grade, group in grade_groups.items(): + grade_size = len(group) + for index_in_grade, row in enumerate(group): + row["assessment_score"] = _assessment_score( + index_in_grade, grade_size, grade + ) + username = filters.username.strip().lower() if filters.username else "" if username: rows = [row for row in rows if username in row["username"].lower()] @@ -258,6 +289,7 @@ def gradebook_csv_rows(gradebook): "排名", "等级", "考核等级", + "考核分数", "用户名", "班级", *[_task_csv_header(task) for task in tasks], @@ -274,6 +306,7 @@ def gradebook_csv_rows(gradebook): row["rank"], row["grade"], row["assessment_grade"], + row["assessment_score"], row["username"], row["classname"], *[_csv_number(row["scores"][task["id"]]["score"]) for task in tasks], diff --git a/submission/schemas.py b/submission/schemas.py index 03cf2c4..cb34917 100644 --- a/submission/schemas.py +++ b/submission/schemas.py @@ -183,6 +183,7 @@ class GradebookRow(Schema): rank: int grade: Literal["A", "B", "C", "D", "E"] assessment_grade: Literal["A", "B", "C", "D", "E"] + assessment_score: int best_submission_score: float scores: dict[int, GradebookCell] tutorial_total: float diff --git a/submission/tests.py b/submission/tests.py index 7c992c1..0a6e55e 100644 --- a/submission/tests.py +++ b/submission/tests.py @@ -549,6 +549,7 @@ class GradebookApiTest(TestCase): "排名", "等级", "考核等级", + "考核分数", "用户名", "班级", "教程1-Intro", @@ -560,9 +561,9 @@ class GradebookApiTest(TestCase): "未提交任务数", ], ) - self.assertEqual(rows[1][3], "alice") - self.assertEqual(rows[1][5], "4") - self.assertEqual(rows[1][8], "4") + self.assertEqual(rows[1][4], "alice") + self.assertEqual(rows[1][6], "4") + self.assertEqual(rows[1][9], "4") class RandomForRatingApiTest(TestCase):