Module:Station
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