Module:YYSandbox
Appearance
local public = {}
local private = {}
-- Removes leading and trailing spaces from strings
function private.trimWhitespace(str)
local whitespace = { [" "]=true, ["\n"]=true, ["\r"]=true }
local _start = 1
while (whitespace[str:sub(_start, _start)]) do
_start = _start + 1
end
local _end = str:len()
while (whitespace[str:sub(_end, _end)]) do
_end = _end - 1
end
return str:sub(_start, _end)
end
-- Checks if a table has a specific key
function private.hasKey(_table, key)
return _table[key] ~= nil
end
-- Gets a specific item from a table, with a fallback if the table doesn't have that key
function private.getValue(_table, key, fallback)
if private.hasKey(_table, key) then
return _table[key]
else
return fallback
end
end
-- Processes a csv row into a table and returns it
function private.processCsv(csv)
local retval = {}
for arg in csv:gmatch("([^,]+)") do
table.insert(retval, private.trimWhitespace(arg))
end
return retval
end
-- Get the arguments from a frame
function private.parseArgs(frame)
if private.getValue(frame.args, "external_args", false) then
return frame:getParent().args
end
return frame.args
end
-- Converts a difficulty number into a format that handles sorting better for + difficulties
function public.SortableDifficulty(frame)
local args = private.parseArgs(frame)
if private.hasKey(args, 1) == false then
return ''
end
local diff = args[1]
if type(diff) == 'number' then
return diff
end
diff = private.trimWhitespace(diff)
if diff:sub(#diff, #diff) == '+' then
return tonumber(diff:sub(1, #diff - 1) .. '.5')
end
return diff
end
-- Converts a version number into a format that handles sorting better
function public.SortableVersion(frame)
local args = private.parseArgs(frame)
if private.hasKey(args, 1) == false then
return ''
end
local retval = ''
for vpart in args[1]:gmatch('[^.]+') do
while #vpart < 4 do
vpart = '0' .. vpart
end
retval = retval .. vpart
end
return retval
end
-- Produces World Mode Data: Lost/Breached Chapter maps
function public.WorldMapBeyond(frame)
local args = private.parseArgs(frame)
local reverse_map = (private.getValue(args, 'reverse', false) ~= false)
local incomplete = (private.getValue(args, 'incomplete', false) ~= false)
-- Put together rows here
local rows = {}
local total_rewards = {single = {}}
local table_id = ''
local i = 1
while args[i] do
local row = {
progress = args[i],
effect = args[i + 1],
reward = private.trimWhitespace(args[i + 2])
}
row.has_reward = (row.reward ~= '-')
if row.has_reward then
-- Adding reward to totals
local reward = row.reward:match('(%d+)%s-Fragment')
if reward then
total_rewards['Fragments'] = private.getValue(total_rewards, 'Fragments', 0) + tonumber(reward)
else
local reward_type = nil
reward_type, reward = row.reward:match('(.-)%s-×%s-(%d+)')
if reward_type then
total_rewards[reward_type] = private.getValue(total_rewards, reward_type, 0) + tonumber(reward)
else
total_rewards.single[#total_rewards.single + 1] = row.reward
end
end
end
rows[#rows + 1] = row
table_id = table_id .. tostring(i) .. tostring(args[i]) .. args[i + 1] .. args[i + 2]
i = i + 3
end
local total_health = ''
if reverse_map then
total_health = rows[1].progress
else
total_health = rows[#rows].progress
end
table_id = tostring(mw.hash.hashValue('sha256', table_id))
-- Stringify total_rewards
local total_rewards_str = '<ul>'
for _, r in ipairs(total_rewards.single) do
total_rewards_str = total_rewards_str .. '<li><b>' .. r .. '</b></li>'
end
for rt, rq in pairs(total_rewards) do
if rt ~= 'single' and rt ~= 'Fragments' and rt ~= 'Ether Drop' then
total_rewards_str = total_rewards_str .. '<li><b>' .. rt .. ' × ' .. tostring(rq) .. '</b></li>'
end
end
if type(total_rewards['Ether Drop']) ~= 'nil' then
total_rewards_str = total_rewards_str .. '<li><b>Ether Drop × ' .. tostring(total_rewards['Ether Drop']) .. '</b></li>'
end
if type(total_rewards['Fragments']) ~= 'nil' then
total_rewards_str = total_rewards_str .. '<li><b>' .. tostring(total_rewards['Fragments']) .. ' Fragments</b></li>'
end
if incomplete then
total_rewards_str = total_rewards_str .. '<li><b>???</b></li>'
end
total_rewards_str = total_rewards_str .. '</ul>'
local row_class = 'mw-collapsible'
if private.getValue(args, 'ForceNoCollapsed', false) == false then
row_class = row_class .. ' mw-collapsed'
end
-- Generate table
local retval = mw.html.create('table')
retval
:addClass('article-table')
:attr('cellspacing', 1)
:attr('cellpadding', 1)
:attr('width', '100%')
retval:tag('tr')
:tag('th')
:attr('scope', 'col')
:attr('width', '15%')
:wikitext('Progress')
:done()
:tag('th')
:attr('scope', 'col')
:attr('width', '50%')
:wikitext('Effect')
:done()
:tag('th')
:attr('scope', 'col')
:attr('width', '35%')
:wikitext('Reward<span id="mw-customcollapsible-' .. table_id .. '" class="mw-collapsible-toggle mw-collapsible mw-customtoggle-' .. table_id .. '">[<span class="link-text">Expand</span>]</span><span id="mw-customcollapsible-' .. table_id .. '" class="mw-collapsible-toggle mw-collapsible mw-collapsed mw-customtoggle-' .. table_id .. '">[<span class="link-text">Collapse</span>]</span></th>')
:done()
:done()
for i, row in ipairs(rows) do
local progress_str = row.progress
local reward_str = row.reward
if row.has_reward then
progress_str = '<b>' .. progress_str .. '</b>'
end
retval:tag('tr')
:attr('id', 'mw-customcollapsible-' .. table_id)
:addClass(row_class)
:tag('td')
:wikitext(progress_str)
:done()
:tag('td')
:wikitext(row.effect)
:done()
:tag('td')
:wikitext(reward_str)
:done()
:done()
end
retval:tag('tr')
:tag('td')
:wikitext('Total: ' .. tostring(total_health))
:done()
:tag('td')
:wikitext('-')
:done()
:tag('td')
:wikitext(total_rewards_str)
:done()
:done()
retval:allDone()
return tostring(retval)
end
function public.UpdateHistory(frame)
local args = private.parseArgs(frame)
local retval = mw.html.create('table')
retval
:addClass('wikitable')
:css('width', '100%')
:tag('tr')
:tag('th')
:css('width', '7pc')
:wikitext('Date (DD/MM/YYYY)')
:done()
:tag('th')
:css('width', '4pc')
:wikitext('Version')
:done()
:tag('th')
:wikitext('Update Information')
:done()
:done()
local i = 1
local version = ''
local version_c = 0
while args[i] do
local vtrim = private.trimWhitespace(args[i])
if #vtrim > 2 and vtrim:sub(1, 2) == 'v:' then
-- look for earliest sub-version date
local ii = i + 1
while args[ii] do
vtrim2 = private.trimWhitespace(args[ii])
if (#vtrim2 > 2 and vtrim2:sub(1, 2) == 'v:') then break end
ii = ii + 3
end
ii = ii - 3
local version_date = private.trimWhitespace(args[ii])
-- Version heading
version = vtrim:sub(3)
local collapsed_states = {'', ' mw-collapsed'}
if version_c == 0 then
collapsed_states = {' mw-collapsed', ''}
end
retval
:tag('tr')
:tag('th')
:attr('colspan', 3)
:wikitext('Version ' .. version .. '.x (' .. version_date .. ')<span id="mw-customcollapsible-' .. version .. '" class="mw-collapsible-toggle mw-collapsible' .. collapsed_states[1] .. ' mw-customtoggle-' .. version .. '">[<span class="link-text">Expand</span>]</span><span id="mw-customcollapsible-' .. version .. '" class="mw-collapsible-toggle mw-collapsible' .. collapsed_states[2] .. ' mw-customtoggle-' .. version .. '">[<span class="link-text">Collapse</span>]</span>')
:done()
:done()
version_c = version_c + 1
i = i + 1
else
-- Version
local classes = 'mw-collapsible'
if version_c > 1 then
classes = classes .. ' mw-collapsed'
end
local v = private.trimWhitespace(args[i + 1])
if #v > 2 and v:sub(1, 2) == 'm:' then
v = '\'\'v' .. v:sub(3) .. '\'\''
else
v = 'v' .. v
end
retval
:tag('tr')
:addClass(classes)
:attr('id', 'mw-customcollapsible-' .. version)
:tag('td')
:wikitext(args[i])
:done()
:tag('td')
:wikitext(v)
:done()
:tag('td')
:wikitext('\n' .. args[i + 2])
:done()
:done()
i = i + 3
end
end
retval:allDone()
return tostring(retval)
end
-- Produces World Mode Data maps
function public.WorldMap(frame)
local args = private.parseArgs(frame)
-- Put together rows here
local rows = {}
local total_steps = 0
local total_rewards = {single = {}}
local table_id = ''
local i = 1
local last_main_reward = 1
while args[i] do
local row = {
steps = args[i],
steps_to_reward = '?',
steps_to_mainreward = '?',
restrict = args[i + 1],
reward = private.trimWhitespace(args[i + 2])
}
total_steps = total_steps + row.steps
row.has_reward = (row.reward ~= '-')
local fragreward = row.reward:match('(%d+)%s-Fragment')
local etherreward = row.reward:match('Ether Drop%s-×%s-(%d+)')
row.has_mainreward = not (row.reward == '-' or fragreward or etherreward)
if row.has_mainreward then
last_main_reward = (i+2)/3
end
rows[#rows + 1] = row
table_id = table_id .. tostring(i) .. tostring(args[i]) .. args[i + 1] .. args[i + 2]
i = i + 3
end
for i, row in ipairs(rows) do
if row.has_reward then
-- Steps to reward calculation
local i2 = i
local str = 0
repeat
i2 = i2 - 1
rows[i2].steps_to_reward = str
str = str + rows[i2].steps
until (i2 == 1 or rows[i2].has_reward)
-- Adding reward to totals
local reward = row.reward:match('(%d+)%s-Fragment')
if reward then
total_rewards['Fragments'] = private.getValue(total_rewards, 'Fragments', 0) + tonumber(reward)
else
local reward_type = nil
reward_type, reward = row.reward:match('(.-)%s-×%s-(%d+)')
if reward_type then
total_rewards[reward_type] = private.getValue(total_rewards, reward_type, 0) + tonumber(reward)
else
total_rewards.single[#total_rewards.single + 1] = row.reward
end
end
end
-- Steps to main reward calculation
if row.has_mainreward then
local i2 = i
local str = 0
repeat
i2 = i2 - 1
rows[i2].steps_to_mainreward = str
str = str + rows[i2].steps
until (i2 == 1 or rows[i2].has_mainreward)
elseif (row.has_reward and i > last_main_reward) then
local i2 = i
local str = 0
repeat
i2 = i2 - 1
rows[i2].steps_to_mainreward = str
str = str + rows[i2].steps
until (i2 == 1 or rows[i2].has_reward)
end
end
rows[#rows].steps_to_reward = '-'
rows[#rows].steps_to_mainreward = '-'
local incomplete = (private.getValue(args, 'incomplete', false) ~= false)
local countallrewards = (private.getValue(args, 'countallrewards', false) ~= false)
table_id = tostring(mw.hash.hashValue('sha256', table_id))
-- Stringify total_rewards
local total_rewards_str = '<ul>'
for _, r in ipairs(total_rewards.single) do
total_rewards_str = total_rewards_str .. '<li><b>' .. r .. '</b></li>'
end
for rt, rq in pairs(total_rewards) do
if rt ~= 'single' and rt ~= 'Fragments' and rt ~= 'Ether Drop' then
total_rewards_str = total_rewards_str .. '<li><b>' .. rt .. ' × ' .. tostring(rq) .. '</b></li>'
end
end
if type(total_rewards['Ether Drop']) ~= 'nil' then
total_rewards_str = total_rewards_str .. '<li><b>Ether Drop × ' .. tostring(total_rewards['Ether Drop']) .. '</b></li>'
end
if type(total_rewards['Fragments']) ~= 'nil' then
total_rewards_str = total_rewards_str .. '<li><b>' .. tostring(total_rewards['Fragments']) .. ' Fragments</b></li>'
end
if incomplete then
total_rewards_str = total_rewards_str .. '<li><b>???</b></li>'
end
total_rewards_str = total_rewards_str .. '</ul>'
local row_class = 'mw-collapsible'
if private.getValue(args, 'ForceNoCollapsed', false) == false then
row_class = row_class .. ' mw-collapsed'
end
local retval = mw.html.create('table')
retval
:addClass('article-table')
:attr('cellspacing', 1)
:attr('cellpadding', 1)
:attr('width', '100%')
retval:tag('tr')
:tag('th')
:attr('scope', 'col')
:attr('width', '10%')
:wikitext('Tile')
:done()
:tag('th')
:attr('scope', 'col')
:attr('width', '15%')
:wikitext('Step (to next reward)')
:done()
:tag('th')
:attr('scope', 'col')
:attr('width', '45%')
:wikitext('Special tile')
:done()
:tag('th')
:attr('scope', 'col')
:attr('width', '30%')
:wikitext('Reward<span id="mw-customcollapsible-' .. table_id .. '" class="mw-collapsible-toggle mw-collapsible mw-customtoggle-' .. table_id .. '">[<span class="link-text">Expand</span>]</span><span id="mw-customcollapsible-' .. table_id .. '" class="mw-collapsible-toggle mw-collapsible mw-collapsed mw-customtoggle-' .. table_id .. '">[<span class="link-text">Collapse</span>]</span></th>')
:done()
:done()
for i, row in ipairs(rows) do
local stepstoreward_str = ''
local tile_str = tostring(i)
local reward_str = row.reward
if countallrewards then
stepstoreward_str = tostring(row.steps_to_reward)
else
stepstoreward_str = tostring(row.steps_to_mainreward)
end
if row.has_mainreward then
tile_str = '<b>' .. tile_str .. '</b>'
reward_str = '<b>' .. reward_str .. '</b>'
end
retval:tag('tr')
:attr('id', 'mw-customcollapsible-' .. table_id)
:addClass(row_class)
:tag('td')
:wikitext(tile_str)
:done()
:tag('td')
:wikitext(tostring(row.steps) .. ' (' .. stepstoreward_str .. ')')
:done()
:tag('td')
:wikitext(row.restrict)
:done()
:tag('td')
:wikitext(reward_str)
:done()
:done()
end
if incomplete then
retval:tag('tr')
:tag('td')
:wikitext('<b>Total: ' .. tostring(#rows - 1) .. '+?</b>')
:done()
:tag('td')
:wikitext('<b>(' .. tostring(total_steps) .. '+?</b>')
:done()
:tag('td')
:wikitext('-')
:done()
:tag('td')
:wikitext(total_rewards_str)
:done()
:done()
else
retval:tag('tr')
:tag('td')
:wikitext('<b>Total: ' .. tostring(#rows - 1) .. '</b>')
:done()
:tag('td')
:wikitext('<b>' .. tostring(total_steps) .. '</b>')
:done()
:tag('td')
:wikitext('-')
:done()
:tag('td')
:wikitext(total_rewards_str)
:done()
:done()
end
retval:allDone()
return tostring(retval)
end
return public