diff --git a/campaign.html b/campaign.html index 56ac968..3410813 100644 --- a/campaign.html +++ b/campaign.html @@ -1279,7 +1279,7 @@ + +
+ +
`; - // Add timer to sidebar - const sidebar = document.getElementById('campaign-sidebar'); - if (sidebar) { - sidebar.style.display = 'block'; + // Add timer to sidebar countdown element (don't replace entire sidebar!) + const showTimer = task.params?.showTimer !== false; + const countdownEl = showTimer ? document.getElementById('sidebar-countdown-display') : null; + const countdownWrapper = showTimer ? document.getElementById('sidebar-countdown-timer') : null; + const gameStatsPanel = document.getElementById('game-stats-panel'); + + console.log('๐ŸŽต RHYTHM TASK - Stats panel element:', gameStatsPanel); + console.log('๐ŸŽต RHYTHM TASK - Stats panel display BEFORE:', gameStatsPanel?.style.display); + console.log('๐ŸŽต RHYTHM TASK - Countdown wrapper display BEFORE:', countdownWrapper?.style.display); + + if (showTimer && countdownWrapper) { + countdownWrapper.style.display = 'block'; + console.log('๐ŸŽต RHYTHM TASK - Countdown wrapper set to: block'); + } + + if (showTimer && countdownEl) { const mins = Math.floor(timeRemaining / 60); const secs = timeRemaining % 60; - sidebar.innerHTML = ` -
-
Time Remaining
-
${mins}:${String(secs).padStart(2, '0')}
-
- `; + countdownEl.textContent = `${mins}:${String(secs).padStart(2, '0')}`; } + console.log('๐ŸŽต RHYTHM TASK - Stats panel display AFTER:', gameStatsPanel?.style.display); + console.log('๐ŸŽต RHYTHM TASK - Countdown wrapper display AFTER:', countdownWrapper?.style.display); + // Create metronome sound (simple beep using Web Audio API) let audioContext; if (enableMetronomeSound && (window.AudioContext || window.webkitAudioContext)) { @@ -4963,6 +5005,12 @@ class InteractiveTaskManager { const videoVolumeDisplay = enableVideo ? container.querySelector('#rhythm-video-volume-display') : null; const metronomeVolumeSlider = container.querySelector('#rhythm-metronome-volume'); const metronomeVolumeDisplay = container.querySelector('#rhythm-metronome-volume-display'); + const skipTaskBtn = container.querySelector('#skip-rhythm-task-btn'); + + // Show skip button if dev mode is enabled + if (window.isDevMode && window.isDevMode()) { + skipTaskBtn.style.display = 'inline-block'; + } if (skipVideoBtn) { skipVideoBtn.addEventListener('click', async () => { @@ -4991,7 +5039,6 @@ class InteractiveTaskManager { const metronomeVisual = container.querySelector('#metronome-visual'); const bpmDisplay = container.querySelector('.bpm-value'); - const timerDisplay = document.getElementById('rhythm-timer'); // Now in sidebar const phaseIndicator = container.querySelector('.phase-indicator'); const patternTitle = container.querySelector('#rhythm-pattern-title'); @@ -5021,9 +5068,12 @@ class InteractiveTaskManager { patternTimeRemaining--; phaseTime--; - const mins = Math.floor(timeRemaining / 60); - const secs = timeRemaining % 60; - timerDisplay.textContent = `${mins}:${String(secs).padStart(2, '0')}`; + // Update sidebar countdown timer + if (showTimer && countdownEl) { + const mins = Math.floor(timeRemaining / 60); + const secs = timeRemaining % 60; + countdownEl.textContent = `${mins}:${String(secs).padStart(2, '0')}`; + } // Check if we need to switch to next pattern in schedule if (multiPattern && patternTimeRemaining <= 0 && currentPatternIndex < patternSchedule.length - 1) { @@ -5058,7 +5108,6 @@ class InteractiveTaskManager { beatTimer = setInterval(beat, beatInterval); bpmDisplay.textContent = bpm === 0 ? 'PAUSE' : bpm; - phaseIndicator.textContent = `Phase ${currentPhase + 1} of ${bpmSequence.length}`; } if (timeRemaining <= 0) { @@ -5066,6 +5115,11 @@ class InteractiveTaskManager { clearInterval(beatTimer); task.completed = true; + // Hide sidebar countdown timer + if (showTimer && countdownWrapper) { + countdownWrapper.style.display = 'none'; + } + container.innerHTML += '
โœ… Rhythm pattern complete!
'; const completeBtn = document.getElementById('interactive-complete-btn'); @@ -5075,6 +5129,38 @@ class InteractiveTaskManager { } }, 1000); + // Dev skip button handler + if (skipTaskBtn) { + skipTaskBtn.addEventListener('click', () => { + console.log('โฉ Dev skip - completing rhythm task'); + clearInterval(countdown); + clearInterval(beatTimer); + + // Stop audio + if (audioContext) { + audioContext.close().catch(err => console.warn('โš ๏ธ Error closing audio context:', err)); + } + if (ambientAudioElement) { + ambientAudioElement.pause(); + ambientAudioElement = null; + } + + // Hide sidebar countdown timer + if (showTimer && countdownWrapper) { + countdownWrapper.style.display = 'none'; + } + + container.innerHTML += '
โœ… Rhythm pattern complete! (Dev skip)
'; + + task.completed = true; + + const completeBtn = document.getElementById('interactive-complete-btn'); + if (completeBtn) { + completeBtn.disabled = false; + } + }); + } + // Store cleanup task.cleanup = () => { console.log('๐Ÿงน Rhythm task cleanup called'); @@ -5094,11 +5180,10 @@ class InteractiveTaskManager { ambientAudioElement = null; } - // Hide sidebar - const sidebar = document.getElementById('campaign-sidebar'); - if (sidebar) { - sidebar.style.display = 'none'; - sidebar.innerHTML = ''; + // Hide countdown timer only (not entire sidebar) + const countdownTimer = document.getElementById('sidebar-countdown-timer'); + if (countdownTimer) { + countdownTimer.style.display = 'none'; } }; } @@ -6119,6 +6204,12 @@ class InteractiveTaskManager { console.log('โฑ๏ธ Showing countdown timer in sidebar - duration:', formatTime(remainingTime)); countdownWrapper.style.display = 'block'; countdownEl.textContent = formatTime(remainingTime); + + // Ensure game stats panel stays visible + const gameStatsPanel = document.getElementById('game-stats-panel'); + if (gameStatsPanel && gameStatsPanel.style.display !== 'none') { + console.log('๐Ÿ“Š Keeping game stats panel visible alongside timer'); + } } else { console.log('โฑ๏ธ Timer NOT shown - reasons:', { showTimer, hasWrapper: !!countdownWrapper, hasDisplay: !!countdownEl }); } @@ -6569,6 +6660,12 @@ class InteractiveTaskManager { if (showTimer && countdownWrapper) { countdownWrapper.style.display = 'block'; + + // Ensure game stats panel stays visible + const gameStatsPanel = document.getElementById('game-stats-panel'); + if (gameStatsPanel && gameStatsPanel.style.display !== 'none') { + console.log('๐Ÿ“Š Keeping game stats panel visible alongside timer'); + } } // Start countdown timer @@ -7457,6 +7554,7 @@ class InteractiveTaskManager { const webcamActive = task.params?.webcamActive || false; const backgroundAudio = task.params?.backgroundAudio || null; const audioVolume = task.params?.audioVolume || 0.3; + const customTempoSequence = task.params?.tempoSequence || null; // Accept custom tempo sequence let timerInterval = null; let audioElement = null; @@ -7464,12 +7562,19 @@ class InteractiveTaskManager { let beatCount = 0; let timeRemaining = duration; - // Tempo progression over 5 minutes: 60-120-150-60-150-200-240 - const tempoSequence = [60, 120, 150, 60, 150, 200, 240]; - const segmentDuration = (5 * 60 * 1000) / tempoSequence.length; + // Use custom tempo sequence if provided, otherwise use default 5-minute progression + const tempoSequence = customTempoSequence ? + customTempoSequence.map(seg => seg.tempo) : + [60, 120, 150, 60, 150, 200, 240]; + const segmentDuration = customTempoSequence ? + (customTempoSequence[0].duration * 1000) : // Use duration from first segment (all should be same) + ((5 * 60 * 1000) / tempoSequence.length); let currentSegmentIndex = 0; let segmentStartTime = null; + // Build tempo progression display string + const tempoProgressionText = tempoSequence.join(' โ†’ '); + container.innerHTML = `

๐ŸŽต Rhythm Training

@@ -7496,14 +7601,13 @@ class InteractiveTaskManager { ${tempo} BPM
- Tempo Progression: 60 โ†’ 120 โ†’ 150 โ†’ 60 โ†’ 150 โ†’ 200 โ†’ 240 + Tempo Progression: ${tempoProgressionText}
-
@@ -7521,7 +7625,6 @@ class InteractiveTaskManager { const startBtn = document.getElementById('start-rhythm-btn'); const stopBtn = document.getElementById('stop-rhythm-btn'); - const skipBtn = document.getElementById('skip-rhythm-btn'); const skipTaskBtn = document.getElementById('skip-rhythm-task-btn'); const statusArea = document.getElementById('rhythm-status'); const timerEl = document.getElementById('rhythm-timer'); @@ -7568,9 +7671,9 @@ class InteractiveTaskManager { const scrollSpeed = 50; // Fixed pixels per second let lastFrameTime = null; - // Pre-generate beat positions for entire 5-minute cycle + // Pre-generate beat positions for entire cycle const beatPositions = []; - const tempoSegments = [ + const tempoSegments = customTempoSequence || [ { tempo: 60, duration: 42.86 }, // 42.86 seconds { tempo: 120, duration: 42.86 }, { tempo: 150, duration: 42.86 }, @@ -7770,7 +7873,6 @@ class InteractiveTaskManager { stopBtn.disabled = false; stopBtn.style.display = 'inline-block'; startBtn.style.display = 'none'; - if (skipBtn) skipBtn.style.display = 'inline-block'; statusArea.innerHTML = '
๐ŸŽต Metronome Started
'; // Start background audio if available @@ -7781,7 +7883,19 @@ class InteractiveTaskManager { // Show sidebar countdown timer const sidebarTimer = document.getElementById('sidebar-countdown-timer'); const sidebarDisplay = document.getElementById('sidebar-countdown-display'); - if (sidebarTimer) sidebarTimer.style.display = 'block'; + const gameStatsPanel = document.getElementById('game-stats-panel'); + + console.log('๐ŸŽต RHYTHM TASK START - Stats panel element:', gameStatsPanel); + console.log('๐ŸŽต RHYTHM TASK START - Stats panel display BEFORE:', gameStatsPanel?.style.display); + console.log('๐ŸŽต RHYTHM TASK START - Sidebar timer display BEFORE:', sidebarTimer?.style.display); + + if (sidebarTimer) { + sidebarTimer.style.display = 'block'; + console.log('๐ŸŽต RHYTHM TASK START - Sidebar timer set to: block'); + } + + console.log('๐ŸŽต RHYTHM TASK START - Stats panel display AFTER:', gameStatsPanel?.style.display); + console.log('๐ŸŽต RHYTHM TASK START - Sidebar timer display AFTER:', sidebarTimer?.style.display); timerInterval = setInterval(() => { timeRemaining--; @@ -7818,10 +7932,6 @@ class InteractiveTaskManager { }, 1000); }); - skipBtn.addEventListener('click', () => { - timeRemaining = 0; - }); - skipTaskBtn.addEventListener('click', () => { console.log('โฉ Dev skip - completing rhythm-training task'); statusArea.innerHTML = '
โœ… Task skipped (Dev Mode)
'; @@ -7831,7 +7941,6 @@ class InteractiveTaskManager { }); startBtn.addEventListener('click', () => { - if (skipBtn) skipBtn.style.display = 'inline-block'; if (skipTaskBtn && window.isDevMode && window.isDevMode()) { skipTaskBtn.style.display = 'inline-block'; } @@ -8036,6 +8145,12 @@ class InteractiveTaskManager { // Show countdown timer in sidebar if enabled if (showTimer && countdownWrapper) { countdownWrapper.style.display = 'block'; + + // Ensure game stats panel stays visible + const gameStatsPanel = document.getElementById('game-stats-panel'); + if (gameStatsPanel && gameStatsPanel.style.display !== 'none') { + console.log('๐Ÿ“Š Keeping game stats panel visible alongside timer'); + } } let slideshowInterval = null; @@ -8600,6 +8715,12 @@ class InteractiveTaskManager { if (showTimer && countdownWrapper) { countdownWrapper.style.display = 'block'; + + // Ensure game stats panel stays visible + const gameStatsPanel = document.getElementById('game-stats-panel'); + if (gameStatsPanel && gameStatsPanel.style.display !== 'none') { + console.log('๐Ÿ“Š Keeping game stats panel visible alongside timer'); + } } if (showTimer && countdownEl) { @@ -8806,6 +8927,9 @@ class InteractiveTaskManager { +