Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions docs/database.md
Original file line number Diff line number Diff line change
@@ -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.
11 changes: 11 additions & 0 deletions server/db/schema.sql
Original file line number Diff line number Diff line change
@@ -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
);
66 changes: 66 additions & 0 deletions server/db/seed.sql
Original file line number Diff line number Diff line change
@@ -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;