NEXT_MATCH fixed

parent 549596de
...@@ -1775,8 +1775,8 @@ class GamesThread(ThreadedComponent): ...@@ -1775,8 +1775,8 @@ class GamesThread(ThreadedComponent):
# Send MATCH_DONE message with result # Send MATCH_DONE message with result
self._send_match_done(fixture_id, match_id, result) self._send_match_done(fixture_id, match_id, result)
# Send START_INTRO message to start the next match cycle # Send NEXT_MATCH message to advance to next match
self._dispatch_start_intro(fixture_id) self._send_next_match(fixture_id, match_id)
except Exception as e: except Exception as e:
logger.error(f"Failed to handle PLAY_VIDEO_RESULTS_DONE message: {e}") logger.error(f"Failed to handle PLAY_VIDEO_RESULTS_DONE message: {e}")
...@@ -1818,12 +1818,8 @@ class GamesThread(ThreadedComponent): ...@@ -1818,12 +1818,8 @@ class GamesThread(ThreadedComponent):
finally: finally:
session.close() session.close()
# Wait 2 seconds then send NEXT_MATCH # NEXT_MATCH is now sent immediately in _handle_play_video_result_done
import time # to avoid the 2-second delay and ensure proper sequencing
time.sleep(2)
# Send NEXT_MATCH message
self._send_next_match(fixture_id, match_id)
except Exception as e: except Exception as e:
logger.error(f"Failed to handle MATCH_DONE message: {e}") logger.error(f"Failed to handle MATCH_DONE message: {e}")
......
...@@ -243,16 +243,24 @@ class MatchTimerComponent(ThreadedComponent): ...@@ -243,16 +243,24 @@ class MatchTimerComponent(ThreadedComponent):
logger.info(f"Received NEXT_MATCH message for fixture {fixture_id}, match {match_id}") logger.info(f"Received NEXT_MATCH message for fixture {fixture_id}, match {match_id}")
logger.info("Previous match completed - restarting timer for next interval") logger.info("Previous match completed - restarting timer for next interval")
# Find and start the next match # Start timer first to ensure countdown is visible immediately
match_interval = self._get_match_interval()
self._start_timer(match_interval * 60, fixture_id)
logger.info(f"Timer started for {match_interval} minute interval")
# Then find and start the next match
match_info = self._find_and_start_next_match() match_info = self._find_and_start_next_match()
if match_info: if match_info:
logger.info(f"Started next match {match_info['match_id']} in fixture {match_info['fixture_id']}") logger.info(f"Prepared next match {match_info['match_id']} in fixture {match_info['fixture_id']}")
# Reset timer for next interval # Update timer with correct fixture_id if different
match_interval = self._get_match_interval() if match_info['fixture_id'] != fixture_id:
self._start_timer(match_interval * 60, match_info['fixture_id']) with self._timer_lock:
logger.info(f"Timer restarted for {match_interval} minute interval") self.current_fixture_id = match_info['fixture_id']
# Send updated timer info
self._send_timer_update()
logger.info(f"Timer updated with fixture {match_info['fixture_id']}")
else: else:
logger.info("No more matches to start, stopping timer") logger.info("No more matches to start, stopping timer")
self._stop_timer() self._stop_timer()
......
...@@ -118,35 +118,41 @@ class OverlayWebChannel(QObject): ...@@ -118,35 +118,41 @@ class OverlayWebChannel(QObject):
"""Send data update to JavaScript (thread-safe)""" """Send data update to JavaScript (thread-safe)"""
# Validate data before sending to prevent null emissions # Validate data before sending to prevent null emissions
if not data: if not data:
logger.warning("send_data_update called with null/empty data, skipping") logger.warning("RESULTS DEBUG: send_data_update called with null/empty data, skipping")
return return
# Debug original data before cleaning # Debug original data before cleaning
logger.debug(f"OverlayWebChannel received data: {data}, type: {type(data)}") logger.info(f"RESULTS DEBUG: OverlayWebChannel received data: {data}, type: {type(data)}")
logger.debug(f"OverlayWebChannel data keys: {list(data.keys()) if isinstance(data, dict) else 'not dict'}") logger.info(f"RESULTS DEBUG: OverlayWebChannel data keys: {list(data.keys()) if isinstance(data, dict) else 'not dict'}")
# Check if this data contains results information
has_results_data = any(key in data for key in ['outcome', 'result', 'match', 'match_id', 'fixture_id'])
logger.info(f"RESULTS DEBUG: Data contains results info: {has_results_data}")
# Clean data to remove null/undefined values before sending to JavaScript # Clean data to remove null/undefined values before sending to JavaScript
cleaned_data = self._clean_data(data) cleaned_data = self._clean_data(data)
logger.debug(f"OverlayWebChannel cleaned data: {cleaned_data}") logger.info(f"RESULTS DEBUG: OverlayWebChannel cleaned data: {cleaned_data}")
if not cleaned_data: if not cleaned_data:
logger.debug("All data properties were null/undefined, skipping JavaScript update") logger.info("RESULTS DEBUG: All data properties were null/undefined, skipping JavaScript update")
return return
# Debug what data is being sent to JavaScript # Debug what data is being sent to JavaScript
data_keys = list(cleaned_data.keys()) if isinstance(cleaned_data, dict) else [] data_keys = list(cleaned_data.keys()) if isinstance(cleaned_data, dict) else []
logger.debug(f"OverlayWebChannel sending to JavaScript: {len(cleaned_data)} items with keys: {data_keys}") logger.info(f"RESULTS DEBUG: OverlayWebChannel sending to JavaScript: {len(cleaned_data)} items with keys: {data_keys}")
logger.debug(f"Data type: {type(cleaned_data)}, Data is dict: {isinstance(cleaned_data, dict)}") logger.info(f"RESULTS DEBUG: Data type: {type(cleaned_data)}, Data is dict: {isinstance(cleaned_data, dict)}")
with QMutexLocker(self.mutex): with QMutexLocker(self.mutex):
self.overlay_data.update(cleaned_data) self.overlay_data.update(cleaned_data)
logger.info(f"RESULTS DEBUG: Updated overlay_data, now contains: {list(self.overlay_data.keys())}")
# Add additional validation just before emit # Add additional validation just before emit
if cleaned_data and isinstance(cleaned_data, dict) and any(v is not None for v in cleaned_data.values()): if cleaned_data and isinstance(cleaned_data, dict) and any(v is not None for v in cleaned_data.values()):
logger.debug(f"OverlayWebChannel emitting dataUpdated signal with: {cleaned_data}") logger.info(f"RESULTS DEBUG: OverlayWebChannel emitting dataUpdated signal with: {cleaned_data}")
self.dataUpdated.emit(cleaned_data) self.dataUpdated.emit(cleaned_data)
data_keys = list(cleaned_data.keys()) if isinstance(cleaned_data, dict) else [] data_keys = list(cleaned_data.keys()) if isinstance(cleaned_data, dict) else []
logger.debug(f"Signal emitted successfully with {len(cleaned_data)} data items: {data_keys}") logger.info(f"RESULTS DEBUG: Signal emitted successfully with {len(cleaned_data)} data items: {data_keys}")
else: else:
logger.warning(f"Prevented emission of invalid data: {cleaned_data}") logger.warning(f"RESULTS DEBUG: Prevented emission of invalid data: {cleaned_data}")
def _clean_data(self, data: Dict[str, Any]) -> Dict[str, Any]: def _clean_data(self, data: Dict[str, Any]) -> Dict[str, Any]:
"""Clean data by removing null/undefined values before sending to JavaScript""" """Clean data by removing null/undefined values before sending to JavaScript"""
...@@ -204,13 +210,19 @@ class OverlayWebChannel(QObject): ...@@ -204,13 +210,19 @@ class OverlayWebChannel(QObject):
def getCurrentData(self) -> str: def getCurrentData(self) -> str:
"""Provide current overlay data to JavaScript via WebChannel""" """Provide current overlay data to JavaScript via WebChannel"""
try: try:
logger.debug("OverlayWebChannel: getCurrentData called") logger.info("RESULTS DEBUG: OverlayWebChannel getCurrentData called")
# Return current overlay data # Return current overlay data
current_data = dict(self.overlay_data) current_data = dict(self.overlay_data)
logger.debug(f"OverlayWebChannel: Returning current data: {current_data}") logger.info(f"RESULTS DEBUG: Current overlay_data keys: {list(current_data.keys())}")
return json.dumps(current_data) logger.info(f"RESULTS DEBUG: Current overlay_data: {current_data}")
logger.info(f"RESULTS DEBUG: Returning current data to JavaScript: {current_data}")
json_result = json.dumps(current_data)
logger.info(f"RESULTS DEBUG: JSON result length: {len(json_result)}")
return json_result
except Exception as e: except Exception as e:
logger.error(f"OverlayWebChannel: Failed to get current data: {e}") logger.error(f"RESULTS DEBUG: OverlayWebChannel Failed to get current data: {e}")
import traceback
logger.error(f"RESULTS DEBUG: Full traceback: {traceback.format_exc()}")
return json.dumps({}) return json.dumps({})
@pyqtSlot(result=str) @pyqtSlot(result=str)
......
...@@ -634,25 +634,37 @@ ...@@ -634,25 +634,37 @@
// Handle timer updates from match_timer // Handle timer updates from match_timer
const timerData = data.timer_update; const timerData = data.timer_update;
if (timerData.running && timerData.remaining_seconds !== undefined) { if (timerData.running && timerData.remaining_seconds !== undefined) {
// Format remaining time // Clear any existing countdown
const minutes = Math.floor(timerData.remaining_seconds / 60); if (countdownInterval) {
const seconds = timerData.remaining_seconds % 60; clearInterval(countdownInterval);
const timeString = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; countdownInterval = null;
}
const countdownTimer = document.getElementById('countdownTimer'); // Set next match start time
if (countdownTimer) { nextMatchStartTime = new Date(Date.now() + (timerData.remaining_seconds * 1000));
countdownTimer.textContent = timeString;
countdownTimer.className = 'countdown-timer';
countdownTimer.style.display = 'block';
// Add warning/urgent classes based on time remaining // Show next match info
if (timerData.remaining_seconds <= 60) { // 1 minute const nextMatchInfo = document.getElementById('nextMatchInfo');
countdownTimer.className = 'countdown-timer urgent'; if (nextMatchInfo) {
} else if (timerData.remaining_seconds <= 300) { // 5 minutes nextMatchInfo.textContent = `Next match starting in:`;
countdownTimer.className = 'countdown-timer warning'; nextMatchInfo.style.display = 'block';
} else {
countdownTimer.className = 'countdown-timer';
} }
// Start countdown
updateCountdown();
countdownInterval = setInterval(updateCountdown, 1000);
console.log('🔍 DEBUG: Countdown started from timer update');
} else {
// No active timer, hide countdown
const nextMatchInfo = document.getElementById('nextMatchInfo');
const countdownTimer = document.getElementById('countdownTimer');
if (nextMatchInfo) nextMatchInfo.style.display = 'none';
if (countdownTimer) countdownTimer.style.display = 'none';
// Clear countdown interval
if (countdownInterval) {
clearInterval(countdownInterval);
countdownInterval = null;
} }
} }
} }
...@@ -661,25 +673,37 @@ ...@@ -661,25 +673,37 @@
// Handle timer updates from match_timer // Handle timer updates from match_timer
const timerData = data.timer_update; const timerData = data.timer_update;
if (timerData.running && timerData.remaining_seconds !== undefined) { if (timerData.running && timerData.remaining_seconds !== undefined) {
// Format remaining time // Clear any existing countdown
const minutes = Math.floor(timerData.remaining_seconds / 60); if (countdownInterval) {
const seconds = timerData.remaining_seconds % 60; clearInterval(countdownInterval);
const timeString = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; countdownInterval = null;
}
const countdownTimer = document.getElementById('countdownTimer'); // Set next match start time
if (countdownTimer) { nextMatchStartTime = new Date(Date.now() + (timerData.remaining_seconds * 1000));
countdownTimer.textContent = timeString;
countdownTimer.className = 'countdown-timer';
countdownTimer.style.display = 'block';
// Add warning/urgent classes based on time remaining // Show next match info
if (timerData.remaining_seconds <= 60) { // 1 minute const nextMatchInfo = document.getElementById('nextMatchInfo');
countdownTimer.className = 'countdown-timer urgent'; if (nextMatchInfo) {
} else if (timerData.remaining_seconds <= 300) { // 5 minutes nextMatchInfo.textContent = `Next match starting in:`;
countdownTimer.className = 'countdown-timer warning'; nextMatchInfo.style.display = 'block';
} else {
countdownTimer.className = 'countdown-timer';
} }
// Start countdown
updateCountdown();
countdownInterval = setInterval(updateCountdown, 1000);
console.log('🔍 DEBUG: Countdown started from timer update');
} else {
// No active timer, hide countdown
const nextMatchInfo = document.getElementById('nextMatchInfo');
const countdownTimer = document.getElementById('countdownTimer');
if (nextMatchInfo) nextMatchInfo.style.display = 'none';
if (countdownTimer) countdownTimer.style.display = 'none';
// Clear countdown interval
if (countdownInterval) {
clearInterval(countdownInterval);
countdownInterval = null;
} }
} }
} }
...@@ -1138,6 +1162,10 @@ ...@@ -1138,6 +1162,10 @@
console.log('🔍 DEBUG: WebServerBaseUrl not received via WebChannel, proceeding with WebChannel data fetch'); console.log('🔍 DEBUG: WebServerBaseUrl not received via WebChannel, proceeding with WebChannel data fetch');
} }
// Check for timer state immediately when page loads
debugTime('Checking timer state on page load');
getTimerStateAndStartCountdown();
// Fetch fixture data directly from WebChannel // Fetch fixture data directly from WebChannel
debugTime('Fetching fixture data from WebChannel'); debugTime('Fetching fixture data from WebChannel');
fetchFixtureData(); fetchFixtureData();
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>Results Overlay</title> <title>Results Overlay</title>
<script src="qrc:///qtwebchannel/qwebchannel.js"></script> <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script src="overlay://overlay.js"></script>
<style> <style>
* { * {
margin: 0; margin: 0;
...@@ -772,6 +773,8 @@ ...@@ -772,6 +773,8 @@
let videoStartTime = null; let videoStartTime = null;
let contentDelayTimer = null; let contentDelayTimer = null;
let resultsTimer = null; let resultsTimer = null;
let lastPositionLogTime = 0;
const POSITION_LOG_THROTTLE_MS = 500; // Throttle position logs to max 1 per 500ms
// Define showLoadingState for compatibility (results template doesn't use loading state) // Define showLoadingState for compatibility (results template doesn't use loading state)
function showLoadingState() { function showLoadingState() {
...@@ -797,13 +800,21 @@ ...@@ -797,13 +800,21 @@
// Function to update overlay data (called by Qt WebChannel) // Function to update overlay data (called by Qt WebChannel)
function updateOverlayData(data) { function updateOverlayData(data) {
console.log('DEBUG: updateOverlayData called with data:', data); console.log('RESULTS TEMPLATE: updateOverlayData called with data:', data);
overlayData = data || {}; overlayData = data || {};
// Only update if we have valid data // Only update if we have valid data
if (data && (data.outcome || data.result)) { if (data && (data.outcome || data.result)) {
let result = data.outcome || data.result; let result = data.outcome || data.result;
console.log('DEBUG: Processing valid result:', result); console.log('RESULTS TEMPLATE: Processing valid result:', result);
// Check if this is the same data we already processed (prevent duplicate processing)
const dataHash = JSON.stringify(data);
if (window.lastProcessedDataHash === dataHash) {
console.log('RESULTS TEMPLATE: Duplicate data received, ignoring');
return;
}
window.lastProcessedDataHash = dataHash;
// Always treat the main result as the primary outcome // Always treat the main result as the primary outcome
currentMainResult = result; currentMainResult = result;
...@@ -811,7 +822,7 @@ ...@@ -811,7 +822,7 @@
// Check if under/over result is provided separately // Check if under/over result is provided separately
if (data.under_over_result) { if (data.under_over_result) {
currentUnderOverResult = data.under_over_result; currentUnderOverResult = data.under_over_result;
console.log('DEBUG: Under/over result provided separately:', currentUnderOverResult); console.log('RESULTS TEMPLATE: Under/over result provided separately:', currentUnderOverResult);
} else { } else {
// Fallback: determine if main result is under/over // Fallback: determine if main result is under/over
if (result === 'UNDER' || result === 'OVER') { if (result === 'UNDER' || result === 'OVER') {
...@@ -824,20 +835,20 @@ ...@@ -824,20 +835,20 @@
if (data.match) { if (data.match) {
currentMatch = data.match; currentMatch = data.match;
console.log('DEBUG: Match data received:', data.match); console.log('RESULTS TEMPLATE: Match data received:', data.match);
} }
if (data.match_id) { if (data.match_id) {
console.log('DEBUG: Match ID received:', data.match_id); console.log('RESULTS TEMPLATE: Match ID received:', data.match_id);
// Fetch winning outcomes for this match // Fetch winning outcomes for this match
fetchWinningOutcomes(data.match_id); fetchWinningOutcomes(data.match_id);
// Check if results have already been shown for this match (handles overlay reloads) // Check if results have already been shown for this match (handles overlay reloads)
const resultsShownKey = 'results_shown_' + data.match_id; const resultsShownKey = 'results_shown_' + data.match_id;
const alreadyShown = sessionStorage.getItem(resultsShownKey) === 'true'; const alreadyShown = sessionStorage.getItem(resultsShownKey) === 'true';
console.log('DEBUG: Results already shown for match?', alreadyShown); console.log('RESULTS TEMPLATE: Results already shown for match?', alreadyShown);
if (alreadyShown) { if (alreadyShown) {
console.log('DEBUG: Results already shown for this match, displaying immediately'); console.log('RESULTS TEMPLATE: Results already shown for this match, displaying immediately');
contentVisible = true; contentVisible = true;
showResultsPanel(); showResultsPanel();
showResultsContent(); showResultsContent();
...@@ -846,11 +857,11 @@ ...@@ -846,11 +857,11 @@
} }
// Prepare data and start 5-second timer to show results // Prepare data and start 5-second timer to show results
console.log('DEBUG: Results data received, preparing animation data'); console.log('RESULTS TEMPLATE: Results data received, preparing animation data');
prepareResultsAnimation(); prepareResultsAnimation();
} else { } else {
console.log('DEBUG: No valid data received, showing loading state'); console.log('RESULTS TEMPLATE: No valid data received, showing loading state');
// No valid data, show loading state // No valid data, show loading state
showLoadingState(); showLoadingState();
} }
...@@ -870,38 +881,43 @@ ...@@ -870,38 +881,43 @@
// Update winning bets display // Update winning bets display
updateWinningBetsDisplay(); updateWinningBetsDisplay();
// Show results after 5 seconds from data receipt // Show blue background after 5 seconds from data receipt
setTimeout(() => { setTimeout(() => {
if (!contentVisible) { if (!contentVisible) {
contentVisible = true; console.log('RESULTS TEMPLATE: Showing blue background after 5 seconds from data received');
console.log('Showing results after 5 seconds from data received');
// Mark results as shown in sessionStorage // Mark results as shown in sessionStorage
if (overlayData && overlayData.match_id) { if (overlayData && overlayData.match_id) {
sessionStorage.setItem('results_shown_' + overlayData.match_id, 'true'); sessionStorage.setItem('results_shown_' + overlayData.match_id, 'true');
} }
showResultsPanel(); showResultsPanel(); // Show blue background
// Show data immediately after background appears
setTimeout(() => {
contentVisible = true;
console.log('RESULTS TEMPLATE: Showing data immediately after background');
showResultsContent(); showResultsContent();
}, 100); // Small delay to ensure background is visible first
} }
}, 5000); }, 5000);
} }
// Fetch winning outcomes for the match // Fetch winning outcomes for the match
function fetchWinningOutcomes(matchId) { function fetchWinningOutcomes(matchId) {
console.log('DEBUG: fetchWinningOutcomes called for match:', matchId); console.log('RESULTS TEMPLATE: fetchWinningOutcomes called for match:', matchId);
// Use Qt WebChannel to request winning outcomes data // Use Qt WebChannel to request winning outcomes data
if (window.overlay && window.overlay.getWinningOutcomes) { if (window.overlay && window.overlay.getWinningOutcomes) {
console.log('DEBUG: Qt WebChannel available, requesting winning outcomes'); console.log('RESULTS TEMPLATE: Qt WebChannel available, requesting winning outcomes');
try { try {
const outcomesJson = window.overlay.getWinningOutcomes(matchId); const outcomesJson = window.overlay.getWinningOutcomes(matchId);
const outcomesData = JSON.parse(outcomesJson); const outcomesData = JSON.parse(outcomesJson);
console.log('DEBUG: Received winning outcomes:', outcomesData); console.log('RESULTS TEMPLATE: Received winning outcomes:', outcomesData);
winningOutcomes = outcomesData || []; winningOutcomes = outcomesData || [];
updateWinningBetsDisplay(); updateWinningBetsDisplay();
} catch (error) { } catch (error) {
console.error('DEBUG: Failed to get winning outcomes:', error); console.error('RESULTS TEMPLATE: Failed to get winning outcomes:', error);
// Fallback: show sample data for testing // Fallback: show sample data for testing
winningOutcomes = [ winningOutcomes = [
{ outcome: 'WIN1', amount: 125.00 }, { outcome: 'WIN1', amount: 125.00 },
...@@ -911,7 +927,7 @@ ...@@ -911,7 +927,7 @@
updateWinningBetsDisplay(); updateWinningBetsDisplay();
} }
} else { } else {
console.warn('DEBUG: Qt WebChannel not available for fetching winning outcomes'); console.warn('RESULTS TEMPLATE: Qt WebChannel not available for fetching winning outcomes');
// Fallback: show sample data for testing // Fallback: show sample data for testing
winningOutcomes = [ winningOutcomes = [
{ outcome: 'WIN1', amount: 125.00 }, { outcome: 'WIN1', amount: 125.00 },
...@@ -924,38 +940,51 @@ ...@@ -924,38 +940,51 @@
// Show results panel with fade-in animation // Show results panel with fade-in animation
function showResultsPanel() { function showResultsPanel() {
console.log('DEBUG: showResultsPanel called'); console.log('RESULTS TEMPLATE: showResultsPanel called');
const resultsPanel = document.getElementById('resultsPanel'); const resultsPanel = document.getElementById('resultsPanel');
if (resultsPanel) { if (resultsPanel) {
console.log('DEBUG: Adding visible class to results panel'); console.log('RESULTS TEMPLATE: Adding visible class to results panel');
resultsPanel.classList.add('visible'); resultsPanel.classList.add('visible');
} else { } else {
console.log('DEBUG: ERROR - resultsPanel element not found'); console.log('RESULTS TEMPLATE: ERROR - resultsPanel element not found');
} }
} }
// Show results content with animation after delay // Show results content with animation after delay
function showResultsContent() { function showResultsContent() {
console.log('DEBUG: showResultsContent called'); console.log('RESULTS TEMPLATE: showResultsContent called');
const resultsContent = document.getElementById('resultsContent'); const resultsContent = document.getElementById('resultsContent');
if (resultsContent) { if (resultsContent) {
console.log('DEBUG: Adding visible class to results content'); console.log('RESULTS TEMPLATE: Adding visible class to results content');
resultsContent.classList.add('visible'); resultsContent.classList.add('visible');
} else { } else {
console.log('DEBUG: ERROR - resultsContent element not found'); console.log('RESULTS TEMPLATE: ERROR - resultsContent element not found');
} }
} }
// Handle video position changes (for logging/debugging purposes) // Handle video position changes (for logging/debugging purposes)
function handlePositionChange(position, duration) { function handlePositionChange(position, duration) {
const currentTime = Date.now();
// Check if video has started playing (position > 0) // Check if video has started playing (position > 0)
if (position > 0 && !videoStarted) { if (position > 0 && !videoStarted) {
videoStarted = true; videoStarted = true;
console.log('Video started playing at position:', position); console.log('RESULTS TEMPLATE: Video started playing at position:', position);
} }
// Log position for debugging // Check if we've reached 5 seconds and should show results
console.log('Video position:', position, 'duration:', duration); if (position >= 5 && !contentVisible && overlayData && (overlayData.outcome || overlayData.result)) {
console.log('RESULTS TEMPLATE: Video reached 5 seconds, showing results');
contentVisible = true;
showResultsPanel();
showResultsContent();
}
// Throttle position logging to reduce message bus traffic
if (currentTime - lastPositionLogTime >= POSITION_LOG_THROTTLE_MS) {
console.log('RESULTS TEMPLATE: Video position:', position, 'duration:', duration);
lastPositionLogTime = currentTime;
}
} }
// Update fighters display // Update fighters display
...@@ -1074,21 +1103,27 @@ ...@@ -1074,21 +1103,27 @@
} }
} }
// Request current data from backend (now handled by WebChannel signals)
function requestCurrentData() {
console.log('RESULTS TEMPLATE: requestCurrentData called - data is received via WebChannel signals');
// Data is handled by dataUpdated signal connection, no need to manually request
}
// Initialize when DOM is loaded // Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
console.log('DEBUG: Results overlay DOM loaded and initialized'); console.log('RESULTS TEMPLATE: DOM loaded and initialized');
console.log('DEBUG: sessionStorage available:', typeof sessionStorage !== 'undefined'); console.log('RESULTS TEMPLATE: sessionStorage available:', typeof sessionStorage !== 'undefined');
// Setup WebChannel communication // Setup WebChannel communication (includes data polling)
setupWebChannel(); setupWebChannel();
// Panel and content will be shown after 5 seconds when video starts playing // Panel and content will be shown after 5 seconds when video starts playing
console.log('DEBUG: Waiting for results data to be received'); console.log('RESULTS TEMPLATE: Waiting for results data to be received via WebChannel signals');
// Fallback: show test results after 5 seconds if no data received // Fallback: show test results after 10 seconds if no data received via signals
setTimeout(() => { setTimeout(() => {
if (!contentVisible) { if (!contentVisible) {
console.log('DEBUG: Fallback - No data received after 5 seconds, showing test results'); console.log('RESULTS TEMPLATE: Fallback - No data received after 10 seconds, showing test results');
// Set test data // Set test data
currentMainResult = 'WIN1'; currentMainResult = 'WIN1';
currentUnderOverResult = 'OVER'; currentUnderOverResult = 'OVER';
...@@ -1104,94 +1139,87 @@ ...@@ -1104,94 +1139,87 @@
updateCombinedResultDisplay(); updateCombinedResultDisplay();
updateWinningBetsDisplay(); updateWinningBetsDisplay();
} }
}, 5000); }, 10000);
}); });
// Setup WebChannel communication (similar to fixtures.html) // Setup WebChannel communication (wait for overlay.js to set up WebChannel)
function setupWebChannel() { function setupWebChannel() {
// Check if WebChannel is already set up by overlay.js console.log('RESULTS TEMPLATE: Waiting for overlay.js WebChannel to be ready...');
if (window.overlay) {
console.log('DEBUG: WebChannel already set up by overlay.js');
// Test WebChannel // Set up global callback for dataUpdated signal (called by overlay.js)
if (window.overlay && window.overlay.log) { window.onDataUpdated = function(data) {
window.overlay.log('TEST: WebChannel connection successful'); console.log('RESULTS TEMPLATE: onDataUpdated callback called with:', data);
} if (data !== null && data !== undefined) {
// Listen for data updates from Python
if (window.overlay.dataUpdated) {
window.overlay.dataUpdated.connect(function(data) {
console.log('DEBUG: Received data update from Python:', data);
updateOverlayData(data); updateOverlayData(data);
}); } else {
console.warn('RESULTS TEMPLATE: onDataUpdated callback received null/undefined data');
} }
};
// Connect positionChanged signal // Wait for overlay.js to set up the WebChannel and overlay object
const checkOverlayReady = () => {
if (window.overlay && window.overlayManager && window.overlayManager.webChannelReady) {
console.log('RESULTS TEMPLATE: overlay.js WebChannel ready');
// Connect positionChanged signal if available
if (window.overlay.positionChanged) { if (window.overlay.positionChanged) {
console.log('DEBUG: Connecting positionChanged signal'); console.log('RESULTS TEMPLATE: Connecting positionChanged signal');
window.overlay.positionChanged.connect(function(position, duration) { window.overlay.positionChanged.connect(function(position, duration) {
if (position !== null && duration !== null) { if (position !== null && duration !== null) {
handlePositionChange(position, duration); handlePositionChange(position, duration);
} else { } else {
console.warn('DEBUG: positionChanged signal received null/undefined parameters'); console.warn('RESULTS TEMPLATE: positionChanged signal received null/undefined parameters');
} }
}); });
} }
return;
}
// Fallback: setup WebChannel if overlay.js didn't do it // Try to get current data immediately when WebChannel is ready
if (typeof qt !== 'undefined' && qt.webChannelTransport) { console.log('RESULTS TEMPLATE: Attempting to get current data from WebChannel');
try { try {
new QWebChannel(qt.webChannelTransport, function(channel) { if (window.overlay && window.overlay.getCurrentData) {
console.log('DEBUG: WebChannel connected successfully (fallback)'); const currentDataJson = window.overlay.getCurrentData();
console.log('RESULTS TEMPLATE: Got current data JSON:', currentDataJson);
// Connect to overlay object if (currentDataJson) {
window.overlay = channel.objects.overlay; const currentData = JSON.parse(currentDataJson);
console.log('RESULTS TEMPLATE: Parsed current data:', currentData);
// Listen for data updates from Python if (currentData && (currentData.outcome || currentData.result)) {
if (window.overlay && window.overlay.dataUpdated) { console.log('RESULTS TEMPLATE: Found valid data in current data, processing');
window.overlay.dataUpdated.connect(function(data) { updateOverlayData(currentData);
console.log('DEBUG: Received data update from Python:', data);
updateOverlayData(data);
});
}
// Connect positionChanged signal
if (window.overlay.positionChanged) {
console.log('DEBUG: Connecting positionChanged signal');
window.overlay.positionChanged.connect(function(position, duration) {
if (position !== null && duration !== null) {
handlePositionChange(position, duration);
} else { } else {
console.warn('DEBUG: positionChanged signal received null/undefined parameters'); console.log('RESULTS TEMPLATE: No valid result data in current data');
} }
});
} }
});
} catch (e) {
console.log('DEBUG: Failed to setup WebChannel:', e);
} }
} catch (error) {
console.error('RESULTS TEMPLATE: Failed to get current data:', error);
}
console.log('RESULTS TEMPLATE: WebChannel setup completed, signals connected');
} else { } else {
console.log('DEBUG: WebChannel not available'); // Keep checking until overlay.js has set up the WebChannel
setTimeout(checkOverlayReady, 50);
} }
};
checkOverlayReady();
} }
// Export functions for external use // Export functions for external use
window.setOutcome = setOutcome; window.setOutcome = setOutcome;
window.updateOverlayData = updateOverlayData; window.updateOverlayData = updateOverlayData;
</script> </script>
<!-- <!--
IMPORTANT: When creating or editing custom templates, always maintain this script tag: IMPORTANT: When creating or editing custom templates, always maintain these script tags:
qrc:///qtwebchannel/qwebchannel.js - Required for Qt WebChannel communication 1. qrc:///qtwebchannel/qwebchannel.js - Required for Qt WebChannel communication
2. overlay://overlay.js - Required for overlay functionality and data updates
This script enables communication between the Qt application and the overlay template. These scripts enable communication between the Qt application and the overlay template.
The results.html template handles its own WebChannel setup and does not use overlay.js The results.html template uses overlay.js for WebChannel setup and adds custom dataUpdated signal handling.
to avoid conflicts with the custom overlay elements.
NOTE: When editing this template, never remove the qwebchannel.js script source! NOTE: When editing this template, never remove these script sources!
The overlay:// custom scheme ensures JavaScript files work for both built-in and uploaded templates.
--> -->
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -47,6 +47,24 @@ class OverlayManager { ...@@ -47,6 +47,24 @@ class OverlayManager {
}); });
} }
// Connect dataUpdated signal for templates that need it (like results.html)
if (window.overlay.dataUpdated) {
window.overlay.dataUpdated.connect((data) => {
if (data !== null && data !== undefined) {
// Call a global callback if it exists (for results.html and other templates)
if (window.onDataUpdated) {
window.onDataUpdated(data);
}
console.log('dataUpdated signal received:', data);
} else {
console.warn('dataUpdated signal received null/undefined data');
}
});
}
// Mark WebChannel as ready
this.webChannelReady = true;
// Process pending updates after full initialization // Process pending updates after full initialization
setTimeout(() => this.processPendingUpdates(), 100); setTimeout(() => this.processPendingUpdates(), 100);
console.log('WebChannel connected and ready'); console.log('WebChannel connected and ready');
...@@ -80,6 +98,24 @@ class OverlayManager { ...@@ -80,6 +98,24 @@ class OverlayManager {
} }
}); });
// Connect dataUpdated signal for templates that need it (like results.html)
if (overlay.dataUpdated) {
overlay.dataUpdated.connect((data) => {
if (data !== null && data !== undefined) {
// Call a global callback if it exists (for results.html and other templates)
if (window.onDataUpdated) {
window.onDataUpdated(data);
}
console.log('dataUpdated signal received:', data);
} else {
console.warn('dataUpdated signal received null/undefined data');
}
});
}
// Mark WebChannel as ready
this.webChannelReady = true;
// Process pending updates after full initialization // Process pending updates after full initialization
setTimeout(() => this.processPendingUpdates(), 100); setTimeout(() => this.processPendingUpdates(), 100);
console.log('WebChannel connected via fallback method'); console.log('WebChannel connected via fallback method');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment