-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathrangedtable.lua
112 lines (98 loc) · 2.46 KB
/
rangedtable.lua
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
-- RangedTable - table with range or group entries
-- Author: Lucas Siqueira
-- License: Public Domain / CC0.
local RangedTable = {}
RangedTable.__index = RangedTable
setmetatable(RangedTable, {
__call = function(class, ...)
local instance = setmetatable({}, class)
if instance.initialize then
instance:initialize(...)
end
return instance
end
})
local function cmp_number(k, t)
for i = 1, #t do
local entry = t[i]
local range, v = entry[1], entry[2]
if k >= range[1] and k <= range[2] then
return v
end
end
end
local function cmp_group(k, t)
for i = 1, #t do
local entry = t[i]
local group, v = entry[1], entry[2]
for i = 1, #group do
if k == group[i] then
return v
end
end
end
end
function RangedTable:get(k)
local cmp = type(k) == "number" and cmp_number or cmp_group
return cmp(k, self.ranges)
end
function RangedTable:keys()
local i = 0
return function()
i = i + 1
return self.ranges[i] and self.ranges[i][1] or nil
end
end
function RangedTable:items()
local i = 0
return function()
i = i + 1
return self.ranges[i] and self.ranges[i][1] or nil,
self.ranges[i] and self.ranges[i][2] or nil
end
end
function RangedTable:values()
local i = 0
return function()
i = i + 1
return self.ranges[i] and self.ranges[i][2] or nil
end
end
function RangedTable:choice()
return self:get(math.random(1, self.max))
end
function RangedTable:initialize(t)
self.ranges = {}
for i = 1, #t do
self.ranges[#self.ranges + 1] = t[i]
end
self:normalize()
return self
end
function RangedTable:size()
return #self.ranges
end
function RangedTable:normalize()
local normalized = {}
local sum = 1
local range
for i = 1, #self.ranges do
local entry = self.ranges[i]
local chance = entry[1]
local content = entry[2]
if type(chance) == "number" then
range = chance
elseif #chance == 1 then
range = chance[1]
elseif type(chance[1]) == "string" then
return
else
range = chance[2] - chance[1] + 1
end
normalized[#normalized + 1] = {{sum, sum + range - 1}, content}
sum = sum + range
end
self.ranges = normalized
self.max = sum - 1
end
return RangedTable