Module:ElectoralCalendarMap

From Elections Wiki
Revision as of 21:13, 26 January 2025 by Dartz (talk | contribs)
Jump to navigation Jump to search

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

local p = {}

function p.load(frame)
    -- i understand chocolateman now, we can't fetch data from an outside source due to mediawiki's stupid restrictions
    local dataPage = "Data:Election_Data.json"
    
    local dataTitle = mw.title.new(dataPage)
    if not dataTitle then
        return "could not find data page '" .. dataPage .. "'!"
    end
    
    local dataContent = dataTitle:getContent()
    if not dataContent then
        return "could not retrieve content from '" .. dataPage .. "'!"
    end
    
    -- Parse the JSON data
    local APIData = mw.text.jsonDecode(dataContent)
    if not APIData then
        return "invalid JSON content in '" .. dataPage .. "'!"
    end
    
    local electionColors = {
        General = "#4682b4", -- blue
        Local = "#8a2be2", -- purple
        Statewide = "#008000", -- green
        Referendum = "#ffa500" -- orange
    }
    
    -- get date
    local currentDate = os.date("!%Y-%m-%dT%H:%M:%S") 
    local combinedJSON = {}
    
    -- i'll try to clean up older elections of course,
    -- but a function to remove old ones is a good idea.
    local function isNewElection(electionDate)
        -- make it consistent with our format
        local formattedDate = mw.ustring.gsub(electionDate, "[-:T]", ""):sub(1, 14) 
        local formattedCurrentDate = mw.ustring.gsub(currentDate, "[-:T]", ""):sub(1, 14)
        return formattedDate > formattedCurrentDate
    end
    
    local function generateDescription(elections)
    	local descriptionBits = {}
    	for _, election in ipairs(elections) do
    		table.insert(descriptionBits, string.format(
    			"<b>%s</b><br>%s<br>%s",
    			election.election_name,
    			election.date,
    			election.description
    		))
    	end
    	return table.concat(descriptionBits, "<br><br>")
    end
    
    for region, elections in pairs(APIData) do
        local mapDataTitle = mw.title.new("MapData:" .. region .. ".map")
        
        if mapDataTitle then
            local content = mapDataTitle:getContent()
            if content then
                local parsedContent = mw.text.jsonDecode(content)
                if parsedContent and type(parsedContent.features) == "table" then
                    for _, feature in ipairs(parsedContent.features) do
                        local validElections = {}
                        for _, election in ipairs(elections) do
                            if isNewElection(election.date) then
								table.insert(validElections, election)
                            end
                        end
                        
                        if #validElections > 0 then 
                        	feature.properties.title = string.gsub(region, "_", " ")
                            feature.properties.description = generateDescription(validElections)
                            
                            local fillColor = electionColors[validElections[1].election_type] or "#404040"
                            feature.properties.fill = fillColor
                            feature.properties["fill-opacity"] = 0.8
                           
                            -- filter out "invalid" elections for now
                            if feature.properties.fill ~= "#555555" then
                                table.insert(combinedJSON, feature)
                            end
                        else
                        	mw.log("election date passed for '" .. region .. "'!")
                        end
                    end
                else
                    mw.log("invalid or missing features in mapdata for region '" .. region .. "'!")
                end
            else
                mw.log("warning: couldn't fetch mapdata for region '" .. region .. "'!")
            end
        else
            mw.log("warning: couldn't create title object for region '" .. region .. "'!")
        end
    end
    
    local combinedMapData = mw.text.jsonEncode({
        type = "FeatureCollection",
        features = combinedJSON
    })
    
    local mapFrame = '<mapframe width="100%" height="400" zoom="3" longitude="0" latitude="0">' .. combinedMapData .. '</mapframe>'
    --local mapFrame = '' .. combinedMapData .. ''
    
    return frame:preprocess(mapFrame)
end

return p