initial commit
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
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
|
||||
Reference in New Issue
Block a user