-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbakedata.go
More file actions
155 lines (142 loc) · 4.25 KB
/
bakedata.go
File metadata and controls
155 lines (142 loc) · 4.25 KB
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package main
import (
"log/slog"
"math/rand/v2"
"os"
"strconv"
"sync"
)
// CycBuffer is a cyclical shift register
type CycBuffer struct {
MU sync.Mutex
NType string // Numeric Type
MAlgo string // Metric Algorithm Name
Values []string // Slice of whatever we need for responses
MaxSize int // How big this buffer can be
Index int // We are at this index in the step buffer
}
// NewShiftCycBuffer creates a series of values based on ENV VAR configurations.
// These number generators are multiplicative and random
// to provide some ambiguity within the number series
// so it isn't always a set of evenly spaced values.
func NewShiftCycBuffer(maxSize, limit, tail int, mod float64, f, a string) *CycBuffer {
values := make([]string, 0, maxSize)
saltF := mod * float64(rand.Int32N(int32(limit))+1) // Seed using *_MOD and *_LIMIT (normalized to 1)
saltM := rand.Float64() + 0.1 // SaltMultiplier, internally randomized (normalized to 0.1)
saltF *= saltM // Float salt
saltI := int(mod) * int(saltF) // Int salt
if saltI == 0 {
saltI = 1
}
switch a {
case "up":
switch f {
case "exp":
for i := 0; i < maxSize; i++ {
values = append(values, strconv.FormatFloat(saltF*float64(limit-(limit-i))*mod, 'e', tail, 64))
}
case "float":
for i := 0; i < maxSize; i++ {
values = append(values, strconv.FormatFloat(saltF*float64(limit-(limit-i))*mod, 'f', tail, 64))
}
case "int":
for i := 0; i < maxSize; i++ {
values = append(values, strconv.Itoa(saltI*(limit-(limit-i))))
}
}
case "down":
switch f {
case "exp":
for i := 0; i < maxSize; i++ {
values = append(values, strconv.FormatFloat(saltF*float64(limit-i)*mod, 'e', tail, 64))
}
case "float":
for i := 0; i < maxSize; i++ {
values = append(values, strconv.FormatFloat(saltF*float64(limit-i)*mod, 'f', tail, 64))
}
case "int":
for i := 0; i < maxSize; i++ {
values = append(values, strconv.Itoa(saltI*(limit-i)))
}
}
case "random":
switch f {
case "exp":
for i := 0; i < maxSize; i++ {
values = append(values, strconv.FormatFloat(saltF, 'e', tail, 64))
}
case "float":
for i := 0; i < maxSize; i++ {
values = append(values, strconv.FormatFloat(saltF, 'f', tail, 64))
}
case "int":
for i := 0; i < maxSize; i++ {
values = append(values, strconv.Itoa(int(saltF)))
}
}
}
return &CycBuffer{
NType: f,
MAlgo: a,
Values: values,
MaxSize: maxSize,
Index: 0,
}
}
// Shift returns the next value in the buffer
// First increase the Index, wrapping when reaching the full size
// then return the value at that spot
func (cb *CycBuffer) Shift() string {
cb.MU.Lock()
defer cb.MU.Unlock()
cb.Index = (cb.Index + 1) % len(cb.Values)
return cb.Values[cb.Index]
}
// RandBuffers is the engine for building random data buffers.
// Each of these can be queried by the endpoint to get well-defined random numbers.
// It grabs new ones every time to create better randomness.
func (eph *EPHandle) RandBuffers() {
for _, mt := range eph.MTypes {
mt.MU.Lock()
buffer := getRandomizedBuffer(mt.Name, "random")
buffer.MU.Lock()
eph.MTypes[mt.Name].RandomBuffer = buffer.Values
buffer.MU.Unlock()
mt.MU.Unlock()
}
}
// ShiftBuffers is the engine for advancing data (mtypes)
// to appear like it moves in a specific algorithmic shape (algos).
func (eph *EPHandle) ShiftBuffers() {
// Run a Shift() on all CyclicBuffers
// This advances buffer.Index along the algorithm
for _, mt := range eph.MTypes {
for _, buff := range mt.ShiftRegisters {
buff.Shift()
}
}
}
// FillEnvVar returns the value of a runtime Environment Variable
func FillEnvVar(ev string) string {
// If the EnvVar doesn't exist return a default string
value := os.Getenv(ev)
if value == "" {
value = "ENOENT"
}
return value
}
// FillEnvVarInt returns a runtime Environment Variable as an int
// It takes the name of the ENV VAR and a default
// For non-default and string ENV VARs, use FillEnvVar()
func FillEnvVarInt(ev string, def int) int {
fetch := os.Getenv(ev)
if fetch == "" {
return def
}
value, err := strconv.Atoi(fetch)
if err != nil || value < 0 {
slog.Warn("Invalid environment variable " + ev)
return def
}
return value
}