# MbetterClient Result Extraction Algorithm

## Overview

The Result Extraction Algorithm is the core component responsible for determining match outcomes in the MbetterClient betting system. It ensures fair play while maintaining system profitability through sophisticated redistribution controls and CAP (Controlled Redistribution) logic.

## Algorithm Flow

### Phase 1: Initialization and Data Collection

#### Step 1.1: Input Validation
- **Inputs**: `fixture_id`, `match_id`
- **Validation**: Ensure match exists and has pending bets
- **Initialization**: Set `selected_result = None`, `extraction_winning_outcome_names = []`

#### Step 1.2: Match Outcomes Retrieval
```sql
SELECT column_name, float_value FROM match_outcomes WHERE match_id = ?
```
- Retrieves all possible betting outcomes for the match (WIN1, WIN2, DRAW, KO1, KO2, UNDER, OVER, etc.)
- Each outcome has an associated coefficient (payout multiplier)

#### Step 1.3: Result Options Filtering
```sql
SELECT result_name FROM result_options
WHERE is_active = true
AND result_name IN (match_outcomes_list)
AND result_name NOT IN ('UNDER', 'OVER')
```
- Identifies active result options that correspond to match outcomes
- Excludes UNDER/OVER as they are handled separately

### Phase 2: Financial Analysis

#### Step 2.1: Total Payin Calculation
**Total Intake = UNDER/OVER Bets + Other Bets**

**UNDER/OVER Payin:**
```sql
SELECT SUM(amount) FROM bet_detail
WHERE match_id = ? AND outcome IN ('UNDER', 'OVER')
AND result = 'pending' AND result != 'cancelled'
```

**Other Bets Payin:**
```sql
SELECT SUM(amount) FROM bet_detail
WHERE match_id = ? AND outcome NOT IN ('UNDER', 'OVER')
AND result = 'pending' AND result != 'cancelled'
```

**Total Payin = under_payin + other_payin**

#### Step 2.2: UNDER/OVER Payout Calculation
For each UNDER/OVER outcome:
```
payout = bet_amount × coefficient
```
- UNDER payout = total UNDER bets × UNDER coefficient
- OVER payout = total OVER bets × OVER coefficient

#### Step 2.3: CAP Threshold Calculation
**Base CAP Threshold = Total Payin × CAP Percentage**

Where CAP Percentage defaults to 70% but is configurable.

**Adjusted CAP Threshold = Base CAP + Accumulated Shortfall**

**Final CAP Threshold = Adjusted CAP - UNDER/OVER Winner Payout**

If UNDER wins: `Final CAP = Adjusted CAP - under_payout`
If OVER wins: `Final CAP = Adjusted CAP - over_payout`

### Phase 3: Result Selection

#### Step 3.1: Payout Calculation for Each Result
For each possible result (WIN1, WIN2, DRAW, etc.):

**Find Associated Outcomes:**
```sql
SELECT outcome_name FROM extraction_associations
WHERE extraction_result = 'result_name'
```

**Calculate Total Result Payout:**
```
result_payout = 0
FOR EACH associated_outcome:
    bet_amount = SUM(bets on associated_outcome)
    coefficient = outcome_coefficient
    result_payout += bet_amount × coefficient
```

**Example:**
- Result: "WIN1"
- Associated outcomes: "KO1" (coeff: 3.0), "SUB1" (coeff: 2.5)
- Bets: $10 on KO1, $15 on SUB1
- WIN1 payout = ($10 × 3.0) + ($15 × 2.5) = $30 + $37.50 = $67.50

#### Step 3.2: Eligibility Filtering
```
eligible_results = {result: payout for result, payout in payouts.items()
                   if payout <= final_cap_threshold}
```

#### Step 3.3: Fallback Logic
If no results are eligible (all payouts exceed CAP):
```
lowest_payout_result = min(payouts, key=payouts.get)
eligible_results = {lowest_payout_result: payouts[lowest_payout_result]}
```

#### Step 3.4: Weighted Random Selection
Among eligible results, select the one with maximum payout:
```
max_payout = max(eligible_results.values())
candidates = [r for r, p in eligible_results.items() if p == max_payout]
selected_result = random.choice(candidates)
```

### Phase 4: Winning Outcomes Determination

#### Step 4.1: Association Lookup
```sql
SELECT DISTINCT outcome_name FROM extraction_associations
WHERE extraction_result = selected_result
```

#### Step 4.2: Validation Against Match Outcomes
```
extraction_winning_outcome_names = [outcome for outcome in associated_outcomes
                                  if outcome in match_possible_outcomes]
```

### Phase 5: Bet Result Updates

#### Step 5.1: UNDER/OVER Bet Processing
Based on stored `under_over_result` from video selection:

**If UNDER wins:**
- Mark UNDER bets as 'win' with `win_amount = bet_amount × under_coefficient`
- Mark OVER bets as 'lost'

**If OVER wins:**
- Mark OVER bets as 'win' with `win_amount = bet_amount × over_coefficient`
- Mark UNDER bets as 'lost'

#### Step 5.2: Selected Result Processing
Mark bets on `selected_result` as 'win':
```
win_amount = bet_amount × result_coefficient
```

#### Step 5.3: Associated Outcomes Processing
For each outcome in `extraction_winning_outcome_names`:
```
outcome_coefficient = get_coefficient(match_id, outcome)
win_amount = bet_amount × outcome_coefficient
```

#### Step 5.4: Loss Processing
Mark all other bets as 'lost':
```
losing_outcomes = [selected_result] + extraction_winning_outcome_names + ['UNDER', 'OVER']
UPDATE bet_detail SET result = 'lost'
WHERE match_id = ? AND outcome NOT IN losing_outcomes AND result = 'pending'
```

### Phase 6: Database Updates

#### Step 6.1: Match Result Storage
```sql
UPDATE matches SET
    result = selected_result,
    winning_outcomes = json.dumps(extraction_winning_outcome_names),
    under_over_result = under_over_result,
    result_breakdown = json.dumps({
        'selected_result': selected_result,
        'winning_outcomes': extraction_winning_outcome_names,
        'under_over_result': under_over_result
    })
WHERE id = match_id
```

#### Step 6.2: Statistics Collection
Store comprehensive extraction metrics in `extraction_stats` table:
- Total bets, amounts collected, redistributed
- UNDER/OVER statistics
- CAP applied status
- Result breakdown

#### Step 6.3: Shortfall Tracking
**Expected Redistribution = Total Payin × CAP Percentage**

**Actual Redistribution = Sum of all win_amounts**

**Shortfall = max(0, Expected - Actual)**

Update daily shortfall tracking for future CAP adjustments.

### Phase 7: System Notifications

#### Step 7.1: Result Broadcasting
Send `PLAY_VIDEO_RESULTS` message with:
- `fixture_id`, `match_id`
- `result = selected_result`
- `under_over_result`
- `winning_outcomes = extraction_winning_outcome_names`

#### Step 7.2: Match Completion
Send `MATCH_DONE` message to advance to next match.

## Key Design Principles

### CAP (Controlled Redistribution) Logic
- **Purpose**: Prevent excessive payouts that could harm profitability
- **Mechanism**: Only select results where total payout ≤ CAP threshold
- **Adjustment Factors**:
  - Accumulated shortfalls from previous extractions
  - Committed UNDER/OVER payouts
  - Total intake from all betting activity

### Multi-Level Winning System
- **Primary Result**: Main outcome selected by algorithm
- **Associated Outcomes**: Additional winning outcomes
- **UNDER/OVER Independence**: Parallel result system

### Profit Maximization
- **Weighted Selection**: Prefers results maximizing redistribution
- **Fallback Protection**: Always selects result, even if CAP exceeded
- **Shortfall Carryover**: Tracks and compensates for under-redistribution

### Data Integrity
- **Transaction Safety**: All updates in database transactions
- **Comprehensive Logging**: All decisions and calculations logged
- **Error Recovery**: Multiple fallback mechanisms

## Configuration Parameters

- **CAP Percentage**: Default 70%, configurable via `extraction_redistribution_cap`
- **Shortfall Tracking**: Daily accumulated shortfalls affect future CAP calculations
- **Result Associations**: Configurable via `extraction_associations` table
- **Betting Mode**: Affects match status progression but not extraction logic

## Error Handling

- **Fallback Selection**: Random selection if extraction fails
- **CAP Override**: Selects lowest payout result if all exceed CAP
- **Transaction Rollback**: Database consistency maintained on errors
- **Logging**: Comprehensive debug information for troubleshooting

## Performance Considerations

- **Database Efficiency**: Single transactions for all updates
- **Memory Management**: Streaming result processing for large datasets
- **Concurrent Safety**: Match-level locking prevents race conditions
- **Audit Trail**: Complete history of all extraction decisions