Module:Ep/Info

From Queen's Court Games

Documentation for this module may be created at Module:Ep/Info/doc

-- TO DO: update this so other modules don't need to call Module:Ep/Matcher directly
-- TO DO: consider changing so the individual functions can be called directly when invoked (instead of using param)

local p = {}

-- For templates to use this module. First unnamed arg is the value to be interpreted.
function p.ep(frame)
	local ep = frame.args[1]
	local title = frame.args['title'] or nil
	local pagename = frame.args['pagename'] or nil
	local epNum = frame.args['epnum'] or nil
	local epCodeFormatted = frame.args['epCodeFormatted'] or nil
	local campaign = frame.args['campaign'] or nil
	local campaignName = frame.args['campaignname'] or nil
	local season = frame.args['season'] or nil
	local seasonName = frame.args['seasonname'] or nil
	local prodCode = frame.args['prodCode'] or nil
	local arcName = frame.args['arcName'] or nil
	local arcNum = frame.args['arcNum'] or nil
	local arcCategory = frame.args['arcCategory'] or nil
	local arcCharacterCategory = frame.args['arcCharacterCategory'] or nil
	local arcPage = frame.args['arcPage'] or nil
	local thumbnail = frame.args['thumbnail'] or nil
	local transcript = frame.args['transcript'] or nil
	local sortkey = frame.args['sortkey'] or nil
	local sortBy = frame.args['sortby'] or 'airdate'
	local epMatcher = require('Module:Ep/Matcher')
	local epCode = epMatcher.matchCode(ep)
	local data = ''
	
	if not isempty(title) then
		data = p.title(epCode)
	elseif not isempty(pagename) then
		data = p.pagename(epCode)
	elseif not isempty(epNum) then
		data = p.epNum(epCode)
	elseif not isempty(epCodeFormatted) then
		data = p.epCodeFormatted(epCode)
	elseif not isempty(campaign) then
		data = p.campaign(epCode)
	elseif not isempty(campaignName) then
		data = p.campaignName(epCode)
	elseif not isempty(season) then
		data = p.season(epCode)
	elseif not isempty(seasonName) then
		data = p.seasonName(epCode)
	elseif not isempty(arcName) then
		data = p.arcName(epCode)
	elseif not isempty(prodCode) then
		data = p.prodCode(epCode)
	elseif not isempty(arcNum) then
		data = p.arcNum(epCode)
	elseif not isempty(arcPage) then
		data = p.arcPage(epCode)
	elseif not isempty(arcCategory) then
		data = p.arcCategory(epCode)
	elseif not isempty(arcCharacterCategory) then
		data = p.arcCharacterCategory(epCode)
	elseif not isempty(sortkey) then
		data = p.calculateSortkey(epCode, sortBy)
	elseif not isempty(thumbnail) then
		data = p.thumbnail(epCode)
	elseif not isempty(transcript) then
		data = p.transcript(epCode)
	else
		data = epCode
	end
	return data
end

-- Functions for querying Module:Ep/Array to get title and/or pagename for output
function p.epInfo(epCode)
	local result

	local epInfos = mw.loadData('Module:Ep/Array')
	
	if epInfos[epCode] == nil then
		result = ""
	else
		result = epInfos[epCode]
	end

	return result

end

p.title = function(epCode)
	return p.epInfo(epCode)['title']
end

p.pagename = function(epCode)
	if p.epInfo(epCode)['pagename'] then
		pagename = p.epInfo(epCode)['pagename']
	else
		pagename = p.title(epCode)
	end
	return pagename
end

-- functions to parse epCode into campaign, season and epnumber, using EPISODE_DECODER

p.parseCode = function(epCode)
	if type(epCode) ~= "string" then
		epCode = epCode.args[1]
		end
	i, j = string.find(epCode,"x")
	prefix, epNum = '', ''
	if i then
		prefix = string.sub(epCode,1,i-1)
		epNum = string.sub(epCode,j+1)
		end
	return prefix, epNum
end

p.epNum = function(epCode)
	-- TM exception; find epNum in pagename
	if p.campaign(epCode) == 'TM' then
		local pagename = p.pagename(epCode)
		epNum = string.match(pagename, "%d+")
	else
		local prefix, epNum = p.parseCode(epCode)
	end
	-- remove leading zeroes
	if epNum then
		epNum = string.format("%d", epNum)
	end
	return epNum
end

-- Parse out shows and (optionally) seasons. Prevents TM from being parsed as having seasons.
p.campSeason = function(epCode)
	local campaign
	local season
	local decoder = mw.loadData('Module:Ep/Decoder')
	
	local prefix, epNum = p.parseCode(epCode)
	
	if prefix == 'TMOS' then
		campaign = 'TM'
	elseif (not tonumber(prefix) and prefix:match("^(.*%D)(%d+)$")) then
		campaign, season = prefix:match("^(.*%D)(%d+)$")
	elseif decoder[prefix] then
		campaign = prefix
	else
		campaign = 'Unknown Campaign'
	end
	
	-- Talks Machina season exception
	if campaign == 'TM' then
		season = ''
	end
	
	return campaign, season
end


p.prefix = function(epCode)
	prefix, epNum = p.parseCode(epCode)
	return prefix
end

p.campaign = function(epCode)
	campaign, season = p.campSeason(epCode)
	return campaign
end

p.campaignName = function(epCode, noItal)
	if not noItal then noItal = false
	end
	
	local campaign = p.campaign(epCode)
	
	if not campaign then
		return "Unknown Campaign"
	end
	
	local decoder = mw.loadData('Module:Ep/Decoder')
	if not decoder[campaign] then return "Unknown Campaign" end
	local campaignName = decoder[campaign]['title']
	
	if decoder[campaign]['italics'] == true and not noItal and campaignName then
		campaignName = "''" .. campaignName .. "''"
	end
	return campaignName
end

p.season = function(epCode)
	campaign, season = p.campSeason(epCode)
	return season
end

-- displays in the infobox "Episode" field before the episode number
p.seasonName = function(epCode)
	local decoder = mw.loadData('Module:Ep/Decoder')
	local campaign, season = p.campSeason(epCode)
	local valid_seasons
	local pagename
	local nameForDisplay
	local italics

	if campaign and decoder[campaign] then
		valid_seasons = decoder[campaign]['seasons'] or nil
	end

	-- if there's no season or the campaign doesn't have seasons, blank
	if isempty(season) or isempty(valid_seasons) then return ''
		
	-- is season valid? if not, blank
	elseif not searchKeys(season, valid_seasons) then return ''
	
	-- get season info from decoder
	else
		nameForDisplay = valid_seasons[season]['name'] or ''
		italics = valid_seasons[season]['italics'] or false
		end

	-- Default display is e.g. "Season 1", other build with season data from decoder
	if isempty(nameForDisplay) then
		nameForDisplay = 'Season ' .. season
	end
	return nameForDisplay
end

-- determine if episode is from a main campaign
p.isCampaign = function(epCode)
    local prefix, epNum = p.parseCode(epCode)
    return tonumber(prefix) and tonumber(epNum)
end

-- format epCode as C[Campaign]E[Episode]
p.prodCode = function(epCode)
    if p.isCampaign(epCode) then
        local prefix, epNum = p.parseCode(epCode)
        return 'C' .. prefix .. 'E' .. string.format("%02d", epNum)
    else
        return nil -- for non-campaign episodes
    end
end

p.arcInfo = function(epCode, arcIndex)
	local campaign = p.campaign(epCode)
	local epNum = tonumber(p.epNum(epCode))
	local decoder = mw.loadData('Module:Ep/Decoder')
	local arc = {}
	
	if decoder[campaign] then
		local arcs = decoder[campaign].arcs
		
		if not isempty(arcs) then
			if not arcIndex then
				for index, arcData in ipairs(arcs) do
					if epNum >= arcData.startEpisode and epNum <= arcData.endEpisode then
						arc = arcData
						break
					end
				end
			else
				local selectedArc = arcs[arcIndex]
				if selectedArc then
					arc = selectedArc
				end
			end
		end
	end
	return arc
end

p.arcNum = function(epCode)
	local arc = p.arcInfo(epCode)
	return arc.arcNum
end

p.arcName = function(epCode)
	local arc = p.arcInfo(epCode)
	return arc.title
end

p.arcPage = function(epCode)
	local campaign = p.campaign(epCode)
	local arc = p.arcInfo(epCode)
	local category = 'Campaign  ' .. campaign .. ' Arc ' .. arc.arcNum .. ': ' .. arc.title
	return category
end

p.arcCategory = function(epCode)
	local arc = p.arcInfo(epCode)
	return 'Category:' .. arc.title .. ' arc'
end

p.arcCharacterCategory = function(epCode)
	local arc = p.arcInfo(epCode)
	local arcName = removeLeadingThe(arc.title)
	return 'Category:Characters in the ' .. arcName .. ' arc'
end

-- get default naming for link to thumbnail
p.thumbnail = function(epCode)
	local thumbnailFile = epCode .. ' Episode Thumb.jpg'
	local campaign = p.campaign(epCode)

	-- Check if thumbnailFile exists, if not, fall back to default
	local title = mw.title.new('File:' .. thumbnailFile)
	if not title or not title.exists then
		if campaign == '3' then
			thumbnailFile = 'Bells Hells logo color.png'
		elseif campaign == 'CO' then
			thumbnailFile = 'Candela Obscura Logo.png'
		end
	end
	return thumbnailFile
end

p.transcript = function(epCode)
	local pagename = p.pagename(epCode)
	local transcript_link = 'Transcript:' .. pagename .. ''
	return transcript_link
end

-- for formatting the episode code
p.epCodeFormatted = function(epCode)
	local campaign = p.campaign(epCode)
	local decoder = mw.loadData('Module:Ep/Decoder')
	local small = mw.html.create('small')
	local formatKey
	local formatted
	
	if campaign ~= 'Unknown Campaign' and decoder[campaign] then
		formatKey = decoder[campaign]['codeFormat']
	end
	
	if formatKey then
		formatted = formatKey:gsub('{campaign}', campaign)
		if p.season(epCode) then
			formatted = formatted:gsub('{season}', p.season(epCode))
		end
		formatted = formatted:gsub('{epNum}', string.format("%02d", p.epNum(epCode)))
	else
		formatted = epCode
	end
	small:wikitext("(" .. formatted .. ")")
	formatted = tostring(small)
	return formatted
end

-- Function to calculate the sortkey for an episode code
p.calculateSortkey = function(epCode, sortBy)
	local epNum = p.epNum(epCode)
	local campaign, season = p.campSeason(epCode)
	if not season then season = "0" end

	-- map of campaign codes to sort values
	local campaignTransform = {
		["1"] = "01",
		["2"] = "02",
		["3"] = "03",
		["OS"] = "05",
		["CO"] = "06",
		["4SD"] = "07",
		["E"] = "08",
		["M"] = "09",
		["TM"] = "10",
		["U"] = "11",
		["Midst"] = "12",
		}

	-- transform campaign code
	if campaignTransform[campaign] then
		campaign = campaignTransform[campaign]
	end

	-- Retrieve the airdate for the episode code from Module:AirdateOrder/Array
	-- Distill airdate to YYYYMMDD
	local airdateOrder = require('Module:AirdateOrder')
	local airdate = airdateOrder.airdate(epCode):gsub("(%d%d%d%d)-(%d%d)-(%d%d).*", "%1%2%3")
	-- Calculate the sortkey based on the specified sorting method
	local sortkey = campaign .. season .. string.format("%04d", epNum)
	if sortBy == "airdate" then
		mw.log(tostring(epCode) .. ' Airdate yes')
		sortkey = airdate .. sortkey
	else mw.log(tostring(epCode) .. " Airdate no")
	end
	return sortkey
end

-- function to remove a leading 'The' at the beginning of a string
function removeLeadingThe(s)
	local result, _ = string.gsub(s, '^The%s*', '', 1)
	return result
end

--function to determine if a string is empty
function isempty(s)
   return s == nil or s == ''
end


return p