Module:Concert location

From Weezerpedia

-- Module:Concert location
local p = {}

-- Allowed artists for automatic categorization
local allowed_artists = {
    ["Weezer"] = true,
}

local states = {
    AL="Alabama", AK="Alaska", AZ="Arizona", AR="Arkansas", CA="California",
    CO="Colorado", CT="Connecticut", DE="Delaware", FL="Florida", GA="Georgia",
    HI="Hawaii", ID="Idaho", IL="Illinois", IN="Indiana", IA="Iowa",
    KS="Kansas", KY="Kentucky", LA="Louisiana", ME="Maine", MD="Maryland",
    MA="Massachusetts", MI="Michigan", MN="Minnesota", MS="Mississippi",
    MO="Missouri", MT="Montana", NE="Nebraska", NV="Nevada", NH="New Hampshire",
    NJ="New Jersey", NM="New Mexico", NY="New York", NC="North Carolina",
    ND="North Dakota", OH="Ohio", OK="Oklahoma", OR="Oregon", PA="Pennsylvania",
    RI="Rhode Island", SC="South Carolina", SD="South Dakota", TN="Tennessee",
    TX="Texas", UT="Utah", VT="Vermont", VA="Virginia", WA="Washington",
    WV="West Virginia", WI="Wisconsin", WY="Wyoming"
}

-- Reverse lookup table for full state names
local stateNames = {}
for abbr, fullname in pairs(states) do
    stateNames[string.upper(fullname)] = fullname
end

-- Countries that require "the" prefix
local countriesWithThe = {
    ["UNITED KINGDOM"] = true,
    ["NETHERLANDS"] = true,
    ["BAHAMAS"] = true,
    ["PHILIPPINES"] = true,
    ["CZECH REPUBLIC"] = true,
}

-- Country aliases
local countryAliases = {
    ["UK"] = "United Kingdom",
    ["U.K."] = "United Kingdom",
}

-- Extract year from date string
local function extractYear(dateStr)
    if not dateStr then return "" end
    local year = string.match(dateStr, "%d%d%d%d")
    return year or ""
end

-- Trim helper
local function trim(s)
    return (s and s:match("^%s*(.-)%s*$")) or ""
end

-- Main function
function p.getCategory(frame)
    local location = trim(frame.args[1] or "")
    local date = trim(frame.args[2] or "")
    local artist = trim(frame.args[3] or "")
    local loc_upper = string.upper(location)
    local sortKey = extractYear(date)

    -- Only process if artist is allowed
    if not allowed_artists[artist] or location == "" then
        return ""
    end

    local categoryBase = artist .. " concerts in "

    -- Check US state abbreviations first (with or without comma)
    for abbr, fullname in pairs(states) do
        local abbr_upper = string.upper(abbr)
        if string.sub(loc_upper, -string.len(", " .. abbr_upper)) == ", " .. abbr_upper
           or string.sub(loc_upper, -string.len(" " .. abbr_upper)) == " " .. abbr_upper
           or loc_upper == abbr_upper then
            if sortKey ~= "" then
                return "[[Category:" .. categoryBase .. fullname .. "|" .. sortKey .. "]]"
            else
                return "[[Category:" .. categoryBase .. fullname .. "]]"
            end
        end
    end

    -- Check full state names
    for full_upper, fullname in pairs(stateNames) do
        if string.sub(loc_upper, -string.len(", " .. full_upper)) == ", " .. full_upper
           or string.sub(loc_upper, -string.len(" " .. full_upper)) == " " .. full_upper
           or loc_upper == full_upper then
            if sortKey ~= "" then
                return "[[Category:" .. categoryBase .. fullname .. "|" .. sortKey .. "]]"
            else
                return "[[Category:" .. categoryBase .. fullname .. "]]"
            end
        end
    end

    -- Fallback for non-US countries: take text after the last comma, trimmed
    local place = location:match(",%s*([^,]+)$") or location
    place = trim(place)

    -- Apply aliases if present
    local alias_upper = string.upper(place)
    if countryAliases[alias_upper] then
        place = countryAliases[alias_upper]
    end

    -- Add "the" for certain countries
    if countriesWithThe[string.upper(place)] then
        place = "the " .. place
    end

    if place ~= "" then
        if sortKey ~= "" then
            return "[[Category:" .. categoryBase .. place .. "|" .. sortKey .. "]]"
        else
            return "[[Category:" .. categoryBase .. place .. "]]"
        end
    end

    return "" -- nothing matched
end

return p