BuddyMath / curriculum_engine.py
dotandru's picture
Fix: Clean production deployment with sse-starlette
9d29c62
raw
history blame
4.65 kB
# curriculum_engine.py - V4.0 (Curriculum Oracle)
# Defines pedagogical boundaries according to the Israeli Ministry of Education (Mafmar).
import logging
logger = logging.getLogger(__name__)
CURRICULUM_RULES = {
# grade: { blacklist: [operators], whitelist: [operators], descriptions: {operator: hebrew_name} }
7: {
"blacklist": ["SYSTEM_OF_EQUATIONS", "QUADRATIC_EQUATION", "DERIVATIVE", "INTEGRAL", "TRIGONOMETRY"],
"whitelist": ["LINEAR_EQUATION", "FRACTIONS", "EXPONENTS_BASIC", "PERCENTAGES"],
"descriptions": {
"SYSTEM_OF_EQUATIONS": "מערכת משוואות בשני נעלמים",
"QUADRATIC_EQUATION": "משוואה ריבועית",
"DERIVATIVE": "נגזרות",
"TRIGONOMETRY": "טריגונומטריה"
}
},
8: {
"blacklist": ["QUADRATIC_EQUATION", "DERIVATIVE", "INTEGRAL", "TRIG_Trig_ADVANCED"],
"whitelist": ["LINEAR_EQUATION", "SYSTEM_OF_EQUATIONS", "BASIC_GEOMETRY", "PYTHAGOREAN_THEOREM"],
"descriptions": {
"QUADRATIC_EQUATION": "משוואה ריבועית",
"DERIVATIVE": "נגזרות"
}
},
9: {
"blacklist": ["DERIVATIVE", "INTEGRAL", "LOGARITHM"],
"whitelist": ["QUADRATIC_EQUATION", "SYSTEM_OF_EQUATIONS", "SIMILAR_TRIANGLES", "CIRCLE_BASIC"],
"descriptions": {
"DERIVATIVE": "נגזרות",
"LOGARITHM": "לוגריתמים"
}
},
10: {
"blacklist": ["INTEGRAL_ADVANCED", "VECTORS"],
"whitelist": ["DERIVATIVE_POLYNOMIAL", "TRIGONOMETRY_BASIC", "CIRCLE_EQUATION_BASIC"],
"descriptions": {
"INTEGRAL_ADVANCED": "אינטגרלים מורכבים",
"VECTORS": "ווקטורים"
}
},
# V286.0: Grade 11 — 4 יח"ל focus
11: {
"blacklist": ["VECTORS_3D", "ADVANCED_INTEGRATION", "SOLID_GEOMETRY_ADVANCED"],
"whitelist": ["DERIVATIVE", "TRIGONOMETRY", "LOGARITHM", "SEQUENCES", "COMPLEX_NUMBERS_BASIC",
"FUNCTION_ANALYSIS", "PROBABILITY_BASIC", "CIRCLE_EQUATION"],
"descriptions": {
"VECTORS_3D": "וקטורים במרחב",
"ADVANCED_INTEGRATION": "אינטגרציה מתקדמת"
}
},
# V286.0: Grade 12 / 5 יח"ל — full access
12: {
"blacklist": [],
"whitelist": ["DERIVATIVE", "INTEGRAL", "INTEGRAL_ADVANCED", "TRIGONOMETRY",
"TRIGONOMETRY_ADVANCED", "LOGARITHM", "SEQUENCES", "COMPLEX_NUMBERS",
"COMPLEX_ANALYSIS", "VECTORS", "VECTORS_3D", "FUNCTION_ANALYSIS",
"PROBABILITY", "COMBINATORICS", "SOLID_GEOMETRY", "LIMITS",
"OPTIMIZATION", "INDUCTION", "GEOMETRY_ANALYTIC", "CIRCLE_EQUATION"],
"descriptions": {}
}
}
def get_allowed_math_operators(grade_str: str, level: str = "4", topic: str = "GENERAL") -> dict:
"""
Returns the pedagogical boundary rules for a specific student profile.
Args:
grade_str: Student grade (e.g. "7", "י", "י\"א")
level: Units level for high school (3, 4, 5)
topic: Current mathematical topic
Returns:
dict: { "allowed": [], "forbidden": [], "reason_map": {} }
"""
# 1. Normalize grade
from topic_taxonomy import _extract_grade_number
grade_num = _extract_grade_number(grade_str)
print(f"🎓 [CURRICULUM] Fetching rules for Grade {grade_num}, Level {level} units")
rules = CURRICULUM_RULES.get(grade_num, {
"blacklist": [],
"whitelist": ["GENERAL"],
"descriptions": {}
})
# 2. Add Level-specific tweaks (Epic V4.1+)
if grade_num >= 10:
if level == "3":
rules["blacklist"].extend(["COMPLEX_ANALYSIS", "IMPLICIT_DERIVATIVE"])
elif level == "5":
rules["whitelist"].extend(["COMPLEX_ANALYSIS", "ADVANCED_CALCULUS"])
return {
"allowed": rules.get("whitelist", []),
"forbidden": rules.get("blacklist", []),
"reason_map": rules.get("descriptions", {})
}
def is_operator_allowed(operator: str, grade_str: str, level: str = "4") -> bool:
"""Helper to check a single operator."""
rules = get_allowed_math_operators(grade_str, level)
if operator in rules["forbidden"]:
return False
return True
if __name__ == "__main__":
# Test
print(get_allowed_math_operators("7"))
print(is_operator_allowed("DERIVATIVE", "7"))
print(is_operator_allowed("SYSTEM_OF_EQUATIONS", "7"))
print(is_operator_allowed("SYSTEM_OF_EQUATIONS", "8"))