package services import ( "context" "sync" "time" "go.uber.org/zap" ) // BandwidthDetectionService gère la détection de bande passante réseau // T0347: Create Network Bandwidth Detection Service type BandwidthDetectionService struct { samples []int64 maxSamples int mutex sync.RWMutex logger *zap.Logger } // NewBandwidthDetectionService crée un nouveau service de détection de bande passante func NewBandwidthDetectionService(logger *zap.Logger) *BandwidthDetectionService { if logger == nil { logger = zap.NewNop() } return &BandwidthDetectionService{ samples: make([]int64, 0, 10), maxSamples: 10, logger: logger, } } // MeasureBandwidth mesure la bande passante en bps (bits per second) // bytesTransferred: nombre d'octets transférés // duration: durée du transfert // Retourne la moyenne de bande passante en bps func (s *BandwidthDetectionService) MeasureBandwidth(ctx context.Context, bytesTransferred int64, duration time.Duration) int64 { if duration <= 0 { s.logger.Warn("Invalid duration for bandwidth measurement", zap.Duration("duration", duration)) return 0 } if bytesTransferred < 0 { s.logger.Warn("Invalid bytes transferred for bandwidth measurement", zap.Int64("bytes", bytesTransferred)) return 0 } // Calculer la bande passante en bps (bits per second) // bytesTransferred * 8 pour convertir en bits // duration.Seconds() pour obtenir la durée en secondes seconds := duration.Seconds() if seconds <= 0 { return 0 } // Utiliser float64 pour éviter les problèmes de précision avec les durées très courtes bandwidth := int64((float64(bytesTransferred) * 8.0) / seconds) s.mutex.Lock() defer s.mutex.Unlock() // Ajouter l'échantillon s.samples = append(s.samples, bandwidth) // Limiter le nombre d'échantillons if len(s.samples) > s.maxSamples { s.samples = s.samples[1:] } // Calculer et retourner la moyenne return s.calculateAverage() } // calculateAverage calcule la moyenne des échantillons de bande passante func (s *BandwidthDetectionService) calculateAverage() int64 { if len(s.samples) == 0 { return 0 } var sum int64 for _, sample := range s.samples { sum += sample } return sum / int64(len(s.samples)) } // GetAverageBandwidth retourne la moyenne actuelle de bande passante sans ajouter de nouvel échantillon func (s *BandwidthDetectionService) GetAverageBandwidth() int64 { s.mutex.RLock() defer s.mutex.RUnlock() return s.calculateAverage() } // RecommendBitrate recommande un bitrate optimal en kbps basé sur la bande passante disponible // bandwidth: bande passante en bps (bits per second) // Retourne le bitrate recommandé en kbps func (s *BandwidthDetectionService) RecommendBitrate(bandwidth int64) int { if bandwidth <= 0 { // Par défaut, retourner le bitrate le plus bas return 128 } // Réserver 20% de buffer pour éviter les problèmes de réseau available := float64(bandwidth) * 0.8 // Convertir en kbps pour la comparaison availableKbps := available / 1000.0 // Recommander le bitrate le plus élevé possible selon la bande passante disponible // Les bitrates standards sont: 128, 192, 320 kbps if availableKbps >= 320 { return 320 } else if availableKbps >= 192 { return 192 } else if availableKbps >= 128 { return 128 } // Si la bande passante est très faible, retourner quand même 128 kbps // (le client devra gérer la mise en buffer) return 128 } // ClearSamples efface tous les échantillons de bande passante func (s *BandwidthDetectionService) ClearSamples() { s.mutex.Lock() defer s.mutex.Unlock() s.samples = make([]int64, 0, s.maxSamples) } // GetSampleCount retourne le nombre d'échantillons actuels func (s *BandwidthDetectionService) GetSampleCount() int { s.mutex.RLock() defer s.mutex.RUnlock() return len(s.samples) }