fix archive

This commit is contained in:
evanpelle
2025-09-09 12:39:49 -07:00
parent defb6bb1d4
commit 8c21c53f74
8 changed files with 66 additions and 43 deletions
+2 -3
View File
@@ -8,7 +8,7 @@ import {
PlayerRecord,
ServerMessage,
} from "../core/Schemas";
import { createGameRecord } from "../core/Util";
import { createPartialGameRecord } from "../core/Util";
import { ServerConfig } from "../core/configuration/Config";
import { getConfig } from "../core/configuration/ConfigLoader";
import { PlayerActions, UnitType } from "../core/game/Game";
@@ -221,7 +221,7 @@ export class ClientGameRunner {
if (this.lobby.gameStartInfo === undefined) {
throw new Error("missing gameStartInfo");
}
const record = createGameRecord(
const record = createPartialGameRecord(
this.lobby.gameStartInfo.gameID,
this.lobby.gameStartInfo.config,
players,
@@ -230,7 +230,6 @@ export class ClientGameRunner {
startTime(),
Date.now(),
update.winner,
this.lobby.serverConfig,
);
endGame(record);
}
+3 -3
View File
@@ -1,11 +1,11 @@
import { GameConfig, GameID, GameRecord } from "../core/Schemas";
import { GameConfig, GameID, PartialGameRecord } from "../core/Schemas";
import { replacer } from "../core/Util";
export interface LocalStatsData {
[key: GameID]: {
lobby: Partial<GameConfig>;
// Only once the game is over
gameRecord?: GameRecord;
gameRecord?: PartialGameRecord;
};
}
@@ -41,7 +41,7 @@ export function startTime() {
return _startTime;
}
export function endGame(gameRecord: GameRecord) {
export function endGame(gameRecord: PartialGameRecord) {
if (localStorage === undefined) {
return;
}
+6 -3
View File
@@ -11,7 +11,11 @@ import {
ServerStartGameMessage,
Turn,
} from "../core/Schemas";
import { createGameRecord, decompressGameRecord, replacer } from "../core/Util";
import {
createPartialGameRecord,
decompressGameRecord,
replacer,
} from "../core/Util";
import { LobbyConfig } from "./ClientGameRunner";
import { ReplaySpeedChangeEvent } from "./InputHandler";
import { getPersistentID } from "./Main";
@@ -188,7 +192,7 @@ export class LocalServer {
if (this.lobbyConfig.gameStartInfo === undefined) {
throw new Error("missing gameStartInfo");
}
const record = createGameRecord(
const record = createPartialGameRecord(
this.lobbyConfig.gameStartInfo.gameID,
this.lobbyConfig.gameStartInfo.config,
players,
@@ -196,7 +200,6 @@ export class LocalServer {
this.startedAt,
Date.now(),
this.winner?.winner,
this.lobbyConfig.serverConfig,
);
const result = GameRecordSchema.safeParse(record);
+13 -1
View File
@@ -512,16 +512,28 @@ const GitCommitSchema = z
.regex(/^[0-9a-fA-F]{40}$/)
.or(z.literal("DEV"));
export const AnalyticsRecordSchema = z.object({
export const ClientAnalyticsRecordSchema = z.object({
info: GameEndInfoSchema,
version: z.literal("v0.0.2"),
});
export type ClientAnalyticsRecord = z.infer<typeof ClientAnalyticsRecordSchema>;
export const AnalyticsRecordSchema = ClientAnalyticsRecordSchema.extend({
gitCommit: GitCommitSchema,
subdomain: z.string(),
domain: z.string(),
});
export type AnalyticsRecord = z.infer<typeof AnalyticsRecordSchema>;
export const GameRecordSchema = AnalyticsRecordSchema.extend({
turns: TurnSchema.array(),
});
export const PartialGameRecordSchema = ClientAnalyticsRecordSchema.extend({
turns: TurnSchema.array(),
});
export type PartialGameRecord = z.infer<typeof PartialGameRecordSchema>;
export type GameRecord = z.infer<typeof GameRecordSchema>;
+5 -13
View File
@@ -6,12 +6,12 @@ import {
GameConfig,
GameID,
GameRecord,
PartialGameRecord,
PlayerRecord,
Turn,
Winner,
} from "./Schemas";
import { ServerConfig } from "./configuration/Config";
import {
BOT_NAME_PREFIXES,
BOT_NAME_SUFFIXES,
@@ -150,7 +150,7 @@ export function onlyImages(html: string) {
});
}
export function createGameRecord(
export function createPartialGameRecord(
gameID: GameID,
config: GameConfig,
// username does not need to be set.
@@ -159,18 +159,13 @@ export function createGameRecord(
start: number,
end: number,
winner: Winner,
serverConfig: ServerConfig,
): GameRecord {
): PartialGameRecord {
const duration = Math.floor((end - start) / 1000);
const version = "v0.0.2";
const gitCommit = serverConfig.gitCommit();
const subdomain = serverConfig.subdomain();
const domain = serverConfig.domain();
const num_turns = allTurns.length;
const turns = allTurns.filter(
(t) => t.intents.length !== 0 || t.hash !== undefined,
);
const record: GameRecord = {
const record: PartialGameRecord = {
info: {
gameID,
config,
@@ -181,10 +176,7 @@ export function createGameRecord(
num_turns,
winner,
},
version,
gitCommit,
subdomain,
domain,
version: "v0.0.2",
turns,
};
return record;
+18 -1
View File
@@ -1,5 +1,11 @@
import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
import { GameID, GameRecord, GameRecordSchema, ID } from "../core/Schemas";
import {
GameID,
GameRecord,
GameRecordSchema,
ID,
PartialGameRecord,
} from "../core/Schemas";
import { logger } from "./Logger";
const config = getServerConfigFromServer();
@@ -62,3 +68,14 @@ export async function readGameRecord(
return null;
}
}
export function finalizeGameRecord(
clientRecord: PartialGameRecord,
): GameRecord {
return {
...clientRecord,
gitCommit: config.gitCommit(),
subdomain: config.subdomain(),
domain: config.domain(),
};
}
+14 -13
View File
@@ -2,6 +2,8 @@ import ipAnonymize from "ip-anonymize";
import { Logger } from "winston";
import WebSocket from "ws";
import { z } from "zod";
import { GameEnv, ServerConfig } from "../core/configuration/Config";
import { GameType } from "../core/game/Game";
import {
ClientID,
ClientMessageSchema,
@@ -19,10 +21,8 @@ import {
ServerTurnMessage,
Turn,
} from "../core/Schemas";
import { createGameRecord } from "../core/Util";
import { GameEnv, ServerConfig } from "../core/configuration/Config";
import { GameType } from "../core/game/Game";
import { archive } from "./Archive";
import { createPartialGameRecord } from "../core/Util";
import { archive, finalizeGameRecord } from "./Archive";
import { Client } from "./Client";
export enum GamePhase {
Lobby = "LOBBY",
@@ -680,15 +680,16 @@ export class GameServer {
},
);
archive(
createGameRecord(
this.id,
this.gameStartInfo.config,
playerRecords,
this.turns,
this._startTime ?? 0,
Date.now(),
this.winner?.winner,
this.config,
finalizeGameRecord(
createPartialGameRecord(
this.id,
this.gameStartInfo.config,
playerRecords,
this.turns,
this._startTime ?? 0,
Date.now(),
this.winner?.winner,
),
),
);
}
+5 -6
View File
@@ -12,13 +12,12 @@ import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
import { GameType } from "../core/game/Game";
import {
ClientMessageSchema,
GameRecord,
GameRecordSchema,
ID,
PartialGameRecordSchema,
ServerErrorMessage,
} from "../core/Schemas";
import { CreateGameInputSchema, GameInputSchema } from "../core/WorkerSchemas";
import { archive, readGameRecord } from "./Archive";
import { archive, finalizeGameRecord, readGameRecord } from "./Archive";
import { Client } from "./Client";
import { GameManager } from "./GameManager";
import { getUserMe, verifyClientToken } from "./jwt";
@@ -252,13 +251,13 @@ export async function startWorker() {
try {
const record = req.body;
const result = GameRecordSchema.safeParse(record);
const result = PartialGameRecordSchema.safeParse(record);
if (!result.success) {
const error = z.prettifyError(result.error);
log.info(error);
return res.status(400).json({ error });
}
const gameRecord: GameRecord = result.data;
const gameRecord = result.data;
if (gameRecord.info.config.gameType !== GameType.Singleplayer) {
log.warn(
@@ -277,7 +276,7 @@ export async function startWorker() {
return res.status(400).json({ error: "Invalid request" });
}
archive(gameRecord);
archive(finalizeGameRecord(gameRecord));
res.json({
success: true,
});