last stint

parent db36c1f5
......@@ -397,8 +397,8 @@ class GamesThread(ThreadedComponent):
# 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}")
extracted_result = self._perform_result_extraction(fixture_id, match_id)
logger.info(f"✅ [EXTRACTION DEBUG] Extraction completed immediately: {extracted_result}")
extracted_result, winning_outcomes = self._perform_result_extraction(fixture_id, match_id)
logger.info(f"✅ [EXTRACTION DEBUG] Extraction completed immediately: {extracted_result}, winning outcomes: {winning_outcomes}")
except Exception as e:
logger.error(f"Failed to handle MATCH_START message: {e}")
......@@ -1919,21 +1919,24 @@ class GamesThread(ThreadedComponent):
# Set match status to '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)
logger.info(f"DEBUG PLAY_VIDEO_MATCH_DONE: extracted_result = '{extracted_result}'")
if 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)
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:
logger.error(f"No extracted result found for match {match_id}")
# Fallback to random selection
fallback_result = self._fallback_result_selection()
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:
logger.error(f"Failed to handle PLAY_VIDEO_MATCH_DONE message: {e}")
......@@ -2292,9 +2295,9 @@ class GamesThread(ThreadedComponent):
# DEBUG: Final check - ensure result is not None
if selected_result is None:
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:
session.close()
......@@ -2307,7 +2310,7 @@ class GamesThread(ThreadedComponent):
logger.info(f"🔄 [EXTRACTION DEBUG] Using fallback random selection")
fallback_result = self._fallback_result_selection()
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:
"""Perform weighted random selection based on inverse coefficients"""
......@@ -2674,6 +2677,46 @@ class GamesThread(ThreadedComponent):
logger.error(f"DEBUG _query_extracted_result: Exception traceback: {traceback.format_exc()}")
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]:
"""Determine the under/over result for display purposes"""
try:
......@@ -2681,14 +2724,19 @@ class GamesThread(ThreadedComponent):
try:
# First, check if we have a stored under_over_result from video selection
match = session.query(MatchModel).filter_by(id=match_id).first()
if match and 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
logger.info(f"DEBUG _determine_under_over_result: Match {match_id} found: {match is not None}")
if match:
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 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
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
from ..database.models import BetDetailModel
winning_under_over = session.query(BetDetailModel).filter(
......@@ -2733,10 +2781,10 @@ class GamesThread(ThreadedComponent):
logger.error(f"Failed to determine under/over result for match {match_id}: {e}")
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)"""
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
under_over_result = self._determine_under_over_result(match_id, result)
......@@ -2747,14 +2795,15 @@ class GamesThread(ThreadedComponent):
fixture_id=fixture_id,
match_id=match_id,
result=result,
under_over_result=under_over_result
under_over_result=under_over_result,
winning_outcomes=winning_outcomes
)
# DEBUG: Log the message content
logger.info(f"DEBUG _send_play_video_results: Message data: {play_results_message.data}")
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:
logger.error(f"Failed to send PLAY_VIDEO_RESULTS: {e}")
......
......@@ -662,7 +662,7 @@ class MessageBuilder:
)
@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"""
data = {
"fixture_id": fixture_id,
......@@ -671,6 +671,8 @@ class MessageBuilder:
}
if under_over_result is not None:
data["under_over_result"] = under_over_result
if winning_outcomes is not None:
data["winning_outcomes"] = winning_outcomes
return Message(
type=MessageType.PLAY_VIDEO_RESULT,
sender=sender,
......
......@@ -4136,8 +4136,9 @@ class QtVideoPlayer(QObject):
match_id = message.data.get("match_id")
result = message.data.get("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
result_video_path = self._find_result_video_file(match_id, result)
......@@ -4157,6 +4158,7 @@ class QtVideoPlayer(QObject):
'match_id': match_id,
'result': result,
'under_over_result': under_over_result,
'winning_outcomes': winning_outcomes,
'duration': video_duration,
'is_result_video': True
}
......@@ -4238,6 +4240,7 @@ class QtVideoPlayer(QObject):
match_id = result_video_info['match_id']
result = result_video_info['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']
duration = result_video_info['duration']
......@@ -4254,11 +4257,20 @@ class QtVideoPlayer(QObject):
if result in ['UNDER', 'OVER']:
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
overlay_data = {
'outcome': main_result,
'result': main_result, # For backwards compatibility
'under_over_result': under_over_result,
'winningOutcomes': winning_outcomes_list, # Include winning outcomes without amounts
'match': {
'fighter1_township': match_details.get('fighter1_township', 'Fighter 1'),
'fighter2_township': match_details.get('fighter2_township', 'Fighter 2'),
......@@ -4269,7 +4281,7 @@ class QtVideoPlayer(QObject):
'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
self.window.play_video(
......
......@@ -1094,7 +1094,15 @@
// Fetch winning outcomes for the match
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) {
try {
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