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:
|
if student_id:
|
||||||
return student_id
|
return student_id
|
||||||
|
|
||||||
# 从仓库名提取(格式:hw1-stu_sit001)
|
# 从仓库名提取
|
||||||
|
# 支持格式:org/assignment-stu_xxx 或 org/assignment-stu-xxx
|
||||||
repo = os.getenv("REPO", "")
|
repo = os.getenv("REPO", "")
|
||||||
if repo:
|
if repo:
|
||||||
# 匹配 hw1-stu_xxxxx 格式
|
# 匹配 xxx-stu_yyy 或 xxx-stu-yyy 格式
|
||||||
match = re.search(r'hw\d+-stu[_-]?([^/]+)', repo)
|
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:
|
if match:
|
||||||
return match.group(1)
|
return match.group(1)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def extract_assignment_id():
|
def extract_assignment_id():
|
||||||
"""从环境变量或仓库名中提取作业 ID"""
|
"""从环境变量或仓库名中提取作业 ID"""
|
||||||
# 优先从环境变量获取
|
# 优先从环境变量获取
|
||||||
@ -41,20 +43,94 @@ def extract_assignment_id():
|
|||||||
if assignment_id:
|
if assignment_id:
|
||||||
return assignment_id
|
return assignment_id
|
||||||
|
|
||||||
# 从仓库名提取(格式:hw1-stu_sit001 或 hw1-template)
|
# 从仓库名提取
|
||||||
|
# 支持格式:org/assignment-stu_xxx 或 org/assignment-template
|
||||||
repo = os.getenv("REPO", "")
|
repo = os.getenv("REPO", "")
|
||||||
if repo:
|
if repo:
|
||||||
# 尝试匹配 hwX-stu_ 或 hwX-template
|
# 取仓库名部分(去掉组织)
|
||||||
match = re.search(r'(hw\d+)-(?:stu|template)', repo)
|
repo_name = repo.split("/")[-1] if "/" in repo else repo
|
||||||
if match:
|
|
||||||
return match.group(1)
|
|
||||||
|
|
||||||
# 如果只是 hwX 格式
|
# 移除 -stu_xxx 或 -template 后缀
|
||||||
match = re.search(r'(hw\d+)$', repo)
|
assignment = re.sub(r'-stu[_-][a-zA-Z0-9_]+$', '', repo_name)
|
||||||
if match:
|
assignment = re.sub(r'-template$', '', assignment)
|
||||||
return match.group(1)
|
|
||||||
|
if assignment:
|
||||||
|
return assignment
|
||||||
|
|
||||||
|
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 {}
|
||||||
|
|
||||||
return "hw1" # 默认回退
|
|
||||||
|
|
||||||
def create_grade_metadata(grade_file='grade.json'):
|
def create_grade_metadata(grade_file='grade.json'):
|
||||||
"""从 grade.json 创建元数据,包含所有详细信息"""
|
"""从 grade.json 创建元数据,包含所有详细信息"""
|
||||||
@ -64,19 +140,20 @@ def create_grade_metadata(grade_file='grade.json'):
|
|||||||
|
|
||||||
assignment_id = extract_assignment_id()
|
assignment_id = extract_assignment_id()
|
||||||
student_id = extract_student_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)
|
base_score = grade_data.get("base_score", final_score)
|
||||||
penalty = grade_data.get("penalty", 0)
|
penalty = grade_data.get("penalty", 0)
|
||||||
passed = grade_data.get("passed", 0)
|
passed = grade_data.get("passed", 0)
|
||||||
total = grade_data.get("total", 0)
|
total = grade_data.get("total", 0)
|
||||||
fails = grade_data.get("fails", [])
|
fails = grade_data.get("fails", [])
|
||||||
max_score = grade_data.get("max_score", 100)
|
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")
|
coverage = grade_data.get("coverage")
|
||||||
raw_score = grade_data.get("raw_score")
|
raw_score = grade_data.get("raw_score")
|
||||||
|
groups = grade_data.get("groups", {})
|
||||||
|
|
||||||
# 动态生成 type 字段
|
# 动态生成 type 字段
|
||||||
type_map = {
|
type_map = {
|
||||||
@ -99,7 +176,8 @@ def create_grade_metadata(grade_file='grade.json'):
|
|||||||
"coverage": round(coverage, 2) if coverage else None,
|
"coverage": round(coverage, 2) if coverage else None,
|
||||||
"raw_score": round(raw_score, 2) if raw_score else None,
|
"raw_score": round(raw_score, 2) if raw_score else None,
|
||||||
"failed_tests": fails,
|
"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_type = os.getenv("GRADE_TYPE", "programming").lower()
|
||||||
grade_file_override = os.getenv("GRADE_FILE")
|
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 成绩
|
||||||
llm_file = grade_file_override or "artifacts/llm_grade.json"
|
llm_file = grade_file_override or "artifacts/llm_grade.json"
|
||||||
if os.path.exists(llm_file):
|
if os.path.exists(llm_file):
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user