2311061111-lyt/autograde/aggregate_final_grade.py
liyitian 83cd133001
All checks were successful
autograde-final-vibevault / check-trigger (push) Successful in 13s
autograde-final-vibevault / grade (push) Has been skipped
add autograde tests
2025-12-14 18:19:41 +08:00

214 lines
7.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
aggregate_final_grade.py - 聚合最终成绩脚本
将编程测试、报告评分等各部分成绩聚合为最终成绩
"""
import json
import argparse
from typing import Dict, Any
def parse_args():
"""解析命令行参数"""
parser = argparse.ArgumentParser(description='Final Grade Aggregation Script')
parser.add_argument('--programming', required=True, help='编程测试评分结果文件')
parser.add_argument('--report', required=True, help='REPORT.md评分结果文件')
parser.add_argument('--frontend', required=True, help='FRONTEND.md评分结果文件')
parser.add_argument('--out', required=True, help='输出最终成绩文件')
parser.add_argument('--summary', required=True, help='输出最终成绩摘要文件')
return parser.parse_args()
def load_grade_file(file_path: str) -> Dict[str, Any]:
"""加载评分结果文件"""
with open(file_path, 'r', encoding='utf-8') as f:
return json.load(f)
def aggregate_grades(
programming_grade: Dict[str, Any],
report_grade: Dict[str, Any],
frontend_grade: Dict[str, Any]
) -> Dict[str, Any]:
"""聚合各部分成绩"""
# 各部分权重配置
weights = {
'programming': 0.6, # 编程测试占60%
'report': 0.25, # 报告占25%
'frontend': 0.15 # 前端报告占15%
}
# 计算各部分成绩
programming_score = programming_grade.get('total', 0.0)
report_score = report_grade.get('total', 0.0)
frontend_score = frontend_grade.get('total', 0.0)
# 计算加权平均分
final_score = (
programming_score * weights['programming'] +
report_score * weights['report'] +
frontend_score * weights['frontend']
)
# 计算各部分的标准化得分(占总分的百分比)
programming_percentage = (programming_score / 100.0) * weights['programming'] * 100.0
report_percentage = (report_score / 100.0) * weights['report'] * 100.0
frontend_percentage = (frontend_score / 100.0) * weights['frontend'] * 100.0
# 生成聚合结果
result = {
'final_score': final_score,
'breakdown': {
'programming': {
'score': programming_score,
'percentage': programming_percentage,
'weight': weights['programming']
},
'report': {
'score': report_score,
'percentage': report_percentage,
'weight': weights['report']
},
'frontend': {
'score': frontend_score,
'percentage': frontend_percentage,
'weight': weights['frontend']
}
},
'weights': weights,
'details': {
'programming': programming_grade,
'report': report_grade,
'frontend': frontend_grade
},
'status': 'completed',
'timestamp': '2025-12-14T18:00:00Z'
}
return result
def generate_summary(aggregate_result: Dict[str, Any]) -> str:
"""生成最终成绩摘要"""
summary = "# 最终成绩报告\n\n"
# 总体成绩
final_score = aggregate_result['final_score']
summary += f"## 总体成绩\n"
summary += f"**最终得分**: {final_score:.2f}/100\n\n"
# 成绩分布
summary += f"## 成绩分布\n"
summary += "| 部分 | 得分 | 权重 | 占总分百分比 |\n"
summary += "|------|------|------|------------|\n"
for part, data in aggregate_result['breakdown'].items():
part_name = {
'programming': '编程测试',
'report': '后端与系统设计报告',
'frontend': '前端界面与交互设计报告'
}.get(part, part)
summary += f"| {part_name} | {data['score']:.2f} | {data['weight']*100:.0f}% | {data['percentage']:.2f} |\n"
summary += "\n"
# 详细说明
summary += f"## 详细说明\n"
# 编程测试
programming = aggregate_result['details']['programming']
programming_total = programming.get('total', 0.0)
summary += f"### 编程测试 ({aggregate_result['weights']['programming']*100:.0f}%)\n"
summary += f"- 原始得分: {programming_total:.2f}/100\n"
summary += f"- 测试通过率: {len([g for g in programming.get('groups', []) if g['passed'] > 0])}/{len(programming.get('groups', []))}\n"
for group in programming.get('groups', []):
summary += f" - {group['group_name']}: {group['passed']}/{group['total']} 测试通过\n"
summary += "\n"
# 报告评分
report = aggregate_result['details']['report']
report_total = report.get('total', 0.0)
summary += f"### 后端与系统设计报告 ({aggregate_result['weights']['report']*100:.0f}%)\n"
summary += f"- 原始得分: {report_total:.2f}/100\n"
if report.get('feedback'):
summary += f"- 反馈摘要: {report['feedback'][:100]}...\n"
summary += "\n"
# 前端报告评分
frontend = aggregate_result['details']['frontend']
frontend_total = frontend.get('total', 0.0)
summary += f"### 前端界面与交互设计报告 ({aggregate_result['weights']['frontend']*100:.0f}%)\n"
summary += f"- 原始得分: {frontend_total:.2f}/100\n"
if frontend.get('feedback'):
summary += f"- 反馈摘要: {frontend['feedback'][:100]}...\n"
summary += "\n"
# 评分等级
if final_score >= 90:
grade_level = "优秀"
elif final_score >= 80:
grade_level = "良好"
elif final_score >= 70:
grade_level = "中等"
elif final_score >= 60:
grade_level = "及格"
else:
grade_level = "不及格"
summary += f"## 评分等级\n"
summary += f"根据最终得分 {final_score:.2f}/100该作业的评分等级为**{grade_level}**\n"
# 建议
summary += f"## 改进建议\n"
summary += "1. 编程测试部分可以进一步提高测试覆盖率\n"
summary += "2. 报告内容可以更加详细和系统化\n"
summary += "3. 前端设计可以考虑更多用户体验细节\n"
return summary
def main():
"""主函数"""
args = parse_args()
# 加载各部分评分结果
print(f"📁 加载编程测试评分: {args.programming}")
programming_grade = load_grade_file(args.programming)
print(f"📁 加载报告评分: {args.report}")
report_grade = load_grade_file(args.report)
print(f"📁 加载前端报告评分: {args.frontend}")
frontend_grade = load_grade_file(args.frontend)
# 聚合成绩
print("📊 聚合最终成绩...")
final_result = aggregate_grades(programming_grade, report_grade, frontend_grade)
# 保存最终成绩
print(f"💾 保存最终成绩: {args.out}")
with open(args.out, 'w', encoding='utf-8') as f:
json.dump(final_result, f, ensure_ascii=False, indent=2)
# 生成摘要
print(f"📝 生成最终成绩摘要: {args.summary}")
summary = generate_summary(final_result)
with open(args.summary, 'w', encoding='utf-8') as f:
f.write(summary)
print(f"✅ 成绩聚合完成! 最终得分: {final_result['final_score']:.2f}/100")
if __name__ == '__main__':
main()