formatting

This commit is contained in:
lila 2026-04-10 20:20:09 +02:00
parent b3b32167c9
commit 2bcf9d7a97
7 changed files with 25 additions and 21 deletions

View file

@ -19,7 +19,7 @@ Stack: Express API, React frontend, Drizzle ORM, Postgres, Valkey, WebSockets.
The core mental model established for the entire API: The core mental model established for the entire API:
``` ```text
HTTP Request HTTP Request
Router — maps URL + HTTP method to a controller Router — maps URL + HTTP method to a controller
@ -126,7 +126,7 @@ touches the database. A service never reads `req.body`. A model never knows what
A staged ETL pipeline was built to enrich translation records with CEFR levels and A staged ETL pipeline was built to enrich translation records with CEFR levels and
difficulty ratings: difficulty ratings:
``` ```text
Raw source files Raw source files
extract-*.py — normalise each source to standard JSON extract-*.py — normalise each source to standard JSON
@ -171,7 +171,7 @@ as a potential constraint for the distractor algorithm at high difficulty.
### Planned schemas (not yet implemented) ### Planned schemas (not yet implemented)
``` ```text
QuizQuestion — prompt, optional gloss, 4 options (no correct answer) QuizQuestion — prompt, optional gloss, 4 options (no correct answer)
QuizOption — optionId + text QuizOption — optionId + text
AnswerSubmission — questionId + selectedOptionId AnswerSubmission — questionId + selectedOptionId
@ -182,7 +182,7 @@ AnswerResult — correct boolean, correctOptionId, selectedOptionId
## API Endpoints ## API Endpoints
``` ```text
POST /api/v1/game/start GameRequest → QuizQuestion[] POST /api/v1/game/start GameRequest → QuizQuestion[]
POST /api/v1/game/answer AnswerSubmission → AnswerResult POST /api/v1/game/answer AnswerSubmission → AnswerResult
``` ```
@ -191,7 +191,7 @@ POST /api/v1/game/answer AnswerSubmission → AnswerResult
## Current File Structure (apps/api) ## Current File Structure (apps/api)
``` ```text
apps/api/src/ apps/api/src/
├── app.ts — Express app, express.json() middleware ├── app.ts — Express app, express.json() middleware
├── server.ts — starts server on PORT ├── server.ts — starts server on PORT
@ -209,7 +209,7 @@ apps/api/src/
## Current File Structure (packages/db) ## Current File Structure (packages/db)
``` ```text
packages/db/src/ packages/db/src/
├── db/ ├── db/
│ └── schema.ts — Drizzle schema (terms, translations, users, decks...) │ └── schema.ts — Drizzle schema (terms, translations, users, decks...)

View file

@ -30,7 +30,7 @@ Each synset extracted from WordNet is represented as:
## 2. Database Schema (relevant tables) ## 2. Database Schema (relevant tables)
``` ```text
terms terms
id uuid PK id uuid PK
synset_id text UNIQUE synset_id text UNIQUE
@ -179,7 +179,7 @@ When `onConflictDoNothing` skips a `terms` insert, the in-memory UUID is never w
Correct format: Correct format:
``` ```text
DATABASE_URL=postgresql://glossa:glossa@localhost:5432/glossa DATABASE_URL=postgresql://glossa:glossa@localhost:5432/glossa
``` ```
@ -220,7 +220,7 @@ The truncate approach is fine for dev but unsuitable for production — it wipes
One JSON file per language pair per POS: One JSON file per language pair per POS:
``` ```text
scripts/datafiles/ scripts/datafiles/
en-it-nouns.json en-it-nouns.json
en-fr-nouns.json en-fr-nouns.json

View file

@ -428,6 +428,8 @@ Phase 0 complete. Phase 1 data pipeline complete. Phase 2 data model finalized a
### Next (Phase 3 — data pipeline + API) ### Next (Phase 3 — data pipeline + API)
1. done
2. done
3. **Expand data pipeline** — import all OMW languages and POS, not just English nouns with Italian translations 3. **Expand data pipeline** — import all OMW languages and POS, not just English nouns with Italian translations
4. **Decide SUBTLEX → `cefr_level` mapping strategy** — raw frequency ranks need a mapping to A1C2 bands before tiered decks are meaningful 4. **Decide SUBTLEX → `cefr_level` mapping strategy** — raw frequency ranks need a mapping to A1C2 bands before tiered decks are meaningful
5. **Generate decks** — run generation script with SUBTLEX-grounded wordlists per source language 5. **Generate decks** — run generation script with SUBTLEX-grounded wordlists per source language

View file

@ -77,7 +77,7 @@ The monorepo structure and tooling are already set up (Phase 0 complete). This i
### Repository Structure (actual, as of Phase 1 data pipeline complete) ### Repository Structure (actual, as of Phase 1 data pipeline complete)
``` ```text
vocab-trainer/ vocab-trainer/
├── apps/ ├── apps/
│ ├── api/ │ ├── api/
@ -133,7 +133,7 @@ vocab-trainer/
## 5. Data Model (relevant tables for MVP) ## 5. Data Model (relevant tables for MVP)
``` ```javascript
export const terms = pgTable( export const terms = pgTable(
"terms", "terms",
{ {
@ -242,7 +242,7 @@ The `QuizService` picks 3 distractors server-side:
## 7. Frontend Structure (MVP) ## 7. Frontend Structure (MVP)
``` ```text
apps/web/src/ apps/web/src/
├── routes/ ├── routes/
│ ├── index.tsx # Landing page / mode select │ ├── index.tsx # Landing page / mode select

View file

@ -5,9 +5,9 @@
- pinning dependencies in package.json files - pinning dependencies in package.json files
- rethink organisation of datafiles and wordlists - rethink organisation of datafiles and wordlists
## notes ## tipps
- backend advice: https://github.com/MohdOwaisShah/backend - backend advice: [backend](https://github.com/MohdOwaisShah/backend)
- openapi - openapi
- bruno for api testing - bruno for api testing
- tailscale - tailscale

View file

@ -152,7 +152,7 @@ Phase 0 (Foundation)
## ui sketch ## ui sketch
i was sketching the ui of the menu and came up with some questions.  i was sketching the ui of the menu and came up with some questions.
this would be the flow to start a single player game: this would be the flow to start a single player game:
main menu => singleplayer, multiplayer, settings main menu => singleplayer, multiplayer, settings

View file

@ -50,7 +50,7 @@ Turborepo adds parallel task running and build caching on top of pnpm workspaces
## 3. Repository Structure ## 3. Repository Structure
``` ```tree
vocab-trainer/ vocab-trainer/
├── apps/ ├── apps/
│ ├── web/ # React SPA (Vite + TanStack Router) │ ├── web/ # React SPA (Vite + TanStack Router)
@ -86,7 +86,7 @@ vocab-trainer/
`pnpm-workspace.yaml` declares: `pnpm-workspace.yaml` declares:
``` ```yaml
packages: packages:
- 'apps/*' - 'apps/*'
- 'packages/*' - 'packages/*'
@ -107,7 +107,7 @@ For parallel dev, use `concurrently` or just two terminal tabs for MVP.
## 4. Architecture — N-Tier / Layered ## 4. Architecture — N-Tier / Layered
``` ```text
┌────────────────────────────────────┐ ┌────────────────────────────────────┐
│ Presentation (React SPA) │ apps/web │ Presentation (React SPA) │ apps/web
├────────────────────────────────────┤ ├────────────────────────────────────┤
@ -148,7 +148,7 @@ Each layer only communicates with the layer directly below it. Business logic li
| `nginx-proxy` | Automatic reverse proxy | | `nginx-proxy` | Automatic reverse proxy |
| `acme-companion` | Let's Encrypt certificate automation | | `acme-companion` | Let's Encrypt certificate automation |
``` ```docker
nginx-proxy (:80/:443) nginx-proxy (:80/:443)
app.domain → web:80 app.domain → web:80
api.domain → api:3000 (HTTP + WS upgrade) api.domain → api:3000 (HTTP + WS upgrade)
@ -163,7 +163,9 @@ Ephemeral room state is stored in Valkey with TTL (e.g., 1 hour).
PostgreSQL stores durable history only. PostgreSQL stores durable history only.
Key Format: `room:{code}:{field}` Key Format: `room:{code}:{field}`
| Key | Type | TTL | Description | | Key | Type | TTL | Description |
|------------------------------|---------|-------|-------------| |------------------------------|---------|-------|-------------|
| `room:{code}:state` | Hash | 1h | Current question index, round status | | `room:{code}:state` | Hash | 1h | Current question index, round status |
| `room:{code}:players` | Set | 1h | List of connected user IDs | | `room:{code}:players` | Set | 1h | List of connected user IDs |
@ -392,7 +394,7 @@ All players see the same question at the same time. Everyone submits independent
### Game flow ### Game flow
``` ```text
host creates room (REST) → host creates room (REST) →
players join via room code (REST + WS room:join) → players join via room code (REST + WS room:join) →
room:state broadcasts player list → room:state broadcasts player list →
@ -423,7 +425,7 @@ Active room state (connected players, current question, answers received this ro
## 12. Frontend Structure ## 12. Frontend Structure
``` ```tree
apps/web/src/ apps/web/src/
├── routes/ ├── routes/
│ ├── index.tsx # Landing / mode select │ ├── index.tsx # Landing / mode select