/
rank_pool.go
180 lines (168 loc) · 3.82 KB
/
rank_pool.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
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package utils
import (
"github.com/helloh2o/lucky/log"
"time"
)
// RankPool 排序池
type RkPool struct {
name string
// 上次排序的结果
rkSorted []RankItem
// 需要排序的数据
rkMap map[interface{}]RankItem
// 排序周期
rkCycle *time.Ticker
// idle 空闲
idle chan struct{}
// 最大排序条数
maxSize int
// 调用者自己规则排序
selfSort func([]RankItem) []RankItem
}
// RankItem 排序项目
type RankItem struct {
// 键
Key interface{}
// 原始值
Data interface{}
// 排名值
RankVal int64
}
// NewRKPool 创建一个新的排序池
func NewRKPool(name string, size int, rankCycle time.Duration, selfSort func([]RankItem) []RankItem) *RkPool {
up := RkPool{
name: name,
rkCycle: time.NewTicker(rankCycle),
idle: make(chan struct{}, 1),
maxSize: size,
selfSort: selfSort,
rkMap: make(map[interface{}]RankItem),
}
return &up
}
// Queue 排队到池
func (rp *RkPool) Queue(item RankItem) {
rp.idle <- struct{}{}
defer func() {
<-rp.idle
log.Release("rank_pool data size %d", len(rp.rkMap))
}()
_, ok := rp.rkMap[item.Key]
if ok {
// 如果已经在队列中,则替换
rp.rkMap[item.Key] = item
} else {
if len(rp.rkMap) >= rp.maxSize {
log.Release("rk queue %d is full.", rp.maxSize)
} else {
rp.rkMap[item.Key] = item
log.Release("rank_pool add new item: %s, val: %d", item.Key, item.RankVal)
}
}
}
// IsInPool 是否在池子中
func (rp *RkPool) IsInPool(item RankItem) bool {
rp.idle <- struct{}{}
defer func() {
<-rp.idle
}()
_, ok := rp.rkMap[item.Key]
return ok
}
// GetRankData 获取已排序数据
func (rp *RkPool) GetRankData(from, to int) (data []RankItem) {
rp.idle <- struct{}{}
defer func() {
<-rp.idle
}()
if from > to || from < 1 || len(rp.rkSorted) == 0 {
return
}
if from >= len(rp.rkSorted) {
from = len(rp.rkSorted)
}
if to >= len(rp.rkSorted) {
to = len(rp.rkSorted)
}
return rp.rkSorted[from-1 : to-1]
}
// GetNO1 获取第一个用户
func (rp *RkPool) GetNO1() *RankItem {
rp.idle <- struct{}{}
defer func() {
<-rp.idle
}()
if len(rp.rkSorted) > 0 {
return &rp.rkSorted[0]
}
return nil
}
// Remove from pool
func (rp *RkPool) Remove(key interface{}) {
rp.idle <- struct{}{}
defer func() {
<-rp.idle
}()
// 删除需要排序的数据
delete(rp.rkMap, key)
// 从已排序中删除
for index, item := range rp.rkSorted {
if item.Key == key {
rp.rkSorted = append(rp.rkSorted[:index], rp.rkSorted[index+1:]...)
}
}
}
// Serve 开启间隙自动排序
func (rp *RkPool) Serve() {
for {
<-rp.rkCycle.C
// do rank by rp val
go rp.Rank()
}
}
// Clean 清空排序池
func (rp *RkPool) Clean() {
rp.idle <- struct{}{}
defer func() {
<-rp.idle
}()
if len(rp.rkSorted) > 0 {
rp.rkSorted = rp.rkSorted[:0]
}
rp.rkMap = make(map[interface{}]RankItem)
}
// 进行排序
func (rp *RkPool) Rank() {
rp.idle <- struct{}{}
defer func() {
<-rp.idle
}()
var needSortItems []RankItem
for _, item := range rp.rkMap {
if val, has := rp.rkMap[item.Key]; has {
needSortItems = append(needSortItems, val)
}
}
// 按照item rank Val 排序
for i := 0; i < len(needSortItems)-1; i++ {
for j := i + 1; j < len(needSortItems); j++ {
// 从大到小
if needSortItems[i].RankVal < needSortItems[j].RankVal {
needSortItems[i], needSortItems[j] = needSortItems[j], needSortItems[i]
}
}
}
rp.rkSorted = needSortItems
// 自定义排序
if rp.selfSort != nil && len(needSortItems) > 1 {
// 外部规则排序
rp.rkSorted = rp.selfSort(needSortItems)
}
/*for rk, item := range rp.rkSorted {
log.Debug("rank:: %d, rank value:%d, item:: %v", rk+1, item.RankVal, item.Key)
}*/
if len(rp.rkSorted) > 0 {
size := len(rp.rkSorted)
log.Release("rank_pool:: %s, sorted items %d, max:%d min:%d", rp.name, size, rp.rkSorted[0].RankVal, rp.rkSorted[len(rp.rkSorted)-1].RankVal)
}
}