73 lines
4.3 KiB
Markdown
73 lines
4.3 KiB
Markdown
# 02. Backend (Flask API)
|
|
|
|
The backend is built with Flask, providing API endpoints for the SvelteKit frontend to fetch lessons, track progress, manage authentication, and proxy compilation requests.
|
|
|
|
## Application Factory (`elemes/app.py`)
|
|
|
|
- `def create_app():`
|
|
Initializes the Flask application, loads configuration from `elemes/config.py` (which reads from `.env`), and registers the following blueprints:
|
|
- `auth_bp` (`routes/auth.py`)
|
|
- `lessons_bp` (`routes/lessons.py`)
|
|
- `compile_bp` (`routes/compile.py`)
|
|
- `progress_bp` (`routes/progress.py`)
|
|
|
|
## Core API Routes
|
|
|
|
### Authentication (`routes/auth.py`)
|
|
- `def login():` (POST `/login`)
|
|
Receives `token` in JSON payload. Validates via `token_service.validate_token()`. On success, sets the `student_token` cookie. Rate-limited and includes a 1.5s tarpit for failures.
|
|
- `def logout():` (POST `/logout`)
|
|
Clears the `student_token` cookie.
|
|
- `def validate_token_route():` (POST `/validate-token`)
|
|
Checks if the current `student_token` cookie is valid.
|
|
|
|
### Lessons (`routes/lessons.py`)
|
|
- `def api_lessons():` (GET `/lessons`)
|
|
Returns a list of all lessons and the rendered `home.md` content via `lesson_service.get_ordered_lessons_with_learning_objectives()`.
|
|
- `def api_lesson(filename):` (GET `/lesson/<slug>.json`)
|
|
Returns the fully parsed lesson data (content, initial code, circuits, key texts, active tabs) via `lesson_service.render_markdown_content(filepath)`.
|
|
- `def get_key_text(filename):` (GET `/get-key-text/<slug>`)
|
|
Returns only the required keywords for a specific lesson without exposing the full content logic.
|
|
|
|
### Compilation (`routes/compile.py`)
|
|
- `def compile_code():` (POST `/compile`)
|
|
Accepts `code` and `language`. Routes execution to the sandboxed worker using the `CompilerFactory`. Incorporates rate-limiting for anonymous users.
|
|
- `def velxio_compile():` (POST `/velxio-compile` mapped from `/velxio/api/compile`)
|
|
A proxy endpoint that forwards Arduino compilation requests to the Velxio container, enforcing rate limits for anonymous users.
|
|
|
|
### Progress Tracking (`routes/progress.py`)
|
|
- `def track_progress():` (POST `/track-progress`)
|
|
Accepts `lesson_name` and `status`. Updates the CSV file via `token_service.update_student_progress()`.
|
|
- `def api_progress_report():` (GET `/progress-report.json`)
|
|
Returns a matrix of all student progress. Requires a teacher token.
|
|
- `def export_progress_csv():` (GET `/progress-report/export-csv`)
|
|
Exports progress data as a CSV download. Requires a teacher token.
|
|
|
|
## Services
|
|
|
|
### Token Service (`services/token_service.py`)
|
|
Manages reads and writes to the `tokens_siswa.csv` file.
|
|
- `def _load_tokens_safely() -> Tuple[Dict[str, dict], List[str]]:` Reads CSV data safely.
|
|
- `def validate_token(token):` Returns `True` if the token exists.
|
|
- `def is_teacher_token(token):` Returns `True` if the token belongs to the first row (the teacher).
|
|
- `def get_student_progress(token):` Returns a dictionary of lesson progress for a specific token.
|
|
- `def update_student_progress(token, lesson_name, status="completed"):` Writes progress back to the CSV.
|
|
|
|
### Lesson Service (`services/lesson_service.py`)
|
|
Parses Markdown files to extract content and configuration.
|
|
- `def get_ordered_lessons_with_learning_objectives(progress=None):` Returns lessons ordered as they appear in `home.md`, optionally injected with user progress status.
|
|
- `def render_markdown_content(file_path):` The core parsing function. Uses regex to extract markers like `---INITIAL_CODE---`, `---VELXIO_CIRCUIT---`, etc. It identifies the `active_tabs` needed for the frontend.
|
|
- `def _parse_flashcards(text):` Specifically parses `---QUIZ_FLASHCARD---` blocks into a structured JSON array for the frontend MCQ/Flashcard component.
|
|
|
|
## Compiler Framework (`compiler/`)
|
|
|
|
The compilation logic is abstracted via a factory pattern.
|
|
|
|
- `class CompilerFactory:` (`compiler/__init__.py`)
|
|
- `def get_compiler(self, language):` Returns the appropriate `BaseCompiler` instance (e.g., `CCompiler` or `PythonCompiler`).
|
|
- `class BaseCompiler(ABC):` (`compiler/base_compiler.py`)
|
|
- `def compile(self, code, timeout=10):` Abstract method.
|
|
- `def run(self, file_path, timeout=5):` Abstract method.
|
|
- `class CCompiler(BaseCompiler):` and `class PythonCompiler(BaseCompiler):`
|
|
Implementation wrappers that construct payloads and send HTTP requests to the `compiler-worker` container (`http://compiler-worker:8080/execute`).
|