Commit 956ae483 authored by Your Name's avatar Your Name

A lot of changes for the r22

parent 513abac6
......@@ -2,6 +2,25 @@
All notable changes to this project will be documented in this file.
## [10.0.22] - 2026-03-16
### Fixed
- **Critical**: Fixed extraction algorithm double processing of UNDER/OVER bets causing incorrect win amounts and report duplication
- **Bet Resolution Logic**: Corrected UNDER/OVER bet processing to ensure each bet is resolved exactly once with proper coefficient calculation
- **Extraction Association Filtering**: Implemented proper filtering to prevent UNDER/OVER outcomes from being processed in both dedicated and associated outcome sections
### Enhanced
- **Extraction Algorithm Robustness**: Improved bet result update logic to handle edge cases and ensure consistent win amount calculations
- **Report Accuracy**: Eliminated double counting of UNDER/OVER bets in statistics and reports
- **Version Management**: Updated version numbers across all components (main.py, build.py, web dashboard, settings, __init__.py)
- **User Agent String**: Updated user agent from MbetterClient/1.0r21 to MbetterClient/10.0r22
### Technical Details
- **Bet Processing Architecture**: Separated UNDER/OVER bet handling from complex outcome associations to prevent duplication
- **Database Transaction Safety**: Ensured all bet updates occur within proper transaction boundaries
- **Coefficient Calculation**: Maintained accurate win amount calculations using match outcome coefficients
- **Cross-Component Version Sync**: Synchronized version numbers across CLI, build system, web interface, and internal modules
## [1.0.13] - 2026-02-02
### Changed
......
......@@ -14,7 +14,7 @@ from typing import List, Dict, Any
# Build configuration
BUILD_CONFIG = {
'app_name': 'MbetterClient',
'app_version': '1.0.16',
'app_version': '10.0.22',
'description': 'Cross-platform multimedia client application',
'author': 'MBetter Team',
'entry_point': 'main.py',
......
......@@ -217,7 +217,7 @@ Examples:
parser.add_argument(
'--version',
action='version',
version='MbetterClient 1.0.20'
version='MbetterClient 10.0.22'
)
# Timer options
......
......@@ -4,7 +4,7 @@ MbetterClient - Cross-platform multimedia client application
A multi-threaded application with video playback, web dashboard, and REST API integration.
"""
__version__ = "1.0.20"
__version__ = "10.0.22"
__author__ = "MBetter Project"
__email__ = "dev@mbetter.net"
__description__ = "Cross-platform multimedia client with video overlay and web dashboard"
......
......@@ -2352,33 +2352,34 @@ class APIClient(ThreadedComponent):
logger.error(f"Failed to refresh endpoints from config: {e}")
def _get_last_fixture_timestamp(self) -> Optional[str]:
"""Get the server activation timestamp of the last active fixture in the database"""
"""Get the server activation timestamp of the last active fixture template in the database"""
try:
# Update heartbeat before database operation
self.heartbeat()
session = self.db_manager.get_session()
try:
# Get the most recent match with fixture_active_time set
last_active_match = session.query(MatchModel).filter(
MatchModel.fixture_active_time.isnot(None)
).order_by(MatchModel.fixture_active_time.desc()).first()
# Get the most recent match template with fixture_active_time set
# Use MatchTemplateModel (templates table) to track what we've synced from server
last_active_template = session.query(MatchTemplateModel).filter(
MatchTemplateModel.fixture_active_time.isnot(None)
).order_by(MatchTemplateModel.fixture_active_time.desc()).first()
# Update heartbeat after database query
self.heartbeat()
if last_active_match and last_active_match.fixture_active_time:
if last_active_template and last_active_template.fixture_active_time:
# Return Unix timestamp as string (long integer number)
return str(last_active_match.fixture_active_time)
return str(last_active_template.fixture_active_time)
else:
# No fixtures with activation time found - don't send 'from' parameter
# No fixture templates with activation time found - don't send 'from' parameter
return None
finally:
session.close()
except Exception as e:
logger.error(f"Failed to get last fixture activation timestamp: {e}")
logger.error(f"Failed to get last fixture template activation timestamp: {e}")
# Update heartbeat even on error
self.heartbeat()
return None
......
......@@ -262,7 +262,7 @@ class ApiConfig:
# Request settings
verify_ssl: bool = True
user_agent: str = "MbetterClient/1.0r20"
user_agent: str = "MbetterClient/10.0r22"
max_response_size_mb: int = 100
# Additional API client settings
......@@ -403,7 +403,7 @@ class AppSettings:
timer: TimerConfig = field(default_factory=TimerConfig)
# Application settings
version: str = "1.0.19"
version: str = "10.0.22"
debug_mode: bool = False
dev_message: bool = False # Enable debug mode showing only message bus messages
debug_messages: bool = False # Show all messages passing through the message bus on screen
......
......@@ -3718,6 +3718,8 @@ class GamesThread(ThreadedComponent):
# Filter winning outcomes to only include those available in the match fixture
extraction_winning_outcome_names = [outcome for outcome in extraction_winning_outcome_names if outcome in available_outcome_names]
# Filter out UNDER/OVER as they are ALWAYS handled separately in the UNDER/OVER logic
extraction_winning_outcome_names = [outcome for outcome in extraction_winning_outcome_names if outcome not in ['UNDER', 'OVER']]
logger.info(f"🏆 [EXTRACTION DEBUG] Winning outcomes for result '{selected_result}': {extraction_winning_outcome_names}")
# Log expected redistribution and actual selected payout
......@@ -3824,21 +3826,13 @@ class GamesThread(ThreadedComponent):
try:
from ..database.models import MatchOutcomeModel
# For UNDER/OVER outcomes, get from fixture coefficients
if outcome in ['UNDER', 'OVER']:
fixture_id = session.query(MatchModel.fixture_id).filter(MatchModel.id == match_id).first()
if fixture_id:
return self._get_fixture_coefficients(fixture_id[0], session)[0 if outcome == 'UNDER' else 1] or 1.0
return 1.0
# For other outcomes, get from match outcomes
# For all outcomes (including UNDER/OVER), get from match outcomes
match_outcome = session.query(MatchOutcomeModel).filter(
MatchOutcomeModel.match_id == match_id,
MatchOutcomeModel.column_name == outcome
).first()
return match_outcome.float_value if match_outcome else 1.0
except Exception as e:
logger.error(f"Failed to get coefficient for outcome {outcome}: {e}")
return 1.0
......@@ -3869,8 +3863,12 @@ class GamesThread(ThreadedComponent):
logger.info(f"DEBUG _update_bet_results: Found {len(under_over_bets)} winning {under_over_outcome} bets")
# Get coefficient for the UNDER/OVER outcome
under_over_coefficient = self._get_outcome_coefficient(match_id, under_over_outcome, session)
logger.info(f"DEBUG _update_bet_results: under_over_coefficient = {under_over_coefficient}")
for bet in under_over_bets:
win_amount = bet.amount * win_coefficient
win_amount = bet.amount * under_over_coefficient
bet.result = 'win'
bet.win_amount = win_amount
logger.info(f"DEBUG _update_bet_results: Set bet {bet.id} to win with amount {win_amount}")
......@@ -3913,8 +3911,8 @@ class GamesThread(ThreadedComponent):
logger.info(f"DEBUG _update_bet_results: Updating bets for {len(extraction_winning_outcome_names)} associated winning outcomes: {extraction_winning_outcome_names}")
for outcome_name in extraction_winning_outcome_names:
# Skip if this outcome is already handled above (selected_result)
if outcome_name == selected_result:
# Skip if this outcome is already handled above (selected_result or UNDER/OVER when under_over_outcome is set)
if outcome_name == selected_result or (outcome_name in ['UNDER', 'OVER'] and under_over_outcome is not None):
continue
# Get coefficient for this associated outcome
......
......@@ -230,7 +230,7 @@ class WebDashboard(ThreadedComponent):
def inject_globals():
return {
'app_name': 'MbetterClient',
'app_version': '1.0.16',
'app_version': '10.0.22',
'current_time': time.time(),
}
......
......@@ -42,12 +42,22 @@ def is_bet_detail_winning(detail, match, session):
Returns:
bool: True if the bet detail is winning
"""
# Direct win check
# Direct win check - this is the authoritative source set by _update_bet_results
if detail.result in ['won', 'win']:
return True
# Check if match has extraction data
# If result is not 'win', check other conditions only for non-UNDER/OVER bets
# For UNDER/OVER bets, we rely solely on the direct result check above
if match:
# Check if this is an UNDER/OVER outcome
is_under_over = detail.outcome and ('UNDER' in detail.outcome.upper() or 'OVER' in detail.outcome.upper())
# For UNDER/OVER bets, we've already checked the direct result above
# No need to check winning_outcomes or under_over_result as they could cause duplicate detection
if is_under_over:
return False
# For non-UNDER/OVER bets, check other conditions
# Check winning_outcomes array (contains all winning outcomes from extraction)
if match.winning_outcomes:
try:
......@@ -63,10 +73,6 @@ def is_bet_detail_winning(detail, match, session):
except (json.JSONDecodeError, TypeError):
pass
# Check under_over_result
if match.under_over_result and detail.outcome == match.under_over_result:
return True
# Check extraction associations if match has extraction result
if match.result:
from ..database.models import ExtractionAssociationModel
......
# MbetterClient v1.0.16
Cross-platform multimedia client application
## Installation
1. Extract this package to your desired location
2. Run the executable file
3. The application will create necessary configuration files on first run
## System Requirements
- **Operating System**: Linux 6.12.15-amd64
- **Architecture**: x86_64
- **Memory**: 512 MB RAM minimum, 1 GB recommended
- **Disk Space**: 100 MB free space
## Configuration
The application stores its configuration and database in:
- **Windows**: `%APPDATA%\MbetterClient`
- **macOS**: `~/Library/Application Support/MbetterClient`
- **Linux**: `~/.config/MbetterClient`
## Web Interface
By default, the web interface is available at: http://localhost:5001
Default login credentials:
- Username: admin
- Password: admin
**Please change the default password after first login.**
## Support
For support and documentation, please visit: https://git.nexlab.net/mbetter/mbetterc
## Version Information
- Version: 1.0.16
- Build Date: sissy
- Platform: Linux-6.12.15-amd64-x86_64-with-glibc2.42
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