Match creation in bet mode

parent 7eef9732
...@@ -2884,9 +2884,11 @@ class GamesThread(ThreadedComponent): ...@@ -2884,9 +2884,11 @@ class GamesThread(ThreadedComponent):
def _select_random_completed_matches(self, count: int, session) -> List[MatchModel]: def _select_random_completed_matches(self, count: int, session) -> List[MatchModel]:
"""Select random completed matches from the database (including cancelled and failed)""" """Select random completed matches from the database (including cancelled and failed)"""
try: try:
from sqlalchemy.orm import joinedload
# Get all completed matches (status = 'done', 'cancelled', or 'failed') # Get all completed matches (status = 'done', 'cancelled', or 'failed')
# Exclude matches from fixtures that contain "_recycle_" in the fixture name # Exclude matches from fixtures that contain "_recycle_" in the fixture name
completed_matches = session.query(MatchModel).filter( completed_matches = session.query(MatchModel).options(joinedload(MatchModel.outcomes)).filter(
MatchModel.status.in_(['done', 'end', 'cancelled', 'failed']), MatchModel.status.in_(['done', 'end', 'cancelled', 'failed']),
MatchModel.active_status == True, MatchModel.active_status == True,
~MatchModel.fixture_id.like('%_recycle_%') ~MatchModel.fixture_id.like('%_recycle_%')
...@@ -2976,6 +2978,9 @@ class GamesThread(ThreadedComponent): ...@@ -2976,6 +2978,9 @@ class GamesThread(ThreadedComponent):
fixture_id = f"recycle_{uuid.uuid4().hex[:8]}" fixture_id = f"recycle_{uuid.uuid4().hex[:8]}"
now = datetime.utcnow() now = datetime.utcnow()
# Determine the status for new matches based on system state
new_match_status = self._determine_new_match_status(fixture_id, session)
# For a new fixture, start match_number from 1 # For a new fixture, start match_number from 1
match_number = 1 match_number = 1
for old_match in old_matches: for old_match in old_matches:
...@@ -2986,7 +2991,7 @@ class GamesThread(ThreadedComponent): ...@@ -2986,7 +2991,7 @@ class GamesThread(ThreadedComponent):
fighter2_township=old_match.fighter2_township, fighter2_township=old_match.fighter2_township,
venue_kampala_township=old_match.venue_kampala_township, venue_kampala_township=old_match.venue_kampala_township,
start_time=now, start_time=now,
status='scheduled', status=new_match_status,
fixture_id=fixture_id, fixture_id=fixture_id,
filename=old_match.filename, filename=old_match.filename,
file_sha1sum=old_match.file_sha1sum, file_sha1sum=old_match.file_sha1sum,
...@@ -3018,7 +3023,7 @@ class GamesThread(ThreadedComponent): ...@@ -3018,7 +3023,7 @@ class GamesThread(ThreadedComponent):
match_number += 1 match_number += 1
session.commit() session.commit()
logger.info(f"Created new fixture {fixture_id} with {len(old_matches)} matches from old completed matches") logger.info(f"Created new fixture {fixture_id} with {len(old_matches)} matches from old completed matches (status: {new_match_status})")
return fixture_id return fixture_id
except Exception as e: except Exception as e:
...@@ -3241,31 +3246,37 @@ class GamesThread(ThreadedComponent): ...@@ -3241,31 +3246,37 @@ class GamesThread(ThreadedComponent):
continue continue
# Final fallback: return whatever matches are available # Final fallback: return whatever matches are available
logger.warning(f"🚨 All {max_attempts} attempts failed - returning all available matches") try:
all_matches = session.query(MatchModel).filter( logger.warning(f"🚨 All {max_attempts} attempts failed - returning all available matches")
MatchModel.status.in_(['done', 'end', 'cancelled', 'failed']), from sqlalchemy.orm import joinedload
MatchModel.active_status == True, all_matches = session.query(MatchModel).options(joinedload(MatchModel.outcomes)).filter(
~MatchModel.fixture_id.like('%_recycle_%')
).all()
if all_matches:
result = all_matches[:count] if len(all_matches) >= count else all_matches
logger.info(f"🔄 Final fallback: returning {len(result)} matches from {len(all_matches)} total available")
return result
else:
# If no matches found with exclusions, recycle the oldest match from database
logger.warning("🚨 No matches available after exclusions - recycling the oldest match from database")
oldest_match = session.query(MatchModel).filter(
MatchModel.status.in_(['done', 'end', 'cancelled', 'failed']), MatchModel.status.in_(['done', 'end', 'cancelled', 'failed']),
MatchModel.active_status == True MatchModel.active_status == True,
).order_by(MatchModel.created_at.asc()).first() ~MatchModel.fixture_id.like('%_recycle_%')
).all()
if oldest_match: if all_matches:
logger.info(f"♻️ Recycled oldest match: {oldest_match.match_number} ({oldest_match.fighter1_township} vs {oldest_match.fighter2_township})") result = all_matches[:count] if len(all_matches) >= count else all_matches
return [oldest_match] logger.info(f"🔄 Final fallback: returning {len(result)} matches from {len(all_matches)} total available")
return result
else: else:
logger.error("🚨 No completed matches found in database at all") # If no matches found with exclusions, recycle the oldest match from database
return [] logger.warning("🚨 No matches available after exclusions - recycling the oldest match from database")
from sqlalchemy.orm import joinedload
oldest_match = session.query(MatchModel).options(joinedload(MatchModel.outcomes)).filter(
MatchModel.status.in_(['done', 'end', 'cancelled', 'failed']),
MatchModel.active_status == True
).order_by(MatchModel.created_at.asc()).first()
if oldest_match:
logger.info(f"♻️ Recycled oldest match: {oldest_match.match_number} ({oldest_match.fighter1_township} vs {oldest_match.fighter2_township})")
return [oldest_match]
else:
logger.error("🚨 No completed matches found in database at all")
return []
except Exception as e:
logger.error(f"Failed to select random completed matches with fallback: {e}")
return []
def _get_available_matches_excluding_recent(self, fixture_id: Optional[str], exclude_last_n: int, fighters_only: bool, session) -> List[MatchModel]: def _get_available_matches_excluding_recent(self, fixture_id: Optional[str], exclude_last_n: int, fighters_only: bool, session) -> List[MatchModel]:
"""Get available matches excluding the last N recent matches in the fixture""" """Get available matches excluding the last N recent matches in the fixture"""
...@@ -3302,7 +3313,8 @@ class GamesThread(ThreadedComponent): ...@@ -3302,7 +3313,8 @@ class GamesThread(ThreadedComponent):
) )
# Query available matches with exclusions # Query available matches with exclusions
query = session.query(MatchModel).filter( from sqlalchemy.orm import joinedload
query = session.query(MatchModel).options(joinedload(MatchModel.outcomes)).filter(
MatchModel.status.in_(['done', 'end', 'cancelled', 'failed']), MatchModel.status.in_(['done', 'end', 'cancelled', 'failed']),
MatchModel.active_status == True, MatchModel.active_status == True,
~MatchModel.fixture_id.like('%_recycle_%'), ~MatchModel.fixture_id.like('%_recycle_%'),
...@@ -3320,27 +3332,25 @@ class GamesThread(ThreadedComponent): ...@@ -3320,27 +3332,25 @@ class GamesThread(ThreadedComponent):
def _determine_new_match_status(self, fixture_id: str, session) -> str: def _determine_new_match_status(self, fixture_id: str, session) -> str:
"""Determine the status for new matches based on system state""" """Determine the status for new matches based on system state"""
try: try:
# Check if system is ingame (has any match with status 'ingame') # Get betting mode configuration
ingame_match = session.query(MatchModel).filter( betting_mode = self._get_betting_mode_config()
MatchModel.status == 'ingame',
MatchModel.active_status == True
).first()
if ingame_match: # If betting mode is "all_bets_on_start", new matches should be 'bet'
# System is ingame, check if last 4 matches in the fixture are in 'bet' status if betting_mode == "all_bets_on_start":
last_4_matches = session.query(MatchModel).filter( logger.info(f"Betting mode is 'all_bets_on_start' - new matches will be in bet status")
MatchModel.fixture_id == fixture_id, return 'bet'
MatchModel.active_status == True
).order_by(MatchModel.match_number.desc()).limit(4).all() # Check if the last match in the fixture is in 'bet' status
last_match = session.query(MatchModel).filter(
MatchModel.fixture_id == fixture_id,
MatchModel.active_status == True
).order_by(MatchModel.match_number.desc()).first()
if len(last_4_matches) >= 4: if last_match and last_match.status == 'bet':
# Check if all last 4 matches are in 'bet' status logger.info(f"Last match in fixture {fixture_id} is in bet status - new matches will be in bet status")
if all(match.status == 'bet' for match in last_4_matches): return 'bet'
logger.info(f"System is ingame and last 4 matches in fixture {fixture_id} are in bet status - new matches will be in bet status")
return 'bet'
# Default status # Default status
logger.info(f"New matches will be in scheduled status (system not ingame or last 4 matches not all in bet status)")
return 'scheduled' return 'scheduled'
except Exception as e: except Exception as e:
......
...@@ -556,10 +556,11 @@ class MatchTimerComponent(ThreadedComponent): ...@@ -556,10 +556,11 @@ class MatchTimerComponent(ThreadedComponent):
"""Select random completed matches from the database, excluding matches with same fighters as the last played match""" """Select random completed matches from the database, excluding matches with same fighters as the last played match"""
try: try:
from ..database.models import MatchModel from ..database.models import MatchModel
from sqlalchemy.orm import joinedload
# Build query for completed matches # Build query for completed matches
# Exclude matches from fixtures that contain "_recycle_" in the fixture name # Exclude matches from fixtures that contain "_recycle_" in the fixture name
query = session.query(MatchModel).filter( query = session.query(MatchModel).options(joinedload(MatchModel.outcomes)).filter(
MatchModel.status.in_(['done', 'end', 'cancelled', 'failed']), MatchModel.status.in_(['done', 'end', 'cancelled', 'failed']),
MatchModel.active_status == True, MatchModel.active_status == True,
~MatchModel.fixture_id.like('%_recycle_%') ~MatchModel.fixture_id.like('%_recycle_%')
...@@ -680,24 +681,15 @@ class MatchTimerComponent(ThreadedComponent): ...@@ -680,24 +681,15 @@ class MatchTimerComponent(ThreadedComponent):
logger.info(f"Betting mode is 'all_bets_on_start' - new matches will be in bet status") logger.info(f"Betting mode is 'all_bets_on_start' - new matches will be in bet status")
return 'bet' return 'bet'
# Check if system is ingame (has any match with status 'ingame') # Check if the last match in the fixture is in 'bet' status
ingame_match = session.query(MatchModel).filter( last_match = session.query(MatchModel).filter(
MatchModel.status == 'ingame', MatchModel.fixture_id == fixture_id,
MatchModel.active_status == True MatchModel.active_status == True
).first() ).order_by(MatchModel.match_number.desc()).first()
if ingame_match: if last_match and last_match.status == 'bet':
# System is ingame, check if last 4 matches in the fixture are in 'bet' status logger.info(f"Last match in fixture {fixture_id} is in bet status - new matches will be in bet status")
last_4_matches = session.query(MatchModel).filter( return 'bet'
MatchModel.fixture_id == fixture_id,
MatchModel.active_status == True
).order_by(MatchModel.match_number.desc()).limit(4).all()
if len(last_4_matches) >= 4:
# Check if all last 4 matches are in 'bet' status
if all(match.status == 'bet' for match in last_4_matches):
logger.info(f"System is ingame and last 4 matches in fixture {fixture_id} are in bet status - new matches will be in bet status")
return 'bet'
# Default status # Default status
return 'scheduled' return 'scheduled'
......
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