|
|
|
|
@ -7,7 +7,7 @@
|
|
|
|
|
3. **接口实现:** 提供获取下一题和提交答案的逻辑。
|
|
|
|
|
"""
|
|
|
|
|
import uuid
|
|
|
|
|
from typing import List, Dict, Any, Optional
|
|
|
|
|
from typing import List, Dict, Any, Optional, Tuple
|
|
|
|
|
|
|
|
|
|
# 引入新的试卷生成模块
|
|
|
|
|
from . import paper_gen
|
|
|
|
|
@ -15,6 +15,10 @@ from . import paper_gen
|
|
|
|
|
# --- 内存会话存储 ---
|
|
|
|
|
_sessions: Dict[str, Dict[str, Any]] = {}
|
|
|
|
|
|
|
|
|
|
# 【新增】缓存上一次成功生成的试卷题目
|
|
|
|
|
# 键结构: (grade, count)
|
|
|
|
|
_last_generated_papers: Dict[Tuple[str, int], List[Dict]] = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ------------------------------
|
|
|
|
|
|
|
|
|
|
@ -22,7 +26,7 @@ _sessions: Dict[str, Dict[str, Any]] = {}
|
|
|
|
|
def create_session(grade: str, count: int) -> dict:
|
|
|
|
|
"""
|
|
|
|
|
创建测验会话。
|
|
|
|
|
首先调用 paper_gen.py 生成题目,然后初始化会话数据到内存。
|
|
|
|
|
【核心修改】:实现“再答一次”功能,优先从缓存中获取题目。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
grade (str): 年级。
|
|
|
|
|
@ -31,22 +35,35 @@ def create_session(grade: str, count: int) -> dict:
|
|
|
|
|
dict: { success, session_id, total_questions, source } 或错误信息。
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# 核心:调用 paper_gen 模块生成题目 (已将逻辑从本文件移除)
|
|
|
|
|
gen_result = paper_gen.generate_test(grade, count)
|
|
|
|
|
questions_key = (grade, count)
|
|
|
|
|
generated_questions = _last_generated_papers.get(questions_key)
|
|
|
|
|
source = "generator" # 默认来源
|
|
|
|
|
|
|
|
|
|
# --- 1. 检查缓存,尝试重用题目 ---
|
|
|
|
|
if generated_questions:
|
|
|
|
|
print(f"INFO: Reusing questions from last paper cache for grade={grade}, count={count}")
|
|
|
|
|
source = "reused" # 标记来源为重用
|
|
|
|
|
else:
|
|
|
|
|
# --- 2. 缓存未命中,调用 paper_gen 模块生成新题目 ---
|
|
|
|
|
gen_result = paper_gen.generate_test(grade, count)
|
|
|
|
|
|
|
|
|
|
if not gen_result["success"]:
|
|
|
|
|
return gen_result # 返回生成失败的消息
|
|
|
|
|
if not gen_result["success"]:
|
|
|
|
|
return gen_result # 返回生成失败的消息
|
|
|
|
|
|
|
|
|
|
generated_questions = gen_result["questions"]
|
|
|
|
|
source = gen_result["source"]
|
|
|
|
|
generated_questions = gen_result["questions"]
|
|
|
|
|
source = gen_result["source"]
|
|
|
|
|
|
|
|
|
|
# 【更新缓存】生成成功后,将新的题目缓存起来
|
|
|
|
|
_last_generated_papers[questions_key] = generated_questions
|
|
|
|
|
|
|
|
|
|
# 3. 初始化新会话数据
|
|
|
|
|
session_id = str(uuid.uuid4())
|
|
|
|
|
_sessions[session_id] = {
|
|
|
|
|
"questions": generated_questions,
|
|
|
|
|
"answers": {}, # {question_id: answer_key}
|
|
|
|
|
"index": 0, # 当前题目索引
|
|
|
|
|
"index": 0, # 当前题目索引,新会话从 0 开始
|
|
|
|
|
"grade": grade,
|
|
|
|
|
"source": source # 记录题目来源(例如: generator, external, fallback)
|
|
|
|
|
"source": source # 记录题目来源(generator, reused 等)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
@ -71,6 +88,7 @@ def get_next_question(session_id: str) -> dict:
|
|
|
|
|
return {"success": False, "message": "无效会话"}
|
|
|
|
|
|
|
|
|
|
# 检查是否完成
|
|
|
|
|
# 【注意】这里访问的是 'index',确保和 create_session 中的键名一致
|
|
|
|
|
if s["index"] >= len(s["questions"]):
|
|
|
|
|
return {"success": False, "finished": True}
|
|
|
|
|
|
|
|
|
|
@ -119,14 +137,7 @@ def submit_answer(session_id: str, question_id: str, answer: str) -> dict:
|
|
|
|
|
|
|
|
|
|
def get_session_data_for_scoring(session_id: str) -> Optional[Dict[str, Any]]:
|
|
|
|
|
"""
|
|
|
|
|
【新增公共接口】
|
|
|
|
|
为 paper_scoring 模块提供会话的只读数据副本。
|
|
|
|
|
职责:根据 session_id 获取会话的题目和用户答案,防止外部直接修改 _sessions。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
session_id (str): 会话 ID。
|
|
|
|
|
Returns:
|
|
|
|
|
Optional[Dict[str, Any]]: 包含 'questions' 和 'answers' 的数据字典,或 None。
|
|
|
|
|
"""
|
|
|
|
|
s = _sessions.get(session_id)
|
|
|
|
|
if not s:
|
|
|
|
|
@ -141,7 +152,6 @@ def get_session_data_for_scoring(session_id: str) -> Optional[Dict[str, Any]]:
|
|
|
|
|
|
|
|
|
|
def clear_session(session_id: str) -> bool:
|
|
|
|
|
"""
|
|
|
|
|
【新增公共接口】
|
|
|
|
|
评分完成后清理内存中的会话。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
@ -151,6 +161,7 @@ def clear_session(session_id: str) -> bool:
|
|
|
|
|
"""
|
|
|
|
|
if session_id in _sessions:
|
|
|
|
|
del _sessions[session_id]
|
|
|
|
|
# 注意: 这里不清理 _last_generated_papers,因为我们希望保留它用于“再答一次”
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|