From 601f606a7f0cfaf02a33196f1bcc471b29081d9d Mon Sep 17 00:00:00 2001 From: evanpelle Date: Mon, 9 Dec 2024 14:36:51 -0800 Subject: [PATCH] save game stats to bigquery, update enums --- src/client/HostLobbyModal.ts | 4 ++-- src/client/SinglePlayerModal.ts | 8 ++++---- src/core/Schemas.ts | 1 + src/core/Util.ts | 1 + src/core/configuration/Config.ts | 3 ++- src/core/configuration/DefaultConfig.ts | 15 ++++++++++++++- src/core/execution/ExecutionManager.ts | 2 +- src/core/game/Game.ts | 24 ++++++++++++------------ src/server/Archive.ts | 20 ++++++++++++++++++++ 9 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts index ee52675a5..f7a55cc4f 100644 --- a/src/client/HostLobbyModal.ts +++ b/src/client/HostLobbyModal.ts @@ -167,13 +167,13 @@ export class HostLobbyModal extends LitElement { } private async handleMapChange(e: Event) { - this.selectedMap = Number((e.target as HTMLSelectElement).value) as GameMap; + this.selectedMap = String((e.target as HTMLSelectElement).value) as GameMap; console.log(`updating map to ${this.selectedMap}`) this.putGameConfig() } private async handleDifficultyChange(e: Event) { - this.selectedDiffculty = Number((e.target as HTMLSelectElement).value) as Difficulty; + this.selectedDiffculty = String((e.target as HTMLSelectElement).value) as Difficulty; console.log(`updating difficulty to ${this.selectedDiffculty}`) this.putGameConfig() } diff --git a/src/client/SinglePlayerModal.ts b/src/client/SinglePlayerModal.ts index b2810bd39..a4fbfb759 100644 --- a/src/client/SinglePlayerModal.ts +++ b/src/client/SinglePlayerModal.ts @@ -84,7 +84,7 @@ export class SinglePlayerModal extends LitElement { .filter(([key]) => isNaN(Number(key))) .map(([key, value]) => html` `)} @@ -96,7 +96,7 @@ export class SinglePlayerModal extends LitElement { .filter(([key]) => isNaN(Number(key))) .map(([key, value]) => html` `)} @@ -117,10 +117,10 @@ export class SinglePlayerModal extends LitElement { } private handleMapChange(e: Event) { - this.selectedMap = Number((e.target as HTMLSelectElement).value) as GameMap; + this.selectedMap = String((e.target as HTMLSelectElement).value) as GameMap; } private handleDifficultyChange(e: Event) { - this.selectedDifficulty = Number((e.target as HTMLSelectElement).value) as Difficulty; + this.selectedDifficulty = String((e.target as HTMLSelectElement).value) as Difficulty; } private startGame() { console.log(`Starting single player game with map: ${GameMap[this.selectedMap]}`); diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts index 8b22023f5..262539116 100644 --- a/src/core/Schemas.ts +++ b/src/core/Schemas.ts @@ -242,5 +242,6 @@ export const GameRecordSchema = z.object({ durationSeconds: z.number(), date: z.string(), usernames: z.array(z.string()), + num_turns: z.number(), turns: z.array(TurnSchema) }) \ No newline at end of file diff --git a/src/core/Util.ts b/src/core/Util.ts index 9873d9693..39fcdadf7 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -246,6 +246,7 @@ export function CreateGameRecord(id: GameID, gameConfig: GameConfig, turns: Turn } record.usernames = Array.from(usernames) record.durationSeconds = Math.floor((record.endTimestampMS - record.startTimestampMS) / 1000) + record.num_turns = turns.length return record; } diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts index 30cf8854a..d08524820 100644 --- a/src/core/configuration/Config.ts +++ b/src/core/configuration/Config.ts @@ -1,4 +1,4 @@ -import { GameType, Gold, Player, PlayerID, PlayerInfo, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "../game/Game"; +import { Difficulty, GameType, Gold, Player, PlayerID, PlayerInfo, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "../game/Game"; import { Colord, colord } from "colord"; import { devConfig } from "./DevConfig"; import { defaultConfig } from "./DefaultConfig"; @@ -64,6 +64,7 @@ export interface Config { defensePostRange(): number defensePostDefenseBonus(): number falloutDefenseModifier(): number + difficultyModifier(difficulty: Difficulty): number } export interface Theme { diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 5a1f84914..6faf08363 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -1,4 +1,4 @@ -import { GameType, Gold, Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "../game/Game"; +import { Difficulty, GameType, Gold, Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "../game/Game"; import { GameID } from "../Schemas"; import { assertNever, distSort, manhattanDist, simpleHash, within } from "../Util"; import { Config, Theme } from "./Config"; @@ -7,6 +7,19 @@ import { pastelTheme } from "./PastelTheme"; export class DefaultConfig implements Config { + difficultyModifier(difficulty: Difficulty): number { + switch (difficulty) { + case Difficulty.Easy: + return 1 + case Difficulty.Medium: + return 3 + case Difficulty.Hard: + return 9 + case Difficulty.Impossible: + return 18 + } + } + cityPopulationIncrease(): number { return 250_000 diff --git a/src/core/execution/ExecutionManager.ts b/src/core/execution/ExecutionManager.ts index 4bfbdfdee..b1811b056 100644 --- a/src/core/execution/ExecutionManager.ts +++ b/src/core/execution/ExecutionManager.ts @@ -125,7 +125,7 @@ export class Executor { this.random.nextID() ), nation.cell, - nation.strength * this.gs.gameConfig().difficulty + nation.strength * this.gs.config().difficultyModifier(this.gs.gameConfig().difficulty) )) } return execs diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 29467f096..9313c2150 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -11,24 +11,24 @@ export type Gold = number export const AllPlayers = "AllPlayers" as const; export enum Difficulty { - Easy = 1, - Medium = 3, - Hard = 9, - Impossible = 18, + Easy = "Easy", + Medium = "Medium", + Hard = "Hard", + Impossible = "Impossible", } export enum GameMap { - World, - Europe, - Mena, - NorthAmerica, - Oceania + World = "World", + Europe = "Europe", + Mena = "Mena", + NorthAmerica = "North America", + Oceania = "Oceania" } export enum GameType { - Singleplayer, - Public, - Private, + Singleplayer = "Singleplayer", + Public = "Public", + Private = "Private", } export interface UnitInfo { diff --git a/src/server/Archive.ts b/src/server/Archive.ts index e3e838568..c8cfe615b 100644 --- a/src/server/Archive.ts +++ b/src/server/Archive.ts @@ -14,6 +14,26 @@ export async function archive(gameRecord: GameRecord) { await file.save(JSON.stringify(GameRecordSchema.parse(gameRecord)), { contentType: 'application/json' }); + // Save metadata to BigQuery + const row = { + id: gameRecord.id, + start: new Date(gameRecord.startTimestampMS), + end: new Date(gameRecord.endTimestampMS), + duration_seconds: gameRecord.durationSeconds, + number_turns: gameRecord.num_turns, + usernames: gameRecord.usernames, + game_mode: gameRecord.gameConfig.gameType, + winner: null, + difficulty: gameRecord.gameConfig.difficulty, + map: gameRecord.gameConfig.gameMap, + }; + + await bigquery + .dataset('game_archive') + .table('game_results') + .insert([row]); + + console.log(`wrote game metadata to BigQuery: ${gameRecord.id}`); } catch (error) { console.log(`error writing to gcs: ${error}`) }