All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 2m30s
144 lines
4.7 KiB
Markdown
144 lines
4.7 KiB
Markdown
# Auto-Import Implementation Summary
|
|
|
|
## What was implemented:
|
|
|
|
### 1. Dependencies (pyproject.toml)
|
|
- Created `pyproject.toml` in `quiz/` directory
|
|
- Added Django and watchdog dependencies
|
|
- Configured for `uv` package manager
|
|
|
|
### 2. Question Importer (quiz/utils/importer.py)
|
|
- `ImportStats` class: Tracks import statistics including:
|
|
- Total files found
|
|
- MCQ vs non-MCQ questions
|
|
- Questions with answers vs TODO placeholders
|
|
- Created vs updated counts
|
|
- Per-folder completion statistics
|
|
- `parse_markdown_question()`: Parses markdown files to extract:
|
|
- Question text
|
|
- Options (supports both `- A:` and `- A` formats)
|
|
- Correct answer from spoiler blocks
|
|
- Skips questions with "TODO" answers
|
|
- `import_question_file()`: Imports a single question file
|
|
- `import_questions()`: Bulk import with statistics
|
|
- `delete_question_by_path()`: Removes deleted questions from database
|
|
|
|
### 3. File System Watcher (quiz/utils/watcher.py)
|
|
- `QuestionFileHandler`: Handles file system events with:
|
|
- 2-second debounce for file changes
|
|
- Auto-import on file create/modify
|
|
- Auto-delete on file removal
|
|
- Real-time console feedback
|
|
- `QuestionWatcher`: Main watcher class using watchdog Observer
|
|
- `start_watcher_thread()`: Starts watcher in background daemon thread
|
|
- Performs initial full import on startup
|
|
- Displays comprehensive statistics
|
|
- Continues watching for changes
|
|
|
|
### 4. Django Integration
|
|
- Updated `QuizAppConfig.ready()` in `apps.py`:
|
|
- Automatically starts watcher thread on Django startup
|
|
- Runs in daemon thread (doesn't block shutdown)
|
|
- Only runs in main process (not reloader)
|
|
- Updated `import_questions` management command:
|
|
- Uses refactored importer
|
|
- Shows detailed statistics output
|
|
- Added `QUESTION_WATCH_PATH` setting to `settings.py`
|
|
|
|
## Current Statistics:
|
|
```
|
|
Total .md files found: 312
|
|
MCQ questions found: 162
|
|
Non-MCQ skipped: 152
|
|
Questions with answers: 6
|
|
Questions with TODO: 154
|
|
Overall completion: 3.7%
|
|
|
|
Completion by Exam Folder:
|
|
2022-01-15 2/ 25 MCQ ( 8.0%)
|
|
2022-06-01 4/ 19 MCQ ( 21.1%)
|
|
2023-01-11 0/ 17 MCQ ( 0.0%)
|
|
2023-05-31 0/ 10 MCQ ( 0.0%)
|
|
2024-01-10 0/ 14 MCQ ( 0.0%)
|
|
2024-05-29 0/ 14 MCQ ( 0.0%)
|
|
2025-01-15 0/ 16 MCQ ( 0.0%)
|
|
2025-02-08 0/ 16 MCQ ( 0.0%)
|
|
2025-06-03 0/ 16 MCQ ( 0.0%)
|
|
2025-08-08 0/ 15 MCQ ( 0.0%)
|
|
```
|
|
|
|
## How it works:
|
|
|
|
1. **On Django startup**:
|
|
- Background thread starts automatically
|
|
- Performs initial import of all questions
|
|
- Displays comprehensive statistics
|
|
- Begins watching for file changes
|
|
|
|
2. **When you edit a question in Obsidian**:
|
|
- Watcher detects file change
|
|
- Waits 2 seconds (debounce multiple saves)
|
|
- Automatically imports/updates the question
|
|
- Shows console feedback
|
|
|
|
3. **When you delete a question file**:
|
|
- Watcher detects deletion
|
|
- Removes question from database
|
|
|
|
4. **Manual import**:
|
|
- Run: `python3 manage.py import_questions`
|
|
- Shows same detailed statistics
|
|
|
|
## Future considerations:
|
|
|
|
### Multi-select questions support:
|
|
Currently the `Question.correct_answer` field is `max_length=1`, which only supports single answers. Many questions have "Välj två alternativ" and answers like "B och D" or "B, D".
|
|
|
|
To support multi-select:
|
|
1. Update `Question.correct_answer` to `max_length=50`
|
|
2. Create Django migration
|
|
3. Update `parse_markdown_question()` to extract multiple letters (e.g., "B och D" → "B,D")
|
|
4. Update `views.py` answer validation to compare sorted comma-separated values
|
|
5. Update quiz UI to allow selecting multiple options
|
|
|
|
### Answer format normalization:
|
|
Need to standardize multi-select answer format in Obsidian:
|
|
- Current: "B och D", "B, D", "BD"
|
|
- Recommended: "B,D" (sorted, comma-separated, no spaces)
|
|
|
|
### Question types not yet supported:
|
|
- `frågetyp/hotspot`: Image-based clickable questions
|
|
- `frågetyp/dnd-text`: Drag-and-drop text matching
|
|
- `frågetyp/textfält`: Free text input questions
|
|
- `frågetyp/sammansatt`: Multi-part questions
|
|
|
|
These are currently skipped during import.
|
|
|
|
## Testing the implementation:
|
|
|
|
1. **Start Django server**:
|
|
```bash
|
|
cd /Users/johandahlin/dev/medical-notes/quiz
|
|
python3 manage.py runserver
|
|
```
|
|
You'll see the initial import statistics on startup.
|
|
|
|
2. **Test auto-import**:
|
|
- Open a question in Obsidian with "TODO" in spoiler block
|
|
- Replace "TODO" with a letter (e.g., "B")
|
|
- Save the file
|
|
- Check Django console for auto-import message
|
|
|
|
3. **Test manual import**:
|
|
```bash
|
|
python3 manage.py import_questions
|
|
```
|
|
|
|
4. **Check database**:
|
|
```bash
|
|
python3 manage.py shell
|
|
>>> from quiz.models import Question
|
|
>>> Question.objects.count()
|
|
```
|
|
|