refactor(exam): SKILL 中文化,增加用户确认阶段,默认子代理分批处理
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Update meta.json and topics/index.json after adding questions.
|
||||
|
||||
Usage:
|
||||
python3 update_meta.py <topics_dir> <group> <subtopic> <question_type>
|
||||
|
||||
- Reads the question file at topics/{group}/{subtopic}/{type}.json
|
||||
- Updates/creates topics/{group}/{subtopic}/meta.json
|
||||
- Updates/creates topics/index.json with subtopic stats
|
||||
|
||||
meta.json format:
|
||||
{
|
||||
"slug": "gc-jvm",
|
||||
"name": "...",
|
||||
"description": "...",
|
||||
"tags": [...],
|
||||
"difficulty_range": [1, 5],
|
||||
"schema_version": "1.0.0",
|
||||
"question_files": ["fill_blank", "single_choice"],
|
||||
"stats": { "total": 20, "by_type": { "fill_blank": 10, "single_choice": 10 } }
|
||||
}
|
||||
|
||||
index.json format:
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"updated": "...",
|
||||
"topics": [
|
||||
{
|
||||
"slug": "qunar-ai-fullstack",
|
||||
"name": "...",
|
||||
"subtopics": [
|
||||
{ "slug": "gc-jvm", "path": "topics/qunar-ai-fullstack/gc-jvm", "stats": {...} }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Exit codes: 0 = success, 1 = error, 2 = usage error.
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from datetime import date
|
||||
|
||||
|
||||
def load_json(path: Path) -> dict:
|
||||
if path.exists() and path.stat().st_size > 0:
|
||||
with open(path, encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
return {}
|
||||
|
||||
|
||||
def save_json(path: Path, data: dict):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
f.write("\n")
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 5:
|
||||
print(f"Usage: {sys.argv[0]} <topics_dir> <group> <subtopic> <question_type>",
|
||||
file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
topics_dir = Path(sys.argv[1])
|
||||
group = sys.argv[2]
|
||||
subtopic = sys.argv[3]
|
||||
q_type = sys.argv[4]
|
||||
|
||||
subtopic_dir = topics_dir / group / subtopic
|
||||
question_file = subtopic_dir / f"{q_type}.json"
|
||||
meta_file = subtopic_dir / "meta.json"
|
||||
index_file = topics_dir / "index.json"
|
||||
|
||||
if not question_file.exists():
|
||||
print(f"❌ Question file not found: {question_file}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Load question file
|
||||
q_data = load_json(question_file)
|
||||
questions = q_data.get("questions", [])
|
||||
count = len(questions)
|
||||
|
||||
# Compute difficulty stats
|
||||
difficulties = [q.get("difficulty", 3) for q in questions]
|
||||
diff_range = [min(difficulties), max(difficulties)] if difficulties else [1, 5]
|
||||
|
||||
# Compute tag union
|
||||
all_tags = sorted(set(
|
||||
tag for q in questions for tag in q.get("tags", [])
|
||||
))
|
||||
|
||||
# --- Update meta.json ---
|
||||
meta = load_json(meta_file)
|
||||
meta["slug"] = meta.get("slug", subtopic)
|
||||
meta["name"] = meta.get("name", subtopic.replace("-", " ").title())
|
||||
meta.setdefault("description", "")
|
||||
meta["tags"] = all_tags
|
||||
meta["difficulty_range"] = diff_range
|
||||
meta["schema_version"] = "1.0.0"
|
||||
meta["updated"] = date.today().isoformat()
|
||||
|
||||
# question_files is an array of type names
|
||||
if "question_files" not in meta:
|
||||
meta["question_files"] = []
|
||||
if q_type not in meta["question_files"]:
|
||||
meta["question_files"].append(q_type)
|
||||
|
||||
# stats has total and by_type
|
||||
if "stats" not in meta:
|
||||
meta["stats"] = {"total": 0, "by_type": {}}
|
||||
meta["stats"]["by_type"][q_type] = count
|
||||
meta["stats"]["total"] = sum(meta["stats"]["by_type"].values())
|
||||
|
||||
save_json(meta_file, meta)
|
||||
|
||||
# --- Update index.json ---
|
||||
index = load_json(index_file)
|
||||
index.setdefault("version", "1.0.0")
|
||||
index["updated"] = date.today().isoformat()
|
||||
index.setdefault("topics", [])
|
||||
|
||||
# Find or create the group topic entry
|
||||
group_entry = None
|
||||
for t in index["topics"]:
|
||||
if t.get("slug") == group:
|
||||
group_entry = t
|
||||
break
|
||||
|
||||
if group_entry is None:
|
||||
group_entry = {
|
||||
"slug": group,
|
||||
"name": meta.get("name", group.replace("-", " ").title()),
|
||||
"description": meta.get("description", ""),
|
||||
"subtopics": [],
|
||||
}
|
||||
index["topics"].append(group_entry)
|
||||
|
||||
group_entry.setdefault("subtopics", [])
|
||||
|
||||
# Find or create the subtopic entry
|
||||
sub_entry = None
|
||||
for s in group_entry["subtopics"]:
|
||||
if s.get("slug") == subtopic:
|
||||
sub_entry = s
|
||||
break
|
||||
|
||||
if sub_entry is None:
|
||||
sub_entry = {
|
||||
"slug": subtopic,
|
||||
"name": meta.get("name", subtopic.replace("-", " ").title()),
|
||||
"description": meta.get("description", ""),
|
||||
"path": f"topics/{group}/{subtopic}",
|
||||
"stats": {"total": 0, "by_type": {}},
|
||||
}
|
||||
group_entry["subtopics"].append(sub_entry)
|
||||
|
||||
sub_entry["stats"]["by_type"][q_type] = count
|
||||
sub_entry["stats"]["total"] = sum(sub_entry["stats"]["by_type"].values())
|
||||
|
||||
save_json(index_file, index)
|
||||
|
||||
# Output summary
|
||||
result = {
|
||||
"subtopic": subtopic,
|
||||
"question_type": q_type,
|
||||
"count": count,
|
||||
"total": meta["stats"]["total"],
|
||||
"meta_file": str(meta_file),
|
||||
"index_file": str(index_file),
|
||||
}
|
||||
print(json.dumps(result, ensure_ascii=False))
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user