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  }