Module:Bundle

--[=[ -- LUA script to get Bundles -- --]=]

local p = {}

---[=[ For testing remove 1 '-' from start of line local bundleData = mw.loadData('Module:Bundle/data') --[==[]=] local bundleData = { ["Davy Jones Bundle"] = {2, ["B"] = "potc", ["R"] = "Informal Information Gathering", ["H"] = "Jack Sparrow#Captain Barbossa#Tia Dalma", ["D"] = {"2021/01/15", 0}, ["C"] = {"Davy Jones", "EC-Gems #100"}, }, } --]==] local cData = mw.loadData( 'Module:ItemCollection/data' )

local util = require('Module:Utility') local getCost = require("Module:MultiItems").getCost local EC = require("Module:EC").getEC local TOK = require("Module:CharacterToken").getTokenDirect local CHEST = require("Module:EnchantedChest").getChest local ICON = require("Module:CharacterAvatar").getAvatar local date = require("Dev:Date") local today = os.date("%Y/%m/%d %H:%M:%S")

local function oneItem(item, type, event) if not item then return "" end local tt = mw.text.split(item, "%s*#%s*") local iName = tt[1] or item local nCount = tt[2] or 0

local height = 65 local width = nil local catsize = 35

if type == 5 then height = 40 elseif type == 42 then height = 80 elseif type == 4 then height = 55 elseif type == 32 then height = 80 width = 140 elseif type == 3 then height = 80 width = 55 elseif type == 22 then height = 140 width = 100 elseif type == 2 then height = 140 width = 85 elseif type == 1 then height = 120 end

local tItem = {' ', , , '', ' '} if type == "C" and nCount ~= 0 then tItem[4] = ' x' .. nCount .. ' ' elseif nCount ~= 0 then tItem[4] = ' x' .. nCount .. ' '	end

local conv = { ["ch"] = "cp", ["cos"] = "cp", ["mb"] = "npc", ["tp"] = "npc", }

local iData = cData["Items"][iName] if iData == nil then iData = cData["Items"][iName:match("(.+)%-%d+$")] end

if item:match("Chests") and not iName:match("Wacky Lunch Chests") then if event and event[1]~="default" and item:match("Chests %#") then iName = iName .. "-" .. event[1]:upper .. (event[2]=="T" and " TC Event" or " Event") end if type == "N" then tItem[2] = CHEST({iName, "L", (nCount ~= "1")}) tItem[4] = '' else tItem[2] = CHEST({iName, ((width or height)-10)}) end elseif iData and iData[2] then if type == 5 then catsize = 25 elseif type == 4 or type == 3 then catsize = 30 elseif type == "C" then catsize = 32 elseif type == "H" then catsize = 25 height = 50 elseif type == 1 then catsize = 40 end

local fname = mw.ustring.gsub(mw.ustring.lower(iName), "[':\"%,%.*]", "")		fname = fname:gsub(" ", "_")		if iData[2] == "pf" then			fname = fname:gsub("_float$", "")		else			fname = fname:gsub("^([^%(]-)%/([^%(]-)$", "%1-%2")			fname = mw.ustring.gsub(fname, "^([^%(]-) *%(([^%(]-)%)$", "%1_%2")		end		if not cData["Items"][iName] and iName:match("^.+%-%d+$") then iName = iName:match("(.+)%-%d+$") end		local iDisp = iName:gsub("^([^%(]-)%/([^%(]-)$", "%2")

if type == "N" then tItem[2] = "" .. (iDisp or iName) .. "" tItem[4] = '' else tItem[2] = ""

if iData["C"] and cData["Categories"][iData["C"]] then local category = iData["C"]

if type == "C" or type == "H" then tItem[3] = ' ' else tItem[3] = ' ' end end

if type == "H" then tItem[2] = " " tItem[4] = " " .. (iDisp or iName) .. " " end end elseif item:match("^EC") then if type == 3 then height = 50 end if type == "N" then tItem[2] = EC({iName, "L", S=(nCount == "1")}) tItem[4] = '' else tItem[2] = EC({iName, nil, nil, "F", (width or height)}) end else if type == "N" then tItem[2] = TOK(iName, "L") if nCount ~= "1" then tItem[3] = "s" end tItem[4] = '' else tItem[2] = TOK(iName, (width or height)) end end

if type == "C" then tItem[2] = ' ' .. tItem[2] .. ' '	end

return table.concat(tItem) end

local function tableBundle(tNumb, cData, event) local tOut = {' ' end

local function getRequ(bRequ, bEvent, bUnlockDate, CardFormat) local tOut = {""}

if not bRequ and bEvent[2]~="" and bUnlockDate <= "2016/09/10" then bRequ = "Mickey's Fun Wheel" elseif not bRequ and bEvent[2]~="" and bUnlockDate <= "2016/11/10" then bRequ = "California Screamin'" elseif not bRequ and bEvent[2]~="" and bUnlockDate <= "2021/01/10" then bRequ = "Mickey Mouse/Pirate" elseif not bRequ and bEvent[2]~="" then bRequ = "Discovery Rewards #6" end

if bRequ then if CardFormat then table.insert(tOut, " ''(") end		table.insert(tOut, "Requires ")		if bEvent[2]~="" and bRequ:match("-" .. (bEvent[2]=="T" and "TTC" or bEvent[1]:upper)) then			table.insert(tOut, "")			bRequ = mw.ustring.gsub(bRequ, "-" .. (bEvent[2]=="T" and "TTC" or bEvent[1]:upper), "")			table.insert(tOut, bRequ)			table.insert(tOut, "")		elseif bRequ:match("^.+ %#%d$") then      			local bItm, bLvl = bRequ:match("^(.+) %#(%d)$")			table.insert(tOut, "")			table.insert(tOut, bItm)			table.insert(tOut, " (Level ")			table.insert(tOut, bLvl)			table.insert(tOut, ")")			table.insert(tOut, "")		elseif bRequ=="Chain Offer" then			table.insert(tOut, "the previous reward in the sequence")		else			table.insert(tOut, "")			table.insert(tOut, bRequ)			table.insert(tOut, "")		end		if CardFormat then table.insert(tOut, " to unlock this bundle)'' ") end end

return table.concat(tOut) end

local function oneCard(bName, bData) local bname = bName:gsub(" ", "_") local event = {(bData["B"] or "default"), ""} if bData["E"] then event = mw.text.split(bData["E"], "%s*%$%s*") event[1] = event[1]:lower end

local tOut = {	'{| class="bundlecard ', (event[2]=="T" and "ttc" or event[1]), '"', '\n| class="Part_1"| ', '\n| class="Part_2"|', "", '', '\n|-\n| colspan="2" class="Part_3"|', tableBundle(bData[1], bData["C"], event), '\n|-\n| colspan="2" class="Part_4"| ', (bData["N"] or bName), ' ', ' ', ('Limit: ' .. (bData["L"] or 1) .. '/' .. (bData["L"] or 1) .. ' '), "", '\n|-\n| colspan="2" class="Part_5"| ', '\n|}\n' }

if bData["E"] and bData["H"] then tOut[8] = 'Helps with Event Helps with Characters' elseif bData["E"] and bData["R"] then tOut[8] = 'Helps with Event (Need Requirements)' elseif bData["H"] and bData["R"] then tOut[8] = 'Helps with Characters (Need Requirements)' elseif bData["E"] then tOut[8] = 'Helps with Event' elseif bData["H"] then tOut[8] = 'Helps with Characters' elseif bData["R"] then tOut[8] = '(Need Requirements)' end

if bData["L"] and bData["L"] == 0 then tOut[16] = "" end

if bData["G"] then tOut[15] = ' ' tOut[17] = tOut[17] .. ' '	end

if tonumber(bData["D"][2]) then local UnlockDate = bData["D"][1] .. util.dayStart local LockDate = date(bData["D"][1]):adddays(bData["D"][2]):fmt("%Y/%m/%d") .. (bData["D"][3] or util.dayStart) if today <= UnlockDate then return "" elseif bData["D"][2] == 0 then tOut[19] = "Permanent Content" elseif today <= LockDate then tOut[19] = util.countdown(LockDate, " for ", " until ", true) elseif today > LockDate then tOut[19] = util.strDate(bData["D"][1], bData["D"][2]) end else tOut[19] = bData["D"][2] end

table.insert(tOut, '{| class="bundle-content mw-collapsible mw-collapsed" id="mw-customcollapsible-')	table.insert(tOut, bname)	table.insert(tOut, '"\n! id="')	table.insert(tOut, bName)	table.insert(tOut, '" colspan="10"| Contents  ') table.insert(tOut, getRequ(bData["R"], event, bData["D"][1], true)) table.insert(tOut, '\n|-')

local iIcon = "" local iName = "" for _, v in pairs(bData["C"]) do iIcon = '\n|' .. oneItem(v, "C", event) .. iIcon iName = '\n| ' .. oneItem(v, "N", event) .. ' ' .. iName end table.insert(tOut, iIcon)

if bData["H"] then table.insert(tOut, '\n| rowspan="2" style="vertical-align: top; border: 4px solid #f5b90c; border-radius: 23px; width: 1%; padding: 0;"| ') end

table.insert(tOut, '\n|-') table.insert(tOut, iName)

if bData["U"] then tOut[14] = ' (' .. ICON({bData["U"], "B", 30}) .. ') ' table.insert(tOut, '\n|-\n| colspan="10" style="height: 2px; padding: 5px; border: 2px solid #31afff; border-radius: 15px;color: #31afff;"|' .. ICON({bData["U"], "B", 30}) .. ': Purchasing this bundle unlocks ' .. bData["U"] .. '') end

table.insert(tOut, '\n|}\n')

return table.concat(tOut) end

local function oneChainOffer(bName, bData) local bname = bName:gsub(" ", "_") local cname = bName:match("(.*)%d$") local event = {(bData["B"] or "default"), ""} if bData["E"] then event = mw.text.split(bData["E"], "%s*%$%s*") event[1] = event[1]:lower end

local tOut = {	'{| class="chainoffer ', "default", 2, '"', '\n| class="Part_1"| ', '\n| class="Part_2"|', bName, '/', bData[1], '', '\n|-\n| colspan="2" class="Part_3"| ', '\n|-\n| colspan="2" class="Part_4"| ', (bData["N"] or bName), ' ', ('Limit: ' .. (bData["L"] or 1) .. '/' .. (bData["L"] or 1) .. ' '), ' ', "", '\n|-\n| colspan="2" class="Part_5"| ', '\n|}\n' }

if bData["CO"][1] == "" then tOut[3] = 1 tOut[14] = ' ' .. oneItem(bData["C"][1], 1, event) .. ' '	else tOut[14] = ' ' .. oneItem(bData["C"][1], 1, event) .. ' ' .. oneItem(bData["CO"][1], 4, event) .. ' '	end

if bData["G"] then tOut[21] = ' ' end

if tonumber(bData["D"][2]) then local UnlockDate = bData["D"][1] .. util.dayStart local LockDate = date(bData["D"][1]):adddays(bData["D"][2]):fmt("%Y/%m/%d") .. (bData["D"][3] or util.dayStart) if today <= UnlockDate then return "" elseif bData["D"][2] == 0 then tOut[23] = "Permanent Content" elseif today <= LockDate then tOut[23] = util.countdown(LockDate, " for ", " until ", true) elseif today > LockDate then tOut[23] = util.strDate(bData["D"][1], bData["D"][2]) end else tOut[23] = bData["D"][2] end

table.insert(tOut, '{| class="bundle-content mw-collapsible mw-collapsed" id="mw-customcollapsible-')	table.insert(tOut, bname)	table.insert(tOut, '"\n! id="')	table.insert(tOut, bName)	table.insert(tOut, '" colspan="10"| Contents  ') table.insert(tOut, getRequ("Chain Offer", {"", ""}, bData["D"][1], true)) table.insert(tOut, '\n|-')

local iIcon = "" local iName = "" local iCost = "" for i = 1, bData[1], 1 do data = (bData["coData"] and bData["coData"][i] or bundleData[cname .. i]) if data then iIcon = iIcon .. '\n|' .. oneItem(data["C"][1], "C", event) iName = iName .. '\n| ' .. oneItem(data["C"][1], "N", event) .. ' '			iCost = iCost .. '\n| style="height: 10px !important;"|' .. ' '		end end table.insert(tOut, '\n|-') table.insert(tOut, iIcon) table.insert(tOut, '\n|-') table.insert(tOut, iName) table.insert(tOut, '\n|-') table.insert(tOut, iCost) table.insert(tOut, '\n|}\n')

return table.concat(tOut) end

function p.getBundle(frame) local tArgs = util.getArgs(frame) if not tArgs[2] then return "" end local tt = mw.text.split(tArgs[2], "%s*$%s*")

local bContent = {} local bHelp = nil local bLim = nil local bReq = nil local bCost = nil

local bName, bNumb, bType = mw.ustring.match(tt[2], "^([^,]-)%s*#%s*(%d+)%s*-*%s*([^,]*)$") if not bName then bName, bType = mw.ustring.match(tt[2], "^([^,]-)%s*#%s*(%d+)$") end

if not bName then bName = "?" end if not bNumb then bNumb = 1 else bNumb = tonumber(bNumb) end if not bType or bType == "" then bType = tArgs[1] end

if bNumb == 1 then bContent = {tt[3]} if tt[4] and tonumber(tt[4]) then bLim = tonumber(tt[4]) elseif tt[4] and tt[4] ~= "" then bHelp = tt[4] end if tt[5] and tt[5] ~= "" then bReq = tt[5] end if tt[6] and tt[6]:match("^EC") then bCost = tt[6] end elseif bNumb == 2 then bContent = {tt[3], tt[4]} if tt[5] and tonumber(tt[5]) then bLim = tonumber(tt[5]) elseif tt[5] and tt[5] ~= "" then bHelp = tt[5] end if tt[6] and tt[6] ~= "" then bReq = tt[6] end if tt[7] and tt[7]:match("^EC") then bCost = tt[7] end elseif bNumb == 3 or bNumb == 32 or bNumb == 33 then bContent = {tt[3], tt[4], tt[5]} if tt[6] and tonumber(tt[6]) then bLim = tonumber(tt[6]) elseif tt[6] and tt[6] ~= "" then bHelp = tt[6] end if tt[7] and tt[7] ~= "" then bReq = tt[7] end if tt[8] and tt[8]:match("^EC") then bCost = tt[8] end elseif bNumb == 4 or bNumb == 42 then bContent = {tt[3], tt[4], tt[5], tt[6]} if tt[7] and tonumber(tt[7]) then bLim = tonumber(tt[7]) elseif tt[7] and tt[7] ~= "" then bHelp = tt[7] end if tt[8] and tt[8] ~= "" then bReq = tt[8] end if tt[9] and tt[9]:match("^EC") then bCost = tt[9] end elseif bNumb == 5 or bNumb == 52 then bContent = {tt[3], tt[4], tt[5], tt[6], tt[7]} if tt[8] and tonumber(tt[8]) then bLim = tonumber(tt[8]) elseif tt[8] and tt[8] ~= "" then bHelp = tt[8] end if tt[9] and tt[9] ~= "" then bReq = tt[9] end if tt[10] and tt[10]:match("^EC") then bCost = tt[10] end elseif bNumb == 6 then bContent = {tt[3], tt[4], tt[5], tt[6], tt[7], tt[8]} if tt[9] and tonumber(tt[9]) then bLim = tonumber(tt[9]) elseif tt[9] and tt[9] ~= "" then bHelp = tt[9] end if tt[10] and tt[10] ~= "" then bReq = tt[10] end if tt[11] and tt[11]:match("^EC") then bCost = tt[11] end end

local bDur1, bDur2 = mw.ustring.match(tt[1], "^([^,]-)%s*#%s*(%d+)$") if not bDur1 then bDur1 = "2016/01/01" bDur2 = tt[1] end

return oneCard(bName, {bNumb, E=(tArgs[3] and bType or nil), B=bType, L=bLim, R=bReq, G=bCost, H=bHelp, D={bDur1, bDur2}, C=bContent}) end

function p.getChainOffer(frame) local tArgs = util.getArgs(frame) if not tArgs[2] then return "" end local tt = mw.text.split(tArgs[2], "%s*$%s*")

local bCost = nil

local bName, bNumb, bType = mw.ustring.match(tt[2], "^([^,]-)%s*#%s*(%d+)%s*-*%s*([^,]*)$") if not bName then bName, bType = mw.ustring.match(tt[2], "^([^,]-)%s*#%s*(%d+)$") end

if not bName then bName = "?" end if not bNumb then bNumb = 1 else bNumb = tonumber(bNumb) end if not bType or bType == "" then bType = tArgs[1] end

local bDur1, bDur2 = mw.ustring.match(tt[1], "^([^,]-)%s*#%s*(%d+)$") if not bDur1 then bDur1 = "2016/01/01" bDur2 = tt[1] end

return oneChainOffer(bName, {bNumb, E=(tArgs[3] and bType or nil), B=bType, N=tt[3], G=tt[6], D={bDur1, bDur2}, C={tt[4]}, CO={tt[5]}, coData=tArgs[4]}) end

function p.getList local cOut = {"===Chain Offers===\n", 'Click on the label icon to display all the contents of each chain offer! \n'} local bOut = {"===Bundles===\n", '<center style="color: #2faff1; border: 3px dashed #2faff1; padding: 5px; margin: 10px;">Click on the question mark icon to display all the contents of each bundle! \n'} local allChains = {} local allBundles = {} for bName, bData in pairs(bundleData) do local UnlockDate = bData["D"][1] .. util.dayStart local LockDate = date(bData["D"][1]):adddays(bData["D"][2]):fmt("%Y/%m/%d") .. (bData["D"][3] or util.dayStart) if (UnlockDate < today) and (LockDate > today) then if bData["CO"] then table.insert(allChains, {bName, bData}) else table.insert(allBundles, {bName, bData}) end elseif (UnlockDate < today) and (bData["D"][2] == 0) then if bData["CO"] then table.insert(allChains, {bName, bData}) else table.insert(allBundles, {bName, bData}) end end end

table.sort(allChains, function(a,b)			if a[2]["D"][1] == b[2]["D"][1] then				return a[1] < b[1]			else				return a[2]["D"][1] > b[2]["D"][1]			end		end)

table.sort(allBundles, function(a,b)			if a[2]["D"][1] == b[2]["D"][1] then				return a[1] < b[1]			else				return a[2]["D"][1] > b[2]["D"][1]			end		end)

for _, cItem in pairs(allChains) do		table.insert(cOut, oneChainOffer(cItem[1], cItem[2])) end

for _, cItem in pairs(allBundles) do		table.insert(bOut, oneCard(cItem[1], cItem[2])) end

return table.concat(cOut) .. table.concat(bOut) end

function p.getTokenFormat(tOut, name) local pagename = name or mw.title.getCurrentTitle.text local tBundles = {}

for bName, bData in pairs(bundleData) do local UnlockDate = bData["D"][1] .. util.dayStart local LockDate = date(bData["D"][1]):adddays(bData["D"][2]):fmt("%Y/%m/%d") .. (bData["D"][3] or util.dayStart) if (UnlockDate < today) and ((LockDate > today) or (bData["D"][2] == 0)) then for _, item in pairs(bData["C"]) do				local tt = mw.text.split(item, "%s*#%s*") local iName = tt[1] or item

if iName:match("^EC") then iName = EC({iName, "T"}) elseif not category and not cData.Items[iName] then iName = TOK(iName, "T") end

if pagename == iName then local event = {(bData["B"] or "default"), ""} if bData["E"] then event = mw.text.split(bData["E"], "%s*%$%s*") event[1] = event[1]:lower end table.insert(tBundles, {bName, (bData["N"] or bName), (tt[2] or "1"), (bData["G"] or ""), getRequ(bData["R"], event, bData["D"][1]), (bData["D"][2]~=0 and LockDate or "")}) end end end end

for k, v in pairs(tBundles) do tOut["Bundle Shop-" .. k] = v[1] .. "$" .. v[2] .. "$x" .. v[3] .. "$$" .. v[4] .. "$" .. v[5] .. "$" .. v[6] end

return tOut end

return p