diff --git a/docs/database.md b/docs/database.md new file mode 100644 index 0000000..7e01ae0 --- /dev/null +++ b/docs/database.md @@ -0,0 +1,82 @@ +# Database – Spillkveld + +## Overview + +The project uses PostgreSQL to store board game data. The database schema and seed data are defined in two SQL files: + +- `server/db/schema.sql` – creates the `games` table and its constraints. +- `server/db/seed.sql` – inserts the 12 example games from `src/data/games.ts`. + +The original game IDs and fields are preserved, including `icon` and `tone`. + +## Local setup + +PostgreSQL 17 was installed and tested locally on macOS using Homebrew. + +Install PostgreSQL: + +```bash +brew install postgresql@17 +``` + +Start the database service: + +```bash +brew services start postgresql@17 +``` + +Create a local database: + +```bash +/opt/homebrew/opt/postgresql@17/bin/createdb spillkveld +``` + +Run the following commands from the project root: + +```bash +/opt/homebrew/opt/postgresql@17/bin/psql -X -v ON_ERROR_STOP=1 -d spillkveld -f server/db/schema.sql +/opt/homebrew/opt/postgresql@17/bin/psql -X -v ON_ERROR_STOP=1 -d spillkveld -f server/db/seed.sql +``` + +The PostgreSQL executable path shown above is specific to this local Homebrew installation. On other systems, the commands may use `psql` directly. + +## Database structure + +The `games` table contains the following fields: + +| Column | Type | Constraint | +|---|---|---| +| id | TEXT | PRIMARY KEY | +| name | TEXT | NOT NULL | +| description | TEXT | NOT NULL | +| min_players | INTEGER | NOT NULL, >= 1 | +| max_players | INTEGER | NOT NULL, >= min_players | +| minutes | INTEGER | NOT NULL, > 0 | +| category | TEXT | NOT NULL | +| icon | TEXT | NOT NULL | +| tone | TEXT | NOT NULL | + +## Seed data + +The seed file contains 12 example games based on the existing prototype data in `src/data/games.ts`. + +It uses `ON CONFLICT (id) DO NOTHING` to prevent duplicate rows when executed multiple times. Existing rows are left unchanged. + +## Local testing + +The following tests were completed using PostgreSQL 17.11: + +1. **Schema creation:** Executing `schema.sql` returned `CREATE TABLE`. +2. **Seed insertion:** Executing `seed.sql` returned `INSERT 0 12`. +3. **Repeated seed execution:** Running `seed.sql` again returned `INSERT 0 0`, confirming that no duplicate rows were inserted. +4. **Row count:** `SELECT COUNT(*) FROM games;` returned 12. +5. **Constraint validation:** An attempt to insert a game with `min_players = 0` was rejected by the `games_min_players_check` constraint. +6. **Player range validation:** An attempt to insert a game with `min_players = 5` and `max_players = 2` was rejected by the `games_check` constraint, confirming that `max_players` cannot be lower than `min_players`. +7. **Game duration validation:** An attempt to insert a game with `minutes = 0` was rejected by the `games_minutes_check` constraint. +8. **NOT NULL validation:** An attempt to insert a game with `name = NULL` was rejected, confirming that the name field is required. + +The database schema and seed data were tested locally. Backend integration and deployment are handled separately. + +## AI usage + +ChatGPT was used to explain PostgreSQL setup, assist with drafting the SQL schema and seed file, and provide testing instructions. The SQL files were executed and their results verified locally. \ No newline at end of file diff --git a/server/db/schema.sql b/server/db/schema.sql new file mode 100644 index 0000000..5885594 --- /dev/null +++ b/server/db/schema.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS games ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + description TEXT NOT NULL, + min_players INTEGER NOT NULL CHECK (min_players >= 1), + max_players INTEGER NOT NULL CHECK (max_players >= min_players), + minutes INTEGER NOT NULL CHECK (minutes > 0), + category TEXT NOT NULL, + icon TEXT NOT NULL, + tone TEXT NOT NULL +); \ No newline at end of file diff --git a/server/db/seed.sql b/server/db/seed.sql new file mode 100644 index 0000000..91ee345 --- /dev/null +++ b/server/db/seed.sql @@ -0,0 +1,66 @@ + +-- Insert the 12 prototype games into the database. +-- Keep the original IDs so the frontend and backend can reference them. +-- ON CONFLICT prevents duplicate entries when the seed is run again. + +INSERT INTO games ( + id, + name, + description, + min_players, + max_players, + minutes, + category, + icon, + tone +) +VALUES + ('azul', 'Azul', + 'Legg fargerike fliser og bygg et mønster som gir flest poeng.', + 2, 4, 40, 'Strategi', '▦', 'blue'), + + ('codenames', 'Codenames', + 'Gi smarte ledetråder og finn lagets hemmelige ord.', + 2, 8, 20, 'Selskap', '✳', 'purple'), + + ('carcassonne', 'Carcassonne', + 'Bygg landskap med brikker og plasser følgere på byer og veier.', + 2, 5, 45, 'Strategi', '⌂', 'green'), + + ('dixit', 'Dixit', + 'Fortell en liten historie til et bilde og gjett hvilket kort som er riktig.', + 3, 6, 30, 'Kreativt', '✦', 'pink'), + + ('ticket-to-ride', 'Ticket to Ride', + 'Bygg togruter mellom byer og fullfør reisemålene dine.', + 2, 5, 60, 'Familie', '↗', 'orange'), + + ('pandemic', 'Pandemic', + 'Samarbeid om å stoppe utbrudd før tiden renner ut.', + 2, 4, 45, 'Samarbeid', '✚', 'teal'), + + ('splendor', 'Splendor', + 'Samle edelstener, kjøp kort og bygg en verdifull samling.', + 2, 4, 30, 'Strategi', '◆', 'purple'), + + ('just-one', 'Just One', + 'Skriv ett hint hver og hjelp en spiller å gjette ordet.', + 3, 7, 20, 'Samarbeid', '☝', 'yellow'), + + ('kingdomino', 'Kingdomino', + 'Velg dominobrikker og sett sammen ditt eget kongerike.', + 2, 4, 25, 'Familie', '♛', 'green'), + + ('7-wonders', '7 Wonders', + 'Bygg en sivilisasjon med kort og samle ressurser over tre epoker.', + 3, 7, 30, 'Strategi', '◭', 'orange'), + + ('the-crew', 'The Crew', + 'Løs oppdrag sammen ved å spille kort uten å si for mye.', + 3, 5, 20, 'Samarbeid', '✧', 'blue'), + + ('patchwork', 'Patchwork', + 'Sy sammen et lappeteppe ved å velge og plassere brikker.', + 2, 2, 30, 'Strategi', '▧', 'pink') + +ON CONFLICT (id) DO NOTHING;