Module:MaroScale: Difference between revisions
Jump to navigation
Jump to search
>Corveroth No edit summary |
>Corveroth (The best part about coding is imagining all of the explosions when your latest commit goes catastrophically wrong) |
||
Line 5: | Line 5: | ||
local MaroScale = {} | local MaroScale = {} | ||
local function | local sub, match, gsub = mw.ustring.sub, mw.ustring.match, mw.ustring.gsub | ||
-- A list of all sets which have been Standard-legal since the introduction of the Storm Scale (September 2012) | |||
local LEGAL_EXPANSIONS = { | |||
"Return to Ravnica", | |||
"Gatecrash", | |||
"Dragon's Maze", | |||
"Magic 2014", | |||
"Theros", | |||
"Born of the Gods", | |||
"Journey into Nyx", | |||
"Magic 2015", | |||
"Khans of Tarkir", | |||
"Fate Reforged", | |||
"Dragons of Tarkir", | |||
"Magic Origins", | |||
"Battle for Zendikar", | |||
"Oath of the Gatewatch", | |||
"Shadows over Innistrad", | |||
"Eldritch Moon", | |||
"Kaladesh", | |||
"Aether Revolt", | |||
"Amonkhet", | |||
"Hour of Devastation", | |||
} | |||
local function generateLink(target, displayText) | |||
if displayText then | if displayText then | ||
return "[["..target.."|"..displayText.."]]" | return "[["..target.."|"..displayText.."]]" | ||
Line 14: | Line 40: | ||
local function parseRatings(raw) | local function parseRatings(raw) | ||
local | local outputList = {} | ||
local newestDate, newestRating = 0, 0 | local newestDate, newestRating = 0, 0 | ||
local rating, refDate, refString, t | local rating, refDate, refString, t | ||
gsub(raw, "{(.-)}", function(a) | |||
rating, refDate, refString = | rating, refDate, refString = match(a, "(%d+),([%d%-]+),(.+)") | ||
rating = tonumber(rating) | rating = tonumber(rating) | ||
-- Dates MUST be yyyy-mm-dd | -- Dates MUST be yyyy-mm-dd | ||
t = os.time({year= | t = os.time({year=sub(refDate, 1,4), sub(refDate, 6,7), sub(refDate, 9,10),}) | ||
if t > newestDate then | if t > newestDate then | ||
newestDate = t | newestDate = t | ||
Line 28: | Line 54: | ||
end | end | ||
table.insert( | table.insert(outputList, {text = rating..refString, t = t}) | ||
end) | |||
return newestRating, outputList | |||
end | |||
local function addPrintings(timeline, printings) | |||
local releaseDate, t | |||
-- Comma-separated list | |||
gsub(printings, "([^,]+)", function(set) | |||
releaseDate = LEGAL_EXPANSIONS[set] | |||
-- The set name provided doesn't match a post-Storm Scale set | |||
if not releaseDate then return end | |||
-- Dates MUST be yyyy-mm-dd | |||
t = os.time({year=sub(releaseDate, 1,4), sub(releaseDate, 6,7), sub(releaseDate, 9,10),}) | |||
table.insert(timeline, {text = generateLink(set), t = t}) | |||
end) | end) | ||
return timeline | |||
end | end | ||
local function sortHistory(events) | |||
-- Sort all events into chronological order | |||
table.sort(events, function(a,b) return a.t < b.t end) | |||
return events | |||
end | |||
function MaroScale.TableBuilder(frame) | function MaroScale.TableBuilder(frame) | ||
local args = frame:getParent().args -- coming from one layer up | local args = frame:getParent().args -- coming from one layer up | ||
Line 47: | Line 96: | ||
_ = args["name" .. tostring(i)] | _ = args["name" .. tostring(i)] | ||
_ = args["entry" .. tostring(i)] | _ = args["entry" .. tostring(i)] | ||
_ = args["ratings" .. tostring(i)] | _ = args["ratings" .. tostring(i)] | ||
end | end | ||
-- Seriously this loop is entirely too clever | -- Seriously this loop is entirely too clever | ||
local listnums = {} | local listnums = {} | ||
for k, v in pairs(args) do | for k, v in pairs(args) do | ||
local listnum = ('' .. k | local listnum = match('' .. k, '^ratings(%d+)$') | ||
if listnum then table.insert(listnums, tonumber(listnum)) end | if listnum then table.insert(listnums, tonumber(listnum)) end | ||
end | end | ||
table.sort(listnums) | table.sort(listnums) | ||
local name, entry, ratings, | |||
-- Build the table header row | |||
local type = args.type | |||
local tbl = mw.html.create("table"):addClass("wikitable"):addClass("sortable") | |||
tbl:tag("tr") | |||
:tag("th"):wikitext(type):done() | |||
:tag("th"):wikitext("Latest ranking"):done() | |||
:tag("th"):addClass("unsortable"):wikitext("Timeline"):done() -- Last column can't be sorted | |||
-- Reusable loop vars for performance | |||
local name, entry, ratings, printings | |||
local linkedEntry, lastRating, timeline | |||
local row, cellText | |||
for i, listnum in ipairs(listnums) do | for i, listnum in ipairs(listnums) do | ||
name, entry, | -- Retrieve the relevant args for this row | ||
name, entry, ratings, printings = args["name"..listnum], args["entry"..listnum], args["ratings"..listnum], args["printings"..listnum] | |||
-- Create a wikilink for the entry, using name as the target article if provided | |||
linkedEntry = generateLink(name, entry) | |||
-- Decode the ratings into a table | |||
lastRating, timeline = parseRatings(ratings) | |||
-- Add any printings | |||
timeline = addPrintings(timeline, printings) | |||
-- Sort chronologically | |||
timeline = sortTimeline(timeline) | |||
-- Make the row | -- Make the row | ||
row = tbl:tag("tr") | |||
-- First cell | |||
row:tag("td"):wikitext(linkedEntry) | |||
-- Second cell | |||
row:tag("td"):wikitext(lastRating) | |||
-- Third cell | |||
row:tag("td"):tag("ul"):cssText("display:block; margin-top:0; margin-left:0;") | |||
for n, event in pairs(timeline) do | |||
if n ~= #timeline then | |||
list:tag("li"):cssText("display:inline-block;"):wikitext(event.text .. ", ") | |||
else | |||
list:tag("li"):cssText("display:inline-block;"):wikitext(event.text) | |||
end | end | ||
end | end |
Revision as of 02:48, 8 January 2017
Documentation for this module may be created at Module:MaroScale/doc
-- Little bit of Lua for building tables for the Storm and Rabiah scales. -- Mechanics have been re-ranked in the past, and it's probably interesting to track their drift. -- Rather than force editors to track the newest one, let's see if we can't do it in code. local MaroScale = {} local sub, match, gsub = mw.ustring.sub, mw.ustring.match, mw.ustring.gsub -- A list of all sets which have been Standard-legal since the introduction of the Storm Scale (September 2012) local LEGAL_EXPANSIONS = { "Return to Ravnica", "Gatecrash", "Dragon's Maze", "Magic 2014", "Theros", "Born of the Gods", "Journey into Nyx", "Magic 2015", "Khans of Tarkir", "Fate Reforged", "Dragons of Tarkir", "Magic Origins", "Battle for Zendikar", "Oath of the Gatewatch", "Shadows over Innistrad", "Eldritch Moon", "Kaladesh", "Aether Revolt", "Amonkhet", "Hour of Devastation", } local function generateLink(target, displayText) if displayText then return "[["..target.."|"..displayText.."]]" else return "[["..target.."]]" end end local function parseRatings(raw) local outputList = {} local newestDate, newestRating = 0, 0 local rating, refDate, refString, t gsub(raw, "{(.-)}", function(a) rating, refDate, refString = match(a, "(%d+),([%d%-]+),(.+)") rating = tonumber(rating) -- Dates MUST be yyyy-mm-dd t = os.time({year=sub(refDate, 1,4), sub(refDate, 6,7), sub(refDate, 9,10),}) if t > newestDate then newestDate = t newestRating = rating end table.insert(outputList, {text = rating..refString, t = t}) end) return newestRating, outputList end local function addPrintings(timeline, printings) local releaseDate, t -- Comma-separated list gsub(printings, "([^,]+)", function(set) releaseDate = LEGAL_EXPANSIONS[set] -- The set name provided doesn't match a post-Storm Scale set if not releaseDate then return end -- Dates MUST be yyyy-mm-dd t = os.time({year=sub(releaseDate, 1,4), sub(releaseDate, 6,7), sub(releaseDate, 9,10),}) table.insert(timeline, {text = generateLink(set), t = t}) end) return timeline end local function sortHistory(events) -- Sort all events into chronological order table.sort(events, function(a,b) return a.t < b.t end) return events end function MaroScale.TableBuilder(frame) local args = frame:getParent().args -- coming from one layer up -- Imitating navbox, here. I trust they know what they're doing. -- Read the arguments in the order they'll be output in, to make references number in the right order. local _ _ = args.type _ = args.above for i = 1, 200 do _ = args["name" .. tostring(i)] _ = args["entry" .. tostring(i)] _ = args["ratings" .. tostring(i)] end -- Seriously this loop is entirely too clever local listnums = {} for k, v in pairs(args) do local listnum = match('' .. k, '^ratings(%d+)$') if listnum then table.insert(listnums, tonumber(listnum)) end end table.sort(listnums) -- Build the table header row local type = args.type local tbl = mw.html.create("table"):addClass("wikitable"):addClass("sortable") tbl:tag("tr") :tag("th"):wikitext(type):done() :tag("th"):wikitext("Latest ranking"):done() :tag("th"):addClass("unsortable"):wikitext("Timeline"):done() -- Last column can't be sorted -- Reusable loop vars for performance local name, entry, ratings, printings local linkedEntry, lastRating, timeline local row, cellText for i, listnum in ipairs(listnums) do -- Retrieve the relevant args for this row name, entry, ratings, printings = args["name"..listnum], args["entry"..listnum], args["ratings"..listnum], args["printings"..listnum] -- Create a wikilink for the entry, using name as the target article if provided linkedEntry = generateLink(name, entry) -- Decode the ratings into a table lastRating, timeline = parseRatings(ratings) -- Add any printings timeline = addPrintings(timeline, printings) -- Sort chronologically timeline = sortTimeline(timeline) -- Make the row row = tbl:tag("tr") -- First cell row:tag("td"):wikitext(linkedEntry) -- Second cell row:tag("td"):wikitext(lastRating) -- Third cell row:tag("td"):tag("ul"):cssText("display:block; margin-top:0; margin-left:0;") for n, event in pairs(timeline) do if n ~= #timeline then list:tag("li"):cssText("display:inline-block;"):wikitext(event.text .. ", ") else list:tag("li"):cssText("display:inline-block;"):wikitext(event.text) end end end return tbl end return MaroScale