43 lines
2.0 KiB
SQL
43 lines
2.0 KiB
SQL
-- EnakGame game catalog (docs/rfc-enakgame.md §5.1). games is extended rather than
|
|||
|
|
-- replaced, because the customer app already reads it.
|
||
|
|
|
||
|
|
ALTER TABLE games
|
||
|
|
ADD COLUMN organization_id UUID,
|
||
|
|
ADD COLUMN slug VARCHAR(100),
|
||
|
|
ADD COLUMN description TEXT,
|
||
|
|
ADD COLUMN thumbnail_url VARCHAR(500),
|
||
|
|
ADD COLUMN game_url VARCHAR(500),
|
||
|
|
ADD COLUMN version VARCHAR(50),
|
||
|
|
ADD COLUMN status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE'
|
||
|
|
CONSTRAINT chk_games_status CHECK (status IN ('DRAFT', 'ACTIVE', 'INACTIVE', 'ARCHIVED')),
|
||
|
|
ADD COLUMN entry_cost BIGINT,
|
||
|
|
ADD COLUMN session_ttl_seconds INT NOT NULL DEFAULT 600
|
||
|
|
CONSTRAINT chk_games_session_ttl_seconds CHECK (session_ttl_seconds > 0),
|
||
|
|
-- Limits the Result Validator checks a result against: max_score,
|
||
|
|
-- min_duration_seconds, max_score_per_second, the valid outcomes, and the game's
|
||
|
|
-- daily reward limit (§5.10, §7.2).
|
||
|
|
ADD COLUMN result_rules JSONB NOT NULL DEFAULT '{}';
|
||
|
|
|
||
|
|
-- The old games leave the product: archived, never deleted (§14). game_plays.game_id
|
||
|
|
-- is ON DELETE CASCADE, and the old GAME_SPEND ledger rows point at game_plays.
|
||
|
|
-- Their coin cost becomes the entry cost; one that is missing, not a whole number or
|
||
|
|
-- below 1 becomes 1, so the CHECK below holds.
|
||
|
|
UPDATE games SET
|
||
|
|
status = 'ARCHIVED',
|
||
|
|
is_active = FALSE,
|
||
|
|
entry_cost = CASE
|
||
|
|
WHEN metadata->>'coin_cost' ~ '^[0-9]{1,18}$' THEN GREATEST((metadata->>'coin_cost')::BIGINT, 1)
|
||
|
|
ELSE 1 END;
|
||
|
|
|
||
|
|
ALTER TABLE games
|
||
|
|
ALTER COLUMN entry_cost SET NOT NULL,
|
||
|
|
-- PRD §10.1: no game is free.
|
||
|
|
ADD CONSTRAINT chk_games_entry_cost CHECK (entry_cost >= 1),
|
||
|
|
-- Every EnakGame game has an organization and a slug. Only the archived old games
|
||
|
|
-- may lack them.
|
||
|
|
ADD CONSTRAINT chk_games_enakgame_identity CHECK (
|
||
|
|
status = 'ARCHIVED' OR (organization_id IS NOT NULL AND slug IS NOT NULL));
|
||
|
|
|
||
|
|
CREATE UNIQUE INDEX uq_games_org_slug ON games(organization_id, slug) WHERE slug IS NOT NULL;
|
||
|
|
CREATE INDEX idx_games_org_status ON games(organization_id, status);
|