fix: support final grade type and flexible repo name parsing
- Add GRADE_TYPE=final support for final_grade.json - Fix assignment_id extraction for non-hw format (e.g. final-vibevault) - Fix student_id extraction for xxx-stu_yyy format - Change default language from python to java
This commit is contained in:
parent
183959f4a0
commit
fa984b79f2
@ -2,7 +2,7 @@
|
||||
"""
|
||||
创建完整的成绩元数据文件
|
||||
|
||||
从 grade.json 或 llm_grade.json 生成 metadata.json
|
||||
从 grade.json / final_grade.json / llm_grade.json 生成 metadata.json
|
||||
包含所有详细信息:未通过的测试、各题详情等
|
||||
"""
|
||||
|
||||
@ -20,20 +20,22 @@ def extract_student_id():
|
||||
if student_id:
|
||||
return student_id
|
||||
|
||||
# 从仓库名提取(格式:hw1-stu_sit001)
|
||||
# 从仓库名提取
|
||||
# 支持格式:org/assignment-stu_xxx 或 org/assignment-stu-xxx
|
||||
repo = os.getenv("REPO", "")
|
||||
if repo:
|
||||
# 匹配 hw1-stu_xxxxx 格式
|
||||
match = re.search(r'hw\d+-stu[_-]?([^/]+)', repo)
|
||||
# 匹配 xxx-stu_yyy 或 xxx-stu-yyy 格式
|
||||
match = re.search(r'-stu[_-]([a-zA-Z0-9_]+)$', repo)
|
||||
if match:
|
||||
return match.group(1)
|
||||
# 也尝试匹配 stu_xxx 在路径中的情况
|
||||
match = re.search(r'stu[_-]([a-zA-Z0-9_]+)', repo)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def extract_assignment_id():
|
||||
"""从环境变量或仓库名中提取作业 ID"""
|
||||
# 优先从环境变量获取
|
||||
@ -41,20 +43,94 @@ def extract_assignment_id():
|
||||
if assignment_id:
|
||||
return assignment_id
|
||||
|
||||
# 从仓库名提取(格式:hw1-stu_sit001 或 hw1-template)
|
||||
# 从仓库名提取
|
||||
# 支持格式:org/assignment-stu_xxx 或 org/assignment-template
|
||||
repo = os.getenv("REPO", "")
|
||||
if repo:
|
||||
# 尝试匹配 hwX-stu_ 或 hwX-template
|
||||
match = re.search(r'(hw\d+)-(?:stu|template)', repo)
|
||||
if match:
|
||||
return match.group(1)
|
||||
# 取仓库名部分(去掉组织)
|
||||
repo_name = repo.split("/")[-1] if "/" in repo else repo
|
||||
|
||||
# 移除 -stu_xxx 或 -template 后缀
|
||||
assignment = re.sub(r'-stu[_-][a-zA-Z0-9_]+$', '', repo_name)
|
||||
assignment = re.sub(r'-template$', '', assignment)
|
||||
|
||||
if assignment:
|
||||
return assignment
|
||||
|
||||
# 如果只是 hwX 格式
|
||||
match = re.search(r'(hw\d+)$', repo)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
return "hw1" # 默认回退
|
||||
return "unknown"
|
||||
|
||||
|
||||
def create_final_metadata(final_grade_file='final_grade.json'):
|
||||
"""从 final_grade.json 创建元数据(期末大作业专用)"""
|
||||
try:
|
||||
with open(final_grade_file, 'r', encoding='utf-8') as f:
|
||||
final_data = json.load(f)
|
||||
|
||||
assignment_id = extract_assignment_id()
|
||||
student_id = extract_student_id()
|
||||
|
||||
total_score = final_data.get("total_score", 0)
|
||||
max_score = final_data.get("max_score", 100)
|
||||
breakdown = final_data.get("breakdown", {})
|
||||
|
||||
# 构建各组成部分
|
||||
components = []
|
||||
|
||||
# 编程测试部分
|
||||
prog = breakdown.get("programming", {})
|
||||
if prog:
|
||||
prog_component = {
|
||||
"type": "programming_java",
|
||||
"score": prog.get("score", 0),
|
||||
"max_score": prog.get("max_score", 80),
|
||||
"details": {
|
||||
"groups": prog.get("groups", {})
|
||||
}
|
||||
}
|
||||
components.append(prog_component)
|
||||
|
||||
# REPORT.md 部分
|
||||
report = breakdown.get("report", {})
|
||||
if report:
|
||||
report_component = {
|
||||
"type": "llm_report",
|
||||
"score": report.get("score", 0),
|
||||
"max_score": report.get("max_score", 10),
|
||||
"details": {
|
||||
"flags": report.get("flags", [])
|
||||
}
|
||||
}
|
||||
components.append(report_component)
|
||||
|
||||
# FRONTEND.md 部分
|
||||
frontend = breakdown.get("frontend", {})
|
||||
if frontend:
|
||||
frontend_component = {
|
||||
"type": "llm_frontend",
|
||||
"score": frontend.get("score", 0),
|
||||
"max_score": frontend.get("max_score", 10),
|
||||
"details": {
|
||||
"flags": frontend.get("flags", [])
|
||||
}
|
||||
}
|
||||
components.append(frontend_component)
|
||||
|
||||
metadata = {
|
||||
"version": "1.0",
|
||||
"assignment": assignment_id,
|
||||
"student_id": student_id,
|
||||
"components": components,
|
||||
"total_score": round(total_score, 2),
|
||||
"total_max_score": max_score,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"generator": "gitea-autograde"
|
||||
}
|
||||
|
||||
return metadata
|
||||
except Exception as e:
|
||||
print(f"Error creating final metadata: {e}", file=sys.stderr)
|
||||
return {}
|
||||
|
||||
|
||||
def create_grade_metadata(grade_file='grade.json'):
|
||||
"""从 grade.json 创建元数据,包含所有详细信息"""
|
||||
@ -64,19 +140,20 @@ def create_grade_metadata(grade_file='grade.json'):
|
||||
|
||||
assignment_id = extract_assignment_id()
|
||||
student_id = extract_student_id()
|
||||
language = os.getenv("LANGUAGE", "python")
|
||||
language = os.getenv("LANGUAGE", "java")
|
||||
|
||||
# 提取所有相关信息
|
||||
final_score = grade_data.get("final_score", grade_data.get("score", 0))
|
||||
final_score = grade_data.get("final_score", grade_data.get("total_score", grade_data.get("score", 0)))
|
||||
base_score = grade_data.get("base_score", final_score)
|
||||
penalty = grade_data.get("penalty", 0)
|
||||
passed = grade_data.get("passed", 0)
|
||||
total = grade_data.get("total", 0)
|
||||
fails = grade_data.get("fails", [])
|
||||
max_score = grade_data.get("max_score", 100)
|
||||
test_framework = grade_data.get("test_framework", "pytest")
|
||||
test_framework = grade_data.get("test_framework", "junit")
|
||||
coverage = grade_data.get("coverage")
|
||||
raw_score = grade_data.get("raw_score")
|
||||
groups = grade_data.get("groups", {})
|
||||
|
||||
# 动态生成 type 字段
|
||||
type_map = {
|
||||
@ -99,7 +176,8 @@ def create_grade_metadata(grade_file='grade.json'):
|
||||
"coverage": round(coverage, 2) if coverage else None,
|
||||
"raw_score": round(raw_score, 2) if raw_score else None,
|
||||
"failed_tests": fails,
|
||||
"test_framework": test_framework
|
||||
"test_framework": test_framework,
|
||||
"groups": groups
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,7 +326,15 @@ def main():
|
||||
grade_type = os.getenv("GRADE_TYPE", "programming").lower()
|
||||
grade_file_override = os.getenv("GRADE_FILE")
|
||||
|
||||
if grade_type == "llm":
|
||||
if grade_type == "final":
|
||||
# 期末大作业成绩(包含编程+报告)
|
||||
final_file = grade_file_override or "final_grade.json"
|
||||
if os.path.exists(final_file):
|
||||
metadata = create_final_metadata(final_file)
|
||||
else:
|
||||
print(f"Error: {final_file} not found", file=sys.stderr)
|
||||
metadata = {}
|
||||
elif grade_type == "llm":
|
||||
# LLM 成绩
|
||||
llm_file = grade_file_override or "artifacts/llm_grade.json"
|
||||
if os.path.exists(llm_file):
|
||||
@ -279,4 +365,4 @@ def main():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user