pkg.re/essentialkaos/ek.10@v12.41.0+incompatible/progress/pass_thru_calc.go (about)

     1  package progress
     2  
     3  // ////////////////////////////////////////////////////////////////////////////////// //
     4  //                                                                                    //
     5  //                         Copyright (c) 2022 ESSENTIAL KAOS                          //
     6  //      Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>     //
     7  //                                                                                    //
     8  // ////////////////////////////////////////////////////////////////////////////////// //
     9  
    10  import (
    11  	"math"
    12  	"time"
    13  )
    14  
    15  // ////////////////////////////////////////////////////////////////////////////////// //
    16  
    17  const _MAX_REMAINING = 5999 * time.Second
    18  
    19  // ////////////////////////////////////////////////////////////////////////////////// //
    20  
    21  // PassThruCalc is pass thru calculator struct
    22  type PassThruCalc struct {
    23  	total      float64
    24  	prev       float64
    25  	speed      float64
    26  	decay      float64
    27  	remaining  time.Duration
    28  	lastUpdate time.Time
    29  }
    30  
    31  // ////////////////////////////////////////////////////////////////////////////////// //
    32  
    33  // NewPassThruCalc creates new pass thru calculator
    34  func NewPassThruCalc(total int64, winSizeSec float64) *PassThruCalc {
    35  	return &PassThruCalc{
    36  		total: float64(total),
    37  		decay: 2 / (winSizeSec + 1),
    38  	}
    39  }
    40  
    41  // ////////////////////////////////////////////////////////////////////////////////// //
    42  
    43  // Calculate calculates number of objects per seconds and remaining time
    44  func (p *PassThruCalc) Calculate(v int64) (float64, time.Duration) {
    45  	c := float64(v)
    46  	now := time.Now()
    47  
    48  	if !p.lastUpdate.IsZero() && now.Sub(p.lastUpdate) < time.Second/2 {
    49  		return p.speed, p.remaining
    50  	}
    51  
    52  	speed := math.Abs(c-p.prev) / time.Since(p.lastUpdate).Seconds()
    53  
    54  	p.speed = (speed * p.decay) + (p.speed * (1.0 - p.decay))
    55  
    56  	if p.prev != 0 && p.speed > 0 {
    57  		p.remaining = time.Duration((p.total-c)/p.speed) * time.Second
    58  	}
    59  
    60  	if p.remaining > _MAX_REMAINING {
    61  		p.remaining = _MAX_REMAINING
    62  	}
    63  
    64  	p.prev = c
    65  	p.lastUpdate = now
    66  
    67  	return p.speed, p.remaining
    68  }
    69  
    70  // SetTotal sets total number of objects
    71  func (p *PassThruCalc) SetTotal(v int64) {
    72  	p.total = float64(v)
    73  }