File size: 10,292 Bytes
6f7e932
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
"""
Confidence-Based Prediction Sections

Categorizes predictions by confidence level:
- Sure Win: 91%+ confidence (ultra-high probability picks)
- Strong Picks: 80-90% confidence (reliable selections)
- Value Hunters: 5%+ edge vs bookmaker odds
- Upset Watch: Underdog potential picks
- Daily Banker: Single safest pick of the day
"""

from dataclasses import dataclass, asdict
from typing import Dict, List, Optional, Tuple
from datetime import datetime
import json


@dataclass
class SectionConfig:
    """Configuration for a confidence section"""
    name: str
    description: str
    icon: str
    color: str
    min_confidence: Optional[float] = None
    max_confidence: Optional[float] = None
    min_edge: Optional[float] = None
    max_picks: Optional[int] = None


class ConfidenceSectionsManager:
    """
    Categorize predictions into confidence-based sections.
    
    Sections:
    - Sure Win: 91%+ confidence picks (very rare, very reliable)
    - Strong Picks: 80-90% confidence (solid selections)
    - Value Hunters: Good edge vs market odds (5%+ value)
    - Upset Watch: Underdog potential (25%+ probability)
    - Daily Banker: Single highest confidence pick
    """
    
    SECTIONS = {
        'sure_win': SectionConfig(
            name='🔒 Sure Win',
            description='Ultra-high confidence picks (91%+ probability)',
            icon='🔒',
            color='#10B981',  # Emerald green
            min_confidence=0.91
        ),
        'strong_picks': SectionConfig(
            name='💪 Strong Picks',
            description='High confidence selections (80-90%)',
            icon='💪',
            color='#3B82F6',  # Blue
            min_confidence=0.80,
            max_confidence=0.90
        ),
        'value_hunters': SectionConfig(
            name='💎 Value Hunters',
            description='Great edge vs bookmaker odds (5%+ value)',
            icon='💎',
            color='#8B5CF6',  # Purple
            min_edge=0.05
        ),
        'upset_watch': SectionConfig(
            name='⚡ Upset Watch',
            description='Potential upsets worth watching',
            icon='⚡',
            color='#F59E0B',  # Amber
        ),
        'daily_banker': SectionConfig(
            name='🎯 Daily Banker',
            description='Single safest pick of the day',
            icon='🎯',
            color='#EF4444',  # Red
            max_picks=1
        ),
        'risky_rewards': SectionConfig(
            name='🎲 Risky Rewards',
            description='Long shots with high potential returns',
            icon='🎲',
            color='#EC4899',  # Pink
            min_confidence=0.30,
            max_confidence=0.50
        )
    }
    
    def __init__(self):
        self.prediction_history = []
    
    def categorize(self, predictions: List[Dict]) -> Dict[str, List[Dict]]:
        """
        Sort predictions into confidence-based sections.
        
        Args:
            predictions: List of prediction dicts with 'confidence', 'value_edge', etc.
            
        Returns:
            Dict mapping section name to list of predictions
        """
        sections = {key: [] for key in self.SECTIONS}
        
        if not predictions:
            return sections
        
        for pred in predictions:
            confidence = pred.get('confidence', 0)
            if isinstance(confidence, str):
                confidence = float(confidence.replace('%', '')) / 100
            elif confidence > 1:
                confidence = confidence / 100
                
            edge = pred.get('value_edge', 0) or 0
            
            # Determine predicted outcome probabilities
            home_prob = pred.get('home_win_prob', 0) or 0
            draw_prob = pred.get('draw_prob', 0) or 0  
            away_prob = pred.get('away_win_prob', 0) or 0
            
            # Normalize if needed
            if home_prob > 1:
                home_prob /= 100
            if draw_prob > 1:
                draw_prob /= 100
            if away_prob > 1:
                away_prob /= 100
            
            max_prob = max(home_prob, draw_prob, away_prob)
            
            # Sure Win: 91%+ confidence
            if confidence >= 0.91 or max_prob >= 0.91:
                sections['sure_win'].append(self._enrich_prediction(pred, 'sure_win'))
            
            # Strong Picks: 80-90%
            elif confidence >= 0.80 or max_prob >= 0.80:
                sections['strong_picks'].append(self._enrich_prediction(pred, 'strong_picks'))
            
            # Value Hunters: 5%+ edge
            if edge >= 0.05:
                sections['value_hunters'].append(self._enrich_prediction(pred, 'value_hunters'))
            
            # Upset Watch: Underdog with reasonable probability
            is_upset = self._is_upset_potential(pred)
            if is_upset:
                sections['upset_watch'].append(self._enrich_prediction(pred, 'upset_watch'))
            
            # Risky Rewards: 30-50% confidence but good odds
            if 0.30 <= confidence <= 0.50:
                sections['risky_rewards'].append(self._enrich_prediction(pred, 'risky_rewards'))
        
        # Daily Banker: Highest confidence pick
        if predictions:
            best = max(predictions, key=lambda x: self._get_confidence(x))
            sections['daily_banker'] = [self._enrich_prediction(best, 'daily_banker')]
        
        # Sort each section by confidence descending
        for section_name in sections:
            if section_name != 'daily_banker':
                sections[section_name].sort(
                    key=lambda x: self._get_confidence(x), 
                    reverse=True
                )
        
        return sections
    
    def _get_confidence(self, pred: Dict) -> float:
        """Extract normalized confidence from prediction"""
        confidence = pred.get('confidence', 0)
        if isinstance(confidence, str):
            confidence = float(confidence.replace('%', '')) / 100
        elif confidence > 1:
            confidence = confidence / 100
        return confidence
    
    def _is_upset_potential(self, pred: Dict) -> bool:
        """
        Check if this is a potential upset.
        
        Criteria:
        - Lower-ranked team has 25%+ win probability
        - OR home team expected to lose but has 30%+ probability
        """
        home_prob = pred.get('home_win_prob', 0) or 0
        away_prob = pred.get('away_win_prob', 0) or 0
        
        if home_prob > 1:
            home_prob /= 100
        if away_prob > 1:
            away_prob /= 100
            
        # Check ELO difference if available
        home_elo = pred.get('home_elo', 1500)
        away_elo = pred.get('away_elo', 1500)
        
        # Underdog is team with lower ELO
        if home_elo < away_elo and home_prob >= 0.25:
            return True
        elif away_elo < home_elo and away_prob >= 0.25:
            return True
        
        # Also check if predicted outcome differs from ELO expectation
        predicted = pred.get('predicted_outcome', '')
        if home_elo > away_elo + 50 and predicted == 'Away':
            return True
        elif away_elo > home_elo + 50 and predicted == 'Home':
            return True
            
        return False
    
    def _enrich_prediction(self, pred: Dict, section: str) -> Dict:
        """Add section metadata to prediction"""
        enriched = pred.copy()
        enriched['section'] = section
        enriched['section_config'] = asdict(self.SECTIONS[section])
        return enriched
    
    def get_sure_wins(self, predictions: List[Dict]) -> List[Dict]:
        """Get only Sure Win picks (91%+ confidence)"""
        return self.categorize(predictions)['sure_win']
    
    def get_strong_picks(self, predictions: List[Dict]) -> List[Dict]:
        """Get Strong Picks (80-90% confidence)"""
        return self.categorize(predictions)['strong_picks']
    
    def get_value_bets(self, predictions: List[Dict]) -> List[Dict]:
        """Get Value Hunter picks (5%+ edge)"""
        return self.categorize(predictions)['value_hunters']
    
    def get_daily_banker(self, predictions: List[Dict]) -> Optional[Dict]:
        """Get the single Daily Banker pick"""
        bankers = self.categorize(predictions)['daily_banker']
        return bankers[0] if bankers else None
    
    def get_section_stats(self, predictions: List[Dict]) -> Dict:
        """Get statistics about each section"""
        sections = self.categorize(predictions)
        
        stats = {}
        for section_name, preds in sections.items():
            if preds:
                confidences = [self._get_confidence(p) for p in preds]
                stats[section_name] = {
                    'count': len(preds),
                    'avg_confidence': round(sum(confidences) / len(confidences) * 100, 1),
                    'min_confidence': round(min(confidences) * 100, 1),
                    'max_confidence': round(max(confidences) * 100, 1),
                    'config': asdict(self.SECTIONS[section_name])
                }
            else:
                stats[section_name] = {
                    'count': 0,
                    'avg_confidence': 0,
                    'min_confidence': 0,
                    'max_confidence': 0,
                    'config': asdict(self.SECTIONS[section_name])
                }
        
        return stats
    
    def get_all_sections_config(self) -> Dict:
        """Get configuration for all sections"""
        return {
            name: asdict(config) 
            for name, config in self.SECTIONS.items()
        }


# Global instance
confidence_manager = ConfidenceSectionsManager()


def get_confidence_sections(predictions: List[Dict]) -> Dict[str, List[Dict]]:
    """Get predictions organized by confidence sections"""
    return confidence_manager.categorize(predictions)


def get_sure_wins(predictions: List[Dict]) -> List[Dict]:
    """Get 91%+ confidence predictions"""
    return confidence_manager.get_sure_wins(predictions)


def get_daily_banker(predictions: List[Dict]) -> Optional[Dict]:
    """Get single safest pick"""
    return confidence_manager.get_daily_banker(predictions)