Combine analytics and game types (#839)

## Description:

Combine analytics and game types. Simplify and remove redundant player
information.

- Remove ip address.
- Add playerID.
- Combine redundant player tables.
- Move game metadata in to GameEndInfo type, an extension of
GameStartInfo

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors

---------

Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com>
This commit is contained in:
Scott Anderson
2025-05-22 15:06:30 -04:00
committed by GitHub
parent 373de1a752
commit 9302af868d
14 changed files with 75 additions and 104 deletions
+18 -34
View File
@@ -1,6 +1,6 @@
import { S3 } from "@aws-sdk/client-s3";
import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
import { GameID, GameRecord } from "../core/Schemas";
import { AnalyticsRecord, GameID, GameRecord } from "../core/Schemas";
import { logger } from "./Logger";
const config = getServerConfigFromServer();
@@ -30,12 +30,12 @@ export async function archive(gameRecord: GameRecord) {
// Archive full game if there are turns
if (gameRecord.turns.length > 0) {
log.info(
`${gameRecord.id}: game has more than zero turns, attempting to write to full game to R2`,
`${gameRecord.info.gameID}: game has more than zero turns, attempting to write to full game to R2`,
);
await archiveFullGameToR2(gameRecord);
}
} catch (error) {
log.error(`${gameRecord.id}: Final archive error: ${error}`, {
log.error(`${gameRecord.info.gameID}: Final archive error: ${error}`, {
message: error?.message || error,
stack: error?.stack,
name: error?.name,
@@ -46,29 +46,16 @@ export async function archive(gameRecord: GameRecord) {
async function archiveAnalyticsToR2(gameRecord: GameRecord) {
// Create analytics data object
const analyticsData = {
id: gameRecord.id,
env: config.env(),
start_time: new Date(gameRecord.startTimestampMS).toISOString(),
end_time: new Date(gameRecord.endTimestampMS).toISOString(),
duration_seconds: gameRecord.durationSeconds,
number_turns: gameRecord.num_turns,
game_mode: gameRecord.gameStartInfo.config.gameType,
winner: gameRecord.winner,
difficulty: gameRecord.gameStartInfo.config.difficulty,
mapType: gameRecord.gameStartInfo.config.gameMap,
players: gameRecord.players.map((p) => ({
username: p.username,
ip: p.ip,
persistentID: p.persistentID,
clientID: p.clientID,
stats: p.stats,
})),
const { info, version, gitCommit } = gameRecord;
const analyticsData: AnalyticsRecord = {
info,
version,
gitCommit,
};
try {
// Store analytics data using just the game ID as the key
const analyticsKey = `${gameRecord.id}.json`;
const analyticsKey = `${info.gameID}.json`;
await r2.putObject({
Bucket: bucket,
@@ -77,17 +64,14 @@ async function archiveAnalyticsToR2(gameRecord: GameRecord) {
ContentType: "application/json",
});
log.info(`${gameRecord.id}: successfully wrote game analytics to R2`);
log.info(`${info.gameID}: successfully wrote game analytics to R2`);
} catch (error) {
log.error(
`${gameRecord.id}: Error writing game analytics to R2: ${error}`,
{
message: error?.message || error,
stack: error?.stack,
name: error?.name,
...(error && typeof error === "object" ? error : {}),
},
);
log.error(`${info.gameID}: Error writing game analytics to R2: ${error}`, {
message: error?.message || error,
stack: error?.stack,
name: error?.name,
...(error && typeof error === "object" ? error : {}),
});
throw error;
}
}
@@ -110,11 +94,11 @@ async function archiveFullGameToR2(gameRecord: GameRecord) {
ContentType: "application/json",
});
} catch (error) {
log.error(`error saving game ${gameRecord.id}`);
log.error(`error saving game ${gameRecord.info.gameID}`);
throw error;
}
log.info(`${gameRecord.id}: game record successfully written to R2`);
log.info(`${gameRecord.info.gameID}: game record successfully written to R2`);
}
export async function readGameRecord(