Module:Rotations/Shattered Worlds
Jump to navigation
Jump to search
Module documentation
This documentation is transcluded from Module:Rotations/Shattered Worlds/doc. [edit] [history] [purge]
This module does not have any documentation. Please consider adding documentation at Module:Rotations/Shattered Worlds/doc. [edit]
Module:Rotations/Shattered Worlds's function future is invoked by Template:Shattered Worlds future challenges.
Module:Rotations/Shattered Worlds's function today is invoked by Template:Shattered Worlds current challenges.
Module:Rotations/Shattered Worlds requires Module:Array.
Module:Rotations/Shattered Worlds requires Module:Purge.
Module:Rotations/Shattered Worlds requires Module:Rotations.
Module:Rotations/Shattered Worlds requires Module:Rotations/RsRandom.
Module:Rotations/Shattered Worlds requires Module:Rotations/Shattered Worlds/data.
| Function list |
|---|
| L 28 — wednesday L 32 — getDates L 37 — p.get L 42 — getSlots L 52 — p.api L 56 — p._api L 92 — makeFullRow L 133 — p.today L 138 — p._today L 170 — makeShortRow L 225 — p.future L 232 — p._future L 240 — parseOffsetsToString L 302 — p.listItems L 356 — p.nextItem L 368 — p._nextItem L 442 — check_count |
--[=[
-- Rotation of the [[Shattered Worlds]] weekly challenges
--]=]
local p = {}
local rotations = require('Module:Rotations')
local rsrandom = require('Module:Rotations/RsRandom')
local purge = require('Module:Purge')._purge
local removeDuplicates = require('Module:Array').unique
local lang = mw.getContentLanguage()
local SECS_IN_DAY = 60 * 60 * 24
local challenges;
local mutators;
do
local _data = require( "Module:Rotations/Shattered Worlds/data" );
challenges = _data.challenges;
mutators = _data.mutators;
end
local rewards = {
['Bronze'] = '250,000',
['Silver'] = '1,000,000',
['Gold'] = '7,500,000'
}
function wednesday(runedate)
return math.floor(runedate/7)*7
end
local function getDates( rot_index )
local stock_date = os.date( "[[%d %B]] [[%Y]]", os.time() + rot_index * SECS_IN_DAY * 7 ):gsub( "%[0", "[" )
return {day_diff = day_diff, rot_index = rot_index, stock_date = stock_date}
end
function p.get(runedate, k, n)
local seed = runedate * (2 ^ 32) + (runedate % k)
return rsrandom.nextInt(seed, n)
end
local function getSlots(offset)
local runedate = wednesday(rsrandom.runeDate_today() + offset * 7)
local index = p.get(runedate, 1, 8) + 1
return {
bronze = challenges[1][index],
silver = challenges[2][index],
gold = challenges[3][index]
}
end
function p.api(frame)
local args = frame:getParent().args
return p._api(args.offset, args.format)
end
function p._api(offset, format)
offset = tonumber(offset or 0) or 0
local slots = getSlots(offset)
local challenge_bronze = slots.bronze
local challenge_silver = slots.silver
local challenge_gold = slots.gold
if format == 'simple' then
return string.format('@%s¦%s¦%s@', challenge_bronze.name, challenge_silver.name, challenge_gold.name)
end
if format == 'json' then
local jsonret = {}
jsonret['timestamp'] = os.time()
jsonret['challenges'] = {challenge_bronze, challenge_silver, challenge_gold}
return mw.text.jsonEncode(jsonret)
end
local ret = mw.html.create('div')
ret :tag('span')
:addClass('slotA')
:tag('span'):addClass('name'):wikitext(a):done()
:tag('span'):addClass('cost'):wikitext(a_d.cost):done()
:tag('span'):addClass('use'):wikitext(a_d.use):done()
:done()
:addClass('slotB')
:tag('span'):addClass('name'):wikitext(b):done()
:tag('span'):addClass('cost'):wikitext(b_d.cost):done()
:tag('span'):addClass('use'):wikitext(b_d.use):done()
:done()
:addClass('slotC')
:tag('span'):addClass('name'):wikitext(c):done()
:tag('span'):addClass('cost'):wikitext(c_d.cost):done()
:tag('span'):addClass('use'):wikitext(c_d.use):done()
:done()
return ret
end
function makeFullRow(rank, challenge)
local tr = mw.html.create('tr')
tr :tag('td')
:wikitext(rank)
:done()
:tag('td')
:wikitext(challenge.name)
:done()
:tag('td')
:wikitext(challenge.description)
:done()
if challenge.mutators ~= nil then
local td = tr:tag('td')
for n,mutator_id in ipairs(challenge.mutators) do
local mutator = mutators[mutator_id]
local mutator_icon = string.format("[[File:%s mutator.png|link=Shattered Worlds#Mutators|27px]] ", mutator.name)
td :wikitext(mutator_icon)
td :tag('span')
:addClass('hover-text')
:attr('title', mutator.description)
:wikitext(mutator.name)
:done()
if n ~= #challenge.mutators then
td:wikitext(', ')
end
end
td:done()
else
tr :tag('td')
:addClass('table-na')
:wikitext('N/A')
:done()
end
tr :tag('td')
:wikitext(rewards[rank])
:done()
return tr
end
function p.today()
local slots = getSlots(0)
return p._today(slots.bronze, slots.silver, slots.gold)
end
function p._today(challenge_bronze, challenge_silver, challenge_gold)
local t = mw.html.create('table')
t :addClass('wikitable')
:tag('tr')
:tag('th')
:wikitext('Rank')
:done()
:tag('th')
:wikitext('Challenge')
:done()
:tag('th')
:wikitext('Description')
:done()
:tag('th')
:wikitext('Mutators')
:done()
:tag('th')
:wikitext('[[Shattered anima]] reward')
:done()
t :node(makeFullRow('Bronze', challenge_bronze))
:node(makeFullRow('Silver', challenge_silver))
:node(makeFullRow('Gold', challenge_gold))
local runedate_wednesday = wednesday(rsrandom.runeDate_today())
local cd = mw.html.create('span')
cd :addClass('countdown')
:attr('data-end', 'stop')
:tag('span')
:addClass('countdowndate')
:wikitext(lang:formatDate("j F Y", "27 February 2002 + " .. (runedate_wednesday + 7) .. " days"))
return string.format("''These are the challenges for the week of %s ([[Runedate]] %s).'' <sup>%s</sup><br>Valid for %s\n%s", lang:formatDate('[[j F]] [[Y]]', "27 February 2002 + " .. runedate_wednesday .. " days"), runedate_wednesday, tostring(purge()), tostring(cd), tostring(t))
end
function makeShortRow(offset, onlyitem_list)
local slots = getSlots(offset)
local challenge_bronze = slots.bronze
local challenge_silver= slots.silver
local challenge_gold = slots.gold
local class_bronze, class_silver, class_gold = nil,nil,nil
local founditems = {}
if onlyitem_list then
local foundonlyitem = false
local highlightclass = 'table-bg-green'
for _,onlyitem in ipairs(onlyitem_list) do
if onlyitem == challenge_bronze.name then
class_bronze = highlightclass
table.insert(founditems, onlyitem)
foundonlyitem = true
end
if onlyitem == challenge_silver.name then
class_silver = highlightclass
table.insert(founditems, onlyitem)
foundonlyitem = true
end
if onlyitem == challenge_gold.name then
class_ = highlightclass
table.insert(founditems, onlyitem)
foundonlyitem = true
end
end
if not foundonlyitem then
return {nil, {nil}}
end
founditems = removeDuplicates(founditems)
end
local tr = mw.html.create('tr')
tr :tag('td')
:wikitext(getDates(offset).stock_date)
:done()
:tag('td')
:wikitext(challenge_bronze.name)
:addClass(class_bronze)
:done()
:tag('td')
:wikitext(challenge_silver.name)
:addClass(class_silver)
:done()
:tag('td')
:wikitext(challenge_gold.name)
:addClass(class_gold)
:done()
return {tr, founditems}
end
function p.future(frame)
local args = frame:getParent().args
local s = args.start or args[1] or 0
local e = args['end'] or args[2] or 5
return p._future(s,e)
end
function p._future(startOffset, endOffset)
-- enforce numbers
startOffset = tonumber(startOffset or 0) or 0
endOffset = tonumber(endOffset or 5) or 5
-- switch around if start/end mixed
if startOffset > endOffset then
startOffset, endOffset = endOffset, startOffset
end
local function parseOffsetsToString()
local start_s = math.abs(startOffset) > 1 and "s" or ""
local end_s = math.abs(endOffset) > 1 and "s" or ""
if startOffset == endOffset then
if startOffset > 0 then
return string.format("%s week%s after this week", startOffset, start_s)
elseif startOffset < 0 then
return string.format("%s week%s before this week", startOffset * -1, start_s)
elseif startOffset == 0 then
return "this week"
end
else
local s = ""
if startOffset > 0 then
s = string.format("%s%s week%s after this week", s, startOffset, start_s)
elseif startOffset < 0 then
s = string.format("%s%s week%s before this week", s, startOffset * -1, start_s)
elseif startOffset == 0 then
s = string.format("%sthis week", s)
end
s = string.format("%s to ", s)
if endOffset > 0 then
s = string.format("%s%s week%s after this week", s, endOffset, end_s)
elseif endOffset < 0 then
s = string.format("%s%s week%s before this week", s, endOffset * -1, end_s)
elseif endOffset == 0 then
s = string.format("%sthis week", s)
end
return s
end
return "(error: start and/or end not numbers)"
end
local t = mw.html.create("table")
t:addClass("wikitable sticky-header")
:tag("tr")
:tag("th")
:wikitext("Date")
:done()
:tag("th")
:wikitext("Bronze")
:done()
:tag("th")
:wikitext("Silver")
:done()
:tag("th")
:wikitext("Gold")
:done()
for i=startOffset,endOffset,1 do
t:node(makeShortRow(i)[1])
end
return string.format(
"This table shows challenges for %s (%s)<sup>%s</sup>\n%s",
parseOffsetsToString(),
lang:formatDate("[[j F]] [[Y]]", "27 February 2002 + " .. rsrandom.runeDate_today() .. " days"),
purge(),
tostring(t)
)
end
function p.listItems()
local challengesBronze = {
'Novice World Traveller', 'Shocking', 'Novice Adventurer', 'The Undead Rise', 'British Summer Time',
'Bug Squasher', 'Instability', 'Automata Adjustment'
}
local challengesSilver = { 'Arachnophobia', 'Experienced World Traveller', 'Zones', 'Experienced Adventurer',
'Hella Mental', 'Demon Slayer', 'Starved', 'Shelve the Elves'
}
local challengesGold = { 'A Quick Trip to Hell', 'Master World Traveller', 'Stardust Crusade', 'Just Keep Moving',
'Master Adventurer', 'The Floor is Lava', 'Un-undead The Undead', 'Knightmare'
}
local t = mw.html.create('table')
t :addClass('wikitable align-center-1 align-center-4')
:tag('tr')
:tag('th'):attr('colspan', 5):wikitext('Slot 1 (always)'):done()
:done()
:tag('tr')
:tag('th'):attr('colspan', 2):wikitext('Item'):done()
:tag('th'):wikitext('Cost'):done()
:tag('th'):wikitext('Quantity'):done()
:tag('th'):wikitext('Use'):done()
:done()
:node(makeFullRow('Uncharted island map (Deep Sea Fishing)', challenges['Uncharted island map (Deep Sea Fishing)']))
:tag('tr')
:tag('th'):attr('colspan', 5):wikitext('Slots 2 and 3'):done()
:done()
:tag('tr')
:tag('th'):attr('colspan', 2):wikitext('Item'):done()
:tag('th'):wikitext('Cost'):done()
:tag('th'):wikitext('Quantity'):done()
:tag('th'):wikitext('Use'):done()
:done()
for i,v in ipairs(challengesBronze) do
t:node(makeFullRow(v, challenges[v]))
end
t :tag('tr')
:tag('th'):attr('colspan', 5):wikitext('Slot 4'):done()
:done()
:tag('tr')
:tag('th'):attr('colspan', 2):wikitext('Item'):done()
:tag('th'):wikitext('Cost'):done()
:tag('th'):wikitext('Quantity'):done()
:tag('th'):wikitext('Use'):done()
:done()
for i,v in ipairs(challengesSilver) do
t:node(makeFullRow(v, challenges[v]))
end
return t
end
function p.nextItem(frame)
local args = frame:getParent().args
local item = args.item
if not item then
item = mw.title.getCurrentTitle().text
end
local item_list = mw.text.split(item,",%s*")
local boolconverter = {["true"]=true,["false"]=false}
local individual = boolconverter[args.individual]
return p._nextItem(item_list, tonumber(args.number), tonumber(args.limit), individual)
end
function p._nextItem(item_list, n, dayslimit, individual)
local list = {
-- Bronze challenges
['Novice World Traveller'] = 'a',
['Shocking'] = 'a',
['Novice Adventurer'] = 'a',
['The Undead Rise'] = 'a',
['British Summer Time'] = 'a',
['Bug Squasher'] = 'a',
['Instability'] = 'a',
['Automata Adjustment'] = 'a',
-- Silver challenges
['Arachnophobia'] = 'b',
['Experienced World Traveller'] = 'b',
['Zones'] = 'b',
['Experienced Adventurer'] = 'b',
['Hella Mental'] = 'b',
['Demon Slayer'] = 'b',
['Starved'] = 'b',
['Shelve the Elves'] = 'b',
-- Gold challenges
['A Quick Trip to Hell'] = 'c',
['Master World Traveller'] = 'c',
['Stardust Crusade'] = 'c',
['Just Keep Moving'] = 'c',
['Master Adventurer'] = 'c',
['The Floor is Lava'] = 'c',
['Un-undead The Undead'] = 'c',
['Knightmare'] = 'c'
}
if not n then
n = 5
end
if not dayslimit then
dayslimit = 200
end
if not individual or #item_list == 1 then
individual = false
end
local unrecognised_item = ""
for _, item in ipairs(item_list) do
if not list[item] then
unrecognised_item = unrecognised_item .. "Unrecognised item ''"..item.."''. Please enter the item name exactly.<br>"
end
end
if unrecognised_item ~= "" then
return unrecognised_item:sub(1, -5)
end
local t = mw.html.create('table')
t :addClass('wikitable sticky-header')
:tag('tr')
:tag('th')
:wikitext('Date')
:done()
:tag('th')
:wikitext('[[Runedate]]')
:done()
:tag('th')
:wikitext('Slot A')
:done()
:tag('th')
:wikitext('Slot B')
:done()
:tag('th')
:wikitext('Slot C')
:done()
local d = 0
function check_count(count_all_table, n)
count_reached = true
for _,v in pairs(count_all_table) do
if v < n then
count_reached = false
end
end
return count_reached
end
local finalcount = math.huge
if not individual then
local count = 0
while count < n and d < dayslimit do
local r = makeShortRow(d, item_list)[1]
if r then
t:node(r)
count = count + 1
end
d = d + 1
end
finalcount = count
else
local count = {}
for _,item in ipairs(item_list) do
count[item] = 0
end
local count_all = false
while not count_all and d < dayslimit do
local r = makeShortRow(d, item_list)
if r[1] then
t:node(r[1])
for _,item in ipairs(r[2]) do
count[item] = count[item] + 1
end
end
count_all = check_count(count, n)
d = d + 1
end
-- local test = ""
-- for k,v in pairs(count) do
-- test = test .. k .. ": " .. tostring(v) .. "<br>"
-- end
-- return test
for _,v in pairs(count) do
finalcount = math.min(finalcount, v)
end
end
local simpleitem = ""
for item_count = 1, #item_list do
local item = item_list[item_count]
local iteminfo = challenges[item]
local andor = "or"
if individual then
andor = "and"
end
if item_count == #item_list then
if #item_list == 1 then
simpleitem = simpleitem..", "
elseif #item_list == 2 then
simpleitem = simpleitem.." " .. andor .. " "
else
simpleitem = simpleitem..", " .. andor .. " "
end
else
simpleitem = simpleitem..", "
end
simpleitem = simpleitem.."<i>"..item.."</i>"
end
simpleitem = simpleitem:sub(3)
local be_string = "is"
if individual then
be_string = "are"
end
local intro = string.format('This table shows the next %s dates<sup>%s</sup> on which %s %s available.', finalcount, tostring(purge()), simpleitem, be_string)
return intro .. '\n' .. tostring(t)
end
return p