Add clanTag to GameRecord for archiving (#2314)

## Description:

This will be used to determine clan winners in the api layer.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
This commit is contained in:
Evan
2025-10-27 20:05:09 -07:00
committed by GitHub
parent b8fab0d359
commit 3fd38e7306
6 changed files with 21 additions and 9 deletions
+5 -1
View File
@@ -11,8 +11,12 @@ export default {
},
transform: {
"^.+\\.tsx?$": ["@swc/jest"],
"^.+\\.mjs$": ["@swc/jest"],
"^.+\\.js$": ["@swc/jest"],
},
transformIgnorePatterns: ["node_modules/(?!(node:)/)"],
transformIgnorePatterns: [
"node_modules/(?!(nanoid|@jsep|fastpriorityqueue|@datastructures-js)/)",
],
collectCoverageFrom: ["src/**/*.ts", "!src/**/*.d.ts"],
coverageThreshold: {
global: {
+2
View File
@@ -14,6 +14,7 @@ import {
import {
createPartialGameRecord,
decompressGameRecord,
getClanTag,
replacer,
} from "../core/Util";
import { LobbyConfig } from "./ClientGameRunner";
@@ -188,6 +189,7 @@ export class LocalServer {
clientID: this.lobbyConfig.clientID,
stats: this.allPlayersStats[this.lobbyConfig.clientID],
cosmetics: this.lobbyConfig.gameStartInfo?.players[0].cosmetics,
clanTag: getClanTag(this.lobbyConfig.playerName) ?? undefined,
},
];
if (this.lobbyConfig.gameStartInfo === undefined) {
+1
View File
@@ -544,6 +544,7 @@ export const ClientMessageSchema = z.discriminatedUnion("type", [
export const PlayerRecordSchema = PlayerSchema.extend({
persistentID: PersistentIdSchema.nullable(), // WARNING: PII
clanTag: z.string().optional(),
stats: PlayerStatsSchema,
});
export type PlayerRecord = z.infer<typeof PlayerRecordSchema>;
+9
View File
@@ -320,3 +320,12 @@ export function sigmoid(
): number {
return 1 / (1 + Math.exp(-decayRate * (value - midpoint)));
}
// Compute clan from name
export function getClanTag(name: string): string | null {
if (!name.includes("[") || !name.includes("]")) {
return null;
}
const clanMatch = name.match(/\[([a-zA-Z0-9]{2,5})\]/);
return clanMatch ? clanMatch[1].toUpperCase() : null;
}
+2 -7
View File
@@ -1,5 +1,6 @@
import { Config } from "../configuration/Config";
import { AllPlayersStats, ClientID } from "../Schemas";
import { getClanTag } from "../Util";
import { GameMap, TileRef } from "./GameMap";
import {
GameUpdate,
@@ -407,13 +408,7 @@ export class PlayerInfo {
public readonly id: PlayerID,
public readonly nation?: Nation | null,
) {
// Compute clan from name
if (!name.includes("[") || !name.includes("]")) {
this.clan = null;
} else {
const clanMatch = name.match(/\[([a-zA-Z0-9]{2,5})\]/);
this.clan = clanMatch ? clanMatch[1].toUpperCase() : null;
}
this.clan = getClanTag(name);
}
}
+2 -1
View File
@@ -21,7 +21,7 @@ import {
ServerTurnMessage,
Turn,
} from "../core/Schemas";
import { createPartialGameRecord } from "../core/Util";
import { createPartialGameRecord, getClanTag } from "../core/Util";
import { archive, finalizeGameRecord } from "./Archive";
import { Client } from "./Client";
export enum GamePhase {
@@ -686,6 +686,7 @@ export class GameServer {
this.allClients.get(player.clientID)?.persistentID ?? "",
stats,
cosmetics: player.cosmetics,
clanTag: getClanTag(player.username) ?? undefined,
} satisfies PlayerRecord;
},
);