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