Module:Sandbox/MonkeysHK

local getArgs = require('Module:Arguments').getArgs local loader = require('Module:Loader')

local string, table, yesno, uiText = loader.require('String', 'Table', 'Yesno', 'UIText') local collectionData, armorSets, tooltips = loader.loadData('Collection/Data', 'Armor/Sets', 'Inventory slot/Aliases')

local p = {}

local recipeAliases = { ['r'] = 'recipe', ['recipe'] = 'recipe', ['recipes'] = 'recipes', ['rs'] = 'recipes', ['rec'] = 'recipe', ['recs'] = 'recipes', ['recip'] = 'recipe', ['recips'] = 'recipes', ['res'] = 'recipes', ['re'] = 'recipe', ['up'] = 'upgrade', ['upg'] = 'upgrade', ['u'] = 'upgrade', ['upgr'] = 'upgrade', ['upgra'] = 'upgrade', ['upgrad'] = 'upgrade', ['upgrade'] = 'upgrade', }

-- first row positions for Collection UI local firstRowPositions = { --1 { {3, 5} },	--2 { {3, 4}, {3, 6} },	--3 { {3, 4}, {3, 5}, {3, 6} },	--4 { {3, 3}, {3, 4}, {3, 6}, {3, 7} },	--5 { {3, 3}, {3, 4}, {3, 5}, {3, 6}, {3, 7} },	--6 { {3, 2}, {3, 3}, {3, 4}, {3, 6}, {3, 7}, {3, 8} },	--7 { {3, 2}, {3, 3}, {3, 4}, {3, 5}, {3, 6}, {3, 7}, {3, 8} },	--8 { {3, 1}, {3, 2}, {3, 3}, {3, 4}, {3, 6}, {3, 7}, {3, 8}, {3, 9} }, }

-- X/Y positions entries for slot amounts 1-9 in Collection Rewards UI local rewardUIPositions = { -- 1 { {3, 5} },	-- 2 { {3, 4}, {3, 6} },	-- 3 { {3, 3}, {3, 5}, {3, 7} },	-- 4 { {3, 2}, {3, 4}, {3, 6}, {3, 8} },	-- 5 { {2, 2}, {2, 4}, {2, 6}, {2, 8}, {4, 5}, },	-- 6 { {2, 2}, {2, 4}, {2, 6}, {2, 8}, {5, 4}, {5, 6}, },	-- 7 { {2, 2}, {2, 4}, {2, 6}, {2, 8}, {3, 3}, {3, 5}, {3, 7}, },	-- 8 { {2, 2}, {2, 4}, {2, 6}, {2, 8}, {4, 2}, {4, 4}, {4, 6}, {4, 8}, },	-- 9 { {2, 4}, {2, 5}, {2, 6}, {3, 4}, {3, 5}, {3, 6}, {4, 4}, {4, 5}, {4, 6}, },	--10 { {2, 4}, {2, 5}, {2, 6}, {2, 7}, {3, 4}, {3, 5}, {3, 6}, {4, 4}, {4, 5}, {4, 6}, },	--11 { {2, 3}, {2, 4}, {2, 5}, {2, 6}, {2, 7}, {3, 4}, {3, 5}, {3, 6}, {4, 4}, {4, 5}, {4, 6}, }, }

local numToEng = { 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty', 'twenty-one', 'twenty-two', 'twenty-three', 'twenty-four', 'twenty-five', 'twenty-six', 'twenty-seven' }

local function makeUI(params) return mw.getCurrentFrame:expandTemplate{ title = 'UI', args = params } end

- -- Template: Collection UI -- -- Creates a main collection UI for a given item - function p.collectionUI(frame) return p._collectionUI(table.deepCopy(getArgs(frame))) end

- -- _collectionUI Helper functions - -- 1/3 local variateStart = { -- { regex to match, subst } { '[Ee]xperience', '&8+' }, } -- 2/3 local function specialCaseColors(s) local matches = { ['[Mm]inion'] = 'blue', -- ['Enchanted Book'] = 'blue', ['[Uu]pgrade'] = 'green', ['[Cc]oming [Ss]oon'] = 'red', }

for k, v in pairs(matches) do		if s:match(k) then return uiText.getColorCode(v) end end if tonumber(s) then return uiText.getColorCode('dark_aqua') end end -- 3/3 local variateEnd = { -- { regex to match, subst } { {'[Nn]one', '[Uu]pgrade'}, '' }, { '[Cc][Oo][Mm][Ii][Nn][Gg] [Ss][Oo][Oo][Nn]', ' &8(&4COMING SOON&8)' }, { '[Dd]warven [Ff]orge [Rr]ecipe', ' &6Dwarven Forge Recipe' }, { '[Mm]inion', ' &rRecipes' } }

local function getStartEnd(_type, expressions) for _,v in ipairs(expressions) do		for _,_exp in ipairs(type(v[1]) == 'table' and v[1] or {v[1]}) do			if not not _type:match(_exp) then return v[2] end end end end

local function explode(data) local ret = {} for _, v in ipairs(data.reward) do		if armorSets[v] then for _, w in ipairs(armorSets[v]) do				local t = table.deepCopy(v) t[1] = w				table.push(ret, t)			end else table.push(ret, v)		end end return ret end

local function parseCollectionData(tb, rewards, collection) rewards = explode(rewards) local rows, total, frp = 1, #rewards, firstRowPositions[total] local function calcXY(i) local x, y		if frp then local pos = frp[i] x, y = pos[1], pos[2] else local x = 2 + rows local y = i % 9 y = y == 0 and 9 or y		end end for i, v in ipairs(rewards) do		if i > 27 then break end -- Processes upwards of 3 rows of rewards -- calculate X, Y		local x, y = calcXY(i) -- advance row if i % 9 == 0 and i > 0 then rows = rows + 1 end ui:setSlot(x, y, {			(i == 1 and 'Yellow Stained Glass Pane,' or 'Red Stained Glass Pane,') .. i,			link = 'none',			title = table.concat{ i == 1 and '&e' or '&c', collection, ' ', string._toRoman(i) },			class = v._goto and 'goto-'..v._goto,			text = formatUIText(string.dedent			&7Progress: &e0&6%%			&f%s &e0&6\/&e%s&7			%s:			%s			&eClick to view rewards!			):format( ('-'):rep(20), string._formatShortNum(string._toNumber(v.amount)), #v > 1 and '&7Rewards' or '&7Reward', table.concat(table.map(v, function(val) local s = val[1] local start_ = val.type and getStartEnd(val.type, variateStart) local end_ = val.type and getStartEnd(val.type, variateEnd) return table.concat{ start_ or '', -- 1/3 val.rarity..s, -- 2/3 end_ or ' &r'..(val.type or '&rRecipe'), -- 3/3 }				end), '/') )		})		--		table.concat(table.map(v, function(val)			local s = val[1]			local start_ = val.type and getStartEnd(val.type, variateStart)			local end_ = val.type and getStartEnd(val.type, variateEnd)			return table.concat{ 				start_ or '', -- 1/3				val.rarity..s, -- 2/3				end_ or ' &r'..(val.type or '&rRecipe'), -- 3/3			}		end), '/') local rewardStr local text = ('/&7Progress: &e0&6%%/&f%s &e0&6\/&e%s&7//&7%s:/%s//&eClick to view rewards!'):format(			('-'):rep(20),			string._formatShortNum(string._toNumber(v.required)),			#v > 1 and 'Rewards' or 'Reward',			rewardStr		) tb[('%s, %s'):format(x, y)] = ('%s; %s, %s-%s; none, %s, %s'):format(			i == 1 and 'Yellow Stained Glass Pane,' or 'Red Stained Glass Pane,', i,			collection, numToEng[i],			title, text		) end end

local function parseTextList(s) -- TODO: Restructure text list into a table like Collection/Data local rewards = {} local count = 0 local function g(s) return s and s:gsub('\255', ',') or nil end for i, v in ipairs(string.split((s:gsub('\\,', '\255')), '\n')) do		local _type v = string.methods(v):_trim if v:getValue ~= '' then if v:charAt(1) == '*' then _type = v:charAt(2) == '*' and 'item' or 'amount' end if _type == 'amount' then -- * amount[, goto] local amount, _goto = unpack(string.split(v:sub(2), "%s*,%s*")) count = count + 1 rewards[count] = {} rewards[count].amount = g(amount) rewards[count]._goto = g(_goto and _goto:gsub('^goto%-', '') or nil) elseif _type == 'item' then -- ** reward[, type][, rarity] local item, type, rarity = unpack(string.split(v:sub(3), '%s*,%s*')) item = g(item or v:sub(3)) rarity = g((rarity and rarity ~= '') and uiText.getFormatting(rarity) or nil) local tooltip = tooltips[item] local tooltipRarity = g(tooltip and tooltip.title and tooltip.title:match('^&([a-z0-9])') or nil) table.push(rewards[count], {					item, 					rarity = '&' .. (rarity or tooltipRarity or specialCaseColors(item) or 'f'),					type = (type and type ~= "") and string.ucfirst(recipeAliases[type:lower] or type)				}) end end end return rewards end

function p._collectionUI(args) checkType(1, args, { 'table' }) assertTrue(args[1], 'No collection specified', 2) local collection = args[1] and args[1]:gsub('[Ee][Nn][Cc][Hh][Aa]?[Nn]?[Tt]?[Ee]?[Dd]? ?', ):gsub('[Bb][Ll][Oo][Cc][Kk] ?[Oo]?[Ff]? ?', ) local dt = collectionData(collection) if not dt then assertTrue(args[2], 'No collection rewards specified', 2) dt = table.deepCopy(parseTextList(args[2]), true) end local title = mw.title.getCurrentTitle local tb = { collection and collection .. ' Collection' or title.rootText, ['1, 5'] = ('%s, none; none, &e%s Collection, &7View all your %s Collection/&7progress and rewards!//&7Total Collected: &e0'):format(			args.title or collection,			collection,			collection		), id = args['id'], return_text = args['return_text'] or args['goback'], return_link = (args['return_text'] or args['goback']) and (args['return_text'] or args['goback']):gsub('%s*[Cc]ollection', ''), return_id = args['return_id'], hide = args['hide'], }	parseCollectionData(tb, dt, collection) -- pipeline(ui, table.dump, 0, error) return (tostring(ui):gsub('\\(.)', '%1'):gsub('\255', ',')) end

- -- Template: Collection Rewards UI -- -- Creates a collection Rewards UI. - function p.collectionRewardsUI(frame) local args = getArgs(frame) return p._collectionRewardsUI(table.deepCopy(args)) end - -- function: _collectionRewardsUI(args) -- -- Invoked by - function p._collectionRewardsUI(args) checkType(1, args, { 'table' }) local collection = args[1] and args[1]:gsub('[Ee][Nn][Cc][Hh][Aa]?[Nn]?[Tt]?[Ee]?[Dd]? ?', ):gsub('[Bb][Ll][Oo][Cc][Kk] ?[Oo]?[Ff]? ?', ) local ui = createBlankUI(collection .. ' ' .. string._toRoman(args[2] or 1) .. ' Rewards', args['id'], {		text = collection..' Collection',		link = args['return_text'] and args['return_text']:gsub('%s*[Cc]ollection', ''),		id = args['return_id'],	}, args['hide']) local rewards = {} local items = table.filter(string.split(args[3], '\n'), function(v)		return string.trim(v) ~= ''	end) local amount = #items for i, line in ipairs(items) do		local item, id, title, desc = pipeline(line, string.trim, 2, string.sub, '%s*,%s*', string.unpackedSplit) local tooltip = tooltips[item] local itemText = desc or (tooltip and tooltip.text) local itemTitle = title or (tooltip and tooltip.title) local function addItem(x, y)			ui:setSlot(x, y, {				item, text=itemText and itemText..'//&eClick to view recipe!', 				title=itemTitle, class= id and 'goto-'..id:gsub('^goto%-', ),				link= id and 'none' or 			}) end addItem(unpack(rewardUIPositions[amount][i])) end return tostring(ui) end

return p