formatting
This commit is contained in:
parent
b3b32167c9
commit
2bcf9d7a97
7 changed files with 25 additions and 21 deletions
|
|
@ -19,7 +19,7 @@ Stack: Express API, React frontend, Drizzle ORM, Postgres, Valkey, WebSockets.
|
|||
|
||||
The core mental model established for the entire API:
|
||||
|
||||
```
|
||||
```text
|
||||
HTTP Request
|
||||
↓
|
||||
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
|
||||
difficulty ratings:
|
||||
|
||||
```
|
||||
```text
|
||||
Raw source files
|
||||
↓
|
||||
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)
|
||||
|
||||
```
|
||||
```text
|
||||
QuizQuestion — prompt, optional gloss, 4 options (no correct answer)
|
||||
QuizOption — optionId + text
|
||||
AnswerSubmission — questionId + selectedOptionId
|
||||
|
|
@ -182,7 +182,7 @@ AnswerResult — correct boolean, correctOptionId, selectedOptionId
|
|||
|
||||
## API Endpoints
|
||||
|
||||
```
|
||||
```text
|
||||
POST /api/v1/game/start GameRequest → QuizQuestion[]
|
||||
POST /api/v1/game/answer AnswerSubmission → AnswerResult
|
||||
```
|
||||
|
|
@ -191,7 +191,7 @@ POST /api/v1/game/answer AnswerSubmission → AnswerResult
|
|||
|
||||
## Current File Structure (apps/api)
|
||||
|
||||
```
|
||||
```text
|
||||
apps/api/src/
|
||||
├── app.ts — Express app, express.json() middleware
|
||||
├── server.ts — starts server on PORT
|
||||
|
|
@ -209,7 +209,7 @@ apps/api/src/
|
|||
|
||||
## Current File Structure (packages/db)
|
||||
|
||||
```
|
||||
```text
|
||||
packages/db/src/
|
||||
├── db/
|
||||
│ └── schema.ts — Drizzle schema (terms, translations, users, decks...)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ Each synset extracted from WordNet is represented as:
|
|||
|
||||
## 2. Database Schema (relevant tables)
|
||||
|
||||
```
|
||||
```text
|
||||
terms
|
||||
id uuid PK
|
||||
synset_id text UNIQUE
|
||||
|
|
@ -179,7 +179,7 @@ When `onConflictDoNothing` skips a `terms` insert, the in-memory UUID is never w
|
|||
|
||||
Correct format:
|
||||
|
||||
```
|
||||
```text
|
||||
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:
|
||||
|
||||
```
|
||||
```text
|
||||
scripts/datafiles/
|
||||
en-it-nouns.json
|
||||
en-fr-nouns.json
|
||||
|
|
|
|||
|
|
@ -428,6 +428,8 @@ Phase 0 complete. Phase 1 data pipeline complete. Phase 2 data model finalized a
|
|||
|
||||
### 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
|
||||
4. **Decide SUBTLEX → `cefr_level` mapping strategy** — raw frequency ranks need a mapping to A1–C2 bands before tiered decks are meaningful
|
||||
5. **Generate decks** — run generation script with SUBTLEX-grounded wordlists per source language
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
```
|
||||
```text
|
||||
vocab-trainer/
|
||||
├── apps/
|
||||
│ ├── api/
|
||||
|
|
@ -133,7 +133,7 @@ vocab-trainer/
|
|||
|
||||
## 5. Data Model (relevant tables for MVP)
|
||||
|
||||
```
|
||||
```javascript
|
||||
export const terms = pgTable(
|
||||
"terms",
|
||||
{
|
||||
|
|
@ -242,7 +242,7 @@ The `QuizService` picks 3 distractors server-side:
|
|||
|
||||
## 7. Frontend Structure (MVP)
|
||||
|
||||
```
|
||||
```text
|
||||
apps/web/src/
|
||||
├── routes/
|
||||
│ ├── index.tsx # Landing page / mode select
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
- pinning dependencies in package.json files
|
||||
- rethink organisation of datafiles and wordlists
|
||||
|
||||
## notes
|
||||
## tipps
|
||||
|
||||
- backend advice: https://github.com/MohdOwaisShah/backend
|
||||
- backend advice: [backend](https://github.com/MohdOwaisShah/backend)
|
||||
- openapi
|
||||
- bruno for api testing
|
||||
- tailscale
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ Phase 0 (Foundation)
|
|||
|
||||
## 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:
|
||||
main menu => singleplayer, multiplayer, settings
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ Turborepo adds parallel task running and build caching on top of pnpm workspaces
|
|||
|
||||
## 3. Repository Structure
|
||||
|
||||
```
|
||||
```tree
|
||||
vocab-trainer/
|
||||
├── apps/
|
||||
│ ├── web/ # React SPA (Vite + TanStack Router)
|
||||
|
|
@ -86,7 +86,7 @@ vocab-trainer/
|
|||
|
||||
`pnpm-workspace.yaml` declares:
|
||||
|
||||
```
|
||||
```yaml
|
||||
packages:
|
||||
- 'apps/*'
|
||||
- 'packages/*'
|
||||
|
|
@ -107,7 +107,7 @@ For parallel dev, use `concurrently` or just two terminal tabs for MVP.
|
|||
|
||||
## 4. Architecture — N-Tier / Layered
|
||||
|
||||
```
|
||||
```text
|
||||
┌────────────────────────────────────┐
|
||||
│ 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 |
|
||||
| `acme-companion` | Let's Encrypt certificate automation |
|
||||
|
||||
```
|
||||
```docker
|
||||
nginx-proxy (:80/:443)
|
||||
app.domain → web:80
|
||||
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.
|
||||
|
||||
Key Format: `room:{code}:{field}`
|
||||
|
||||
| Key | Type | TTL | Description |
|
||||
|
||||
|------------------------------|---------|-------|-------------|
|
||||
| `room:{code}:state` | Hash | 1h | Current question index, round status |
|
||||
| `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
|
||||
|
||||
```
|
||||
```text
|
||||
host creates room (REST) →
|
||||
players join via room code (REST + WS room:join) →
|
||||
room:state broadcasts player list →
|
||||
|
|
@ -423,7 +425,7 @@ Active room state (connected players, current question, answers received this ro
|
|||
|
||||
## 12. Frontend Structure
|
||||
|
||||
```
|
||||
```tree
|
||||
apps/web/src/
|
||||
├── routes/
|
||||
│ ├── index.tsx # Landing / mode select
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue