-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlocations_avg.go
114 lines (91 loc) · 2.58 KB
/
locations_avg.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
110
111
112
113
114
package main
import (
"github.com/valyala/fasthttp"
"fmt"
//"log"
)
type locationsAvg struct {
// sort key = Visit
// key
Visited_at int // visit
Age int // user
Gender rune // user
// data
Mark int // visit
}
type LocationsAvgNode struct {
key int
val *locationsAvg
nextNode *LocationsAvgNode
}
type LocationsAvgIndex struct {
head *LocationsAvgNode
}
func NewLocationsAvgIndex() LocationsAvgIndex {
return LocationsAvgIndex{head: &LocationsAvgNode{key: 0, val: nil, nextNode: nil}}
}
func (b LocationsAvgIndex) Insert(key int, value * locationsAvg) {
currentNode := b.head
var previousNode *LocationsAvgNode
newNode := &LocationsAvgNode{key: key, val: value, nextNode: nil}
for {
if currentNode.key > key {
newNode.nextNode = previousNode.nextNode
previousNode.nextNode = newNode
return
}
if currentNode.nextNode == nil {
currentNode.nextNode = newNode
return
}
previousNode = currentNode
currentNode = currentNode.nextNode
}
}
func (b LocationsAvgIndex) Remove(key int) (*locationsAvg) {
currentNode := b.head
var previousNode *LocationsAvgNode
for {
if currentNode.key == key {
previousNode.nextNode = currentNode.nextNode
return currentNode.val
}
if currentNode.nextNode == nil {
return nil
}
previousNode = currentNode
currentNode = currentNode.nextNode
}
}
func (b LocationsAvgIndex) CalcAvg(ctx *fasthttp.RequestCtx, skipGender bool, fromDate int, toDate int, fromAge int, toAge int, gender rune) {
if b.head.nextNode == nil { // no marks of this location
ctx.Write([]byte("{\"avg\":0.0}"))
return
}
currentNode := b.head.nextNode
sum := 0
cnt := 0
for {
val := currentNode.val
matched :=
(val.Visited_at > fromDate) &&
(val.Visited_at < toDate) &&
(val.Age >= fromAge) &&
(val.Age < toAge) &&
(skipGender || gender == val.Gender)
if matched {
//log.Println("matched", val.Visited_at, val.Birth_date, val.Gender, val.Mark)
sum += val.Mark
cnt++
}
if currentNode.nextNode == nil {
break
}
currentNode = currentNode.nextNode
}
if cnt == 0 {
ctx.Write([]byte("{\"avg\":0.0}"))
return
}
fmt.Fprintf(ctx, "{\"avg\":%.6g}", float64(sum) / float64(cnt) + 1e-10)
}