Module:Sandbox/LootTable

local java_data = mw.text.jsonDecode(mw.getCurrentFrame:expandTemplate{ title = 'Module:Sandbox/LootTable/Java.json' } )

local p = { calc_average_amount_this_item_per_pool = function(			min_stacksize, max_stacksize,			min_pool_rolls, max_pool_rolls,			item_weight, pool_total_item_weight )

local avg_stacksize = ( min_stacksize + max_stacksize ) / 2 local avg_rolls = ( min_pool_rolls + max_pool_rolls ) / 2

return avg_stacksize * avg_rolls * item_weight / pool_total_item_weight

end,

calc_chance_any_of_this_item_per_pool = function(			min_pool_rolls, max_pool_rolls,			item_weight, pool_total_item_weight )

local inverse_result = 0 -- 1 - inverse_result = return value local inverse_item_weight = pool_total_item_weight - item_weight

-- will be used for the division in the for loop to avoid the slightly -- less performant math.pow. The divisor already includes the probability -- of picking any specific number of rolls. local cur_dividend = pool_total_item_weight local cur_divisor = pool_total_item_weight * (max_pool_rolls - min_pool_rolls + 1) for i = 0, max_pool_rolls do			if i >= min_pool_rolls then inverse_result = inverse_result + cur_dividend / cur_divisor end cur_dividend = cur_dividend * inverse_item_weight -- simulate pow cur_divisor = cur_divisor * pool_total_item_weight -- simulate pow end

return 1 - inverse_result end,

get_tables_and_items = function(data) local items = {} local loottables = {}

for table_id, details in pairs(data) do           loottables[table_id] = { category = details.category, sub_category = details.sub_category, type = details.type, pools = {}, }           for pool_i, pool in ipairs(details["loot_table"]["pools"]) do                loottables[table_id].pools[pool_i] = { rolls = pool.rolls, total_weight = 0 }               -- TODO parse conditions

for i, entry in ipairs(pool["entries"]) do                   if entry["type"] == "minecraft:item" then local item = { id = entry["name"], min_stacksize = 1, max_stacksize = 1, item_weight = entry["weight"] or 1, pool = pool_i, loot_table = table_id, }

for i, func in ipairs(entry["functions"]) do                           if func["function"] == "minecraft:set_count" then item.min_stacksize = entry["count"]["min"] or 1 item.max_stacksize = entry["count"]["max"] or 1 -- TODO parse other functions end end

loottables[table_id].pools[pool_i].total_weight = loottables[table_id].pools[pool_i].total_weight + item.item_weight

if items[item.id] then table.insert(items[item.id], item) else items[item.key] = table.pack(item) end end end end end return items, loottables end,

current_frame = nil }

p.loot_tables = function( ... ) local items, loottables = p.get_tables_and_items(java_data) local output = '{| class="wikitable sortable"\n|-\n! Item !! Pool !! Chance per pool !! Average amount per pool' for item_id, item_data in pairs(items) do       for _, item in ipairs(item_data) do            local chance = p.calc_chance_any_of_this_item_per_pool(                loottables[item.loot_table].pools[item.pool].rolls.min,                loottables[item.loot_table].pools[item.pool].rolls.max,                item.item_weight,                loottables[item.loot_table].pools[item.pool].total_weight            ) local avg_amount = p.calc_average_amount_this_item_per_pool(               item.min_stacksize,                item.max_stacksize,                loottables[item.loot_table].pools[item.pool].rolls.min,                loottables[item.loot_table].pools[item.pool].rolls.max,                item.item_weight,                loottables[item.loot_table].pools[item.pool].total_weight            ) output = output .. string.format('\n|-\n| %s || %d || %f || %f', item_id, item.pool, chance, avg_amount) end end output = output .. '\n|}' return output end