final-vibevault-template/.autograde/aggregate_final_grade.py
2025-12-01 22:12:02 +08:00

116 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""
期末大作业成绩汇总脚本
汇总编程测试分数 + REPORT.md 分数 + FRONTEND.md 分数
"""
import argparse
import json
import os
import sys
def load_json(filepath, default=None):
"""安全加载 JSON 文件"""
if not os.path.exists(filepath):
return default or {}
try:
with open(filepath, "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
print(f"Error loading {filepath}: {e}", file=sys.stderr)
return default or {}
def main():
parser = argparse.ArgumentParser(description="Aggregate final project grades")
parser.add_argument("--programming", required=True, help="Programming test grade JSON")
parser.add_argument("--report", required=True, help="REPORT.md LLM grade JSON")
parser.add_argument("--frontend", required=True, help="FRONTEND.md LLM grade JSON")
parser.add_argument("--out", default="final_grade.json", help="Output JSON file")
parser.add_argument("--summary", default="final_summary.md", help="Output summary markdown")
args = parser.parse_args()
# 加载各部分成绩
prog_grade = load_json(args.programming, {"total_score": 0, "max_score": 80})
report_grade = load_json(args.report, {"total": 0})
frontend_grade = load_json(args.frontend, {"total": 0})
# 提取分数
prog_score = prog_grade.get("total_score", 0)
prog_max = prog_grade.get("max_score", 80)
report_score = report_grade.get("total", 0)
report_max = 10 # REPORT.md 满分 10 分
frontend_score = frontend_grade.get("total", 0)
frontend_max = 10 # FRONTEND.md 满分 10 分
# 计算总分
total_score = prog_score + report_score + frontend_score
total_max = prog_max + report_max + frontend_max
# 构建最终成绩数据
final_grade = {
"total_score": round(total_score, 2),
"max_score": total_max,
"breakdown": {
"programming": {
"score": round(prog_score, 2),
"max_score": prog_max,
"groups": prog_grade.get("groups", {})
},
"report": {
"score": round(report_score, 2),
"max_score": report_max,
"flags": report_grade.get("flags", [])
},
"frontend": {
"score": round(frontend_score, 2),
"max_score": frontend_max,
"flags": frontend_grade.get("flags", [])
}
}
}
# 保存 final_grade.json
with open(args.out, "w", encoding="utf-8") as f:
json.dump(final_grade, f, ensure_ascii=False, indent=2)
# 生成 summary.md
with open(args.summary, "w", encoding="utf-8") as f:
f.write("# 期末大作业成绩报告\n\n")
f.write(f"## 总分:{total_score:.2f} / {total_max}\n\n")
f.write("## 分项成绩\n\n")
f.write("| 项目 | 得分 | 满分 | 备注 |\n")
f.write("|------|------|------|------|\n")
f.write(f"| 编程测试 | {prog_score:.2f} | {prog_max} | Core + Advanced + Challenge |\n")
f.write(f"| REPORT.md | {report_score:.2f} | {report_max} | 后端与系统设计报告 |\n")
f.write(f"| FRONTEND.md | {frontend_score:.2f} | {frontend_max} | 前端界面与交互设计报告 |\n")
# 编程测试详情
if prog_grade.get("groups"):
f.write("\n### 编程测试详情\n\n")
f.write("| 分组 | 通过 | 总数 | 得分 | 满分 |\n")
f.write("|------|------|------|------|------|\n")
for group_name, group_info in prog_grade["groups"].items():
f.write(f"| {group_name} | {group_info.get('passed', 0)} | "
f"{group_info.get('total', 0)} | {group_info.get('score', 0):.2f} | "
f"{group_info.get('max_score', 0)} |\n")
# 标记
all_flags = report_grade.get("flags", []) + frontend_grade.get("flags", [])
if all_flags:
f.write("\n### 标记\n\n")
for flag in set(all_flags):
f.write(f"- {flag}\n")
print(f"Final grade: {total_score:.2f}/{total_max}")
if __name__ == "__main__":
main()