Module:Highway shields/defs

From Wikipedia

Documentation for this module may be created at Module:Highway shields/defs/doc

local p = {}

local format = string.format

Shield = {formatArgs = {"route"}}

function Shield:new(obj)
    obj = obj or {}
    setmetatable(obj, self)
    self.__index = self
    return obj
end

function Shield:shield(args)
    self:preprocess(args)
    return self:exception(args) or self:default(args)
end

function Shield:update(args)
    return
end

function Shield:preprocess(args)
    local preprocessors = self.preprocessors or {}
    for i,preprocessor in ipairs(preprocessors) do
        preprocessor(args)
    end
end

function Shield:exception(args)
    local exceptions = self.exceptions or {}
    local route = args.route
    return exceptions[route]
end

function Shield:default(args)
    local formatArgs = self.formatArgs
    local formatArguments = {}
    for i,v in ipairs(formatArgs) do
        formatArguments[i] = args[v]
    end
    local subtypes = self.subtypes or {}
    local subtype = args.subtype or ''
    local subtypeShield = subtypes[subtype]
    if subtypeShield then
        return format(subtypeShield, unpack(formatArguments))
    end
    local by100 = self.by100
    local formatStr = ""
    if by100 then
        local less = by100.less
        local more = by100.more
        local route = tonumber(args.route)
        formatStr = (route < 100) and less or more
    else
        formatStr = self.formatStr
    end
    return formatStr and format(formatStr, unpack(formatArguments)) or false
end

Type = Shield:new()

function Type:shield(args)
    self:preprocess(args)
    return self:fromState(args) or self:exception(args) or self:default(args)
end

function Type:fromState(args)
    local stateName = args.state
    local state = self[stateName]
    return state and state:shield(args) or nil
end

function Type:addShield(state, shield)
    self[state] = shield
end

UniqueType = Type:new()

function UniqueType:update(args)
    local state = args.state
    local shield = args.shield
    if state then self.states[state] = true end
    if shield and not(self.uniqueShield) then
        self.uniqueShield = shield
    end
end

function UniqueType:shield(args)
    local stateArg = args.state
    local states = self.states
    if states[stateArg] then
        local uniqueShield = self.uniqueShield
        return uniqueShield:shield(args)
    else
        return nil
    end
end

Alias = {}

function Alias:new(obj)
    obj = obj or {}
    setmetatable(obj, self)
    self.__index = self
    return obj
end

function Alias:shield(args)
    local type = self.type
    setmetatable(args, {__index = self})
    if self.state then
        args.stateOrig = args.state
        args.state = self.state
    end
    return type:shield(args)
end

Country = {}

function Country:new(obj)
    obj = obj or {}
    setmetatable(obj, self)
    self.__index = self
    return obj
end

function Country:addType(key, type)
    self[key] = type
end

Country.addShield = Country.addType

function Country:shield(args)
    local type = self[args.type]
    return type and type:shield(args)
end

function Country:type(typeToCheck)
    local type = self[typeToCheck]
    if not(type) then
        type = Type:new()
        self[typeToCheck] = type
    end
    return type
end

function Country:uniqueType(typeToCheck)
    local type = self[typeToCheck]
    if not(type) then
        type = UniqueType:new{states = {}}
        self[typeToCheck] = type
    end
    return type
end

ShieldPreprocessors = {}

p.Country = Country
p.Shield = Shield
p.Type = Type
p.UniqueType = UniqueType
p.Alias = Alias
p.ShieldPreprocessors = ShieldPreprocessors

return p