Module:MaroScale: Difference between revisions

From MTG Wiki
Jump to navigation Jump to search
>Corveroth
(The best part about coding is imagining all of the explosions when your latest commit goes catastrophically wrong)
>Corveroth
(The next best thing is leaving out critical data)
Line 9: Line 9:
-- A list of all sets which have been Standard-legal since the introduction of the Storm Scale (September 2012)
-- A list of all sets which have been Standard-legal since the introduction of the Storm Scale (September 2012)
local LEGAL_EXPANSIONS = {
local LEGAL_EXPANSIONS = {
"Return to Ravnica",
["Return to Ravnica"] = "2012-10-05",
"Gatecrash",
["Gatecrash"] = "2013-02-01",
"Dragon's Maze",
["Dragon's Maze"] = "2013-05-03",
"Magic 2014",
["Magic 2014"] = "2013-06-13",
"Theros",
["Theros"] = "2013-09-27",
"Born of the Gods",
["Born of the Gods"] = "2014-02-07",
"Journey into Nyx",
["Journey into Nyx"] = "2014-05-02",
"Magic 2015",
["Magic 2015"] = "2014-07-18",
"Khans of Tarkir",
["Khans of Tarkir"] = "2014-09-26",
"Fate Reforged",
["Fate Reforged"] = "2015-01-23",
"Dragons of Tarkir",
["Dragons of Tarkir"] = "2015-03-17",
"Magic Origins",
["Magic Origins"] = "2015-07-15",
"Battle for Zendikar",
["Battle for Zendikar"] = "2015-10-02",
"Oath of the Gatewatch",
["Oath of the Gatewatch"] = "2016-01-22",
"Shadows over Innistrad",
["Shadows over Innistrad"] = "2016-04-08",
"Eldritch Moon",
["Eldritch Moon"] = "2016-06-22",
"Kaladesh",
["Kaladesh"] = "2016-09-30",
"Aether Revolt",
["Aether Revolt"] = "2016-01-20",
"Amonkhet",
["Amonkhet"] = "2017-04-28",
"Hour of Devastation",
["Hour of Devastation"] = "2017-07-14",
}
}



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"]		= "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 "[["..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 .. ",&nbsp;")
			else
				list:tag("li"):cssText("display:inline-block;"):wikitext(event.text)
			end
		end
	end
	return tbl
end

return MaroScale