Fix infinite recursion bug and remove old Quick Play implementation

- Fixed infinite recursion in loadMainTask() using setTimeout to break call stack
- Removed old in-window Quick Play mode from gameModeManager
- Removed Quick Play UI configuration from index.html
- Cleaned up Quick Play specific code from game.js
- Quick Play now uses dedicated quick-play.html file only (newer version)
- Fixed syntax errors from code removal
This commit is contained in:
dilgenfritz 2025-11-03 15:53:04 -06:00
parent c33b0211d6
commit 6701a8e7bf
3 changed files with 18 additions and 270 deletions

View File

@ -2193,26 +2193,6 @@ class TaskChallengeGame {
});
});
// Add listeners for Quick Play controls
const playTimeSelect = document.getElementById('play-time-select');
if (playTimeSelect) {
console.log('⏱️ Found play time select, adding listener');
playTimeSelect.addEventListener('change', () => {
console.log('⏱️ Play time select changed');
this.handleQuickPlayTimeChange();
});
} else {
console.log('⚠️ Play time select not found');
}
// Add listeners for custom input changes (if elements exist)
const customPlayTimeValue = document.getElementById('custom-play-time-value');
if (customPlayTimeValue) {
customPlayTimeValue.addEventListener('input', () => {
this.handleCustomPlayTimeChange();
});
}
// Initialize with default mode
this.handleGameModeChange();
}
@ -2226,19 +2206,9 @@ class TaskChallengeGame {
console.log(`🎮 Game mode changed to: ${selectedMode}`);
// Show/hide configuration options based on selected mode (if elements exist)
const quickPlayConfig = document.getElementById('quick-play-config');
// Hide all configs first (in case there are any old ones)
const allConfigs = document.querySelectorAll('.mode-config');
allConfigs.forEach(config => config.style.display = 'none');
// Show Quick Play config (it's the only mode now)
if (selectedMode === 'quick-play' && quickPlayConfig) {
quickPlayConfig.style.display = 'block';
console.log('⚡ Showing Quick Play configuration options');
this.handleQuickPlayTimeChange();
}
console.log(`Game state updated:`, {
gameMode: this.gameState.gameMode,
timeLimit: this.gameState.timeLimit
@ -2319,43 +2289,6 @@ class TaskChallengeGame {
}
}
handleQuickPlayTimeChange() {
const playTimeSelect = document.getElementById('play-time-select');
const customPlayTimeInput = document.getElementById('custom-play-time-input');
if (!playTimeSelect) {
console.log('⚠️ Play time select element not found');
return;
}
const selectedValue = playTimeSelect.value;
console.log(`⚡ Play time selection: ${selectedValue}`);
if (customPlayTimeInput) {
if (selectedValue === 'custom') {
customPlayTimeInput.style.display = 'block';
console.log('⚡ Showing custom play time input');
this.handleCustomPlayTimeChange();
} else {
customPlayTimeInput.style.display = 'none';
this.gameState.timeLimit = parseInt(selectedValue);
console.log(`⚡ Play time set to: ${this.gameState.timeLimit} seconds`);
}
} else if (selectedValue !== 'custom') {
this.gameState.timeLimit = parseInt(selectedValue);
console.log(`⚡ Play time set to: ${this.gameState.timeLimit} seconds`);
}
}
handleCustomPlayTimeChange() {
const customPlayTimeValue = document.getElementById('custom-play-time-value');
if (customPlayTimeValue) {
const minutes = parseInt(customPlayTimeValue.value) || 15;
this.gameState.timeLimit = minutes * 60; // Convert minutes to seconds
console.log(`Custom play time set to ${minutes} minutes (${this.gameState.timeLimit} seconds)`);
}
}
// XP Calculation Methods
calculateTimeBasedXp() {
if (!this.gameState.sessionStartTime) return 0;
@ -4727,64 +4660,11 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
}
// Get selected game mode
const selectedMode = document.querySelector('input[name="gameMode"]:checked')?.value || 'quick-play';
const selectedMode = document.querySelector('input[name="gameMode"]:checked')?.value || 'standard';
if (window.gameModeManager) {
window.gameModeManager.currentMode = selectedMode;
// Map the new mode names to the original game engine modes
this.gameState.gameMode = window.gameModeManager.getGameModeForEngine();
// Apply Quick Play settings
if (selectedMode === 'quick-play' && window.quickPlaySettings) {
// Set play time
this.gameState.timeLimit = window.quickPlaySettings.getPlayTime();
console.log(`⚡ Quick Play time limit set to: ${this.gameState.timeLimit} seconds`);
// Configure background audio
const backgroundAudioEnabled = window.quickPlaySettings.isBackgroundAudioEnabled();
if (this.audioManager) {
if (backgroundAudioEnabled) {
this.audioManager.resumePlaylist();
console.log('🎵 Background audio enabled for Quick Play');
} else {
this.audioManager.pausePlaylist();
console.log('🔇 Background audio disabled for Quick Play');
}
}
// Configure popup images
if (this.popupImageManager) {
const popupFrequency = window.quickPlaySettings.getPopupFrequency();
const popupDuration = window.quickPlaySettings.getPopupDuration();
// Update popup image settings using the correct method
this.popupImageManager.updateConfig({
displayDuration: popupDuration * 1000, // Convert to milliseconds
});
// Update periodic popup settings
if (this.popupImageManager.updatePeriodicSettings) {
this.popupImageManager.updatePeriodicSettings({
minInterval: popupFrequency,
maxInterval: popupFrequency,
displayDuration: popupDuration
});
}
console.log(`🖼️ Popup images: ${popupFrequency}s frequency, ${popupDuration}s duration`);
}
// Configure flash messages
if (this.flashMessageManager) {
const messageFrequency = window.quickPlaySettings.getMessageFrequency();
const messageDuration = window.quickPlaySettings.getMessageDuration();
// Update flash message settings
this.flashMessageManager.updateConfig({
displayDuration: messageDuration * 1000, // Convert to milliseconds
intervalDelay: messageFrequency * 1000 // Convert to milliseconds
});
console.log(`💬 Flash messages: ${messageFrequency}s frequency, ${messageDuration}s duration`);
}
}
} else {
// Fallback if gameModeManager is not available
this.gameState.gameMode = selectedMode === 'timed' ? 'timed' :
@ -4885,8 +4765,8 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
// In timed and xp-target modes, reset used tasks and continue
console.log(`All tasks completed in ${this.gameState.gameMode} mode, cycling through tasks again`);
this.gameState.usedMainTasks = [];
// Recursively call loadMainTask to select from reset pool
this.loadMainTask();
// Use setTimeout to break the recursion chain and prevent stack overflow
setTimeout(() => this.loadMainTask(), 0);
return;
}
}
@ -4903,7 +4783,8 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
} else {
console.log(`All tasks completed in ${this.gameState.gameMode} mode, cycling through tasks again`);
this.gameState.usedMainTasks = [];
this.loadMainTask();
// Use setTimeout to break the recursion chain and prevent stack overflow
setTimeout(() => this.loadMainTask(), 0);
return;
}
}

View File

@ -5,13 +5,8 @@
class GameModeManager {
constructor() {
this.currentMode = 'quick-play'; // Default to quick play mode
this.currentMode = 'standard'; // Default to standard mode
this.availableModes = {
'quick-play': {
name: 'Quick Play',
description: 'Timed challenge mode with customizable options',
icon: '⚡'
},
'photography-studio': {
name: 'Photography Studio',
description: 'Dedicated webcam photography and dressing sessions',
@ -87,82 +82,18 @@ class GameModeManager {
<h3>Choose Your Game Mode</h3>
<div class="game-mode-grid">
${Object.entries(this.availableModes).map(([key, mode]) => `
<div class="game-mode-card ${key === 'quick-play' ? 'selected' : ''}" data-mode="${key}">
<div class="game-mode-card ${key === 'standard' ? 'selected' : ''}" data-mode="${key}">
<div class="mode-icon">${mode.icon}</div>
<div class="mode-info">
<h4>${mode.name}</h4>
<h3>${mode.name}</h3>
<p>${mode.description}</p>
</div>
<input type="radio" name="gameMode" value="${key}" id="mode-${key}" ${key === 'quick-play' ? 'checked' : ''}>
<input type="radio" name="gameMode" value="${key}" id="mode-${key}" ${key === 'standard' ? 'checked' : ''}>
</div>
`).join('')}
</div>
<div class="mode-options" id="mode-options">
<!-- Quick Play Configuration -->
<div class="mode-config" id="quick-play-config" style="display: block;">
<div class="config-section">
<h4> Quick Play Options</h4>
<!-- Play Time Configuration -->
<div class="option-group">
<label> Play Time:
<select id="play-time-select">
<option value="300">5 minutes</option>
<option value="600">10 minutes</option>
<option value="900">15 minutes</option>
<option value="1200">20 minutes</option>
<option value="1800">30 minutes</option>
<option value="custom">Custom...</option>
</select>
</label>
<div id="custom-play-time-input" style="display: none; margin-top: 10px;">
<label>Custom time (minutes):
<input type="number" id="custom-play-time-value" min="1" max="180" value="15" style="width: 60px;">
</label>
</div>
</div>
<!-- Background Audio Configuration -->
<div class="option-group">
<label class="checkbox-label">
<input type="checkbox" id="enable-background-audio" checked>
🎵 Enable Background Audio Tracks
</label>
</div>
<!-- Popup Image Configuration -->
<div class="option-group">
<h5>🖼 Popup Images</h5>
<div class="sub-option">
<label>Frequency (seconds between popups):
<input type="number" id="popup-frequency" min="10" max="300" value="60" style="width: 70px;">
</label>
</div>
<div class="sub-option">
<label>Duration (seconds displayed):
<input type="number" id="popup-duration" min="2" max="30" value="8" style="width: 70px;">
</label>
</div>
</div>
<!-- Flash Message Configuration -->
<div class="option-group">
<h5>💬 Flash Messages</h5>
<div class="sub-option">
<label>Frequency (seconds between messages):
<input type="number" id="message-frequency" min="5" max="300" value="45" style="width: 70px;">
</label>
</div>
<div class="sub-option">
<label>Duration (seconds displayed):
<input type="number" id="message-duration" min="1" max="10" value="3" style="width: 70px;">
</label>
</div>
</div>
</div>
</div>
<!-- Scenario Configuration -->
<div class="mode-config" id="scenario-config" style="display: none;">
<div class="config-section">
@ -182,7 +113,7 @@ class GameModeManager {
`;
// Add event listeners for the new controls
this.setupQuickPlayListeners();
this.bindEvents();
// Verify the radio buttons were created
const radioButtons = gameModeSelection.querySelectorAll('input[name="gameMode"]');
@ -192,59 +123,6 @@ class GameModeManager {
}
}
/**
* Setup event listeners for Quick Play configuration
*/
setupQuickPlayListeners() {
// Play time selection
const playTimeSelect = document.getElementById('play-time-select');
const customPlayTimeInput = document.getElementById('custom-play-time-input');
const customPlayTimeValue = document.getElementById('custom-play-time-value');
if (playTimeSelect) {
playTimeSelect.addEventListener('change', () => {
if (playTimeSelect.value === 'custom') {
customPlayTimeInput.style.display = 'block';
} else {
customPlayTimeInput.style.display = 'none';
}
});
}
// Store all settings in a global object for easy access
window.quickPlaySettings = {
getPlayTime: () => {
const select = document.getElementById('play-time-select');
if (select.value === 'custom') {
const customValue = document.getElementById('custom-play-time-value');
return parseInt(customValue.value) * 60; // Convert minutes to seconds
} else {
return parseInt(select.value); // Already in seconds
}
},
isBackgroundAudioEnabled: () => {
const checkbox = document.getElementById('enable-background-audio');
return checkbox ? checkbox.checked : true;
},
getPopupFrequency: () => {
const input = document.getElementById('popup-frequency');
return input ? parseInt(input.value) : 60;
},
getPopupDuration: () => {
const input = document.getElementById('popup-duration');
return input ? parseInt(input.value) : 8;
},
getMessageFrequency: () => {
const input = document.getElementById('message-frequency');
return input ? parseInt(input.value) : 45;
},
getMessageDuration: () => {
const input = document.getElementById('message-duration');
return input ? parseInt(input.value) : 3;
}
};
}
/**
* Remove hint buttons from scenarios in game.js
*/
@ -317,20 +195,11 @@ class GameModeManager {
const allConfigs = document.querySelectorAll('.mode-config');
allConfigs.forEach(config => config.style.display = 'none');
// Show appropriate config based on mode
if (mode === 'quick-play') {
const quickPlayConfig = document.getElementById('quick-play-config');
if (quickPlayConfig) {
quickPlayConfig.style.display = 'block';
console.log('⚡ Showing Quick Play configuration');
}
} else {
// Show scenario config for scenario modes
const scenarioConfig = document.getElementById('scenario-config');
if (scenarioConfig) {
scenarioConfig.style.display = 'block';
console.log('🎮 Showing scenario configuration');
}
// Show scenario config for scenario modes
const scenarioConfig = document.getElementById('scenario-config');
if (scenarioConfig) {
scenarioConfig.style.display = 'block';
console.log('🎮 Showing scenario configuration');
}
// Update UI to highlight selected mode
@ -344,7 +213,7 @@ class GameModeManager {
* Get tasks for the current game mode
*/
getTasksForMode() {
if (this.currentMode === 'standard' || this.currentMode === 'timed' || this.currentMode === 'scored' || this.currentMode === 'quick-play') {
if (this.currentMode === 'standard' || this.currentMode === 'timed' || this.currentMode === 'scored') {
return this.getStandardTasks();
} else {
return this.getScenarioModeTasks();
@ -695,7 +564,7 @@ class GameModeManager {
* Check if current mode is scenario-based
*/
isScenarioMode() {
return this.currentMode && this.currentMode !== 'standard' && this.currentMode !== 'quick-play';
return this.currentMode && this.currentMode !== 'standard';
}
/**

View File

@ -6,9 +6,7 @@ const gameData = {
// Consequence tasks - now sourced from mainGameData.js via GameDataManager
consequenceTasks: [],
// Image directory configuration
taskImageDirectory: "images/tasks/",
consequenceImageDirectory: "images/consequences/",
// Image configuration
supportedImageFormats: ['.jpg', '.jpeg', '.png', '.gif'],
discoveredTaskImages: [], // Will be populated automatically
discoveredConsequenceImages: [], // Will be populated automatically