Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
MBetterc
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Mbetter
MBetterc
Commits
ca38e0be
Commit
ca38e0be
authored
Nov 25, 2025
by
Stefy Lanza (nextime / spora )
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Match creation in bet mode
parent
7eef9732
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
63 additions
and
61 deletions
+63
-61
games_thread.py
mbetterclient/core/games_thread.py
+53
-43
match_timer.py
mbetterclient/core/match_timer.py
+10
-18
No files found.
mbetterclient/core/games_thread.py
View file @
ca38e0be
...
@@ -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
:
...
...
mbetterclient/core/match_timer.py
View file @
ca38e0be
...
@@ -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'
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment