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:

image --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
image -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.

Answered on disc

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