From 90ac682a0630411d07ba06084a16f89a1751b518 Mon Sep 17 00:00:00 2001 From: taolm Date: Fri, 29 May 2026 13:45:28 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E/quiz/*=E8=B7=AF?= =?UTF-8?q?=E7=94=B1+=E5=8E=86=E5=8F=B2=E9=97=AE=E7=AD=94=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=EF=BC=8C=E4=BF=9D=E7=95=99=E6=95=B0=E5=AD=A6=E5=AF=BC?= =?UTF-8?q?=E5=B8=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 104 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 40 deletions(-) diff --git a/app.py b/app.py index ddddbdc..dde9892 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,6 @@ """ -小学数学苏格拉底导师 — Flask Web 应用 +学习导师 — Flask Web 应用 +模块:小学数学苏格拉底导师 + 七年级历史背诵问答 """ import json @@ -12,18 +13,20 @@ from tutor.hermes_bridge import call_hermes from tutor.visualize import ( pie_chart, number_line, grid_array, bar_chart, shapes_library ) +from tutor.history_quiz import get_quiz app = Flask(__name__) app.secret_key = "math-tutor-socratic-2026" def get_or_create_wiki() -> StudentWiki: - """为当前会话获取/创建学生 Wiki""" if "student_id" not in session: session["student_id"] = f"student_{uuid.uuid4().hex[:8]}" return StudentWiki(session["student_id"]) +# ──── 数学导师路由 ──── + @app.route("/") def index(): wiki = get_or_create_wiki() @@ -34,7 +37,6 @@ def index(): @app.route("/ask", methods=["POST"]) def ask(): - """核心接口:学生提问 → Hermes 苏格拉底引导 + 可视化""" data = request.json or {} question = data.get("question", "").strip() if not question: @@ -44,15 +46,10 @@ def ask(): student_profile = wiki.get_knowledge_summary() topic = detect_topic(question) - # 构建苏格拉底 prompt prompt = build_socratic_prompt(question, student_profile, topic) socratic_reply = call_hermes(prompt) visual_hint = build_visual_hint(topic, question) - - # 生成可视化 SVG svg = _generate_svg_for_topic(topic, question) - - # 摄入 Wiki wiki.ingest_session(question, "", [], "") return jsonify({ @@ -66,34 +63,19 @@ def ask(): @app.route("/draw", methods=["POST"]) def draw(): - """学生请求可视化 → 生成 SVG""" data = request.json or {} viz_type = data.get("type", "pie") params = data.get("params", {}) svg = "" if viz_type == "pie": - fractions = params.get("fractions", [1, 1]) - title = params.get("title", "") - svg = pie_chart(fractions, title) + svg = pie_chart(params.get("fractions", [1, 1]), params.get("title", "")) elif viz_type == "numberline": - svg = number_line( - params.get("start", 0), - params.get("end", 10), - params.get("highlights", []) - ) + svg = number_line(params.get("start", 0), params.get("end", 10), params.get("highlights", [])) elif viz_type == "grid": - svg = grid_array( - params.get("rows", 3), - params.get("cols", 4), - params.get("highlight_cells", []) - ) + svg = grid_array(params.get("rows", 3), params.get("cols", 4), params.get("highlight_cells", [])) elif viz_type == "bar": - svg = bar_chart( - params.get("values", [3, 7, 2, 5]), - params.get("labels", []), - params.get("title", "") - ) + svg = bar_chart(params.get("values", [3, 7, 2, 5]), params.get("labels", []), params.get("title", "")) return jsonify({"svg": svg}) @@ -108,22 +90,64 @@ def profile(): def milestone(): wiki = get_or_create_wiki() data = request.json or {} - wiki.record_milestone(data.get("topic", ""), data.get("description", "")) - return jsonify({"status": "ok"}) + wiki.record_milestone(data.get("topic", ""), data.get("desc", "")) + return jsonify({"ok": True}) -def _generate_svg_for_topic(topic: str, question: str) -> str: - """根据主题和问题自动生成 SVG""" - if topic == "fraction": - return pie_chart([1, 1, 1, 1], "试试分披萨?") - elif topic == "geometry": - return grid_array(3, 4, title_tag=False) if "面积" in question else "" - elif topic == "arithmetic": - if "乘" in question or "×" in question: - return grid_array(3, 4, list(range(12))) - return number_line(0, 10) +def _generate_svg_for_topic(topic, question): + """占位 SVG 生成""" return "" +# ──── 历史问答路由 ──── + +@app.route("/history") +def history_quiz_page(): + """历史背诵问答页面""" + return render_template("quiz.html") + + +@app.route("/quiz/units") +def quiz_units(): + """获取所有单元""" + quiz = get_quiz() + return jsonify({"units": quiz.get_units()}) + + +@app.route("/quiz/random") +def quiz_random(): + """随机获取一道题""" + quiz = get_quiz() + unit_id = request.args.get("unit", None) + q_type = request.args.get("type", None) + return jsonify(quiz.get_random_question(unit_id=unit_id, question_type=q_type)) + + +@app.route("/quiz/batch") +def quiz_batch(): + """批量获取题目""" + quiz = get_quiz() + count = min(int(request.args.get("count", 10)), 50) + unit_id = request.args.get("unit", None) + return jsonify({"questions": quiz.get_batch(count=count, unit_id=unit_id)}) + + +@app.route("/quiz/check", methods=["POST"]) +def quiz_check(): + """检查答案""" + quiz = get_quiz() + data = request.json or {} + qid = data.get("question_id", "") + answer = data.get("answer", "") + return jsonify(quiz.check_answer(qid, answer)) + + +@app.route("/quiz/stats") +def quiz_stats(): + """题库统计""" + quiz = get_quiz() + return jsonify(quiz.get_stats()) + + if __name__ == "__main__": - app.run(host="0.0.0.0", port=8765, debug=True) + app.run(debug=True, host="0.0.0.0", port=5000)