package main import ( "math/rand" "sync" "time" ) var ( searchEngineLock sync.Mutex ) // SearchEngine struct now includes metrics for calculating reputation. type SearchEngine struct { Name string Func func(string, string, string, int) ([]SearchResult, time.Duration, error) Weight int TotalRequests int TotalTime time.Duration SuccessfulSearches int FailedSearches int } // init function seeds the random number generator. func init() { rand.Seed(time.Now().UnixNano()) } // Selects a search engine based on weighted random selection with dynamic weighting. func selectSearchEngine(engines []SearchEngine) SearchEngine { searchEngineLock.Lock() defer searchEngineLock.Unlock() // Recalculate weights based on average response time and success rate. for i := range engines { engines[i].Weight = calculateReputation(engines[i]) } totalWeight := 0 for _, engine := range engines { totalWeight += engine.Weight } randValue := rand.Intn(totalWeight) for _, engine := range engines { if randValue < engine.Weight { return engine } randValue -= engine.Weight } return engines[0] // fallback to the first engine } // Updates the engine's performance metrics. func updateEngineMetrics(engine *SearchEngine, responseTime time.Duration, success bool) { searchEngineLock.Lock() defer searchEngineLock.Unlock() engine.TotalRequests++ engine.TotalTime += responseTime if success { engine.SuccessfulSearches++ } else { engine.FailedSearches++ } engine.Weight = calculateReputation(*engine) } // Calculates the reputation of the search engine based on average response time and success rate. func calculateReputation(engine SearchEngine) int { const referenceTime = time.Second // 1 second reference time in nanoseconds (1000 ms) if engine.TotalRequests == 0 { return 10 // Default weight for new engines } // Calculate average response time in seconds. avgResponseTime := engine.TotalTime.Seconds() / float64(engine.TotalRequests) // Calculate success rate. successRate := float64(engine.SuccessfulSearches) / float64(engine.TotalRequests) // Combine response time and success rate into a single reputation score. // The formula can be adjusted to weigh response time and success rate differently. reputation := (referenceTime.Seconds() / avgResponseTime) * successRate // Scale reputation for better interpretability (e.g., multiply by 10) return int(reputation * 10) }