Merge branch 'v25'

This commit is contained in:
evanpelle
2025-09-18 11:26:53 -07:00
33 changed files with 508 additions and 374 deletions
+1
View File
@@ -44,6 +44,7 @@ export const PatternSchema = z
export const PatternInfoSchema = z.object({
name: PatternNameSchema,
pattern: PatternSchema,
affiliateCode: z.string().nullable(),
product: ProductSchema.nullable(),
});
+20 -3
View File
@@ -502,7 +502,7 @@ export const ClientMessageSchema = z.discriminatedUnion("type", [
//
export const PlayerRecordSchema = PlayerSchema.extend({
persistentID: PersistentIdSchema, // WARNING: PII
persistentID: PersistentIdSchema.nullable(), // WARNING: PII
stats: PlayerStatsSchema,
});
export type PlayerRecord = z.infer<typeof PlayerRecordSchema>;
@@ -517,18 +517,35 @@ export const GameEndInfoSchema = GameStartInfoSchema.extend({
});
export type GameEndInfo = z.infer<typeof GameEndInfoSchema>;
const GitCommitSchema = z.string().regex(/^[0-9a-fA-F]{40}$/);
const GitCommitSchema = z
.string()
.regex(/^[0-9a-fA-F]{40}$/)
.or(z.literal("DEV"));
export const AnalyticsRecordSchema = z.object({
export const PartialAnalyticsRecordSchema = z.object({
info: GameEndInfoSchema,
version: z.literal("v0.0.2"),
});
export type ClientAnalyticsRecord = z.infer<
typeof PartialAnalyticsRecordSchema
>;
export const AnalyticsRecordSchema = PartialAnalyticsRecordSchema.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 = PartialAnalyticsRecordSchema.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;
+1
View File
@@ -48,6 +48,7 @@ export interface ServerConfig {
r2Endpoint(): string;
r2AccessKey(): string;
r2SecretKey(): string;
apiKey(): string;
otelEndpoint(): string;
otelAuthHeader(): string;
otelEnabled(): boolean;
+4
View File
@@ -153,6 +153,10 @@ export abstract class DefaultServerConfig implements ServerConfig {
return process.env.R2_BUCKET ?? "";
}
apiKey(): string {
return process.env.API_KEY ?? "";
}
adminHeader(): string {
return "x-admin-key";
}
+4
View File
@@ -9,6 +9,10 @@ export class DevServerConfig extends DefaultServerConfig {
return "WARNING_DEV_ADMIN_KEY_DO_NOT_USE_IN_PRODUCTION";
}
apiKey(): string {
return "WARNING_DEV_API_KEY_DO_NOT_USE_IN_PRODUCTION";
}
env(): GameEnv {
return GameEnv.Dev;
}
+3 -1
View File
@@ -447,6 +447,9 @@ export class GameView implements GameMap {
);
}
});
this._myPlayer ??= this.playerByClientID(this._myClientID);
for (const unit of this._units.values()) {
unit._wasUpdated = false;
unit.lastPos = unit.lastPos.slice(-1);
@@ -507,7 +510,6 @@ export class GameView implements GameMap {
}
myPlayer(): PlayerView | null {
this._myPlayer ??= this.playerByClientID(this._myClientID);
return this._myPlayer;
}