From 2733e4acd16b96f7e6e7cec60f88aaf1d82eafae Mon Sep 17 00:00:00 2001 From: Tyler Marques Date: Mon, 9 Jun 2025 16:11:19 -0700 Subject: [PATCH] Typefixes Updating some typing errors, removing ports in docker-compose that weren't used but were stopping others from using them. --- ai_animation/src/domElements.ts | 130 ++++++++++++++------------------ ai_animation/src/gameState.ts | 21 +++--- ai_animation/src/main.ts | 3 +- docker-compose.yaml | 2 - 4 files changed, 68 insertions(+), 88 deletions(-) diff --git a/ai_animation/src/domElements.ts b/ai_animation/src/domElements.ts index bcf029e..1903d88 100644 --- a/ai_animation/src/domElements.ts +++ b/ai_animation/src/domElements.ts @@ -1,9 +1,37 @@ import { gameState } from "./gameState"; import { logger } from "./logger"; +/** + * Helper function to get a DOM element by ID and throw an error if not found + * @param id The element ID to search for + * @returns The HTMLElement + * @throws Error if element is not found + */ +function getRequiredElement(id: string): HTMLElement { + const element = document.getElementById(id); + if (!element) { + throw new Error(`Element with ID '${id}' not found`); + } + return element; +} + +/** + * Helper function to get a typed DOM element by ID and throw an error if not found + * @param id The element ID to search for + * @returns The typed HTMLElement + * @throws Error if element is not found + */ +function getRequiredTypedElement(id: string): T { + const element = document.getElementById(id) as T; + if (!element) { + throw new Error(`Element with ID '${id}' not found`); + } + return element; +} export function updatePhaseDisplay() { const currentPhase = gameState.gameData.phases[gameState.phaseIndex]; + // Add fade-out effect phaseDisplay.style.transition = 'opacity 0.3s ease-out'; phaseDisplay.style.opacity = '0'; @@ -17,8 +45,6 @@ export function updatePhaseDisplay() { } export function updateGameIdDisplay() { - if (!gameIdDisplay) return; - // Add fade-out effect gameIdDisplay.style.transition = 'opacity 0.3s ease-out'; gameIdDisplay.style.opacity = '0'; @@ -30,88 +56,46 @@ export function updateGameIdDisplay() { gameIdDisplay.style.opacity = '1'; }, 300); } -// --- LOADING & DISPLAYING GAME PHASES --- -export function loadGameBtnFunction(file) { + +export function loadGameBtnFunction(file: File) { const reader = new FileReader(); reader.onload = e => { - gameState.loadGameData(e.target?.result) + if (e.target === null || e.target.result === null) { + throw new Error("Failed to load file") + } + if (e.target.result instanceof ArrayBuffer) { + const decoder = new TextDecoder("utf-8"); + gameState.loadGameData(decoder.decode(e.target.result)) + } else { + gameState.loadGameData(e.target.result) + } }; reader.onerror = () => { logger.log("Error reading file.") }; reader.readAsText(file); } -export const loadBtn = document.getElementById('load-btn'); -if (null === loadBtn) throw new Error("Element with ID 'load-btn' not found"); -export const fileInput = document.getElementById('file-input'); -if (null === fileInput) throw new Error("Element with ID 'file-input' not found"); +// DOM Elements +export const loadBtn = getRequiredElement('load-btn'); +export const fileInput = getRequiredTypedElement('file-input'); +export const prevBtn = getRequiredTypedElement('prev-btn'); +export const nextBtn = getRequiredTypedElement('next-btn'); +export const playBtn = getRequiredTypedElement('play-btn'); +export const speedSelector = getRequiredTypedElement('speed-selector'); +export const phaseDisplay = getRequiredElement('phase-display'); +export const gameIdDisplay = getRequiredElement('game-id-display'); +export const mapView = getRequiredElement('map-view'); +export const leaderboard = getRequiredElement('leaderboard'); +export const rotatingDisplay = getRequiredElement('rotating-display'); -export const prevBtn = document.getElementById('prev-btn'); -if (null === prevBtn) throw new Error("Element with ID 'prev-btn' not found"); - -export const nextBtn = document.getElementById('next-btn'); -if (null === nextBtn) throw new Error("Element with ID 'next-btn' not found"); - -export const playBtn = document.getElementById('play-btn'); -if (null === playBtn) throw new Error("Element with ID 'play-btn' not found"); - -export const speedSelector = document.getElementById('speed-selector'); -if (null === speedSelector) throw new Error("Element with ID 'speed-selector' not found"); - -export const phaseDisplay = document.getElementById('phase-display'); -if (null === phaseDisplay) throw new Error("Element with ID 'phase-display' not found"); - -export const gameIdDisplay = document.getElementById('game-id-display'); -if (null === gameIdDisplay) throw new Error("Element with ID 'game-id-display' not found"); - -export const mapView = document.getElementById('map-view'); -if (null === mapView) throw new Error("Element with ID 'map-view' not found"); - -export const leaderboard = document.getElementById('leaderboard'); -if (null === leaderboard) throw new Error("Element with ID 'leaderboard' not found"); - -export const rotatingDisplay = document.getElementById('rotating-display'); -if (null === rotatingDisplay) throw new Error("Element with ID 'rotating-display' not found"); // Debug menu elements -export const debugMenu = document.getElementById('debug-menu'); -if (null === debugMenu) throw new Error("Element with ID 'debug-menu' not found"); - -export const debugToggleBtn = document.getElementById('debug-toggle-btn') as HTMLButtonElement; -if (null === debugToggleBtn) throw new Error("Element with ID 'debug-toggle-btn' not found"); - -export const debugPanel = document.getElementById('debug-panel'); -if (null === debugPanel) throw new Error("Element with ID 'debug-panel' not found"); - -export const debugCloseBtn = document.getElementById('debug-close-btn') as HTMLButtonElement; -if (null === debugCloseBtn) throw new Error("Element with ID 'debug-close-btn' not found"); - -export const provinceInput = document.getElementById('province-input') as HTMLInputElement; -if (null === provinceInput) throw new Error("Element with ID 'province-input' not found"); - -export const highlightProvinceBtn = document.getElementById('highlight-province-btn'); -if (null === highlightProvinceBtn) throw new Error("Element with ID 'highlight-province-btn' not found"); +export const debugMenu = getRequiredElement('debug-menu'); +export const debugToggleBtn = getRequiredTypedElement('debug-toggle-btn'); +export const debugPanel = getRequiredElement('debug-panel'); +export const debugCloseBtn = getRequiredTypedElement('debug-close-btn'); +export const provinceInput = getRequiredTypedElement('province-input'); +export const highlightProvinceBtn = getRequiredElement('highlight-province-btn'); -// Add roundRect polyfill for browsers that don't support it -if (!CanvasRenderingContext2D.prototype.roundRect) { - CanvasRenderingContext2D.prototype.roundRect = function (x, y, width, height, radius) { - if (typeof radius === 'undefined') { - radius = 5; - } - this.beginPath(); - this.moveTo(x + radius, y); - this.lineTo(x + width - radius, y); - this.arcTo(x + width, y, x + width, y + radius, radius); - this.lineTo(x + width, y + height - radius); - this.arcTo(x + width, y + height, x + width - radius, y + height, radius); - this.lineTo(x + radius, y + height); - this.arcTo(x, y + height, x, y + height - radius, radius); - this.lineTo(x, y + radius); - this.arcTo(x, y, x + radius, y, radius); - this.closePath(); - return this; - }; -} - diff --git a/ai_animation/src/gameState.ts b/ai_animation/src/gameState.ts index 52e35b7..e78a740 100644 --- a/ai_animation/src/gameState.ts +++ b/ai_animation/src/gameState.ts @@ -82,13 +82,13 @@ function loadFileFromServer(filePath: string): Promise { class GameState { - boardState: CoordinateData + boardState!: CoordinateData gameId: number - gameData: GameSchemaType - momentsData: NormalizedMomentsData | null + gameData!: GameSchemaType + momentsData!: NormalizedMomentsData phaseIndex: number boardName: string - currentPower: PowerENUM + currentPower!: PowerENUM // state locks messagesPlaying: boolean @@ -102,9 +102,9 @@ class GameState { scene: THREE.Scene // camera and controls - camControls: OrbitControls - camera: THREE.PerspectiveCamera - renderer: THREE.WebGLRenderer + camControls!: OrbitControls + camera!: THREE.PerspectiveCamera + renderer!: THREE.WebGLRenderer unitMeshes: THREE.Group[] @@ -112,10 +112,10 @@ class GameState { unitAnimations: Tween[] // - playbackTimer: number + playbackTimer!: number // Camera Animation during playing - cameraPanAnim: TweenGroup | undefined + cameraPanAnim!: TweenGroup // Global timing for animations globalTime: number @@ -124,10 +124,8 @@ class GameState { constructor(boardName: AvailableMaps) { this.phaseIndex = 0 this.boardName = boardName - this.currentPower = null; this.gameId = 16 - this.momentsData = null; // Initialize as null, will be loaded later // State locks this.isSpeaking = false this.isPlaying = false @@ -169,7 +167,6 @@ class GameState { this.gameData.phases[0].orders.length : Object.keys(this.gameData.phases[0].orders).length) : 0, ordersType: this.gameData.phases[0].orders ? typeof this.gameData.phases[0].orders : 'none', - unitsCount: this.gameData.phases[0].units ? this.gameData.phases[0].units.length : 0 }); } diff --git a/ai_animation/src/main.ts b/ai_animation/src/main.ts index c6acd30..e8ad303 100644 --- a/ai_animation/src/main.ts +++ b/ai_animation/src/main.ts @@ -9,7 +9,7 @@ import { initRotatingDisplay, } from "./components/rotatingDisplay"; import { debugMenuInstance } from "./debug/debugMenu"; import { initializeBackgroundAudio, startBackgroundAudio } from "./backgroundAudio"; import { updateLeaderboard } from "./components/leaderboard"; -import { _setPhase, advanceToNextPhase, nextPhase } from "./phase"; +import { _setPhase, advanceToNextPhase, nextPhase, previousPhase } from "./phase"; import { togglePlayback } from "./phase"; //TODO: Create a function that finds a suitable unit location within a given polygon, for placing units better @@ -118,6 +118,7 @@ function createCameraPan(): Group { */ function animate() { + requestAnimationFrame(animate); if (gameState.isPlaying) { // Update the camera angle diff --git a/docker-compose.yaml b/docker-compose.yaml index beb4ddb..0340730 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -23,13 +23,11 @@ services: env_file: "./ai_animation/.env" ports: - "4173:4173" - - "5173:5173" volumes: - ./ai_animation/public/games/:/app/dist/games diplomacy-dev: build: ai_animation ports: - - "4173:4173" - "5173:5173" command: ["npm", "run", "dev-all"] volumes: