UNPKG

advanced-games-library

Version:

Advanced Gaming Library for React Native - Four Complete Games with iOS Compatibility Fixes

971 lines (838 loc) 27 kB
/** * Smart Network Adaptation System - מערכת התאמה חכמה לעומס רשת * מנטרת את מצב הרשת ומתאימה את איכות המשחק בהתאם */ export interface NetworkMetrics { latency: number; // ms bandwidth: number; // Mbps packetLoss: number; // percentage 0-100 jitter: number; // ms connectionType: 'wifi' | 'cellular' | 'ethernet' | 'unknown'; signalStrength: number; // 0-100 isOnline: boolean; timestamp: number; } export interface AdaptationProfile { id: string; name: string; minLatency: number; maxLatency: number; minBandwidth: number; maxPacketLoss: number; gameSettings: GameQualitySettings; uiSettings: UIAdaptationSettings; syncSettings: SyncAdaptationSettings; } export interface GameQualitySettings { updateRate: number; // Hz compressionLevel: number; // 0-100 maxParticipants: number; enablePrediction: boolean; bufferSize: number; // ms priorityMode: 'performance' | 'quality' | 'balanced'; fallbackToOffline: boolean; } export interface UIAdaptationSettings { animationQuality: 'high' | 'medium' | 'low' | 'disabled'; effectsEnabled: boolean; imageCompression: number; // 0-100 fontOptimization: boolean; lazyLoading: boolean; preloadingEnabled: boolean; } export interface SyncAdaptationSettings { syncInterval: number; // ms batchUpdates: boolean; deltaCompression: boolean; stateSize: 'full' | 'minimal' | 'compressed'; conflictResolution: 'server' | 'client' | 'consensus'; retryStrategy: RetryStrategy; } export interface RetryStrategy { maxRetries: number; baseDelay: number; // ms backoffMultiplier: number; maxDelay: number; // ms exponentialBackoff: boolean; } export interface NetworkEvent { type: 'connection_change' | 'quality_change' | 'adaptation_triggered' | 'error'; timestamp: number; metrics?: NetworkMetrics; adaptationApplied?: string; details?: any; } export interface PredictiveModel { patterns: Array<{ timeRange: { start: number; end: number }; expectedMetrics: NetworkMetrics; confidence: number; }>; learningData: Array<{ timestamp: number; metrics: NetworkMetrics; context: any; }>; accuracy: number; } class SmartNetworkAdaptationSystem { private currentMetrics: NetworkMetrics; private metricsHistory: NetworkMetrics[] = []; private adaptationProfiles: Map<string, AdaptationProfile> = new Map(); private activeProfile: AdaptationProfile | null = null; private eventHistory: NetworkEvent[] = []; private predictiveModel: PredictiveModel; private monitoringInterval?: NodeJS.Timeout; private adaptationCallbacks: Map<string, (profile: AdaptationProfile) => void> = new Map(); private isMonitoring = false; private adaptationThreshold = 0.3; // Sensitivity for changes constructor() { this.currentMetrics = { latency: 0, bandwidth: 0, packetLoss: 0, jitter: 0, connectionType: 'unknown', signalStrength: 0, isOnline: true, timestamp: Date.now() }; this.predictiveModel = { patterns: [], learningData: [], accuracy: 0 }; this.initializeAdaptationProfiles(); this.setupNetworkMonitoring(); console.log('🌐 Smart Network Adaptation System initialized'); } /** * אתחול פרופילי התאמה */ private initializeAdaptationProfiles(): void { // High Quality Profile - לרשת מהירה ויציבה const highQuality: AdaptationProfile = { id: 'high_quality', name: 'High Quality', minLatency: 0, maxLatency: 50, minBandwidth: 10, maxPacketLoss: 1, gameSettings: { updateRate: 60, compressionLevel: 10, maxParticipants: 8, enablePrediction: true, bufferSize: 100, priorityMode: 'quality', fallbackToOffline: false }, uiSettings: { animationQuality: 'high', effectsEnabled: true, imageCompression: 10, fontOptimization: false, lazyLoading: false, preloadingEnabled: true }, syncSettings: { syncInterval: 16, // 60 FPS batchUpdates: false, deltaCompression: false, stateSize: 'full', conflictResolution: 'server', retryStrategy: { maxRetries: 5, baseDelay: 100, backoffMultiplier: 1.5, maxDelay: 2000, exponentialBackoff: true } } }; // Medium Quality Profile - לרשת בינונית const mediumQuality: AdaptationProfile = { id: 'medium_quality', name: 'Medium Quality', minLatency: 50, maxLatency: 150, minBandwidth: 2, maxPacketLoss: 5, gameSettings: { updateRate: 30, compressionLevel: 30, maxParticipants: 6, enablePrediction: true, bufferSize: 200, priorityMode: 'balanced', fallbackToOffline: false }, uiSettings: { animationQuality: 'medium', effectsEnabled: true, imageCompression: 30, fontOptimization: true, lazyLoading: true, preloadingEnabled: true }, syncSettings: { syncInterval: 33, // 30 FPS batchUpdates: true, deltaCompression: true, stateSize: 'compressed', conflictResolution: 'server', retryStrategy: { maxRetries: 3, baseDelay: 200, backoffMultiplier: 2, maxDelay: 3000, exponentialBackoff: true } } }; // Low Quality Profile - לרשת איטית const lowQuality: AdaptationProfile = { id: 'low_quality', name: 'Low Quality', minLatency: 150, maxLatency: 500, minBandwidth: 0.5, maxPacketLoss: 15, gameSettings: { updateRate: 15, compressionLevel: 60, maxParticipants: 4, enablePrediction: true, bufferSize: 500, priorityMode: 'performance', fallbackToOffline: false }, uiSettings: { animationQuality: 'low', effectsEnabled: false, imageCompression: 60, fontOptimization: true, lazyLoading: true, preloadingEnabled: false }, syncSettings: { syncInterval: 66, // 15 FPS batchUpdates: true, deltaCompression: true, stateSize: 'minimal', conflictResolution: 'client', retryStrategy: { maxRetries: 2, baseDelay: 500, backoffMultiplier: 2.5, maxDelay: 5000, exponentialBackoff: true } } }; // Offline Profile - למצב לא מקוון const offline: AdaptationProfile = { id: 'offline', name: 'Offline Mode', minLatency: 500, maxLatency: Infinity, minBandwidth: 0, maxPacketLoss: 100, gameSettings: { updateRate: 60, compressionLevel: 0, maxParticipants: 1, enablePrediction: false, bufferSize: 0, priorityMode: 'performance', fallbackToOffline: true }, uiSettings: { animationQuality: 'high', effectsEnabled: true, imageCompression: 0, fontOptimization: false, lazyLoading: false, preloadingEnabled: false }, syncSettings: { syncInterval: 0, batchUpdates: false, deltaCompression: false, stateSize: 'full', conflictResolution: 'client', retryStrategy: { maxRetries: 0, baseDelay: 0, backoffMultiplier: 1, maxDelay: 0, exponentialBackoff: false } } }; this.adaptationProfiles.set('high_quality', highQuality); this.adaptationProfiles.set('medium_quality', mediumQuality); this.adaptationProfiles.set('low_quality', lowQuality); this.adaptationProfiles.set('offline', offline); // Set default profile this.activeProfile = mediumQuality; } /** * הגדרת ניטור רשת */ private setupNetworkMonitoring(): void { if (typeof window !== 'undefined') { // Monitor online/offline status window.addEventListener('online', () => { this.handleConnectionChange(true); }); window.addEventListener('offline', () => { this.handleConnectionChange(false); }); // Monitor connection type changes if ('connection' in navigator) { const connection = (navigator as any).connection; connection.addEventListener('change', () => { this.updateConnectionInfo(); }); } } this.startContinuousMonitoring(); } /** * התחלת ניטור רציף */ startContinuousMonitoring(): void { if (this.isMonitoring) return; this.isMonitoring = true; this.monitoringInterval = setInterval(() => { this.measureNetworkMetrics(); }, 2000); // Measure every 2 seconds console.log('📊 Network monitoring started'); } /** * עצירת ניטור */ stopMonitoring(): void { if (this.monitoringInterval) { clearInterval(this.monitoringInterval); this.monitoringInterval = undefined; } this.isMonitoring = false; console.log('📊 Network monitoring stopped'); } /** * מדידת מדדי רשת */ private async measureNetworkMetrics(): Promise<void> { try { const startTime = performance.now(); // Measure latency with a lightweight request const latency = await this.measureLatency(); // Get connection info const connectionInfo = this.getConnectionInfo(); // Estimate bandwidth (simplified) const bandwidth = await this.estimateBandwidth(); // Calculate jitter from latency history const jitter = this.calculateJitter(); const metrics: NetworkMetrics = { latency, bandwidth, packetLoss: 0, // Would need more complex measurement jitter, connectionType: connectionInfo.type, signalStrength: connectionInfo.strength, isOnline: navigator.onLine, timestamp: Date.now() }; this.updateMetrics(metrics); } catch (error) { console.warn('Network measurement failed:', error); // Use fallback metrics const fallbackMetrics: NetworkMetrics = { ...this.currentMetrics, isOnline: navigator.onLine, timestamp: Date.now() }; this.updateMetrics(fallbackMetrics); } } /** * מדידת latency */ private async measureLatency(): Promise<number> { const startTime = performance.now(); try { // Use a lightweight endpoint or create a data URL const testUrl = 'data:text/plain,ping'; await fetch(testUrl, { method: 'HEAD', cache: 'no-store' }); const endTime = performance.now(); return endTime - startTime; } catch (error) { // Fallback to previous latency or default return this.currentMetrics.latency || 100; } } /** * הערכת bandwidth */ private async estimateBandwidth(): Promise<number> { if ('connection' in navigator) { const connection = (navigator as any).connection; if (connection.downlink) { return connection.downlink; } } // Fallback estimation based on connection type const connectionInfo = this.getConnectionInfo(); switch (connectionInfo.type) { case 'wifi': return 10; // Assume decent WiFi case 'cellular': return 2; // Conservative cellular estimate case 'ethernet': return 100; // Assume fast ethernet default: return 1; // Conservative default } } /** * חישוב jitter */ private calculateJitter(): number { if (this.metricsHistory.length < 3) return 0; const recentLatencies = this.metricsHistory .slice(-5) .map(m => m.latency); const diffs = []; for (let i = 1; i < recentLatencies.length; i++) { diffs.push(Math.abs(recentLatencies[i] - recentLatencies[i - 1])); } return diffs.reduce((sum, diff) => sum + diff, 0) / diffs.length; } /** * קבלת מידע על החיבור */ private getConnectionInfo(): { type: NetworkMetrics['connectionType']; strength: number } { if ('connection' in navigator) { const connection = (navigator as any).connection; let type: NetworkMetrics['connectionType'] = 'unknown'; if (connection.type) { switch (connection.type) { case 'wifi': case 'ethernet': type = connection.type; break; case 'cellular': type = 'cellular'; break; default: type = 'unknown'; } } // Estimate signal strength based on effective type let strength = 50; // Default if (connection.effectiveType) { switch (connection.effectiveType) { case '4g': strength = 90; break; case '3g': strength = 60; break; case '2g': strength = 30; break; case 'slow-2g': strength = 10; break; } } return { type, strength }; } return { type: 'unknown', strength: 50 }; } /** * עדכון מדדים */ private updateMetrics(metrics: NetworkMetrics): void { this.currentMetrics = metrics; this.metricsHistory.push(metrics); // Keep only last 50 measurements if (this.metricsHistory.length > 50) { this.metricsHistory.shift(); } // Add to learning data this.predictiveModel.learningData.push({ timestamp: metrics.timestamp, metrics, context: this.getCurrentContext() }); // Check if adaptation is needed this.checkAdaptationNeeded(metrics); // Update predictive model this.updatePredictiveModel(); } /** * בדיקה אם נדרשת התאמה */ private checkAdaptationNeeded(metrics: NetworkMetrics): void { if (!this.activeProfile) return; const currentProfile = this.activeProfile; const bestProfile = this.findBestProfile(metrics); if (bestProfile.id !== currentProfile.id) { const changeSignificance = this.calculateChangeSignificance(metrics, currentProfile); if (changeSignificance > this.adaptationThreshold) { this.triggerAdaptation(bestProfile, metrics, changeSignificance); } } } /** * חיפוש הפרופיל הטוב ביותר */ private findBestProfile(metrics: NetworkMetrics): AdaptationProfile { if (!metrics.isOnline) { return this.adaptationProfiles.get('offline')!; } // Score each profile based on how well it matches current conditions let bestProfile = this.adaptationProfiles.get('medium_quality')!; let bestScore = -Infinity; for (const profile of this.adaptationProfiles.values()) { if (profile.id === 'offline') continue; // Skip offline when online const score = this.scoreProfile(profile, metrics); if (score > bestScore) { bestScore = score; bestProfile = profile; } } return bestProfile; } /** * ניקוד פרופיל לפי מדדים נוכחיים */ private scoreProfile(profile: AdaptationProfile, metrics: NetworkMetrics): number { let score = 0; // Latency score if (metrics.latency <= profile.maxLatency) { score += 100 - (metrics.latency / profile.maxLatency) * 50; } else { score -= 50; // Penalty for exceeding latency } // Bandwidth score if (metrics.bandwidth >= profile.minBandwidth) { score += 50; } else { score -= (profile.minBandwidth - metrics.bandwidth) * 10; } // Packet loss score if (metrics.packetLoss <= profile.maxPacketLoss) { score += 30; } else { score -= (metrics.packetLoss - profile.maxPacketLoss) * 5; } // Connection type bonus switch (metrics.connectionType) { case 'ethernet': score += 20; break; case 'wifi': score += 15; break; case 'cellular': score += 5; break; default: score += 0; } return score; } /** * חישוב משמעות השינוי */ private calculateChangeSignificance(metrics: NetworkMetrics, currentProfile: AdaptationProfile): number { let significance = 0; // Latency change significance const latencyRatio = metrics.latency / Math.max(currentProfile.maxLatency, 1); if (latencyRatio > 1.5 || latencyRatio < 0.5) { significance += 0.4; } // Bandwidth change significance const bandwidthRatio = metrics.bandwidth / Math.max(currentProfile.minBandwidth, 0.1); if (bandwidthRatio < 0.5 || bandwidthRatio > 2) { significance += 0.3; } // Connection stability if (metrics.jitter > 50 || metrics.packetLoss > currentProfile.maxPacketLoss) { significance += 0.3; } return significance; } /** * הפעלת התאמה */ private triggerAdaptation(newProfile: AdaptationProfile, metrics: NetworkMetrics, significance: number): void { const previousProfile = this.activeProfile; this.activeProfile = newProfile; // Log the adaptation event const event: NetworkEvent = { type: 'adaptation_triggered', timestamp: Date.now(), metrics, adaptationApplied: newProfile.id, details: { previousProfile: previousProfile?.id, significance, reason: this.getAdaptationReason(metrics, newProfile) } }; this.eventHistory.push(event); // Notify callbacks this.adaptationCallbacks.forEach(callback => { try { callback(newProfile); } catch (error) { console.error('Adaptation callback error:', error); } }); console.log(`🔄 Network adaptation: ${previousProfile?.name} → ${newProfile.name}`); } /** * קבלת סיבת ההתאמה */ private getAdaptationReason(metrics: NetworkMetrics, profile: AdaptationProfile): string { const reasons = []; if (!metrics.isOnline) { reasons.push('offline'); } if (metrics.latency > 300) { reasons.push('high_latency'); } if (metrics.bandwidth < 1) { reasons.push('low_bandwidth'); } if (metrics.packetLoss > 10) { reasons.push('high_packet_loss'); } if (metrics.jitter > 100) { reasons.push('unstable_connection'); } return reasons.join(', ') || 'optimization'; } /** * טיפול בשינוי חיבור */ private handleConnectionChange(isOnline: boolean): void { const event: NetworkEvent = { type: 'connection_change', timestamp: Date.now(), details: { isOnline } }; this.eventHistory.push(event); if (!isOnline) { // Switch to offline mode immediately const offlineProfile = this.adaptationProfiles.get('offline')!; this.triggerAdaptation(offlineProfile, { ...this.currentMetrics, isOnline: false }, 1.0); } else { // Re-measure network when coming back online setTimeout(() => { this.measureNetworkMetrics(); }, 1000); } } /** * עדכון מידע חיבור */ private updateConnectionInfo(): void { const connectionInfo = this.getConnectionInfo(); this.currentMetrics = { ...this.currentMetrics, connectionType: connectionInfo.type, signalStrength: connectionInfo.strength, timestamp: Date.now() }; } /** * קבלת קונטקסט נוכחי */ private getCurrentContext(): any { return { timeOfDay: new Date().getHours(), dayOfWeek: new Date().getDay(), userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'unknown', screenSize: typeof window !== 'undefined' ? { width: window.screen.width, height: window.screen.height } : { width: 0, height: 0 } }; } /** * עדכון מודל חיזוי */ private updatePredictiveModel(): void { // Simplified predictive model update if (this.predictiveModel.learningData.length < 10) return; // Analyze patterns in the last 50 data points const recentData = this.predictiveModel.learningData.slice(-50); // Group by time of day const hourlyPatterns: { [hour: number]: NetworkMetrics[] } = {}; recentData.forEach(data => { const hour = new Date(data.timestamp).getHours(); if (!hourlyPatterns[hour]) { hourlyPatterns[hour] = []; } hourlyPatterns[hour].push(data.metrics); }); // Create patterns this.predictiveModel.patterns = []; Object.entries(hourlyPatterns).forEach(([hour, metrics]) => { if (metrics.length >= 3) { const avgMetrics = this.calculateAverageMetrics(metrics); this.predictiveModel.patterns.push({ timeRange: { start: parseInt(hour), end: (parseInt(hour) + 1) % 24 }, expectedMetrics: avgMetrics, confidence: Math.min(0.9, metrics.length / 10) }); } }); // Update accuracy based on recent predictions vs actual this.updateModelAccuracy(); } /** * חישוב ממוצע מדדים */ private calculateAverageMetrics(metrics: NetworkMetrics[]): NetworkMetrics { const avg = metrics.reduce((acc, m) => ({ latency: acc.latency + m.latency, bandwidth: acc.bandwidth + m.bandwidth, packetLoss: acc.packetLoss + m.packetLoss, jitter: acc.jitter + m.jitter, signalStrength: acc.signalStrength + m.signalStrength }), { latency: 0, bandwidth: 0, packetLoss: 0, jitter: 0, signalStrength: 0 }); const count = metrics.length; return { latency: avg.latency / count, bandwidth: avg.bandwidth / count, packetLoss: avg.packetLoss / count, jitter: avg.jitter / count, connectionType: metrics[0].connectionType, signalStrength: avg.signalStrength / count, isOnline: true, timestamp: Date.now() }; } /** * עדכון דיוק המודל */ private updateModelAccuracy(): void { // Simplified accuracy calculation // In practice, this would compare predictions with actual outcomes this.predictiveModel.accuracy = Math.min(0.95, 0.5 + (this.predictiveModel.learningData.length / 1000) * 0.4 ); } /** * רישום callback להתאמה */ onAdaptation(id: string, callback: (profile: AdaptationProfile) => void): void { this.adaptationCallbacks.set(id, callback); } /** * הסרת callback */ offAdaptation(id: string): void { this.adaptationCallbacks.delete(id); } /** * קבלת פרופיל פעיל */ getActiveProfile(): AdaptationProfile | null { return this.activeProfile; } /** * קבלת מדדי רשת נוכחיים */ getCurrentMetrics(): NetworkMetrics { return { ...this.currentMetrics }; } /** * קבלת היסטוריית מדדים */ getMetricsHistory(limit?: number): NetworkMetrics[] { const history = [...this.metricsHistory]; return limit ? history.slice(-limit) : history; } /** * קבלת חיזוי למדדי רשת */ getPrediction(timeAhead: number = 3600000): NetworkMetrics | null { // 1 hour ahead const currentHour = new Date().getHours(); const targetTime = new Date(Date.now() + timeAhead); const targetHour = targetTime.getHours(); const pattern = this.predictiveModel.patterns.find(p => p.timeRange.start <= targetHour && targetHour < p.timeRange.end ); return pattern ? pattern.expectedMetrics : null; } /** * הגדרת רגישות התאמה */ setAdaptationThreshold(threshold: number): void { this.adaptationThreshold = Math.max(0.1, Math.min(1.0, threshold)); } /** * כפיית פרופיל ספציפי */ forceProfile(profileId: string): boolean { const profile = this.adaptationProfiles.get(profileId); if (!profile) return false; this.activeProfile = profile; // Notify callbacks this.adaptationCallbacks.forEach(callback => { try { callback(profile); } catch (error) { console.error('Forced adaptation callback error:', error); } }); console.log(`🔧 Forced network profile: ${profile.name}`); return true; } /** * קבלת נתונים סטטיסטיים */ getNetworkStatistics(): { averageLatency: number; averageBandwidth: number; connectionStability: number; adaptationCount: number; mostUsedProfile: string; modelAccuracy: number; } { const recentMetrics = this.metricsHistory.slice(-20); const avgLatency = recentMetrics.length > 0 ? recentMetrics.reduce((sum, m) => sum + m.latency, 0) / recentMetrics.length : 0; const avgBandwidth = recentMetrics.length > 0 ? recentMetrics.reduce((sum, m) => sum + m.bandwidth, 0) / recentMetrics.length : 0; // Calculate stability as inverse of jitter variance const jitters = recentMetrics.map(m => m.jitter); const avgJitter = jitters.reduce((sum, j) => sum + j, 0) / Math.max(jitters.length, 1); const jitterVariance = jitters.reduce((sum, j) => sum + Math.pow(j - avgJitter, 2), 0) / Math.max(jitters.length, 1); const stability = Math.max(0, 1 - (jitterVariance / 1000)); // Normalize const adaptationEvents = this.eventHistory.filter(e => e.type === 'adaptation_triggered'); // Find most used profile const profileUsage: { [id: string]: number } = {}; adaptationEvents.forEach(event => { const profileId = event.adaptationApplied || 'unknown'; profileUsage[profileId] = (profileUsage[profileId] || 0) + 1; }); const mostUsedProfile = Object.entries(profileUsage) .sort(([,a], [,b]) => b - a)[0]?.[0] || 'medium_quality'; return { averageLatency: avgLatency, averageBandwidth: avgBandwidth, connectionStability: stability, adaptationCount: adaptationEvents.length, mostUsedProfile, modelAccuracy: this.predictiveModel.accuracy }; } /** * ניקוי משאבים */ dispose(): void { this.stopMonitoring(); if (typeof window !== 'undefined') { window.removeEventListener('online', (e: Event) => this.handleConnectionChange((e as any).isOnline)); window.removeEventListener('offline', (e: Event) => this.handleConnectionChange((e as any).isOnline)); } this.adaptationCallbacks.clear(); this.metricsHistory.length = 0; this.eventHistory.length = 0; this.predictiveModel.learningData.length = 0; console.log('🌐 Smart Network Adaptation System disposed'); } } export default SmartNetworkAdaptationSystem;