Spaces:
Running
Running
| # MathPulse AI — Firestore Schema (Practice Center) | |
| ## Collection: practice_sessions | |
| ### Document: practice_sessions/{session_id} | |
| Purpose: stores the generated question set for a practice session. | |
| Ownership: user-owned via `userId`. | |
| Written by: backend `/api/practice/generate` endpoint. | |
| Read by: backend `/api/practice/submit` endpoint. | |
| Retention: kept for debugging and audit, can be cleaned up after result is stored. | |
| | Field | Type | Description | | |
| |-------|------|-------------| | |
| | session_id | string | UUID | | |
| | userId | string | Firebase UID | | |
| | subject | string | Subject name | | |
| | competency | string | Competency/topic | | |
| | difficulty | string | Practice, Challenge, or Mastery | | |
| | questions | array | Array of question objects | | |
| | generated_at | timestamp | When generated | | |
| ```json | |
| { | |
| "session_id": "uuid string", | |
| "userId": "firebase uid", | |
| "subject": "Algebra | Geometry | ...", | |
| "competency": "string", | |
| "difficulty": "Practice | Challenge | Mastery", | |
| "questions": [ | |
| { | |
| "id": "q1", | |
| "question": "What is 2+2?", | |
| "options": ["3", "4", "5", "6"], | |
| "correct_index": 1, | |
| "explanation": "Basic addition...", | |
| "competency": "Basic Arithmetic", | |
| "difficulty": "Practice", | |
| "bloomsLevel": "Remember" | |
| } | |
| ], | |
| "generated_at": "ISO timestamp" | |
| } | |
| ``` | |
| **Indexes needed:** None, single doc reads by `session_id`. | |
| ## Collection: practice_results/{userId}/sessions | |
| ### Document: practice_results/{userId}/sessions/{session_id} | |
| Purpose: stores the result of a completed practice session. | |
| Ownership: user-owned subcollection under `practice_results/{userId}`. | |
| Written by: backend `/api/practice/submit` endpoint. | |
| Read by: backend `/api/practice/stats` and `/api/practice/history` endpoints. | |
| | Field | Type | Description | | |
| |-------|------|-------------| | |
| | session_id | string | UUID | | |
| | userId | string | Firebase UID | | |
| | score_percent | number | Score percentage | | |
| | correct_count | number | Correct answers | | |
| | total | number | Total questions | | |
| | xp_earned | number | XP earned | | |
| | subject | string | Subject name | | |
| | difficulty | string | Practice, Challenge, or Mastery | | |
| | answers | array | Selected answers per question | | |
| | per_question_feedback | array | Per-question feedback objects | | |
| | submitted_at | timestamp | When submitted | | |
| ```json | |
| { | |
| "session_id": "uuid string", | |
| "userId": "firebase uid", | |
| "score_percent": 80, | |
| "correct_count": 8, | |
| "total": 10, | |
| "xp_earned": 130, | |
| "subject": "Algebra", | |
| "difficulty": "Challenge", | |
| "answers": [ | |
| { "question_id": "q1", "selected_index": 1 } | |
| ], | |
| "per_question_feedback": [ | |
| { | |
| "question_id": "q1", | |
| "selected_index": 1, | |
| "correct_index": 1, | |
| "is_correct": true, | |
| "explanation": "..." | |
| } | |
| ], | |
| "submitted_at": "ISO timestamp" | |
| } | |
| ``` | |
| **Indexes needed:** `submitted_at DESC` for history queries. | |
| ## User Stats Updated by Practice | |
| | Field | Update Rule | | |
| |-------|-------------| | |
| | totalXP | Increment by `xp_earned` | | |
| | quizzesCompleted | Increment by 1 | | |
| | averageScore | Rolling average: `(old_avg * old_count + new_score) / (old_count + 1)` | | |
| ## Query Patterns | |
| - `practice_results/{userId}/sessions` ordered by `submitted_at DESC` for history | |
| - `practice_results/{userId}/sessions` limit 10 for recent sessions used in stats | |
| - `users/{userId}` read `totalXP`, `quizzesCompleted`, `averageScore` | |