-
Notifications
You must be signed in to change notification settings - Fork 0
/
action.go
76 lines (70 loc) · 1.75 KB
/
action.go
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
package main
import (
"encoding/json"
"errors"
"log"
"math/rand"
"time"
)
// Duration is a time.Duration that can be unmarshalled to JSON.
type Duration struct {
time.Duration
}
func (d *Duration) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch value := v.(type) {
case float64:
d.Duration = time.Duration(value)
return nil
case string:
var err error
d.Duration, err = time.ParseDuration(value)
if err != nil {
return err
}
return nil
}
return errors.New("invalid duration")
}
type Action struct {
Schema string // Schema is the targeted gsettings schema.
Key string // Key is the key modified.
Every Duration // Every is the period at which the key is updated.
Random bool // Random indicates wether the next is randomly chosen.
Values []string // Values is the set of values from which next value if chosen.
rng *rand.Rand // rng will be lazily created if Random is true.
}
// perform performs the action.
func (a *Action) perform() error {
v := a.nextValue()
return gset(a.Schema, a.Key, v)
}
// nextValue returns the value to which we should set the key corresponding to current
// action.
func (a *Action) nextValue() string {
var nexti int
if a.Random {
if a.rng == nil {
// lazily create the random number generator
seed := time.Now().UnixNano()
a.rng = rand.New(rand.NewSource(seed))
}
nexti = a.rng.Intn(len(a.Values))
} else {
cur, err := gget(a.Schema, a.Key)
if err != nil {
log.Printf("can't get value (schema=%v, key=%v): %v", a.Schema, a.Key, err)
} else {
for i := range a.Values {
if a.Values[i] == cur {
nexti = (i + 1) % len(a.Values)
break
}
}
}
}
return a.Values[nexti]
}