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 player
import (
"encoding/base64"
"math/bits"
"gopkg.in/yaml.v3"
)
type RoomSet struct {
bits []byte
}
func (rs *RoomSet) Add(roomID int) {
if roomID < 0 {
return
}
byteIdx := roomID / 8
if byteIdx >= len(rs.bits) {
nb := make([]byte, byteIdx+1)
copy(nb, rs.bits)
rs.bits = nb
}
rs.bits[byteIdx] |= 1 << (roomID % 8)
}
func (rs *RoomSet) Has(roomID int) bool {
if roomID < 0 {
return false
}
byteIdx := roomID / 8
return byteIdx < len(rs.bits) && rs.bits[byteIdx]&(1<<(roomID%8)) != 0
}
func (rs *RoomSet) Len() int {
n := 0
for _, b := range rs.bits {
n += bits.OnesCount8(b)
}
return n
}
func (rs RoomSet) IsZero() bool {
return len(rs.bits) == 0
}
func (rs *RoomSet) Keys() []int {
var keys []int
for byteIdx, b := range rs.bits {
if b == 0 {
continue
}
base := byteIdx * 8
for bitIdx := 0; bitIdx < 8; bitIdx++ {
if b&(1<<bitIdx) != 0 {
keys = append(keys, base+bitIdx)
}
}
}
return keys
}
func (rs *RoomSet) Rekey(idMap map[int]int) (RoomSet, bool) {
var next RoomSet
changed := false
for _, k := range rs.Keys() {
newK, ok := idMap[k]
if !ok {
newK = k
} else if newK != k {
changed = true
}
next.Add(newK)
}
return next, changed
}
func NewRoomSetFrom(ids ...int) RoomSet {
var rs RoomSet
for _, id := range ids {
rs.Add(id)
}
return rs
}
func (rs RoomSet) MarshalYAML() (any, error) {
return base64.StdEncoding.EncodeToString(rs.bits), nil
}
func (rs *RoomSet) UnmarshalYAML(value *yaml.Node) error {
if value.Kind == yaml.ScalarNode && (value.Tag == "!!null" || value.Value == "null") {
rs.bits = nil
return nil
}
var s string
if err := value.Decode(&s); err != nil {
return err
}
if s == "" {
rs.bits = nil
return nil
}
b, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return err
}
rs.bits = b
return nil
}
|