mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-23 11:28:04 +00:00
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:
+18
-34
@@ -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(
|
||||
|
||||
@@ -393,7 +393,7 @@ export class GameServer {
|
||||
);
|
||||
}
|
||||
return {
|
||||
ip: ipAnonymize(client.ip),
|
||||
playerID: client.playerID,
|
||||
clientID: client.clientID,
|
||||
username: client.username,
|
||||
persistentID: client.persistentID,
|
||||
@@ -403,7 +403,7 @@ export class GameServer {
|
||||
archive(
|
||||
createGameRecord(
|
||||
this.id,
|
||||
this.gameStartInfo,
|
||||
this.gameStartInfo.config,
|
||||
playerRecords,
|
||||
this.turns,
|
||||
this._startTime ?? 0,
|
||||
|
||||
@@ -242,14 +242,12 @@ export function startWorker() {
|
||||
"/api/archive_singleplayer_game",
|
||||
gatekeeper.httpHandler(LimiterType.Post, async (req, res) => {
|
||||
const gameRecord: GameRecord = req.body;
|
||||
const clientIP = req.ip || req.socket.remoteAddress || "unknown";
|
||||
|
||||
if (!gameRecord) {
|
||||
log.info("game record not found in request");
|
||||
res.status(404).json({ error: "Game record not found" });
|
||||
return;
|
||||
}
|
||||
gameRecord.players.forEach((p) => (p.ip = clientIP));
|
||||
archive(gameRecord);
|
||||
res.json({
|
||||
success: true,
|
||||
|
||||
Reference in New Issue
Block a user