github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/p2p/scoring/decay.go (about) 1 package scoring 2 3 import ( 4 "fmt" 5 "math" 6 "time" 7 ) 8 9 // GeometricDecay returns the decayed score based on the decay factor and the time since the last update. 10 // 11 // The decayed score is calculated as follows: 12 // penalty = score * decay^t where t is the time since the last update in seconds. 13 // Args: 14 // - score: the score to be decayed. 15 // - decay: the decay factor, it should be in the range of (0, 1]. 16 // - lastUpdated: the time when the penalty was last updated. 17 // Returns: 18 // - the decayed score. 19 // - an error if the decay factor is not in the range of (0, 1] or the decayed score is NaN. 20 // it also returns an error if the last updated time is in the future (to avoid overflow). 21 // The error is considered irrecoverable (unless the parameters can be adjusted). 22 func GeometricDecay(score float64, decay float64, lastUpdated time.Time) (float64, error) { 23 if decay <= 0 || decay > 1 { 24 return 0.0, fmt.Errorf("decay factor must be in the range (0, 1], got %f", decay) 25 } 26 27 now := time.Now() 28 if lastUpdated.After(now) { 29 return 0.0, fmt.Errorf("last updated time is in the future %v now: %v", lastUpdated, now) 30 } 31 32 t := time.Since(lastUpdated).Seconds() 33 decayFactor := math.Pow(decay, t) 34 35 if math.IsNaN(decayFactor) { 36 return 0.0, fmt.Errorf("decay factor is NaN for %f^%f", decay, t) 37 } 38 39 return score * decayFactor, nil 40 }