# Weighted Table not working correctly

Problem: Weighted system does not return the correct item in range properly

Scenario:
I have a weighted table system where if the randomised number is within the range of the counter then it will return the item’s name, however some items let says in this case, a common item can still be returned even though the randomised number is like “40” which should return a rare item

Here are some examples of what i mean:

--See how it returns a “Roffy” item ? even though the randomising value was 40 which in this case is within the range of a rare item as shown in the items table module:

``````local WeightedChance = { --The numbers applied to it are the chances, 125 common, 50 is rare, 3 is super rare
Items = {
["Rohklea"] = 125,
["Kahruto(Kid)"] = 125,
["Roffy"] = 125,
["Ikigoh"] = 125,
["Kokyu"] = 125,
["Yuru"] = 125,
["Zakuse(Kid)"] = 125,
["Picohloh"] = 125,
["Vegehtah"] = 125,
["Chah"] = 125,
["Kahruto(TS)"] = 50,
["Zakuse(TS)"] = 50,
["Vegehtah(SSJ)"] = 50,
["Ace"] = 3,

}

}
``````

This is the code i use:

``````function RandomiseItem(TotalWeight, Stats) --Receives the total chances (This function decides the weighted system)
local Counter = 0
--local RarityGroup
local Randomising = math.random(1,TotalWeight)
for CharName, CharChances in pairs(Module.GetMainBanner()) do
--local RarityChance = CharChances --CharChances.Rarity.Chance
Counter = Counter + CharChances
if Randomising <= Counter then
--RarityGroup = CharName
--print(RarityGroup)
local UnlockedItems = CharName --Chances.Items
print(Counter)
print(Randomising)
print(UnlockedItems)
return UnlockedItems
end
end
end
``````

Module.GetMainBanner() returns a live module consisting of the items available in the “Shop”
–Here is the screenshot
-See how i printed it here ?

And finally!

This is where i call the RandomiseItem function

``````	local MainBanner = Module.GetMainBanner() --getting the banner as shown in picture above
for Name, Chance in pairs(MainBanner) do
TotalMainBannerWeight = TotalMainBannerWeight + Chance --Adding the total chances
end
coroutine.resume(coroutine.create(function()
local Characters = RandomiseItem(TotalMainBannerWeight) --Sending the chances
end))
``````

Please, i appreciate if anyone can help or could show me a better way of doing it, Thank You

Isnt this supposed to be in code review then?

I dont think it is i explained the problem with it at the top

I have made the issue more clear now Thank You

There is no reason to move this to code review, this would fall under the scripting support category too.

``````function module.NormalBanner()
return    {
Common = {
Chance = 125,
Items = {
"Rohklea",
"Kahruto(Kid)",
"Roffy",
"Ikigoh",
"Kokyu",
"Yuru",
"Zakuse(Kid)",
"Picohloh",
"Vegehtah",
"Chah",
}

},

Rare = {
Chance = 50,
Items = {
"Kahruto(TS)",
"Zakuse(TS)",
"Vegehtah(SSJ)",
}
},

SuperRare = {
Chance = 3,
Items = {
"Ace",
}
}
}
end

local function shallowCloneArray(tbl) -- the other function
return {unpack(tbl)}
end

function module.getUniqueRandom(type, amount)
local picked = {}
local banners = shallowCloneArray(module.GetTableType(type))

for i = 1, amount do
picked[i] = table.remove(banners, math.random(#banners))
end

return picked
end

function module.StartRandomBanner()
local pickedCommon = module.getUniqueRandom("common", 3)
local pickedRare = module.getUniqueRandom("rare", 2)
local pickedLegendary = module.getUniqueRandom("legendary",  1)

module.UpdateMainBanner({common = pickedCommon, rare = pickedRare, legendary =  pickedLegendary })
end

local function getChance(type)
return banners[type].Chance
end

local function pickItem(tbl)
local randWeight = math.random(125 * 3 + 50 * 2 + 3) -- you can leave like this or make it function which actually calcs that

for type, items in pairs(tbl) do
for _, item in ipairs(items) do
local chance = getChance(type)

if randWeight <= chance then
return item
else
randWeight -= chance
end
end
end
end

function module.updateMainBanner(tbl)
local pickedItem = pickItem(tbl)
-- ... other stuff
end
``````