"""习题与知识点编码的匹配、范围过滤。""" from __future__ import annotations from app.models import Exercise from app.utils.knowledge_codes import knowledge_family_prefix, split_knowledge_codes def exercise_matches_knowledge_point(ex: Exercise, selected_code: str) -> bool: sel = (selected_code or "").strip() if not sel: return False raw = (getattr(ex, "knowledge_code", None) or "").strip() if not raw: return False ex_codes = split_knowledge_codes(raw) if not ex_codes: ex_codes = [raw] if sel in ex_codes: return True fam = knowledge_family_prefix(sel) if fam: for c in ex_codes: if c.startswith(fam) or c == sel: return True return False def exercise_matches_any_selected(ex: Exercise, selected_codes: list[str]) -> bool: return any(exercise_matches_knowledge_point(ex, c) for c in selected_codes if c.strip()) def exercise_in_grade_category_scope( ex: Exercise, knowledge_grade: str | None, knowledge_category: str | None, ) -> bool: """题量补足:仅允许与当前页面所选年级、类别一致(题目需有对应元数据)。""" g_req = (knowledge_grade or "").strip() c_req = (knowledge_category or "").strip() if not g_req and not c_req: return False g_ex = (getattr(ex, "knowledge_grade", None) or "").strip() c_ex = (getattr(ex, "knowledge_category", None) or "").strip() if g_req and g_ex != g_req: return False if c_req and c_ex != c_req: return False return bool(g_ex or c_ex)