178 lines
5.9 KiB
Lua
178 lines
5.9 KiB
Lua
local ____lualib = require("lualib_bundle")
|
|
local __TS__Class = ____lualib.__TS__Class
|
|
local __TS__Delete = ____lualib.__TS__Delete
|
|
local __TS__ArrayIndexOf = ____lualib.__TS__ArrayIndexOf
|
|
local __TS__ArraySplice = ____lualib.__TS__ArraySplice
|
|
local __TS__New = ____lualib.__TS__New
|
|
local ____exports = {}
|
|
____exports.WeightedPool = __TS__Class()
|
|
local WeightedPool = ____exports.WeightedPool
|
|
WeightedPool.name = "WeightedPool"
|
|
WeightedPool.____file_path = "scripts/vscripts/lib/pool.lua"
|
|
function WeightedPool.prototype.____constructor(self, name, upperLimit, gain)
|
|
if name == nil then
|
|
name = "Безымянный пул"
|
|
end
|
|
self.data = {}
|
|
self.mappingTable = {}
|
|
self.len = 0
|
|
self.totalProportion = 0
|
|
self.virtualTotalProportion = 0
|
|
self.gain = 10000
|
|
self.name = name
|
|
self.upperLimit = upperLimit
|
|
self.gain = gain or 10000
|
|
end
|
|
function WeightedPool.prototype.add(self, object, proportion)
|
|
if proportion == nil then
|
|
proportion = 1
|
|
end
|
|
if self.mappingTable[object] then
|
|
local currentWeight = self:getWeightPrize(object)
|
|
self:remove(object)
|
|
return self:add(object, currentWeight + proportion)
|
|
end
|
|
if self.upperLimit and self.len >= self.upperLimit then
|
|
return self
|
|
end
|
|
self.totalProportion = self.totalProportion + proportion
|
|
self.virtualTotalProportion = math.floor(self.totalProportion * self.gain)
|
|
local weightPrize = {object = object, proportion = proportion, virtualProportion = proportion * self.gain}
|
|
self.mappingTable[object] = weightPrize
|
|
local ____self_data_0 = self.data
|
|
____self_data_0[#____self_data_0 + 1] = weightPrize
|
|
self.len = self.len + 1
|
|
return self
|
|
end
|
|
function WeightedPool.prototype.sub(self, object, proportion)
|
|
if self.mappingTable[object] then
|
|
local currentWeight = self:getWeightPrize(object)
|
|
self:remove(object)
|
|
self:add(object, currentWeight - proportion)
|
|
else
|
|
end
|
|
end
|
|
function WeightedPool.prototype.remove(self, object)
|
|
if not self.mappingTable[object] then
|
|
return
|
|
end
|
|
local prize = self.mappingTable[object]
|
|
__TS__Delete(self.mappingTable, object)
|
|
local index = __TS__ArrayIndexOf(self.data, prize)
|
|
if index > -1 then
|
|
__TS__ArraySplice(self.data, index, 1)
|
|
end
|
|
self.totalProportion = self.totalProportion - prize.proportion
|
|
self.virtualTotalProportion = math.floor(self.totalProportion * self.gain)
|
|
self.len = self.len - 1
|
|
end
|
|
function WeightedPool.prototype.getProbability(self, object)
|
|
local weightPrize = self.mappingTable[object]
|
|
if not weightPrize then
|
|
return {0, 0}
|
|
end
|
|
return {weightPrize.proportion / self.totalProportion, weightPrize.proportion}
|
|
end
|
|
function WeightedPool.prototype.getWeightPrize(self, object)
|
|
local weightPrize = self.mappingTable[object]
|
|
return weightPrize ~= nil and weightPrize.proportion or 0
|
|
end
|
|
function WeightedPool.prototype.setWeightPrize(self, object, proportion)
|
|
local weightPrize = self.mappingTable[object]
|
|
if not weightPrize then
|
|
return {0, 0}
|
|
end
|
|
local used = weightPrize.proportion
|
|
self.totalProportion = self.totalProportion - used
|
|
weightPrize.proportion = proportion
|
|
weightPrize.virtualProportion = proportion * self.gain
|
|
self.totalProportion = self.totalProportion + proportion
|
|
self.virtualTotalProportion = math.floor(self.totalProportion * self.gain)
|
|
return {used, proportion}
|
|
end
|
|
function WeightedPool.prototype.random(self)
|
|
if self.len == 0 then
|
|
return nil
|
|
end
|
|
local winningProbability = RandomInt(1, self.virtualTotalProportion)
|
|
for ____, prize in ipairs(self.data) do
|
|
winningProbability = winningProbability - prize.virtualProportion
|
|
if winningProbability <= 0 then
|
|
return prize.object
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
function WeightedPool.prototype.randomAndRemove(self)
|
|
if self.len == 0 then
|
|
return nil
|
|
end
|
|
local winningProbability = RandomInt(1, self.virtualTotalProportion)
|
|
for ____, prize in ipairs(self.data) do
|
|
winningProbability = winningProbability - prize.virtualProportion
|
|
if winningProbability <= 0 then
|
|
self:remove(prize.object)
|
|
return prize.object
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
function WeightedPool.prototype.clear(self)
|
|
self.len = 0
|
|
self.data = {}
|
|
self.mappingTable = {}
|
|
self.totalProportion = 0
|
|
self.virtualTotalProportion = 0
|
|
end
|
|
function WeightedPool.prototype.randomSole(self, n)
|
|
local result = {}
|
|
local temp = {}
|
|
do
|
|
local i = 0
|
|
while i < n do
|
|
local obj = self:random()
|
|
if obj ~= nil then
|
|
result[#result + 1] = obj
|
|
local weight = self:getWeightPrize(obj)
|
|
temp[#temp + 1] = {obj, weight}
|
|
self:setWeightPrize(obj, 0)
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
for ____, ____value in ipairs(temp) do
|
|
local obj = ____value[1]
|
|
local weight = ____value[2]
|
|
self:setWeightPrize(obj, weight)
|
|
end
|
|
return result
|
|
end
|
|
function WeightedPool.prototype.randomCard(self, n)
|
|
local result = {}
|
|
local temp = {}
|
|
do
|
|
local i = 0
|
|
while i < n do
|
|
local obj = self:random()
|
|
if obj ~= nil then
|
|
result[#result + 1] = obj
|
|
local weight = self:getWeightPrize(obj)
|
|
temp[#temp + 1] = {obj, weight}
|
|
local newWeight = weight - 1
|
|
self:setWeightPrize(obj, newWeight >= 0 and newWeight or 0)
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
for ____, ____value in ipairs(temp) do
|
|
local obj = ____value[1]
|
|
local currentWeight = self:getWeightPrize(obj)
|
|
self:setWeightPrize(obj, currentWeight + 1)
|
|
end
|
|
return result
|
|
end
|
|
_G.pool = function(____, name, upperLimit, gain)
|
|
return __TS__New(____exports.WeightedPool, name, upperLimit, gain)
|
|
end
|
|
return ____exports
|