Module:Station: Difference between revisions

From Nguhcraft Wiki
Jump to navigation Jump to search
Biangfox (talk | contribs)
No edit summary
Biangfox (talk | contribs)
No edit summary
Line 4: Line 4:
-- Load the main railway network data
-- Load the main railway network data
local data = mw.loadJsonData("Data:NguhRoutes/network.json")
local data = mw.loadJsonData("Data:NguhRoutes/network.json")
-- Predefined display names for known lines
local lineDisplayNames = {
    CN = "Central Line",
    ZY = "Zyrian Line",
    AQ = "Aquatic Line",
    NO = "Northern Line",
    LC = "Line of Chaos",
    MT = "Mountain Line",
    WE = "Western Line",
    OL = "Olympic Line",
    AR = "Archipelago Line",
    TR = "Traeth Line",
    TV = "Transversal Line",
    FR = "Forest Line",
    CR = "Crystal Line",
    SO = "Southern Line",
    LQ = "Lautseq Line",
    NgE = "Ŋerlin Line",
    CU = "Cuban Line",
    CO = "Corner Line",
    TF = "Transfortunate Line",
    NgA = "Ŋafrican Line",
    MI = "Mitosis Line",
    SL = "Slab Line",
    LL = "Local Line",
    FE = "FERRA"
    -- Note: LKL is NOT here since it's a station code, not a line
}


-- Helper function to find a station by code
-- Helper function to find a station by code
local function findStation(code)
local function findStation(code)
    -- Direct lookup in stations table
     return data.stations[code]
     return data.stations[code]
end
end
Line 20: Line 48:
             for _, stop in ipairs(line.stops) do
             for _, stop in ipairs(line.stops) do
                 if type(stop) == "table" then
                 if type(stop) == "table" then
                    -- Check if this stop matches our station
                     local fullCode = (dimension == "the_nether" and "N-" or "") .. stop.code
                     local fullCode = (dimension == "the_nether" and "N-" or "") .. stop.code
                     if fullCode == stationCode then
                     if fullCode == stationCode then
                        -- This line serves our station
                         servedLines[line.code] = {
                         servedLines[line.code] = {
                             name = line.name,
                             name = line.name,
Line 44: Line 70:
     end
     end
      
      
    -- Remove # if present
     hexColor = hexColor:gsub("#", "")
     hexColor = hexColor:gsub("#", "")
      
      
     -- Convert to RGB
     -- Handle 3-character hex codes
    if #hexColor == 3 then
        hexColor = hexColor:gsub("(.)", "%1%1")
    end
   
     local r = tonumber(hexColor:sub(1, 2), 16) or 0
     local r = tonumber(hexColor:sub(1, 2), 16) or 0
     local g = tonumber(hexColor:sub(3, 4), 16) or 0
     local g = tonumber(hexColor:sub(3, 4), 16) or 0
     local b = tonumber(hexColor:sub(5, 6), 16) or 0
     local b = tonumber(hexColor:sub(5, 6), 16) or 0
      
      
     -- Calculate relative luminance
     if not r or not g or not b then
        return "000"
    end
   
     local luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
     local luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
    return luminance < 0.5 and "fff" or "000"
end
-- Function to create a display name for any line code
local function getLineDisplayName(lineCode, lineData)
    -- Check predefined names first
    if lineDisplayNames[lineCode] then
        return lineDisplayNames[lineCode]
    end
      
      
     -- Return white text for dark backgrounds, black for light
     -- Use line name from data
    return luminance < 0.5 and "fff" or "000"
    if lineData and lineData.name then
        return lineData.name
    end
   
    -- Default: convert code to readable name
    if lineCode:sub(1, 2) == "Ng" then
        return "Ŋ" .. lineCode:sub(3) .. " Line"
    end
   
    return lineCode .. " Line"
end
end


-- Main function to generate infobox
-- Main function to generate infobox
p.infobox = function(frame)
p.infobox = function(frame)
    -- Get the station code from the first parameter
     local code = frame.args[1] or frame.args.code or ""
     local code = frame.args[1] or frame.args.code or ""
      
      
Line 68: Line 117:
     end
     end
      
      
    -- Find the station in the dataset
     local station = findStation(code)
     local station = findStation(code)
      
      
Line 75: Line 123:
     end
     end
      
      
    -- Determine which lines serve this station
     local servedLines = getLinesForStation(code)
     local servedLines = getLinesForStation(code)
   
    -- Start building the infobox
     local output = {}
     local output = {}
      
      
Line 84: Line 129:
     table.insert(output, '{{Infobox')
     table.insert(output, '{{Infobox')
      
      
     -- Above section with station name
     -- Above section
     local stationName = station[1] or "Unknown Station"
     local stationName = station[1] or station.name or "Unknown Station"
     table.insert(output, '| above = ' .. stationName)
     table.insert(output, '| above = ' .. stationName)
      
      
     -- Header section with code and optional Leshrail symbol
     -- Header section
     local header = string.format('%s [%s]', stationName, code)
     local header = string.format('%s [%s]', stationName, code)
   
    -- Check if this is a Leshrail station (Nether station)
     if code:sub(1, 2) == "N-" then
     if code:sub(1, 2) == "N-" then
         header = header .. ' [[File:LeshrailSymbol.png|frameless|upright=0.3|link=Leshrail]]'
         header = header .. ' [[File:LeshrailSymbol.png|frameless|upright=0.3|link=Leshrail]]'
Line 97: Line 140:
     table.insert(output, '| header1 = ' .. header)
     table.insert(output, '| header1 = ' .. header)
      
      
     -- Image section (if station has image data)
     -- Image section
     if station.image then
     if station.image then
         table.insert(output, '| image = ' .. station.image)
         table.insert(output, '| image = ' .. station.image)
Line 106: Line 149:
     local lineCount = 1
     local lineCount = 1
      
      
     -- Mapping of line codes to display names
     -- Sort line codes for consistent output
     local lineDisplayNames = {
     local sortedLineCodes = {}
        CN = "Central Line",
    for lineCode in pairs(servedLines) do
        ZY = "Zyrian Line",
         table.insert(sortedLineCodes, lineCode)
         AQ = "Aquatic Line",
    end
        NO = "Northern Line",
     table.sort(sortedLineCodes)
        LC = "Line of Chaos",
        MT = "Mountain Line",
        WE = "Western Line",
        OL = "Olympic Line",
        AR = "Archipelago Line",
        TR = "Traeth Line",
        TV = "Transversal Line",
        FR = "Forest Line",
        CR = "Crystal Line",
        SO = "Southern Line",
        LQ = "Lautseq Line",
        NgE = "Ŋerlin Line",
        CU = "Cuban Line",
        CO = "Corner Line",
        TF = "Transfortunate Line",
        NgA = "Ŋafrican Line",
        MI = "Mitosis Line",
        SL = "Slab Line",
        LL = "Local Line",
        FE = "FERRA"  -- Special case, handled separately
     }
      
      
     -- Check each possible line
     -- Process each line
     local lineOrder = {"CN", "ZY", "AQ", "NO", "LC", "MT", "WE", "OL", "AR", "TR",  
     for _, lineCode in ipairs(sortedLineCodes) do
                      "TV", "FR", "CR", "SO", "LQ", "NgE", "CU", "CO", "TF",
        lineCount = lineCount + 1
                      "NgA", "MI", "SL", "LL", "FE"}
        local lineData = servedLines[lineCode]
   
       
    for _, lineCode in ipairs(lineOrder) do
        if lineCode == "FE" then
        if servedLines[lineCode] then
            -- FERRA line (special handling)
            lineCount = lineCount + 1
            table.insert(output, string.format('| header%d = [[File:FERRAlogo.png|frameless|upright=0.3|link=FERRA]]',  
                lineCount))
            table.insert(output, string.format('| header%dstyle = background:#a4a4c6',  
                lineCount))
        elseif lineCode == "LL" then
            -- Local Line (special handling)
            local localLineName = station.local_line_name or "Local Rail Services"
            table.insert(output, string.format('| header%d = {{colorlink|FFF|Cenrail#Local_Rail_Services|%s}}',  
                lineCount, localLineName))
            table.insert(output, string.format('| header%dstyle = background:#555',  
                lineCount))
        else
            -- Regular line
            local displayName = getLineDisplayName(lineCode, lineData)
            local wikiLinkName = displayName:gsub(" Line", ""):gsub(" ", "_")
            local textColor = getTextColor(lineData.color)
            local bgColor = lineData.color:gsub("#", "")
              
              
             if lineCode == "FE" then
             table.insert(output, string.format('| header%d = {{Colorlink|%s|Cenrail#%s|%s}}',  
                -- Special handling for FERRA
                lineCount, textColor, wikiLinkName, displayName))
                table.insert(output, string.format('| header%d = [[File:FERRAlogo.png|frameless|upright=0.3|link=FERRA]]',
            table.insert(output, string.format('| header%dstyle = background:#%s',  
                    lineCount))
                lineCount, bgColor))
                table.insert(output, string.format('| header%dstyle = background:#a4a4c6',
                    lineCount))
            elseif lineCode == "LL" then
                -- Special handling for Local Line
                local localLineName = station.local_line_name or "Local Rail Services"
                table.insert(output, string.format('| header%d = {{colorlink|FFF|Cenrail#Local_Rail_Services|%s}}',
                    lineCount, localLineName))
                table.insert(output, string.format('| header%dstyle = background:#555',
                    lineCount))
            else
                -- Regular line handling
                local lineData = servedLines[lineCode]
                local displayName = lineDisplayNames[lineCode] or lineCode .. " Line"
                local textColor = getTextColor(lineData.color)
                local bgColor = lineData.color:gsub("#", "")
               
                table.insert(output, string.format('| header%d = {{Colorlink|%s|Cenrail#%s|%s}}',  
                    lineCount, textColor, displayName:gsub(" ", "_"), displayName))
                table.insert(output, string.format('| header%dstyle = background:#%s',  
                    lineCount, bgColor))
            end
         end
         end
     end
     end
   
    -- REMOVED THE PROBLEMATIC "No lines found" MESSAGE
    -- If a station truly has no lines, it will just show header and image
      
      
     -- Close the infobox
     -- Close the infobox
     table.insert(output, '}}')
     table.insert(output, '}}')
      
      
    -- Return the complete infobox wikitext
     return table.concat(output, '\n')
     return table.concat(output, '\n')
end
end


-- Alternative function that returns data for debugging
-- Test function to check specific station
p.getStationInfo = function(frame)
p.test = function(frame)
     local code = frame.args[1] or frame.args.code or ""
     local code = frame.args[1] or "SVG" -- Default to SVG for testing
   
    if code == "" then
        return "No code provided"
    end
      
      
     local station = findStation(code)
     local station = findStation(code)
    if not station then
        return "Station not found: " .. code
    end
   
     local servedLines = getLinesForStation(code)
     local servedLines = getLinesForStation(code)
      
      
     local result = { "=== Station: " .. code .. " ===" }
     local result = {
    table.insert(result, "Name: " .. (station[1] or "Unknown"))
        "=== Testing Station: " .. code .. " ===",
   
        "Station found: " .. tostring(station ~= nil),
    if station.image then
         ""
         table.insert(result, "Image: " .. station.image)
     }
     end
      
      
     if station.caption then
     if station then
         table.insert(result, "Caption: " .. station.caption)
         result[#result + 1] = "Station name: " .. (station[1] or "No name")
        result[#result + 1] = "Station type: " .. type(station)
        result[#result + 1] = ""
     end
     end
      
      
     table.insert(result, "")
     result[#result + 1] = "Lines serving this station (" .. #servedLines .. "):"
    table.insert(result, "=== Lines serving this station ===")
      
      
     for lineCode, lineData in pairs(servedLines) do
     if next(servedLines) then
        table.insert(result, string.format("- %s: %s (Color: %s)",  
        for lineCode, lineData in pairs(servedLines) do
            lineCode, lineData.name, lineData.color))
            result[#result + 1] = string.format("- %s: %s (color: %s)",  
                lineCode, lineData.name, lineData.color)
        end
    else
        result[#result + 1] = "- No lines found"
     end
     end
      
      
     if next(servedLines) == nil then
     result[#result + 1] = ""
        table.insert(result, "No lines found for this station")
    result[#result + 1] = "=== Generated Infobox ==="
     end
     result[#result + 1] = p.infobox(frame)
      
      
     return table.concat(result, "\n")
     return table.concat(result, "\n")

Revision as of 07:02, 7 January 2026

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

-- Module:InfoboxStation
local p = {}

-- Load the main railway network data
local data = mw.loadJsonData("Data:NguhRoutes/network.json")

-- Predefined display names for known lines
local lineDisplayNames = {
    CN = "Central Line",
    ZY = "Zyrian Line", 
    AQ = "Aquatic Line",
    NO = "Northern Line",
    LC = "Line of Chaos",
    MT = "Mountain Line",
    WE = "Western Line",
    OL = "Olympic Line",
    AR = "Archipelago Line",
    TR = "Traeth Line",
    TV = "Transversal Line",
    FR = "Forest Line",
    CR = "Crystal Line",
    SO = "Southern Line",
    LQ = "Lautseq Line",
    NgE = "Ŋerlin Line",
    CU = "Cuban Line",
    CO = "Corner Line",
    TF = "Transfortunate Line",
    NgA = "Ŋafrican Line",
    MI = "Mitosis Line",
    SL = "Slab Line",
    LL = "Local Line",
    FE = "FERRA"
    -- Note: LKL is NOT here since it's a station code, not a line
}

-- Helper function to find a station by code
local function findStation(code)
    return data.stations[code]
end

-- Helper function to determine which lines serve this station
local function getLinesForStation(stationCode)
    local servedLines = {}
    
    -- Check both overworld and nether lines
    for dimension, lines in pairs(data.lines) do
        for _, line in ipairs(lines) do
            for _, stop in ipairs(line.stops) do
                if type(stop) == "table" then
                    local fullCode = (dimension == "the_nether" and "N-" or "") .. stop.code
                    if fullCode == stationCode then
                        servedLines[line.code] = {
                            name = line.name,
                            color = line.color or "#000000",
                            dimension = dimension
                        }
                    end
                end
            end
        end
    end
    
    return servedLines
end

-- Function to convert hex color to text color (light/dark)
local function getTextColor(hexColor)
    if not hexColor or hexColor == "" then
        return "000"
    end
    
    hexColor = hexColor:gsub("#", "")
    
    -- Handle 3-character hex codes
    if #hexColor == 3 then
        hexColor = hexColor:gsub("(.)", "%1%1")
    end
    
    local r = tonumber(hexColor:sub(1, 2), 16) or 0
    local g = tonumber(hexColor:sub(3, 4), 16) or 0
    local b = tonumber(hexColor:sub(5, 6), 16) or 0
    
    if not r or not g or not b then
        return "000"
    end
    
    local luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
    return luminance < 0.5 and "fff" or "000"
end

-- Function to create a display name for any line code
local function getLineDisplayName(lineCode, lineData)
    -- Check predefined names first
    if lineDisplayNames[lineCode] then
        return lineDisplayNames[lineCode]
    end
    
    -- Use line name from data
    if lineData and lineData.name then
        return lineData.name
    end
    
    -- Default: convert code to readable name
    if lineCode:sub(1, 2) == "Ng" then
        return "Ŋ" .. lineCode:sub(3) .. " Line"
    end
    
    return lineCode .. " Line"
end

-- Main function to generate infobox
p.infobox = function(frame)
    local code = frame.args[1] or frame.args.code or ""
    
    if code == "" then
        return "'''Error: No station code provided'''"
    end
    
    local station = findStation(code)
    
    if not station then
        return "'''Error: Station '" .. code .. "' not found in dataset'''"
    end
    
    local servedLines = getLinesForStation(code)
    local output = {}
    
    -- Infobox opening
    table.insert(output, '{{Infobox')
    
    -- Above section
    local stationName = station[1] or station.name or "Unknown Station"
    table.insert(output, '| above = ' .. stationName)
    
    -- Header section
    local header = string.format('%s [%s]', stationName, code)
    if code:sub(1, 2) == "N-" then
        header = header .. ' [[File:LeshrailSymbol.png|frameless|upright=0.3|link=Leshrail]]'
    end
    table.insert(output, '| header1 = ' .. header)
    
    -- Image section
    if station.image then
        table.insert(output, '| image = ' .. station.image)
        table.insert(output, '| caption = ' .. (station.caption or stationName))
    end
    
    -- Add lines that serve this station
    local lineCount = 1
    
    -- Sort line codes for consistent output
    local sortedLineCodes = {}
    for lineCode in pairs(servedLines) do
        table.insert(sortedLineCodes, lineCode)
    end
    table.sort(sortedLineCodes)
    
    -- Process each line
    for _, lineCode in ipairs(sortedLineCodes) do
        lineCount = lineCount + 1
        local lineData = servedLines[lineCode]
        
        if lineCode == "FE" then
            -- FERRA line (special handling)
            table.insert(output, string.format('| header%d = [[File:FERRAlogo.png|frameless|upright=0.3|link=FERRA]]', 
                lineCount))
            table.insert(output, string.format('| header%dstyle = background:#a4a4c6', 
                lineCount))
        elseif lineCode == "LL" then
            -- Local Line (special handling)
            local localLineName = station.local_line_name or "Local Rail Services"
            table.insert(output, string.format('| header%d = {{colorlink|FFF|Cenrail#Local_Rail_Services|%s}}', 
                lineCount, localLineName))
            table.insert(output, string.format('| header%dstyle = background:#555', 
                lineCount))
        else
            -- Regular line
            local displayName = getLineDisplayName(lineCode, lineData)
            local wikiLinkName = displayName:gsub(" Line", ""):gsub(" ", "_")
            local textColor = getTextColor(lineData.color)
            local bgColor = lineData.color:gsub("#", "")
            
            table.insert(output, string.format('| header%d = {{Colorlink|%s|Cenrail#%s|%s}}', 
                lineCount, textColor, wikiLinkName, displayName))
            table.insert(output, string.format('| header%dstyle = background:#%s', 
                lineCount, bgColor))
        end
    end
    
    -- REMOVED THE PROBLEMATIC "No lines found" MESSAGE
    -- If a station truly has no lines, it will just show header and image
    
    -- Close the infobox
    table.insert(output, '}}')
    
    return table.concat(output, '\n')
end

-- Test function to check specific station
p.test = function(frame)
    local code = frame.args[1] or "SVG"  -- Default to SVG for testing
    
    local station = findStation(code)
    local servedLines = getLinesForStation(code)
    
    local result = {
        "=== Testing Station: " .. code .. " ===",
        "Station found: " .. tostring(station ~= nil),
        ""
    }
    
    if station then
        result[#result + 1] = "Station name: " .. (station[1] or "No name")
        result[#result + 1] = "Station type: " .. type(station)
        result[#result + 1] = ""
    end
    
    result[#result + 1] = "Lines serving this station (" .. #servedLines .. "):"
    
    if next(servedLines) then
        for lineCode, lineData in pairs(servedLines) do
            result[#result + 1] = string.format("- %s: %s (color: %s)", 
                lineCode, lineData.name, lineData.color)
        end
    else
        result[#result + 1] = "- No lines found"
    end
    
    result[#result + 1] = ""
    result[#result + 1] = "=== Generated Infobox ==="
    result[#result + 1] = p.infobox(frame)
    
    return table.concat(result, "\n")
end

return p