Initialize project with basic structure, including Docker configuration, backend and frontend setup, environment configuration, and essential files for development.
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / compose (push) Has been cancelled

This commit is contained in:
2026-07-19 00:17:31 +03:00
parent d401e9009c
commit 1239fcee08
69 changed files with 12391 additions and 10 deletions

View File

@@ -0,0 +1,108 @@
-- +mixmaker Up
CREATE TABLE IF NOT EXISTS schema_migrations (
version text PRIMARY KEY,
applied_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE accounts (
id text PRIMARY KEY,
discord_id text NOT NULL UNIQUE,
username text NOT NULL,
avatar_url text NOT NULL DEFAULT '',
role text NOT NULL CHECK (role IN ('admin', 'player')),
created_at timestamptz NOT NULL
);
CREATE TABLE players (
id text PRIMARY KEY,
account_id text NOT NULL UNIQUE REFERENCES accounts(id),
display_name text NOT NULL,
tank_rating smallint NOT NULL CHECK (tank_rating BETWEEN 1 AND 40),
damage_rating smallint NOT NULL CHECK (damage_rating BETWEEN 1 AND 40),
support_rating smallint NOT NULL CHECK (support_rating BETWEEN 1 AND 40),
preferred_roles jsonb NOT NULL DEFAULT '[]'::jsonb,
preferred_player_ids jsonb NOT NULL DEFAULT '[]'::jsonb,
created_at timestamptz NOT NULL,
updated_at timestamptz NOT NULL
);
CREATE TABLE sessions (
token_hash text PRIMARY KEY,
account_id text NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
expires_at timestamptz NOT NULL
);
CREATE INDEX sessions_expiry_idx ON sessions(expires_at);
CREATE TABLE events (
id text PRIMARY KEY,
name text NOT NULL,
description text NOT NULL DEFAULT '',
starts_at timestamptz NOT NULL,
ends_at timestamptz NOT NULL,
registration_deadline timestamptz NOT NULL,
created_by text NOT NULL REFERENCES accounts(id),
created_at timestamptz NOT NULL,
updated_at timestamptz NOT NULL,
CHECK (ends_at > starts_at),
CHECK (registration_deadline <= starts_at)
);
CREATE TABLE rsvps (
event_id text NOT NULL REFERENCES events(id) ON DELETE CASCADE,
player_id text NOT NULL REFERENCES players(id) ON DELETE CASCADE,
status text NOT NULL CHECK (status IN ('Going', 'Maybe', 'NotGoing')),
actor_account_id text NOT NULL REFERENCES accounts(id),
source text NOT NULL CHECK (source IN ('player', 'admin')),
updated_at timestamptz NOT NULL,
PRIMARY KEY(event_id, player_id)
);
CREATE TABLE teams (
id text PRIMARY KEY,
event_id text NOT NULL REFERENCES events(id) ON DELETE CASCADE,
name text NOT NULL,
captain_player_id text REFERENCES players(id),
slots jsonb NOT NULL
);
CREATE TABLE rulesets (
id text PRIMARY KEY,
name text NOT NULL,
body jsonb NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE series (
id text PRIMARY KEY,
tournament_id text NOT NULL DEFAULT '',
body jsonb NOT NULL,
version integer NOT NULL DEFAULT 0
);
CREATE TABLE tournaments (
id text PRIMARY KEY,
event_id text NOT NULL REFERENCES events(id) ON DELETE CASCADE,
body jsonb NOT NULL
);
CREATE TABLE draft_states (
id text PRIMARY KEY,
kind text NOT NULL CHECK (kind IN ('map', 'hero', 'coin')),
body jsonb NOT NULL,
version integer NOT NULL DEFAULT 0,
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE audit_log (
id bigserial PRIMARY KEY,
actor_account_id text NOT NULL REFERENCES accounts(id),
action text NOT NULL,
subject_id text NOT NULL,
payload jsonb NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX audit_subject_idx ON audit_log(subject_id, created_at);
-- +mixmaker Down
DROP TABLE IF EXISTS audit_log, draft_states, tournaments, series, rulesets, teams,
rsvps, events, sessions, players, accounts, schema_migrations CASCADE;

View File

@@ -0,0 +1,52 @@
-- +mixmaker Up
INSERT INTO rulesets (id, name, body)
VALUES
(
'standard-control-hybrid-control',
'Control → Hybrid → Control',
'{
"ID": "standard-control-hybrid-control",
"Name": "Control → Hybrid → Control",
"MapPools": [
["Antarctic Peninsula", "Busan", "Ilios", "Lijiang Tower", "Nepal", "Oasis", "Samoa"],
["Blizzard World", "Eichenwalde", "Hollywood", "King''s Row", "Midtown", "Numbani", "Paraíso"],
["Antarctic Peninsula", "Busan", "Ilios", "Lijiang Tower", "Nepal", "Oasis", "Samoa"]
],
"Heroes": [
{"name":"D.Va","role":"Tank"},{"name":"Doomfist","role":"Tank"},{"name":"Hazard","role":"Tank"},{"name":"Junker Queen","role":"Tank"},{"name":"Mauga","role":"Tank"},{"name":"Orisa","role":"Tank"},{"name":"Ramattra","role":"Tank"},{"name":"Reinhardt","role":"Tank"},{"name":"Roadhog","role":"Tank"},{"name":"Sigma","role":"Tank"},{"name":"Winston","role":"Tank"},{"name":"Wrecking Ball","role":"Tank"},{"name":"Zarya","role":"Tank"},
{"name":"Ashe","role":"Damage"},{"name":"Bastion","role":"Damage"},{"name":"Cassidy","role":"Damage"},{"name":"Echo","role":"Damage"},{"name":"Freja","role":"Damage"},{"name":"Genji","role":"Damage"},{"name":"Hanzo","role":"Damage"},{"name":"Junkrat","role":"Damage"},{"name":"Mei","role":"Damage"},{"name":"Pharah","role":"Damage"},{"name":"Reaper","role":"Damage"},{"name":"Sojourn","role":"Damage"},{"name":"Soldier: 76","role":"Damage"},{"name":"Sombra","role":"Damage"},{"name":"Symmetra","role":"Damage"},{"name":"Torbjörn","role":"Damage"},{"name":"Tracer","role":"Damage"},{"name":"Venture","role":"Damage"},{"name":"Widowmaker","role":"Damage"},
{"name":"Ana","role":"Support"},{"name":"Baptiste","role":"Support"},{"name":"Brigitte","role":"Support"},{"name":"Illari","role":"Support"},{"name":"Juno","role":"Support"},{"name":"Kiriko","role":"Support"},{"name":"Lifeweaver","role":"Support"},{"name":"Lúcio","role":"Support"},{"name":"Mercy","role":"Support"},{"name":"Moira","role":"Support"},{"name":"Zenyatta","role":"Support"}
],
"HeroBansPerTeam": 2,
"BestOf": 3,
"InitialMapBanner": 0,
"InitialHeroBanner": 1
}'::jsonb
)
ON CONFLICT (id) DO NOTHING;
INSERT INTO rulesets (id, name, body)
VALUES (
'variety-control-push-escort',
'Control → Push → Escort',
jsonb_set(
jsonb_set(
(SELECT body FROM rulesets WHERE id = 'standard-control-hybrid-control'),
'{ID}',
'"variety-control-push-escort"'
),
'{Name}',
'"Control → Push → Escort"'
) || '{
"MapPools": [
["Antarctic Peninsula", "Busan", "Ilios", "Lijiang Tower", "Nepal", "Oasis", "Samoa"],
["Colosseo", "Esperança", "New Queen Street", "Runasapi"],
["Circuit Royal", "Dorado", "Havana", "Junkertown", "Rialto", "Route 66", "Shambali Monastery", "Watchpoint: Gibraltar"]
]
}'::jsonb
)
ON CONFLICT (id) DO NOTHING;
-- +mixmaker Down
DELETE FROM rulesets
WHERE id IN ('standard-control-hybrid-control', 'variety-control-push-escort');

View File

@@ -0,0 +1,9 @@
-- +mixmaker Up
ALTER TABLE players
ADD COLUMN IF NOT EXISTS preferred_roles jsonb NOT NULL DEFAULT '[]'::jsonb,
ADD COLUMN IF NOT EXISTS preferred_player_ids jsonb NOT NULL DEFAULT '[]'::jsonb;
-- +mixmaker Down
ALTER TABLE players
DROP COLUMN IF EXISTS preferred_player_ids,
DROP COLUMN IF EXISTS preferred_roles;

View File

@@ -0,0 +1,22 @@
-- +mixmaker Up
UPDATE players
SET tank_rating = LEAST(GREATEST(tank_rating, 1), 40),
damage_rating = LEAST(GREATEST(damage_rating, 1), 40),
support_rating = LEAST(GREATEST(support_rating, 1), 40);
ALTER TABLE players
DROP CONSTRAINT IF EXISTS players_tank_rating_check,
DROP CONSTRAINT IF EXISTS players_damage_rating_check,
DROP CONSTRAINT IF EXISTS players_support_rating_check,
ADD CONSTRAINT players_tank_rating_check CHECK (tank_rating BETWEEN 1 AND 40),
ADD CONSTRAINT players_damage_rating_check CHECK (damage_rating BETWEEN 1 AND 40),
ADD CONSTRAINT players_support_rating_check CHECK (support_rating BETWEEN 1 AND 40);
-- +mixmaker Down
ALTER TABLE players
DROP CONSTRAINT IF EXISTS players_tank_rating_check,
DROP CONSTRAINT IF EXISTS players_damage_rating_check,
DROP CONSTRAINT IF EXISTS players_support_rating_check,
ADD CONSTRAINT players_tank_rating_check CHECK (tank_rating BETWEEN 1 AND 100),
ADD CONSTRAINT players_damage_rating_check CHECK (damage_rating BETWEEN 1 AND 100),
ADD CONSTRAINT players_support_rating_check CHECK (support_rating BETWEEN 1 AND 100);