Spaces:
Sleeping
Sleeping
github-actions[bot] commited on
Commit ยท
3ec1cd7
1
Parent(s): 4f74e1c
๐ Auto-deploy backend from GitHub (5544829)
Browse files
main.py
CHANGED
|
@@ -290,6 +290,7 @@ def call_hf_chat(
|
|
| 290 |
top_p: float = 0.9,
|
| 291 |
repetition_penalty: float = 1.15,
|
| 292 |
model: Optional[str] = None,
|
|
|
|
| 293 |
) -> str:
|
| 294 |
"""
|
| 295 |
Call the HF Serverless Inference API (OpenAI-compatible chat endpoint)
|
|
@@ -314,7 +315,7 @@ def call_hf_chat(
|
|
| 314 |
}
|
| 315 |
|
| 316 |
for attempt in range(3):
|
| 317 |
-
resp = http_requests.post(url, headers=headers, json=payload, timeout=
|
| 318 |
if resp.status_code == 503 and attempt < 2:
|
| 319 |
logger.warning(f"HF chat 503 (model loading), retry {attempt + 1}/3")
|
| 320 |
time.sleep(3)
|
|
@@ -1342,48 +1343,70 @@ class CalculatorResponse(BaseModel):
|
|
| 1342 |
latex: Optional[str] = None
|
| 1343 |
|
| 1344 |
|
| 1345 |
-
# โโโ Quiz Topics Database โโโโโโโโโโโโโ
|
| 1346 |
|
| 1347 |
MATH_TOPICS_BY_GRADE: Dict[str, Dict[str, List[str]]] = {
|
| 1348 |
-
"Grade 7": {
|
| 1349 |
-
"Number Sense": ["Integers", "Fractions & Decimals", "Ratios & Proportions", "Percentages"],
|
| 1350 |
-
"Algebra": ["Variables & Expressions", "One-Step Equations", "Inequalities", "Patterns"],
|
| 1351 |
-
"Geometry": ["Angles", "Triangles", "Area & Perimeter", "Volume"],
|
| 1352 |
-
"Statistics": ["Mean, Median, Mode", "Bar & Line Graphs", "Probability Basics"],
|
| 1353 |
-
},
|
| 1354 |
-
"Grade 8": {
|
| 1355 |
-
"Algebra": ["Linear Equations", "Systems of Equations (Introduction)", "Slope & Rate of Change", "Functions"],
|
| 1356 |
-
"Geometry": ["Pythagorean Theorem", "Transformations", "Congruence & Similarity", "Surface Area & Volume"],
|
| 1357 |
-
"Number Sense": ["Exponents & Powers", "Scientific Notation", "Square & Cube Roots", "Rational & Irrational Numbers"],
|
| 1358 |
-
"Statistics": ["Scatter Plots", "Two-Way Tables", "Probability of Compound Events"],
|
| 1359 |
-
},
|
| 1360 |
-
"Grade 9": {
|
| 1361 |
-
"Algebra": ["Linear Functions", "Quadratic Equations", "Polynomials", "Factoring"],
|
| 1362 |
-
"Geometry": ["Coordinate Geometry", "Circles", "Trigonometric Ratios", "Proofs"],
|
| 1363 |
-
"Statistics": ["Data Analysis", "Normal Distribution Basics", "Sampling Methods"],
|
| 1364 |
-
"Number Sense": ["Radicals & Exponents", "Rational Expressions"],
|
| 1365 |
-
},
|
| 1366 |
-
"Grade 10": {
|
| 1367 |
-
"Algebra": ["Quadratic Functions", "Systems of Equations", "Exponential Functions", "Radical Equations"],
|
| 1368 |
-
"Geometry": ["Circle Theorems", "Solid Geometry", "Coordinate Proofs", "Trigonometry"],
|
| 1369 |
-
"Statistics & Probability": ["Permutations & Combinations", "Conditional Probability", "Binomial Probability"],
|
| 1370 |
-
"Pre-Calculus": ["Sequences & Series", "Polynomial Functions"],
|
| 1371 |
-
},
|
| 1372 |
"Grade 11": {
|
| 1373 |
-
"
|
| 1374 |
-
|
| 1375 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1376 |
},
|
| 1377 |
"Grade 12": {
|
| 1378 |
-
"
|
| 1379 |
-
|
| 1380 |
-
|
| 1381 |
-
|
| 1382 |
-
|
| 1383 |
-
"Calculus
|
| 1384 |
-
|
| 1385 |
-
|
| 1386 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1387 |
},
|
| 1388 |
}
|
| 1389 |
|
|
@@ -1630,15 +1653,64 @@ Remember:
|
|
| 1630 |
|
| 1631 |
logger.info(f"Generating quiz: {request.numQuestions} questions, topics={effective_topics}")
|
| 1632 |
|
| 1633 |
-
|
| 1634 |
-
|
|
|
|
|
|
|
| 1635 |
|
| 1636 |
-
parsed_questions =
|
| 1637 |
-
if
|
| 1638 |
-
|
| 1639 |
-
|
| 1640 |
-
|
| 1641 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1642 |
)
|
| 1643 |
|
| 1644 |
validated = _validate_quiz_questions(parsed_questions, distribution)
|
|
@@ -1712,7 +1784,8 @@ async def preview_quiz(request: QuizGenerationRequest):
|
|
| 1712 |
@app.get("/api/quiz/topics")
|
| 1713 |
async def get_quiz_topics(gradeLevel: Optional[str] = None):
|
| 1714 |
"""
|
| 1715 |
-
Return structured list of math topics organised by grade level.
|
|
|
|
| 1716 |
If gradeLevel is provided, return topics for that grade only.
|
| 1717 |
"""
|
| 1718 |
if gradeLevel:
|
|
@@ -1729,7 +1802,11 @@ async def get_quiz_topics(gradeLevel: Optional[str] = None):
|
|
| 1729 |
detail=f"Grade level '{gradeLevel}' not found. Available: {list(MATH_TOPICS_BY_GRADE.keys())}",
|
| 1730 |
)
|
| 1731 |
|
| 1732 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1733 |
|
| 1734 |
|
| 1735 |
# โโโ Student Competency Assessment โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
@@ -2195,6 +2272,165 @@ async def get_analytics_config():
|
|
| 2195 |
}
|
| 2196 |
|
| 2197 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2198 |
# โโโ Automation Engine Endpoints โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 2199 |
|
| 2200 |
|
|
|
|
| 290 |
top_p: float = 0.9,
|
| 291 |
repetition_penalty: float = 1.15,
|
| 292 |
model: Optional[str] = None,
|
| 293 |
+
timeout: int = 90,
|
| 294 |
) -> str:
|
| 295 |
"""
|
| 296 |
Call the HF Serverless Inference API (OpenAI-compatible chat endpoint)
|
|
|
|
| 315 |
}
|
| 316 |
|
| 317 |
for attempt in range(3):
|
| 318 |
+
resp = http_requests.post(url, headers=headers, json=payload, timeout=timeout)
|
| 319 |
if resp.status_code == 503 and attempt < 2:
|
| 320 |
logger.warning(f"HF chat 503 (model loading), retry {attempt + 1}/3")
|
| 321 |
time.sleep(3)
|
|
|
|
| 1343 |
latex: Optional[str] = None
|
| 1344 |
|
| 1345 |
|
| 1346 |
+
# โโโ Quiz Topics Database (SHS Grade 11-12 Only) โโโโโโโโโโโโโ
|
| 1347 |
|
| 1348 |
MATH_TOPICS_BY_GRADE: Dict[str, Dict[str, List[str]]] = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1349 |
"Grade 11": {
|
| 1350 |
+
"General Mathematics - Functions and Their Graphs": [
|
| 1351 |
+
"Functions and Relations", "Evaluating Functions", "Operations on Functions",
|
| 1352 |
+
"Composite Functions", "Inverse Functions", "Rational Functions",
|
| 1353 |
+
"Exponential Functions", "Logarithmic Functions",
|
| 1354 |
+
],
|
| 1355 |
+
"General Mathematics - Business Mathematics": [
|
| 1356 |
+
"Simple Interest", "Compound Interest", "Annuities",
|
| 1357 |
+
"Loans and Amortization", "Stocks and Bonds",
|
| 1358 |
+
],
|
| 1359 |
+
"General Mathematics - Logic": [
|
| 1360 |
+
"Propositions and Connectives", "Truth Tables",
|
| 1361 |
+
"Logical Equivalence", "Valid Arguments and Fallacies",
|
| 1362 |
+
],
|
| 1363 |
+
"Statistics and Probability - Random Variables": [
|
| 1364 |
+
"Random Variables", "Discrete Probability Distributions",
|
| 1365 |
+
"Mean and Variance of Discrete RV",
|
| 1366 |
+
],
|
| 1367 |
+
"Statistics and Probability - Normal Distribution": [
|
| 1368 |
+
"Normal Distribution", "Standard Normal Distribution and Z-scores",
|
| 1369 |
+
"Areas Under the Normal Curve",
|
| 1370 |
+
],
|
| 1371 |
+
"Statistics and Probability - Sampling and Estimation": [
|
| 1372 |
+
"Sampling Distributions", "Central Limit Theorem",
|
| 1373 |
+
"Point Estimation", "Confidence Intervals",
|
| 1374 |
+
],
|
| 1375 |
+
"Statistics and Probability - Hypothesis Testing": [
|
| 1376 |
+
"Hypothesis Testing Concepts", "T-test", "Z-test",
|
| 1377 |
+
"Correlation and Regression",
|
| 1378 |
+
],
|
| 1379 |
},
|
| 1380 |
"Grade 12": {
|
| 1381 |
+
"Pre-Calculus - Analytic Geometry": [
|
| 1382 |
+
"Conic Sections - Parabola", "Conic Sections - Ellipse",
|
| 1383 |
+
"Conic Sections - Hyperbola", "Conic Sections - Circle",
|
| 1384 |
+
"Systems of Nonlinear Equations",
|
| 1385 |
+
],
|
| 1386 |
+
"Pre-Calculus - Series and Induction": [
|
| 1387 |
+
"Sequences and Series", "Arithmetic Sequences", "Geometric Sequences",
|
| 1388 |
+
"Mathematical Induction", "Binomial Theorem",
|
| 1389 |
+
],
|
| 1390 |
+
"Pre-Calculus - Trigonometry": [
|
| 1391 |
+
"Angles and Unit Circle", "Trigonometric Functions",
|
| 1392 |
+
"Trigonometric Identities", "Sum and Difference Formulas",
|
| 1393 |
+
"Inverse Trigonometric Functions", "Polar Coordinates",
|
| 1394 |
+
],
|
| 1395 |
+
"Basic Calculus - Limits": [
|
| 1396 |
+
"Limits of Functions", "Limit Theorems", "One-Sided Limits",
|
| 1397 |
+
"Infinite Limits and Limits at Infinity", "Continuity of Functions",
|
| 1398 |
+
],
|
| 1399 |
+
"Basic Calculus - Derivatives": [
|
| 1400 |
+
"Definition of the Derivative", "Differentiation Rules", "Chain Rule",
|
| 1401 |
+
"Implicit Differentiation", "Higher-Order Derivatives", "Related Rates",
|
| 1402 |
+
"Extrema and the First Derivative Test",
|
| 1403 |
+
"Concavity and the Second Derivative Test", "Optimization Problems",
|
| 1404 |
+
],
|
| 1405 |
+
"Basic Calculus - Integration": [
|
| 1406 |
+
"Antiderivatives and Indefinite Integrals",
|
| 1407 |
+
"Definite Integrals and the FTC",
|
| 1408 |
+
"Integration by Substitution", "Area Under a Curve",
|
| 1409 |
+
],
|
| 1410 |
},
|
| 1411 |
}
|
| 1412 |
|
|
|
|
| 1653 |
|
| 1654 |
logger.info(f"Generating quiz: {request.numQuestions} questions, topics={effective_topics}")
|
| 1655 |
|
| 1656 |
+
# Scale max_tokens based on requested questions โ each question needs ~400-600 tokens
|
| 1657 |
+
max_tokens = min(16384, max(4096, request.numQuestions * 600))
|
| 1658 |
+
# Use longer HTTP timeout for quiz generation (scales with question count)
|
| 1659 |
+
http_timeout = max(90, request.numQuestions * 12)
|
| 1660 |
|
| 1661 |
+
parsed_questions: List[Dict[str, Any]] = []
|
| 1662 |
+
max_attempts = 2 # Retry once if LLM generates too few questions
|
| 1663 |
+
|
| 1664 |
+
for attempt in range(max_attempts):
|
| 1665 |
+
raw_content = call_hf_chat(
|
| 1666 |
+
messages, max_tokens=max_tokens, temperature=0.3, top_p=0.9,
|
| 1667 |
+
timeout=http_timeout,
|
| 1668 |
+
)
|
| 1669 |
+
logger.info(f"Raw quiz response length: {len(raw_content)} chars (attempt {attempt + 1})")
|
| 1670 |
+
|
| 1671 |
+
parsed_questions = _parse_quiz_json(raw_content)
|
| 1672 |
+
|
| 1673 |
+
if not parsed_questions:
|
| 1674 |
+
logger.error(f"Failed to parse quiz JSON (attempt {attempt + 1}). Raw content:\n{raw_content[:500]}")
|
| 1675 |
+
if attempt < max_attempts - 1:
|
| 1676 |
+
logger.info("Retrying quiz generation...")
|
| 1677 |
+
continue
|
| 1678 |
+
raise HTTPException(
|
| 1679 |
+
status_code=500,
|
| 1680 |
+
detail="Failed to parse quiz questions from AI response. Please try again.",
|
| 1681 |
+
)
|
| 1682 |
+
|
| 1683 |
+
# If we got at least 70% of requested questions, accept the result
|
| 1684 |
+
if len(parsed_questions) >= request.numQuestions * 0.7:
|
| 1685 |
+
break
|
| 1686 |
+
|
| 1687 |
+
# Otherwise retry with a stronger nudge
|
| 1688 |
+
if attempt < max_attempts - 1:
|
| 1689 |
+
logger.warning(
|
| 1690 |
+
f"LLM generated only {len(parsed_questions)}/{request.numQuestions} questions "
|
| 1691 |
+
f"(attempt {attempt + 1}). Retrying with reinforced prompt..."
|
| 1692 |
+
)
|
| 1693 |
+
# Add an assistant + user turn to push the LLM harder
|
| 1694 |
+
messages = [
|
| 1695 |
+
{"role": "system", "content": QUIZ_GENERATION_SYSTEM_PROMPT},
|
| 1696 |
+
{"role": "user", "content": prompt},
|
| 1697 |
+
{"role": "assistant", "content": raw_content},
|
| 1698 |
+
{
|
| 1699 |
+
"role": "user",
|
| 1700 |
+
"content": (
|
| 1701 |
+
f"You only generated {len(parsed_questions)} questions but I need "
|
| 1702 |
+
f"exactly {request.numQuestions}. Please generate ALL "
|
| 1703 |
+
f"{request.numQuestions} questions in a single JSON array. "
|
| 1704 |
+
f"Do not stop early."
|
| 1705 |
+
),
|
| 1706 |
+
},
|
| 1707 |
+
]
|
| 1708 |
+
|
| 1709 |
+
# Warn if the LLM still generated fewer questions than requested
|
| 1710 |
+
if len(parsed_questions) < request.numQuestions:
|
| 1711 |
+
logger.warning(
|
| 1712 |
+
f"LLM generated {len(parsed_questions)}/{request.numQuestions} questions "
|
| 1713 |
+
f"after {max_attempts} attempts (raw length={len(raw_content)} chars)."
|
| 1714 |
)
|
| 1715 |
|
| 1716 |
validated = _validate_quiz_questions(parsed_questions, distribution)
|
|
|
|
| 1784 |
@app.get("/api/quiz/topics")
|
| 1785 |
async def get_quiz_topics(gradeLevel: Optional[str] = None):
|
| 1786 |
"""
|
| 1787 |
+
Return structured list of SHS math topics organised by grade level.
|
| 1788 |
+
Only Grade 11 and Grade 12 are supported.
|
| 1789 |
If gradeLevel is provided, return topics for that grade only.
|
| 1790 |
"""
|
| 1791 |
if gradeLevel:
|
|
|
|
| 1802 |
detail=f"Grade level '{gradeLevel}' not found. Available: {list(MATH_TOPICS_BY_GRADE.keys())}",
|
| 1803 |
)
|
| 1804 |
|
| 1805 |
+
# Return all SHS topics organized by grade
|
| 1806 |
+
return {
|
| 1807 |
+
"gradeLevels": list(MATH_TOPICS_BY_GRADE.keys()),
|
| 1808 |
+
"allTopics": MATH_TOPICS_BY_GRADE,
|
| 1809 |
+
}
|
| 1810 |
|
| 1811 |
|
| 1812 |
# โโโ Student Competency Assessment โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
|
| 2272 |
}
|
| 2273 |
|
| 2274 |
|
| 2275 |
+
# โโโ Topic Mastery Analytics โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 2276 |
+
|
| 2277 |
+
# SHS topic data for fallback/mock generation
|
| 2278 |
+
_SHS_TOPICS = {
|
| 2279 |
+
"gen-math": {
|
| 2280 |
+
"name": "General Mathematics",
|
| 2281 |
+
"topics": [
|
| 2282 |
+
("Functions and Relations", "Functions and Their Graphs"),
|
| 2283 |
+
("Evaluating Functions", "Functions and Their Graphs"),
|
| 2284 |
+
("Operations on Functions", "Functions and Their Graphs"),
|
| 2285 |
+
("Composite Functions", "Functions and Their Graphs"),
|
| 2286 |
+
("Inverse Functions", "Functions and Their Graphs"),
|
| 2287 |
+
("Rational Functions", "Functions and Their Graphs"),
|
| 2288 |
+
("Exponential Functions", "Functions and Their Graphs"),
|
| 2289 |
+
("Logarithmic Functions", "Functions and Their Graphs"),
|
| 2290 |
+
("Simple Interest", "Business Mathematics"),
|
| 2291 |
+
("Compound Interest", "Business Mathematics"),
|
| 2292 |
+
("Annuities", "Business Mathematics"),
|
| 2293 |
+
("Loans and Amortization", "Business Mathematics"),
|
| 2294 |
+
("Stocks and Bonds", "Business Mathematics"),
|
| 2295 |
+
("Propositions and Connectives", "Logic"),
|
| 2296 |
+
("Truth Tables", "Logic"),
|
| 2297 |
+
("Logical Equivalence", "Logic"),
|
| 2298 |
+
("Valid Arguments and Fallacies", "Logic"),
|
| 2299 |
+
],
|
| 2300 |
+
},
|
| 2301 |
+
"stats-prob": {
|
| 2302 |
+
"name": "Statistics and Probability",
|
| 2303 |
+
"topics": [
|
| 2304 |
+
("Random Variables", "Random Variables"),
|
| 2305 |
+
("Discrete Probability Distributions", "Random Variables"),
|
| 2306 |
+
("Mean and Variance of Discrete RV", "Random Variables"),
|
| 2307 |
+
("Normal Distribution", "Normal Distribution"),
|
| 2308 |
+
("Standard Normal Distribution and Z-scores", "Normal Distribution"),
|
| 2309 |
+
("Areas Under the Normal Curve", "Normal Distribution"),
|
| 2310 |
+
("Sampling Distributions", "Sampling and Estimation"),
|
| 2311 |
+
("Central Limit Theorem", "Sampling and Estimation"),
|
| 2312 |
+
("Point Estimation", "Sampling and Estimation"),
|
| 2313 |
+
("Confidence Intervals", "Sampling and Estimation"),
|
| 2314 |
+
("Hypothesis Testing Concepts", "Hypothesis Testing"),
|
| 2315 |
+
("T-test", "Hypothesis Testing"),
|
| 2316 |
+
("Z-test", "Hypothesis Testing"),
|
| 2317 |
+
("Correlation and Regression", "Correlation and Regression"),
|
| 2318 |
+
],
|
| 2319 |
+
},
|
| 2320 |
+
"pre-calc": {
|
| 2321 |
+
"name": "Pre-Calculus",
|
| 2322 |
+
"topics": [
|
| 2323 |
+
("Conic Sections - Parabola", "Analytic Geometry"),
|
| 2324 |
+
("Conic Sections - Ellipse", "Analytic Geometry"),
|
| 2325 |
+
("Conic Sections - Hyperbola", "Analytic Geometry"),
|
| 2326 |
+
("Conic Sections - Circle", "Analytic Geometry"),
|
| 2327 |
+
("Systems of Nonlinear Equations", "Analytic Geometry"),
|
| 2328 |
+
("Sequences and Series", "Series and Induction"),
|
| 2329 |
+
("Arithmetic Sequences", "Series and Induction"),
|
| 2330 |
+
("Geometric Sequences", "Series and Induction"),
|
| 2331 |
+
("Mathematical Induction", "Series and Induction"),
|
| 2332 |
+
("Binomial Theorem", "Series and Induction"),
|
| 2333 |
+
("Angles and Unit Circle", "Trigonometry"),
|
| 2334 |
+
("Trigonometric Functions", "Trigonometry"),
|
| 2335 |
+
("Trigonometric Identities", "Trigonometry"),
|
| 2336 |
+
("Sum and Difference Formulas", "Trigonometry"),
|
| 2337 |
+
("Inverse Trigonometric Functions", "Trigonometry"),
|
| 2338 |
+
("Polar Coordinates", "Trigonometry"),
|
| 2339 |
+
],
|
| 2340 |
+
},
|
| 2341 |
+
"basic-calc": {
|
| 2342 |
+
"name": "Basic Calculus",
|
| 2343 |
+
"topics": [
|
| 2344 |
+
("Limits of Functions", "Limits"),
|
| 2345 |
+
("Limit Theorems", "Limits"),
|
| 2346 |
+
("One-Sided Limits", "Limits"),
|
| 2347 |
+
("Infinite Limits and Limits at Infinity", "Limits"),
|
| 2348 |
+
("Continuity of Functions", "Limits"),
|
| 2349 |
+
("Definition of the Derivative", "Derivatives"),
|
| 2350 |
+
("Differentiation Rules", "Derivatives"),
|
| 2351 |
+
("Chain Rule", "Derivatives"),
|
| 2352 |
+
("Implicit Differentiation", "Derivatives"),
|
| 2353 |
+
("Higher-Order Derivatives", "Derivatives"),
|
| 2354 |
+
("Related Rates", "Derivatives"),
|
| 2355 |
+
("Extrema and the First Derivative Test", "Derivatives"),
|
| 2356 |
+
("Concavity and the Second Derivative Test", "Derivatives"),
|
| 2357 |
+
("Optimization Problems", "Derivatives"),
|
| 2358 |
+
("Antiderivatives and Indefinite Integrals", "Integration"),
|
| 2359 |
+
("Definite Integrals and the FTC", "Integration"),
|
| 2360 |
+
("Integration by Substitution", "Integration"),
|
| 2361 |
+
("Area Under a Curve", "Integration"),
|
| 2362 |
+
],
|
| 2363 |
+
},
|
| 2364 |
+
}
|
| 2365 |
+
|
| 2366 |
+
|
| 2367 |
+
@app.get("/api/analytics/topic-mastery")
|
| 2368 |
+
async def topic_mastery_analytics(
|
| 2369 |
+
teacherId: str = Query(..., description="Teacher UID"),
|
| 2370 |
+
classId: Optional[str] = Query(None, description="Optional class ID filter"),
|
| 2371 |
+
):
|
| 2372 |
+
"""
|
| 2373 |
+
Aggregate per-topic mastery statistics for a teacher's class.
|
| 2374 |
+
Returns topic-level averages, attempt counts, and mastery status.
|
| 2375 |
+
"""
|
| 2376 |
+
import random
|
| 2377 |
+
|
| 2378 |
+
try:
|
| 2379 |
+
# In production, this would query Firestore quiz submissions.
|
| 2380 |
+
# For now, generate realistic mock data seeded by teacherId.
|
| 2381 |
+
rng = random.Random(hash(teacherId))
|
| 2382 |
+
total_students = 30
|
| 2383 |
+
|
| 2384 |
+
topics_out = []
|
| 2385 |
+
mastered_count = 0
|
| 2386 |
+
needs_attention_count = 0
|
| 2387 |
+
excluded_count = 0
|
| 2388 |
+
|
| 2389 |
+
for subj_id, subj_data in _SHS_TOPICS.items():
|
| 2390 |
+
for topic_name, unit in subj_data["topics"]:
|
| 2391 |
+
attempted = rng.randint(3, total_students)
|
| 2392 |
+
class_avg = round(rng.uniform(35, 95), 1)
|
| 2393 |
+
above_85 = int(attempted * (rng.uniform(0.6, 0.95) if class_avg >= 85 else rng.uniform(0.05, 0.35)))
|
| 2394 |
+
mastery_pct = round((above_85 / total_students) * 100, 1)
|
| 2395 |
+
|
| 2396 |
+
if attempted < 3:
|
| 2397 |
+
status = "no_data"
|
| 2398 |
+
elif mastery_pct >= 75:
|
| 2399 |
+
status = "mastered"
|
| 2400 |
+
mastered_count += 1
|
| 2401 |
+
elif class_avg >= 60:
|
| 2402 |
+
status = "on_track"
|
| 2403 |
+
else:
|
| 2404 |
+
status = "needs_attention"
|
| 2405 |
+
needs_attention_count += 1
|
| 2406 |
+
|
| 2407 |
+
topics_out.append({
|
| 2408 |
+
"topicName": topic_name,
|
| 2409 |
+
"subjectId": subj_id,
|
| 2410 |
+
"unit": unit,
|
| 2411 |
+
"classAverage": class_avg,
|
| 2412 |
+
"studentsAttempted": attempted,
|
| 2413 |
+
"totalStudents": total_students,
|
| 2414 |
+
"studentsAbove85": above_85,
|
| 2415 |
+
"masteryPercentage": mastery_pct,
|
| 2416 |
+
"masteryStatus": status,
|
| 2417 |
+
"isExcluded": False,
|
| 2418 |
+
})
|
| 2419 |
+
|
| 2420 |
+
return {
|
| 2421 |
+
"topics": topics_out,
|
| 2422 |
+
"summary": {
|
| 2423 |
+
"totalTopicsTracked": len(topics_out),
|
| 2424 |
+
"masteredCount": mastered_count,
|
| 2425 |
+
"needsAttentionCount": needs_attention_count,
|
| 2426 |
+
"excludedCount": excluded_count,
|
| 2427 |
+
},
|
| 2428 |
+
}
|
| 2429 |
+
except Exception as e:
|
| 2430 |
+
logger.error(f"Topic mastery analytics error: {e}")
|
| 2431 |
+
raise HTTPException(status_code=500, detail=f"Topic mastery error: {str(e)}")
|
| 2432 |
+
|
| 2433 |
+
|
| 2434 |
# โโโ Automation Engine Endpoints โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 2435 |
|
| 2436 |
|