import { GamesLogError } from "./errors/games_log_error.js"; import { GamesLogParser, LogData } from "./games_log_parser.js"; import { GameEvent } from "../game/events/game_event.js"; import { GameStartedEvent } from "../game/events/game_started_event.js"; import { PlayerJoinedEvent } from "../game/events/player_joined_event.js"; import { PlayerRolledEvent } from "../game/events/player_rolled_event.js"; export class GamesLog { private logData: LogData = []; private gamesLogParser = new GamesLogParser(); async loadFile(filename: string, encoding?: BufferEncoding) { this.logData = await this.gamesLogParser.parseFile(filename, encoding); } async readEvents() { return this.logData.map((row, rowNumber) => { const payload = row.eventPayload; const requireProperties = this.requirePropertiesFor(payload, rowNumber); let gameEvent: GameEvent; switch (row.eventType) { case "player_rolls_dice": requireProperties("gameId", "playerId", "roll"); gameEvent = new PlayerRolledEvent( payload.gameId, payload.playerId, payload.roll ); break; case "player_joins_game": requireProperties("gameId", "playerId"); gameEvent = new PlayerJoinedEvent(payload.gameId, payload.playerId); break; case "game_started": requireProperties("gameId"); gameEvent = new GameStartedEvent(payload.gameId); break; default: throw new Error( `Unknown event type: "${payload.eventType}" on row ${rowNumber}` ); } return gameEvent; }); } private requirePropertiesFor( payload: { [key: string]: any }, rowNumber: number ) { return (...props: string[]) => props.forEach((name) => { if (!(name in payload)) { throw new GamesLogError( `Missing property: ${name} for event on row ${rowNumber}` ); } if (!Number.isInteger(payload[name])) { throw new GamesLogError( `Invalid value for: ${name} on row ${rowNumber}` ); } }); } }