feat: add ranking and hall of fame features

- Implemented new routes for Best General and Hall of Fame views in the frontend.
- Created BestGeneralView and HallOfFameView components to display rankings based on game data.
- Added new database models for RankData and HallOfFame to store ranking information.
- Introduced ranking types and hall of fame types in common types for better type safety.
- Developed ranking router to handle fetching of best general and hall of fame data.
- Updated database schema with migrations to include new tables for rank data and hall of fame.
- Enhanced the main view with links to the new ranking features.
This commit is contained in:
2026-01-29 18:18:35 +00:00
parent 19c359d0b2
commit 9fff671c2f
16 changed files with 1217 additions and 2 deletions
+47
View File
@@ -146,6 +146,53 @@ model General {
@@map("general")
}
model RankData {
id Int @id @default(autoincrement())
nationId Int @default(0) @map("nation_id")
generalId Int @map("general_id")
type String @db.VarChar(20)
value Int @default(0)
@@unique([generalId, type])
@@index([type, value], name: "by_type")
@@index([nationId, type, value], name: "by_nation")
@@map("rank_data")
}
model HallOfFame {
id Int @id @default(autoincrement())
serverId String @map("server_id")
season Int
scenario Int
generalNo Int @map("general_no")
type String @db.VarChar(20)
value Float
owner String? @map("owner")
aux Json @default(dbgenerated("'{}'::jsonb"))
@@unique([serverId, type, generalNo])
@@unique([owner, serverId, type], name: "hall_owner")
@@index([serverId, type, value], name: "server_show")
@@index([season, scenario, type, value], name: "scenario")
@@map("hall")
}
model GameHistory {
id Int @id @default(autoincrement())
serverId String @map("server_id")
date DateTime
winnerNation Int? @map("winner_nation")
map String? @map("map")
season Int
scenario Int
scenarioName String @map("scenario_name")
env Json @default(dbgenerated("'{}'::jsonb"))
@@unique([serverId])
@@index([date])
@@map("ng_games")
}
model Troop {
troopLeaderId Int @id @map("troop_leader")
nationId Int @map("nation")
@@ -0,0 +1,43 @@
CREATE TABLE "rank_data" (
"id" SERIAL PRIMARY KEY,
"nation_id" INTEGER NOT NULL DEFAULT 0,
"general_id" INTEGER NOT NULL,
"type" VARCHAR(20) NOT NULL,
"value" INTEGER NOT NULL DEFAULT 0
);
CREATE UNIQUE INDEX "rank_data_by_general" ON "rank_data"("general_id", "type");
CREATE INDEX "rank_data_by_type" ON "rank_data"("type", "value");
CREATE INDEX "rank_data_by_nation" ON "rank_data"("nation_id", "type", "value");
CREATE TABLE "hall" (
"id" SERIAL PRIMARY KEY,
"server_id" TEXT NOT NULL,
"season" INTEGER NOT NULL,
"scenario" INTEGER NOT NULL,
"general_no" INTEGER NOT NULL,
"type" VARCHAR(20) NOT NULL,
"value" DOUBLE PRECISION NOT NULL,
"owner" TEXT,
"aux" JSONB NOT NULL DEFAULT '{}'::jsonb
);
CREATE UNIQUE INDEX "hall_server_general" ON "hall"("server_id", "type", "general_no");
CREATE UNIQUE INDEX "hall_owner" ON "hall"("owner", "server_id", "type");
CREATE INDEX "hall_server_show" ON "hall"("server_id", "type", "value");
CREATE INDEX "hall_scenario" ON "hall"("season", "scenario", "type", "value");
CREATE TABLE "ng_games" (
"id" SERIAL PRIMARY KEY,
"server_id" TEXT NOT NULL,
"date" TIMESTAMP(3) NOT NULL,
"winner_nation" INTEGER,
"map" TEXT,
"season" INTEGER NOT NULL,
"scenario" INTEGER NOT NULL,
"scenario_name" TEXT NOT NULL,
"env" JSONB NOT NULL DEFAULT '{}'::jsonb
);
CREATE UNIQUE INDEX "ng_games_server_id" ON "ng_games"("server_id");
CREATE INDEX "ng_games_date" ON "ng_games"("date");