diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index c3dbe7df2..98341af35 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -81,7 +81,6 @@ jobs: ./www/ ./savedata/ ./bin/ - ./bundled-schema/ retention-days: 7 - name: Build Windows-amd64 @@ -97,7 +96,6 @@ jobs: ./www/ ./savedata/ ./bin/ - ./bundled-schema/ retention-days: 7 lint: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 703cab6da..ba8602508 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,9 +45,7 @@ jobs: cp config.example.json staging/ cp -r www/ staging/www/ cp -r savedata/ staging/savedata/ - cp -r schemas/ staging/schemas/ - # Create a standalone SCHEMA.sql from init schema for convenience - cp schemas/init.sql staging/SCHEMA.sql + # Schema is now embedded in the binary via server/migrations/ cd staging && zip -r ../erupe-${{ matrix.os_name }}.zip . - name: Upload build artifact @@ -70,8 +68,8 @@ jobs: with: path: artifacts - - name: Copy SCHEMA.sql for standalone download - run: cp schemas/init.sql SCHEMA.sql + - name: Copy standalone schema for download + run: cp server/migrations/sql/0001_init.sql SCHEMA.sql - name: Create GitHub Release uses: softprops/action-gh-release@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index ab85d3d87..30d4048d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Embedded auto-migrating database schema system (`server/migrations/`): the server binary now contains all SQL schemas and runs migrations automatically on startup — no more `pg_restore`, manual patch ordering, or external `schemas/` directory needed - Setup wizard: web-based first-run configuration at `http://localhost:8080` when `config.json` is missing — guides users through database connection, schema initialization, and server settings - CI: Coverage threshold enforcement — fails build if total coverage drops below 50% - CI: Release workflow that automatically builds and uploads Linux/Windows binaries to GitHub Releases on tag push @@ -25,6 +26,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Schema management consolidated: replaced 4 independent code paths (Docker shell script, setup wizard, test helpers, manual psql) with a single embedded migration runner +- Setup wizard simplified: 3 schema checkboxes replaced with single "Apply database schema" checkbox +- Docker simplified: removed schema volume mounts and init script — the server binary handles everything +- Test helpers simplified: `ApplyTestSchema` now uses the migration runner instead of `pg_restore` + manual patch application - Updated minimum Go version requirement from 1.23 to 1.25 - Improved config handling - Refactored logout flow to save all data before cleanup (prevents data loss race conditions) diff --git a/Dockerfile b/Dockerfile index 59424bc2b..d36099f76 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,6 @@ RUN adduser -D -h /app erupe WORKDIR /app COPY --from=builder /build/erupe-ce . -COPY --from=builder /build/schemas/ ./schemas/ # www/ and bin/ are mounted at runtime if needed diff --git a/README.md b/README.md index 1b1c4864a..6f4d3273f 100644 --- a/README.md +++ b/README.md @@ -51,27 +51,21 @@ Docker handles the database automatically. You only need to provide quest files 2. Set up PostgreSQL and create a database: ```bash - wget https://github.com/Mezeporta/Erupe/releases/latest/download/SCHEMA.sql - psql -U postgres -d erupe -f SCHEMA.sql + createdb -U postgres erupe ``` -3. Apply any patch schemas from [schemas/patch-schema/](./schemas/patch-schema/) in numerical order: + The server will automatically apply all schema migrations on first startup. - ```bash - psql -U postgres -d erupe -f schemas/patch-schema/01-example-patch.sql - # Repeat for each patch file - ``` - -4. Copy and edit the config: +3. Copy and edit the config: ```bash cp config.example.json config.json # Edit config.json with your database credentials ``` -5. Download [quest/scenario files](#quest--scenario-files) and extract them to `bin/` +4. Download [quest/scenario files](#quest--scenario-files) and extract them to `bin/` -6. Run: `./erupe-ce` +5. Run: `./erupe-ce` ### Option C: From Source @@ -124,7 +118,7 @@ go mod tidy go build -o erupe-ce ``` -**Check for new patch schemas** in [schemas/patch-schema/](./schemas/patch-schema/) after pulling — apply any you haven't run yet, in numerical order. +Database schema migrations are applied automatically when the server starts — no manual SQL steps needed. ### Docker @@ -135,8 +129,6 @@ docker compose build docker compose up ``` -Apply any new patch schemas via pgAdmin or `psql` into the running container. - ## Configuration Edit `config.json` before starting the server. The essential settings are: @@ -210,7 +202,7 @@ Erupe uses a structured schema system: - **Initialization Schema**: Bootstraps database to version 9.1.0 - **Update Schemas**: Production-ready updates for new releases - **Patch Schemas**: Development updates (subject to change) -- **Bundled Schemas**: Demo templates for shops, distributions, events, and gacha in [schemas/bundled-schema/](./schemas/bundled-schema/) +- **Seed Data**: Demo templates for shops, distributions, events, and gacha in [server/migrations/seed/](./server/migrations/seed/) **Note**: Only use patch schemas if you're following active development. They get consolidated into update schemas on release. diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 96578f738..0c6e27fc0 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -14,8 +14,6 @@ services: - "5432:5432" volumes: - ./db-data/:/var/lib/postgresql/ - - ../schemas/:/schemas/ - - ./init/setup.sh:/docker-entrypoint-initdb.d/setup.sh healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s diff --git a/docker/init/setup.sh b/docker/init/setup.sh deleted file mode 100644 index 02e9b9709..000000000 --- a/docker/init/setup.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -set -e - -echo "INIT: Restoring database schema..." -pg_restore --username="$POSTGRES_USER" --dbname="$POSTGRES_DB" --no-owner --no-acl --verbose /schemas/init.sql || { - echo "WARN: pg_restore exited with errors (this is expected if the database already has objects)" -} - -echo "Updating!" -for file in /schemas/update-schema/*; do - echo " Applying $file" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -1 -f "$file" -done - -echo "Patching!" -for file in /schemas/patch-schema/*; do - [ -f "$file" ] || continue - echo " Applying $file" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -1 -f "$file" -done - -echo "Loading bundled data (shops, events, gacha)..." -for file in /schemas/bundled-schema/*; do - [ -f "$file" ] || continue - echo " Applying $file" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -1 -f "$file" -done \ No newline at end of file diff --git a/main.go b/main.go index 6aa495607..a88ee3dfa 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ import ( "erupe-ce/server/channelserver" "erupe-ce/server/discordbot" "erupe-ce/server/entranceserver" + "erupe-ce/server/migrations" "erupe-ce/server/setup" "erupe-ce/server/signserver" "strings" @@ -154,6 +155,16 @@ func main() { logger.Info("Database: Started successfully") + // Run database migrations + applied, migErr := migrations.Migrate(db, logger.Named("migrations")) + if migErr != nil { + preventClose(config, fmt.Sprintf("Database migration failed: %s", migErr.Error())) + } + if applied > 0 { + ver, _ := migrations.Version(db) + logger.Info(fmt.Sprintf("Database: Applied %d migration(s), now at version %d", applied, ver)) + } + // Pre-compute all server IDs this instance will own, so we only // delete our own rows (safe for multi-instance on the same DB). var ownedServerIDs []string diff --git a/schemas/init.sql b/schemas/init.sql deleted file mode 100644 index 3ae0ca127..000000000 Binary files a/schemas/init.sql and /dev/null differ diff --git a/schemas/patch-schema/.gitkeep b/schemas/patch-schema/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/schemas/patch-schema/00-psn-id.sql b/schemas/patch-schema/00-psn-id.sql deleted file mode 100644 index 4054767fb..000000000 --- a/schemas/patch-schema/00-psn-id.sql +++ /dev/null @@ -1,13 +0,0 @@ -BEGIN; - -ALTER TABLE users ADD COLUMN IF NOT EXISTS psn_id TEXT; - -ALTER TABLE public.sign_sessions ADD COLUMN id SERIAL; - -ALTER TABLE public.sign_sessions ADD CONSTRAINT sign_sessions_pkey PRIMARY KEY (id); - -ALTER TABLE public.sign_sessions ALTER COLUMN user_id DROP NOT NULL; - -ALTER TABLE public.sign_sessions ADD COLUMN psn_id TEXT; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/01-wiiu-key.sql b/schemas/patch-schema/01-wiiu-key.sql deleted file mode 100644 index 2dfe06203..000000000 --- a/schemas/patch-schema/01-wiiu-key.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE public.users ADD COLUMN IF NOT EXISTS wiiu_key TEXT; - -END; diff --git a/schemas/patch-schema/02-tower.sql b/schemas/patch-schema/02-tower.sql deleted file mode 100644 index 732f46c5e..000000000 --- a/schemas/patch-schema/02-tower.sql +++ /dev/null @@ -1,29 +0,0 @@ -BEGIN; - -CREATE TABLE IF NOT EXISTS tower ( - char_id INT, - tr INT, - trp INT, - tsp INT, - block1 INT, - block2 INT, - skills TEXT, - gems TEXT -); - -ALTER TABLE IF EXISTS guild_characters - ADD COLUMN IF NOT EXISTS tower_mission_1 INT; - -ALTER TABLE IF EXISTS guild_characters - ADD COLUMN IF NOT EXISTS tower_mission_2 INT; - -ALTER TABLE IF EXISTS guild_characters - ADD COLUMN IF NOT EXISTS tower_mission_3 INT; - -ALTER TABLE IF EXISTS guilds - ADD COLUMN IF NOT EXISTS tower_mission_page INT DEFAULT 1; - -ALTER TABLE IF EXISTS guilds - ADD COLUMN IF NOT EXISTS tower_rp INT DEFAULT 0; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/03-event_quests.sql b/schemas/patch-schema/03-event_quests.sql deleted file mode 100644 index 1374a3d08..000000000 --- a/schemas/patch-schema/03-event_quests.sql +++ /dev/null @@ -1,14 +0,0 @@ -BEGIN; - -create table if not exists event_quests -( - id serial primary key, - max_players integer, - quest_type integer not null, - quest_id integer not null, - mark integer -); - -ALTER TABLE IF EXISTS public.servers DROP COLUMN IF EXISTS season; - -END; diff --git a/schemas/patch-schema/04-trend-weapons.sql b/schemas/patch-schema/04-trend-weapons.sql deleted file mode 100644 index 15a7b86c4..000000000 --- a/schemas/patch-schema/04-trend-weapons.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE TABLE public.trend_weapons -( - weapon_id integer NOT NULL, - weapon_type integer NOT NULL, - count integer DEFAULT 0, - PRIMARY KEY (weapon_id) -); \ No newline at end of file diff --git a/schemas/patch-schema/05-gacha-roll-name.sql b/schemas/patch-schema/05-gacha-roll-name.sql deleted file mode 100644 index ee4b11269..000000000 --- a/schemas/patch-schema/05-gacha-roll-name.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE IF EXISTS public.gacha_entries - ADD COLUMN name text; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/06-goocoo-rename.sql b/schemas/patch-schema/06-goocoo-rename.sql deleted file mode 100644 index e72585ab3..000000000 --- a/schemas/patch-schema/06-goocoo-rename.sql +++ /dev/null @@ -1,11 +0,0 @@ -BEGIN; - -ALTER TABLE gook RENAME TO goocoo; - -ALTER TABLE goocoo RENAME COLUMN gook0 TO goocoo0; -ALTER TABLE goocoo RENAME COLUMN gook1 TO goocoo1; -ALTER TABLE goocoo RENAME COLUMN gook2 TO goocoo2; -ALTER TABLE goocoo RENAME COLUMN gook3 TO goocoo3; -ALTER TABLE goocoo RENAME COLUMN gook4 TO goocoo4; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/07-scenarios-counter.sql b/schemas/patch-schema/07-scenarios-counter.sql deleted file mode 100644 index 3ea2c65b2..000000000 --- a/schemas/patch-schema/07-scenarios-counter.sql +++ /dev/null @@ -1,9 +0,0 @@ -BEGIN; - -CREATE TABLE IF NOT EXISTS scenario_counter ( - id serial primary key, - scenario_id numeric not null, - category_id numeric not null -); - -END; \ No newline at end of file diff --git a/schemas/patch-schema/08-kill-counts.sql b/schemas/patch-schema/08-kill-counts.sql deleted file mode 100644 index 1c170cedd..000000000 --- a/schemas/patch-schema/08-kill-counts.sql +++ /dev/null @@ -1,12 +0,0 @@ -CREATE TABLE public.kill_logs -( - id serial, - character_id integer NOT NULL, - monster integer NOT NULL, - quantity integer NOT NULL, - timestamp timestamp with time zone NOT NULL, - PRIMARY KEY (id) -); - -ALTER TABLE IF EXISTS public.guild_characters - ADD COLUMN box_claimed timestamp with time zone DEFAULT now(); \ No newline at end of file diff --git a/schemas/patch-schema/09-fix-guild-treasure.sql b/schemas/patch-schema/09-fix-guild-treasure.sql deleted file mode 100644 index 1c022292f..000000000 --- a/schemas/patch-schema/09-fix-guild-treasure.sql +++ /dev/null @@ -1,26 +0,0 @@ -BEGIN; - -ALTER TABLE IF EXISTS public.guild_hunts DROP COLUMN IF EXISTS hunters; - -ALTER TABLE IF EXISTS public.guild_characters - ADD COLUMN treasure_hunt integer; - -ALTER TABLE IF EXISTS public.guild_hunts - ADD COLUMN start timestamp with time zone NOT NULL DEFAULT now(); - -UPDATE guild_hunts SET start=to_timestamp(return); - -ALTER TABLE IF EXISTS public.guild_hunts DROP COLUMN IF EXISTS "return"; - -ALTER TABLE IF EXISTS public.guild_hunts - RENAME claimed TO collected; - -CREATE TABLE public.guild_hunts_claimed -( - hunt_id integer NOT NULL, - character_id integer NOT NULL -); - -ALTER TABLE IF EXISTS public.guild_hunts DROP COLUMN IF EXISTS treasure; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/10-rework-distributions.sql b/schemas/patch-schema/10-rework-distributions.sql deleted file mode 100644 index 7945de343..000000000 --- a/schemas/patch-schema/10-rework-distributions.sql +++ /dev/null @@ -1,36 +0,0 @@ -BEGIN; - --- This will delete all of your old distribution data! ---ALTER TABLE IF EXISTS public.distribution DROP COLUMN IF EXISTS data; - -CREATE TABLE public.distribution_items -( - id serial PRIMARY KEY, - distribution_id integer NOT NULL, - item_type integer NOT NULL, - item_id integer, - quantity integer -); - -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_hr DROP DEFAULT; -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_hr DROP DEFAULT; -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_sr DROP DEFAULT; -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_sr DROP DEFAULT; -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_gr DROP DEFAULT; -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_gr DROP DEFAULT; - -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_hr DROP NOT NULL; -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_hr DROP NOT NULL; -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_sr DROP NOT NULL; -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_sr DROP NOT NULL; -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_gr DROP NOT NULL; -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_gr DROP NOT NULL; - -UPDATE distribution SET min_hr=NULL WHERE min_hr=65535; -UPDATE distribution SET max_hr=NULL WHERE max_hr=65535; -UPDATE distribution SET min_sr=NULL WHERE min_sr=65535; -UPDATE distribution SET max_sr=NULL WHERE max_sr=65535; -UPDATE distribution SET min_gr=NULL WHERE min_gr=65535; -UPDATE distribution SET max_gr=NULL WHERE max_gr=65535; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/11-event-quest-flags.sql b/schemas/patch-schema/11-event-quest-flags.sql deleted file mode 100644 index 5f88d732d..000000000 --- a/schemas/patch-schema/11-event-quest-flags.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS flags integer; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/12-event_quest_cycling.sql b/schemas/patch-schema/12-event_quest_cycling.sql deleted file mode 100644 index 8760bdab4..000000000 --- a/schemas/patch-schema/12-event_quest_cycling.sql +++ /dev/null @@ -1,10 +0,0 @@ -BEGIN; - -ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS start_time timestamp with time zone NOT NULL DEFAULT now(); -ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS active_duration int; -ALTER TABLE IF EXISTS public.event_quests ADD COLUMN IF NOT EXISTS inactive_duration int; -UPDATE public.event_quests SET active_duration=NULL, inactive_duration=NULL; -ALTER TABLE IF EXISTS public.event_quests RENAME active_duration TO active_days; -ALTER TABLE IF EXISTS public.event_quests RENAME inactive_duration TO inactive_days; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/13-festa-trial-votes.sql b/schemas/patch-schema/13-festa-trial-votes.sql deleted file mode 100644 index d9e3d0290..000000000 --- a/schemas/patch-schema/13-festa-trial-votes.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE IF EXISTS public.guild_characters ADD COLUMN trial_vote integer; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/14-fix-fpoint-trades.sql b/schemas/patch-schema/14-fix-fpoint-trades.sql deleted file mode 100644 index 1477560ad..000000000 --- a/schemas/patch-schema/14-fix-fpoint-trades.sql +++ /dev/null @@ -1,20 +0,0 @@ -DO $$ BEGIN - -- Only apply if the new-schema columns exist (item_type vs legacy itemtype) - IF EXISTS ( - SELECT 1 FROM information_schema.columns - WHERE table_name='fpoint_items' AND column_name='item_type' - ) THEN - DELETE FROM public.fpoint_items; - ALTER TABLE public.fpoint_items ALTER COLUMN item_type SET NOT NULL; - ALTER TABLE public.fpoint_items ALTER COLUMN item_id SET NOT NULL; - ALTER TABLE public.fpoint_items ALTER COLUMN quantity SET NOT NULL; - ALTER TABLE public.fpoint_items ALTER COLUMN fpoints SET NOT NULL; - ALTER TABLE public.fpoint_items DROP COLUMN IF EXISTS trade_type; - IF NOT EXISTS ( - SELECT 1 FROM information_schema.columns - WHERE table_name='fpoint_items' AND column_name='buyable' - ) THEN - ALTER TABLE public.fpoint_items ADD COLUMN buyable boolean NOT NULL DEFAULT false; - END IF; - END IF; -END $$; \ No newline at end of file diff --git a/schemas/patch-schema/15-reset-goocoos.sql b/schemas/patch-schema/15-reset-goocoos.sql deleted file mode 100644 index ca4d3fa11..000000000 --- a/schemas/patch-schema/15-reset-goocoos.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -UPDATE goocoo SET goocoo0=NULL, goocoo1=NULL, goocoo2=NULL, goocoo3=NULL, goocoo4=NULL; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/16-discord-password-resets.sql b/schemas/patch-schema/16-discord-password-resets.sql deleted file mode 100644 index bd2e83fea..000000000 --- a/schemas/patch-schema/16-discord-password-resets.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE IF EXISTS public.users ADD COLUMN discord_token text; -ALTER TABLE IF EXISTS public.users ADD COLUMN discord_id text; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/17-op-accounts.sql b/schemas/patch-schema/17-op-accounts.sql deleted file mode 100644 index bdf5dccd8..000000000 --- a/schemas/patch-schema/17-op-accounts.sql +++ /dev/null @@ -1,12 +0,0 @@ -BEGIN; - -ALTER TABLE IF EXISTS public.users ADD COLUMN op boolean; - -CREATE TABLE public.bans -( - user_id integer NOT NULL, - expires timestamp with time zone, - PRIMARY KEY (user_id) -); - -END; \ No newline at end of file diff --git a/schemas/patch-schema/18-timer-toggle.sql b/schemas/patch-schema/18-timer-toggle.sql deleted file mode 100644 index c2bff008f..000000000 --- a/schemas/patch-schema/18-timer-toggle.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE users ADD COLUMN IF NOT EXISTS timer bool; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/19-festa-submissions.sql b/schemas/patch-schema/19-festa-submissions.sql deleted file mode 100644 index 5f8a95448..000000000 --- a/schemas/patch-schema/19-festa-submissions.sql +++ /dev/null @@ -1,16 +0,0 @@ -CREATE TABLE IF NOT EXISTS festa_submissions ( - character_id int NOT NULL, - guild_id int NOT NULL, - trial_type int NOT NULL, - souls int NOT NULL, - timestamp timestamp with time zone NOT NULL -); - -ALTER TABLE guild_characters DROP COLUMN IF EXISTS souls; - -DO $$ BEGIN - ALTER TYPE festival_colour RENAME TO festival_color; -EXCEPTION - WHEN undefined_object THEN NULL; - WHEN duplicate_object THEN NULL; -END $$; \ No newline at end of file diff --git a/schemas/patch-schema/20-reset-warehouses.sql b/schemas/patch-schema/20-reset-warehouses.sql deleted file mode 100644 index efb42f8a9..000000000 --- a/schemas/patch-schema/20-reset-warehouses.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -UPDATE guilds SET item_box=NULL; -UPDATE users SET item_box=NULL; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/21-rename-hrp.sql b/schemas/patch-schema/21-rename-hrp.sql deleted file mode 100644 index 605210636..000000000 --- a/schemas/patch-schema/21-rename-hrp.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE IF EXISTS public.characters RENAME hrp TO hr; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/22-clan-changing-room.sql b/schemas/patch-schema/22-clan-changing-room.sql deleted file mode 100644 index 4af9ef18a..000000000 --- a/schemas/patch-schema/22-clan-changing-room.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE guilds ADD COLUMN IF NOT EXISTS room_rp INT DEFAULT 0; -ALTER TABLE guilds ADD COLUMN IF NOT EXISTS room_expiry TIMESTAMP WITHOUT TIME ZONE; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/23-rework-distributions-2.sql b/schemas/patch-schema/23-rework-distributions-2.sql deleted file mode 100644 index da6250eb0..000000000 --- a/schemas/patch-schema/23-rework-distributions-2.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE distribution ADD COLUMN rights INTEGER; -ALTER TABLE distribution ADD COLUMN selection BOOLEAN; - -END; \ No newline at end of file diff --git a/schemas/patch-schema/24-fix-weekly-stamps.sql b/schemas/patch-schema/24-fix-weekly-stamps.sql deleted file mode 100644 index 88825345f..000000000 --- a/schemas/patch-schema/24-fix-weekly-stamps.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE IF EXISTS public.stamps RENAME hl_next TO hl_checked; -ALTER TABLE IF EXISTS public.stamps RENAME ex_next TO ex_checked; - -END; diff --git a/schemas/patch-schema/25-fix-rasta-id.sql b/schemas/patch-schema/25-fix-rasta-id.sql deleted file mode 100644 index 6de8bb6f4..000000000 --- a/schemas/patch-schema/25-fix-rasta-id.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -CREATE SEQUENCE IF NOT EXISTS public.rasta_id_seq; - -END; diff --git a/schemas/patch-schema/26-fix-mail.sql b/schemas/patch-schema/26-fix-mail.sql deleted file mode 100644 index 358ab17e6..000000000 --- a/schemas/patch-schema/26-fix-mail.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE mail ADD COLUMN IF NOT EXISTS is_sys_message BOOLEAN NOT NULL DEFAULT false; - -END; diff --git a/schemas/patch-schema/27-fix-character-defaults.sql b/schemas/patch-schema/27-fix-character-defaults.sql deleted file mode 100644 index 55f9fb4d0..000000000 --- a/schemas/patch-schema/27-fix-character-defaults.sql +++ /dev/null @@ -1,15 +0,0 @@ -BEGIN; - --- Initialize otomoairou (mercenary data) with default empty data for characters that have NULL or empty values --- This prevents error logs when loading mercenary data during zone transitions -UPDATE characters -SET otomoairou = decode(repeat('00', 10), 'hex') -WHERE otomoairou IS NULL OR length(otomoairou) = 0; - --- Initialize platemyset (plate configuration) with default empty data for characters that have NULL or empty values --- This prevents error logs when loading plate data during zone transitions -UPDATE characters -SET platemyset = decode(repeat('00', 1920), 'hex') -WHERE platemyset IS NULL OR length(platemyset) = 0; - -COMMIT; diff --git a/schemas/patch-schema/28-drop-transient-binary-columns.sql b/schemas/patch-schema/28-drop-transient-binary-columns.sql deleted file mode 100644 index 738ce5555..000000000 --- a/schemas/patch-schema/28-drop-transient-binary-columns.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Drop transient binary columns that are now memory-only. --- UserBinary type2/type3 and characters.minidata are session state --- resent by the client on every login; they do not need persistence. - -ALTER TABLE user_binary DROP COLUMN IF EXISTS type2; -ALTER TABLE user_binary DROP COLUMN IF EXISTS type3; -ALTER TABLE characters DROP COLUMN IF EXISTS minidata; diff --git a/schemas/patch-schema/29-guild-weekly-bonus.sql b/schemas/patch-schema/29-guild-weekly-bonus.sql deleted file mode 100644 index 93f3cfedf..000000000 --- a/schemas/patch-schema/29-guild-weekly-bonus.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE IF EXISTS public.guilds - ADD COLUMN IF NOT EXISTS weekly_bonus_users INT NOT NULL DEFAULT 0; - -END; diff --git a/schemas/patch-schema/30-daily-resets.sql b/schemas/patch-schema/30-daily-resets.sql deleted file mode 100644 index 18b24e5ca..000000000 --- a/schemas/patch-schema/30-daily-resets.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; -ALTER TABLE IF EXISTS public.gacha_stepup - ADD COLUMN IF NOT EXISTS created_at TIMESTAMP WITH TIME ZONE DEFAULT now(); -ALTER TABLE IF EXISTS public.guilds - ADD COLUMN IF NOT EXISTS rp_reset_at TIMESTAMP WITH TIME ZONE; -END; diff --git a/schemas/patch-schema/31-monthly-items.sql b/schemas/patch-schema/31-monthly-items.sql deleted file mode 100644 index 6c78e6ab2..000000000 --- a/schemas/patch-schema/31-monthly-items.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE IF EXISTS public.stamps ADD COLUMN IF NOT EXISTS monthly_claimed TIMESTAMP WITH TIME ZONE; -ALTER TABLE IF EXISTS public.stamps ADD COLUMN IF NOT EXISTS monthly_hl_claimed TIMESTAMP WITH TIME ZONE; -ALTER TABLE IF EXISTS public.stamps ADD COLUMN IF NOT EXISTS monthly_ex_claimed TIMESTAMP WITH TIME ZONE; diff --git a/schemas/patch-schema/32-guild-posts-soft-delete.sql b/schemas/patch-schema/32-guild-posts-soft-delete.sql deleted file mode 100644 index 58786d6ff..000000000 --- a/schemas/patch-schema/32-guild-posts-soft-delete.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - --- Add soft-delete column to guild_posts, matching the pattern used by characters and mail tables. -ALTER TABLE guild_posts ADD COLUMN IF NOT EXISTS deleted boolean DEFAULT false NOT NULL; - -COMMIT; diff --git a/schemas/update-schema/9.2-update.sql b/schemas/update-schema/9.2-update.sql deleted file mode 100644 index e7dbf699b..000000000 --- a/schemas/update-schema/9.2-update.sql +++ /dev/null @@ -1,241 +0,0 @@ -BEGIN; - -DROP TABLE IF EXISTS public.fpoint_items; - -CREATE TABLE IF NOT EXISTS public.fpoint_items ( - id serial PRIMARY KEY, - item_type integer, - item_id integer, - quantity integer, - fpoints integer, - trade_type integer -); - -ALTER TABLE IF EXISTS public.characters ADD bonus_quests INT NOT NULL DEFAULT 0; - -ALTER TABLE IF EXISTS public.characters ADD daily_quests INT NOT NULL DEFAULT 0; - -ALTER TABLE IF EXISTS public.characters ADD promo_points INT NOT NULL DEFAULT 0; - -ALTER TABLE IF EXISTS public.guild_characters ADD rp_today INT DEFAULT 0; - -ALTER TABLE IF EXISTS public.guild_characters ADD rp_yesterday INT DEFAULT 0; - -UPDATE public.characters SET savemercenary = NULL; - -ALTER TABLE IF EXISTS public.characters ADD rasta_id INT; - -ALTER TABLE IF EXISTS public.characters ADD pact_id INT; - -ALTER TABLE IF EXISTS public.characters ADD stampcard INT NOT NULL DEFAULT 0; - -ALTER TABLE IF EXISTS public.characters DROP COLUMN IF EXISTS gacha_prem; - -ALTER TABLE IF EXISTS public.characters DROP COLUMN IF EXISTS gacha_trial; - -ALTER TABLE IF EXISTS public.characters DROP COLUMN IF EXISTS frontier_points; - -ALTER TABLE IF EXISTS public.users ADD IF NOT EXISTS gacha_premium INT; - -ALTER TABLE IF EXISTS public.users ADD IF NOT EXISTS gacha_trial INT; - -ALTER TABLE IF EXISTS public.users ADD IF NOT EXISTS frontier_points INT; - -DROP TABLE IF EXISTS public.gacha_shop; - -CREATE TABLE IF NOT EXISTS public.gacha_shop ( - id SERIAL PRIMARY KEY, - min_gr INTEGER, - min_hr INTEGER, - name TEXT, - url_banner TEXT, - url_feature TEXT, - url_thumbnail TEXT, - wide BOOLEAN, - recommended BOOLEAN, - gacha_type INTEGER, - hidden BOOLEAN -); - -DROP TABLE IF EXISTS public.gacha_shop_items; - -CREATE TABLE IF NOT EXISTS public.gacha_entries ( - id SERIAL PRIMARY KEY, - gacha_id INTEGER, - entry_type INTEGER, - item_type INTEGER, - item_number INTEGER, - item_quantity INTEGER, - weight INTEGER, - rarity INTEGER, - rolls INTEGER, - frontier_points INTEGER, - daily_limit INTEGER -); - -CREATE TABLE IF NOT EXISTS public.gacha_items ( - id SERIAL PRIMARY KEY, - entry_id INTEGER, - item_type INTEGER, - item_id INTEGER, - quantity INTEGER -); - -DROP TABLE IF EXISTS public.stepup_state; - -CREATE TABLE IF NOT EXISTS public.gacha_stepup ( - gacha_id INTEGER, - step INTEGER, - character_id INTEGER -); - -DROP TABLE IF EXISTS public.lucky_box_state; - -CREATE TABLE IF NOT EXISTS public.gacha_box ( - gacha_id INTEGER, - entry_id INTEGER, - character_id INTEGER -); - -DROP TABLE IF EXISTS public.login_boost_state; - -CREATE TABLE IF NOT EXISTS public.login_boost ( - char_id INTEGER, - week_req INTEGER, - expiration TIMESTAMP WITH TIME ZONE, - reset TIMESTAMP WITH TIME ZONE -); - -ALTER TABLE IF EXISTS public.characters ADD COLUMN mezfes BYTEA; - -ALTER TABLE IF EXISTS public.characters ALTER COLUMN daily_time TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.characters ALTER COLUMN guild_post_checked TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.characters ALTER COLUMN boost_time TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.characters ADD COLUMN IF NOT EXISTS cafe_reset TIMESTAMP WITHOUT TIME ZONE; - -ALTER TABLE IF EXISTS public.characters ALTER COLUMN cafe_reset TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.distribution ALTER COLUMN deadline TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.events ALTER COLUMN start_time TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.feature_weapon ALTER COLUMN start_time TYPE TIMESTAMP WITH TIME ZONE; - -CREATE TABLE IF NOT EXISTS public.feature_weapon -( - start_time TIMESTAMP WITH TIME ZONE NOT NULL, - featured INTEGER NOT NULL -); - -ALTER TABLE IF EXISTS public.guild_alliances ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.guild_applications ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.guild_characters ALTER COLUMN joined_at TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.guild_posts ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.characters ALTER COLUMN daily_time TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.guilds ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.mail ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.stamps ALTER COLUMN hl_next TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.stamps ALTER COLUMN ex_next TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.titles ALTER COLUMN unlocked_at TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.titles ALTER COLUMN updated_at TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.users ALTER COLUMN last_login TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.users ALTER COLUMN return_expires TYPE TIMESTAMP WITH TIME ZONE; - -ALTER TABLE IF EXISTS public.guild_meals DROP COLUMN IF EXISTS expires; - -ALTER TABLE IF EXISTS public.guild_meals ADD COLUMN IF NOT EXISTS created_at TIMESTAMP WITH TIME ZONE; - -DROP TABLE IF EXISTS public.account_ban; - -DROP TABLE IF EXISTS public.account_history; - -DROP TABLE IF EXISTS public.account_moderation; - -DROP TABLE IF EXISTS public.account_sub; - -DROP TABLE IF EXISTS public.history; - -DROP TABLE IF EXISTS public.questlists; - -DROP TABLE IF EXISTS public.schema_migrations; - -DROP TABLE IF EXISTS public.user_binaries; - -DROP PROCEDURE IF EXISTS raviinit; - -DROP PROCEDURE IF EXISTS ravireset; - -ALTER TABLE IF EXISTS public.normal_shop_items RENAME TO shop_items; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN shoptype TO shop_type; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN shopid TO shop_id; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN itemhash TO id; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN itemid TO item_id; - -ALTER TABLE IF EXISTS public.shop_items ALTER COLUMN points TYPE integer; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN points TO cost; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN tradequantity TO quantity; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN rankreqlow TO min_hr; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN rankreqhigh TO min_sr; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN rankreqg TO min_gr; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN storelevelreq TO store_level; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN maximumquantity TO max_quantity; - -ALTER TABLE IF EXISTS public.shop_items DROP COLUMN IF EXISTS boughtquantity; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN roadfloorsrequired TO road_floors; - -ALTER TABLE IF EXISTS public.shop_items RENAME COLUMN weeklyfataliskills TO road_fatalis; - -ALTER TABLE public.shop_items RENAME CONSTRAINT normal_shop_items_pkey TO shop_items_pkey; - -ALTER TABLE IF EXISTS public.shop_items DROP CONSTRAINT IF EXISTS normal_shop_items_itemhash_key; - -CREATE SEQUENCE IF NOT EXISTS public.shop_items_id_seq; - -ALTER SEQUENCE IF EXISTS public.shop_items_id_seq OWNER TO postgres; - -ALTER TABLE IF EXISTS public.shop_items ALTER COLUMN id SET DEFAULT nextval('shop_items_id_seq'::regclass); - -ALTER SEQUENCE IF EXISTS public.shop_items_id_seq OWNED BY shop_items.id; - -SELECT setval('shop_items_id_seq', (SELECT MAX(id) FROM public.shop_items)); - -DROP TABLE IF EXISTS public.shop_item_state; - -CREATE TABLE IF NOT EXISTS public.shop_items_bought ( - character_id INTEGER, - shop_item_id INTEGER, - bought INTEGER -); - -UPDATE users SET rights = rights-2; - -ALTER TABLE IF EXISTS public.users ALTER COLUMN rights SET DEFAULT 12; - -END; \ No newline at end of file diff --git a/server/channelserver/testhelpers_db.go b/server/channelserver/testhelpers_db.go index 5bcbd1779..78d421c3b 100644 --- a/server/channelserver/testhelpers_db.go +++ b/server/channelserver/testhelpers_db.go @@ -3,17 +3,16 @@ package channelserver import ( "fmt" "os" - "os/exec" - "path/filepath" - "sort" "strings" "sync" "testing" "time" "erupe-ce/server/channelserver/compression/nullcomp" + "erupe-ce/server/migrations" "github.com/jmoiron/sqlx" _ "github.com/lib/pq" + "go.uber.org/zap" ) var ( @@ -104,147 +103,14 @@ func CleanTestDB(t *testing.T, db *sqlx.DB) { } } -// ApplyTestSchema applies the database schema from init.sql using pg_restore +// ApplyTestSchema applies the database schema using the embedded migration system. func ApplyTestSchema(t *testing.T, db *sqlx.DB) { t.Helper() - // Find the project root (where schemas/ directory is located) - projectRoot := findProjectRoot(t) - schemaPath := filepath.Join(projectRoot, "schemas", "init.sql") - - // Get the connection config - config := DefaultTestDBConfig() - - // Use pg_restore to load the schema dump - // The init.sql file is a pg_dump custom format, so we need pg_restore - cmd := exec.Command("pg_restore", - "-h", config.Host, - "-p", config.Port, - "-U", config.User, - "-d", config.DBName, - "--no-owner", - "--no-acl", - schemaPath, - ) - cmd.Env = append(os.Environ(), fmt.Sprintf("PGPASSWORD=%s", config.Password)) - - output, err := cmd.CombinedOutput() + logger, _ := zap.NewDevelopment() + _, err := migrations.Migrate(db, logger.Named("test-migrations")) if err != nil { - out := string(output) - // pg_restore reports non-fatal warnings (version mismatches, already exists) as errors. - // Only fail if we see no "errors ignored on restore" summary, which means a real failure. - if !strings.Contains(out, "errors ignored on restore") { - t.Fatalf("pg_restore failed: %v\n%s", err, out) - } - t.Logf("pg_restore completed with non-fatal warnings (ignored)") - } - - // Apply the 9.2 update schema (init.sql bootstraps to 9.1.0) - applyUpdateSchema(t, db, projectRoot) - - // Apply patch schemas in order - applyPatchSchemas(t, db, projectRoot) -} - -// applyUpdateSchema applies the 9.2 update schema that bridges init.sql (v9.1.0) to v9.2.0. -// It runs each statement individually to tolerate partial failures (e.g. role references). -func applyUpdateSchema(t *testing.T, db *sqlx.DB, projectRoot string) { - t.Helper() - - updatePath := filepath.Join(projectRoot, "schemas", "update-schema", "9.2-update.sql") - updateSQL, err := os.ReadFile(updatePath) - if err != nil { - t.Logf("Warning: Could not read 9.2 update schema: %v", err) - return - } - - // Strip the outer BEGIN/END transaction wrapper so we can run statements individually. - content := string(updateSQL) - content = strings.Replace(content, "BEGIN;", "", 1) - // Remove trailing END; (last occurrence) - if idx := strings.LastIndex(content, "END;"); idx >= 0 { - content = content[:idx] + content[idx+4:] - } - - // Split on semicolons and execute each statement, tolerating errors from - // role references or already-applied changes. - for _, stmt := range strings.Split(content, ";") { - stmt = strings.TrimSpace(stmt) - if stmt == "" { - continue - } - _, _ = db.Exec(stmt) // Errors expected for role mismatches, already-applied changes, etc. - } -} - -// applyPatchSchemas applies all patch schema files in numeric order -func applyPatchSchemas(t *testing.T, db *sqlx.DB, projectRoot string) { - t.Helper() - - patchDir := filepath.Join(projectRoot, "schemas", "patch-schema") - entries, err := os.ReadDir(patchDir) - if err != nil { - t.Logf("Warning: Could not read patch-schema directory: %v", err) - return - } - - // Sort patch files numerically - var patchFiles []string - for _, entry := range entries { - if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".sql") { - patchFiles = append(patchFiles, entry.Name()) - } - } - sort.Strings(patchFiles) - - // Apply each patch in its own transaction - for _, filename := range patchFiles { - patchPath := filepath.Join(patchDir, filename) - patchSQL, err := os.ReadFile(patchPath) - if err != nil { - t.Logf("Warning: Failed to read patch file %s: %v", filename, err) - continue - } - - // Start a new transaction for each patch - tx, err := db.Begin() - if err != nil { - t.Logf("Warning: Failed to start transaction for patch %s: %v", filename, err) - continue - } - - _, err = tx.Exec(string(patchSQL)) - if err != nil { - _ = tx.Rollback() - t.Logf("Warning: Failed to apply patch %s: %v", filename, err) - // Continue with other patches even if one fails - } else { - _ = tx.Commit() - } - } -} - -// findProjectRoot finds the project root directory by looking for the schemas directory -func findProjectRoot(t *testing.T) string { - t.Helper() - - // Start from current directory and walk up - dir, err := os.Getwd() - if err != nil { - t.Fatalf("Failed to get working directory: %v", err) - } - - for { - schemasPath := filepath.Join(dir, "schemas") - if stat, err := os.Stat(schemasPath); err == nil && stat.IsDir() { - return dir - } - - parent := filepath.Dir(dir) - if parent == dir { - t.Fatal("Could not find project root (schemas directory not found)") - } - dir = parent + t.Fatalf("Failed to apply schema migrations: %v", err) } } diff --git a/server/migrations/migrations.go b/server/migrations/migrations.go new file mode 100644 index 000000000..1172f56fa --- /dev/null +++ b/server/migrations/migrations.go @@ -0,0 +1,229 @@ +package migrations + +import ( + "embed" + "fmt" + "io/fs" + "sort" + "strconv" + "strings" + + "github.com/jmoiron/sqlx" + "go.uber.org/zap" +) + +//go:embed sql/*.sql +var migrationFS embed.FS + +//go:embed seed/*.sql +var seedFS embed.FS + +// Migrate creates the schema_version table if needed, detects existing databases +// (auto-marks baseline as applied), then runs all pending migrations in order. +// Each migration runs in its own transaction. +func Migrate(db *sqlx.DB, logger *zap.Logger) (int, error) { + if err := ensureVersionTable(db); err != nil { + return 0, fmt.Errorf("creating schema_version table: %w", err) + } + + if err := detectExistingDB(db, logger); err != nil { + return 0, fmt.Errorf("detecting existing database: %w", err) + } + + migrations, err := readMigrations() + if err != nil { + return 0, fmt.Errorf("reading migration files: %w", err) + } + + applied, err := appliedVersions(db) + if err != nil { + return 0, fmt.Errorf("querying applied versions: %w", err) + } + + count := 0 + for _, m := range migrations { + if applied[m.version] { + continue + } + logger.Info(fmt.Sprintf("Applying migration %04d: %s", m.version, m.filename)) + if err := applyMigration(db, m); err != nil { + return count, fmt.Errorf("applying %s: %w", m.filename, err) + } + count++ + } + + return count, nil +} + +// ApplySeedData runs all seed/*.sql files. Not tracked in schema_version. +// Safe to run multiple times if seed files use ON CONFLICT DO NOTHING. +func ApplySeedData(db *sqlx.DB, logger *zap.Logger) (int, error) { + files, err := fs.ReadDir(seedFS, "seed") + if err != nil { + return 0, fmt.Errorf("reading seed directory: %w", err) + } + + var names []string + for _, f := range files { + if !f.IsDir() && strings.HasSuffix(f.Name(), ".sql") { + names = append(names, f.Name()) + } + } + sort.Strings(names) + + count := 0 + for _, name := range names { + data, err := seedFS.ReadFile("seed/" + name) + if err != nil { + return count, fmt.Errorf("reading seed file %s: %w", name, err) + } + logger.Info(fmt.Sprintf("Applying seed data: %s", name)) + if _, err := db.Exec(string(data)); err != nil { + return count, fmt.Errorf("executing seed file %s: %w", name, err) + } + count++ + } + return count, nil +} + +// Version returns the highest applied migration number, or 0 if none. +func Version(db *sqlx.DB) (int, error) { + var exists bool + err := db.QueryRow(`SELECT EXISTS( + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'public' AND table_name = 'schema_version' + )`).Scan(&exists) + if err != nil { + return 0, err + } + if !exists { + return 0, nil + } + + var version int + err = db.QueryRow("SELECT COALESCE(MAX(version), 0) FROM schema_version").Scan(&version) + return version, err +} + +type migration struct { + version int + filename string + sql string +} + +func ensureVersionTable(db *sqlx.DB) error { + _, err := db.Exec(`CREATE TABLE IF NOT EXISTS schema_version ( + version INTEGER PRIMARY KEY, + filename TEXT NOT NULL, + applied_at TIMESTAMPTZ DEFAULT now() + )`) + return err +} + +// detectExistingDB checks if the database has tables but no schema_version rows. +// If so, it marks the baseline migration (version 1) as already applied. +func detectExistingDB(db *sqlx.DB, logger *zap.Logger) error { + var count int + if err := db.QueryRow("SELECT COUNT(*) FROM schema_version").Scan(&count); err != nil { + return err + } + if count > 0 { + return nil // Already tracked + } + + // Check if the database has any user tables (beyond schema_version itself) + var tableCount int + err := db.QueryRow(`SELECT COUNT(*) FROM information_schema.tables + WHERE table_schema = 'public' AND table_name != 'schema_version'`).Scan(&tableCount) + if err != nil { + return err + } + if tableCount == 0 { + return nil // Fresh database + } + + // Existing database without migration tracking — mark baseline as applied + logger.Info("Detected existing database without schema_version tracking, marking baseline as applied") + _, err = db.Exec("INSERT INTO schema_version (version, filename) VALUES (1, '0001_init.sql')") + return err +} + +func readMigrations() ([]migration, error) { + files, err := fs.ReadDir(migrationFS, "sql") + if err != nil { + return nil, err + } + + var migrations []migration + for _, f := range files { + if f.IsDir() || !strings.HasSuffix(f.Name(), ".sql") { + continue + } + version, err := parseVersion(f.Name()) + if err != nil { + return nil, fmt.Errorf("parsing version from %s: %w", f.Name(), err) + } + data, err := migrationFS.ReadFile("sql/" + f.Name()) + if err != nil { + return nil, err + } + migrations = append(migrations, migration{ + version: version, + filename: f.Name(), + sql: string(data), + }) + } + + sort.Slice(migrations, func(i, j int) bool { + return migrations[i].version < migrations[j].version + }) + return migrations, nil +} + +func parseVersion(filename string) (int, error) { + parts := strings.SplitN(filename, "_", 2) + if len(parts) < 2 { + return 0, fmt.Errorf("invalid migration filename: %s (expected NNNN_description.sql)", filename) + } + return strconv.Atoi(parts[0]) +} + +func appliedVersions(db *sqlx.DB) (map[int]bool, error) { + rows, err := db.Query("SELECT version FROM schema_version") + if err != nil { + return nil, err + } + defer func() { _ = rows.Close() }() + + applied := make(map[int]bool) + for rows.Next() { + var v int + if err := rows.Scan(&v); err != nil { + return nil, err + } + applied[v] = true + } + return applied, rows.Err() +} + +func applyMigration(db *sqlx.DB, m migration) error { + tx, err := db.Begin() + if err != nil { + return err + } + + if _, err := tx.Exec(m.sql); err != nil { + _ = tx.Rollback() + return err + } + + if _, err := tx.Exec( + "INSERT INTO schema_version (version, filename) VALUES ($1, $2)", + m.version, m.filename, + ); err != nil { + _ = tx.Rollback() + return err + } + + return tx.Commit() +} diff --git a/server/migrations/migrations_test.go b/server/migrations/migrations_test.go new file mode 100644 index 000000000..602fc3722 --- /dev/null +++ b/server/migrations/migrations_test.go @@ -0,0 +1,202 @@ +package migrations + +import ( + "fmt" + "os" + "testing" + + "github.com/jmoiron/sqlx" + _ "github.com/lib/pq" + "go.uber.org/zap" +) + +func testDB(t *testing.T) *sqlx.DB { + t.Helper() + + host := getEnv("TEST_DB_HOST", "localhost") + port := getEnv("TEST_DB_PORT", "5433") + user := getEnv("TEST_DB_USER", "test") + password := getEnv("TEST_DB_PASSWORD", "test") + dbName := getEnv("TEST_DB_NAME", "erupe_test") + + connStr := fmt.Sprintf( + "host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", + host, port, user, password, dbName, + ) + + db, err := sqlx.Open("postgres", connStr) + if err != nil { + t.Skipf("Test database not available: %v", err) + return nil + } + + if err := db.Ping(); err != nil { + _ = db.Close() + t.Skipf("Test database not available: %v", err) + return nil + } + + // Clean slate + _, err = db.Exec("DROP SCHEMA public CASCADE; CREATE SCHEMA public;") + if err != nil { + t.Fatalf("Failed to clean database: %v", err) + } + + return db +} + +func getEnv(key, defaultValue string) string { + if value := os.Getenv(key); value != "" { + return value + } + return defaultValue +} + +func TestMigrateEmptyDB(t *testing.T) { + db := testDB(t) + defer func() { _ = db.Close() }() + + logger, _ := zap.NewDevelopment() + + applied, err := Migrate(db, logger) + if err != nil { + t.Fatalf("Migrate failed: %v", err) + } + if applied != 1 { + t.Errorf("expected 1 migration applied, got %d", applied) + } + + ver, err := Version(db) + if err != nil { + t.Fatalf("Version failed: %v", err) + } + if ver != 1 { + t.Errorf("expected version 1, got %d", ver) + } +} + +func TestMigrateAlreadyMigrated(t *testing.T) { + db := testDB(t) + defer func() { _ = db.Close() }() + + logger, _ := zap.NewDevelopment() + + // First run + _, err := Migrate(db, logger) + if err != nil { + t.Fatalf("First Migrate failed: %v", err) + } + + // Second run should apply 0 + applied, err := Migrate(db, logger) + if err != nil { + t.Fatalf("Second Migrate failed: %v", err) + } + if applied != 0 { + t.Errorf("expected 0 migrations on second run, got %d", applied) + } +} + +func TestMigrateExistingDBWithoutSchemaVersion(t *testing.T) { + db := testDB(t) + defer func() { _ = db.Close() }() + + logger, _ := zap.NewDevelopment() + + // Simulate an existing database: create a dummy table + _, err := db.Exec("CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT)") + if err != nil { + t.Fatalf("Failed to create dummy table: %v", err) + } + + // Migrate should detect existing DB and auto-mark baseline + applied, err := Migrate(db, logger) + if err != nil { + t.Fatalf("Migrate failed: %v", err) + } + // Baseline (0001) is auto-marked, so 0 "new" migrations applied + if applied != 0 { + t.Errorf("expected 0 migrations applied (baseline auto-marked), got %d", applied) + } + + ver, err := Version(db) + if err != nil { + t.Fatalf("Version failed: %v", err) + } + if ver != 1 { + t.Errorf("expected version 1 (auto-marked baseline), got %d", ver) + } +} + +func TestVersionEmptyDB(t *testing.T) { + db := testDB(t) + defer func() { _ = db.Close() }() + + ver, err := Version(db) + if err != nil { + t.Fatalf("Version failed: %v", err) + } + if ver != 0 { + t.Errorf("expected version 0 on empty DB, got %d", ver) + } +} + +func TestApplySeedData(t *testing.T) { + db := testDB(t) + defer func() { _ = db.Close() }() + + logger, _ := zap.NewDevelopment() + + // Apply schema first + _, err := Migrate(db, logger) + if err != nil { + t.Fatalf("Migrate failed: %v", err) + } + + count, err := ApplySeedData(db, logger) + if err != nil { + t.Fatalf("ApplySeedData failed: %v", err) + } + if count == 0 { + t.Error("expected at least 1 seed file applied, got 0") + } +} + +func TestParseVersion(t *testing.T) { + tests := []struct { + filename string + want int + wantErr bool + }{ + {"0001_init.sql", 1, false}, + {"0002_add_users.sql", 2, false}, + {"0100_big_change.sql", 100, false}, + {"bad.sql", 0, true}, + } + for _, tt := range tests { + got, err := parseVersion(tt.filename) + if (err != nil) != tt.wantErr { + t.Errorf("parseVersion(%q) error = %v, wantErr %v", tt.filename, err, tt.wantErr) + continue + } + if got != tt.want { + t.Errorf("parseVersion(%q) = %d, want %d", tt.filename, got, tt.want) + } + } +} + +func TestReadMigrations(t *testing.T) { + migrations, err := readMigrations() + if err != nil { + t.Fatalf("readMigrations failed: %v", err) + } + if len(migrations) == 0 { + t.Fatal("expected at least 1 migration, got 0") + } + if migrations[0].version != 1 { + t.Errorf("first migration version = %d, want 1", migrations[0].version) + } + if migrations[0].filename != "0001_init.sql" { + t.Errorf("first migration filename = %q, want 0001_init.sql", migrations[0].filename) + } +} diff --git a/server/migrations/seed/DistributionDemo.sql b/server/migrations/seed/DistributionDemo.sql new file mode 100644 index 000000000..c37a16a57 --- /dev/null +++ b/server/migrations/seed/DistributionDemo.sql @@ -0,0 +1,11 @@ +BEGIN; + +-- Adds a Distribution that can be accepted up to 20 times that gives one of Item Type 30 (Item Box extra page) +INSERT INTO distribution (type, event_name, description, times_acceptable, data) VALUES (1, 'Extra Item Storage', '~C05Adds one new page to your Item Box.', 20, ''::bytea); +INSERT INTO distribution_items (distribution_id, item_type, quantity) VALUES ((SELECT id FROM distribution ORDER BY id DESC LIMIT 1), 30, 1); + +-- Adds a Distribution that can be accepted up to 20 times that gives one of Item Type 31 (Equipment Box extra page) +INSERT INTO distribution (type, event_name, description, times_acceptable, data) VALUES (1, 'Extra Equipment Storage', '~C05Adds one new page to your Equipment Box.', 20, ''::bytea); +INSERT INTO distribution_items (distribution_id, item_type, quantity) VALUES ((SELECT id FROM distribution ORDER BY id DESC LIMIT 1), 31, 1); + +END; \ No newline at end of file diff --git a/server/migrations/seed/DivaShops.sql b/server/migrations/seed/DivaShops.sql new file mode 100644 index 000000000..c1a1d850b --- /dev/null +++ b/server/migrations/seed/DivaShops.sql @@ -0,0 +1,45 @@ +BEGIN; + +INSERT INTO public.shop_items +(shop_type, shop_id, item_id, cost, quantity, min_hr, min_sr, min_gr, store_level, max_quantity, road_floors, road_fatalis) +VALUES + (8,5,1,30,10,0,0,0,0,10,0,0), + (8,5,2,60,10,0,0,0,0,10,0,0), + (8,5,3,60,10,0,0,0,0,10,0,0), + (8,5,4,30,10,0,0,0,0,10,0,0), + (8,5,5,60,10,0,0,0,0,10,0,0), + (8,5,6,80,10,0,0,0,1,10,0,0), + (8,5,7,80,10,0,0,0,1,10,0,0), + (8,5,8,80,10,0,0,0,1,10,0,0), + (8,5,9,100,10,0,0,0,2,10,0,0), + (8,5,10,100,10,0,0,0,2,10,0,0), + (8,5,11,100,10,0,0,0,2,10,0,0), + (8,5,12,100,10,0,0,0,2,10,0,0), + (8,5,13,100,10,0,0,0,2,10,0,0), + (8,5,14,200,10,0,0,0,2,10,0,0), + (8,5,15,500,10,0,0,0,3,10,0,0), + (8,5,16,1000,10,0,0,0,3,10,0,0), + (8,5,20,30,10,0,0,0,0,10,0,0), + (8,5,21,30,10,0,0,0,0,10,0,0), + (8,5,22,60,10,0,0,0,0,10,0,0), + (8,5,23,60,10,0,0,0,0,10,0,0), + (8,5,24,60,10,0,0,0,0,10,0,0), + (8,5,25,80,10,0,0,0,1,10,0,0), + (8,5,26,80,10,0,0,0,1,10,0,0), + (8,5,27,500,10,0,0,1,3,10,0,0), + (8,5,28,60,10,0,0,0,0,10,0,0), + (8,5,29,60,10,299,0,0,0,10,0,0), + (8,5,30,100,10,0,0,1,3,10,0,0), + (8,5,31,80,10,299,0,0,1,10,0,0), + (8,5,32,80,10,299,0,0,1,10,0,0), + (8,5,33,80,10,299,0,0,1,10,0,0), + (8,7,2209,400,1,299,0,0,2,5,0,0), + (8,7,2208,400,1,299,0,0,2,5,0,0), + (8,7,5113,400,1,299,0,0,2,5,0,0), + (8,7,3571,400,1,299,0,0,2,5,0,0), + (8,7,3572,400,1,299,0,0,2,5,0,0), + (8,7,3738,400,1,299,0,0,2,5,0,0), + (8,7,3737,400,1,299,0,0,2,5,0,0), + (8,7,4399,400,1,299,0,0,2,5,0,0); + +END; \ No newline at end of file diff --git a/server/migrations/seed/EventQuests.sql b/server/migrations/seed/EventQuests.sql new file mode 100644 index 000000000..23b4277c7 --- /dev/null +++ b/server/migrations/seed/EventQuests.sql @@ -0,0 +1,292 @@ +BEGIN; + +-- Ripped quests +INSERT INTO public.event_quests (max_players, quest_type, quest_id, mark) VALUES + (0,9,40060,0), + (0,9,40079,0), + (0,9,40080,0), + (0,9,40081,0), + (0,9,40133,0), + (0,9,40134,0), + (0,9,40135,0), + (0,9,40136,0), + (0,9,40137,0), + (0,9,40138,0), + (0,9,40142,0), + (0,9,40143,0), + (0,9,40161,0), + (0,9,40162,0), + (4,9,40173,0), + (4,9,40174,0), + (0,9,40201,0), + (0,9,40218,0), + (4,43,40236,1), + (4,28,40241,1), + (0,8,50534,0), + (4,18,50852,1), + (4,18,50940,1), + (4,18,51024,1), + (4,18,51025,1), + (4,18,51026,1), + (4,18,51027,1), + (4,38,51052,9), + (4,38,51053,9), + (4,18,51059,1), + (4,38,51107,9), + (4,24,51125,0), + (1,24,51126,0), + (4,24,51127,0), + (4,24,51128,0), + (4,24,51129,0), + (4,26,53034,1), + (4,18,53140,1), + (4,18,53187,1), + (4,18,53201,1), + (1,18,53253,1), + (4,26,53307,1), + (4,24,53314,0), + (4,24,53315,0), + (4,24,53316,0), + (4,24,53317,0), + (4,24,53318,0), + (4,24,53319,0), + (4,24,53320,0), + (4,24,53321,0), + (4,24,53324,0), + (1,18,53326,2), + (4,31,54244,0), + (0,8,54425,0), + (4,28,54449,1), + (4,28,54593,1), + (4,28,54594,1), + (4,28,54603,1), + (4,28,54604,1), + (4,28,54605,1), + (4,28,54606,1), + (1,28,54608,0), + (1,28,54609,0), + (32,40,54751,0), + (32,40,54752,0), + (32,40,54753,0), + (32,40,54754,0), + (32,40,54755,0), + (32,40,54756,0), + (32,40,54757,0), + (32,40,54758,0), + (32,40,54759,0), + (32,40,54760,0), + (32,40,54761,0), + (4,28,54801,0), + (4,28,55002,1), + (4,28,55195,0), + (4,28,55202,0), + (4,28,55203,0), + (4,28,55204,0), + (0,8,55369,0), + (4,28,55464,1), + (4,43,55513,1), + (4,28,55529,0), + (4,28,55532,0), + (1,28,55536,0), + (1,28,55537,0), + (32,50,55596,0), + (32,50,55597,0), + (32,50,55598,0), + (32,50,55599,0), + (32,50,55601,0), + (32,50,55602,0), + (32,50,55603,0), + (32,50,55604,0), + (32,50,55605,0), + (32,50,55606,0), + (32,50,55607,0), + (4,28,55619,0), + (4,28,55670,1), + (4,39,55679,9), + (4,39,55680,9), + (4,43,55691,1), + (4,43,55692,1), + (4,43,55693,1), + (4,43,55694,1), + (4,43,55695,1), + (4,43,55696,1), + (4,43,55697,1), + (4,43,55698,1), + (1,43,55728,1), + (4,43,55738,1), + (0,8,55767,0), + (0,8,55768,0), + (4,28,55771,1), + (4,39,55772,9), + (8,51,55796,0), + (8,51,55797,0), + (8,51,55798,0), + (8,51,55799,0), + (8,51,55801,0), + (8,51,55802,0), + (8,51,55803,0), + (8,51,55804,0), + (8,51,55805,0), + (8,51,55806,0), + (8,51,55807,0), + (1,28,55808,0), + (0,8,55870,0), + (0,8,55872,0), + (0,8,55879,0), + (0,8,55880,0), + (0,8,55881,0), + (0,8,55882,0), + (4,28,55896,1), + (0,8,55897,0), + (0,8,55899,0), + (0,8,55901,0), + (0,8,55902,0), + (0,8,55903,0), + (0,8,55904,0), + (0,8,55905,0), + (0,8,55906,0), + (0,8,55907,0), + (0,8,55908,0), + (0,8,55909,0), + (0,8,55910,0), + (0,8,55911,0), + (0,8,55912,0), + (4,39,55916,9), + (4,39,55917,9), + (4,39,55918,9), + (4,39,55919,9), + (4,28,55920,0), + (4,39,55921,9), + (4,39,55922,9), + (4,43,55923,1), + (4,43,55924,1), + (4,43,55925,1), + (4,43,55926,1), + (4,43,55929,1), + (4,43,55930,1), + (4,43,55931,1), + (4,43,55932,1), + (4,28,55935,0), + (4,28,55936,0), + (4,28,55937,0), + (4,28,55938,0), + (4,28,55939,0), + (4,28,55948,0), + (4,28,55949,0), + (4,28,55950,0), + (4,28,55951,0), + (1,28,55963,0), + (4,28,55964,1), + (4,28,55967,1), + (4,43,56042,1), + (4,43,56056,1), + (4,43,56058,1), + (4,43,56059,1), + (4,43,56063,1), + (4,43,56064,1), + (4,43,56076,4), + (4,43,56077,4), + (4,43,56078,4), + (4,43,56079,4), + (4,43,56080,4), + (4,43,56125,1), + (4,24,56134,0), + (4,24,56135,0), + (4,24,56138,0), + (4,24,56139,0), + (4,24,56141,0), + (4,24,56142,0), + (4,28,56143,1), + (4,43,56144,1), + (4,43,56145,1), + (0,8,56146,0), + (4,28,56147,1), + (4,24,56148,0), + (1,24,56149,0), + (4,43,56150,1), + (4,43,56151,1), + (4,43,56154,1), + (4,43,56155,1), + (4,43,56156,1), + (4,28,56157,1), + (1,28,56158,1), + (4,28,56159,1), + (4,48,58043,1), + (4,46,58050,0), + (4,46,58051,0), + (4,46,58052,0), + (4,46,58053,0), + (4,46,58054,0), + (4,46,58055,0), + (4,46,58056,0), + (4,46,58057,0), + (4,46,58058,0), + (4,46,58059,0), + (4,46,58060,0), + (4,46,58061,0), + (4,46,58062,0), + (4,46,58063,0), + (4,46,58064,0), + (4,46,58065,0), + (4,46,58066,0), + (4,46,58067,0), + (4,46,58068,0), + (4,46,58069,0), + (4,46,58070,0), + (4,46,58071,0), + (4,46,58072,0), + (4,46,58074,0), + (4,46,58075,0), + (4,46,58076,0), + (4,46,58077,0), + (4,46,58078,0), + (4,47,58079,0), + (4,47,58080,0), + (4,47,58081,0), + (4,47,58082,0), + (4,47,58083,0), + (4,46,58088,0), + (4,46,58089,0), + (4,46,58090,0), + (4,46,58091,0), + (4,46,58096,0), + (4,46,58097,0), + (4,46,58098,0), + (4,46,58099,0), + (4,46,58101,0), + (4,46,58102,1), + (4,46,58103,1), + (4,46,58104,1), + (4,46,58105,1), + (4,46,58106,1), + (4,46,58107,1), + (4,46,58108,1), + (4,46,58109,1), + (4,46,58112,1), + (4,46,58113,1), + (4,46,58114,1), + (4,46,58115,1), + (4,46,58118,0), + (4,46,58119,0), + (4,46,58120,0), + (4,46,58121,0), + (4,46,58122,0), + (4,46,58123,0), + (4,46,58125,1), + (4,46,58126,1), + (4,46,58127,1), + (4,46,58128,1), + (4,13,61050,0), + (4,13,61051,0), + (4,13,61053,0), + (4,13,61055,0), + (2,13,61067,0), + (4,13,61068,0), + (2,13,61070,0), + (4,13,61071,0), + (8,22,62101,0), + (8,16,62104,0), + (8,16,62105,0), + (8,16,62108,0), + (1,18,62910,1); +END; \ No newline at end of file diff --git a/server/migrations/seed/FPointItems.sql b/server/migrations/seed/FPointItems.sql new file mode 100644 index 000000000..7012e6f25 --- /dev/null +++ b/server/migrations/seed/FPointItems.sql @@ -0,0 +1,391 @@ +BEGIN; + +INSERT INTO fpoint_items (item_type, item_id, quantity, fpoints, buyable) VALUES +(7,8895,1,500,true), +(7,8891,1,300,true), +(7,8892,1,300,true), +(7,8893,1,300,true), +(7,8894,1,300,true), +(7,8890,1,10,true), +(7,10354,1,500,true), +(7,11983,1,300,true), +(7,11984,1,300,true), +(7,11985,1,300,true), +(7,11986,1,300,true), +(7,12524,1,500,true), +(7,12470,1,300,true), +(7,12471,1,300,true), +(7,12472,1,300,true), +(7,12473,1,300,true), +(7,2158,2,1,true), +(7,14548,1,500,true), +(7,9509,1,1,true), +(7,9510,1,1,true), +(7,9511,1,1,true), +(7,9512,1,1,true), +(7,9513,1,1,true), +(7,9514,1,1,true), +(7,9515,1,1,true), +(7,10753,1,1,true), +(7,10754,1,1,true), +(7,10755,1,1,true), +(7,10756,1,1,true), +(7,10757,1,1,true), +(7,10758,1,1,true), +(7,10759,1,1,true), +(7,11296,1,1,true), +(7,11297,1,1,true), +(7,11298,1,1,true), +(7,11299,1,1,true), +(7,11300,1,1,true), +(7,12386,1,1,true), +(7,12387,1,1,true), +(7,12388,1,1,true), +(7,12389,1,1,true), +(7,12390,1,1,true), +(7,13034,1,1,true), +(7,13035,1,1,true), +(7,13036,1,1,true), +(7,13037,1,1,true), +(7,13038,1,1,true), +(7,14179,1,1,true), +(7,14180,1,1,true), +(7,14181,1,1,true), +(7,14182,1,1,true), +(7,14183,1,1,true), +(7,13422,1,1,true), +(7,13423,1,1,true), +(7,13424,1,1,true), +(7,13425,1,1,true), +(7,13426,1,1,true), +(7,13427,1,1,true), +(7,9796,1,3,false), +(7,9700,1,3,false), +(7,10380,1,3,false), +(7,10810,1,3,false), +(7,10811,1,3,false), +(7,11436,1,3,false), +(7,9509,1,1,false), +(7,9510,1,1,false), +(7,9511,1,1,false), +(7,9512,1,1,false), +(7,9513,1,1,false), +(7,9514,1,1,false), +(7,9515,1,1,false), +(7,10753,1,1,false), +(7,10754,1,1,false), +(7,10755,1,1,false), +(7,10756,1,1,false), +(7,10757,1,1,false), +(7,10758,1,1,false), +(7,10759,1,1,false), +(7,11296,1,1,false), +(7,11297,1,1,false), +(7,11298,1,1,false), +(7,11299,1,1,false), +(7,11300,1,1,false), +(7,12509,1,3,false), +(7,12386,1,1,false), +(7,12387,1,1,false), +(7,12388,1,1,false), +(7,12389,1,1,false), +(7,12390,1,1,false), +(7,12872,1,3,false), +(7,12873,1,3,false), +(7,12840,1,1,false), +(7,12841,1,1,false), +(7,12874,1,1,false), +(7,12875,1,1,false), +(7,13191,1,3,false), +(7,13177,1,3,false), +(7,13326,1,3,false), +(7,13034,1,1,false), +(7,13035,1,1,false), +(7,13036,1,1,false), +(7,13037,1,1,false), +(7,13038,1,1,false), +(7,13178,1,3,false), +(7,13453,1,3,false), +(7,13449,1,3,false), +(7,13450,1,3,false), +(7,13404,1,3,false), +(7,13422,1,1,false), +(7,13423,1,1,false), +(7,13424,1,1,false), +(7,13425,1,1,false), +(7,13426,1,1,false), +(7,13427,1,1,false), +(7,13791,1,3,false), +(7,14006,1,3,false), +(7,14031,1,3,false), +(7,14032,1,3,false), +(7,13960,1,3,false), +(7,14029,1,3,false), +(7,13956,1,1,false), +(7,13958,1,1,false), +(7,13957,1,1,false), +(7,13959,1,1,false), +(7,13790,1,3,false), +(7,14005,1,3,false), +(7,14010,1,3,false), +(7,14009,1,3,false), +(7,14008,1,3,false), +(7,13965,1,3,false), +(7,14028,1,3,false), +(7,13963,1,3,false), +(7,14026,1,3,false), +(7,13964,1,3,false), +(7,14027,1,3,false), +(7,14069,1,3,false), +(7,14124,1,3,false), +(7,14065,1,1,false), +(7,14066,1,1,false), +(7,14067,1,1,false), +(7,14068,1,1,false), +(7,13962,1,3,false), +(7,14125,1,3,false), +(7,14089,1,3,false), +(7,14090,1,3,false), +(7,14091,1,3,false), +(7,14092,1,3,false), +(7,14194,1,3,false), +(7,14191,1,3,false), +(7,14198,1,3,false), +(7,14197,1,3,false), +(7,14179,1,1,false), +(7,14180,1,1,false), +(7,14181,1,1,false), +(7,14182,1,1,false), +(7,14183,1,1,false), +(7,14196,1,3,false), +(7,14195,1,3,false), +(7,14193,1,3,false), +(7,14192,1,3,false), +(7,14407,1,3,false), +(7,14414,1,3,false), +(7,14406,1,3,false), +(7,14413,1,3,false), +(7,14416,1,3,false), +(7,14549,1,3,false), +(7,14550,1,3,false), +(7,14502,1,3,false), +(7,14507,1,3,false), +(7,14501,1,3,false), +(7,14506,1,3,false), +(7,14500,1,3,false), +(7,14505,1,3,false), +(7,14498,1,3,false), +(7,14659,1,3,false), +(7,14660,1,3,false), +(7,14657,1,1,false), +(7,14658,1,1,false), +(7,11420,1,3,false), +(7,14704,1,3,false), +(7,11288,1,1,false), +(7,11289,1,1,false), +(7,11290,1,1,false), +(7,11291,1,1,false), +(7,10750,1,3,false), +(7,14705,1,3,false), +(7,10633,1,1,false), +(7,10634,1,1,false), +(7,10635,1,1,false), +(7,10636,1,1,false), +(7,14662,1,3,false), +(7,14663,1,3,false), +(7,14665,1,3,false), +(7,14666,1,3,false), +(7,14667,1,3,false), +(7,14668,1,3,false), +(7,14669,1,3,false), +(7,14670,1,3,false), +(7,14671,1,3,false), +(7,14672,1,3,false), +(7,14673,1,3,false), +(7,14674,1,3,false), +(7,14675,1,3,false), +(7,14676,1,3,false), +(7,14677,1,3,false), +(7,14678,1,3,false), +(7,14679,1,3,false), +(7,14680,1,3,false), +(7,14681,1,3,false), +(7,14682,1,3,false), +(7,14683,1,3,false), +(7,14684,1,3,false), +(7,14685,1,3,false), +(7,14686,1,3,false), +(7,14687,1,3,false), +(7,14688,1,3,false), +(7,14689,1,3,false), +(7,14690,1,3,false), +(7,14691,1,3,false), +(7,14692,1,3,false), +(7,14693,1,3,false), +(7,14694,1,3,false), +(7,14695,1,3,false), +(7,14696,1,3,false), +(7,14697,1,3,false), +(7,14698,1,3,false), +(7,14699,1,3,false), +(7,14700,1,3,false), +(7,14314,1,3,false), +(7,14503,1,3,false), +(7,14510,1,3,false), +(7,14904,1,3,false), +(7,14906,1,3,false), +(7,14910,1,1,false), +(7,14912,1,1,false), +(7,14905,1,3,false), +(7,14907,1,3,false), +(7,14911,1,1,false), +(7,14909,1,1,false), +(7,14855,1,3,false), +(7,14894,1,3,false), +(7,14913,1,3,false), +(7,14914,1,3,false), +(7,14891,1,3,false), +(7,14895,1,3,false), +(7,15027,1,3,false), +(7,15028,1,3,false), +(7,15026,1,1,false), +(7,15025,1,1,false), +(7,15024,1,1,false), +(7,15023,1,1,false), +(7,15064,1,3,false), +(7,15065,1,3,false), +(7,15030,1,3,false), +(7,15031,1,3,false), +(7,15062,1,3,false), +(7,15063,1,3,false), +(7,15066,1,3,false), +(7,15067,1,3,false), +(7,15061,1,3,false), +(7,15060,1,3,false), +(7,1227,1,2,false), +(7,13176,1,2,false), +(7,4360,1,2,false), +(7,4358,1,1,false), +(7,15118,1,3,false), +(7,15119,1,3,false), +(7,15113,1,3,false), +(7,15114,1,3,false), +(7,15115,1,3,false), +(7,15116,1,3,false), +(7,15220,1,3,false), +(7,15221,1,3,false), +(7,14126,1,3,false), +(7,15222,1,3,false), +(7,15223,1,3,false), +(7,15224,1,3,false), +(7,15225,1,3,false), +(7,15524,1,3,false), +(7,15525,1,3,false), +(7,15507,1,3,false), +(7,15508,1,3,false), +(7,15285,1,3,false), +(7,15286,1,3,false), +(7,15281,1,1,false), +(7,15282,1,1,false), +(7,15283,1,1,false), +(7,15284,1,1,false), +(7,15776,1,3,false), +(7,15777,1,3,false), +(7,15774,1,3,false), +(7,15775,1,3,false), +(7,15823,1,3,false), +(7,15824,1,3,false), +(7,15343,1,3,false), +(7,15342,1,3,false), +(7,15341,1,3,false), +(7,15340,1,3,false), +(7,15339,1,3,false), +(7,15338,1,3,false), +(7,15337,1,3,false), +(7,15336,1,3,false), +(7,15335,1,3,false), +(7,15334,1,3,false), +(7,15333,1,3,false), +(7,15332,1,3,false), +(7,15331,1,3,false), +(7,15330,1,3,false), +(7,15329,1,3,false), +(7,15328,1,3,false), +(7,15327,1,3,false), +(7,15326,1,3,false), +(7,15325,1,3,false), +(7,15324,1,3,false), +(7,15323,1,3,false), +(7,15322,1,3,false), +(7,15321,1,3,false), +(7,15314,1,3,false), +(7,15312,1,3,false), +(7,15311,1,3,false), +(7,15306,1,3,false), +(7,15307,1,3,false), +(7,15308,1,3,false), +(7,15309,1,3,false), +(7,15310,1,3,false), +(7,15305,1,3,false), +(7,15304,1,3,false), +(7,15303,1,3,false), +(7,15302,1,3,false), +(7,15301,1,3,false), +(7,15300,1,3,false), +(7,15299,1,3,false), +(7,15298,1,3,false), +(7,15297,1,3,false), +(7,15296,1,3,false), +(7,15295,1,3,false), +(7,15293,1,3,false), +(7,15294,1,3,false), +(7,15292,1,3,false), +(7,15291,1,3,false), +(7,15290,1,3,false), +(7,15289,1,3,false), +(7,15315,1,3,false), +(7,15316,1,3,false), +(7,15317,1,3,false), +(7,15318,1,3,false), +(7,15319,1,3,false), +(7,15320,1,3,false), +(7,15819,1,3,false), +(7,15820,1,3,false), +(7,15821,1,3,false), +(7,15822,1,3,false), +(7,16450,1,3,false), +(7,16451,1,3,false), +(7,16459,1,1,false), +(7,16460,1,1,false), +(7,16461,1,1,false), +(7,16462,1,1,false), +(7,16463,1,1,false), +(7,16464,1,1,false), +(7,16465,1,1,false), +(7,16466,1,1,false), +(7,16467,1,1,false), +(7,16468,1,1,false), +(7,16469,1,1,false), +(7,16470,1,1,false), +(7,16471,1,1,false), +(7,16472,1,1,false), +(7,16454,1,3,false), +(7,16455,1,3,false), +(7,16442,1,3,false), +(7,16443,1,3,false), +(7,16342,1,3,false), +(7,16343,1,3,false), +(7,16444,1,3,false), +(7,16445,1,3,false), +(7,16344,1,3,false), +(7,16345,1,3,false), +(7,16352,1,3,false), +(7,16353,1,3,false), +(7,16446,1,3,false), +(7,16447,1,3,false), +(7,16448,1,3,false), +(7,16449,1,3,false), +(7,16348,1,3,false), +(7,16349,1,3,false); + +END; \ No newline at end of file diff --git a/server/migrations/seed/FestaDefaults.sql b/server/migrations/seed/FestaDefaults.sql new file mode 100644 index 000000000..b8a3d46fc --- /dev/null +++ b/server/migrations/seed/FestaDefaults.sql @@ -0,0 +1,260 @@ +BEGIN; + +-- Ripped prizes +INSERT INTO public.festa_prizes + (type, tier, souls_req, item_id, num_item) +VALUES + ('personal', 1, 1, 9647, 7), + ('personal', 2, 1, 9647, 7), + ('personal', 3, 1, 9647, 7), + ('personal', 1, 200, 11284, 4), + ('personal', 2, 200, 11284, 4), + ('personal', 3, 200, 11284, 4), + ('personal', 1, 400, 11381, 3), + ('personal', 2, 400, 11381, 3), + ('personal', 3, 400, 11381, 3), + ('personal', 1, 600, 11284, 8), + ('personal', 2, 600, 11284, 8), + ('personal', 3, 600, 11284, 8), + ('personal', 1, 800, 11384, 3), + ('personal', 2, 800, 11384, 3), + ('personal', 3, 800, 11384, 3), + ('personal', 1, 1000, 11284, 12), + ('personal', 2, 1000, 11284, 12), + ('personal', 3, 1000, 11284, 12), + ('personal', 1, 1200, 11381, 5), + ('personal', 2, 1200, 11381, 5), + ('personal', 3, 1200, 11381, 5), + ('personal', 1, 1400, 11284, 16), + ('personal', 2, 1400, 11284, 16), + ('personal', 3, 1400, 11284, 16), + ('personal', 1, 1700, 11384, 5), + ('personal', 2, 1700, 11384, 5), + ('personal', 3, 1700, 11384, 5), + ('personal', 1, 2000, 11284, 16), + ('personal', 2, 2000, 11284, 16), + ('personal', 3, 2000, 11284, 16), + ('personal', 1, 2500, 11382, 4), + ('personal', 2, 2500, 11382, 4), + ('personal', 3, 2500, 11382, 4), + ('personal', 1, 3000, 11284, 24), + ('personal', 2, 3000, 11284, 24), + ('personal', 3, 3000, 11284, 24), + ('personal', 1, 4000, 11385, 4), + ('personal', 2, 4000, 11385, 4), + ('personal', 3, 4000, 11385, 4), + ('personal', 1, 5000, 11381, 11), + ('personal', 2, 5000, 11381, 11), + ('personal', 3, 5000, 11381, 11), + ('personal', 1, 6000, 5177, 5), + ('personal', 2, 6000, 5177, 5), + ('personal', 3, 6000, 5177, 5), + ('personal', 1, 7000, 11384, 11), + ('personal', 2, 7000, 11384, 11), + ('personal', 3, 7000, 11384, 11), + ('personal', 1, 10000, 11382, 8), + ('personal', 2, 10000, 11382, 8), + ('personal', 3, 10000, 11382, 8), + ('personal', 1, 15000, 11385, 4), + ('personal', 2, 15000, 11385, 4), + ('personal', 3, 15000, 11385, 4), + ('personal', 1, 20000, 11381, 13), + ('personal', 2, 20000, 11381, 13), + ('personal', 3, 20000, 11381, 13), + ('personal', 1, 25000, 11385, 4), + ('personal', 2, 25000, 11385, 4), + ('personal', 3, 25000, 11385, 4), + ('personal', 1, 30000, 11383, 1), + ('personal', 2, 30000, 11383, 1), + ('personal', 3, 30000, 11383, 1); + +INSERT INTO public.festa_prizes +(type, tier, souls_req, item_id, num_item) +VALUES + ('guild', 1, 100, 7468, 5), + ('guild', 2, 100, 7468, 5), + ('guild', 3, 100, 7465, 5), + ('guild', 1, 300, 7469, 5), + ('guild', 2, 300, 7469, 5), + ('guild', 3, 300, 7466, 5), + ('guild', 1, 700, 7470, 5), + ('guild', 2, 700, 7470, 5), + ('guild', 3, 700, 7467, 5), + ('guild', 1, 1500, 13405, 14), + ('guild', 1, 1500, 1520, 3), + ('guild', 2, 1500, 13405, 14), + ('guild', 2, 1500, 1520, 3), + ('guild', 3, 1500, 7011, 3), + ('guild', 3, 1500, 13405, 14), + ('guild', 1, 3000, 10201, 10), + ('guild', 2, 3000, 10201, 10), + ('guild', 3, 3000, 10201, 10), + ('guild', 1, 6000, 13895, 14), + ('guild', 1, 6000, 1520, 6), + ('guild', 2, 6000, 13895, 14), + ('guild', 2, 6000, 1520, 6), + ('guild', 3, 6000, 13895, 14), + ('guild', 3, 6000, 7011, 4), + ('guild', 1, 12000, 13406, 14), + ('guild', 1, 12000, 1520, 9), + ('guild', 2, 12000, 13406, 14), + ('guild', 2, 12000, 1520, 9), + ('guild', 3, 12000, 13406, 14), + ('guild', 3, 12000, 7011, 5), + ('guild', 1, 25000, 10207, 10), + ('guild', 2, 25000, 10207, 10), + ('guild', 3, 25000, 10207, 10), + ('guild', 1, 50000, 1520, 12), + ('guild', 1, 50000, 13896, 14), + ('guild', 2, 50000, 1520, 12), + ('guild', 2, 50000, 13896, 14), + ('guild', 3, 50000, 7011, 6), + ('guild', 3, 50000, 13896, 14), + ('guild', 1, 100000, 10201, 10), + ('guild', 2, 100000, 10201, 10), + ('guild', 3, 100000, 10201, 10), + ('guild', 1, 200000, 13406, 16), + ('guild', 2, 200000, 13406, 16), + ('guild', 3, 200000, 13406, 16), + ('guild', 1, 300000, 13896, 16), + ('guild', 2, 300000, 13896, 16), + ('guild', 3, 300000, 13896, 16), + ('guild', 1, 400000, 10207, 10), + ('guild', 2, 400000, 10207, 10), + ('guild', 3, 400000, 10207, 10), + ('guild', 1, 500000, 13407, 6), + ('guild', 1, 500000, 13897, 6), + ('guild', 2, 500000, 13407, 6), + ('guild', 2, 500000, 13897, 6), + ('guild', 3, 500000, 13407, 6), + ('guild', 3, 500000, 13897, 6); + +-- Ripped trials +INSERT INTO public.festa_trials + (objective, goal_id, times_req, locale_req, reward) +VALUES + (1,27,1,0,1), + (5,53034,0,0,400), + (5,22042,0,0,89), + (5,23397,0,0,89), + (1,28,1,0,1), + (1,68,1,0,1), + (1,6,1,0,2), + (1,38,1,0,2), + (1,20,1,0,3), + (1,39,1,0,4), + (1,48,1,0,4), + (1,67,1,0,4), + (1,93,1,0,4), + (1,22,1,0,5), + (1,52,1,0,5), + (1,101,1,0,5), + (1,1,1,0,5), + (1,37,1,0,5), + (1,15,1,0,5), + (1,45,1,0,5), + (1,74,1,0,5), + (1,78,1,0,5), + (1,103,1,0,5), + (1,51,1,0,6), + (1,17,1,0,6), + (1,21,1,0,6), + (1,92,1,0,6), + (1,47,1,0,7), + (1,46,1,0,7), + (1,26,1,0,7), + (1,14,1,0,7), + (1,11,1,0,7), + (1,44,1,0,8), + (1,43,1,0,8), + (1,49,1,0,8), + (1,40,1,0,8), + (1,76,1,0,8), + (1,89,1,0,8), + (1,94,1,0,8), + (1,96,1,0,8), + (1,75,1,0,8), + (1,91,1,0,8), + (1,53,1,0,9), + (1,80,1,0,9), + (1,42,1,0,9), + (1,79,1,0,9), + (1,81,1,0,10), + (1,41,1,0,10), + (1,82,1,0,10), + (1,90,1,0,10), + (1,149,1,0,10), + (1,85,1,0,11), + (1,95,1,0,11), + (1,121,1,0,11), + (1,142,1,0,11), + (1,141,1,0,11), + (1,146,1,0,12), + (1,147,1,0,12), + (1,148,1,0,12), + (1,151,1,0,12), + (1,152,1,0,12), + (1,159,1,0,12), + (1,153,1,0,12), + (1,162,1,0,12), + (1,111,1,0,13), + (1,110,1,0,13), + (1,112,1,0,13), + (1,109,1,0,14), + (1,169,1,0,15), + (2,33,1,0,6), + (2,104,1,0,8), + (2,119,1,0,8), + (2,120,1,0,8), + (2,54,1,0,8), + (2,59,1,0,8), + (2,64,1,0,8), + (2,65,1,0,8), + (2,99,1,0,9), + (2,83,1,0,9), + (2,84,1,0,10), + (2,77,1,0,10), + (2,106,1,0,10), + (2,55,1,0,10), + (2,58,1,0,10), + (2,7,1,0,10), + (2,50,1,0,11), + (2,131,1,0,11), + (2,129,1,0,11), + (2,140,1,0,11), + (2,122,1,0,11), + (2,126,1,0,11), + (2,127,1,0,11), + (2,128,1,0,11), + (2,130,1,0,11), + (2,139,1,0,11), + (2,144,1,0,11), + (2,150,1,0,11), + (2,158,1,0,11), + (2,164,1,0,15), + (2,165,1,0,15), + (2,2,1,7,15), + (2,36,1,0,15), + (2,71,1,0,15), + (2,108,1,0,15), + (2,116,1,0,15), + (2,107,1,0,15), + (2,154,1,0,17), + (2,166,1,0,17), + (2,170,1,0,18), + (3,31,1,0,1), + (3,8,1,0,3), + (3,123,1,0,8), + (3,105,1,0,9), + (3,125,1,0,11), + (3,115,1,0,12), + (3,114,1,0,12), + (3,161,1,0,12), + (4,670,1,0,1), + (4,671,1,0,1), + (4,672,1,0,1), + (4,675,1,0,1), + (4,673,1,0,1), + (4,674,1,0,1); + +END; \ No newline at end of file diff --git a/server/migrations/seed/GachaDemo.sql b/server/migrations/seed/GachaDemo.sql new file mode 100644 index 000000000..b32c1c3ac --- /dev/null +++ b/server/migrations/seed/GachaDemo.sql @@ -0,0 +1,102 @@ +BEGIN; + +-- Start Normal Demo +INSERT INTO gacha_shop (min_gr, min_hr, name, url_banner, url_feature, url_thumbnail, wide, recommended, gacha_type, hidden) + VALUES (0, 0, 'Normal Demo', + 'http://img4.imagetitan.com/img4/QeRWNAviFD8UoTx/26/26_template_innerbanner.png', + 'http://img4.imagetitan.com/img4/QeRWNAviFD8UoTx/26/26_template_feature.png', + 'http://img4.imagetitan.com/img4/small/26/26_template_outerbanner.png', + false, false, 0, false); + +-- Create two different 'rolls', the first rolls once for 1z, the second rolls eleven times for 10z +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) +VALUES + ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 0, 10, 1, 0, 0, 0, 1, 0, 0), + ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 1, 10, 10, 0, 0, 0, 11, 0, 0); + +-- Creates a prize of 1z with a weighted chance of 100 +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 100, 0, 0, 0, 100, 0, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 1, 0); + +-- Creates a prize of 2z with a weighted chance of 70 +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 100, 0, 0, 0, 70, 1, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 2, 0); + +-- Creates a prize of 3z with a weighted chance of 10 +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 100, 0, 0, 0, 10, 2, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 3, 0); +-- End Normal Demo + +-- Start Step-Up Demo +INSERT INTO gacha_shop (min_gr, min_hr, name, url_banner, url_feature, url_thumbnail, wide, recommended, gacha_type, hidden) +VALUES (0, 0, 'Step-Up Demo', '', '', '', false, false, 1, false); + +-- Create two 'steps', the first costs 1z, the second costs 2z +-- The first step has zero rolls so it will only give the prizes directly linked to the entry ID, being 1z +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 0, 10, 1, 0, 0, 0, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 1, 0); + +-- The second step has one roll on the random prize list as will as the direct prize, being 3z +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 1, 10, 2, 0, 0, 0, 1, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 3, 0); + +-- Set up two random prizes, the first gives 1z, the second gives 2z +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 100, 0, 0, 0, 100, 0, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 1, 0); + +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 100, 0, 0, 0, 90, 1, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 2, 0); +-- End Step-Up Demo + +-- Start Box Demo +INSERT INTO gacha_shop (min_gr, min_hr, name, url_banner, url_feature, url_thumbnail, wide, recommended, gacha_type, hidden) +VALUES (0, 0, 'Box Demo', '', '', '', false, false, 4, false); + +-- Create two different 'rolls', the first rolls once for 1z, the second rolls twice for 2z +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) +VALUES + ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 0, 10, 1, 0, 0, 0, 1, 0, 0), + ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 1, 10, 2, 0, 0, 0, 2, 0, 0); + +-- Create five different 'Box' items, weight is always 0 for these +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 100, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 1, 0); + +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 100, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 1, 0); + +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 100, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 1, 0); + +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 100, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 2, 0); + +INSERT INTO gacha_entries (gacha_id, entry_type, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points) + VALUES ((SELECT id FROM gacha_shop ORDER BY id DESC LIMIT 1), 100, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO gacha_items (entry_id, item_type, item_id, quantity) + VALUES ((SELECT id FROM gacha_entries ORDER BY id DESC LIMIT 1), 10, 3, 0); +-- End Box Demo + +END; \ No newline at end of file diff --git a/server/migrations/seed/NetcafeDefaults.sql b/server/migrations/seed/NetcafeDefaults.sql new file mode 100644 index 000000000..dd0b101b2 --- /dev/null +++ b/server/migrations/seed/NetcafeDefaults.sql @@ -0,0 +1,15 @@ +BEGIN; + +TRUNCATE public.cafebonus; + +INSERT INTO public.cafebonus (time_req, item_type, item_id, quantity) +VALUES + (1800, 17, 0, 50), + (3600, 17, 0, 100), + (7200, 17, 0, 200), + (10800, 17, 0, 300), + (18000, 17, 0, 350), + (28800, 17, 0, 500), + (43200, 17, 0, 500); + +END; \ No newline at end of file diff --git a/server/migrations/seed/OtherShops.sql b/server/migrations/seed/OtherShops.sql new file mode 100644 index 000000000..3c88bb896 --- /dev/null +++ b/server/migrations/seed/OtherShops.sql @@ -0,0 +1,48 @@ +BEGIN; + +INSERT INTO public.shop_items +(shop_type, shop_id, item_id, cost, quantity, min_hr, min_sr, min_gr, store_level, max_quantity, road_floors, road_fatalis) +VALUES + (5,5,16516,100,1,0,0,1,0,0,0,0), + (5,5,16517,100,1,0,0,1,0,0,0,0), + (6,5,9958,3,3,1,0,0,0,0,0,0), + (6,5,1897,3,1,1,0,0,0,0,0,0), + (6,5,8889,3,1,0,0,1,0,0,0,0), + (6,5,6176,3,6,1,0,0,0,0,0,0), + (6,5,1472,3,10,1,0,0,0,0,0,0), + (6,5,7280,3,3,0,0,1,0,0,0,0), + (6,5,8027,3,30,1,0,0,0,0,0,0), + (6,5,8028,3,30,1,0,0,0,0,0,0), + (6,5,8029,3,30,1,0,0,0,0,0,0), + (6,5,8026,3,30,1,0,0,0,0,0,0), + (6,5,8030,3,30,1,0,0,0,0,0,0), + (6,5,4353,3,30,1,0,0,0,0,0,0), + (6,5,4354,3,30,1,0,0,0,0,0,0), + (6,5,4355,3,30,1,0,0,0,0,0,0), + (6,5,4356,3,30,1,0,0,0,0,0,0), + (6,5,4357,3,30,1,0,0,0,0,0,0), + (6,5,4745,3,30,1,0,0,0,0,0,0), + (6,5,4746,3,30,1,0,0,0,0,0,0), + (6,5,4747,3,30,1,0,0,0,0,0,0), + (6,5,4748,3,30,1,0,0,0,0,0,0), + (6,5,4749,3,30,1,0,0,0,0,0,0), + (6,5,5122,3,30,1,0,0,0,0,0,0), + (6,5,5123,3,30,1,0,0,0,0,0,0), + (6,5,5124,3,30,1,0,0,0,0,0,0), + (6,5,5125,3,30,1,0,0,0,0,0,0), + (6,5,5126,3,30,1,0,0,0,0,0,0), + (6,5,5795,3,30,1,0,0,0,0,0,0), + (6,5,5796,3,30,1,0,0,0,0,0,0), + (6,5,5797,3,30,1,0,0,0,0,0,0), + (6,5,5798,3,30,1,0,0,0,0,0,0), + (6,5,5799,3,30,1,0,0,0,0,0,0), + (6,5,6168,3,30,1,0,0,0,0,0,0), + (6,5,6169,3,30,1,0,0,0,0,0,0), + (6,5,6170,3,30,1,0,0,0,0,0,0), + (6,5,6171,3,30,1,0,0,0,0,0,0), + (6,5,6172,3,30,1,0,0,0,0,0,0), + (7,0,13190,10,1,0,0,0,0,0,0,0), + (7,0,1662,10,1,0,0,0,0,0,0,0), + (7,0,10179,100,1,0,0,0,0,0,0,0); + +END; \ No newline at end of file diff --git a/server/migrations/seed/RoadShopItems.sql b/server/migrations/seed/RoadShopItems.sql new file mode 100644 index 000000000..31c157344 --- /dev/null +++ b/server/migrations/seed/RoadShopItems.sql @@ -0,0 +1,868 @@ +BEGIN; + +INSERT INTO public.shop_items +(shop_type, shop_id, item_id, cost, quantity, min_hr, min_sr, min_gr, store_level, max_quantity, road_floors, road_fatalis) +VALUES + (10,4,11664,20000,1,0,0,1,1,0,0,0), + (10,4,11665,20000,1,0,0,1,1,0,0,0), + (10,4,11666,20000,1,0,0,1,1,0,0,0), + (10,4,11667,20000,1,0,0,1,1,0,0,0), + (10,4,11668,20000,1,0,0,1,1,0,0,0), + (10,4,11669,20000,1,0,0,1,1,0,0,0), + (10,4,11670,20000,1,0,0,1,1,0,0,0), + (10,4,11671,20000,1,0,0,1,1,0,0,0), + (10,4,11672,20000,1,0,0,1,1,0,0,0), + (10,4,11673,20000,1,0,0,1,1,0,0,0), + (10,4,11674,20000,1,0,0,1,1,0,0,0), + (10,4,11675,20000,1,0,0,1,1,0,0,0), + (10,4,11676,20000,1,0,0,1,1,0,0,0), + (10,4,11677,20000,1,0,0,1,1,0,0,0), + (10,4,11678,20000,1,0,0,1,1,0,0,0), + (10,4,11679,20000,1,0,0,1,1,0,0,0), + (10,4,11680,20000,1,0,0,1,1,0,0,0), + (10,4,11681,20000,1,0,0,1,1,0,0,0), + (10,4,11682,20000,1,0,0,1,1,0,0,0), + (10,4,11683,20000,1,0,0,1,1,0,0,0), + (10,4,11684,20000,1,0,0,1,1,0,0,0), + (10,4,11685,20000,1,0,0,1,1,0,0,0), + (10,4,11686,20000,1,0,0,1,1,0,0,0), + (10,4,11687,20000,1,0,0,1,1,0,0,0), + (10,4,11688,20000,1,0,0,1,1,0,0,0), + (10,4,11689,20000,1,0,0,1,1,0,0,0), + (10,4,11690,20000,1,0,0,1,1,0,0,0), + (10,4,11691,20000,1,0,0,1,1,0,0,0), + (10,4,11692,20000,1,0,0,1,1,0,0,0), + (10,4,11693,20000,1,0,0,1,1,0,0,0), + (10,4,11694,20000,1,0,0,1,1,0,0,0), + (10,4,11695,20000,1,0,0,1,1,0,0,0), + (10,4,11696,20000,1,0,0,1,1,0,0,0), + (10,4,11697,20000,1,0,0,1,1,0,0,0), + (10,4,12893,20000,1,0,0,1,1,0,0,0), + (10,4,12894,20000,1,0,0,1,1,0,0,0), + (10,4,12895,20000,1,0,0,1,1,0,0,0), + (10,4,12896,20000,1,0,0,1,1,0,0,0), + (10,4,12897,20000,1,0,0,1,1,0,0,0), + (10,4,12898,20000,1,0,0,1,1,0,0,0), + (10,4,12899,20000,1,0,0,1,1,0,0,0), + (10,4,14337,20000,1,0,0,1,1,0,0,0), + (10,4,14338,20000,1,0,0,1,1,0,0,0), + (10,4,14339,20000,1,0,0,1,1,0,0,0), + (10,4,14340,20000,1,0,0,1,1,0,0,0), + (10,4,14341,20000,1,0,0,1,1,0,0,0), + (10,4,14342,20000,1,0,0,1,1,0,0,0), + (10,4,14343,20000,1,0,0,1,1,0,0,0), + (10,4,14344,20000,1,0,0,1,1,0,0,0), + (10,4,14345,20000,1,0,0,1,1,0,0,0), + (10,4,9254,10000,1,0,0,1,1,0,0,0), + (10,4,9255,10000,1,0,0,1,1,0,0,0), + (10,4,9256,10000,1,0,0,1,1,0,0,0), + (10,4,9257,10000,1,0,0,1,1,0,0,0), + (10,4,9258,10000,1,0,0,1,1,0,0,0), + (10,4,9259,10000,1,0,0,1,1,0,0,0), + (10,4,9260,10000,1,0,0,1,1,0,0,0), + (10,4,9261,10000,1,0,0,1,1,0,0,0), + (10,4,9262,10000,1,0,0,1,1,0,0,0), + (10,4,9263,10000,1,0,0,1,1,0,0,0), + (10,4,9264,10000,1,0,0,1,1,0,0,0), + (10,4,9265,10000,1,0,0,1,1,0,0,0), + (10,4,9266,10000,1,0,0,1,1,0,0,0), + (10,4,9267,10000,1,0,0,1,1,0,0,0), + (10,4,9268,10000,1,0,0,1,1,0,0,0), + (10,4,9269,10000,1,0,0,1,1,0,0,0), + (10,4,9270,10000,1,0,0,1,1,0,0,0), + (10,4,9271,10000,1,0,0,1,1,0,0,0), + (10,4,9272,10000,1,0,0,1,1,0,0,0), + (10,4,9273,10000,1,0,0,1,1,0,0,0), + (10,4,9274,10000,1,0,0,1,1,0,0,0), + (10,4,9275,10000,1,0,0,1,1,0,0,0), + (10,4,9276,10000,1,0,0,1,1,0,0,0), + (10,4,9277,10000,1,0,0,1,1,0,0,0), + (10,4,9278,10000,1,0,0,1,1,0,0,0), + (10,4,9279,10000,1,0,0,1,1,0,0,0), + (10,4,9280,10000,1,0,0,1,1,0,0,0), + (10,4,9281,10000,1,0,0,1,1,0,0,0), + (10,4,9282,10000,1,0,0,1,1,0,0,0), + (10,4,9283,10000,1,0,0,1,1,0,0,0), + (10,4,9284,10000,1,0,0,1,1,0,0,0), + (10,4,9285,10000,1,0,0,1,1,0,0,0), + (10,4,9286,10000,1,0,0,1,1,0,0,0), + (10,4,9287,10000,1,0,0,1,1,0,0,0), + (10,4,9288,10000,1,0,0,1,1,0,0,0), + (10,4,9289,10000,1,0,0,1,1,0,0,0), + (10,4,9290,10000,1,0,0,1,1,0,0,0), + (10,4,9291,10000,1,0,0,1,1,0,0,0), + (10,4,9292,10000,1,0,0,1,1,0,0,0), + (10,4,9293,10000,1,0,0,1,1,0,0,0), + (10,4,9294,10000,1,0,0,1,1,0,0,0), + (10,4,9295,10000,1,0,0,1,1,0,0,0), + (10,4,9296,10000,1,0,0,1,1,0,0,0), + (10,4,9297,10000,1,0,0,1,1,0,0,0), + (10,4,9298,10000,1,0,0,1,1,0,0,0), + (10,4,9299,10000,1,0,0,1,1,0,0,0), + (10,4,9300,10000,1,0,0,1,1,0,0,0), + (10,4,9301,10000,1,0,0,1,1,0,0,0), + (10,4,13196,10000,1,0,0,1,1,0,0,0), + (10,4,13197,10000,1,0,0,1,1,0,0,0), + (10,4,13198,10000,1,0,0,1,1,0,0,0), + (10,4,13199,10000,1,0,0,1,1,0,0,0), + (10,4,15542,10000,1,0,0,1,1,0,0,0), + (10,4,15543,10000,1,0,0,1,1,0,0,0), + (10,4,15544,10000,1,0,0,1,1,0,0,0), + (10,4,15545,10000,1,0,0,1,1,0,0,0), + (10,4,13640,20000,1,0,0,1,1,0,0,0), + (10,4,13641,20000,1,0,0,1,1,0,0,0), + (10,4,13642,20000,1,0,0,1,1,0,0,0), + (10,4,13643,20000,1,0,0,1,1,0,0,0), + (10,4,13644,20000,1,0,0,1,1,0,0,0), + (10,4,13645,20000,1,0,0,1,1,0,0,0), + (10,4,13646,20000,1,0,0,1,1,0,0,0), + (10,4,13647,20000,1,0,0,1,1,0,0,0), + (10,4,13648,20000,1,0,0,1,1,0,0,0), + (10,4,13649,20000,1,0,0,1,1,0,0,0), + (10,4,13650,20000,1,0,0,1,1,0,0,0), + (10,4,13651,20000,1,0,0,1,1,0,0,0), + (10,4,13652,20000,1,0,0,1,1,0,0,0), + (10,4,13653,20000,1,0,0,1,1,0,0,0), + (10,4,13654,20000,1,0,0,1,1,0,0,0), + (10,4,13655,20000,1,0,0,1,1,0,0,0), + (10,4,13656,20000,1,0,0,1,1,0,0,0), + (10,4,13657,20000,1,0,0,1,1,0,0,0), + (10,4,13658,20000,1,0,0,1,1,0,0,0), + (10,4,13659,20000,1,0,0,1,1,0,0,0), + (10,4,13660,20000,1,0,0,1,1,0,0,0), + (10,4,13661,20000,1,0,0,1,1,0,0,0), + (10,4,13662,20000,1,0,0,1,1,0,0,0), + (10,4,13663,20000,1,0,0,1,1,0,0,0), + (10,4,13664,20000,1,0,0,1,1,0,0,0), + (10,4,13665,20000,1,0,0,1,1,0,0,0), + (10,4,13666,20000,1,0,0,1,1,0,0,0), + (10,4,13667,20000,1,0,0,1,1,0,0,0), + (10,4,13668,20000,1,0,0,1,1,0,0,0), + (10,4,13669,20000,1,0,0,1,1,0,0,0), + (10,4,13670,20000,1,0,0,1,1,0,0,0), + (10,4,13671,20000,1,0,0,1,1,0,0,0), + (10,4,13672,20000,1,0,0,1,1,0,0,0), + (10,4,13673,20000,1,0,0,1,1,0,0,0), + (10,4,13674,20000,1,0,0,1,1,0,0,0), + (10,4,13675,20000,1,0,0,1,1,0,0,0), + (10,4,13676,20000,1,0,0,1,1,0,0,0), + (10,4,13677,20000,1,0,0,1,1,0,0,0), + (10,4,13678,20000,1,0,0,1,1,0,0,0), + (10,4,13679,20000,1,0,0,1,1,0,0,0), + (10,4,13680,20000,1,0,0,1,1,0,0,0), + (10,4,13681,20000,1,0,0,1,1,0,0,0), + (10,4,13682,20000,1,0,0,1,1,0,0,0), + (10,4,13683,20000,1,0,0,1,1,0,0,0), + (10,4,13684,20000,1,0,0,1,1,0,0,0), + (10,4,13685,20000,1,0,0,1,1,0,0,0), + (10,4,13686,20000,1,0,0,1,1,0,0,0), + (10,4,13687,20000,1,0,0,1,1,0,0,0), + (10,4,13688,20000,1,0,0,1,1,0,0,0), + (10,4,13689,20000,1,0,0,1,1,0,0,0), + (10,4,13690,20000,1,0,0,1,1,0,0,0), + (10,4,13691,20000,1,0,0,1,1,0,0,0), + (10,4,15546,20000,1,0,0,1,1,0,0,0), + (10,4,15547,20000,1,0,0,1,1,0,0,0), + (10,4,15548,20000,1,0,0,1,1,0,0,0), + (10,4,15549,20000,1,0,0,1,1,0,0,0), + (10,4,16162,35000,1,0,0,1,1,0,0,0), + (10,4,16163,35000,1,0,0,1,1,0,0,0), + (10,4,16164,35000,1,0,0,1,1,0,0,0), + (10,4,16165,35000,1,0,0,1,1,0,0,0), + (10,4,16166,35000,1,0,0,1,1,0,0,0), + (10,4,16167,35000,1,0,0,1,1,0,0,0), + (10,4,16168,35000,1,0,0,1,1,0,0,0), + (10,4,16169,35000,1,0,0,1,1,0,0,0), + (10,4,16172,35000,1,0,0,1,1,0,0,0), + (10,4,16173,35000,1,0,0,1,1,0,0,0), + (10,4,16174,35000,1,0,0,1,1,0,0,0), + (10,4,16175,35000,1,0,0,1,1,0,0,0), + (10,4,16176,35000,1,0,0,1,1,0,0,0), + (10,4,16177,35000,1,0,0,1,1,0,0,0), + (10,4,16178,35000,1,0,0,1,1,0,0,0), + (10,4,16179,35000,1,0,0,1,1,0,0,0), + (10,4,16182,35000,1,0,0,1,1,0,0,0), + (10,4,16183,35000,1,0,0,1,1,0,0,0), + (10,4,16184,35000,1,0,0,1,1,0,0,0), + (10,4,16185,35000,1,0,0,1,1,0,0,0), + (10,4,16186,35000,1,0,0,1,1,0,0,0), + (10,4,16187,35000,1,0,0,1,1,0,0,0), + (10,4,16188,35000,1,0,0,1,1,0,0,0), + (10,4,16189,35000,1,0,0,1,1,0,0,0), + (10,4,16192,35000,1,0,0,1,1,0,0,0), + (10,4,16193,35000,1,0,0,1,1,0,0,0), + (10,4,16194,35000,1,0,0,1,1,0,0,0), + (10,4,16195,35000,1,0,0,1,1,0,0,0), + (10,4,16196,35000,1,0,0,1,1,0,0,0), + (10,4,16197,35000,1,0,0,1,1,0,0,0), + (10,4,16198,35000,1,0,0,1,1,0,0,0), + (10,4,16199,35000,1,0,0,1,1,0,0,0), + (10,4,16202,35000,1,0,0,1,1,0,0,0), + (10,4,16203,35000,1,0,0,1,1,0,0,0), + (10,4,16204,35000,1,0,0,1,1,0,0,0), + (10,4,16205,35000,1,0,0,1,1,0,0,0), + (10,4,16206,35000,1,0,0,1,1,0,0,0), + (10,4,16207,35000,1,0,0,1,1,0,0,0), + (10,4,16208,35000,1,0,0,1,1,0,0,0), + (10,4,16209,35000,1,0,0,1,1,0,0,0), + (10,4,16212,35000,1,0,0,1,1,0,0,0), + (10,4,16213,35000,1,0,0,1,1,0,0,0), + (10,4,16214,35000,1,0,0,1,1,0,0,0), + (10,4,16215,35000,1,0,0,1,1,0,0,0), + (10,4,16216,35000,1,0,0,1,1,0,0,0), + (10,4,16217,35000,1,0,0,1,1,0,0,0), + (10,4,16218,35000,1,0,0,1,1,0,0,0), + (10,4,16219,35000,1,0,0,1,1,0,0,0), + (10,4,16222,35000,1,0,0,1,1,0,0,0), + (10,4,16223,35000,1,0,0,1,1,0,0,0), + (10,4,16224,35000,1,0,0,1,1,0,0,0), + (10,4,16225,35000,1,0,0,1,1,0,0,0), + (10,4,16226,35000,1,0,0,1,1,0,0,0), + (10,4,16227,35000,1,0,0,1,1,0,0,0), + (10,4,16228,35000,1,0,0,1,1,0,0,0), + (10,4,16229,35000,1,0,0,1,1,0,0,0), + (10,4,16232,35000,1,0,0,1,1,0,0,0), + (10,4,16233,35000,1,0,0,1,1,0,0,0), + (10,4,16234,35000,1,0,0,1,1,0,0,0), + (10,4,16235,35000,1,0,0,1,1,0,0,0), + (10,4,16236,35000,1,0,0,1,1,0,0,0), + (10,4,16237,35000,1,0,0,1,1,0,0,0), + (10,4,16238,35000,1,0,0,1,1,0,0,0), + (10,4,16239,35000,1,0,0,1,1,0,0,0), + (10,4,16242,35000,1,0,0,1,1,0,0,0), + (10,4,16243,35000,1,0,0,1,1,0,0,0), + (10,4,16244,35000,1,0,0,1,1,0,0,0), + (10,4,16245,35000,1,0,0,1,1,0,0,0), + (10,4,16246,35000,1,0,0,1,1,0,0,0), + (10,4,16247,35000,1,0,0,1,1,0,0,0), + (10,4,16248,35000,1,0,0,1,1,0,0,0), + (10,4,16249,35000,1,0,0,1,1,0,0,0), + (10,4,16252,35000,1,0,0,1,1,0,0,0), + (10,4,16253,35000,1,0,0,1,1,0,0,0), + (10,4,16254,35000,1,0,0,1,1,0,0,0), + (10,4,16255,35000,1,0,0,1,1,0,0,0), + (10,4,16256,35000,1,0,0,1,1,0,0,0), + (10,4,16257,35000,1,0,0,1,1,0,0,0), + (10,4,16258,35000,1,0,0,1,1,0,0,0), + (10,4,16259,35000,1,0,0,1,1,0,0,0), + (10,4,16262,35000,1,0,0,1,1,0,0,0), + (10,4,16263,35000,1,0,0,1,1,0,0,0), + (10,4,16264,35000,1,0,0,1,1,0,0,0), + (10,4,16265,35000,1,0,0,1,1,0,0,0), + (10,4,16266,35000,1,0,0,1,1,0,0,0), + (10,4,16267,35000,1,0,0,1,1,0,0,0), + (10,4,16268,35000,1,0,0,1,1,0,0,0), + (10,4,16269,35000,1,0,0,1,1,0,0,0), + (10,4,16272,35000,1,0,0,1,1,0,0,0), + (10,4,16273,35000,1,0,0,1,1,0,0,0), + (10,4,16274,35000,1,0,0,1,1,0,0,0), + (10,4,16275,35000,1,0,0,1,1,0,0,0), + (10,4,16276,35000,1,0,0,1,1,0,0,0), + (10,4,16277,35000,1,0,0,1,1,0,0,0), + (10,4,16278,35000,1,0,0,1,1,0,0,0), + (10,4,16279,35000,1,0,0,1,1,0,0,0), + (10,4,16282,35000,1,0,0,1,1,0,0,0), + (10,4,16283,35000,1,0,0,1,1,0,0,0), + (10,4,16284,35000,1,0,0,1,1,0,0,0), + (10,4,16285,35000,1,0,0,1,1,0,0,0), + (10,4,16286,35000,1,0,0,1,1,0,0,0), + (10,4,16287,35000,1,0,0,1,1,0,0,0), + (10,4,16288,35000,1,0,0,1,1,0,0,0), + (10,4,16289,35000,1,0,0,1,1,0,0,0), + (10,4,16292,35000,1,0,0,1,1,0,0,0), + (10,4,16293,35000,1,0,0,1,1,0,0,0), + (10,4,16294,35000,1,0,0,1,1,0,0,0), + (10,4,16295,35000,1,0,0,1,1,0,0,0), + (10,4,16296,35000,1,0,0,1,1,0,0,0), + (10,4,16297,35000,1,0,0,1,1,0,0,0), + (10,4,16298,35000,1,0,0,1,1,0,0,0), + (10,4,16299,35000,1,0,0,1,1,0,0,0), + (10,8,14136,15000,1,0,0,1,1,0,0,0), + (10,8,14137,15000,1,0,0,1,1,0,0,0), + (10,8,14138,15000,1,0,0,1,1,0,0,0), + (10,8,14139,15000,1,0,0,1,1,0,0,0), + (10,8,14140,15000,1,0,0,1,1,0,0,0), + (10,8,14141,15000,1,0,0,1,1,0,0,0), + (10,8,14142,15000,1,0,0,1,1,0,0,0), + (10,8,14143,15000,1,0,0,1,1,0,0,0), + (10,8,14144,15000,1,0,0,1,1,0,0,0), + (10,8,14145,15000,1,0,0,1,1,0,0,0), + (10,8,14454,30000,1,0,0,1,1,0,0,0), + (10,8,14455,30000,1,0,0,1,1,0,0,0), + (10,8,14456,30000,1,0,0,1,1,0,0,0), + (10,8,14457,30000,1,0,0,1,1,0,0,0), + (10,8,14458,30000,1,0,0,1,1,0,0,0), + (10,8,14459,30000,1,0,0,1,1,0,0,0), + (10,8,14460,30000,1,0,0,1,1,0,0,0), + (10,8,14461,30000,1,0,0,1,1,0,0,0), + (10,8,14462,30000,1,0,0,1,1,0,0,0), + (10,8,14463,30000,1,0,0,1,1,0,0,0), + (10,8,12724,50000,1,0,0,1,1,0,0,0), + (10,8,12725,50000,1,0,0,1,1,0,0,0), + (10,8,12726,50000,1,0,0,1,1,0,0,0), + (10,8,12727,50000,1,0,0,1,1,0,0,0), + (10,8,12728,50000,1,0,0,1,1,0,0,0), + (10,8,12729,50000,1,0,0,1,1,0,0,0), + (10,8,12730,50000,1,0,0,1,1,0,0,0), + (10,8,12731,50000,1,0,0,1,1,0,0,0), + (10,8,12732,50000,1,0,0,1,1,0,0,0), + (10,8,12733,50000,1,0,0,1,1,0,0,0), + (10,8,12734,50000,1,0,0,1,1,0,0,0), + (10,8,12735,50000,1,0,0,1,1,0,0,0), + (10,8,12736,50000,1,0,0,1,1,0,0,0), + (10,8,12737,50000,1,0,0,1,1,0,0,0), + (10,8,12738,50000,1,0,0,1,1,0,0,0), + (10,8,12739,50000,1,0,0,1,1,0,0,0), + (10,8,12740,50000,1,0,0,1,1,0,0,0), + (10,8,12741,50000,1,0,0,1,1,0,0,0), + (10,8,12742,50000,1,0,0,1,1,0,0,0), + (10,8,12743,50000,1,0,0,1,1,0,0,0), + (10,8,12744,50000,1,0,0,1,1,0,0,0), + (10,8,12745,50000,1,0,0,1,1,0,0,0), + (10,8,12746,50000,1,0,0,1,1,0,0,0), + (10,8,12747,50000,1,0,0,1,1,0,0,0), + (10,8,12748,50000,1,0,0,1,1,0,0,0), + (10,8,12749,50000,1,0,0,1,1,0,0,0), + (10,8,12750,50000,1,0,0,1,1,0,0,0), + (10,8,12751,50000,1,0,0,1,1,0,0,0), + (10,8,12752,50000,1,0,0,1,1,0,0,0), + (10,8,12753,50000,1,0,0,1,1,0,0,0), + (10,8,15070,50000,1,0,0,1,1,0,0,0), + (10,8,15071,50000,1,0,0,1,1,0,0,0), + (10,8,15072,50000,1,0,0,1,1,0,0,0), + (10,8,15073,50000,1,0,0,1,1,0,0,0), + (10,8,15074,50000,1,0,0,1,1,0,0,0), + (10,8,15075,50000,1,0,0,1,1,0,0,0), + (10,8,15076,50000,1,0,0,1,1,0,0,0), + (10,8,15077,50000,1,0,0,1,1,0,0,0), + (10,8,15078,50000,1,0,0,1,1,0,0,0), + (10,8,15079,50000,1,0,0,1,1,0,0,0), + (10,8,15567,20000,1,0,0,1,1,0,0,0), + (10,8,15568,20000,1,0,0,1,1,0,0,0), + (10,8,15569,20000,1,0,0,1,1,0,0,0), + (10,8,15570,20000,1,0,0,1,1,0,0,0), + (10,8,15571,20000,1,0,0,1,1,0,0,0), + (10,8,15572,20000,1,0,0,1,1,0,0,0), + (10,8,15573,20000,1,0,0,1,1,0,0,0), + (10,8,15574,20000,1,0,0,1,1,0,0,0), + (10,8,15575,20000,1,0,0,1,1,0,0,0), + (10,8,15576,20000,1,0,0,1,1,0,0,0), + (10,8,15577,20000,1,0,0,1,1,0,0,0), + (10,8,15578,20000,1,0,0,1,1,0,0,0), + (10,8,15579,20000,1,0,0,1,1,0,0,0), + (10,8,15580,20000,1,0,0,1,1,0,0,0), + (10,8,15581,20000,1,0,0,1,1,0,0,0), + (10,8,15582,20000,1,0,0,1,1,0,0,0), + (10,8,15583,20000,1,0,0,1,1,0,0,0), + (10,8,15584,20000,1,0,0,1,1,0,0,0), + (10,8,15585,20000,1,0,0,1,1,0,0,0), + (10,8,15586,20000,1,0,0,1,1,0,0,0), + (10,8,15587,20000,1,0,0,1,1,0,0,0), + (10,8,15588,20000,1,0,0,1,1,0,0,0), + (10,8,15589,20000,1,0,0,1,1,0,0,0), + (10,8,15590,20000,1,0,0,1,1,0,0,0), + (10,8,15591,20000,1,0,0,1,1,0,0,0), + (10,8,15592,20000,1,0,0,1,1,0,0,0), + (10,8,15593,20000,1,0,0,1,1,0,0,0), + (10,8,15594,20000,1,0,0,1,1,0,0,0), + (10,8,15595,20000,1,0,0,1,1,0,0,0), + (10,8,15596,20000,1,0,0,1,1,0,0,0), + (10,8,15597,20000,1,0,0,1,1,0,0,0), + (10,8,15598,20000,1,0,0,1,1,0,0,0), + (10,8,15599,20000,1,0,0,1,1,0,0,0), + (10,8,15600,20000,1,0,0,1,1,0,0,0), + (10,8,15601,20000,1,0,0,1,1,0,0,0), + (10,8,15602,20000,1,0,0,1,1,0,0,0), + (10,8,15603,20000,1,0,0,1,1,0,0,0), + (10,8,15604,20000,1,0,0,1,1,0,0,0), + (10,8,15605,20000,1,0,0,1,1,0,0,0), + (10,8,15606,20000,1,0,0,1,1,0,0,0), + (10,8,15607,20000,1,0,0,1,1,0,0,0), + (10,8,15608,20000,1,0,0,1,1,0,0,0), + (10,8,15609,20000,1,0,0,1,1,0,0,0), + (10,8,15610,20000,1,0,0,1,1,0,0,0), + (10,8,15611,20000,1,0,0,1,1,0,0,0), + (10,8,15612,20000,1,0,0,1,1,0,0,0), + (10,8,15613,20000,1,0,0,1,1,0,0,0), + (10,8,15614,20000,1,0,0,1,1,0,0,0), + (10,8,15615,20000,1,0,0,1,1,0,0,0), + (10,8,15616,20000,1,0,0,1,1,0,0,0), + (10,8,15617,20000,1,0,0,1,1,0,0,0), + (10,8,15618,20000,1,0,0,1,1,0,0,0), + (10,8,15619,20000,1,0,0,1,1,0,0,0), + (10,8,15620,20000,1,0,0,1,1,0,0,0), + (10,8,15621,20000,1,0,0,1,1,0,0,0), + (10,8,15622,20000,1,0,0,1,1,0,0,0), + (10,8,15623,20000,1,0,0,1,1,0,0,0), + (10,8,15624,20000,1,0,0,1,1,0,0,0), + (10,8,15625,20000,1,0,0,1,1,0,0,0), + (10,8,15626,20000,1,0,0,1,1,0,0,0), + (10,8,15627,20000,1,0,0,1,1,0,0,0), + (10,8,15628,20000,1,0,0,1,1,0,0,0), + (10,8,15629,20000,1,0,0,1,1,0,0,0), + (10,8,15630,20000,1,0,0,1,1,0,0,0), + (10,8,15631,20000,1,0,0,1,1,0,0,0), + (10,8,15632,20000,1,0,0,1,1,0,0,0), + (10,8,15633,20000,1,0,0,1,1,0,0,0), + (10,8,15634,20000,1,0,0,1,1,0,0,0), + (10,8,15635,20000,1,0,0,1,1,0,0,0), + (10,8,15636,20000,1,0,0,1,1,0,0,0), + (10,8,15637,20000,1,0,0,1,1,0,0,0), + (10,8,15638,20000,1,0,0,1,1,0,0,0), + (10,8,15639,20000,1,0,0,1,1,0,0,0), + (10,8,15640,20000,1,0,0,1,1,0,0,0), + (10,8,15641,20000,1,0,0,1,1,0,0,0), + (10,8,15642,20000,1,0,0,1,1,0,0,0), + (10,8,15643,20000,1,0,0,1,1,0,0,0), + (10,8,15644,20000,1,0,0,1,1,0,0,0), + (10,8,15645,20000,1,0,0,1,1,0,0,0), + (10,8,15646,20000,1,0,0,1,1,0,0,0), + (10,8,15647,20000,1,0,0,1,1,0,0,0), + (10,8,15648,20000,1,0,0,1,1,0,0,0), + (10,8,15649,20000,1,0,0,1,1,0,0,0), + (10,8,15650,20000,1,0,0,1,1,0,0,0), + (10,8,15651,20000,1,0,0,1,1,0,0,0), + (10,8,15652,20000,1,0,0,1,1,0,0,0), + (10,8,15653,20000,1,0,0,1,1,0,0,0), + (10,8,15654,20000,1,0,0,1,1,0,0,0), + (10,8,15655,20000,1,0,0,1,1,0,0,0), + (10,8,15656,20000,1,0,0,1,1,0,0,0), + (10,8,15657,20000,1,0,0,1,1,0,0,0), + (10,8,15658,20000,1,0,0,1,1,0,0,0), + (10,8,15659,20000,1,0,0,1,1,0,0,0), + (10,8,15660,20000,1,0,0,1,1,0,0,0), + (10,8,15661,20000,1,0,0,1,1,0,0,0), + (10,8,15662,20000,1,0,0,1,1,0,0,0), + (10,8,15663,20000,1,0,0,1,1,0,0,0), + (10,8,15664,20000,1,0,0,1,1,0,0,0), + (10,8,15665,20000,1,0,0,1,1,0,0,0), + (10,8,15666,20000,1,0,0,1,1,0,0,0), + (10,8,15667,20000,1,0,0,1,1,0,0,0), + (10,8,15668,20000,1,0,0,1,1,0,0,0), + (10,8,15669,20000,1,0,0,1,1,0,0,0), + (10,8,15670,20000,1,0,0,1,1,0,0,0), + (10,8,15671,20000,1,0,0,1,1,0,0,0), + (10,8,15672,20000,1,0,0,1,1,0,0,0), + (10,8,15673,20000,1,0,0,1,1,0,0,0), + (10,8,15674,20000,1,0,0,1,1,0,0,0), + (10,8,15675,20000,1,0,0,1,1,0,0,0), + (10,8,15676,20000,1,0,0,1,1,0,0,0), + (10,8,15677,20000,1,0,0,1,1,0,0,0), + (10,8,15678,20000,1,0,0,1,1,0,0,0), + (10,8,15679,20000,1,0,0,1,1,0,0,0), + (10,8,15680,20000,1,0,0,1,1,0,0,0), + (10,8,15681,20000,1,0,0,1,1,0,0,0), + (10,8,15682,20000,1,0,0,1,1,0,0,0), + (10,8,15683,20000,1,0,0,1,1,0,0,0), + (10,8,15684,20000,1,0,0,1,1,0,0,0), + (10,8,15685,20000,1,0,0,1,1,0,0,0), + (10,8,15686,20000,1,0,0,1,1,0,0,0), + (10,8,15687,20000,1,0,0,1,1,0,0,0), + (10,8,15688,20000,1,0,0,1,1,0,0,0), + (10,8,15689,20000,1,0,0,1,1,0,0,0), + (10,8,15690,20000,1,0,0,1,1,0,0,0), + (10,8,15691,20000,1,0,0,1,1,0,0,0), + (10,8,15692,20000,1,0,0,1,1,0,0,0), + (10,8,15693,20000,1,0,0,1,1,0,0,0), + (10,8,15694,20000,1,0,0,1,1,0,0,0), + (10,8,15695,20000,1,0,0,1,1,0,0,0), + (10,8,15696,20000,1,0,0,1,1,0,0,0), + (10,8,15697,20000,1,0,0,1,1,0,0,0), + (10,8,15698,20000,1,0,0,1,1,0,0,0), + (10,8,15699,20000,1,0,0,1,1,0,0,0), + (10,8,15700,20000,1,0,0,1,1,0,0,0), + (10,8,15701,20000,1,0,0,1,1,0,0,0), + (10,8,15702,20000,1,0,0,1,1,0,0,0), + (10,8,15703,20000,1,0,0,1,1,0,0,0), + (10,8,15704,20000,1,0,0,1,1,0,0,0), + (10,8,15705,20000,1,0,0,1,1,0,0,0), + (10,8,15706,20000,1,0,0,1,1,0,0,0), + (10,8,15707,20000,1,0,0,1,1,0,0,0), + (10,8,15708,20000,1,0,0,1,1,0,0,0), + (10,8,15709,20000,1,0,0,1,1,0,0,0), + (10,8,15710,20000,1,0,0,1,1,0,0,0), + (10,8,15711,20000,1,0,0,1,1,0,0,0), + (10,8,15712,20000,1,0,0,1,1,0,0,0), + (10,8,15713,20000,1,0,0,1,1,0,0,0), + (10,8,15714,20000,1,0,0,1,1,0,0,0), + (10,8,15715,20000,1,0,0,1,1,0,0,0), + (10,8,15716,20000,1,0,0,1,1,0,0,0), + (10,8,15717,20000,1,0,0,1,1,0,0,0), + (10,8,15718,20000,1,0,0,1,1,0,0,0), + (10,8,15719,20000,1,0,0,1,1,0,0,0), + (10,8,15720,20000,1,0,0,1,1,0,0,0), + (10,8,15721,20000,1,0,0,1,1,0,0,0), + (10,8,15722,20000,1,0,0,1,1,0,0,0), + (10,8,15723,20000,1,0,0,1,1,0,0,0), + (10,8,15724,20000,1,0,0,1,1,0,0,0), + (10,8,15725,20000,1,0,0,1,1,0,0,0), + (10,8,15726,20000,1,0,0,1,1,0,0,0), + (10,8,15727,20000,1,0,0,1,1,0,0,0), + (10,8,15728,20000,1,0,0,1,1,0,0,0), + (10,8,15729,20000,1,0,0,1,1,0,0,0), + (10,8,15730,20000,1,0,0,1,1,0,0,0), + (10,8,15731,20000,1,0,0,1,1,0,0,0), + (10,8,15732,20000,1,0,0,1,1,0,0,0), + (10,8,15733,20000,1,0,0,1,1,0,0,0), + (10,8,15734,20000,1,0,0,1,1,0,0,0), + (10,8,15735,20000,1,0,0,1,1,0,0,0), + (10,8,15736,20000,1,0,0,1,1,0,0,0), + (10,8,15737,20000,1,0,0,1,1,0,0,0), + (10,8,15738,20000,1,0,0,1,1,0,0,0), + (10,8,15739,20000,1,0,0,1,1,0,0,0), + (10,8,15740,20000,1,0,0,1,1,0,0,0), + (10,8,15741,20000,1,0,0,1,1,0,0,0), + (10,8,15742,20000,1,0,0,1,1,0,0,0), + (10,8,15743,20000,1,0,0,1,1,0,0,0), + (10,8,15744,20000,1,0,0,1,1,0,0,0), + (10,8,15745,20000,1,0,0,1,1,0,0,0), + (10,8,15746,20000,1,0,0,1,1,0,0,0), + (10,8,15747,20000,1,0,0,1,1,0,0,0), + (10,8,15748,20000,1,0,0,1,1,0,0,0), + (10,8,15749,20000,1,0,0,1,1,0,0,0), + (10,8,15750,20000,1,0,0,1,1,0,0,0), + (10,8,15751,20000,1,0,0,1,1,0,0,0), + (10,8,15752,20000,1,0,0,1,1,0,0,0), + (10,8,15753,20000,1,0,0,1,1,0,0,0), + (10,8,15754,20000,1,0,0,1,1,0,0,0), + (10,8,15755,20000,1,0,0,1,1,0,0,0), + (10,8,15756,20000,1,0,0,1,1,0,0,0), + (10,8,15757,20000,1,0,0,1,1,0,0,0), + (10,8,15758,20000,1,0,0,1,1,0,0,0), + (10,8,15759,20000,1,0,0,1,1,0,0,0), + (10,8,15760,20000,1,0,0,1,1,0,0,0), + (10,8,15761,20000,1,0,0,1,1,0,0,0), + (10,8,15762,20000,1,0,0,1,1,0,0,0), + (10,8,15763,20000,1,0,0,1,1,0,0,0), + (10,8,15764,20000,1,0,0,1,1,0,0,0), + (10,8,15765,20000,1,0,0,1,1,0,0,0), + (10,8,15766,20000,1,0,0,1,1,0,0,0), + (10,8,15919,20000,1,0,0,1,1,0,0,0), + (10,8,15920,20000,1,0,0,1,1,0,0,0), + (10,8,15921,20000,1,0,0,1,1,0,0,0), + (10,8,15922,20000,1,0,0,1,1,0,0,0), + (10,8,15923,20000,1,0,0,1,1,0,0,0), + (10,8,15924,20000,1,0,0,1,1,0,0,0), + (10,8,15925,20000,1,0,0,1,1,0,0,0), + (10,8,15926,20000,1,0,0,1,1,0,0,0), + (10,8,15927,20000,1,0,0,1,1,0,0,0), + (10,8,15928,20000,1,0,0,1,1,0,0,0), + (10,8,15929,20000,1,0,0,1,1,0,0,0), + (10,8,15930,20000,1,0,0,1,1,0,0,0), + (10,8,15931,20000,1,0,0,1,1,0,0,0), + (10,8,15932,20000,1,0,0,1,1,0,0,0), + (10,8,15933,20000,1,0,0,1,1,0,0,0), + (10,8,15934,20000,1,0,0,1,1,0,0,0), + (10,8,15935,20000,1,0,0,1,1,0,0,0), + (10,8,15936,20000,1,0,0,1,1,0,0,0), + (10,8,15937,20000,1,0,0,1,1,0,0,0), + (10,8,15938,20000,1,0,0,1,1,0,0,0), + (10,8,15939,20000,1,0,0,1,1,0,0,0), + (10,8,15940,20000,1,0,0,1,1,0,0,0), + (10,8,15941,20000,1,0,0,1,1,0,0,0), + (10,8,15942,20000,1,0,0,1,1,0,0,0), + (10,8,15943,20000,1,0,0,1,1,0,0,0), + (10,8,15944,20000,1,0,0,1,1,0,0,0), + (10,8,15945,20000,1,0,0,1,1,0,0,0), + (10,8,15946,20000,1,0,0,1,1,0,0,0), + (10,8,15947,20000,1,0,0,1,1,0,0,0), + (10,8,15948,20000,1,0,0,1,1,0,0,0), + (10,8,15949,20000,1,0,0,1,1,0,0,0), + (10,8,15950,20000,1,0,0,1,1,0,0,0), + (10,8,15951,20000,1,0,0,1,1,0,0,0), + (10,8,15952,20000,1,0,0,1,1,0,0,0), + (10,8,15953,20000,1,0,0,1,1,0,0,0), + (10,8,15954,20000,1,0,0,1,1,0,0,0), + (10,8,15955,20000,1,0,0,1,1,0,0,0), + (10,8,15956,20000,1,0,0,1,1,0,0,0), + (10,8,15957,20000,1,0,0,1,1,0,0,0), + (10,8,15958,20000,1,0,0,1,1,0,0,0), + (10,8,15959,20000,1,0,0,1,1,0,0,0), + (10,8,15960,20000,1,0,0,1,1,0,0,0), + (10,8,15961,20000,1,0,0,1,1,0,0,0), + (10,8,15962,20000,1,0,0,1,1,0,0,0), + (10,8,15963,20000,1,0,0,1,1,0,0,0), + (10,8,15964,20000,1,0,0,1,1,0,0,0), + (10,8,15965,20000,1,0,0,1,1,0,0,0), + (10,8,15966,20000,1,0,0,1,1,0,0,0), + (10,8,15967,20000,1,0,0,1,1,0,0,0), + (10,8,15968,20000,1,0,0,1,1,0,0,0), + (10,7,13506,250,1,0,0,1,1,0,50,0), + (10,7,15011,250,1,0,0,1,1,0,50,0), + (10,7,13636,250,1,0,0,1,1,0,50,0), + (10,7,15022,250,1,0,0,1,1,0,50,0), + (10,8,4407,1000,1,0,0,1,1,0,0,0), + (10,8,4408,1000,1,0,0,1,1,0,0,0), + (10,8,4409,1000,1,0,0,1,1,0,0,0), + (10,8,4410,1000,1,0,0,1,1,0,0,0), + (10,8,4411,1000,1,0,0,1,1,0,0,0), + (10,8,4412,1000,1,0,0,1,1,0,0,0), + (10,8,4413,1000,1,0,0,1,1,0,0,0), + (10,8,4414,1000,1,0,0,1,1,0,0,0), + (10,8,4823,1000,1,0,0,1,1,0,0,0), + (10,8,4824,1000,1,0,0,1,1,0,0,0), + (10,8,4825,1000,1,0,0,1,1,0,0,0), + (10,8,4826,1000,1,0,0,1,1,0,0,0), + (10,8,4827,1000,1,0,0,1,1,0,0,0), + (10,8,4828,1000,1,0,0,1,1,0,0,0), + (10,8,4829,1000,1,0,0,1,1,0,0,0), + (10,8,4830,1000,1,0,0,1,1,0,0,0), + (10,8,5194,1000,1,0,0,1,1,0,0,0), + (10,8,5195,1000,1,0,0,1,1,0,0,0), + (10,8,5196,1000,1,0,0,1,1,0,0,0), + (10,8,5197,1000,1,0,0,1,1,0,0,0), + (10,8,5198,1000,1,0,0,1,1,0,0,0), + (10,8,5199,1000,1,0,0,1,1,0,0,0), + (10,8,5200,1000,1,0,0,1,1,0,0,0), + (10,8,5201,1000,1,0,0,1,1,0,0,0), + (10,8,13630,1000,1,0,0,1,1,0,0,0), + (10,8,13631,1000,1,0,0,1,1,0,0,0), + (10,8,13632,1000,1,0,0,1,1,0,0,0), + (10,8,13633,1000,1,0,0,1,1,0,0,0), + (10,8,13634,1000,1,0,0,1,1,0,0,0), + (10,8,13635,1000,1,0,0,1,1,0,0,0), + (10,8,15103,1000,1,0,0,1,1,0,0,0), + (10,8,15104,1000,1,0,0,1,1,0,0,0), + (10,8,15105,1000,1,0,0,1,1,0,0,0), + (10,8,15106,1000,1,0,0,1,1,0,0,0), + (10,8,15107,1000,1,0,0,1,1,0,0,0), + (10,8,15108,1000,1,0,0,1,1,0,0,0), + (10,8,16459,1000,1,0,0,1,1,0,0,0), + (10,8,16460,1000,1,0,0,1,1,0,0,0), + (10,8,16461,1000,1,0,0,1,1,0,0,0), + (10,8,16462,1000,1,0,0,1,1,0,0,0), + (10,8,16463,1000,1,0,0,1,1,0,0,0), + (10,8,16464,1000,1,0,0,1,1,0,0,0), + (10,8,16465,1000,1,0,0,1,1,0,0,0), + (10,8,16466,1000,1,0,0,1,1,0,0,0), + (10,8,16467,1000,1,0,0,1,1,0,0,0), + (10,8,16468,1000,1,0,0,1,1,0,0,0), + (10,8,16469,1000,1,0,0,1,1,0,0,0), + (10,8,16470,1000,1,0,0,1,1,0,0,0), + (10,8,16471,1000,1,0,0,1,1,0,0,0), + (10,8,16472,1000,1,0,0,1,1,0,0,0), + (10,8,13416,1000,1,0,0,1,1,0,0,0), + (10,8,13417,1000,1,0,0,1,1,0,0,0), + (10,8,13418,1000,1,0,0,1,1,0,0,0), + (10,8,13419,1000,1,0,0,1,1,0,0,0), + (10,8,13420,1000,1,0,0,1,1,0,0,0), + (10,8,14283,1000,1,0,0,1,1,0,0,0), + (10,8,14284,1000,1,0,0,1,1,0,0,0), + (10,8,14285,1000,1,0,0,1,1,0,0,0), + (10,8,14286,1000,1,0,0,1,1,0,0,0), + (10,8,13182,1000,1,0,0,1,1,0,0,0), + (10,8,13507,1000,1,0,0,1,1,0,0,0), + (10,8,13981,1000,1,0,0,1,1,0,0,0), + (10,8,14744,1000,1,0,0,1,1,0,0,0), + (10,8,14893,1000,1,0,0,1,1,0,0,0), + (10,8,15785,1000,1,0,0,1,1,0,0,0), + (10,8,16419,1000,1,0,0,1,1,0,0,0), + (10,8,11470,1000,1,0,0,1,1,0,0,0), + (10,8,12512,1000,1,0,0,1,1,0,0,0), + (10,8,12884,1000,1,0,0,1,1,0,0,0), + (10,8,12513,1000,1,0,0,1,1,0,0,0), + (10,8,12514,1000,1,0,0,1,1,0,0,0), + (10,8,12515,1000,1,0,0,1,1,0,0,0), + (10,8,12516,1000,1,0,0,1,1,0,0,0), + (10,8,12517,1000,1,0,0,1,1,0,0,0), + (10,8,12518,1000,1,0,0,1,1,0,0,0), + (10,8,12519,1000,1,0,0,1,1,0,0,0), + (10,8,12520,1000,1,0,0,1,1,0,0,0), + (10,8,12521,1000,1,0,0,1,1,0,0,0), + (10,8,8179,1000,1,0,0,1,1,0,0,0), + (10,8,9704,1000,1,0,0,1,1,0,0,0), + (10,8,15448,1000,1,0,0,1,1,0,0,0), + (10,8,11162,1000,1,0,0,1,1,0,0,0), + (10,8,11163,1000,1,0,0,1,1,0,0,0), + (10,8,11164,1000,1,0,0,1,1,0,0,0), + (10,8,11165,1000,1,0,0,1,1,0,0,0), + (10,8,11661,1000,1,0,0,1,1,0,0,0), + (10,8,11662,1000,1,0,0,1,1,0,0,0), + (10,8,14639,1000,1,0,0,1,1,0,0,0), + (10,7,15774,3000,1,0,0,1,1,0,100,0), + (10,7,15775,3000,1,0,0,1,1,0,100,0), + (10,7,11420,3000,1,0,0,1,1,0,100,0), + (10,7,14704,3000,1,0,0,1,1,0,100,0), + (10,7,13177,3000,1,0,0,1,1,0,100,0), + (10,7,14191,3000,1,0,0,1,1,0,100,0), + (10,7,13449,3000,1,0,0,1,1,0,100,0), + (10,7,14192,3000,1,0,0,1,1,0,100,0), + (10,7,15772,3000,1,0,0,1,1,0,100,0), + (10,7,13791,3000,1,0,0,1,1,0,100,0), + (10,7,14006,3000,1,0,0,1,1,0,100,0), + (10,7,15768,3000,1,0,0,1,1,0,100,0), + (10,7,14069,3000,1,0,0,1,1,0,100,0), + (10,7,14124,3000,1,0,0,1,1,0,100,0), + (10,7,15507,3000,1,0,0,1,1,0,100,0), + (10,7,15508,3000,1,0,0,1,1,0,100,0), + (10,7,14855,3000,1,0,0,1,1,0,100,0), + (10,7,14894,3000,1,0,0,1,1,0,100,0), + (10,7,16444,3000,1,0,0,1,1,0,100,0), + (10,7,16445,3000,1,0,0,1,1,0,100,0), + (10,7,12509,3000,1,0,0,1,1,0,100,0), + (10,7,14126,3000,1,0,0,1,1,0,100,0), + (10,7,15062,3000,1,0,0,1,1,0,100,0), + (10,7,15063,3000,1,0,0,1,1,0,100,0), + (10,7,14891,3000,1,0,0,1,1,0,100,0), + (10,7,14895,3000,1,0,0,1,1,0,100,0), + (10,7,14091,3000,1,0,0,1,1,0,100,0), + (10,7,14092,3000,1,0,0,1,1,0,100,0), + (10,7,14501,3000,1,0,0,1,1,0,100,0), + (10,7,14506,3000,1,0,0,1,1,0,100,0), + (10,7,15285,3000,1,0,0,1,1,0,100,0), + (10,7,15286,3000,1,0,0,1,1,0,100,0), + (10,7,16442,3000,1,0,0,1,1,0,100,0), + (10,7,16443,3000,1,0,0,1,1,0,100,0), + (10,7,15027,3000,1,0,0,1,1,0,100,0), + (10,7,15028,3000,1,0,0,1,1,0,100,0), + (10,7,13453,3000,1,0,0,1,1,0,100,0), + (10,7,14193,3000,1,0,0,1,1,0,100,0), + (10,7,13178,3000,1,0,0,1,1,0,100,0), + (10,7,14194,3000,1,0,0,1,1,0,100,0), + (10,7,16454,3000,1,0,0,1,1,0,100,0), + (10,7,16455,3000,1,0,0,1,1,0,100,0), + (10,7,15030,3000,1,0,0,1,1,0,100,0), + (10,7,15031,3000,1,0,0,1,1,0,100,0), + (10,7,13790,3000,1,0,0,1,1,0,100,0), + (10,7,14005,3000,1,0,0,1,1,0,100,0), + (10,7,14406,3000,1,0,0,1,1,0,100,0), + (10,7,14413,3000,1,0,0,1,1,0,100,0), + (10,7,16448,3000,1,0,0,1,1,0,100,0), + (10,7,16449,3000,1,0,0,1,1,0,100,0), + (10,7,12872,3000,1,0,0,1,1,0,100,0), + (10,7,14187,3000,1,0,0,1,1,0,100,0), + (10,7,14125,3000,1,0,0,1,1,0,100,0), + (10,7,14500,3000,1,0,0,1,1,0,100,0), + (10,7,14505,3000,1,0,0,1,1,0,100,0), + (10,7,15118,3000,1,0,0,1,1,0,100,0), + (10,7,15119,3000,1,0,0,1,1,0,100,0), + (10,7,14662,3000,1,0,0,1,1,0,100,0), + (10,7,14663,3000,1,0,0,1,1,0,100,0), + (10,7,15771,3000,1,0,0,1,1,0,100,0), + (10,7,9700,3000,1,0,0,1,1,0,100,0), + (10,7,14498,3000,1,0,0,1,1,0,100,0), + (10,7,14913,3000,1,0,0,1,1,0,100,0), + (10,7,14914,3000,1,0,0,1,1,0,100,0), + (10,7,13508,3000,1,0,0,1,1,0,100,0), + (10,7,15115,3000,1,0,0,1,1,0,100,0), + (10,7,15116,3000,1,0,0,1,1,0,100,0), + (10,7,15113,3000,1,0,0,1,1,0,100,0), + (10,7,15114,3000,1,0,0,1,1,0,100,0), + (10,7,15222,3000,1,0,0,1,1,0,100,0), + (10,7,15223,3000,1,0,0,1,1,0,100,0), + (10,7,10750,3000,1,0,0,1,1,0,100,0), + (10,7,14705,3000,1,0,0,1,1,0,100,0), + (10,7,15027,3000,1,0,0,1,1,0,100,0), + (10,7,15028,3000,1,0,0,1,1,0,100,0), + (10,7,10380,3000,1,0,0,1,1,0,100,0), + (10,7,15060,3000,1,0,0,1,1,0,100,0), + (10,7,13963,3000,1,0,0,1,1,0,100,0), + (10,7,14026,3000,1,0,0,1,1,0,100,0), + (10,7,13964,3000,1,0,0,1,1,0,100,0), + (10,7,14027,3000,1,0,0,1,1,0,100,0), + (10,7,15064,3000,1,0,0,1,1,0,100,0), + (10,7,15065,3000,1,0,0,1,1,0,100,0), + (10,7,15524,3000,1,0,0,1,1,0,100,0), + (10,7,15525,3000,1,0,0,1,1,0,100,0), + (10,7,16450,3000,1,0,0,1,1,0,100,0), + (10,7,16451,3000,1,0,0,1,1,0,100,0), + (10,7,16344,3000,1,0,0,1,1,0,100,0), + (10,7,16345,3000,1,0,0,1,1,0,100,0), + (10,7,16342,3000,1,0,0,1,1,0,100,0), + (10,7,16343,3000,1,0,0,1,1,0,100,0), + (10,7,15220,3000,1,0,0,1,1,0,100,0), + (10,7,15221,3000,1,0,0,1,1,0,100,0), + (10,7,15066,3000,1,0,0,1,1,0,100,0), + (10,7,15067,3000,1,0,0,1,1,0,100,0), + (10,7,14089,3000,1,0,0,1,1,0,100,0), + (10,7,14090,3000,1,0,0,1,1,0,100,0), + (10,7,14195,3000,1,0,0,1,1,0,100,0), + (10,7,14196,3000,1,0,0,1,1,0,100,0), + (10,7,13965,3000,1,0,0,1,1,0,100,0), + (10,7,14028,3000,1,0,0,1,1,0,100,0), + (10,7,13508,3000,1,0,0,1,1,0,100,0), + (10,7,13962,3000,1,0,0,1,1,0,100,0), + (10,7,14314,3000,1,0,0,1,1,0,100,0), + (10,7,13404,3000,1,0,0,1,1,0,100,0), + (10,7,14188,3000,1,0,0,1,1,0,100,0), + (10,7,14032,3000,1,0,0,1,1,0,100,0), + (10,7,13960,3000,1,0,0,1,1,0,100,0), + (10,7,15819,3000,1,0,0,1,1,0,100,0), + (10,7,15820,3000,1,0,0,1,1,0,100,0), + (10,7,10750,3000,1,0,0,1,1,0,100,0), + (10,7,14705,3000,1,0,0,1,1,0,100,0), + (10,7,14407,3000,1,0,0,1,1,0,100,0), + (10,7,14414,3000,1,0,0,1,1,0,100,0), + (10,7,16352,3000,1,0,0,1,1,0,100,0), + (10,7,16353,3000,1,0,0,1,1,0,100,0), + (10,7,14502,3000,1,0,0,1,1,0,100,0), + (10,7,14507,3000,1,0,0,1,1,0,100,0), + (10,7,10811,3000,1,0,0,1,1,0,100,0), + (10,7,15061,3000,1,0,0,1,1,0,100,0), + (10,7,15823,3000,1,0,0,1,1,0,100,0), + (10,7,15824,3000,1,0,0,1,1,0,100,0), + (10,7,15224,3000,1,0,0,1,1,0,100,0), + (10,7,15225,3000,1,0,0,1,1,0,100,0), + (10,7,14503,3000,1,0,0,1,1,0,100,0), + (10,7,14510,3000,1,0,0,1,1,0,100,0), + (10,7,15776,3000,1,0,0,1,1,0,100,0), + (10,7,15777,3000,1,0,0,1,1,0,100,0), + (10,7,15821,3000,1,0,0,1,1,0,100,0), + (10,7,15822,3000,1,0,0,1,1,0,100,0), + (10,7,14198,3000,1,0,0,1,1,0,100,0), + (10,7,14197,3000,1,0,0,1,1,0,100,0), + (10,7,16446,3000,1,0,0,1,1,0,100,0), + (10,7,16447,3000,1,0,0,1,1,0,100,0), + (10,7,14905,3000,1,0,0,1,1,0,100,0), + (10,7,14907,3000,1,0,0,1,1,0,100,0), + (10,7,14904,3000,1,0,0,1,1,0,100,0), + (10,7,14906,3000,1,0,0,1,1,0,100,0), + (10,7,14659,3000,1,0,0,1,1,0,100,0), + (10,7,14660,3000,1,0,0,1,1,0,100,0), + (10,7,13326,3000,1,0,0,1,1,0,100,0), + (10,7,14416,3000,1,0,0,1,1,0,100,0), + (10,7,13450,3000,1,0,0,1,1,0,100,0), + (10,7,14031,3000,1,0,0,1,1,0,100,0), + (10,7,16492,3000,1,0,0,1,1,0,100,0), + (10,7,16493,3000,1,0,0,1,1,0,100,0), + (10,7,14299,500,1,0,0,1,1,0,20,0), + (10,7,14389,500,1,0,0,1,1,0,20,0), + (10,7,15177,500,1,0,0,1,1,0,20,0), + (10,7,14537,500,1,0,0,1,1,0,20,0), + (10,7,14758,500,1,0,0,1,1,0,20,0), + (10,7,14854,500,1,0,0,1,1,0,20,0), + (10,7,13974,500,1,0,0,1,1,0,20,0), + (10,7,15021,500,1,0,0,1,1,0,20,0), + (10,7,15111,500,1,0,0,1,1,0,20,0), + (10,7,15226,500,1,0,0,1,1,0,20,0), + (10,7,15773,500,1,0,0,1,1,0,20,0), + (10,7,15825,500,1,0,0,1,1,0,20,0), + (10,7,15827,500,1,0,0,1,1,0,20,0), + (10,7,16340,500,1,0,0,1,1,0,20,0), + (10,7,16341,500,1,0,0,1,1,0,20,0), + (10,7,16457,500,1,0,0,1,1,0,20,0), + (10,7,16458,500,1,0,0,1,1,0,20,0), + (10,7,11698,250,1,0,0,1,1,0,50,0), + (10,7,11700,250,1,0,0,1,1,0,50,0), + (10,8,9958,20,1,0,0,1,1,0,0,999), + (10,8,11284,15,1,0,0,1,1,0,0,0), + (10,8,11285,15,1,0,0,1,1,0,0,0), + (10,8,11286,15,1,0,0,1,1,0,0,0), + (10,8,10356,500,1,0,0,1,1,0,0,0), + (10,8,12511,500,1,0,0,1,1,0,0,0), + (10,8,13238,500,1,0,0,1,1,0,0,0), + (10,8,11383,10,1,0,0,1,1,0,0,0), + (10,8,11382,10,1,0,0,1,1,0,0,0), + (10,8,11381,10,1,0,0,1,1,0,0,0), + (10,7,16348,3000,1,0,0,1,1,0,100,0), + (10,8,11386,10,1,0,0,1,1,0,0,0), + (10,8,14444,10,1,0,0,1,1,0,0,0), + (10,8,14443,10,1,0,0,1,1,0,0,0), + (10,8,14445,10,1,0,0,1,1,0,0,0), + (10,8,15068,500,1,0,0,1,1,0,20,0), + (10,7,16532,1000,1,0,0,1,1,0,0,0), + (10,7,14368,3000,1,0,0,1,1,0,50,0), + (10,7,1622,3000,1,0,0,1,1,0,0,0), + (10,7,16456,500,1,0,0,1,1,0,0,0); + +END; \ No newline at end of file diff --git a/server/migrations/seed/ScenarioDefaults.sql b/server/migrations/seed/ScenarioDefaults.sql new file mode 100644 index 000000000..ec7b3d99e --- /dev/null +++ b/server/migrations/seed/ScenarioDefaults.sql @@ -0,0 +1,178 @@ +BEGIN; + +INSERT INTO public.scenario_counter +(scenario_id, category_id) +VALUES + (17,0), + (93,1), + (92,1), + (81,1), + (91,1), + (90,1), + (89,1), + (88,1), + (87,1), + (86,1), + (85,1), + (84,1), + (83,1), + (82,1), + (87,3), + (88,3), + (89,3), + (90,3), + (91,3), + (92,3), + (83,3), + (86,3), + (60,3), + (58,3), + (59,3), + (27,3), + (25,3), + (26,3), + (23,3), + (2,3), + (3,3), + (4,3), + (31,3), + (32,3), + (33,3), + (34,3), + (35,3), + (36,3), + (37,3), + (40,3), + (38,3), + (39,3), + (48,3), + (12,3), + (13,3), + (30,3), + (29,3), + (46,3), + (0,4), + (1,4), + (2,4), + (3,4), + (4,4), + (5,4), + (6,4), + (7,4), + (8,4), + (9,4), + (10,4), + (11,4), + (12,4), + (13,4), + (14,4), + (50,5), + (51,5), + (52,5), + (53,5), + (54,5), + (55,5), + (56,5), + (58,5), + (63,5), + (64,5), + (65,5), + (67,5), + (71,5), + (75,5), + (61,5), + (68,5), + (66,5), + (76,5), + (70,5), + (77,5), + (72,5), + (74,5), + (73,5), + (78,5), + (69,5), + (62,5), + (79,5), + (0,6), + (1,6), + (2,6), + (3,6), + (4,6), + (5,6), + (6,6), + (7,6), + (8,6), + (9,6), + (17,6), + (10,6), + (11,6), + (12,6), + (13,6), + (14,6), + (15,6), + (16,6), + (50,7), + (53,7), + (62,7), + (52,7), + (56,7), + (51,7), + (49,7), + (54,7), + (57,7), + (55,7), + (61,7), + (58,7), + (60,7), + (59,7), + (42,7), + (48,7), + (40,7), + (39,7), + (43,7), + (46,7), + (41,7), + (44,7), + (45,7), + (47,7), + (37,7), + (34,7), + (33,7), + (32,7), + (28,7), + (26,7), + (36,7), + (38,7), + (35,7), + (27,7), + (30,7), + (31,7), + (29,7), + (24,7), + (23,7), + (22,7), + (21,7), + (25,7), + (20,7), + (7,7), + (9,7), + (13,7), + (16,7), + (12,7), + (14,7), + (15,7), + (19,7), + (10,7), + (8,7), + (11,7), + (18,7), + (17,7), + (6,7), + (5,7), + (4,7), + (3,7), + (2,7), + (1,7), + (0,7); + +END; \ No newline at end of file diff --git a/server/migrations/sql/0001_init.sql b/server/migrations/sql/0001_init.sql new file mode 100644 index 000000000..eec83adef --- /dev/null +++ b/server/migrations/sql/0001_init.sql @@ -0,0 +1,2035 @@ +-- Erupe consolidated database schema +-- This file is auto-generated. Do not edit manually. +-- To update, modify future migration files (0002_*.sql, etc.) +-- +-- Includes: init.sql (v9.1.0) + 9.2-update.sql + all 33 patch schemas + + +-- +-- Name: event_type; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.event_type AS ENUM ( + 'festa', + 'diva', + 'vs', + 'mezfes' +); + + +-- +-- Name: festival_color; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.festival_color AS ENUM ( + 'none', + 'red', + 'blue' +); + + +-- +-- Name: guild_application_type; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.guild_application_type AS ENUM ( + 'applied', + 'invited' +); + + +-- +-- Name: prize_type; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.prize_type AS ENUM ( + 'personal', + 'guild' +); + + +-- +-- Name: uint16; Type: DOMAIN; Schema: public; Owner: - +-- + +CREATE DOMAIN public.uint16 AS integer + CONSTRAINT uint16_check CHECK (((VALUE >= 0) AND (VALUE <= 65536))); + + +-- +-- Name: uint8; Type: DOMAIN; Schema: public; Owner: - +-- + +CREATE DOMAIN public.uint8 AS smallint + CONSTRAINT uint8_check CHECK (((VALUE >= 0) AND (VALUE <= 255))); + + +-- +-- Name: achievements; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.achievements ( + id integer NOT NULL, + ach0 integer DEFAULT 0, + ach1 integer DEFAULT 0, + ach2 integer DEFAULT 0, + ach3 integer DEFAULT 0, + ach4 integer DEFAULT 0, + ach5 integer DEFAULT 0, + ach6 integer DEFAULT 0, + ach7 integer DEFAULT 0, + ach8 integer DEFAULT 0, + ach9 integer DEFAULT 0, + ach10 integer DEFAULT 0, + ach11 integer DEFAULT 0, + ach12 integer DEFAULT 0, + ach13 integer DEFAULT 0, + ach14 integer DEFAULT 0, + ach15 integer DEFAULT 0, + ach16 integer DEFAULT 0, + ach17 integer DEFAULT 0, + ach18 integer DEFAULT 0, + ach19 integer DEFAULT 0, + ach20 integer DEFAULT 0, + ach21 integer DEFAULT 0, + ach22 integer DEFAULT 0, + ach23 integer DEFAULT 0, + ach24 integer DEFAULT 0, + ach25 integer DEFAULT 0, + ach26 integer DEFAULT 0, + ach27 integer DEFAULT 0, + ach28 integer DEFAULT 0, + ach29 integer DEFAULT 0, + ach30 integer DEFAULT 0, + ach31 integer DEFAULT 0, + ach32 integer DEFAULT 0 +); + + +-- +-- Name: airou_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.airou_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: bans; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.bans ( + user_id integer NOT NULL, + expires timestamp with time zone +); + + +-- +-- Name: cafe_accepted; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.cafe_accepted ( + cafe_id integer NOT NULL, + character_id integer NOT NULL +); + + +-- +-- Name: cafebonus; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.cafebonus ( + id integer NOT NULL, + time_req integer NOT NULL, + item_type integer NOT NULL, + item_id integer NOT NULL, + quantity integer NOT NULL +); + + +-- +-- Name: cafebonus_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.cafebonus_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: cafebonus_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.cafebonus_id_seq OWNED BY public.cafebonus.id; + + +-- +-- Name: characters; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.characters ( + id integer NOT NULL, + user_id bigint, + is_female boolean, + is_new_character boolean, + name character varying(15), + unk_desc_string character varying(31), + gr public.uint16, + hr public.uint16, + weapon_type public.uint16, + last_login integer, + savedata bytea, + decomyset bytea, + hunternavi bytea, + otomoairou bytea, + partner bytea, + platebox bytea, + platedata bytea, + platemyset bytea, + rengokudata bytea, + savemercenary bytea, + restrict_guild_scout boolean DEFAULT false NOT NULL, + gacha_items bytea, + daily_time timestamp with time zone, + house_info bytea, + login_boost bytea, + skin_hist bytea, + kouryou_point integer, + gcp integer, + guild_post_checked timestamp with time zone DEFAULT now() NOT NULL, + time_played integer DEFAULT 0 NOT NULL, + weapon_id integer DEFAULT 0 NOT NULL, + scenariodata bytea, + savefavoritequest bytea, + friends text DEFAULT ''::text NOT NULL, + blocked text DEFAULT ''::text NOT NULL, + deleted boolean DEFAULT false NOT NULL, + cafe_time integer DEFAULT 0, + netcafe_points integer DEFAULT 0, + boost_time timestamp with time zone, + cafe_reset timestamp with time zone, + bonus_quests integer DEFAULT 0 NOT NULL, + daily_quests integer DEFAULT 0 NOT NULL, + promo_points integer DEFAULT 0 NOT NULL, + rasta_id integer, + pact_id integer, + stampcard integer DEFAULT 0 NOT NULL, + mezfes bytea +); + + +-- +-- Name: characters_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.characters_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: characters_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.characters_id_seq OWNED BY public.characters.id; + + +-- +-- Name: distribution; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.distribution ( + id integer NOT NULL, + character_id integer, + type integer NOT NULL, + deadline timestamp with time zone, + event_name text DEFAULT 'GM Gift!'::text NOT NULL, + description text DEFAULT '~C05You received a gift!'::text NOT NULL, + times_acceptable integer DEFAULT 1 NOT NULL, + min_hr integer, + max_hr integer, + min_sr integer, + max_sr integer, + min_gr integer, + max_gr integer, + data bytea NOT NULL, + rights integer, + selection boolean +); + + +-- +-- Name: distribution_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.distribution_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: distribution_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.distribution_id_seq OWNED BY public.distribution.id; + + +-- +-- Name: distribution_items; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.distribution_items ( + id integer NOT NULL, + distribution_id integer NOT NULL, + item_type integer NOT NULL, + item_id integer, + quantity integer +); + + +-- +-- Name: distribution_items_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.distribution_items_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: distribution_items_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.distribution_items_id_seq OWNED BY public.distribution_items.id; + + +-- +-- Name: distributions_accepted; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.distributions_accepted ( + distribution_id integer, + character_id integer +); + + +-- +-- Name: event_quests; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.event_quests ( + id integer NOT NULL, + max_players integer, + quest_type integer NOT NULL, + quest_id integer NOT NULL, + mark integer, + flags integer, + start_time timestamp with time zone DEFAULT now() NOT NULL, + active_days integer, + inactive_days integer +); + + +-- +-- Name: event_quests_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.event_quests_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: event_quests_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.event_quests_id_seq OWNED BY public.event_quests.id; + + +-- +-- Name: events; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.events ( + id integer NOT NULL, + event_type public.event_type NOT NULL, + start_time timestamp with time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: events_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.events_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: events_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.events_id_seq OWNED BY public.events.id; + + +-- +-- Name: feature_weapon; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.feature_weapon ( + start_time timestamp with time zone NOT NULL, + featured integer NOT NULL +); + + +-- +-- Name: festa_prizes; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.festa_prizes ( + id integer NOT NULL, + type public.prize_type NOT NULL, + tier integer NOT NULL, + souls_req integer NOT NULL, + item_id integer NOT NULL, + num_item integer NOT NULL +); + + +-- +-- Name: festa_prizes_accepted; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.festa_prizes_accepted ( + prize_id integer NOT NULL, + character_id integer NOT NULL +); + + +-- +-- Name: festa_prizes_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.festa_prizes_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: festa_prizes_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.festa_prizes_id_seq OWNED BY public.festa_prizes.id; + + +-- +-- Name: festa_registrations; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.festa_registrations ( + guild_id integer NOT NULL, + team public.festival_color NOT NULL +); + + +-- +-- Name: festa_submissions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.festa_submissions ( + character_id integer NOT NULL, + guild_id integer NOT NULL, + trial_type integer NOT NULL, + souls integer NOT NULL, + "timestamp" timestamp with time zone NOT NULL +); + + +-- +-- Name: festa_trials; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.festa_trials ( + id integer NOT NULL, + objective integer NOT NULL, + goal_id integer NOT NULL, + times_req integer NOT NULL, + locale_req integer DEFAULT 0 NOT NULL, + reward integer NOT NULL +); + + +-- +-- Name: festa_trials_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.festa_trials_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: festa_trials_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.festa_trials_id_seq OWNED BY public.festa_trials.id; + + +-- +-- Name: fpoint_items; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.fpoint_items ( + id integer NOT NULL, + item_type integer NOT NULL, + item_id integer NOT NULL, + quantity integer NOT NULL, + fpoints integer NOT NULL, + buyable boolean DEFAULT false NOT NULL +); + + +-- +-- Name: fpoint_items_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.fpoint_items_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: fpoint_items_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.fpoint_items_id_seq OWNED BY public.fpoint_items.id; + + +-- +-- Name: gacha_box; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.gacha_box ( + gacha_id integer, + entry_id integer, + character_id integer +); + + +-- +-- Name: gacha_entries; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.gacha_entries ( + id integer NOT NULL, + gacha_id integer, + entry_type integer, + item_type integer, + item_number integer, + item_quantity integer, + weight integer, + rarity integer, + rolls integer, + frontier_points integer, + daily_limit integer, + name text +); + + +-- +-- Name: gacha_entries_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.gacha_entries_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: gacha_entries_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.gacha_entries_id_seq OWNED BY public.gacha_entries.id; + + +-- +-- Name: gacha_items; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.gacha_items ( + id integer NOT NULL, + entry_id integer, + item_type integer, + item_id integer, + quantity integer +); + + +-- +-- Name: gacha_items_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.gacha_items_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: gacha_items_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.gacha_items_id_seq OWNED BY public.gacha_items.id; + + +-- +-- Name: gacha_shop; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.gacha_shop ( + id integer NOT NULL, + min_gr integer, + min_hr integer, + name text, + url_banner text, + url_feature text, + url_thumbnail text, + wide boolean, + recommended boolean, + gacha_type integer, + hidden boolean +); + + +-- +-- Name: gacha_shop_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.gacha_shop_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: gacha_shop_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.gacha_shop_id_seq OWNED BY public.gacha_shop.id; + + +-- +-- Name: gacha_stepup; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.gacha_stepup ( + gacha_id integer, + step integer, + character_id integer, + created_at timestamp with time zone DEFAULT now() +); + + +-- +-- Name: goocoo; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.goocoo ( + id integer CONSTRAINT gook_id_not_null NOT NULL, + goocoo0 bytea, + goocoo1 bytea, + goocoo2 bytea, + goocoo3 bytea, + goocoo4 bytea +); + + +-- +-- Name: gook_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.gook_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: gook_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.gook_id_seq OWNED BY public.goocoo.id; + + +-- +-- Name: guild_adventures; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.guild_adventures ( + id integer NOT NULL, + guild_id integer NOT NULL, + destination integer NOT NULL, + charge integer DEFAULT 0 NOT NULL, + depart integer NOT NULL, + return integer NOT NULL, + collected_by text DEFAULT ''::text NOT NULL +); + + +-- +-- Name: guild_adventures_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.guild_adventures_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: guild_adventures_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.guild_adventures_id_seq OWNED BY public.guild_adventures.id; + + +-- +-- Name: guild_alliances; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.guild_alliances ( + id integer NOT NULL, + name character varying(24) NOT NULL, + created_at timestamp with time zone DEFAULT now() NOT NULL, + parent_id integer NOT NULL, + sub1_id integer, + sub2_id integer +); + + +-- +-- Name: guild_alliances_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.guild_alliances_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: guild_alliances_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.guild_alliances_id_seq OWNED BY public.guild_alliances.id; + + +-- +-- Name: guild_applications; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.guild_applications ( + id integer NOT NULL, + guild_id integer NOT NULL, + character_id integer NOT NULL, + actor_id integer NOT NULL, + application_type public.guild_application_type NOT NULL, + created_at timestamp with time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: guild_applications_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.guild_applications_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: guild_applications_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.guild_applications_id_seq OWNED BY public.guild_applications.id; + + +-- +-- Name: guild_characters; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.guild_characters ( + id integer NOT NULL, + guild_id bigint, + character_id bigint, + joined_at timestamp with time zone DEFAULT now(), + avoid_leadership boolean DEFAULT false NOT NULL, + order_index integer DEFAULT 1 NOT NULL, + recruiter boolean DEFAULT false NOT NULL, + rp_today integer DEFAULT 0, + rp_yesterday integer DEFAULT 0, + tower_mission_1 integer, + tower_mission_2 integer, + tower_mission_3 integer, + box_claimed timestamp with time zone DEFAULT now(), + treasure_hunt integer, + trial_vote integer +); + + +-- +-- Name: guild_characters_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.guild_characters_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: guild_characters_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.guild_characters_id_seq OWNED BY public.guild_characters.id; + + +-- +-- Name: guild_hunts; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.guild_hunts ( + id integer NOT NULL, + guild_id integer NOT NULL, + host_id integer NOT NULL, + destination integer NOT NULL, + level integer NOT NULL, + acquired boolean DEFAULT false NOT NULL, + collected boolean DEFAULT false CONSTRAINT guild_hunts_claimed_not_null NOT NULL, + hunt_data bytea NOT NULL, + cats_used text NOT NULL, + start timestamp with time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: guild_hunts_claimed; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.guild_hunts_claimed ( + hunt_id integer NOT NULL, + character_id integer NOT NULL +); + + +-- +-- Name: guild_hunts_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.guild_hunts_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: guild_hunts_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.guild_hunts_id_seq OWNED BY public.guild_hunts.id; + + +-- +-- Name: guild_meals; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.guild_meals ( + id integer NOT NULL, + guild_id integer NOT NULL, + meal_id integer NOT NULL, + level integer NOT NULL, + created_at timestamp with time zone +); + + +-- +-- Name: guild_meals_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.guild_meals_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: guild_meals_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.guild_meals_id_seq OWNED BY public.guild_meals.id; + + +-- +-- Name: guild_posts; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.guild_posts ( + id integer NOT NULL, + guild_id integer NOT NULL, + author_id integer NOT NULL, + post_type integer NOT NULL, + stamp_id integer NOT NULL, + title text NOT NULL, + body text NOT NULL, + created_at timestamp with time zone DEFAULT now() NOT NULL, + liked_by text DEFAULT ''::text NOT NULL, + deleted boolean DEFAULT false NOT NULL +); + + +-- +-- Name: guild_posts_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.guild_posts_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: guild_posts_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.guild_posts_id_seq OWNED BY public.guild_posts.id; + + +-- +-- Name: guilds; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.guilds ( + id integer NOT NULL, + name character varying(24), + created_at timestamp with time zone DEFAULT now(), + leader_id integer NOT NULL, + main_motto integer DEFAULT 0, + rank_rp integer DEFAULT 0 NOT NULL, + comment character varying(255) DEFAULT ''::character varying NOT NULL, + icon bytea, + sub_motto integer DEFAULT 0, + item_box bytea, + event_rp integer DEFAULT 0 NOT NULL, + pugi_name_1 character varying(12) DEFAULT ''::character varying, + pugi_name_2 character varying(12) DEFAULT ''::character varying, + pugi_name_3 character varying(12) DEFAULT ''::character varying, + recruiting boolean DEFAULT true NOT NULL, + pugi_outfit_1 integer DEFAULT 0 NOT NULL, + pugi_outfit_2 integer DEFAULT 0 NOT NULL, + pugi_outfit_3 integer DEFAULT 0 NOT NULL, + pugi_outfits integer DEFAULT 0 NOT NULL, + tower_mission_page integer DEFAULT 1, + tower_rp integer DEFAULT 0, + room_rp integer DEFAULT 0, + room_expiry timestamp without time zone, + weekly_bonus_users integer DEFAULT 0 NOT NULL, + rp_reset_at timestamp with time zone +); + + +-- +-- Name: guilds_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.guilds_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: guilds_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.guilds_id_seq OWNED BY public.guilds.id; + + +-- +-- Name: kill_logs; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.kill_logs ( + id integer NOT NULL, + character_id integer NOT NULL, + monster integer NOT NULL, + quantity integer NOT NULL, + "timestamp" timestamp with time zone NOT NULL +); + + +-- +-- Name: kill_logs_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.kill_logs_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: kill_logs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.kill_logs_id_seq OWNED BY public.kill_logs.id; + + +-- +-- Name: login_boost; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.login_boost ( + char_id integer, + week_req integer, + expiration timestamp with time zone, + reset timestamp with time zone +); + + +-- +-- Name: mail; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.mail ( + id integer NOT NULL, + sender_id integer NOT NULL, + recipient_id integer NOT NULL, + subject character varying DEFAULT ''::character varying NOT NULL, + body character varying DEFAULT ''::character varying NOT NULL, + read boolean DEFAULT false NOT NULL, + attached_item_received boolean DEFAULT false NOT NULL, + attached_item integer, + attached_item_amount integer DEFAULT 1 NOT NULL, + is_guild_invite boolean DEFAULT false NOT NULL, + created_at timestamp with time zone DEFAULT now() NOT NULL, + deleted boolean DEFAULT false NOT NULL, + locked boolean DEFAULT false NOT NULL, + is_sys_message boolean DEFAULT false NOT NULL +); + + +-- +-- Name: mail_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.mail_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: mail_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.mail_id_seq OWNED BY public.mail.id; + + +-- +-- Name: rasta_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.rasta_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: rengoku_score; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.rengoku_score ( + character_id integer NOT NULL, + max_stages_mp integer, + max_points_mp integer, + max_stages_sp integer, + max_points_sp integer +); + + +-- +-- Name: scenario_counter; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.scenario_counter ( + id integer NOT NULL, + scenario_id numeric NOT NULL, + category_id numeric NOT NULL +); + + +-- +-- Name: scenario_counter_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.scenario_counter_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: scenario_counter_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.scenario_counter_id_seq OWNED BY public.scenario_counter.id; + + +-- +-- Name: servers; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.servers ( + server_id integer NOT NULL, + current_players integer NOT NULL, + world_name text, + world_description text, + land integer +); + + +-- +-- Name: shop_items; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.shop_items ( + shop_type integer, + shop_id integer, + id integer CONSTRAINT normal_shop_items_itemhash_not_null NOT NULL, + item_id public.uint16, + cost integer, + quantity public.uint16, + min_hr public.uint16, + min_sr public.uint16, + min_gr public.uint16, + store_level public.uint16, + max_quantity public.uint16, + road_floors public.uint16, + road_fatalis public.uint16 +); + + +-- +-- Name: shop_items_bought; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.shop_items_bought ( + character_id integer, + shop_item_id integer, + bought integer +); + + +-- +-- Name: shop_items_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.shop_items_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: shop_items_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.shop_items_id_seq OWNED BY public.shop_items.id; + + +-- +-- Name: sign_sessions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.sign_sessions ( + user_id integer, + char_id integer, + token character varying(16) NOT NULL, + server_id integer, + id integer NOT NULL, + psn_id text +); + + +-- +-- Name: sign_sessions_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.sign_sessions_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: sign_sessions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.sign_sessions_id_seq OWNED BY public.sign_sessions.id; + + +-- +-- Name: stamps; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.stamps ( + character_id integer NOT NULL, + hl_total integer DEFAULT 0, + hl_redeemed integer DEFAULT 0, + hl_checked timestamp with time zone, + ex_total integer DEFAULT 0, + ex_redeemed integer DEFAULT 0, + ex_checked timestamp with time zone, + monthly_claimed timestamp with time zone, + monthly_hl_claimed timestamp with time zone, + monthly_ex_claimed timestamp with time zone +); + + +-- +-- Name: titles; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.titles ( + id integer NOT NULL, + char_id integer NOT NULL, + unlocked_at timestamp with time zone, + updated_at timestamp with time zone +); + + +-- +-- Name: tower; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.tower ( + char_id integer, + tr integer, + trp integer, + tsp integer, + block1 integer, + block2 integer, + skills text, + gems text +); + + +-- +-- Name: trend_weapons; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.trend_weapons ( + weapon_id integer NOT NULL, + weapon_type integer NOT NULL, + count integer DEFAULT 0 +); + + +-- +-- Name: user_binary; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.user_binary ( + id integer NOT NULL, + house_tier bytea, + house_state integer, + house_password text, + house_data bytea, + house_furniture bytea, + bookshelf bytea, + gallery bytea, + tore bytea, + garden bytea, + mission bytea +); + + +-- +-- Name: user_binary_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.user_binary_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: user_binary_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.user_binary_id_seq OWNED BY public.user_binary.id; + + +-- +-- Name: users; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.users ( + id integer NOT NULL, + username text NOT NULL, + password text NOT NULL, + item_box bytea, + rights integer DEFAULT 12 NOT NULL, + last_character integer DEFAULT 0, + last_login timestamp with time zone, + return_expires timestamp with time zone, + gacha_premium integer, + gacha_trial integer, + frontier_points integer, + psn_id text, + wiiu_key text, + discord_token text, + discord_id text, + op boolean, + timer boolean +); + + +-- +-- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.users_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id; + + +-- +-- Name: warehouse; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.warehouse ( + character_id integer NOT NULL, + item0 bytea, + item1 bytea, + item2 bytea, + item3 bytea, + item4 bytea, + item5 bytea, + item6 bytea, + item7 bytea, + item8 bytea, + item9 bytea, + item10 bytea, + item0name text, + item1name text, + item2name text, + item3name text, + item4name text, + item5name text, + item6name text, + item7name text, + item8name text, + item9name text, + equip0 bytea, + equip1 bytea, + equip2 bytea, + equip3 bytea, + equip4 bytea, + equip5 bytea, + equip6 bytea, + equip7 bytea, + equip8 bytea, + equip9 bytea, + equip10 bytea, + equip0name text, + equip1name text, + equip2name text, + equip3name text, + equip4name text, + equip5name text, + equip6name text, + equip7name text, + equip8name text, + equip9name text +); + + +-- +-- Name: cafebonus id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.cafebonus ALTER COLUMN id SET DEFAULT nextval('public.cafebonus_id_seq'::regclass); + + +-- +-- Name: characters id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.characters ALTER COLUMN id SET DEFAULT nextval('public.characters_id_seq'::regclass); + + +-- +-- Name: distribution id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.distribution ALTER COLUMN id SET DEFAULT nextval('public.distribution_id_seq'::regclass); + + +-- +-- Name: distribution_items id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.distribution_items ALTER COLUMN id SET DEFAULT nextval('public.distribution_items_id_seq'::regclass); + + +-- +-- Name: event_quests id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.event_quests ALTER COLUMN id SET DEFAULT nextval('public.event_quests_id_seq'::regclass); + + +-- +-- Name: events id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.events ALTER COLUMN id SET DEFAULT nextval('public.events_id_seq'::regclass); + + +-- +-- Name: festa_prizes id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.festa_prizes ALTER COLUMN id SET DEFAULT nextval('public.festa_prizes_id_seq'::regclass); + + +-- +-- Name: festa_trials id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.festa_trials ALTER COLUMN id SET DEFAULT nextval('public.festa_trials_id_seq'::regclass); + + +-- +-- Name: fpoint_items id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fpoint_items ALTER COLUMN id SET DEFAULT nextval('public.fpoint_items_id_seq'::regclass); + + +-- +-- Name: gacha_entries id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.gacha_entries ALTER COLUMN id SET DEFAULT nextval('public.gacha_entries_id_seq'::regclass); + + +-- +-- Name: gacha_items id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.gacha_items ALTER COLUMN id SET DEFAULT nextval('public.gacha_items_id_seq'::regclass); + + +-- +-- Name: gacha_shop id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.gacha_shop ALTER COLUMN id SET DEFAULT nextval('public.gacha_shop_id_seq'::regclass); + + +-- +-- Name: goocoo id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.goocoo ALTER COLUMN id SET DEFAULT nextval('public.gook_id_seq'::regclass); + + +-- +-- Name: guild_adventures id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_adventures ALTER COLUMN id SET DEFAULT nextval('public.guild_adventures_id_seq'::regclass); + + +-- +-- Name: guild_alliances id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_alliances ALTER COLUMN id SET DEFAULT nextval('public.guild_alliances_id_seq'::regclass); + + +-- +-- Name: guild_applications id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_applications ALTER COLUMN id SET DEFAULT nextval('public.guild_applications_id_seq'::regclass); + + +-- +-- Name: guild_characters id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_characters ALTER COLUMN id SET DEFAULT nextval('public.guild_characters_id_seq'::regclass); + + +-- +-- Name: guild_hunts id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_hunts ALTER COLUMN id SET DEFAULT nextval('public.guild_hunts_id_seq'::regclass); + + +-- +-- Name: guild_meals id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_meals ALTER COLUMN id SET DEFAULT nextval('public.guild_meals_id_seq'::regclass); + + +-- +-- Name: guild_posts id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_posts ALTER COLUMN id SET DEFAULT nextval('public.guild_posts_id_seq'::regclass); + + +-- +-- Name: guilds id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guilds ALTER COLUMN id SET DEFAULT nextval('public.guilds_id_seq'::regclass); + + +-- +-- Name: kill_logs id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.kill_logs ALTER COLUMN id SET DEFAULT nextval('public.kill_logs_id_seq'::regclass); + + +-- +-- Name: mail id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.mail ALTER COLUMN id SET DEFAULT nextval('public.mail_id_seq'::regclass); + + +-- +-- Name: scenario_counter id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.scenario_counter ALTER COLUMN id SET DEFAULT nextval('public.scenario_counter_id_seq'::regclass); + + +-- +-- Name: shop_items id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.shop_items ALTER COLUMN id SET DEFAULT nextval('public.shop_items_id_seq'::regclass); + + +-- +-- Name: sign_sessions id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.sign_sessions ALTER COLUMN id SET DEFAULT nextval('public.sign_sessions_id_seq'::regclass); + + +-- +-- Name: user_binary id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_binary ALTER COLUMN id SET DEFAULT nextval('public.user_binary_id_seq'::regclass); + + +-- +-- Name: users id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass); + + +-- +-- Name: achievements achievements_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.achievements + ADD CONSTRAINT achievements_pkey PRIMARY KEY (id); + + +-- +-- Name: bans bans_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.bans + ADD CONSTRAINT bans_pkey PRIMARY KEY (user_id); + + +-- +-- Name: cafebonus cafebonus_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.cafebonus + ADD CONSTRAINT cafebonus_pkey PRIMARY KEY (id); + + +-- +-- Name: characters characters_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.characters + ADD CONSTRAINT characters_pkey PRIMARY KEY (id); + + +-- +-- Name: distribution_items distribution_items_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.distribution_items + ADD CONSTRAINT distribution_items_pkey PRIMARY KEY (id); + + +-- +-- Name: distribution distribution_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.distribution + ADD CONSTRAINT distribution_pkey PRIMARY KEY (id); + + +-- +-- Name: event_quests event_quests_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.event_quests + ADD CONSTRAINT event_quests_pkey PRIMARY KEY (id); + + +-- +-- Name: events events_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.events + ADD CONSTRAINT events_pkey PRIMARY KEY (id); + + +-- +-- Name: festa_prizes festa_prizes_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.festa_prizes + ADD CONSTRAINT festa_prizes_pkey PRIMARY KEY (id); + + +-- +-- Name: festa_trials festa_trials_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.festa_trials + ADD CONSTRAINT festa_trials_pkey PRIMARY KEY (id); + + +-- +-- Name: fpoint_items fpoint_items_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fpoint_items + ADD CONSTRAINT fpoint_items_pkey PRIMARY KEY (id); + + +-- +-- Name: gacha_entries gacha_entries_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.gacha_entries + ADD CONSTRAINT gacha_entries_pkey PRIMARY KEY (id); + + +-- +-- Name: gacha_items gacha_items_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.gacha_items + ADD CONSTRAINT gacha_items_pkey PRIMARY KEY (id); + + +-- +-- Name: gacha_shop gacha_shop_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.gacha_shop + ADD CONSTRAINT gacha_shop_pkey PRIMARY KEY (id); + + +-- +-- Name: goocoo gook_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.goocoo + ADD CONSTRAINT gook_pkey PRIMARY KEY (id); + + +-- +-- Name: guild_adventures guild_adventures_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_adventures + ADD CONSTRAINT guild_adventures_pkey PRIMARY KEY (id); + + +-- +-- Name: guild_alliances guild_alliances_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_alliances + ADD CONSTRAINT guild_alliances_pkey PRIMARY KEY (id); + + +-- +-- Name: guild_applications guild_application_character_id; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_applications + ADD CONSTRAINT guild_application_character_id UNIQUE (guild_id, character_id); + + +-- +-- Name: guild_applications guild_applications_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_applications + ADD CONSTRAINT guild_applications_pkey PRIMARY KEY (id); + + +-- +-- Name: guild_characters guild_characters_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_characters + ADD CONSTRAINT guild_characters_pkey PRIMARY KEY (id); + + +-- +-- Name: guild_hunts guild_hunts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_hunts + ADD CONSTRAINT guild_hunts_pkey PRIMARY KEY (id); + + +-- +-- Name: guild_meals guild_meals_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_meals + ADD CONSTRAINT guild_meals_pkey PRIMARY KEY (id); + + +-- +-- Name: guild_posts guild_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_posts + ADD CONSTRAINT guild_posts_pkey PRIMARY KEY (id); + + +-- +-- Name: guilds guilds_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guilds + ADD CONSTRAINT guilds_pkey PRIMARY KEY (id); + + +-- +-- Name: kill_logs kill_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.kill_logs + ADD CONSTRAINT kill_logs_pkey PRIMARY KEY (id); + + +-- +-- Name: mail mail_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.mail + ADD CONSTRAINT mail_pkey PRIMARY KEY (id); + + +-- +-- Name: rengoku_score rengoku_score_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.rengoku_score + ADD CONSTRAINT rengoku_score_pkey PRIMARY KEY (character_id); + + +-- +-- Name: scenario_counter scenario_counter_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.scenario_counter + ADD CONSTRAINT scenario_counter_pkey PRIMARY KEY (id); + + +-- +-- Name: shop_items shop_items_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.shop_items + ADD CONSTRAINT shop_items_pkey PRIMARY KEY (id); + + +-- +-- Name: sign_sessions sign_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.sign_sessions + ADD CONSTRAINT sign_sessions_pkey PRIMARY KEY (id); + + +-- +-- Name: stamps stamps_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.stamps + ADD CONSTRAINT stamps_pkey PRIMARY KEY (character_id); + + +-- +-- Name: trend_weapons trend_weapons_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.trend_weapons + ADD CONSTRAINT trend_weapons_pkey PRIMARY KEY (weapon_id); + + +-- +-- Name: user_binary user_binary_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.user_binary + ADD CONSTRAINT user_binary_pkey PRIMARY KEY (id); + + +-- +-- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.users + ADD CONSTRAINT users_pkey PRIMARY KEY (id); + + +-- +-- Name: users users_username_key; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.users + ADD CONSTRAINT users_username_key UNIQUE (username); + + +-- +-- Name: warehouse warehouse_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.warehouse + ADD CONSTRAINT warehouse_pkey PRIMARY KEY (character_id); + + +-- +-- Name: guild_application_type_index; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX guild_application_type_index ON public.guild_applications USING btree (application_type); + + +-- +-- Name: guild_character_unique_index; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX guild_character_unique_index ON public.guild_characters USING btree (character_id); + + +-- +-- Name: mail_recipient_deleted_created_id_index; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX mail_recipient_deleted_created_id_index ON public.mail USING btree (recipient_id, deleted, created_at DESC, id DESC); + + +-- +-- Name: characters characters_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.characters + ADD CONSTRAINT characters_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id); + + +-- +-- Name: guild_applications guild_applications_actor_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_applications + ADD CONSTRAINT guild_applications_actor_id_fkey FOREIGN KEY (actor_id) REFERENCES public.characters(id); + + +-- +-- Name: guild_applications guild_applications_character_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_applications + ADD CONSTRAINT guild_applications_character_id_fkey FOREIGN KEY (character_id) REFERENCES public.characters(id); + + +-- +-- Name: guild_applications guild_applications_guild_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_applications + ADD CONSTRAINT guild_applications_guild_id_fkey FOREIGN KEY (guild_id) REFERENCES public.guilds(id); + + +-- +-- Name: guild_characters guild_characters_character_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_characters + ADD CONSTRAINT guild_characters_character_id_fkey FOREIGN KEY (character_id) REFERENCES public.characters(id); + + +-- +-- Name: guild_characters guild_characters_guild_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.guild_characters + ADD CONSTRAINT guild_characters_guild_id_fkey FOREIGN KEY (guild_id) REFERENCES public.guilds(id); + + +-- +-- Name: mail mail_recipient_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.mail + ADD CONSTRAINT mail_recipient_id_fkey FOREIGN KEY (recipient_id) REFERENCES public.characters(id); + + +-- +-- Name: mail mail_sender_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.mail + ADD CONSTRAINT mail_sender_id_fkey FOREIGN KEY (sender_id) REFERENCES public.characters(id); diff --git a/server/setup/handlers.go b/server/setup/handlers.go index a2e42d3f3..37dbd1cfb 100644 --- a/server/setup/handlers.go +++ b/server/setup/handlers.go @@ -1,13 +1,14 @@ package setup import ( - "database/sql" "embed" "encoding/json" "fmt" "net/http" - "path/filepath" + "erupe-ce/server/migrations" + + "github.com/jmoiron/sqlx" _ "github.com/lib/pq" "go.uber.org/zap" ) @@ -73,16 +74,14 @@ func (ws *wizardServer) handleTestDB(w http.ResponseWriter, r *http.Request) { // initDBRequest is the JSON body for POST /api/setup/init-db. type initDBRequest struct { - Host string `json:"host"` - Port int `json:"port"` - User string `json:"user"` - Password string `json:"password"` - DBName string `json:"dbName"` - CreateDB bool `json:"createDB"` - ApplyInit bool `json:"applyInit"` - ApplyUpdate bool `json:"applyUpdate"` - ApplyPatch bool `json:"applyPatch"` - ApplyBundled bool `json:"applyBundled"` + Host string `json:"host"` + Port int `json:"port"` + User string `json:"user"` + Password string `json:"password"` + DBName string `json:"dbName"` + CreateDB bool `json:"createDB"` + ApplySchema bool `json:"applySchema"` + ApplyBundled bool `json:"applyBundled"` } func (ws *wizardServer) handleInitDB(w http.ResponseWriter, r *http.Request) { @@ -108,23 +107,12 @@ func (ws *wizardServer) handleInitDB(w http.ResponseWriter, r *http.Request) { addLog("Database created successfully") } - if req.ApplyInit { - addLog("Applying init schema (pg_restore)...") - if err := applyInitSchema(req.Host, req.Port, req.User, req.Password, req.DBName); err != nil { - addLog(fmt.Sprintf("ERROR: %s", err)) - writeJSON(w, http.StatusOK, map[string]interface{}{"success": false, "log": log}) - return - } - addLog("Init schema applied successfully") - } - - // For update/patch/bundled schemas, connect to the target DB. - if req.ApplyUpdate || req.ApplyPatch || req.ApplyBundled { + if req.ApplySchema || req.ApplyBundled { connStr := fmt.Sprintf( "host='%s' port='%d' user='%s' password='%s' dbname='%s' sslmode=disable", req.Host, req.Port, req.User, req.Password, req.DBName, ) - db, err := sql.Open("postgres", connStr) + db, err := sqlx.Open("postgres", connStr) if err != nil { addLog(fmt.Sprintf("ERROR connecting to database: %s", err)) writeJSON(w, http.StatusOK, map[string]interface{}{"success": false, "log": log}) @@ -132,37 +120,26 @@ func (ws *wizardServer) handleInitDB(w http.ResponseWriter, r *http.Request) { } defer func() { _ = db.Close() }() - applyDir := func(dir, label string) bool { - addLog(fmt.Sprintf("Applying %s schemas from %s...", label, dir)) - applied, err := applySQLFiles(db, filepath.Join("schemas", dir)) - for _, f := range applied { - addLog(fmt.Sprintf(" Applied: %s", f)) - } + if req.ApplySchema { + addLog("Running database migrations...") + applied, err := migrations.Migrate(db, ws.logger) if err != nil { addLog(fmt.Sprintf("ERROR: %s", err)) - return false + writeJSON(w, http.StatusOK, map[string]interface{}{"success": false, "log": log}) + return } - addLog(fmt.Sprintf("%s schemas applied (%d files)", label, len(applied))) - return true + addLog(fmt.Sprintf("Schema migrations applied (%d migration(s))", applied)) } - if req.ApplyUpdate { - if !applyDir("update-schema", "update") { - writeJSON(w, http.StatusOK, map[string]interface{}{"success": false, "log": log}) - return - } - } - if req.ApplyPatch { - if !applyDir("patch-schema", "patch") { - writeJSON(w, http.StatusOK, map[string]interface{}{"success": false, "log": log}) - return - } - } if req.ApplyBundled { - if !applyDir("bundled-schema", "bundled") { + addLog("Applying bundled data (shops, events, gacha)...") + applied, err := migrations.ApplySeedData(db, ws.logger) + if err != nil { + addLog(fmt.Sprintf("ERROR: %s", err)) writeJSON(w, http.StatusOK, map[string]interface{}{"success": false, "log": log}) return } + addLog(fmt.Sprintf("Bundled data applied (%d files)", applied)) } } diff --git a/server/setup/wizard.go b/server/setup/wizard.go index 689b92256..96c9466b7 100644 --- a/server/setup/wizard.go +++ b/server/setup/wizard.go @@ -6,10 +6,6 @@ import ( "fmt" "net" "os" - "os/exec" - "path/filepath" - "sort" - "strings" ) // clientModes returns all supported client version strings. @@ -373,71 +369,3 @@ func createDatabase(host string, port int, user, password, dbName string) error return nil } -// applyInitSchema runs pg_restore to load the init.sql (PostgreSQL custom dump format). -func applyInitSchema(host string, port int, user, password, dbName string) error { - pgRestore, err := exec.LookPath("pg_restore") - if err != nil { - return fmt.Errorf("pg_restore not found in PATH: %w (install PostgreSQL client tools)", err) - } - - schemaPath := filepath.Join("schemas", "init.sql") - if _, err := os.Stat(schemaPath); err != nil { - return fmt.Errorf("schema file not found: %s", schemaPath) - } - - cmd := exec.Command(pgRestore, - "--host", host, - "--port", fmt.Sprint(port), - "--username", user, - "--dbname", dbName, - "--no-owner", - "--no-privileges", - schemaPath, - ) - cmd.Env = append(os.Environ(), fmt.Sprintf("PGPASSWORD=%s", password)) - - output, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("pg_restore failed: %w\n%s", err, string(output)) - } - return nil -} - -// collectSQLFiles returns sorted .sql filenames from a directory. -func collectSQLFiles(dir string) ([]string, error) { - entries, err := os.ReadDir(dir) - if err != nil { - return nil, fmt.Errorf("reading directory %s: %w", dir, err) - } - var files []string - for _, e := range entries { - if !e.IsDir() && strings.HasSuffix(e.Name(), ".sql") { - files = append(files, e.Name()) - } - } - sort.Strings(files) - return files, nil -} - -// applySQLFiles executes all .sql files in a directory in sorted order. -func applySQLFiles(db *sql.DB, dir string) ([]string, error) { - files, err := collectSQLFiles(dir) - if err != nil { - return nil, err - } - - var applied []string - for _, f := range files { - path := filepath.Join(dir, f) - data, err := os.ReadFile(path) - if err != nil { - return applied, fmt.Errorf("reading %s: %w", f, err) - } - _, err = db.Exec(string(data)) - if err != nil { - return applied, fmt.Errorf("executing %s: %w", f, err) - } - applied = append(applied, f) - } - return applied, nil -} diff --git a/server/setup/wizard.html b/server/setup/wizard.html index 729235535..01c3e4742 100644 --- a/server/setup/wizard.html +++ b/server/setup/wizard.html @@ -122,9 +122,7 @@ h1{font-size:1.75rem;margin-bottom:.5rem;color:#e94560;text-align:center}

Select which schema operations to perform.

- - - +
@@ -208,9 +206,9 @@ function updateSchemaOptions() { createCheck.disabled = false; createLabel.style.opacity = '1'; } - // If tables already exist, uncheck init + // If tables already exist, uncheck schema (migrations will detect and skip) if (dbTestResult && dbTestResult.tablesExist) { - document.getElementById('chk-init').checked = false; + document.getElementById('chk-schema').checked = false; } } @@ -283,9 +281,7 @@ async function initDB() { password: document.getElementById('db-password').value, dbName: document.getElementById('db-name').value, createDB: document.getElementById('chk-create-db').checked, - applyInit: document.getElementById('chk-init').checked, - applyUpdate: document.getElementById('chk-update').checked, - applyPatch: document.getElementById('chk-patch').checked, + applySchema: document.getElementById('chk-schema').checked, applyBundled: document.getElementById('chk-bundled').checked, }) }); diff --git a/server/setup/wizard_test.go b/server/setup/wizard_test.go index 4587e4da0..9776cab99 100644 --- a/server/setup/wizard_test.go +++ b/server/setup/wizard_test.go @@ -130,44 +130,6 @@ func TestClientModes(t *testing.T) { } } -func TestApplySQLFiles(t *testing.T) { - // This test doesn't need a real database — we test the file reading/sorting logic - // by verifying it returns errors when the directory doesn't exist. - _, err := applySQLFiles(nil, "/nonexistent/path") - if err == nil { - t.Error("expected error for nonexistent directory") - } -} - -func TestApplySQLFilesOrdering(t *testing.T) { - // Verify that collectSQLFiles returns files in sorted order and skips non-.sql files. - dir := t.TempDir() - files := []string{"03_c.sql", "01_a.sql", "02_b.sql"} - for _, f := range files { - if err := os.WriteFile(filepath.Join(dir, f), []byte("-- "+f), 0644); err != nil { - t.Fatal(err) - } - } - // Non-SQL file should be skipped - if err := os.WriteFile(filepath.Join(dir, "readme.txt"), []byte("not sql"), 0644); err != nil { - t.Fatal(err) - } - - collected, err := collectSQLFiles(dir) - if err != nil { - t.Fatalf("collectSQLFiles failed: %v", err) - } - if len(collected) != 3 { - t.Fatalf("got %d files, want 3", len(collected)) - } - expected := []string{"01_a.sql", "02_b.sql", "03_c.sql"} - for i, f := range collected { - if f != expected[i] { - t.Errorf("file[%d] = %q, want %q", i, f, expected[i]) - } - } -} - func TestWriteConfig(t *testing.T) { dir := t.TempDir() origDir, _ := os.Getwd()