last stint

parent db36c1f5
...@@ -397,8 +397,8 @@ class GamesThread(ThreadedComponent): ...@@ -397,8 +397,8 @@ class GamesThread(ThreadedComponent):
# Perform result extraction immediately after sending PLAY_VIDEO_MATCH # Perform result extraction immediately after sending PLAY_VIDEO_MATCH
logger.info(f"🔍 [EXTRACTION DEBUG] Starting immediate extraction after PLAY_VIDEO_MATCH for fixture {fixture_id}, match {match_id}") logger.info(f"🔍 [EXTRACTION DEBUG] Starting immediate extraction after PLAY_VIDEO_MATCH for fixture {fixture_id}, match {match_id}")
extracted_result = self._perform_result_extraction(fixture_id, match_id) extracted_result, winning_outcomes = self._perform_result_extraction(fixture_id, match_id)
logger.info(f"✅ [EXTRACTION DEBUG] Extraction completed immediately: {extracted_result}") logger.info(f"✅ [EXTRACTION DEBUG] Extraction completed immediately: {extracted_result}, winning outcomes: {winning_outcomes}")
except Exception as e: except Exception as e:
logger.error(f"Failed to handle MATCH_START message: {e}") logger.error(f"Failed to handle MATCH_START message: {e}")
...@@ -1919,21 +1919,24 @@ class GamesThread(ThreadedComponent): ...@@ -1919,21 +1919,24 @@ class GamesThread(ThreadedComponent):
# Set match status to 'ingame' # Set match status to 'ingame'
self._set_match_status(match_id, 'ingame') self._set_match_status(match_id, 'ingame')
# Query database for the previously extracted result # Query database for the previously extracted result and winning outcomes
extracted_result = self._query_extracted_result(match_id) extracted_result = self._query_extracted_result(match_id)
logger.info(f"DEBUG PLAY_VIDEO_MATCH_DONE: extracted_result = '{extracted_result}'") logger.info(f"DEBUG PLAY_VIDEO_MATCH_DONE: extracted_result = '{extracted_result}'")
if extracted_result: if extracted_result:
logger.info(f"Found extracted result for match {match_id}: {extracted_result}") logger.info(f"Found extracted result for match {match_id}: {extracted_result}")
# Get winning outcomes from the extraction stats
winning_outcomes = self._query_winning_outcomes(match_id)
logger.info(f"Found winning outcomes for match {match_id}: {winning_outcomes}")
# Send PLAY_VIDEO_RESULTS message (note: RESULTS plural as per user request) # Send PLAY_VIDEO_RESULTS message (note: RESULTS plural as per user request)
self._send_play_video_results(fixture_id, match_id, extracted_result) self._send_play_video_results(fixture_id, match_id, extracted_result, winning_outcomes)
else: else:
logger.error(f"No extracted result found for match {match_id}") logger.error(f"No extracted result found for match {match_id}")
# Fallback to random selection # Fallback to random selection
fallback_result = self._fallback_result_selection() fallback_result = self._fallback_result_selection()
logger.info(f"Using fallback result for match {match_id}: {fallback_result}") logger.info(f"Using fallback result for match {match_id}: {fallback_result}")
self._send_play_video_results(fixture_id, match_id, fallback_result) self._send_play_video_results(fixture_id, match_id, fallback_result, [])
except Exception as e: except Exception as e:
logger.error(f"Failed to handle PLAY_VIDEO_MATCH_DONE message: {e}") logger.error(f"Failed to handle PLAY_VIDEO_MATCH_DONE message: {e}")
...@@ -2292,9 +2295,9 @@ class GamesThread(ThreadedComponent): ...@@ -2292,9 +2295,9 @@ class GamesThread(ThreadedComponent):
# DEBUG: Final check - ensure result is not None # DEBUG: Final check - ensure result is not None
if selected_result is None: if selected_result is None:
logger.error(f"❌ [EXTRACTION DEBUG] CRITICAL: selected_result is None! This should not happen.") logger.error(f"❌ [EXTRACTION DEBUG] CRITICAL: selected_result is None! This should not happen.")
return self._fallback_result_selection() return self._fallback_result_selection(), []
return selected_result return selected_result, winning_outcome_names
finally: finally:
session.close() session.close()
...@@ -2307,7 +2310,7 @@ class GamesThread(ThreadedComponent): ...@@ -2307,7 +2310,7 @@ class GamesThread(ThreadedComponent):
logger.info(f"🔄 [EXTRACTION DEBUG] Using fallback random selection") logger.info(f"🔄 [EXTRACTION DEBUG] Using fallback random selection")
fallback_result = self._fallback_result_selection() fallback_result = self._fallback_result_selection()
logger.info(f"🔄 [EXTRACTION DEBUG] Fallback result: {fallback_result}") logger.info(f"🔄 [EXTRACTION DEBUG] Fallback result: {fallback_result}")
return fallback_result return fallback_result, []
def _weighted_result_selection(self, eligible_payouts: Dict[str, float], session, match_id: int) -> str: def _weighted_result_selection(self, eligible_payouts: Dict[str, float], session, match_id: int) -> str:
"""Perform weighted random selection based on inverse coefficients""" """Perform weighted random selection based on inverse coefficients"""
...@@ -2674,6 +2677,46 @@ class GamesThread(ThreadedComponent): ...@@ -2674,6 +2677,46 @@ class GamesThread(ThreadedComponent):
logger.error(f"DEBUG _query_extracted_result: Exception traceback: {traceback.format_exc()}") logger.error(f"DEBUG _query_extracted_result: Exception traceback: {traceback.format_exc()}")
return None return None
def _query_winning_outcomes(self, match_id: int) -> List[str]:
"""Query database for winning outcomes from extraction stats"""
try:
logger.info(f"DEBUG _query_winning_outcomes: Querying for match {match_id}")
session = self.db_manager.get_session()
try:
# Query for the most recent extraction stats for this match
from ..database.models import ExtractionStatsModel
extraction_stats = session.query(ExtractionStatsModel).filter(
ExtractionStatsModel.match_id == match_id
).order_by(ExtractionStatsModel.created_at.desc()).first()
if extraction_stats and extraction_stats.result_breakdown:
# Parse the result_breakdown JSON to extract winning outcomes
import json
try:
breakdown = json.loads(extraction_stats.result_breakdown)
# The winning outcomes should be stored in the breakdown
# For now, we'll extract from the match's winning_outcomes field
match = session.query(MatchModel).filter_by(id=match_id).first()
if match and match.winning_outcomes:
winning_outcomes = json.loads(match.winning_outcomes)
logger.info(f"Found winning outcomes for match {match_id}: {winning_outcomes}")
return winning_outcomes
except json.JSONDecodeError as e:
logger.error(f"Failed to parse result_breakdown JSON: {e}")
logger.warning(f"No winning outcomes found for match {match_id}")
return []
finally:
session.close()
except Exception as e:
logger.error(f"Failed to query winning outcomes for match {match_id}: {e}")
import traceback
logger.error(f"DEBUG _query_winning_outcomes: Exception traceback: {traceback.format_exc()}")
return []
def _determine_under_over_result(self, match_id: int, main_result: str) -> Optional[str]: def _determine_under_over_result(self, match_id: int, main_result: str) -> Optional[str]:
"""Determine the under/over result for display purposes""" """Determine the under/over result for display purposes"""
try: try:
...@@ -2681,14 +2724,19 @@ class GamesThread(ThreadedComponent): ...@@ -2681,14 +2724,19 @@ class GamesThread(ThreadedComponent):
try: try:
# First, check if we have a stored under_over_result from video selection # First, check if we have a stored under_over_result from video selection
match = session.query(MatchModel).filter_by(id=match_id).first() match = session.query(MatchModel).filter_by(id=match_id).first()
if match and match.under_over_result: logger.info(f"DEBUG _determine_under_over_result: Match {match_id} found: {match is not None}")
logger.info(f"Using stored under_over_result '{match.under_over_result}' for match {match_id}") if match:
return match.under_over_result logger.info(f"DEBUG _determine_under_over_result: match.under_over_result = '{match.under_over_result}'")
if match.under_over_result:
logger.info(f"Using stored under_over_result '{match.under_over_result}' for match {match_id}")
return match.under_over_result
# If the main result is already UNDER or OVER, return it # If the main result is already UNDER or OVER, return it
if main_result in ['UNDER', 'OVER']: if main_result in ['UNDER', 'OVER']:
logger.info(f"DEBUG _determine_under_over_result: Main result '{main_result}' is UNDER/OVER, returning it")
return main_result return main_result
logger.warning(f"DEBUG _determine_under_over_result: No stored under_over_result found for match {match_id}, main_result='{main_result}' - this should not happen!")
# Check if there are winning UNDER or OVER bets for this match # Check if there are winning UNDER or OVER bets for this match
from ..database.models import BetDetailModel from ..database.models import BetDetailModel
winning_under_over = session.query(BetDetailModel).filter( winning_under_over = session.query(BetDetailModel).filter(
...@@ -2733,10 +2781,10 @@ class GamesThread(ThreadedComponent): ...@@ -2733,10 +2781,10 @@ class GamesThread(ThreadedComponent):
logger.error(f"Failed to determine under/over result for match {match_id}: {e}") logger.error(f"Failed to determine under/over result for match {match_id}: {e}")
return None return None
def _send_play_video_results(self, fixture_id: str, match_id: int, result: str): def _send_play_video_results(self, fixture_id: str, match_id: int, result: str, winning_outcomes: Optional[List[str]] = None):
"""Send PLAY_VIDEO_RESULTS message (plural as per user request)""" """Send PLAY_VIDEO_RESULTS message (plural as per user request)"""
try: try:
logger.info(f"DEBUG _send_play_video_results: Sending PLAY_VIDEO_RESULTS with fixture_id={fixture_id}, match_id={match_id}, result='{result}'") logger.info(f"DEBUG _send_play_video_results: Sending PLAY_VIDEO_RESULTS with fixture_id={fixture_id}, match_id={match_id}, result='{result}', winning_outcomes={winning_outcomes}")
# Determine under/over result separately from main result # Determine under/over result separately from main result
under_over_result = self._determine_under_over_result(match_id, result) under_over_result = self._determine_under_over_result(match_id, result)
...@@ -2747,14 +2795,15 @@ class GamesThread(ThreadedComponent): ...@@ -2747,14 +2795,15 @@ class GamesThread(ThreadedComponent):
fixture_id=fixture_id, fixture_id=fixture_id,
match_id=match_id, match_id=match_id,
result=result, result=result,
under_over_result=under_over_result under_over_result=under_over_result,
winning_outcomes=winning_outcomes
) )
# DEBUG: Log the message content # DEBUG: Log the message content
logger.info(f"DEBUG _send_play_video_results: Message data: {play_results_message.data}") logger.info(f"DEBUG _send_play_video_results: Message data: {play_results_message.data}")
self.message_bus.publish(play_results_message) self.message_bus.publish(play_results_message)
logger.info(f"Sent PLAY_VIDEO_RESULTS for fixture {fixture_id}, match {match_id}, result {result}, under_over {under_over_result}") logger.info(f"Sent PLAY_VIDEO_RESULTS for fixture {fixture_id}, match {match_id}, result {result}, under_over {under_over_result}, winning_outcomes {winning_outcomes}")
except Exception as e: except Exception as e:
logger.error(f"Failed to send PLAY_VIDEO_RESULTS: {e}") logger.error(f"Failed to send PLAY_VIDEO_RESULTS: {e}")
......
...@@ -662,7 +662,7 @@ class MessageBuilder: ...@@ -662,7 +662,7 @@ class MessageBuilder:
) )
@staticmethod @staticmethod
def play_video_result(sender: str, fixture_id: str, match_id: int, result: str, under_over_result: Optional[str] = None) -> Message: def play_video_result(sender: str, fixture_id: str, match_id: int, result: str, under_over_result: Optional[str] = None, winning_outcomes: Optional[List[str]] = None) -> Message:
"""Create PLAY_VIDEO_RESULT message""" """Create PLAY_VIDEO_RESULT message"""
data = { data = {
"fixture_id": fixture_id, "fixture_id": fixture_id,
...@@ -671,6 +671,8 @@ class MessageBuilder: ...@@ -671,6 +671,8 @@ class MessageBuilder:
} }
if under_over_result is not None: if under_over_result is not None:
data["under_over_result"] = under_over_result data["under_over_result"] = under_over_result
if winning_outcomes is not None:
data["winning_outcomes"] = winning_outcomes
return Message( return Message(
type=MessageType.PLAY_VIDEO_RESULT, type=MessageType.PLAY_VIDEO_RESULT,
sender=sender, sender=sender,
......
...@@ -4136,8 +4136,9 @@ class QtVideoPlayer(QObject): ...@@ -4136,8 +4136,9 @@ class QtVideoPlayer(QObject):
match_id = message.data.get("match_id") match_id = message.data.get("match_id")
result = message.data.get("result") result = message.data.get("result")
under_over_result = message.data.get("under_over_result") under_over_result = message.data.get("under_over_result")
winning_outcomes = message.data.get("winning_outcomes", [])
logger.info(f"Handling PLAY_VIDEO_RESULTS: fixture={fixture_id}, match={match_id}, result={result}, under_over={under_over_result}") logger.info(f"Handling PLAY_VIDEO_RESULTS: fixture={fixture_id}, match={match_id}, result={result}, under_over={under_over_result}, winning_outcomes={winning_outcomes}")
# Find the result video file # Find the result video file
result_video_path = self._find_result_video_file(match_id, result) result_video_path = self._find_result_video_file(match_id, result)
...@@ -4157,6 +4158,7 @@ class QtVideoPlayer(QObject): ...@@ -4157,6 +4158,7 @@ class QtVideoPlayer(QObject):
'match_id': match_id, 'match_id': match_id,
'result': result, 'result': result,
'under_over_result': under_over_result, 'under_over_result': under_over_result,
'winning_outcomes': winning_outcomes,
'duration': video_duration, 'duration': video_duration,
'is_result_video': True 'is_result_video': True
} }
...@@ -4238,6 +4240,7 @@ class QtVideoPlayer(QObject): ...@@ -4238,6 +4240,7 @@ class QtVideoPlayer(QObject):
match_id = result_video_info['match_id'] match_id = result_video_info['match_id']
result = result_video_info['result'] result = result_video_info['result']
under_over_result = result_video_info.get('under_over_result') under_over_result = result_video_info.get('under_over_result')
winning_outcomes = result_video_info.get('winning_outcomes', [])
video_path = result_video_info['path'] video_path = result_video_info['path']
duration = result_video_info['duration'] duration = result_video_info['duration']
...@@ -4254,11 +4257,20 @@ class QtVideoPlayer(QObject): ...@@ -4254,11 +4257,20 @@ class QtVideoPlayer(QObject):
if result in ['UNDER', 'OVER']: if result in ['UNDER', 'OVER']:
main_result = None # No separate main result main_result = None # No separate main result
# Prepare winning outcomes list in the format expected by the template
winning_outcomes_list = [{'outcome': outcome} for outcome in winning_outcomes]
# Add under_over_result to winning outcomes if it's not already included
if under_over_result and under_over_result not in [o['outcome'] for o in winning_outcomes_list]:
winning_outcomes_list.append({'outcome': under_over_result})
logger.info(f"Added under_over_result '{under_over_result}' to winning outcomes")
# Prepare overlay data for results template # Prepare overlay data for results template
overlay_data = { overlay_data = {
'outcome': main_result, 'outcome': main_result,
'result': main_result, # For backwards compatibility 'result': main_result, # For backwards compatibility
'under_over_result': under_over_result, 'under_over_result': under_over_result,
'winningOutcomes': winning_outcomes_list, # Include winning outcomes without amounts
'match': { 'match': {
'fighter1_township': match_details.get('fighter1_township', 'Fighter 1'), 'fighter1_township': match_details.get('fighter1_township', 'Fighter 1'),
'fighter2_township': match_details.get('fighter2_township', 'Fighter 2'), 'fighter2_township': match_details.get('fighter2_township', 'Fighter 2'),
...@@ -4269,7 +4281,7 @@ class QtVideoPlayer(QObject): ...@@ -4269,7 +4281,7 @@ class QtVideoPlayer(QObject):
'is_result_video': True 'is_result_video': True
} }
logger.info(f"Sending results data to overlay: {overlay_data}") logger.info(f"Sending results data to overlay: outcome={main_result}, under_over={under_over_result}, winning_outcomes_count={len(winning_outcomes_list)}")
# Play the result video with results overlay template # Play the result video with results overlay template
self.window.play_video( self.window.play_video(
......
...@@ -1094,7 +1094,15 @@ ...@@ -1094,7 +1094,15 @@
// Fetch winning outcomes for the match // Fetch winning outcomes for the match
function fetchWinningOutcomes(matchId) { function fetchWinningOutcomes(matchId) {
// Use Qt WebChannel to request winning outcomes data // First check if winning outcomes are already available in overlayData
if (overlayData && overlayData.winningOutcomes && Array.isArray(overlayData.winningOutcomes)) {
console.log('RESULTS TEMPLATE: Using winning outcomes from overlayData:', overlayData.winningOutcomes);
winningOutcomes = overlayData.winningOutcomes;
updateWinningBetsDisplay();
return;
}
// Fallback: Use Qt WebChannel to request winning outcomes data (for backwards compatibility)
if (window.overlay && window.overlay.getWinningOutcomes) { if (window.overlay && window.overlay.getWinningOutcomes) {
try { try {
const outcomesJson = window.overlay.getWinningOutcomes(matchId); const outcomesJson = window.overlay.getWinningOutcomes(matchId);
......
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