Files
OnlineJudge/problem/utils.py
yuetsh 2ec036ac37 feat: 新增 rebuild_sql_display 管理命令,为存量 SQL 题回填展示数据
生成逻辑从 ProblemBase._build_sql_display 提取为 problem.utils.generate_sql_display,
管理端保存与回填命令共用。命令支持 --dry-run / --force。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 09:42:11 -06:00

69 lines
2.5 KiB
Python
Raw 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.
import json
import os
import re
from functools import lru_cache
from django.conf import settings
from judge.sql_runner import SQLCaseError, build_display
from utils.shortcuts import natural_sort_key
TEMPLATE_BASE = """//PREPEND BEGIN
{}
//PREPEND END
//TEMPLATE BEGIN
{}
//TEMPLATE END
//APPEND BEGIN
{}
//APPEND END"""
@lru_cache(maxsize=100)
def parse_problem_template(template_str):
prepend = re.findall(r"//PREPEND BEGIN\n([\s\S]+?)//PREPEND END", template_str)
template = re.findall(r"//TEMPLATE BEGIN\n([\s\S]+?)//TEMPLATE END", template_str)
append = re.findall(r"//APPEND BEGIN\n([\s\S]+?)//APPEND END", template_str)
return {"prepend": prepend[0] if prepend else "", "template": template[0] if template else "", "append": append[0] if append else ""}
@lru_cache(maxsize=100)
def build_problem_template(prepend, template, append):
return TEMPLATE_BASE.format(prepend, template, append)
def generate_sql_display(test_case_id, answers, sql_config):
"""SQL 题用测试点1的初始化脚本 + 标准答案生成题目页展示数据。
返回 (sql_display, error):成功时 error 为 None失败时 sql_display 为 None、error 为中文提示。
"""
test_case_dir = os.path.join(settings.TEST_CASE_DIR, test_case_id)
try:
with open(os.path.join(test_case_dir, "info"), encoding="utf-8") as f:
info = json.load(f)
except (OSError, json.JSONDecodeError):
return None, "测试点信息读取失败,请重新上传测试点"
if not info.get("sql"):
return None, "测试点不是 SQL 类型,请重新上传 SQL 测试点压缩包"
try:
keys = sorted(info["test_cases"].keys(), key=natural_sort_key)
if not keys:
return None, "题目没有任何测试点"
input_name = info["test_cases"][keys[0]]["input_name"]
except (KeyError, AttributeError, TypeError):
return None, "测试点信息损坏,请重新上传测试点"
try:
with open(os.path.join(test_case_dir, input_name), encoding="utf-8") as f:
init_sql = f.read()
except OSError:
return None, f"测试点脚本 {input_name} 读取失败"
ref_sql = next((item["code"] for item in answers or [] if item.get("language") == "SQL" and item.get("code", "").strip()), None)
if ref_sql is None:
return None, "题目缺少 SQL 标准答案"
try:
return build_display(init_sql, ref_sql, sql_config["mode"]), None
except SQLCaseError as e:
return None, f"SQL 展示数据生成失败: {e.message}"