-
Notifications
You must be signed in to change notification settings - Fork 9
/
state.go
109 lines (91 loc) · 1.8 KB
/
state.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
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
package main
import (
"encoding/json"
"errors"
"fmt"
)
type SingleValue struct {
Value interface{} `json:"value"`
}
type Update struct {
value interface{} `json:"value"`
diff int64 `json:"diff"`
}
type State struct {
state map[string]int64
timestamp int64
valid bool
history []Update
}
func NewState(collectHistory bool) *State {
state := make(map[string]int64)
history := []Update{}
return &State{
state: state,
timestamp: 0,
valid: true,
history: history,
}
}
func (s *State) getState() []interface{} {
list := []interface{}{}
for key, value := range s.state {
clone := make(map[string]interface{})
err := json.Unmarshal([]byte(key), &clone)
if err != nil {
fmt.Println(err);
continue
}
for i := int64(0); i < value; i++ {
list = append(list, clone["value"])
}
}
return list
}
func (s *State) getHistory() []Update {
return s.history
}
func (s *State) validate(timestamp int64) error {
if !s.valid {
return errors.New("Invalid state.")
} else if timestamp < s.timestamp {
s.valid = false
return errors.New("Invalid timestamp.")
}
return nil
}
func (s *State) process(update Update) {
var sv = SingleValue { Value: update.value }
value, err := json.Marshal(sv)
// fmt.Println(sv, value);
if err != nil {
fmt.Println(err);
return
}
count, ok := s.state[string(value)]
if !ok {
count = 0
}
count += update.diff
if count <= 0 {
delete(s.state, string(value))
} else {
s.state[string(value)] = count
}
if s.history != nil {
s.history = append(s.history, update)
}
}
func (s *State) Update(updates []Update, timestamp int64) error {
if len(updates) > 0 {
err := s.validate(timestamp)
if err != nil {
return err
}
s.timestamp = timestamp
for _, update := range updates {
s.process(update)
}
}
return nil
}