Fixed cap

parent ec9fe6b6
......@@ -385,6 +385,10 @@ class GamesThread(ThreadedComponent):
# Calculate result using betting CAP logic
result = self._calculate_match_result(fixture_id, match_id)
# Store the under/over result from video selection calculation
logger.info(f"Storing under_over_result '{result}' for match {match_id}")
self._store_under_over_result(match_id, result)
# Send PLAY_VIDEO_MATCH with calculated result
self._send_play_video_match(fixture_id, match_id, result)
......@@ -403,6 +407,9 @@ class GamesThread(ThreadedComponent):
fixture_id = message.data.get("fixture_id")
match_id = message.data.get("match_id")
result = self._weighted_random_selection(1.0, 1.0) # Equal weights
# Store the fallback under/over result
logger.info(f"Storing fallback under_over_result '{result}' for match {match_id}")
self._store_under_over_result(match_id, result)
self._send_play_video_match(fixture_id, match_id, result)
except Exception as fallback_e:
logger.error(f"Fallback betting calculation also failed: {fallback_e}")
......@@ -1790,25 +1797,26 @@ class GamesThread(ThreadedComponent):
return None, None
def _get_redistribution_cap(self) -> float:
"""Get redistribution CAP percentage from configuration"""
"""Get redistribution CAP percentage from game configuration"""
try:
session = self.db_manager.get_session()
try:
# Get global CAP configuration
# Get CAP from game_config table (same as web dashboard saves it)
cap_config = session.query(GameConfigModel).filter_by(
config_key='redistribution_cap'
config_key='extraction_redistribution_cap'
).first()
if cap_config:
cap_value = cap_config.get_typed_value()
if isinstance(cap_value, (int, float)) and 10 <= cap_value <= 100:
logger.debug(f"Using redistribution CAP: {cap_value}%")
return float(cap_value)
else:
logger.warning(f"Invalid CAP value: {cap_value}, using default 70%")
return 70.0
else:
logger.debug("No CAP configuration found, using default 70%")
return 70.0 # Default CAP
logger.debug("No redistribution CAP configuration found, using default 70%")
return 70.0
finally:
session.close()
......@@ -2074,6 +2082,23 @@ class GamesThread(ThreadedComponent):
import traceback
logger.error(f"Full traceback: {traceback.format_exc()}")
def _store_under_over_result(self, match_id: int, under_over_result: str):
"""Store the under/over result from video selection calculation"""
try:
session = self.db_manager.get_session()
try:
match = session.query(MatchModel).filter_by(id=match_id).first()
if match:
match.under_over_result = under_over_result
session.commit()
logger.info(f"Stored under_over_result '{under_over_result}' for match {match_id}")
else:
logger.error(f"Match {match_id} not found for storing under_over_result")
finally:
session.close()
except Exception as e:
logger.error(f"Failed to store under_over_result for match {match_id}: {e}")
def _set_match_status(self, match_id: int, status: str):
"""Set match status in database"""
try:
......@@ -2355,12 +2380,12 @@ class GamesThread(ThreadedComponent):
win_coefficient = self._get_outcome_coefficient(match_id, selected_result, session)
logger.info(f"DEBUG _update_bet_results: win_coefficient = {win_coefficient}")
# Update UNDER/OVER bets - they win if they match the UNDER/OVER outcome
under_over_outcome = 'UNDER' if selected_result == 'UNDER' else 'OVER' if selected_result == 'OVER' else None
logger.info(f"DEBUG _update_bet_results: under_over_outcome = '{under_over_outcome}'")
# Get the stored UNDER/OVER result from video selection calculation
match = session.query(MatchModel).filter_by(id=match_id).first()
under_over_outcome = match.under_over_result if match else None
logger.info(f"DEBUG _update_bet_results: under_over_outcome from stored value = '{under_over_outcome}'")
# DEBUG: Log the current match result before updating
match = session.query(MatchModel).filter_by(id=match_id).first()
if match:
logger.info(f"DEBUG _update_bet_results: Current match.result before formatting = '{match.result}'")
......@@ -2424,12 +2449,23 @@ class GamesThread(ThreadedComponent):
if match:
logger.info(f"DEBUG _update_bet_results: Before update - match.result = '{match.result}'")
# Get winning outcomes for the selected result
winning_outcomes = session.query(ExtractionAssociationModel.outcome_name).filter(
# Get winning outcomes for the selected result from extraction associations
extraction_winning_outcomes = session.query(ExtractionAssociationModel.outcome_name).filter(
ExtractionAssociationModel.extraction_result == selected_result
).distinct().all()
winning_outcome_names = [outcome.outcome_name for outcome in winning_outcomes]
logger.info(f"DEBUG _update_bet_results: Found {len(winning_outcomes)} winning outcomes for '{selected_result}': {winning_outcome_names}")
extraction_winning_outcome_names = [outcome.outcome_name for outcome in extraction_winning_outcomes]
logger.info(f"DEBUG _update_bet_results: Found {len(extraction_winning_outcomes)} winning outcomes from extraction associations for '{selected_result}': {extraction_winning_outcome_names}")
# Get possible outcomes for this match
possible_outcomes = session.query(MatchOutcomeModel.column_name).filter(
MatchOutcomeModel.match_id == match_id
).all()
possible_outcome_names = [outcome.column_name for outcome in possible_outcomes]
logger.info(f"DEBUG _update_bet_results: Match {match_id} has {len(possible_outcomes)} possible outcomes: {possible_outcome_names}")
# Filter winning outcomes to only include those that are possible for this match
winning_outcome_names = [outcome for outcome in extraction_winning_outcome_names if outcome in possible_outcome_names]
logger.info(f"DEBUG _update_bet_results: After filtering against possible outcomes, {len(winning_outcome_names)} winning outcomes remain: {winning_outcome_names}")
# Set the main result (selected_result)
match.result = selected_result
......@@ -2643,6 +2679,12 @@ class GamesThread(ThreadedComponent):
try:
session = self.db_manager.get_session()
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
# If the main result is already UNDER or OVER, return it
if main_result in ['UNDER', 'OVER']:
return main_result
......
......@@ -419,9 +419,9 @@ class OverlayWebChannel(QObject):
return []
def _get_winning_outcomes_from_database(self, match_id: int) -> List[Dict[str, Any]]:
"""Get winning outcomes aggregated by outcome type for a match from database"""
"""Get winning outcomes aggregated by outcome type for a match from database, including UNDER/OVER when they win"""
try:
from ..database.models import BetDetailModel, MatchModel
from ..database.models import BetDetailModel, MatchModel, MatchOutcomeModel, ExtractionStatsModel, ExtractionAssociationModel
from sqlalchemy import func
logger.debug(f"QtWebChannel: _get_winning_outcomes_from_database called for match {match_id}")
......@@ -436,8 +436,46 @@ class OverlayWebChannel(QObject):
try:
logger.debug(f"QtWebChannel: Executing query for match {match_id}")
# Get aggregated winning amounts by outcome for this match
winning_outcomes_query = session.query(
# First, check if match has result set (from extraction)
match = session.query(MatchModel).filter(MatchModel.id == match_id).first()
if match and match.result:
logger.debug(f"QtWebChannel: Match {match_id} has result set: {match.result}")
# Get winning outcomes from associations
winning_outcomes_query = session.query(ExtractionAssociationModel.outcome_name).filter(
ExtractionAssociationModel.extraction_result == match.result
).all()
winning_outcome_names = [outcome.outcome_name for outcome in winning_outcomes_query]
logger.debug(f"QtWebChannel: Found {len(winning_outcome_names)} winning outcomes from associations for result {match.result}: {winning_outcome_names}")
# Include under_over_result if available
if match.under_over_result:
winning_outcome_names.append(match.under_over_result)
logger.debug(f"QtWebChannel: Added under_over_result: {match.under_over_result}")
# Calculate amounts from pending bets
outcomes_data = []
for outcome_name in set(winning_outcome_names):
total_amount = session.query(func.sum(BetDetailModel.amount)).filter(
BetDetailModel.match_id == match_id,
BetDetailModel.outcome == outcome_name,
BetDetailModel.result == 'pending'
).scalar() or 0.0
outcome_data = {
'outcome': outcome_name,
'amount': float(total_amount)
}
outcomes_data.append(outcome_data)
logger.debug(f"QtWebChannel: Calculated amount for {outcome_name}: {total_amount}")
logger.debug(f"QtWebChannel: Retrieved {len(outcomes_data)} winning outcomes from match result: {outcomes_data}")
return outcomes_data
# Fallback: try to get winning outcomes from updated bet results
all_winning_outcomes_query = session.query(
BetDetailModel.outcome,
func.sum(BetDetailModel.win_amount).label('total_amount')
).join(MatchModel).filter(
......@@ -446,18 +484,74 @@ class OverlayWebChannel(QObject):
MatchModel.active_status == True
).group_by(BetDetailModel.outcome).all()
logger.debug(f"QtWebChannel: Query returned {len(winning_outcomes_query)} results")
logger.debug(f"QtWebChannel: Query returned {len(all_winning_outcomes_query)} winning outcomes from bet results")
if all_winning_outcomes_query:
# Convert to dictionary format for JavaScript
outcomes_data = []
for outcome_name, total_amount in winning_outcomes_query:
for outcome_name, total_amount in all_winning_outcomes_query:
outcome_data = {
'outcome': outcome_name,
'amount': float(total_amount) if total_amount else 0.0
}
outcomes_data.append(outcome_data)
logger.debug(f"QtWebChannel: Retrieved {len(outcomes_data)} winning outcomes for match {match_id}: {outcomes_data}")
logger.debug(f"QtWebChannel: Retrieved {len(outcomes_data)} winning outcomes from bet results: {outcomes_data}")
return outcomes_data
# Fallback: No winning bets found, try to get from extraction results
logger.debug("QtWebChannel: No winning bets found, trying extraction results fallback")
# Get extraction stats for this match
extraction_stats = session.query(ExtractionStatsModel).filter(
ExtractionStatsModel.match_id == match_id
).first()
if not extraction_stats or not extraction_stats.actual_result:
logger.debug("QtWebChannel: No extraction stats found for match")
return []
extraction_result = extraction_stats.actual_result
logger.debug(f"QtWebChannel: Found extraction result: {extraction_result}")
# Get winning outcomes from extraction associations
winning_outcomes_query = session.query(ExtractionAssociationModel.outcome_name).filter(
ExtractionAssociationModel.extraction_result == extraction_result
).all()
winning_outcome_names = [outcome.outcome_name for outcome in winning_outcomes_query]
logger.debug(f"QtWebChannel: Found {len(winning_outcome_names)} winning outcomes from associations: {winning_outcome_names}")
# Get the match to check for under_over_result
match = session.query(MatchModel).filter(MatchModel.id == match_id).first()
under_over_result = match.under_over_result if match else None
logger.debug(f"QtWebChannel: Under/over result from match: {under_over_result}")
# Combine winning outcomes
all_winning_outcomes = set(winning_outcome_names)
if under_over_result:
all_winning_outcomes.add(under_over_result)
logger.debug(f"QtWebChannel: Combined winning outcomes: {all_winning_outcomes}")
# Calculate amounts for each winning outcome from pending bets
outcomes_data = []
for outcome_name in all_winning_outcomes:
# Get total amount of pending bets for this outcome
total_amount = session.query(func.sum(BetDetailModel.amount)).filter(
BetDetailModel.match_id == match_id,
BetDetailModel.outcome == outcome_name,
BetDetailModel.result == 'pending'
).scalar() or 0.0
outcome_data = {
'outcome': outcome_name,
'amount': float(total_amount)
}
outcomes_data.append(outcome_data)
logger.debug(f"QtWebChannel: Calculated amount for {outcome_name}: {total_amount}")
logger.debug(f"QtWebChannel: Retrieved {len(outcomes_data)} winning outcomes from extraction fallback: {outcomes_data}")
return outcomes_data
finally:
......@@ -4041,8 +4135,9 @@ class QtVideoPlayer(QObject):
fixture_id = message.data.get("fixture_id")
match_id = message.data.get("match_id")
result = message.data.get("result")
under_over_result = message.data.get("under_over_result")
logger.info(f"Handling PLAY_VIDEO_RESULTS: fixture={fixture_id}, match={match_id}, result={result}")
logger.info(f"Handling PLAY_VIDEO_RESULTS: fixture={fixture_id}, match={match_id}, result={result}, under_over={under_over_result}")
# Find the result video file
result_video_path = self._find_result_video_file(match_id, result)
......@@ -4061,6 +4156,7 @@ class QtVideoPlayer(QObject):
'fixture_id': fixture_id,
'match_id': match_id,
'result': result,
'under_over_result': under_over_result,
'duration': video_duration,
'is_result_video': True
}
......@@ -4141,6 +4237,7 @@ class QtVideoPlayer(QObject):
fixture_id = result_video_info['fixture_id']
match_id = result_video_info['match_id']
result = result_video_info['result']
under_over_result = result_video_info.get('under_over_result')
video_path = result_video_info['path']
duration = result_video_info['duration']
......@@ -4152,16 +4249,10 @@ class QtVideoPlayer(QObject):
logger.error(f"Could not get match details for match {match_id}")
return
# Determine under/over result if applicable
under_over_result = None
# Use the under_over_result from the message data (already determined by games_thread)
main_result = result
if result in ['UNDER', 'OVER']:
under_over_result = result
main_result = None # No separate main result
elif result not in ['UNDER', 'OVER']:
# For main results, check if there's a separate under/over from database
# This is a simplified approach - in practice, you'd need to determine this from the match outcome
pass
# Prepare overlay data for results template
overlay_data = {
......
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