56 lines
1.6 KiB
Markdown
56 lines
1.6 KiB
Markdown
# JSON I/O, State Machine, and Folders (Minimal)
|
|
|
|
## Folders
|
|
- `input/` — source exam JSON files
|
|
- `attempts/{userId}/{examId}/{attemptId}.json` — current attempt files
|
|
- `output/{examId}_{attemptId}.json` — final bundle `{ exam, attempt }`
|
|
- `progress/{userId}.json` — per-user snapshot
|
|
- `manifest.json` — registry of published exams and user completion
|
|
|
|
## Input Exam JSON
|
|
- Must conform to `docs/exam-format.md`
|
|
|
|
## Attempt JSON
|
|
```
|
|
{
|
|
"attemptId": "<id>",
|
|
"userId": "<user>",
|
|
"examId": "<exam>",
|
|
"status": "in_progress|submitted|finished",
|
|
"startedAt": "ISO-8601",
|
|
"updatedAt": "ISO-8601",
|
|
"submittedAt": "ISO-8601?",
|
|
"answers": [ { "questionId": "q1", "response": <any>, "timeSec": 25 } ]
|
|
}
|
|
```
|
|
|
|
## Output JSON
|
|
```
|
|
{
|
|
"exam": { /* original exam JSON */ },
|
|
"attempt": { /* final attempt JSON */ }
|
|
}
|
|
```
|
|
|
|
## State Machine
|
|
- `draft` → `published` → `in_progress` → `submitted` → `finished`
|
|
|
|
## Publish & Finish
|
|
- Publish: `manifest.json` marks `{ examId, published: true }`
|
|
- Finish for a user: attempt.status `finished` AND output bundle exists AND manifest.users[userId].finished includes examId
|
|
|
|
## Autosave & Integrity
|
|
- Write to temp file then atomic rename for attempts/progress/output/manifest
|
|
- Server returns `updatedAt` for reconciliation
|
|
- One active attempt per exam per user (simple lock)
|
|
|
|
## Naming
|
|
- `attemptId = <userId>-<examId>-<timestamp>`
|
|
- Output file name: `<examId>_<attemptId>.json`
|
|
|
|
## Versioning
|
|
- Store `examVersion` in attempt; warn on resume if drift
|
|
|
|
## Permissions (minimal)
|
|
- Local file permissions: read-only for `input/`; write for others
|