feat: remove LocalPersistantStats so we locally save GameRecords

GameRecords also now include PlayerStats
This commit is contained in:
ilan schemoul
2025-03-08 17:39:41 +01:00
parent 2b8cc2cf28
commit 1b76c46bc5
15 changed files with 157 additions and 123 deletions
+21
View File
@@ -77,6 +77,9 @@ export type ClientHashMessage = z.infer<typeof ClientHashSchema>;
export type PlayerRecord = z.infer<typeof PlayerRecordSchema>;
export type GameRecord = z.infer<typeof GameRecordSchema>;
export type AllPlayersStats = z.infer<typeof AllPlayersStatsSchema>;
export type PlayerStats = z.infer<typeof PlayerStatsSchema>;
const PlayerTypeSchema = z.nativeEnum(PlayerType);
export interface GameInfo {
@@ -132,6 +135,21 @@ const ID = z
.regex(/^[a-zA-Z0-9]+$/)
.length(8);
const NukesEnum = z.enum([
"Atom Bomb",
"Hydrogen Bomb",
"MIRV",
"MIRV Warhead",
]);
const NukeStatsSchema = z.record(NukesEnum, z.number());
export const PlayerStatsSchema = z.object({
sentNukes: z.record(ID, NukeStatsSchema),
});
export const AllPlayersStatsSchema = z.record(ID, PlayerStatsSchema);
// Zod schemas
const BaseIntentSchema = z.object({
type: z.enum([
@@ -313,6 +331,7 @@ const ClientBaseMessageSchema = z.object({
export const ClientSendWinnerSchema = ClientBaseMessageSchema.extend({
type: z.literal("winner"),
winner: ID.nullable(),
allPlayersStats: AllPlayersStatsSchema,
});
export const ClientHashSchema = ClientBaseMessageSchema.extend({
@@ -371,4 +390,6 @@ export const GameRecordSchema = z.object({
num_turns: z.number(),
turns: z.array(TurnSchema),
winner: ID.nullable(),
allPlayersStats: z.record(ID, PlayerStatsSchema),
version: z.enum(["v0.0.1"]),
});
+5
View File
@@ -3,11 +3,13 @@ import twemoji from "twemoji";
import DOMPurify from "dompurify";
import { Cell, Game, Player, Unit } from "./game/Game";
import {
AllPlayersStats,
ClientID,
GameConfig,
GameID,
GameRecord,
PlayerRecord,
PlayerStats,
Turn,
} from "./Schemas";
import { customAlphabet, nanoid } from "nanoid";
@@ -262,6 +264,7 @@ export function CreateGameRecord(
start: number,
end: number,
winner: ClientID | null,
allPlayersStats: AllPlayersStats,
): GameRecord {
const record: GameRecord = {
id: id,
@@ -270,6 +273,8 @@ export function CreateGameRecord(
endTimestampMS: end,
date: new Date().toISOString().split("T")[0],
turns: [],
allPlayersStats,
version: "v0.0.1",
};
for (const turn of turns) {
+1 -1
View File
@@ -33,7 +33,7 @@ export class WinCheckExecution implements Execution {
(max.numTilesOwned() / numTilesWithoutFallout) * 100 >
this.mg.config().percentageTilesOwnedToWin()
) {
this.mg.setWinner(max);
this.mg.setWinner(max, this.mg.stats().stats());
console.log(`${max.name()} has won the game`);
this.active = false;
}
+3 -3
View File
@@ -1,7 +1,7 @@
import { Config } from "../configuration/Config";
import { GameEvent } from "../EventBus";
import { PlayerView } from "./GameView";
import { ClientID, GameConfig, GameID } from "../Schemas";
import { ClientID, GameConfig, GameID, AllPlayersStats } from "../Schemas";
import { GameMap, GameMapImpl, TileRef } from "./GameMap";
import {
GameUpdate,
@@ -9,7 +9,7 @@ import {
PlayerUpdate,
UnitUpdate,
} from "./GameUpdates";
import { PlayerStats, Stats } from "./Stats";
import { Stats } from "./Stats";
export type PlayerID = string;
export type Tick = number;
@@ -378,7 +378,7 @@ export interface Game extends GameMap {
ticks(): Tick;
inSpawnPhase(): boolean;
executeNextTick(): GameUpdates;
setWinner(winner: Player): void;
setWinner(winner: Player, allPlayersStats: AllPlayersStats): void;
config(): Config;
// Units
+3 -2
View File
@@ -24,7 +24,7 @@ import { PlayerImpl } from "./PlayerImpl";
import { TerraNulliusImpl } from "./TerraNulliusImpl";
import { AllianceRequestImpl } from "./AllianceRequestImpl";
import { AllianceImpl } from "./AllianceImpl";
import { ClientID, GameConfig } from "../Schemas";
import { ClientID, AllPlayersStats } from "../Schemas";
import { MessageType } from "./Game";
import { UnitImpl } from "./UnitImpl";
import { consolex } from "../Consolex";
@@ -516,10 +516,11 @@ export class GameImpl implements Game {
});
}
setWinner(winner: Player): void {
setWinner(winner: Player, allPlayersStats: AllPlayersStats): void {
this.addUpdate({
type: GameUpdateType.Win,
winnerID: winner.smallID(),
allPlayersStats,
});
}
+2 -2
View File
@@ -1,4 +1,4 @@
import { ClientID } from "../Schemas";
import { ClientID, PlayerStats, AllPlayersStats } from "../Schemas";
import {
AllianceRequest,
EmojiMessage,
@@ -12,7 +12,6 @@ import {
UnitType,
} from "./Game";
import { TileRef, TileUpdate } from "./GameMap";
import { PlayerStats } from "./Stats";
export interface GameUpdateViewData {
tick: number;
@@ -156,6 +155,7 @@ export interface DisplayMessageUpdate {
export interface WinUpdate {
type: GameUpdateType.Win;
allPlayersStats: AllPlayersStats;
winnerID: number;
}
+1 -2
View File
@@ -24,13 +24,12 @@ import {
UnitInfo,
UnitType,
} from "./Game";
import { ClientID, GameID } from "../Schemas";
import { ClientID, GameID, PlayerStats } from "../Schemas";
import { TerraNulliusImpl } from "./TerraNulliusImpl";
import { WorkerClient } from "../worker/WorkerClient";
import { GameMap, GameMapImpl, TileRef, TileUpdate } from "./GameMap";
import { GameUpdateViewData } from "./GameUpdates";
import { DefenseGrid } from "./DefensePostGrid";
import { PlayerStats } from "./Stats";
export class UnitView {
public _wasUpdated = true;
+2 -9
View File
@@ -1,15 +1,8 @@
import { AllPlayersStats, PlayerStats } from "../Schemas";
import { NukeType, PlayerID } from "./Game";
export interface PlayerStats {
sentNukes: {
// target
[key: PlayerID]: {
[key in NukeType]: number;
};
};
}
export interface Stats {
increaseNukeCount(sender: PlayerID, target: PlayerID, type: NukeType): void;
getPlayerStats(player: PlayerID): PlayerStats;
stats(): AllPlayersStats;
}
+8 -8
View File
@@ -1,13 +1,9 @@
import { NukeType, Player, PlayerID, UnitType } from "./Game";
import { PlayerStats, Stats } from "./Stats";
interface StatsInternalData {
// player
[key: PlayerID]: PlayerStats;
}
import { AllPlayersStats, PlayerStats } from "../Schemas";
import { NukeType, PlayerID, UnitType } from "./Game";
import { Stats } from "./Stats";
export class StatsImpl implements Stats {
data: StatsInternalData = {};
data: AllPlayersStats = {};
_createUserData(sender: PlayerID, target: PlayerID): void {
if (!this.data[sender]) {
@@ -31,4 +27,8 @@ export class StatsImpl implements Stats {
getPlayerStats(player: PlayerID): PlayerStats {
return this.data[player];
}
stats() {
return this.data;
}
}