feat: add world travel database schema

This commit is contained in:
Bastian Wagner
2026-08-18 18:27:21 +02:00
parent 1210ba2d15
commit 492765d8ca
7 changed files with 399 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class CreateVisibleVerticalSlice1787072400000 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"');
await queryRunner.query(`CREATE TABLE "location_definitions" (
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"key" character varying(100) NOT NULL,
"name" character varying(150) NOT NULL,
"description" text NOT NULL,
"region_key" character varying(100) NOT NULL,
"min_recommended_level" integer NOT NULL,
"max_recommended_level" integer NOT NULL,
"danger_level" integer NOT NULL,
"is_safe" boolean NOT NULL,
"hunting_enabled" boolean NOT NULL,
"artwork_path" character varying(255) NOT NULL,
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
"updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
CONSTRAINT "PK_location_definitions" PRIMARY KEY ("id")
)`);
await queryRunner.query(
'CREATE UNIQUE INDEX "IDX_location_definitions_key" ON "location_definitions" ("key")',
);
await queryRunner.query(`CREATE TABLE "characters" (
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"name" character varying(150) NOT NULL,
"level" integer NOT NULL,
"experience" integer NOT NULL,
"base_hp" integer NOT NULL,
"base_attack" integer NOT NULL,
"current_hp" integer NOT NULL,
"current_location_id" uuid NOT NULL,
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
"updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
CONSTRAINT "PK_characters" PRIMARY KEY ("id"),
CONSTRAINT "FK_characters_current_location" FOREIGN KEY ("current_location_id") REFERENCES "location_definitions"("id") ON DELETE RESTRICT ON UPDATE NO ACTION
)`);
await queryRunner.query(
'CREATE INDEX "IDX_characters_current_location" ON "characters" ("current_location_id")',
);
await queryRunner.query(`CREATE TABLE "location_connections" (
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"from_location_id" uuid NOT NULL,
"to_location_id" uuid NOT NULL,
"travel_duration_seconds" integer NOT NULL,
"ambush_chance" numeric(5,4) NOT NULL,
"enabled" boolean NOT NULL,
CONSTRAINT "PK_location_connections" PRIMARY KEY ("id"),
CONSTRAINT "FK_location_connections_from_location" FOREIGN KEY ("from_location_id") REFERENCES "location_definitions"("id") ON DELETE RESTRICT ON UPDATE NO ACTION,
CONSTRAINT "FK_location_connections_to_location" FOREIGN KEY ("to_location_id") REFERENCES "location_definitions"("id") ON DELETE RESTRICT ON UPDATE NO ACTION
)`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_location_connection_direction"
ON "location_connections" ("from_location_id", "to_location_id")`);
await queryRunner.query(
'CREATE INDEX "IDX_location_connections_from_location" ON "location_connections" ("from_location_id")',
);
await queryRunner.query(
'CREATE INDEX "IDX_location_connections_to_location" ON "location_connections" ("to_location_id")',
);
await queryRunner.query(
"CREATE TYPE \"travel_status_enum\" AS ENUM ('TRAVELLING', 'COMPLETED')",
);
await queryRunner.query(`CREATE TABLE "travels" (
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"character_id" uuid NOT NULL,
"origin_location_id" uuid NOT NULL,
"target_location_id" uuid NOT NULL,
"started_at" TIMESTAMP WITH TIME ZONE NOT NULL,
"arrives_at" TIMESTAMP WITH TIME ZONE NOT NULL,
"status" "travel_status_enum" NOT NULL,
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
CONSTRAINT "PK_travels" PRIMARY KEY ("id"),
CONSTRAINT "FK_travels_character" FOREIGN KEY ("character_id") REFERENCES "characters"("id") ON DELETE RESTRICT ON UPDATE NO ACTION,
CONSTRAINT "FK_travels_origin_location" FOREIGN KEY ("origin_location_id") REFERENCES "location_definitions"("id") ON DELETE RESTRICT ON UPDATE NO ACTION,
CONSTRAINT "FK_travels_target_location" FOREIGN KEY ("target_location_id") REFERENCES "location_definitions"("id") ON DELETE RESTRICT ON UPDATE NO ACTION
)`);
await queryRunner.query(
'CREATE INDEX "IDX_travels_character" ON "travels" ("character_id")',
);
await queryRunner.query(
'CREATE INDEX "IDX_travels_origin_location" ON "travels" ("origin_location_id")',
);
await queryRunner.query(
'CREATE INDEX "IDX_travels_target_location" ON "travels" ("target_location_id")',
);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_active_travel_per_character"
ON "travels" ("character_id")
WHERE "status" = 'TRAVELLING'`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX "IDX_active_travel_per_character"');
await queryRunner.query('DROP INDEX "IDX_travels_target_location"');
await queryRunner.query('DROP INDEX "IDX_travels_origin_location"');
await queryRunner.query('DROP INDEX "IDX_travels_character"');
await queryRunner.query('DROP TABLE "travels"');
await queryRunner.query(
'DROP INDEX "IDX_location_connections_to_location"',
);
await queryRunner.query(
'DROP INDEX "IDX_location_connections_from_location"',
);
await queryRunner.query('DROP INDEX "IDX_location_connection_direction"');
await queryRunner.query('DROP TABLE "location_connections"');
await queryRunner.query('DROP INDEX "IDX_characters_current_location"');
await queryRunner.query('DROP TABLE "characters"');
await queryRunner.query('DROP INDEX "IDX_location_definitions_key"');
await queryRunner.query('DROP TABLE "location_definitions"');
await queryRunner.query('DROP TYPE "travel_status_enum"');
}
}