Module:MaroScale: Difference between revisions
Jump to navigation
Jump to search
>Corveroth No edit summary |
>Jerodast (In my review/learning about this code, was surprised to see <ul> used for the inline list. Realized that format also made the entry align differently than the rest of the row (although that's probably fixable with CSS style). In any case I'll update to use this simpler style. This will make the current lists more compact vertically!) |
||
(15 intermediate revisions by one other user not shown) | |||
Line 5: | Line 5: | ||
local MaroScale = {} | local MaroScale = {} | ||
local function | local sub, match, gsub = mw.ustring.sub, mw.ustring.match, mw.ustring.gsub | ||
local MAX_ENTRIES = 500 | |||
-- 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"] = "2012-10-05", | |||
["Gatecrash"] = "2013-02-01", | |||
["Dragon's Maze"] = "2013-05-03", | |||
["Magic 2014"] = "2013-06-13", | |||
["Theros"] = "2013-09-27", | |||
["Born of the Gods"] = "2014-02-07", | |||
["Journey into Nyx"] = "2014-05-02", | |||
["Magic 2015"] = "2014-07-18", | |||
["Khans of Tarkir"] = "2014-09-26", | |||
["Fate Reforged"] = "2015-01-23", | |||
["Dragons of Tarkir"] = "2015-03-17", | |||
["Magic Origins"] = "2015-07-15", | |||
["Battle for Zendikar"] = "2015-10-02", | |||
["Oath of the Gatewatch"] = "2016-01-22", | |||
["Shadows over Innistrad"] = "2016-04-08", | |||
["Eldritch Moon"] = "2016-06-22", | |||
["Kaladesh"] = "2016-09-30", | |||
["Aether Revolt"] = "2016-01-20", | |||
["Amonkhet"] = "2017-04-28", | |||
["Hour of Devastation"] = "2017-07-14", | |||
} | |||
local function generateLink(target, displayText) | |||
if displayText then | if displayText then | ||
return "[[".. | return "[["..displayText.."|"..target.."]]" | ||
else | else | ||
return "[["..target.."]]" | return "[["..target.."]]" | ||
Line 14: | Line 41: | ||
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), month=sub(refDate, 6,7), day=sub(refDate, 9,10),}) | ||
if t > newestDate then | if t > newestDate then | ||
newestDate = t | newestDate = t | ||
Line 28: | Line 55: | ||
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), month=sub(releaseDate, 6,7), day=sub(releaseDate, 9,10),}) | |||
table.insert(timeline, {text = generateLink(set), t = t}) | |||
end) | end) | ||
return timeline | |||
end | end | ||
local function sortTimeline(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 44: | Line 94: | ||
_ = args.type | _ = args.type | ||
_ = args.above | _ = args.above | ||
for i = 1, | for i = 1, MAX_ENTRIES do | ||
_ = args["name" .. tostring(i)] | _ = args["name" .. tostring(i)] | ||
_ = args["entry" .. tostring(i)] | _ = args["entry" .. tostring(i)] | ||
_ = args[" | _ = args["note" .. tostring(i)] | ||
_ = args["ratings" .. tostring(i)] | _ = args["ratings" .. tostring(i)] | ||
_ = args[" | _ = args["printings" .. tostring(i)] | ||
end | 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, {num = tonumber(listnum), alpha = args["entry"..listnum]}) end | |||
end | |||
table.sort(listnums, function(a,b) return a.alpha < b.alpha end) | |||
-- Build the table header row | |||
local type = args.type | local type = args.type | ||
local tbl = mw.html.create("table"):addClass("wikitable"):addClass("sortable") | local tbl = mw.html.create("table"):addClass("wikitable"):addClass("sortable") | ||
Line 60: | Line 117: | ||
:tag("th"):wikitext(type):done() | :tag("th"):wikitext(type):done() | ||
:tag("th"):wikitext("Latest ranking"):done() | :tag("th"):wikitext("Latest ranking"):done() | ||
:tag("th"):addClass("unsortable"):wikitext(" | :tag("th"):addClass("unsortable"):wikitext("Timeline"):done() -- Last column can't be sorted | ||
local hasNotes = false | |||
-- | -- Reusable loop vars for performance | ||
local | local name, entry, note, ratings, printings | ||
local linkedEntry, lastRating, timeline | |||
local row, list, cellText | |||
local | |||
for i, listnum in ipairs(listnums) do | for i, listnum in ipairs(listnums) do | ||
name, entry, | listnum = listnum.num | ||
-- Retrieve the relevant args for this row | |||
name, entry, note, ratings, printings = args["name"..listnum], args["entry"..listnum], args["note"..listnum], args["ratings"..listnum], args["printings"..listnum] | |||
-- Create a wikilink for the entry, using name as the target article if provided | |||
linkedEntry = generateLink(entry, name) | |||
if note then | |||
if not hasNotes then hasNotes = true end | |||
linkedEntry = linkedEntry .. frame:expandTemplate({title = "efn", args = { note }}) | |||
end | |||
-- Decode the ratings into a table | |||
if | lastRating, timeline = parseRatings(ratings) | ||
-- Add any printings | |||
if printings then | |||
timeline = addPrintings(timeline, printings) | |||
end | end | ||
-- 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 | |||
--[[ Commented out by jerodast - let's just try regular wikitext. | |||
list = row:tag("td"):tag("ul"):cssText("display:block; margin-top:0; margin-left:0;") | |||
for j, event in ipairs(timeline) do | |||
if j ~= #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 | ||
]] | |||
list = {} | |||
for j, event in ipairs(timeline) do table.insert(list, event.text) end | |||
row:tag("td"):wikitext(table.concat(list,", ")) | |||
end | |||
if hasNotes then | |||
return tostring(tbl) .. frame:expandTemplate({title = "notelist"}) | |||
else | |||
return tbl | |||
end | end | ||
end | end | ||
return MaroScale | return MaroScale |
Latest revision as of 19:22, 4 July 2022
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 local MAX_ENTRIES = 500 -- 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"] = "2012-10-05", ["Gatecrash"] = "2013-02-01", ["Dragon's Maze"] = "2013-05-03", ["Magic 2014"] = "2013-06-13", ["Theros"] = "2013-09-27", ["Born of the Gods"] = "2014-02-07", ["Journey into Nyx"] = "2014-05-02", ["Magic 2015"] = "2014-07-18", ["Khans of Tarkir"] = "2014-09-26", ["Fate Reforged"] = "2015-01-23", ["Dragons of Tarkir"] = "2015-03-17", ["Magic Origins"] = "2015-07-15", ["Battle for Zendikar"] = "2015-10-02", ["Oath of the Gatewatch"] = "2016-01-22", ["Shadows over Innistrad"] = "2016-04-08", ["Eldritch Moon"] = "2016-06-22", ["Kaladesh"] = "2016-09-30", ["Aether Revolt"] = "2016-01-20", ["Amonkhet"] = "2017-04-28", ["Hour of Devastation"] = "2017-07-14", } local function generateLink(target, displayText) if displayText then return "[["..displayText.."|"..target.."]]" 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), month=sub(refDate, 6,7), day=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), month=sub(releaseDate, 6,7), day=sub(releaseDate, 9,10),}) table.insert(timeline, {text = generateLink(set), t = t}) end) return timeline end local function sortTimeline(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, MAX_ENTRIES do _ = args["name" .. tostring(i)] _ = args["entry" .. tostring(i)] _ = args["note" .. tostring(i)] _ = args["ratings" .. tostring(i)] _ = args["printings" .. 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, {num = tonumber(listnum), alpha = args["entry"..listnum]}) end end table.sort(listnums, function(a,b) return a.alpha < b.alpha end) -- 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 local hasNotes = false -- Reusable loop vars for performance local name, entry, note, ratings, printings local linkedEntry, lastRating, timeline local row, list, cellText for i, listnum in ipairs(listnums) do listnum = listnum.num -- Retrieve the relevant args for this row name, entry, note, ratings, printings = args["name"..listnum], args["entry"..listnum], args["note"..listnum], args["ratings"..listnum], args["printings"..listnum] -- Create a wikilink for the entry, using name as the target article if provided linkedEntry = generateLink(entry, name) if note then if not hasNotes then hasNotes = true end linkedEntry = linkedEntry .. frame:expandTemplate({title = "efn", args = { note }}) end -- Decode the ratings into a table lastRating, timeline = parseRatings(ratings) -- Add any printings if printings then timeline = addPrintings(timeline, printings) end -- 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 --[[ Commented out by jerodast - let's just try regular wikitext. list = row:tag("td"):tag("ul"):cssText("display:block; margin-top:0; margin-left:0;") for j, event in ipairs(timeline) do if j ~= #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 ]] list = {} for j, event in ipairs(timeline) do table.insert(list, event.text) end row:tag("td"):wikitext(table.concat(list,", ")) end if hasNotes then return tostring(tbl) .. frame:expandTemplate({title = "notelist"}) else return tbl end end return MaroScale