Hunter0x7c7
2022-08-11 a82f9cb69f63aaeba40c024960deda7d75b9fece
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package router
 
import (
    "regexp"
    "strconv"
    "strings"
)
 
type weightScaler func(value, weight float64) float64
 
var numberFinder = regexp.MustCompile(`\d+(\.\d+)?`)
 
// NewWeightManager creates a new WeightManager with settings
func NewWeightManager(s []*StrategyWeight, defaultWeight float64, scaler weightScaler) *WeightManager {
    return &WeightManager{
        settings:      s,
        cache:         make(map[string]float64),
        scaler:        scaler,
        defaultWeight: defaultWeight,
    }
}
 
// WeightManager manages weights for specific settings
type WeightManager struct {
    settings      []*StrategyWeight
    cache         map[string]float64
    scaler        weightScaler
    defaultWeight float64
}
 
// Get gets the weight of specified tag
func (s *WeightManager) Get(tag string) float64 {
    weight, ok := s.cache[tag]
    if ok {
        return weight
    }
    weight = s.findValue(tag)
    s.cache[tag] = weight
    return weight
}
 
// Apply applies weight to the value
func (s *WeightManager) Apply(tag string, value float64) float64 {
    return s.scaler(value, s.Get(tag))
}
 
func (s *WeightManager) findValue(tag string) float64 {
    for _, w := range s.settings {
        matched := s.getMatch(tag, w.Match, w.Regexp)
        if matched == "" {
            continue
        }
        if w.Value > 0 {
            return float64(w.Value)
        }
        // auto weight from matched
        numStr := numberFinder.FindString(matched)
        if numStr == "" {
            return s.defaultWeight
        }
        weight, err := strconv.ParseFloat(numStr, 64)
        if err != nil {
            newError("unexpected error from ParseFloat: ", err).AtError().WriteToLog()
            return s.defaultWeight
        }
        return weight
    }
    return s.defaultWeight
}
 
func (s *WeightManager) getMatch(tag, find string, isRegexp bool) string {
    if !isRegexp {
        idx := strings.Index(tag, find)
        if idx < 0 {
            return ""
        }
        return find
    }
    r, err := regexp.Compile(find)
    if err != nil {
        newError("invalid regexp: ", find, "err: ", err).AtError().WriteToLog()
        return ""
    }
    return r.FindString(tag)
}