Module:Ep/Matcher

local p = {}

-- use the query pairs to match any input string to the formatted episode code -- TO DO: this reference and category assignment belongs in Module:Ep, not here. should only be passed ep function p.matchCode(frame) local ep   if reference and frame.args["ep"] then ep = frame.args.ep:lower elseif reference and not isnotempty(frame.args["ep"]) then return " Undefined Episode ", "" elseif reference then ep = "0x00" elseif not isnotempty(frame.args[1]) then return "", "" else ep = frame.args[1]:lower end local epCode = p.matchIndividualCode(ep) return epCode end

function p.matchIndividualCode(ep) local epCode if p.areYouACode(ep) then ep = p.zeropadCode(ep) end queryPairs = makeQueryPairs if queryPairs[ep] then epCode = queryPairs[ep] else epCode = '0x00' 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[k:lower] = k        for key, val in pairs(v) do            if type(val) == 'string' then queryPairs[val:lower] = k           else for i, option in pairs(val) do                   queryPairs[option:lower] = 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

-- function to determine that a variable has a value function isnotempty(s) return s ~= nil and s~= '' 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