Module:LootChest

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 avg_rolls = ( min_pool_rolls + max_pool_rolls ) / 2 local relativeweight = item_weight / pool_total_item_weight return 1 - math.pow( 1 - relativeweight, avg_rolls ) end, dev = 'In 1.13 ', -- these define which sprite, label and link to use, in the table, -- and 'cannot_stack' and 'plural' dictate how to display the single-item summary -- NOTE: order in this list doesn't matter.

items = { ["acacia-wood"]        = { "block", link="Wood", title="Acacia or Dark Oak Wood", plural=false }, ["acacia-log"]         = { "block", link="Log" }, ["activator-rail"]     = { "block" }, ["apple"]              = { "item" }, ["arrow"]              = { "item" }, ["beetroot"]           = { "item" }, ["beetroot-seeds"]     = { "item", plural=false }, ["birch-log"]          = { "block", link="Log" }, ["bone"]               = { "item" }, ["book"]               = { "item" }, ["bottle-o'-enchanting"] = { "item", title="Bottle o' Enchanting", plural="bottles o' enchanting" }, ["bread"]              = { "item", plural=false }, ["bucket"]             = { "item" }, ["buried-treasure-map"] = { "item", link="Explorer Map" }, ["carrot"]             = { "item" }, ["chainmail-chestplate"] = { "item", link="Armor", cannot_stack=true }, ["coal"]               = { "item", plural=false }, ["cooked-fish"]        = { "item", plural=false, link="Fish", category=true }, ["cooked-salmon"]      = { "item", plural=false, link="Fish" }, ["compass"]            = { "item" }, ["dark-oak-log"]       = { "block", link="Log" }, ["detector-rail"]      = { "block" }, ["diamond"]            = { "item" }, ["diamond-chestplate"] = { "item", link="Armor", cannot_stack=true }, ["diamond-hoe"]        = { "item", link="Hoe", cannot_stack=true }, ["diamond-horse-armor"] = { "item", link="Horse Armor", cannot_stack=true, plural=false }, ["disc-13"]            = { "item", title="Music Disc (13)", link="Music Disc", cannot_stack=true, plural=false }, ["disc-cat"]           = { "item", title="Music Disc (Cat)", link="Music Disc", cannot_stack=true, plural=false }, ["emerald"]            = { "item" }, ["empty-map"]          = { "item", link="Map", title="Empty Map" }, ["enchanted-book"]     = { "item", cannot_stack=true, note="enchant-with-levels" }, ["enchanted-book-rnd"] = { "item", id='enchanted-book', title="Enchanted Book", link="Enchanted Book", cannot_stack=true, note="enchant-randomly" }, ["ender-pearl"]        = { "item" }, ["enchanted-fishing-rod"] = { "item", id="fishing-rod", link="Fishing Rod", cannot_stack=true, note="enchant-randomly" }, ["enchanted-golden-apple"] = { "item", id='golden-apple', link="Golden Apple" }, ["feather"]            = { "item" }, ["flint-and-steel"]    = { "item", cannot_stack=true, plural=false }, ["golden-apple"]       = { "item" }, ["golden-chestplate"]  = { "item", link="Armor", cannot_stack=true }, ["golden-helmet"]      = { "item", link="Armor", cannot_stack=true }, ["golden-horse-armor"] = { "item", link="Horse Armor", cannot_stack=true, plural=false }, ["golden-sword"]       = { "item", link="Sword", cannot_stack=true }, ["gold-ingot"]         = { "item" }, ["gold-nugget"]        = { "item" }, ["gunpowder"]          = { "item", plural=false }, ["iron-boots"]         = { "item", link="Armor", cannot_stack=true, plural=false }, ["iron-chestplate"]    = { "item", link="Armor", cannot_stack=true }, ["iron-helmet"]        = { "item", link="Armor", cannot_stack=true }, ["iron-horse-armor"]   = { "item", link="Horse Armor", cannot_stack=true, plural=false }, ["iron-ingot"]         = { "item" }, ["iron-leggings"]      = { "item", link="Armor", cannot_stack=true, plural=false }, ["iron-nugget"]        = { "item" }, ["iron-pickaxe"]       = { "item", link="Pickaxe", cannot_stack=true }, ["iron-sword"]         = { "item", link="Sword", cannot_stack=true }, ["jungle-log"]         = { "block", link="Log" }, ["lapis-lazuli"]       = { "item", plural=false }, ["lead"]               = { "item" }, ["leather-tunic"]      = { "item", link="Armor", cannot_stack=true }, ["melon-seeds"]        = { "item", plural=false }, ["name-tag"]           = { "item" }, ["nether-wart"]        = { "item", plural=false }, ["oak-log"]            = { "block", link="Log" }, ["oak-planks"]         = { "block", link="Planks", id="oak-wood-planks", plural=false }, ["oak-sapling"]        = { "block", link="Sapling" }, ["oak-wood"]           = { "block", link="Wood", title="Oak, Spruce, Birch or Jungle Wood", plural=false }, ["oak-wood-only"]      = { "block", id='oak-wood', link="Wood", title="Oak Wood", plural=false }, ["obsidian"]           = { "block", plural=false }, ["paper"]              = { "item", plural=false }, ["potato"]             = { "item", plural="potatoes" }, ["poisonous-potato"]   = { "item", plural="poisonous potatoes" }, ["powered-rail"]       = { "block", title="Powered Rails", plural=false }, ["prismarine-crystals"] = { "item", plural=false }, ["pumpkin"]            = { "block" }, ["pumpkin-seeds"]      = { "item", plural=false }, ["rail"]               = { "block", title="Rails", plural=false }, ["redstone"]           = { "item", plural=false }, ["rotten-flesh"]       = { "item", plural=false }, ["sand"]               = { "block", plural=false }, ["saddle"]             = { "item", cannot_stack=true }, ["raw-salmon"]         = { "item", plural=false }, ["spider-eye"]         = { "item" }, ["spruce-log"]         = { "block", link="Log" }, ["stick"]              = { "item" }, ["stone-axe"]          = { "item", link="Axe", cannot_stack=true }, ["stone-pickaxe"]      = { "item", link="Pickaxe", cannot_stack=true }, ["string"]             = { "item", plural=false }, ["tnt"]                = { "block", title="TNT", plural=false, preserve_case=true }, ["torch"]              = { "block" }, ["wheat"]              = { "item", plural=false }, ["wheat-seeds"]        = { "item", plural=false }, ["wooden-axe"]         = { "item", link="Axe", cannot_stack=true }, ["wooden-hoe"]         = { "item", link="Hoe", cannot_stack=true }, ["wooden-pickaxe"]     = { "item", link="Pickaxe", cannot_stack=true },

["enchanted-leather-cap"]       = { "item", id="leather-cap", link="Armor", note="enchant-randomly", cannot_stack=true }, ["enchanted-leather-tunic"]     = { "item", id="leather-tunic", link="Armor", note="enchant-randomly", cannot_stack=true }, ["enchanted-leather-pants"]     = { "item", id="leather-pants", link="Armor", note="enchant-randomly", cannot_stack=true, plural=false }, ["enchanted-leather-boots"]     = { "item", id="leather-boots", link="Armor", note="enchant-randomly", cannot_stack=true, plural=false }, ["enchanted-diamond-boots"]     = { "item", id="diamond-boots", link="Armor", note="enchant-with-levels-20-39", cannot_stack=true, plural=false }, ["enchanted-diamond-chestplate"] = { "item", id="diamond-chestplate", link="Armor", note="enchant-with-levels-20-39", cannot_stack=true }, ["enchanted-diamond-helmet"]    = { "item", id="diamond-helmet", link="Armor", note="enchant-with-levels-20-39", cannot_stack=true }, ["enchanted-diamond-leggings"]  = { "item", id="diamond-leggings", link="Armor", note="enchant-with-levels-20-39", cannot_stack=true, plural=false }, ["enchanted-diamond-pickaxe"]   = { "item", id="diamond-pickaxe", link="Pickaxe", note="enchant-with-levels-20-39", cannot_stack=true }, ["enchanted-diamond-shovel"]    = { "item", id="diamond-shovel", link="Shovel", note="enchant-with-levels-20-39", cannot_stack=true }, ["enchanted-diamond-sword"]     = { "item", id="diamond-sword", link="Sword", note="enchant-with-levels-20-39", cannot_stack=true }, ["enchanted-iron-boots"]        = { "item", id="iron-boots", link="Armor", note="enchant-with-levels-20-39", cannot_stack=true, plural=false }, ["enchanted-iron-chestplate"]   = { "item", id="iron-chestplate", link="Armor", note="enchant-with-levels-20-39", cannot_stack=true }, ["enchanted-iron-helmet"]       = { "item", id="iron-helmet", link="Armor", note="enchant-with-levels-20-39", cannot_stack=true }, ["enchanted-iron-leggings"]     = { "item", id="iron-leggings", link="Armor", note="enchant-with-levels-20-39", cannot_stack=true, plural=false }, ["enchanted-iron-pickaxe"]      = { "item", id="iron-pickaxe", link="Pickaxe", note="enchant-with-levels-20-39", cannot_stack=true }, ["enchanted-iron-shovel"]       = { "item", id="iron-shovel", link="Shovel", note="enchant-with-levels-20-39", cannot_stack=true }, ["enchanted-iron-sword"]        = { "item", id="iron-sword", link="Sword", note="enchant-with-levels-20-39", cannot_stack=true },

["empty"]                       = { "block", id="air", link='', title='Nothing', plural=false, note="nothing" }, },

notes = { ["enchant-with-levels"] = " ", ["enchant-with-levels-20-39"] = " ", ["enchant-randomly"] = " ", ["nothing"] = " ", },	-- NOTE: order here doesn't matter. --		 * in the table, chests will sort in alphabetical order --      * in the table, items will sort by chance, then by avg#, then alphabetically. --      * If poolsDev is omitted, pools will be used. To omit a pool entirely in the dev version, set poolsDev = {}. chests = { ["shipwreck-map"] = { -- shipwreck_map.json header = "Map", superheader = "Shipwreck", link  = "shipwreck map", pools = {}, poolsDev = { {					rolls = {1,1}, items = { ["buried-treasure-map"] = {1,1,1}, }				},				{					rolls = {3,3}, items = { ["compass"]            = {1,1,1}, ["empty-map"]          = {1,1,1}, ["clock"]              = {1,1,1}, ["paper"]              = {1,10,20}, ["feather"]            = {1,5,10}, ["book"]               = {1,5,5}, }				},			}		},		["shipwreck-supply"] = { -- shipwreck_supply.json header = "Supply", superheader = "Shipwreck", link  = "shipwreck supply", pools = {}, poolsDev = { {					rolls = {3,10}, items = { ["paper"]              = {1,12,8}, ["potato"]             = {2,6,7}, ["poisonous-potato"]   = {2,6,7}, ["carrot"]             = {4,8,7}, ["wheat"]              = {8,21,7}, ["coal"]               = {2,8,6}, ["rotten-flesh"]       = {5,24,5}, ["pumpkin"]            = {1,3,2}, ["gunpowder"]          = {1,5,3}, ["tnt"]                = {1,2,1}, ["enchanted-leather-cap"]        = {1,1,3}, ["enchanted-leather-tunic"]      = {1,1,3}, ["enchanted-leather-pants"]      = {1,1,3}, ["enchanted-leather-boots"]      = {1,1,3}, }				},			}		},		["shipwreck-treasure"] = { -- shipwreck_treasure.json header = "Treasure", superheader = "Shipwreck", link  = "shipwreck treasure", pools = {}, poolsDev = { {					rolls = {3,6}, items = { ["iron-ingot"]         = {1,5,90}, ["gold-ingot"]         = {1,5,10}, ["emerald"]            = {1,5,40}, ["diamond"]            = {1,1,5}, ["bottle-o'-enchanting"] = {1,1,5}, }				},				{					rolls = {2,5}, items = { ["iron-nugget"]        = {1,10,50}, ["gold-nugget"]        = {1,10,10}, ["lapis-lazuli"]       = {1,10,20}, }				},			}		},		["buried-treasure"] = { -- buried_treasure.json header = "Buried treasure", link  = "buried treasure", pools = {}, poolsDev = { {					rolls = {5,8}, items = { ["iron-ingot"]         = {1,4,20}, ["gold-ingot"]         = {1,4,10}, ["tnt"]                = {1,2,5}, }				},				{					rolls = {1,3}, items = { ["emerald"]            = {4,8,5}, ["diamond"]            = {1,2,5}, ["prismarine-crystals"] = {1,5,5}, }				},				{					rolls = {0,1}, items = { ["leather-tunic"]      = {1,1,1}, ["iron-sword"]         = {1,1,1}, }				},				{					rolls = {2,2}, items = { ["cooked-fish"]         = {2,4,1}, ["cooked-salmon"]      = {2,4,1}, }				},			}		},		["underwater-ruin-big"] = { -- underwater_ruin_big.json header = "Big", superheader = "Underwater ruins", link  = "big underwater ruins", pools = {}, poolsDev = { {					rolls = {2,8}, items = { ["coal"]               = {1,4,10}, ["gold-nugget"]        = {1,3,10}, ["emerald"]            = {1,1,1}, ["wheat"]              = {2,3,10}, }				},				{					rolls = {1,1}, items = { ["golden-apple"]       = {1,1,1}, ["enchanted-book-rnd"] = {1,1,5}, ["leather-tunic"]      = {1,1,1}, ["golden-helmet"]      = {1,1,1}, ["enchanted-fishing-rod"] = {1,1,5}, ["buried-treasure-map"] = {1,1,10}, }				},			}		},		["underwater-ruin-small"] = { -- underwater_ruin_small.json header = "Small", superheader = "Underwater ruins", link  = "small underwater ruins", pools = {}, poolsDev = { {					rolls = {2,8}, items = { ["coal"]               = {1,4,10}, ["stone-axe"]          = {1,1,2}, ["rotten-flesh"]       = {1,1,5}, ["emerald"]            = {1,1,1}, ["wheat"]              = {2,3,10}, }				},				{					rolls = {1,1}, items = { ["leather-tunic"]      = {1,1,1}, ["golden-helmet"]      = {1,1,1}, ["enchanted-fishing-rod"] = {1,1,5}, ["buried-treasure-map"] = {1,1,5}, }				},			}		},		["village-blacksmith"] = { -- village_blacksmith.json header = "Blacksmith", superheader = "Village", link  = "village blacksmith", pools = { {					rolls = {3,8}, items = { ["diamond"]            = {1,3,3}, ["iron-ingot"]         = {1,5,10}, ["gold-ingot"]         = {1,3,5}, ["bread"]              = {1,3,15}, ["apple"]              = {1,3,15}, ["iron-pickaxe"]       = {1,1,5}, ["iron-sword"]         = {1,1,5}, ["iron-chestplate"]    = {1,1,5}, ["iron-helmet"]        = {1,1,5}, ["iron-leggings"]      = {1,1,5}, ["iron-boots"]         = {1,1,5}, ["obsidian"]           = {3,7,5}, ["oak-sapling"]        = {3,7,5}, ["iron-horse-armor"]   = {1,1,1}, ["golden-horse-armor"] = {1,1,1}, ["diamond-horse-armor"] = {1,1,1}, ["saddle"]             = {1,1,3} }				},			},			poolsDev = {} },		["village-two-room-house"] = { -- village_two_room_house.json header = "Two-room house", superheader = "Village", link  = "village two-room house", pools = { {					rolls = {6,8}, items = { ["potato"]     = {5,8,10}, ["carrot"]     = {4,8,10}, ["wheat"]      = {8,12,15}, ["wheat-seeds"] = {2,4,5}, ["beetroot"]   = {5,8,5}, ["wooden-hoe"] = {1,1,1} }				},			},			poolsDev = {} },		["stronghold-altar"] = { -- stronghold_corridor.json header     = "Altar", superheader = "Stronghold", link       = "stronghold altar", pools = { {					rolls = {2,3}, items = { ["ender-pearl"]        = {1,1,10}, ["diamond"]            = {1,3,3}, ["iron-ingot"]         = {1,5,10}, ["gold-ingot"]         = {1,3,5}, ["redstone"]           = {4,9,5}, ["bread"]              = {1,3,15}, ["apple"]              = {1,3,15}, ["iron-pickaxe"]       = {1,1,5}, ["iron-sword"]         = {1,1,5}, ["iron-chestplate"]    = {1,1,5}, ["iron-helmet"]        = {1,1,5}, ["iron-leggings"]      = {1,1,5}, ["iron-boots"]         = {1,1,5}, ["golden-apple"]       = {1,1,1}, ["saddle"]             = {1,1,1}, ["iron-horse-armor"]   = {1,1,1}, ["golden-horse-armor"]   = {1,1,1}, ["diamond-horse-armor"] = {1,1,1}, ["enchanted-book"]     = {1,1,1}, }				},			},			poolsDev = {} },		["stronghold-library"] = { -- stronghold_library.json header     = "Library", superheader = "Stronghold", link       = "stronghold library", pools = { {					rolls = {2,10}, items = { ["book"]               = {1,3,20}, ["paper"]              = {2,7,20}, ["empty-map"]          = {1,1,1}, ["compass"]            = {1,1,1}, ["enchanted-book"]     = {1,1,10}, }				},			},			poolsDev = {} },		["stronghold-storeroom"] = { -- stronghold_crossing.json header     = "Storeroom", superheader = "Stronghold", link       = "stronghold storeroom", pools = { {					rolls = {1,4}, items = { ["iron-ingot"]         = {1,5,10}, ["gold-ingot"]         = {1,3,5}, ["redstone"]           = {4,9,5}, ["coal"]               = {3,8,10}, ["bread"]              = {1,3,15}, ["apple"]              = {1,3,15}, ["iron-pickaxe"]       = {1,1,1}, ["enchanted-book"]     = {1,1,1}, }				},			},			poolsDev = {} },		["bonus"] = { -- spawn_bonus_chest.json header = "Bonus", link  = "bonus", pools = { {					rolls = {1,1}, items = { ["stone-axe"]          = {1,1,1}, ["wooden-axe"]         = {1,1,3}, }				},				{					rolls = {1,1}, items = { ["stone-pickaxe"]      = {1,1,1}, ["wooden-pickaxe"]     = {1,1,3} }				},				{					rolls = {3,3}, items = { ["apple"]              = {1,2,5}, ["bread"]              = {1,2,3}, ["raw-salmon"]         = {1,2,3}, }				},				{					rolls = {4,4}, items = { ["stick"]              = {1,12,10}, ["oak-planks"]         = {1,12,10}, ["oak-wood"]           = {1,3,10}, ["acacia-wood"]        = {1,3,10}, }				},			},			poolsDev = { {					rolls = {1,1}, items = { ["stone-axe"]          = {1,1,1}, ["wooden-axe"]         = {1,1,3}, }				},				{					rolls = {1,1}, items = { ["stone-pickaxe"]      = {1,1,1}, ["wooden-pickaxe"]     = {1,1,3} }				},				{					rolls = {3,3}, items = { ["apple"]              = {1,2,5}, ["bread"]              = {1,2,3}, ["raw-salmon"]         = {1,2,3}, }				},				{					rolls = {4,4}, items = { ["stick"]              = {1,12,10}, ["oak-planks"]         = {1,12,10}, ["oak-log"]            = {1,3,3}, ["spruce-log"]         = {1,3,3}, ["birch-log"]          = {1,3,3}, ["jungle-log"]         = {1,3,3}, ["acacia-log"]         = {1,3,3}, ["dark-oak-log"]       = {1,3,3}, }				},			}		},		["dungeon"] = { -- simple_dungeon.json header = "Dungeon", link  = "dungeon", pools = { {					rolls = {1,3}, items = { ["saddle"]             = {1,1,20}, ["golden-apple"]       = {1,1,15}, ["enchanted-golden-apple"] = {1,1,2}, ["disc-13"]            = {1,1,15}, ["disc-cat"]           = {1,1,15}, ["name-tag"]           = {1,1,20}, ["golden-horse-armor"] = {1,1,10}, ["iron-horse-armor"]   = {1,1,15}, ["diamond-horse-armor"] = {1,1,5}, ["enchanted-book-rnd"] = {1,1,10}, }				},				{					rolls = {1,4}, items = { ["iron-ingot"]         = {1,4,10}, ["gold-ingot"]         = {1,4,5}, ["bread"]              = {1,1,20}, ["wheat"]              = {1,4,20}, ["bucket"]             = {1,1,10}, ["redstone"]           = {1,4,15}, ["coal"]               = {1,4,15}, ["melon-seeds"]        = {2,4,10}, ["pumpkin-seeds"]      = {2,4,10}, ["beetroot-seeds"]     = {2,4,10}, }				},				{					rolls = {3,3}, items = { ["bone"]               = {1,8,10}, ["gunpowder"]          = {1,8,10}, ["rotten-flesh"]       = {1,8,10}, ["string"]             = {1,8,10}, }				},			},			poolsDev = {} },		["mineshaft"] = { -- abandoned_mineshaft.json chest_type = "minecart with chest", header = "Mineshaft", link  = "abandoned mineshafts", pools = { {					rolls = {1,1}, items = { ["golden-apple"]       = {1,1,20}, ["enchanted-golden-apple"] = {1,1,1}, ["name-tag"]           = {1,1,30}, ["enchanted-book-rnd"] = {1,1,10}, ["iron-pickaxe"]       = {1,1,5}, ["empty"]				= {1,1,5}, }				},				{					rolls = {2,4}, items = { ["iron-ingot"]         = {1,5,10}, ["gold-ingot"]         = {1,3,5}, ["redstone"]           = {4,9,5}, ["lapis-lazuli"]       = {4,9,5}, ["diamond"]            = {1,2,3}, ["coal"]               = {3,8,10}, ["bread"]              = {1,3,15}, ["melon-seeds"]        = {2,4,10}, ["pumpkin-seeds"]      = {2,4,10}, ["beetroot-seeds"]     = {2,4,10}, }				},				{					rolls = {3,3}, items = { ["rail"]               = {4,8,20}, ["powered-rail"]       = {1,4,5}, ["detector-rail"]      = {1,4,5}, ["activator-rail"]     = {1,4,5}, ["torch"]              = {1,16,15}, }				},			},			poolsDev = {} },		["nether-fortress"] = { -- nether_bridge.json header = "Nether fortress", link  = "nether fortress", pools = { {					rolls = {2,4}, items = { ["diamond"]            = {1,3,5}, ["iron-ingot"]         = {1,5,5}, ["gold-ingot"]         = {1,3,15}, ["golden-sword"]       = {1,1,5}, ["golden-chestplate"]  = {1,1,5}, ["flint-and-steel"]    = {1,1,5}, ["nether-wart"]        = {3,7,5}, ["saddle"]             = {1,1,10}, ["golden-horse-armor"]   = {1,1,8}, ["iron-horse-armor"]   = {1,1,5}, ["diamond-horse-armor"] = {1,1,3}, ["obsidian"]           = {2,4,2}, }				},			},			poolsDev = {} },		["desert-temple"] = { -- desert_pyramid.json header = "Desert temple", link  = "desert temple", pools = { {					rolls = {2,4}, items = { ["diamond"]            = {1,3,5}, ["iron-ingot"]         = {1,5,15}, ["gold-ingot"]         = {2,7,15}, ["emerald"]            = {1,3,15}, ["bone"]               = {4,6,25}, ["spider-eye"]         = {1,3,25}, ["rotten-flesh"]       = {3,7,25}, ["saddle"]             = {1,1,20}, ["iron-horse-armor"]   = {1,1,15}, ["golden-horse-armor"] = {1,1,10}, ["diamond-horse-armor"] = {1,1,5}, ["enchanted-book-rnd"] = {1,1,20}, ["golden-apple"]       = {1,1,20}, ["enchanted-golden-apple"] = {1,1,2}, ["empty"]              = {1,1,15}, }				},				{					rolls = {4,4}, items = { ["bone"]               = {1,8,10}, ["gunpowder"]          = {1,8,10}, ["rotten-flesh"]       = {1,8,10}, ["string"]             = {1,8,10}, ["sand"]               = {1,8,10}, }				},			},			poolsDev = {} },		["jungle-temple"] = { -- jungle_temple.json header = "Jungle temple", link  = "jungle temple", pools = { {					rolls = {2,6}, items = { ["diamond"]            = {1,3,3}, ["iron-ingot"]         = {1,5,10}, ["gold-ingot"]         = {2,7,15}, ["emerald"]            = {1,3,2}, ["iron-horse-armor"]   = {1,1,1}, ["golden-horse-armor"]   = {1,1,1}, ["diamond-horse-armor"] = {1,1,1}, ["saddle"]             = {1,1,3}, ["enchanted-book"]     = {1,1,1}, ["bone"]               = {4,6,20}, ["rotten-flesh"]       = {3,7,16} }				},			},			poolsDev = {} },		["jungle-temple-dispenser"] = { -- jungle_temple_dispenser.json chest_type = "dispenser", link  = "jungle temples", pools = { {					rolls = {1,2}, items = { ["arrow"] = {2,7,30} }				},			},			poolsDev = {} },		["end-city"] = { -- end_city_treasure.json header = "End city", link  = "End city", pools = { {					rolls = {2,6}, items = { ["diamond"]            = {2,7,5}, ["iron-ingot"]         = {4,8,10}, ["gold-ingot"]         = {2,7,15}, ["emerald"]            = {2,6,2}, ["beetroot-seeds"]     = {1,10,5}, ["saddle"]             = {1,1,3}, ["iron-horse-armor"]   = {1,1,1}, ["golden-horse-armor"]   = {1,1,1}, ["diamond-horse-armor"] = {1,1,1}, ["enchanted-diamond-sword"]     = {1,1,3}, ["enchanted-diamond-boots"]     = {1,1,3}, ["enchanted-diamond-chestplate"] = {1,1,3}, ["enchanted-diamond-leggings"]  = {1,1,3}, ["enchanted-diamond-helmet"]    = {1,1,3}, ["enchanted-diamond-pickaxe"]   = {1,1,3}, ["enchanted-diamond-shovel"]    = {1,1,3}, ["enchanted-iron-sword"]        = {1,1,3}, ["enchanted-iron-boots"]        = {1,1,3}, ["enchanted-iron-chestplate"]   = {1,1,3}, ["enchanted-iron-leggings"]     = {1,1,3}, ["enchanted-iron-helmet"]       = {1,1,3}, ["enchanted-iron-pickaxe"]      = {1,1,3}, ["enchanted-iron-shovel"]       = {1,1,3}, }				},			},			poolsDev = {} },		["igloo"] = { header = "Igloo", link  = "igloo", pools = { {					rolls = {2,8}, items = { ["apple"]              = {1,3,15}, ["coal"]               = {1,4,15}, ["gold-nugget"]        = {1,3,10}, ["stone-axe"]          = {1,1,2}, ["rotten-flesh"]       = {1,1,10}, ["emerald"]            = {1,1,1}, ["wheat"]              = {2,3,10} }				},				{					rolls = {1,1}, items = { ["golden-apple"]       = {1,1,1}, }				},			},			poolsDev = {} },		["woodland-mansion"] = { -- woodland_mansion.json header = "Woodland Mansion", link  = "woodland mansion", pools = { {					rolls = {1,3}, items = { ["lead"]                 = {1,1,20}, ["golden-apple"]         = {1,1,15}, ["enchanted-golden-apple"] = {1,1,2}, ["disc-13"]              = {1,1,15}, ["disc-cat"]             = {1,1,15}, ["name-tag"]             = {1,1,20}, ["chainmail-chestplate"] = {1,1,10}, ["diamond-hoe"]          = {1,1,15}, ["diamond-chestplate"]   = {1,1,5}, ["enchanted-book-rnd"]   = {1,1,10}, }				},				{					rolls = {1,4}, items = { ["iron-ingot"]           = {1,4,10}, ["gold-ingot"]           = {1,4,5}, ["bread"]                = {1,1,20}, ["wheat"]                = {1,4,20}, ["bucket"]               = {1,1,10}, ["redstone"]             = {1,4,15}, ["coal"]                 = {1,4,15}, ["melon-seeds"]          = {2,4,10}, ["pumpkin-seeds"]        = {2,4,10}, ["beetroot-seeds"]       = {2,4,10}, }				},				{					rolls = {3,3}, items = { ["bone"]                 = {1,8,10}, ["gunpowder"]            = {1,8,10}, ["rotten-flesh"]         = {1,8,10}, ["string"]               = {1,8,10}, }				},			},			poolsDev = {}, },	},

-- these values are used: -- * in place of the keys, when the key is used as a parameter -- chest-param -> internally-valid-chest-param synonyms = { ["desert"] = "desert-temple", ["jungle"] = "jungle-temple", ["nether"] = "nether-fortress", ["fortress"] = "nether-fortress", ["blacksmith"] = "village-blacksmith", ["altar"] = "stronghold-altar", ["storeroom"] = "stronghold-storeroom", ["library"] = "stronghold-library", ["mansion"] = "woodland-mansion" },

-- these values are used: -- * in the header-description of a table showing only a single chest -- * if the key is not here, but it is a valid chest parameter, --  that header-description will default to use the key string from p.chests, --  e.g. "nether-fortress" -- chest-param -> description-string display_names = { ["nether-fortress"] = "Nether fortress", ["nether"] = "Nether fortress", ["fortress"] = "Nether fortress", ["desert"] = "desert temple", ["jungle"] = "jungle temple", ["desert-temple"] = "desert temple", ["jungle-temple"] = "jungle temple" },	-- these descriptions are used: -- * in column titles, -- * and above the table when only a single column-type is chosen columns = { ["stacksize"] = 'the size of stacks (or for unstackable items, number) of this item found in this chest.', ["weight"] = 'the weight of this item relative to other items in the chest.', ["items"] = 'the number of items expected per chest, averaged over a large number of chests.', ["chance"] = 'the odds of getting any of this item in a single chest.', ["chests"] = 'the number of chests expected to search, to find any of this item.' },	current_frame = nil }

p.base = function( ... )

p.current_frame = mw.getCurrentFrame

local args = { ... }	if args[1] == p.current_frame then args = require( 'Module:ProcessArgs' ).merge( true ) else args = args[1] end -- transform args into usable list local chests, columns = q.massage_args( args ) if #chests == 0 then return " Module:LootChest: no valid arguments " end

q.fill_in_chest_derivative_data( chests ) -- construct an ordered list dictating the order of the rows local ordered_item_rows, ordered_item_rows_dev

local ret = {} if args.dev and args.dev ~= '0' then local ordered_item_rows = q.construct_ordered_item_rows( chests, 'Dev' ) if q.tablelength( ordered_item_rows ) > 0 then table.insert( ret, q.print_table( chests, columns, ordered_item_rows, 'Dev' ) ) end else local ordered_item_rows = q.construct_ordered_item_rows( chests, '' ) local ordered_item_rows_dev = q.construct_ordered_item_rows( chests, 'Dev' )

if q.tablelength( ordered_item_rows ) > 0 then table.insert( ret, q.print_table( chests, columns, ordered_item_rows, '' ) ) end if q.tablelength( ordered_item_rows_dev ) > 0 and q.compare_tables( ordered_item_rows, ordered_item_rows_dev ) then table.insert( ret, p.current_frame:preprocess( p.dev ) .. q.lcfirst( q.print_table( chests, columns, ordered_item_rows_dev, 'Dev' ) ) ) end end

return table.concat( ret, '\n\n' ) end

p.doc = function

local valid_args = {} for chest_name, val in pairs(p.chests) do		local synonyms = {} for syn, orig in pairs(p.synonyms) do			if orig == chest_name then table.insert( synonyms, syn ) end end if #synonyms > 0 then chest_name = chest_name .. " ( " .. table.concat( synonyms, ", " ) .. " )" end table.insert( valid_args, chest_name ) end table.sort( valid_args ) return table.concat( valid_args, ",\n " )

end

p.doc2 = function

local valid_args = {} for column_name, val in pairs(p.columns) do table.insert( valid_args, column_name .. ": " .. val ) end table.sort( valid_args ) return table.concat( valid_args, ",\n " )

end

p.doc3 = function

local valid_args = {} for item_name, val in pairs(p.items) do		table.insert( valid_args, item_name ) end table.sort( valid_args ) return table.concat( valid_args, ", " )

end

p.base2 = function( ... )

p.current_frame = mw.getCurrentFrame

local args = { ... }	if args[1] == p.current_frame then args = require( 'Module:ProcessArgs' ).merge( true ) else args = args[1] end local itemname = args[1] if p.items[itemname] == nil then return ' unknown item "' .. itemname .. '" ' end local chances, devChances if args.dev and args.dev ~= '0' then chances = q.single_item_find_values( itemname, 'poolsDev' ) devChances = {} else chances = q.single_item_find_values( itemname, 'pools' ) devChances = q.single_item_find_values( itemname, 'poolsDev' ) end local html = {} local any_current = q.tablelength( chances ) > 0 local any_changes_upcoming = q.tablelength( devChances ) > 0 and q.compare_tables( chances, devChances ) local use_they = any_current and any_changes_upcoming

if any_current then table.insert( html, p.base2_sub( itemname, chances ) ) end if any_changes_upcoming then if p.items[itemname].preserve_case == nil or p.items[itemname].preserve_case ~= true then table.insert( html, p.current_frame:preprocess( p.dev ) .. q.lcfirst( p.base2_sub( itemname, devChances, use_they ) ) ) else table.insert( html, p.current_frame:preprocess( p.dev ) .. p.base2_sub( itemname, devChances, use_they ) ) end end

if args.nocat and args.nocat == false then else table.insert( html, '' ) if p.items[itemname].category ~= nil and p.items[itemname].category ~= false then table.insert( html, '' ) end end return table.concat( html, ' ' ) end

p.base2_sub = function( itemname, chances, use_they ) local html = {} local item_display_name = '' if use_they then item_display_name = 'they' else if p.items[itemname].plural ~= nil and p.items[itemname].plural ~= false then item_display_name = p.items[itemname].plural else if p.items[itemname].title ~= nil then item_display_name = p.items[itemname].title else item_display_name = string.gsub( itemname, '-', ' ' ) end if p.items[itemname].plural == nil or p.items[itemname].plural ~= false then item_display_name = q.single_item_plural( item_display_name ) end end if p.items[itemname].preserve_case == nil or p.items[itemname].preserve_case ~= true then item_display_name = q.capitalize( item_display_name ) end if p.items[itemname].note and p.notes[p.items[itemname].note] then item_display_name = item_display_name .. p.current_frame:preprocess( p.notes[p.items[itemname].note] ) end end table.insert( html, item_display_name ) table.insert( html, ' can be found ' )

local html_stacks = {} local stack_sep = ', ' local ns = q.tablelength( chances ) local s = 0

for stacksize, chest_details in pairs( chances ) do		s = s + 1 local html_per_stack = { 'in ' } local c = 0 local nc = q.tablelength( chest_details ) local sep = q.tern( nc > 2, ', ', ' ' ) if nc > 2 and s ~= ns then stack_sep = '; ' end for k, chest in pairs( chest_details ) do			c = c + 1 if c == nc and nc > 1 then table.insert( html_per_stack, 'and ' ) end if chest.chance == 1 then table.insert( html_per_stack, " all " ) else table.insert( html_per_stack, string.format("%.1f", chest.chance*100) ) table.insert( html_per_stack, "% of " ) end if chest.chest_type == 'minecart with chest' then table.insert( html_per_stack, ' chest minecarts in ' ) table.insert( html_per_stack, p.chests[chest.chest_name].link ) elseif chest.chest_type == 'dispenser' then table.insert( html_per_stack, ' dispensers in ' ) table.insert( html_per_stack, p.chests[chest.chest_name].link ) else table.insert( html_per_stack, p.chests[chest.chest_name].link ) table.insert( html_per_stack, ' chests' ) end table.insert( html_per_stack, sep ) end if nc > 2 then table.insert( html_per_stack, 'all ' ) end table.insert( html_per_stack, 'in ' ) if p.items[itemname].cannot_stack ~= nil then table.insert( html_per_stack, 'groups of ' ) else table.insert( html_per_stack, 'stacks of ' ) end table.insert( html_per_stack, stacksize ) table.insert( html_stacks, table.concat( html_per_stack ) ) end local stackwise_summaries = '' if #html_stacks == 1 then table.insert( html, html_stacks[1] ) else for i = 1, #html_stacks - 1 do			table.insert( html, html_stacks[ i ] ) table.insert( html, stack_sep ) end table.insert( html, 'and ' ) table.insert( html, html_stacks[#html_stacks] ) end table.insert( html, '.' ) return table.concat( html ) end

p.base2_test = function

items = {} for item_name, v in pairs( p.items ) do table.insert( items, p.base2{ item_name, nocat=true } .. '\n\n' ) end

table.sort( items ) return table.concat(items) end

q = {

tablelength = function(T) local count = 0 for _ in pairs(T) do count = count + 1 end return count end, single_item_find_values = function( itemname, key ) local chances = {}

for chest_name, chest in pairs( p.chests ) do			local poolchances = {} for k, pool in pairs( chest[key] or chest.pools or {} ) do				local poolitem = pool.items[itemname] if poolitem ~= nil then local stacksize = poolitem[1] if poolitem[1] ~= poolitem[2] then stacksize = stacksize .. "–" .. poolitem[2] end local itemweight = poolitem[3] local pool_total_item_weight = 0 for itemname, item in pairs(pool.items) do						pool_total_item_weight = pool_total_item_weight + item[3] end local chance = p.calc_chance_any_of_this_item_per_pool( 						pool.rolls[1], pool.rolls[2],						itemweight, pool_total_item_weight )

if poolchances[stacksize] == nil then poolchances[stacksize] = chance else poolchances[stacksize] = poolchances[stacksize] + (1 - poolchances[stacksize]) * chance end end end for stacksize, chance in pairs( poolchances ) do				if chances[stacksize] == nil then chances[stacksize] = {} end table.insert( chances[stacksize], { ["chance"]=chance, ["chest_name"]=chest_name, ["chest_type"]=( chest.chest_type or "chest" ) } ) end end

return chances end, single_item_plural = function( itemname ) if string.sub( itemname, -2 ) == 'ss' or string.sub( itemname, -2 ) == 'ch' or string.sub( itemname, -2 ) == 'sh' or string.sub( itemname, -1 ) == 's' then return itemname .. 'es' end return itemname .. 's'	end, massage_args = function( args )

-- find what columns to put local columns = {} for k, _arg in pairs(args) do			if p.columns[_arg] ~= nil then columns[_arg] = true end end if q.tablelength(columns) == 0 then for column_name, v in pairs(p.columns) do				columns[column_name] = true end end -- find what chests to show

local chests = {} for k, _arg in pairs(args) do			if p.chests[_arg] ~= nil then table.insert( chests, _arg ) elseif p.synonyms[_arg] ~= nil then table.insert( chests, p.synonyms[_arg] ) end if p.display_names[_arg] ~= nil then local chestname = _arg if p.chests[chestname] == nil then chestname = p.synonyms[_arg] end p.chests[chestname].display_name = p.display_names[_arg] end end if #chests == 0 then for chest_name, chest in pairs(p.chests) do				local chest_type = ( chest.chest_type or "chest" ) if chest_type == "chest" or chest_type == "minecart with chest" then table.insert( chests, chest_name ) end end end table.sort( chests ) return chests, columns end,

sort_items = function( e1, e2 ) if e1.chanceany ~= e2.chanceany then return ( e1.chanceany > e2.chanceany ) end if e1.avgamount ~= e2.avgamount then return ( e1.avgamount > e2.avgamount ) end if e1.material == nil then e1.material = 0 if string.find( e1.itemname, "leather" ) ~= nil then e1.material = 1 end if string.find( e1.itemname, "iron" ) ~= nil then e1.material = 2 end if string.find( e1.itemname, "gold" ) ~= nil then e1.material = 3 end if string.find( e1.itemname, "diamond" ) ~= nil then e1.material = 4 end e1.armor = 0 if string.find( e1.itemname, "helmet" ) ~= nil or string.find( e1.itemname, "cap" ) ~= nil then e1.armor = 1 end if string.find( e1.itemname, "chestplate" ) ~= nil or string.find( e1.itemname, "tunic" ) ~= nil then e1.armor = 2 end if string.find( e1.itemname, "leggings" ) ~= nil or string.find( e1.itemname, "pants" ) ~= nil then e1.armor = 3 end if string.find( e1.itemname, "boots" ) ~= nil then e1.armor = 4 end end if e2.material == nil then e2.material = 0 if string.find( e2.itemname, "leather" ) ~= nil then e2.material = 1 end if string.find( e2.itemname, "iron" ) ~= nil then e2.material = 2 end if string.find( e2.itemname, "gold" ) ~= nil then e2.material = 3 end if string.find( e2.itemname, "diamond" ) ~= nil then e2.material = 4 end e2.armor = 0 if string.find( e2.itemname, "helmet" ) ~= nil or string.find( e2.itemname, "cap" ) ~= nil then e2.armor = 1 end if string.find( e2.itemname, "chestplate" ) ~= nil or string.find( e2.itemname, "tunic" ) ~= nil then e2.armor = 2 end if string.find( e2.itemname, "leggings" ) ~= nil or string.find( e2.itemname, "pants" ) ~= nil then e2.armor = 3 end if string.find( e2.itemname, "boots" ) ~= nil then e2.armor = 4 end end if e1.material ~= e2.material then return ( e1.material < e2.material ) end if e1.armor ~= e2.armor then return ( e1.armor < e2.armor ) end return ( e1.itemname < e2.itemname ) end, fill_in_chest_derivative_data = function( chest_names )

for k, chest_name in pairs(chest_names) do			local chest = p.chests[chest_name] if chest == nil then break end

chest.allRolls = {} chest.itemData = {} for k, pool in pairs( chest.pools or {} ) do				table.insert( chest.allRolls, q.tern( pool.rolls[1] == pool.rolls[2], pool.rolls[1], pool.rolls[1]..'–'..pool.rolls[2] ) )

local total_weight = 0 for itemname, item in pairs(pool.items) do					total_weight = total_weight + item[3] end pool.totalweight = total_weight

q.fill_in_chest_item_details( chest.itemData, pool, #chest.allRolls ) end

chest.allRollsDev = {} chest.itemDataDev = {} for k, pool in pairs( chest.poolsDev or chest.pools or {} ) do				table.insert( chest.allRollsDev, q.tern( pool.rolls[1] == pool.rolls[2], pool.rolls[1], pool.rolls[1]..'–'..pool.rolls[2] ) )

local total_weight = 0 for itemname, item in pairs(pool.items) do					total_weight = total_weight + item[3] end pool.totalweight = total_weight

q.fill_in_chest_item_details( chest.itemDataDev, pool, #chest.allRollsDev ) end end end,

fill_in_chest_item_details = function( data, pool, ct ) for item_name, item in pairs(pool.items) do			if p.items[item_name] then local min_stacksize = item[1] local max_stacksize = item[2] local min_pool_rolls = pool.rolls[1] local max_pool_rolls = pool.rolls[2] local item_weight = item[3] if data[item_name] == nil then data[item_name] = { avgamount = 0, chanceany = 0, itemname = item_name, sortsize = {}, sortweight = {}, sizes = {}, weights = {}, }					for i = 1, ct-1 do						data[item_name].sortsize[i] = 0 data[item_name].sortweight[i] = 0 data[item_name].sizes[i] = '—' data[item_name].weights[i] = '—' end end

data[item_name].avgamount = data[item_name].avgamount + p.calc_average_amount_this_item_per_pool( 					min_stacksize, max_stacksize, 					min_pool_rolls, max_pool_rolls, 					item_weight, pool.totalweight ) data[item_name].chanceany = data[item_name].chanceany + (1 - data[item_name].chanceany) * p.calc_chance_any_of_this_item_per_pool(					min_pool_rolls, max_pool_rolls, 					item_weight, pool.totalweight )

data[item_name].sortsize[ct] = ( min_stacksize + max_stacksize ) / 2 data[item_name].sortweight[ct] = item_weight; data[item_name].sizes[ct] = q.tern( min_stacksize == max_stacksize, min_stacksize, min_stacksize .. '–' .. max_stacksize ) data[item_name].weights[ct] = p.current_frame:expandTemplate{ title = 'frac', args = { item_weight, pool.totalweight } } end end

for item_name, d in pairs(data) do			if not d.sizes[ct] then d.sortsize[ct] = 0 d.sortweight[ct] = 0 d.sizes[ct] = '—' d.weights[ct] = '—' end end end,

construct_ordered_items_from_first_chest = function( chest_names, suffix ) local items_from_first_table = {} local item_chests = {} local item_names_ordered = {} for item_name, item in pairs( p.chests[chest_names[1]]['itemData'..suffix] ) do			table.insert( items_from_first_table, item ) end table.sort( items_from_first_table, q.sort_items ) for k, item in pairs( items_from_first_table ) do			table.insert( item_names_ordered, item.itemname ) item_chests[item.itemname] = true end return item_names_ordered, item_chests end,

get_ordered_items_from_other_chests = function( chest_names, item_chests, suffix ) local items_not_from_first_table = {} for chest_idx = 2, #chest_names do			for item_name, item in pairs( p.chests[chest_names[chest_idx]]['itemData'..suffix] ) do				if item_chests[item_name] == nil then p.items[item_name].itemname = item_name table.insert( items_not_from_first_table, p.chests[chest_names[chest_idx]]['itemData'..suffix][item_name] ) item_chests[item_name] = true end end end

table.sort( items_not_from_first_table, q.sort_items ) return items_not_from_first_table end,

add_other_items_to_first_list = function( chest_names, item_names_ordered, item_chests, items_not_from_first_table ) for k, item in pairs( items_not_from_first_table ) do			table.insert( item_names_ordered, item.itemname ) end return item_names_ordered end,

set_up_ordered_item_rows = function( chest_names, item_names_ordered, suffix ) for k, itemname in pairs(item_names_ordered) do			item_names_ordered[k] = {itemname} for chest_idx = 1, #chest_names do				if suffix == 'Dev' or p.chests[chest_names[chest_idx]]['pools'..suffix] ~= nil then local item_data = p.chests[chest_names[chest_idx]]['itemData'..suffix][itemname] if item_data == nil then table.insert( item_names_ordered[k], false ) else table.insert( item_names_ordered[k], item_data ) end end end end

return item_names_ordered end,

construct_ordered_item_rows = function( chest_names, suffix ) -- for the first chest, sort its by chance desc, then by avg amount desc, then alphabetically asc local item_names_ordered, item_chests = q.construct_ordered_items_from_first_chest( chest_names, suffix ) if #chest_names > 1 then -- after that, sort all the remaining items in list order local items_not_from_first_table = q.get_ordered_items_from_other_chests( chest_names, item_chests, suffix ) item_names_ordered = q.add_other_items_to_first_list( chest_names, item_names_ordered, item_chests, items_not_from_first_table ) end

-- set up item_names_ordered so that each is a row, representing chest values item_names_ordered = q.set_up_ordered_item_rows( chest_names, item_names_ordered, suffix ) return item_names_ordered end,

print_table = function( chest_names, columns, ordered_item_rows, suffix )

local html = {} local use_roll_row = false local use_superheader = false local superheader_sizes = {} for i = 1, #chest_names do			sh = p.chests[chest_names[i]].superheader if sh ~= nil then if superheader_sizes[sh] == nil then superheader_sizes[sh] = 0 end superheader_sizes[sh] = superheader_sizes[sh] + 1 use_superheader = true end local allRolls = p.chests[chest_names[i]]['allRolls'..suffix] if #allRolls > 1 then use_roll_row = true end end if columns['stacksize'] == nil and columns['weight'] == nil then use_roll_row = false end local rowspan = ( 1 + q.tern( #chest_names > 1, 1, 0 ) + q.tern( use_superheader, 1, 0 ) ) local hide_col_description = rowspan > 1 and q.tablelength(columns) == 1 if use_roll_row then rowspan = rowspan + 1 end if q.tablelength(columns) == 1 then for column_name, v in pairs(columns) do				table.insert( html, "Values represent " ) table.insert( html, p.columns[column_name] ) table.insert( html, "\n" ) end end

if #chest_names == 1 then if q.tablelength(columns) == 1 then table.insert( html, " " ) end local chest_name = chest_names[1] local allRolls = p.chests[chest_name]['allRolls'..suffix] local chest_type = p.chests[chest_name].chest_type or "chest"

local display_name = p.chests[chest_name].display_name

chest_name = chest_name:gsub( "-", " " ) table.insert( html, "Each " ) table.insert( html, display_name or chest_name ) if chest_type ~= 'chest' and chest_type ~= 'minecart with chest' then table.insert( html, " contains " ) else table.insert( html, " chest contains " ) end if #allRolls == 1 then table.insert( html, allRolls[1] ) else table.insert( html, #allRolls ) table.insert( html, ' groups of ' ) local s = q.tern( #allRolls > 2, ', ', ' ' ) for i = 1, #allRolls-1 do					table.insert( html, allRolls[i] ) table.insert( html, s ) end table.insert( html, 'and ' ) table.insert( html, allRolls[#allRolls] ) end table.insert( html, " item stacks, with the following distribution: \n" ) end table.insert( html, ' \n' ) table.insert( html, " " ) return table.concat( html ) end, titlecase = function( str ) local buf = {} for word in string.gfind(str, "%S+") do			if word == "and" then table.insert( buf, word ) else local first, rest = string.sub( word, 1, 1 ), string.sub( word, 2 ) table.insert( buf, string.upper(first) .. string.lower(rest) ) end end return table.concat( buf, " " ) end, capitalize = function( str ) return ( string.lower(str):gsub( "^%l", string.upper ) ) end,

lcfirst = function( str ) return ( string.gsub( str, "^%u", string.lower ) ) end, tern = function( cond, T , F ) if cond then return T else return F end end,

compare_tables = function( a, b ) local seen = {} for k, v in pairs( a ) do			if type( v ) ~= type( b[k] ) then return true end if v ~= b[k] then return true end if type( v ) == 'table' and q.compare_tables( v, b[k] ) then return true end seen[k] = true end for k, v in pairs( b ) do			if not seen[k] then return true end end return false end, }

string.lpad = function(str, len, char) if char == nil then char = ' ' end return string.rep(char, len - #(''..str)) .. str end

return p