Spaces:
Running
Running
File size: 3,365 Bytes
65ba59e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | # 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`
|