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
e9e2f6c9
Commit
e9e2f6c9
authored
Nov 19, 2025
by
Stefy Lanza (nextime / spora )
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update
parent
4ae8c528
Changes
9
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
393 additions
and
48 deletions
+393
-48
INTRO.mp4
assets/INTRO.mp4
+0
-0
build.py
build.py
+81
-13
games_thread.py
mbetterclient/core/games_thread.py
+119
-1
thread_manager.py
mbetterclient/core/thread_manager.py
+10
-4
player.py
mbetterclient/qt_player/player.py
+163
-25
default.html
mbetterclient/qt_player/templates/default.html
+3
-3
routes.py
mbetterclient/web_dashboard/routes.py
+2
-2
new_bet.html
mbetterclient/web_dashboard/templates/dashboard/new_bet.html
+11
-0
qt.conf
qt.conf
+4
-0
No files found.
assets/INTRO.mp4
View file @
e9e2f6c9
No preview for this file type
build.py
View file @
e9e2f6c9
...
@@ -88,13 +88,15 @@ def collect_data_files() -> List[tuple]:
...
@@ -88,13 +88,15 @@ def collect_data_files() -> List[tuple]:
project_root
=
get_project_root
()
project_root
=
get_project_root
()
data_files
=
[]
data_files
=
[]
# Include assets directory
# Include assets directory
- ensure it's at the root level in the bundle
assets_dir
=
project_root
/
'assets'
assets_dir
=
project_root
/
'assets'
if
assets_dir
.
exists
():
if
assets_dir
.
exists
():
for
file_path
in
assets_dir
.
rglob
(
'*'
):
for
file_path
in
assets_dir
.
rglob
(
'*'
):
if
file_path
.
is_file
():
if
file_path
.
is_file
():
relative_path
=
file_path
.
relative_to
(
project_root
)
# For assets, we want them at the root level, not nested
data_files
.
append
((
str
(
file_path
),
str
(
relative_path
.
parent
)))
# So instead of relative_path.parent, we use just 'assets'
data_files
.
append
((
str
(
file_path
),
'assets'
))
print
(
f
" 📁 Including asset file: {file_path.name} ({file_path.stat().st_size} bytes) -> assets/"
)
# Include web dashboard templates and static files
# Include web dashboard templates and static files
web_templates
=
project_root
/
'mbetterclient'
/
'web_dashboard'
/
'templates'
web_templates
=
project_root
/
'mbetterclient'
/
'web_dashboard'
/
'templates'
...
@@ -153,8 +155,37 @@ def collect_data_files() -> List[tuple]:
...
@@ -153,8 +155,37 @@ def collect_data_files() -> List[tuple]:
data_files
.
append
((
str
(
file_path
),
str
(
relative_path
.
parent
)))
data_files
.
append
((
str
(
file_path
),
str
(
relative_path
.
parent
)))
print
(
f
" 📁 Including asset directory: {asset_dir}"
)
print
(
f
" 📁 Including asset directory: {asset_dir}"
)
# Removed qt.conf creation for self-contained binary
# Include Qt WebEngine data files and resources
print
(
" 📦 Building self-contained binary - no external Qt configuration needed"
)
webengine_data_dirs
=
[
'/usr/share/qt6/resources'
,
'/usr/share/qt6/translations/qtwebengine_locales'
,
'/usr/lib/x86_64-linux-gnu/qt6/libexec'
,
]
for
data_dir
in
webengine_data_dirs
:
if
os
.
path
.
exists
(
data_dir
):
for
root
,
dirs
,
files
in
os
.
walk
(
data_dir
):
for
file
in
files
:
full_path
=
os
.
path
.
join
(
root
,
file
)
rel_path
=
os
.
path
.
relpath
(
root
,
'/usr/share/qt6'
)
if
'share'
in
data_dir
else
os
.
path
.
relpath
(
root
,
'/usr/lib/x86_64-linux-gnu/qt6'
)
data_files
.
append
((
full_path
,
rel_path
))
print
(
f
" 📁 Including Qt WebEngine data: {data_dir}"
)
# Create qt.conf to ensure Qt uses bundled libraries
qt_conf_content
=
"""[Paths]
Prefix = .
Libraries = .
Plugins = plugins
"""
qt_conf_path
=
project_root
/
'qt.conf'
with
open
(
qt_conf_path
,
'w'
)
as
f
:
f
.
write
(
qt_conf_content
)
# Include qt.conf in the build
data_files
.
append
((
str
(
qt_conf_path
),
'.'
))
print
(
" 📦 Created qt.conf for self-contained Qt configuration"
)
print
(
" 📦 Building self-contained binary with all Qt libraries included"
)
return
data_files
return
data_files
...
@@ -202,10 +233,7 @@ def collect_hidden_imports() -> List[str]:
...
@@ -202,10 +233,7 @@ def collect_hidden_imports() -> List[str]:
'barcode'
,
'barcode'
,
'barcode.codex'
,
'barcode.codex'
,
'barcode.ean'
,
'barcode.ean'
,
'barcode.isbn'
,
'barcode.isxn'
,
'barcode.code39'
,
'barcode.code128'
,
'barcode.pzn'
,
]
]
# Conditionally add ffmpeg module if available
# Conditionally add ffmpeg module if available
...
@@ -224,6 +252,14 @@ def collect_hidden_imports() -> List[str]:
...
@@ -224,6 +252,14 @@ def collect_hidden_imports() -> List[str]:
except
ImportError
:
except
ImportError
:
print
(
" ⚠️ PyQt6.QtDBus not available, skipping D-Bus imports"
)
print
(
" ⚠️ PyQt6.QtDBus not available, skipping D-Bus imports"
)
# Add barcode submodules conditionally
try
:
import
barcode.isbn
hidden_imports
.
extend
([
'barcode.isbn'
,
'barcode.code39'
,
'barcode.code128'
,
'barcode.pzn'
])
print
(
" 📦 Added barcode submodules to hidden imports"
)
except
ImportError
:
print
(
" ⚠️ Some barcode submodules not available, skipping"
)
# Conditionally add D-Bus modules if available
# Conditionally add D-Bus modules if available
try
:
try
:
import
dbus
import
dbus
...
@@ -304,18 +340,50 @@ def collect_binaries() -> List[tuple]:
...
@@ -304,18 +340,50 @@ def collect_binaries() -> List[tuple]:
(
'/usr/lib/x86_64-linux-gnu/qt6/plugins/platforms/libqoffscreen.so'
,
'platforms/'
),
(
'/usr/lib/x86_64-linux-gnu/qt6/plugins/platforms/libqoffscreen.so'
,
'platforms/'
),
]
]
# Minimal X11 libraries - only include essential ones to avoid version conflicts
# Essential Qt6 libraries that need to be bundled - use venv libraries instead of system ones
# Most X11 libraries should be provided by the system to prevent segfaults
qt6_libraries
=
[
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6Core.so.6'
,
'.'
),
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6Gui.so.6'
,
'.'
),
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6Widgets.so.6'
,
'.'
),
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6Multimedia.so.6'
,
'.'
),
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6MultimediaWidgets.so.6'
,
'.'
),
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6WebEngineCore.so.6'
,
'.'
),
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6WebEngineWidgets.so.6'
,
'.'
),
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6WebChannel.so.6'
,
'.'
),
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6Network.so.6'
,
'.'
),
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6DBus.so.6'
,
'.'
),
(
'venv/lib/python3.13/site-packages/PyQt6/Qt6/lib/libQt6OpenGL.so.6'
,
'.'
),
]
# Minimal X11 libraries - include more to ensure compatibility
essential_x11_libraries
=
[
essential_x11_libraries
=
[
(
'/lib/x86_64-linux-gnu/libxcb.so.1'
,
'.'
),
# Core xcb library
(
'/lib/x86_64-linux-gnu/libxcb.so.1'
,
'.'
),
# Core xcb library
(
'/lib/x86_64-linux-gnu/libX11.so.6'
,
'.'
),
# Core X11 library
(
'/lib/x86_64-linux-gnu/libX11.so.6'
,
'.'
),
# Core X11 library
(
'/lib/x86_64-linux-gnu/libX11-xcb.so.1'
,
'.'
),
# X11-xcb bridge
(
'/lib/x86_64-linux-gnu/libxcb-shm.so.0'
,
'.'
),
# Shared memory
(
'/lib/x86_64-linux-gnu/libxcb-render.so.0'
,
'.'
),
# Render extension
(
'/lib/x86_64-linux-gnu/libxcb-image.so.0'
,
'.'
),
# Image utilities
(
'/lib/x86_64-linux-gnu/libxcb-keysyms.so.1'
,
'.'
),
# Key symbols
(
'/lib/x86_64-linux-gnu/libxcb-randr.so.0'
,
'.'
),
# RandR extension
(
'/lib/x86_64-linux-gnu/libxcb-xfixes.so.0'
,
'.'
),
# XFixes extension
]
# GStreamer libraries for multimedia support
gstreamer_libraries
=
[
(
'/usr/lib/x86_64-linux-gnu/libgstreamer-1.0.so.0'
,
'.'
),
(
'/usr/lib/x86_64-linux-gnu/libgstbase-1.0.so.0'
,
'.'
),
(
'/usr/lib/x86_64-linux-gnu/libgstvideo-1.0.so.0'
,
'.'
),
(
'/usr/lib/x86_64-linux-gnu/libgstaudio-1.0.so.0'
,
'.'
),
(
'/usr/lib/x86_64-linux-gnu/libgstpbutils-1.0.so.0'
,
'.'
),
]
]
binaries
.
extend
(
qt_platform_plugins
)
binaries
.
extend
(
qt_platform_plugins
)
binaries
.
extend
(
qt6_libraries
)
binaries
.
extend
(
essential_x11_libraries
)
binaries
.
extend
(
essential_x11_libraries
)
binaries
.
extend
(
gstreamer_libraries
)
print
(
" 📦 Including
only essential X11 libraries to prevent segfaults
"
)
print
(
" 📦 Including
Qt6, X11, and GStreamer libraries for self-contained binary
"
)
print
(
" 💡
System will provide most X11/GL libraries to avoid version conflicts
"
)
print
(
" 💡
This ensures the binary works on systems without Qt6/GStreamer installed
"
)
return
binaries
return
binaries
...
...
mbetterclient/core/games_thread.py
View file @
e9e2f6c9
...
@@ -42,6 +42,7 @@ class GamesThread(ThreadedComponent):
...
@@ -42,6 +42,7 @@ class GamesThread(ThreadedComponent):
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
MATCH_START
,
self
.
_handle_match_start
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
MATCH_START
,
self
.
_handle_match_start
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
PLAY_VIDEO_MATCH_DONE
,
self
.
_handle_play_video_match_done
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
PLAY_VIDEO_MATCH_DONE
,
self
.
_handle_play_video_match_done
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
MATCH_DONE
,
self
.
_handle_match_done
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
MATCH_DONE
,
self
.
_handle_match_done
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
GAME_STATUS
,
self
.
_handle_game_status_request
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
SYSTEM_STATUS
,
self
.
_handle_system_status
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
SYSTEM_STATUS
,
self
.
_handle_system_status
)
# Send ready status
# Send ready status
...
@@ -265,6 +266,34 @@ class GamesThread(ThreadedComponent):
...
@@ -265,6 +266,34 @@ class GamesThread(ThreadedComponent):
except
Exception
as
fallback_e
:
except
Exception
as
fallback_e
:
logger
.
error
(
f
"Fallback betting calculation also failed: {fallback_e}"
)
logger
.
error
(
f
"Fallback betting calculation also failed: {fallback_e}"
)
def
_handle_game_status_request
(
self
,
message
:
Message
):
"""Handle GAME_STATUS requests from Qt player"""
try
:
logger
.
info
(
f
"Received GAME_STATUS request from {message.sender}"
)
# Determine current game status
game_status
=
self
.
_determine_game_status
()
# Send GAME_STATUS response back to the requester
response
=
Message
(
type
=
MessageType
.
GAME_STATUS
,
sender
=
self
.
name
,
recipient
=
message
.
sender
,
data
=
{
"status"
:
game_status
,
"fixture_id"
:
self
.
current_fixture_id
,
"game_active"
:
self
.
game_active
,
"timestamp"
:
time
.
time
()
},
correlation_id
=
message
.
correlation_id
)
# Broadcast the response instead of sending to specific recipient
self
.
message_bus
.
publish
(
response
,
broadcast
=
True
)
logger
.
info
(
f
"Broadcast game status response: {game_status}"
)
except
Exception
as
e
:
logger
.
error
(
f
"Failed to handle game status request: {e}"
)
def
_process_message
(
self
,
message
:
Message
):
def
_process_message
(
self
,
message
:
Message
):
"""Process incoming messages"""
"""Process incoming messages"""
try
:
try
:
...
@@ -277,12 +306,16 @@ class GamesThread(ThreadedComponent):
...
@@ -277,12 +306,16 @@ class GamesThread(ThreadedComponent):
self
.
_handle_schedule_games
(
message
)
self
.
_handle_schedule_games
(
message
)
elif
message
.
type
==
MessageType
.
SYSTEM_SHUTDOWN
:
elif
message
.
type
==
MessageType
.
SYSTEM_SHUTDOWN
:
self
.
_handle_shutdown_message
(
message
)
self
.
_handle_shutdown_message
(
message
)
elif
message
.
type
==
MessageType
.
SYSTEM_STATUS
:
self
.
_handle_system_status
(
message
)
elif
message
.
type
==
MessageType
.
GAME_UPDATE
:
elif
message
.
type
==
MessageType
.
GAME_UPDATE
:
self
.
_handle_game_update
(
message
)
self
.
_handle_game_update
(
message
)
elif
message
.
type
==
MessageType
.
PLAY_VIDEO_MATCH_DONE
:
elif
message
.
type
==
MessageType
.
PLAY_VIDEO_MATCH_DONE
:
self
.
_handle_play_video_match_done
(
message
)
self
.
_handle_play_video_match_done
(
message
)
elif
message
.
type
==
MessageType
.
MATCH_DONE
:
elif
message
.
type
==
MessageType
.
MATCH_DONE
:
self
.
_handle_match_done
(
message
)
self
.
_handle_match_done
(
message
)
elif
message
.
type
==
MessageType
.
GAME_STATUS
:
self
.
_handle_game_status_request
(
message
)
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
f
"Failed to process message: {e}"
)
logger
.
error
(
f
"Failed to process message: {e}"
)
...
@@ -1315,9 +1348,12 @@ class GamesThread(ThreadedComponent):
...
@@ -1315,9 +1348,12 @@ class GamesThread(ThreadedComponent):
logger
.
error
(
f
"Failed to handle MATCH_DONE message: {e}"
)
logger
.
error
(
f
"Failed to handle MATCH_DONE message: {e}"
)
def
_handle_system_status
(
self
,
message
:
Message
):
def
_handle_system_status
(
self
,
message
:
Message
):
"""Handle SYSTEM_STATUS messages, particularly fixture update completion"""
"""Handle SYSTEM_STATUS messages, particularly fixture update completion
and status requests
"""
try
:
try
:
logger
.
debug
(
f
"GamesThread handling SYSTEM_STATUS message from {message.sender}: {message.data}"
)
status
=
message
.
data
.
get
(
"status"
)
status
=
message
.
data
.
get
(
"status"
)
details
=
message
.
data
.
get
(
"details"
,
{})
if
status
==
"fixture_update_completed"
:
if
status
==
"fixture_update_completed"
:
synchronized_matches
=
message
.
data
.
get
(
"synchronized_matches"
,
0
)
synchronized_matches
=
message
.
data
.
get
(
"synchronized_matches"
,
0
)
downloaded_zips
=
message
.
data
.
get
(
"downloaded_zips"
,
0
)
downloaded_zips
=
message
.
data
.
get
(
"downloaded_zips"
,
0
)
...
@@ -1338,8 +1374,43 @@ class GamesThread(ThreadedComponent):
...
@@ -1338,8 +1374,43 @@ class GamesThread(ThreadedComponent):
)
)
self
.
message_bus
.
publish
(
start_game_message
)
self
.
message_bus
.
publish
(
start_game_message
)
elif
status
==
"status_request"
:
# Handle status requests from Qt player
request_type
=
details
.
get
(
"request_type"
)
logger
.
debug
(
f
"Status request type: {request_type}, details: {details}"
)
if
request_type
==
"game_status"
:
logger
.
info
(
f
"Received game status request from {message.sender}"
)
# Determine current game status
game_status
=
self
.
_determine_game_status
()
logger
.
debug
(
f
"Determined game status: {game_status}"
)
# Send GAME_STATUS response back to the requester (broadcast to ensure delivery)
response
=
Message
(
type
=
MessageType
.
GAME_STATUS
,
sender
=
self
.
name
,
recipient
=
message
.
sender
,
data
=
{
"status"
:
game_status
,
"fixture_id"
:
self
.
current_fixture_id
,
"game_active"
:
self
.
game_active
,
"timestamp"
:
time
.
time
()
},
correlation_id
=
message
.
correlation_id
)
logger
.
debug
(
f
"About to publish GAME_STATUS response: {response.data}"
)
# Broadcast the response to ensure it reaches the Qt player
self
.
message_bus
.
publish
(
response
,
broadcast
=
True
)
logger
.
info
(
f
"Sent game status response to {message.sender}: {game_status}"
)
else
:
logger
.
debug
(
f
"Ignoring status_request with unknown request_type: {request_type}"
)
else
:
logger
.
debug
(
f
"Ignoring SYSTEM_STATUS message with unknown status: {status}"
)
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
f
"Failed to handle system status message: {e}"
)
logger
.
error
(
f
"Failed to handle system status message: {e}"
)
import
traceback
logger
.
error
(
f
"Full traceback: {traceback.format_exc()}"
)
def
_set_match_status
(
self
,
match_id
:
int
,
status
:
str
):
def
_set_match_status
(
self
,
match_id
:
int
,
status
:
str
):
"""Set match status in database"""
"""Set match status in database"""
...
@@ -1869,6 +1940,53 @@ class GamesThread(ThreadedComponent):
...
@@ -1869,6 +1940,53 @@ class GamesThread(ThreadedComponent):
session
.
rollback
()
session
.
rollback
()
return
None
return
None
def
_determine_game_status
(
self
)
->
str
:
"""Determine the current game status for status requests"""
try
:
# If a game is currently active, return "started"
if
self
.
game_active
and
self
.
current_fixture_id
:
return
"started"
# Check if there are any active fixtures (matches in non-terminal states)
session
=
self
.
db_manager
.
get_session
()
try
:
# Get today's date
today
=
datetime
.
now
()
.
date
()
# Check for active matches today
active_matches
=
session
.
query
(
MatchModel
)
.
filter
(
MatchModel
.
start_time
.
isnot
(
None
),
MatchModel
.
start_time
>=
datetime
.
combine
(
today
,
datetime
.
min
.
time
()),
MatchModel
.
start_time
<
datetime
.
combine
(
today
,
datetime
.
max
.
time
()),
MatchModel
.
status
.
notin_
([
'done'
,
'cancelled'
,
'failed'
,
'paused'
]),
MatchModel
.
active_status
==
True
)
.
all
()
if
active_matches
:
return
"already_active"
# Check if all today's fixtures are in terminal states
if
self
.
_has_today_fixtures_all_terminal
():
return
"completed_no_old_matches"
# Check if there are any fixtures at all (even if not today)
any_fixtures
=
session
.
query
(
MatchModel
)
.
filter
(
MatchModel
.
active_status
==
True
)
.
count
()
if
any_fixtures
>
0
:
return
"ready"
# Fixtures exist but no active game
# No fixtures at all
return
"shutdown"
finally
:
session
.
close
()
except
Exception
as
e
:
logger
.
error
(
f
"Failed to determine game status: {e}"
)
return
"ready"
# Default fallback
def
_cleanup
(
self
):
def
_cleanup
(
self
):
"""Perform cleanup operations"""
"""Perform cleanup operations"""
try
:
try
:
...
...
mbetterclient/core/thread_manager.py
View file @
e9e2f6c9
...
@@ -99,6 +99,8 @@ class ThreadedComponent(ABC):
...
@@ -99,6 +99,8 @@ class ThreadedComponent(ABC):
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
f
"Failed to stop component {self.name}: {e}"
)
logger
.
error
(
f
"Failed to stop component {self.name}: {e}"
)
import
traceback
logger
.
error
(
f
"Full traceback: {traceback.format_exc()}"
)
return
False
return
False
def
_thread_wrapper
(
self
):
def
_thread_wrapper
(
self
):
...
@@ -237,11 +239,15 @@ class ThreadManager:
...
@@ -237,11 +239,15 @@ class ThreadManager:
with
self
.
_lock
:
with
self
.
_lock
:
for
name
,
component
in
self
.
components
.
items
():
for
name
,
component
in
self
.
components
.
items
():
try
:
if
not
component
.
stop
(
stop_timeout
):
if
not
component
.
stop
(
stop_timeout
):
logger
.
error
(
f
"Failed to stop component {name}"
)
logger
.
error
(
f
"Failed to stop component {name}"
)
success
=
False
success
=
False
else
:
else
:
logger
.
info
(
f
"Component {name} stopped"
)
logger
.
info
(
f
"Component {name} stopped"
)
except
Exception
as
e
:
logger
.
error
(
f
"Exception stopping component {name}: {e}"
)
success
=
False
if
success
:
if
success
:
logger
.
info
(
"All components stopped successfully"
)
logger
.
info
(
"All components stopped successfully"
)
...
...
mbetterclient/qt_player/player.py
View file @
e9e2f6c9
This diff is collapsed.
Click to expand it.
mbetterclient/qt_player/templates/default.html
View file @
e9e2f6c9
...
@@ -222,9 +222,9 @@
...
@@ -222,9 +222,9 @@
<script>
<script>
// Global variables for overlay data handling
// Global variables for overlay data handling
let
overlayData
=
{};
let
overlayData
=
{};
let
currentTitle
=
'
Announcement
'
;
let
currentTitle
=
'
Mbetter system:
'
;
let
currentMessage
=
'
This is a custom message from the system
.'
;
let
currentMessage
=
'
Waiting for game to start..
.'
;
let
currentIcon
=
'
📢
'
;
let
currentIcon
=
'
🥊
'
;
// Function to update overlay data (called by Qt WebChannel)
// Function to update overlay data (called by Qt WebChannel)
function
updateOverlayData
(
data
)
{
function
updateOverlayData
(
data
)
{
...
...
mbetterclient/web_dashboard/routes.py
View file @
e9e2f6c9
...
@@ -3702,8 +3702,8 @@ def create_result_options_migration():
...
@@ -3702,8 +3702,8 @@ def create_result_options_migration():
from
..database.migrations
import
DatabaseMigration
from
..database.migrations
import
DatabaseMigration
class
Migration_023
(
DatabaseMigration
):
class
Migration_023
(
DatabaseMigration
):
version
=
"023"
def
__init__
(
self
):
description
=
"Add result_options table for extraction system results area"
super
()
.
__init__
(
"023"
,
"Add result_options table for extraction system results area"
)
def
up
(
self
,
db_manager
):
def
up
(
self
,
db_manager
):
"""Apply migration"""
"""Apply migration"""
...
...
mbetterclient/web_dashboard/templates/dashboard/new_bet.html
View file @
e9e2f6c9
...
@@ -713,6 +713,17 @@ function updateAvailableMatchesDisplay(data, container) {
...
@@ -713,6 +713,17 @@ function updateAvailableMatchesDisplay(data, container) {
// Add event listeners for amount inputs only
// Add event listeners for amount inputs only
container
.
querySelectorAll
(
'.amount-input'
).
forEach
(
input
=>
{
container
.
querySelectorAll
(
'.amount-input'
).
forEach
(
input
=>
{
input
.
addEventListener
(
'input'
,
function
()
{
input
.
addEventListener
(
'input'
,
function
()
{
// Clear other outcomes for this match when entering an amount
const
matchId
=
this
.
getAttribute
(
'data-match-id'
);
const
currentOutcome
=
this
.
getAttribute
(
'data-outcome'
);
// Clear all other amount inputs for this match
container
.
querySelectorAll
(
`.amount-input[data-match-id="
${
matchId
}
"]`
).
forEach
(
otherInput
=>
{
if
(
otherInput
!==
this
)
{
otherInput
.
value
=
''
;
}
});
updateBetSummary
();
updateBetSummary
();
});
});
});
});
...
...
qt.conf
0 → 100644
View file @
e9e2f6c9
[
Paths
]
Prefix
= .
Libraries
= .
Plugins
=
plugins
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