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
549596de
Commit
549596de
authored
Nov 24, 2025
by
Stefy Lanza (nextime / spora )
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Almost there
parent
7fc35762
Changes
8
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
765 additions
and
202 deletions
+765
-202
client.py
mbetterclient/api_client/client.py
+11
-0
games_thread.py
mbetterclient/core/games_thread.py
+334
-96
match_timer.py
mbetterclient/core/match_timer.py
+2
-2
migrations.py
mbetterclient/database/migrations.py
+45
-0
models.py
mbetterclient/database/models.py
+2
-0
player.py
mbetterclient/qt_player/player.py
+194
-23
results.html
mbetterclient/qt_player/templates/results.html
+171
-80
fixture_details.html
...nt/web_dashboard/templates/dashboard/fixture_details.html
+6
-1
No files found.
mbetterclient/api_client/client.py
View file @
549596de
...
@@ -633,6 +633,14 @@ class UpdatesResponseHandler(ResponseHandler):
...
@@ -633,6 +633,14 @@ class UpdatesResponseHandler(ResponseHandler):
if
not
zip_filename
:
if
not
zip_filename
:
continue
continue
# Check if ZIP has already been validated successfully
if
match
.
zip_validation_status
==
'valid'
:
logger
.
debug
(
f
"ZIP file already validated: {zip_filename} for fixture {fixture_id}"
)
continue
elif
match
.
zip_validation_status
==
'validating'
:
logger
.
debug
(
f
"ZIP file validation in progress: {zip_filename} for fixture {fixture_id}"
)
continue
logger
.
debug
(
f
"Validating ZIP file: {zip_filename} for fixture {fixture_id}"
)
logger
.
debug
(
f
"Validating ZIP file: {zip_filename} for fixture {fixture_id}"
)
zip_path
=
self
.
zip_storage_dir
/
zip_filename
zip_path
=
self
.
zip_storage_dir
/
zip_filename
...
@@ -649,6 +657,9 @@ class UpdatesResponseHandler(ResponseHandler):
...
@@ -649,6 +657,9 @@ class UpdatesResponseHandler(ResponseHandler):
fixture_valid
=
False
fixture_valid
=
False
else
:
else
:
logger
.
debug
(
f
"ZIP file validation passed: {zip_filename}"
)
logger
.
debug
(
f
"ZIP file validation passed: {zip_filename}"
)
# Mark as validated in database
match
.
zip_validation_status
=
'valid'
session
.
commit
()
if
not
fixture_valid
:
if
not
fixture_valid
:
logger
.
warning
(
f
"Fixture {fixture_id} has invalid/missing ZIP files: {missing_or_invalid_zips}"
)
logger
.
warning
(
f
"Fixture {fixture_id} has invalid/missing ZIP files: {missing_or_invalid_zips}"
)
...
...
mbetterclient/core/games_thread.py
View file @
549596de
This diff is collapsed.
Click to expand it.
mbetterclient/core/match_timer.py
View file @
549596de
...
@@ -526,7 +526,7 @@ class MatchTimerComponent(ThreadedComponent):
...
@@ -526,7 +526,7 @@ class MatchTimerComponent(ThreadedComponent):
# Find the most recently completed match in this fixture
# Find the most recently completed match in this fixture
last_match
=
session
.
query
(
MatchModel
)
.
filter
(
last_match
=
session
.
query
(
MatchModel
)
.
filter
(
MatchModel
.
fixture_id
==
fixture_id
,
MatchModel
.
fixture_id
==
fixture_id
,
MatchModel
.
status
.
in_
([
'done'
,
'cancelled'
,
'failed'
]),
MatchModel
.
status
.
in_
([
'done'
,
'
end'
,
'
cancelled'
,
'failed'
]),
MatchModel
.
active_status
==
True
MatchModel
.
active_status
==
True
)
.
order_by
(
MatchModel
.
updated_at
.
desc
())
.
first
()
)
.
order_by
(
MatchModel
.
updated_at
.
desc
())
.
first
()
...
@@ -547,7 +547,7 @@ class MatchTimerComponent(ThreadedComponent):
...
@@ -547,7 +547,7 @@ class MatchTimerComponent(ThreadedComponent):
# 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
)
.
filter
(
MatchModel
.
status
.
in_
([
'done'
,
'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_
%
'
)
)
)
...
...
mbetterclient/database/migrations.py
View file @
549596de
...
@@ -2316,6 +2316,50 @@ class Migration_029_ChangeMatchNumberToUniqueWithinFixture(DatabaseMigration):
...
@@ -2316,6 +2316,50 @@ class Migration_029_ChangeMatchNumberToUniqueWithinFixture(DatabaseMigration):
logger
.
error
(
f
"Failed to revert match_number constraint: {e}"
)
logger
.
error
(
f
"Failed to revert match_number constraint: {e}"
)
return
False
return
False
class
Migration_030_AddZipValidationStatus
(
DatabaseMigration
):
"""Add zip_validation_status field to matches table"""
def
__init__
(
self
):
super
()
.
__init__
(
"030"
,
"Add zip_validation_status field to matches table"
)
def
up
(
self
,
db_manager
)
->
bool
:
"""Add zip_validation_status column to matches table"""
try
:
with
db_manager
.
engine
.
connect
()
as
conn
:
# Check if zip_validation_status column already exists
result
=
conn
.
execute
(
text
(
"PRAGMA table_info(matches)"
))
columns
=
[
row
[
1
]
for
row
in
result
.
fetchall
()]
if
'zip_validation_status'
not
in
columns
:
# Add zip_validation_status column with default value 'pending'
conn
.
execute
(
text
(
"""
ALTER TABLE matches
ADD COLUMN zip_validation_status VARCHAR(20) DEFAULT 'pending'
"""
))
# Add index for zip_validation_status column
conn
.
execute
(
text
(
"""
CREATE INDEX IF NOT EXISTS ix_matches_zip_validation_status
ON matches(zip_validation_status)
"""
))
conn
.
commit
()
logger
.
info
(
"zip_validation_status column added to matches table"
)
else
:
logger
.
info
(
"zip_validation_status column already exists in matches table"
)
return
True
except
Exception
as
e
:
logger
.
error
(
f
"Failed to add zip_validation_status field to matches: {e}"
)
return
False
def
down
(
self
,
db_manager
)
->
bool
:
"""Remove zip_validation_status column - SQLite doesn't support DROP COLUMN easily"""
logger
.
warning
(
"SQLite doesn't support DROP COLUMN - zip_validation_status column will remain"
)
return
True
# Registry of all migrations in order
# Registry of all migrations in order
MIGRATIONS
:
List
[
DatabaseMigration
]
=
[
MIGRATIONS
:
List
[
DatabaseMigration
]
=
[
Migration_001_InitialSchema
(),
Migration_001_InitialSchema
(),
...
@@ -2347,6 +2391,7 @@ MIGRATIONS: List[DatabaseMigration] = [
...
@@ -2347,6 +2391,7 @@ MIGRATIONS: List[DatabaseMigration] = [
Migration_027_AddDefaultIntroTemplatesConfig
(),
Migration_027_AddDefaultIntroTemplatesConfig
(),
Migration_028_AddFixtureRefreshIntervalConfig
(),
Migration_028_AddFixtureRefreshIntervalConfig
(),
Migration_029_ChangeMatchNumberToUniqueWithinFixture
(),
Migration_029_ChangeMatchNumberToUniqueWithinFixture
(),
Migration_030_AddZipValidationStatus
(),
]
]
...
...
mbetterclient/database/models.py
View file @
549596de
...
@@ -472,6 +472,7 @@ class MatchModel(BaseModel):
...
@@ -472,6 +472,7 @@ class MatchModel(BaseModel):
Index
(
'ix_matches_file_sha1sum'
,
'file_sha1sum'
),
Index
(
'ix_matches_file_sha1sum'
,
'file_sha1sum'
),
Index
(
'ix_matches_zip_sha1sum'
,
'zip_sha1sum'
),
Index
(
'ix_matches_zip_sha1sum'
,
'zip_sha1sum'
),
Index
(
'ix_matches_zip_upload_status'
,
'zip_upload_status'
),
Index
(
'ix_matches_zip_upload_status'
,
'zip_upload_status'
),
Index
(
'ix_matches_zip_validation_status'
,
'zip_validation_status'
),
Index
(
'ix_matches_created_by'
,
'created_by'
),
Index
(
'ix_matches_created_by'
,
'created_by'
),
Index
(
'ix_matches_fixture_active_time'
,
'fixture_active_time'
),
Index
(
'ix_matches_fixture_active_time'
,
'fixture_active_time'
),
Index
(
'ix_matches_composite'
,
'active_status'
,
'zip_upload_status'
,
'created_at'
),
Index
(
'ix_matches_composite'
,
'active_status'
,
'zip_upload_status'
,
'created_at'
),
...
@@ -504,6 +505,7 @@ class MatchModel(BaseModel):
...
@@ -504,6 +505,7 @@ class MatchModel(BaseModel):
zip_sha1sum
=
Column
(
String
(
255
),
comment
=
'SHA1 checksum of ZIP file'
)
zip_sha1sum
=
Column
(
String
(
255
),
comment
=
'SHA1 checksum of ZIP file'
)
zip_upload_status
=
Column
(
String
(
20
),
default
=
'pending'
,
comment
=
'Upload status: pending, uploading, completed, failed'
)
zip_upload_status
=
Column
(
String
(
20
),
default
=
'pending'
,
comment
=
'Upload status: pending, uploading, completed, failed'
)
zip_upload_progress
=
Column
(
Float
,
default
=
0.0
,
comment
=
'Upload progress percentage (0.0-100.0)'
)
zip_upload_progress
=
Column
(
Float
,
default
=
0.0
,
comment
=
'Upload progress percentage (0.0-100.0)'
)
zip_validation_status
=
Column
(
String
(
20
),
default
=
'pending'
,
comment
=
'Validation status: pending, validating, valid, invalid, failed'
)
# User tracking
# User tracking
created_by
=
Column
(
Integer
,
ForeignKey
(
'users.id'
),
comment
=
'User who created this record'
)
created_by
=
Column
(
Integer
,
ForeignKey
(
'users.id'
),
comment
=
'User who created this record'
)
...
...
mbetterclient/qt_player/player.py
View file @
549596de
This diff is collapsed.
Click to expand it.
mbetterclient/qt_player/templates/results.html
View file @
549596de
This diff is collapsed.
Click to expand it.
mbetterclient/web_dashboard/templates/dashboard/fixture_details.html
View file @
549596de
...
@@ -116,6 +116,7 @@
...
@@ -116,6 +116,7 @@
<th>
Fighters
</th>
<th>
Fighters
</th>
<th>
Status
</th>
<th>
Status
</th>
<th>
Start Time
</th>
<th>
Start Time
</th>
<th>
End Time
</th>
<th>
Result
</th>
<th>
Result
</th>
<th>
Outcomes
</th>
<th>
Outcomes
</th>
<th>
Actions
</th>
<th>
Actions
</th>
...
@@ -391,6 +392,7 @@ function renderMatchesTable(matches) {
...
@@ -391,6 +392,7 @@ function renderMatchesTable(matches) {
matches
.
forEach
(
match
=>
{
matches
.
forEach
(
match
=>
{
const
row
=
document
.
createElement
(
'tr'
);
const
row
=
document
.
createElement
(
'tr'
);
const
startTimeDisplay
=
match
.
start_time
?
new
Date
(
match
.
start_time
).
toLocaleString
()
:
'Not set'
;
const
startTimeDisplay
=
match
.
start_time
?
new
Date
(
match
.
start_time
).
toLocaleString
()
:
'Not set'
;
const
endTimeDisplay
=
match
.
end_time
?
new
Date
(
match
.
end_time
).
toLocaleString
()
:
'Not set'
;
const
resultDisplay
=
match
.
result
||
'Not available'
;
const
resultDisplay
=
match
.
result
||
'Not available'
;
const
outcomesCount
=
match
.
outcome_count
||
0
;
const
outcomesCount
=
match
.
outcome_count
||
0
;
...
@@ -403,6 +405,7 @@ function renderMatchesTable(matches) {
...
@@ -403,6 +405,7 @@ function renderMatchesTable(matches) {
</td>
</td>
<td>
${
getStatusBadge
(
match
)}
</td>
<td>
${
getStatusBadge
(
match
)}
</td>
<td><small class="text-info">
${
startTimeDisplay
}
</small></td>
<td><small class="text-info">
${
startTimeDisplay
}
</small></td>
<td><small class="text-success">
${
endTimeDisplay
}
</small></td>
<td><small class="text-muted">
${
resultDisplay
}
</small></td>
<td><small class="text-muted">
${
resultDisplay
}
</small></td>
<td><span class="badge bg-light text-dark">
${
outcomesCount
}
outcomes</span></td>
<td><span class="badge bg-light text-dark">
${
outcomesCount
}
outcomes</span></td>
<td>
<td>
...
@@ -438,6 +441,7 @@ function updateMatchesTable(matches) {
...
@@ -438,6 +441,7 @@ function updateMatchesTable(matches) {
processedMatches
.
add
(
match
.
id
);
processedMatches
.
add
(
match
.
id
);
const
startTimeDisplay
=
match
.
start_time
?
new
Date
(
match
.
start_time
).
toLocaleString
()
:
'Not set'
;
const
startTimeDisplay
=
match
.
start_time
?
new
Date
(
match
.
start_time
).
toLocaleString
()
:
'Not set'
;
const
endTimeDisplay
=
match
.
end_time
?
new
Date
(
match
.
end_time
).
toLocaleString
()
:
'Not set'
;
const
resultDisplay
=
match
.
result
||
'Not available'
;
const
resultDisplay
=
match
.
result
||
'Not available'
;
const
outcomesCount
=
match
.
outcome_count
||
0
;
const
outcomesCount
=
match
.
outcome_count
||
0
;
...
@@ -450,6 +454,7 @@ function updateMatchesTable(matches) {
...
@@ -450,6 +454,7 @@ function updateMatchesTable(matches) {
</td>
</td>
<td>
${
getStatusBadge
(
match
)}
</td>
<td>
${
getStatusBadge
(
match
)}
</td>
<td><small class="text-info">
${
startTimeDisplay
}
</small></td>
<td><small class="text-info">
${
startTimeDisplay
}
</small></td>
<td><small class="text-success">
${
endTimeDisplay
}
</small></td>
<td><small class="text-muted">
${
resultDisplay
}
</small></td>
<td><small class="text-muted">
${
resultDisplay
}
</small></td>
<td><span class="badge bg-light text-dark">
${
outcomesCount
}
outcomes</span></td>
<td><span class="badge bg-light text-dark">
${
outcomesCount
}
outcomes</span></td>
<td>
<td>
...
...
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