-
Notifications
You must be signed in to change notification settings - Fork 1
/
SingleRanking.sol
112 lines (83 loc) · 2.59 KB
/
SingleRanking.sol
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
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.6.0;
import "./FastArray.sol";
import "./RankingRedBlackTree.sol";
library SingleRanking {
struct Data {
RankingRedBlackTree.Tree tree;
mapping(uint => FastArray.Data ) keys;
uint length;
}
function add(Data storage _singleRanking, uint _key, uint _value) internal {
FastArray.Data storage keys = _singleRanking.keys[_value];
if (FastArray.length(keys) == 0) {
RankingRedBlackTree.insert(_singleRanking.tree, _value);
}
else {
RankingRedBlackTree.addToCount(_singleRanking.tree, _value, 1);
}
FastArray.insert(_singleRanking.keys[_value], _key);
_singleRanking.length += 1;
}
function remove(Data storage _singleRanking, uint _key, uint _value) internal {
FastArray.Data storage keys = _singleRanking.keys[_value];
if (FastArray.length(keys) > 0) {
FastArray.remove(keys, _key);
if (FastArray.length(keys) == 0) {
RankingRedBlackTree.remove(_singleRanking.tree, _value);
}
else {
RankingRedBlackTree.minusFromCount(_singleRanking.tree, _value, 1);
}
}
_singleRanking.length -= 1;
}
function length(Data storage _singleRanking) public view returns (uint) {
return _singleRanking.length;
}
function get(Data storage _singleRanking, uint _offset, uint _count) public view returns (uint[] memory) {
require(_offset >= 0, "Offet can not be negative");
require(_count >= 0 && _count <= 40, "Count must be between 0 and 40");
uint[] memory result = new uint[](_count);
uint size = 0;
uint id;
(id, _offset) = RankingRedBlackTree.lastByOffset(_singleRanking.tree, _offset);
while (id != 0) {
uint value = RankingRedBlackTree.value(_singleRanking.tree, id);
FastArray.Data storage keys = _singleRanking.keys[value];
if (_offset >= FastArray.length(keys)) {
_offset -= FastArray.length(keys);
}
else if (FastArray.length(keys) < _offset + _count) {
uint index = FastArray.length(keys) - 1;
while (index >= _offset) {
uint key = FastArray.get(keys, index);
result[size] = key;
size += 1;
if (index == 0) {
break;
}
index -= 1;
}
_count -= FastArray.length(keys) - _offset;
_offset = 0;
}
else {
uint index = _count - 1;
while (index >= _offset) {
uint key = FastArray.get(keys, index);
result[size] = key;
size += 1;
if (index == 0) {
break;
}
index -= 1;
}
result[size] = value;
break;
}
id = RankingRedBlackTree.prev(_singleRanking.tree, id);
}
return result;
}
}