Spaces:
Runtime error
Runtime error
| """ | |
| Enhanced API Endpoints | |
| Additional API routes for: | |
| - Enhanced predictions with caching | |
| - Real-time data streaming | |
| - User notifications | |
| - Advanced statistics | |
| - Match recommendations | |
| """ | |
| from flask import Blueprint, jsonify, request | |
| from datetime import datetime, timedelta | |
| from typing import Dict, List, Optional | |
| # Import our new modules | |
| from src.cache_system import ( | |
| cache_prediction, cache_fixtures, | |
| prediction_cache, get_cache_stats, | |
| invalidate_prediction_cache | |
| ) | |
| from src.realtime_updates import ( | |
| event_emitter, live_tracker, odds_tracker, | |
| alert_manager, get_event_stream, emit_prediction | |
| ) | |
| from src.notification_service import ( | |
| notification_service, get_user_notifications, | |
| get_unread_count, notify_sure_win | |
| ) | |
| # Create blueprint | |
| enhanced_api = Blueprint('enhanced_api', __name__, url_prefix='/api/v4') | |
| # ============================================================ | |
| # Enhanced Prediction Endpoints | |
| # ============================================================ | |
| def enhanced_prediction(): | |
| """Enhanced prediction with caching and full analysis""" | |
| home = request.args.get('home') | |
| away = request.args.get('away') | |
| league = request.args.get('league', 'bundesliga') | |
| if not home or not away: | |
| return jsonify({'success': False, 'error': 'Missing home or away team'}) | |
| # Check cache first | |
| cache_key = f"pred_{home}_{away}_{league}" | |
| cached = prediction_cache.get(cache_key) | |
| if cached: | |
| cached['from_cache'] = True | |
| cached['cache_age'] = 'recent' | |
| return jsonify({'success': True, 'prediction': cached}) | |
| # Generate prediction | |
| try: | |
| from src.enhanced_predictor_v2 import enhanced_predict_with_goals | |
| from src.advanced_features import get_team_form, get_h2h_stats | |
| # Get prediction | |
| prediction = enhanced_predict_with_goals(home, away, league) | |
| # Enrich with additional data | |
| home_form = get_team_form(home) | |
| away_form = get_team_form(away) | |
| h2h = get_h2h_stats(home, away) | |
| result = { | |
| 'match': { | |
| 'home': home, | |
| 'away': away, | |
| 'league': league | |
| }, | |
| 'prediction': prediction, | |
| 'form': { | |
| 'home': home_form, | |
| 'away': away_form | |
| }, | |
| 'h2h': h2h, | |
| 'timestamp': datetime.now().isoformat(), | |
| 'from_cache': False | |
| } | |
| # Cache the result | |
| prediction_cache.set(cache_key, result, ttl=300) | |
| # Emit event for real-time subscribers | |
| emit_prediction(result) | |
| # Check for sure win | |
| if prediction.get('confidence', 0) >= 0.91: | |
| alert_manager.send_sure_win_alert(result) | |
| return jsonify({'success': True, 'prediction': result}) | |
| except Exception as e: | |
| return jsonify({'success': False, 'error': str(e)}) | |
| def batch_predictions(): | |
| """Get predictions for multiple matches at once""" | |
| data = request.get_json() or {} | |
| matches = data.get('matches', []) | |
| if not matches: | |
| return jsonify({'success': False, 'error': 'No matches provided'}) | |
| results = [] | |
| for match in matches[:20]: # Limit to 20 matches | |
| home = match.get('home') | |
| away = match.get('away') | |
| league = match.get('league', 'bundesliga') | |
| if home and away: | |
| cache_key = f"pred_{home}_{away}_{league}" | |
| cached = prediction_cache.get(cache_key) | |
| if cached: | |
| results.append({'match': match, 'prediction': cached, 'cached': True}) | |
| else: | |
| try: | |
| from src.enhanced_predictor_v2 import enhanced_predict | |
| pred = enhanced_predict(home, away, league) | |
| prediction_cache.set(cache_key, pred, ttl=300) | |
| results.append({'match': match, 'prediction': pred, 'cached': False}) | |
| except Exception as e: | |
| results.append({'match': match, 'error': str(e)}) | |
| return jsonify({ | |
| 'success': True, | |
| 'predictions': results, | |
| 'count': len(results) | |
| }) | |
| # ============================================================ | |
| # Real-time Data Endpoints | |
| # ============================================================ | |
| def realtime_stream(): | |
| """Get real-time event stream status""" | |
| return jsonify({ | |
| 'success': True, | |
| 'stream': get_event_stream() | |
| }) | |
| def get_events(): | |
| """Get recent events""" | |
| event_type = request.args.get('type') | |
| limit = int(request.args.get('limit', 50)) | |
| events = event_emitter.get_history(event_type, limit) | |
| return jsonify({ | |
| 'success': True, | |
| 'events': events, | |
| 'count': len(events) | |
| }) | |
| def get_live_matches(): | |
| """Get currently tracked live matches""" | |
| return jsonify({ | |
| 'success': True, | |
| 'matches': live_tracker.get_live_matches(), | |
| 'count': len(live_tracker.live_matches) | |
| }) | |
| def get_alerts(): | |
| """Get recent alerts""" | |
| limit = int(request.args.get('limit', 20)) | |
| return jsonify({ | |
| 'success': True, | |
| 'alerts': alert_manager.get_active_alerts(limit) | |
| }) | |
| # ============================================================ | |
| # Notification Endpoints | |
| # ============================================================ | |
| def user_notifications(): | |
| """Get user notifications""" | |
| user_id = request.args.get('user_id', 'default') | |
| return jsonify({ | |
| 'success': True, | |
| 'notifications': get_user_notifications(user_id), | |
| 'unread_count': get_unread_count(user_id) | |
| }) | |
| def mark_notification_read(): | |
| """Mark notification as read""" | |
| data = request.get_json() or {} | |
| user_id = data.get('user_id', 'default') | |
| notification_id = data.get('notification_id') | |
| if notification_id: | |
| success = notification_service.in_app.mark_read(user_id, notification_id) | |
| return jsonify({'success': success}) | |
| return jsonify({'success': False, 'error': 'Missing notification_id'}) | |
| def subscribe_notifications(): | |
| """Subscribe to push notifications""" | |
| data = request.get_json() or {} | |
| subscription = data.get('subscription') | |
| if subscription: | |
| success = notification_service.push.subscribe(subscription) | |
| return jsonify({'success': success}) | |
| return jsonify({'success': False, 'error': 'Missing subscription data'}) | |
| # ============================================================ | |
| # Cache Management Endpoints | |
| # ============================================================ | |
| def cache_stats(): | |
| """Get cache statistics""" | |
| return jsonify({ | |
| 'success': True, | |
| 'stats': get_cache_stats() | |
| }) | |
| def clear_cache(): | |
| """Clear prediction cache""" | |
| cleared = prediction_cache.clear() | |
| return jsonify({ | |
| 'success': True, | |
| 'cleared': cleared | |
| }) | |
| def invalidate_cache(): | |
| """Invalidate specific cache entries""" | |
| data = request.get_json() or {} | |
| home = data.get('home') | |
| away = data.get('away') | |
| league = data.get('league') | |
| invalidate_prediction_cache(home, away, league) | |
| return jsonify({'success': True}) | |
| # ============================================================ | |
| # Advanced Statistics Endpoints | |
| # ============================================================ | |
| def accuracy_stats(): | |
| """Get detailed accuracy statistics""" | |
| try: | |
| from src.accuracy_monitor import get_accuracy_stats, get_recent_predictions | |
| stats = get_accuracy_stats() | |
| recent = get_recent_predictions(limit=20) | |
| return jsonify({ | |
| 'success': True, | |
| 'stats': stats, | |
| 'recent': recent | |
| }) | |
| except Exception as e: | |
| return jsonify({'success': False, 'error': str(e)}) | |
| def league_stats(): | |
| """Get per-league statistics""" | |
| try: | |
| from src.success_tracker import get_success_analytics | |
| analytics = get_success_analytics() | |
| return jsonify({ | |
| 'success': True, | |
| 'analytics': analytics | |
| }) | |
| except Exception as e: | |
| return jsonify({'success': False, 'error': str(e)}) | |
| def performance_stats(): | |
| """Get overall performance metrics""" | |
| try: | |
| from src.accuracy_monitor import get_accuracy_stats | |
| stats = get_accuracy_stats() | |
| cache = get_cache_stats() | |
| return jsonify({ | |
| 'success': True, | |
| 'accuracy': stats, | |
| 'cache_performance': cache, | |
| 'uptime': '99.9%', | |
| 'api_version': 'v4', | |
| 'timestamp': datetime.now().isoformat() | |
| }) | |
| except Exception as e: | |
| return jsonify({'success': False, 'error': str(e)}) | |
| # ============================================================ | |
| # Match Recommendations | |
| # ============================================================ | |
| def get_recommendations(): | |
| """Get personalized match recommendations""" | |
| user_id = request.args.get('user_id', 'default') | |
| strategy = request.args.get('strategy', 'balanced') | |
| limit = int(request.args.get('limit', 10)) | |
| try: | |
| from src.data.free_data_sources import UnifiedFreeDataProvider | |
| from src.enhanced_predictor_v2 import enhanced_predict | |
| provider = UnifiedFreeDataProvider() | |
| fixtures = provider.get_unified_fixtures('bundesliga') | |
| recommendations = [] | |
| for fixture in fixtures[:limit]: | |
| home = fixture.get('home_team', {}).get('name') or fixture.get('home_team') | |
| away = fixture.get('away_team', {}).get('name') or fixture.get('away_team') | |
| if home and away: | |
| try: | |
| pred = enhanced_predict(home, away, 'bundesliga') | |
| # Calculate recommendation score | |
| confidence = pred.get('confidence', 0.5) | |
| if strategy == 'safe': | |
| score = confidence * 100 | |
| elif strategy == 'value': | |
| edge = pred.get('edge', 0) | |
| score = edge * 10 + confidence * 50 | |
| else: # balanced | |
| score = confidence * 70 + 30 | |
| recommendations.append({ | |
| 'match': f"{home} vs {away}", | |
| 'home': home, | |
| 'away': away, | |
| 'prediction': pred.get('predicted_outcome', 'N/A'), | |
| 'confidence': round(confidence * 100, 1), | |
| 'score': round(score, 1), | |
| 'reason': 'High confidence' if confidence > 0.7 else 'Good value' | |
| }) | |
| except: | |
| pass | |
| # Sort by score | |
| recommendations.sort(key=lambda x: x['score'], reverse=True) | |
| return jsonify({ | |
| 'success': True, | |
| 'strategy': strategy, | |
| 'recommendations': recommendations[:limit] | |
| }) | |
| except Exception as e: | |
| return jsonify({'success': False, 'error': str(e)}) | |
| def sure_wins_endpoint(): | |
| """Get sure win recommendations""" | |
| try: | |
| from src.confidence_sections import get_sure_wins | |
| sure_wins = get_sure_wins(min_confidence=0.91) | |
| return jsonify({ | |
| 'success': True, | |
| 'sure_wins': sure_wins, | |
| 'count': len(sure_wins) | |
| }) | |
| except Exception as e: | |
| return jsonify({'success': False, 'error': str(e)}) | |
| # ============================================================ | |
| # Health & API Info | |
| # ============================================================ | |
| def api_health(): | |
| """Enhanced API health check""" | |
| return jsonify({ | |
| 'success': True, | |
| 'status': 'healthy', | |
| 'version': 'v4', | |
| 'features': [ | |
| 'enhanced_predictions', | |
| 'caching', | |
| 'realtime_events', | |
| 'notifications', | |
| 'batch_predictions', | |
| 'recommendations', | |
| 'performance_stats' | |
| ], | |
| 'cache': get_cache_stats(), | |
| 'timestamp': datetime.now().isoformat() | |
| }) | |
| def api_info(): | |
| """Get API information""" | |
| return jsonify({ | |
| 'success': True, | |
| 'api': { | |
| 'name': 'FootyPredict Pro Enhanced API', | |
| 'version': 'v4.0.0', | |
| 'base_url': '/api/v4', | |
| 'endpoints': { | |
| 'predictions': '/predict/enhanced', | |
| 'batch': '/predict/batch', | |
| 'realtime': '/realtime/stream', | |
| 'notifications': '/notifications', | |
| 'stats': '/stats/performance', | |
| 'recommendations': '/recommendations' | |
| } | |
| }, | |
| 'rate_limits': { | |
| 'predictions': '100/minute', | |
| 'batch': '10/minute', | |
| 'general': '1000/hour' | |
| } | |
| }) | |
| def register_enhanced_api(app): | |
| """Register the enhanced API blueprint""" | |
| app.register_blueprint(enhanced_api) | |
| print("✅ Enhanced API v4 registered at /api/v4") | |