Module:Ep/Matcher

From Queen's Court Games

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

local p = {}

-- how templates can call this module
-- only uses one unnamed arg
function p.matchCodeTemplate(frame)
	local ep = frame.args[1]
	epCode = p.matchCode(ep)
	return epCode
end

-- for other modules to use the query pairs to match any input string to the formatted episode code
-- NOTE: "the sunken tomb" is ambiguous whether 1x44 or LVM2x03
-- NOTE: "those who walk away" is ambiguous whether 1x45 or LVM2x04
function p.matchCode(ep)
	local epCode
    if p.areYouACode(ep) then
    	ep = p.zeropadCode(ep)
    	end

    epInfos = mw.loadData('Module:Ep/Array')
    if epInfos[ep] then
        epCode = ep
    else
        queryPairs = makeQueryPairs()
    
        ep = ep:gsub("_", " "):gsub("^%s*(.-)%s*$", "%1")
	    ep = p.cleanMarkup(ep)
        if (queryPairs[ep] and
            ep ~= 'the sunken tomb' and
            ep ~= 'those who walk away') then
            epCode = queryPairs[ep]
        else
            epCode = '0x00'
        end
    end
    return epCode
end

-- for converting Ep/Array array into pairs of input string:output episode code
function makeQueryPairs()
	local epInfos = mw.loadData('Module:Ep/Array')
    queryPairs = {}
    for k, v in pairs(epInfos) do
        queryPairs[p.cleanMarkup(k)] = k
        for key, val in pairs(v) do
            if type(val) == 'string' then
                queryPairs[p.cleanMarkup(val)] = k
            else
                for i, option in pairs(val) do
                    queryPairs[p.cleanMarkup(option)] = k
            end
            end
        end
        end
    return queryPairs
end

-- functions to parse epcode into campaign, season, number, and suffix, using Module:Ep/Decoder
p.parseCode = function(ep)
    i, j = string.find(ep,"x")
    prefix, ep_num = '', ''
    if i then
        prefix = string.sub(ep,1,i-1)
        ep_num = string.sub(ep,j+1)
        end
    return prefix, ep_num
end

p.parseCodeFull = function(ep)
	local campaign_code
	local season
	local num
	local suffix
    prefix, ep_num = p.parseCode(ep)
    if (not tonumber(prefix) and tonumber(prefix:sub(-1))) then
        campaign_code = prefix:sub(1, -2)
        season = prefix:sub(-1)
    else
        campaign_code = prefix
        season = ''
    end
    
    -- get episode number
    if tonumber(ep_num) then
        num = tonumber(ep_num)
        suffix = ''
    else
        suffix = ep_num:sub(-1):lower()
        num = ep_num:sub(1, -2)
    end
    
    return campaign_code, season, num, suffix
end

-- will zeropad code if fits, otherwise return same value
p.zeropadCode = function(ep)
    campaign_code, season, num, suffix = p.parseCodeFull(ep)
    local new_code
    local padded_num
    if tonumber(num) then
        padded_num = string.format("%02d", num)
        new_code = campaign_code .. season .. 'x' .. padded_num .. suffix
    else
        new_code = frame
        end
    return new_code
    end

-- true/false test for whether a string is a valid episode code 
p.areYouACode = function(ep)
    local campaign_code, season, num, suffix = p.parseCodeFull(ep)
    local decoder = mw.loadData('Module:Ep/Decoder')

    -- if no num, invalid
    if not num or num == '' then return false

    -- is the campaign prefix one of the acceptable ones?        
    elseif not searchKeys(campaign_code, decoder) then return false
    
    -- is the season a number or blank?
    elseif not (tonumber(season) or season == '') then return false
        
    -- is the num a number and if suffix is it 'a' or 'b'?
    elseif tonumber(num) and (suffix == 'a' or suffix == 'b' or suffix == '') then
            return true
    else
            return false
end
    end

-- remove all characters not spaces or alphanumeric
p.cleanMarkup = function(text)
    result = string.gsub(string.lower(text), "[^%w%s]", "")
    -- clean up double spaces that might result
    result = string.gsub(result, "%s+", " ")
    return result
end

-- functions for searching an array for a value (case-insensitive)
function keyset(dict)
	local keys = {}
	for k,v in pairs(dict) do
	    keys[k:lower()]=true
	end
	return keys
end

function searchKeys(item, dict)
    local keys = keyset(dict)
    if keys[item:lower()] then
        return true
    else
		return false
        end
end

return p