Module:SouthernStraitCorridorOps
From MicrasWiki
Documentation for this module may be created at Module:SouthernStraitCorridorOps/doc
-- Module:SouthernStraitCorridorOps
-- Southern Strait corridor display.
-- Pulls from:
-- Module:WarLeagueDivisionOpsBVR
-- Module:MissionaryDailyOpsBVR
-- Module:HatchMinistryDailyOps
--
-- This module intentionally overrides the displayed city/node to Mylecia
-- for all rendered War League, Temple Bank, and Hatch Ministry corridor rows.
local p = {}
--------------------------------------------------------------------------------
-- Configuration
--------------------------------------------------------------------------------
local SOUTHERN_STRAIT_CITY = "Mylecia"
local SOUTHERN_STRAIT_CITY_FLAG = "MyleciaFlabB.jpeg"
local CITY_PAGE = "List_of_cities_in_Bassaridia_Vaeringheim"
local DEFAULT_LIMIT = 24
local HAIFAN_STAGING_CITIES = {
["Keybir-Aviv"] = true,
["Tel-Amin"] = true,
["Diamandis"] = true,
["Jogi"] = true,
["Lewisburg"] = true,
["Thermosalem"] = true,
["Akróstadium"] = true,
["Sufriya"] = true,
["Lykopolis"] = true,
["Mylecia"] = true,
}
--------------------------------------------------------------------------------
-- Basic helpers
--------------------------------------------------------------------------------
local function trim(s)
return mw.text.trim(tostring(s or ""))
end
local function lower(s)
return mw.ustring.lower(tostring(s or ""))
end
local function safeRequire(name)
local ok, mod = pcall(require, name)
if ok and mod then
return mod
end
return nil
end
local function flagIcon(fileName, size)
size = tonumber(size) or 20
if not fileName or fileName == "" then
return ""
end
return string.format("[[File:%s|%dpx]]", fileName, size)
end
local function myleciaCell(flagSize)
return string.format(
"%s [[%s#Mylecia|Mylecia]]",
flagIcon(SOUTHERN_STRAIT_CITY_FLAG, flagSize),
CITY_PAGE
)
end
local function stripCellMarkup(s)
s = tostring(s or "")
s = s:gsub("<br%s*/?>", " ")
s = s:gsub("%[%[File:[^%]]+%]%]", "")
s = s:gsub("%[%[[^%]|]+|([^%]]+)%]%]", "%1")
s = s:gsub("%[%[([^%]]+)%]%]", "%1")
s = s:gsub("'''", "")
s = s:gsub("''", "")
return trim(s)
end
local function rowContainsSouthernStrait(text)
local t = lower(stripCellMarkup(text))
if t:find("southern strait", 1, true) then return true end
if t:find("southern straits", 1, true) then return true end
if t:find("former maritime markets", 1, true) then return true end
if t:find("maritime markets", 1, true) then return true end
if t:find("straits compliance", 1, true) then return true end
if t:find("strait compliance", 1, true) then return true end
if t:find("prize%-court") then return true end
if t:find("ferry lane") then return true end
if t:find("ferry%-lane") then return true end
if t:find("inland transfer") then return true end
if t:find("pilgrimage%-route") then return true end
if t:find("harbor%-to%-road") then return true end
for city in pairs(HAIFAN_STAGING_CITIES) do
if t:find(lower(city), 1, true) then
return true
end
end
return false
end
local function splitWikiCells(line)
line = tostring(line or "")
line = line:gsub("^|%s*", "")
local parts = mw.text.split(line, "%s*||%s*")
for i, v in ipairs(parts) do
parts[i] = trim(v)
end
return parts
end
local function firstNonEmpty(...)
for _, v in ipairs({ ... }) do
v = trim(v)
if v ~= "" then
return v
end
end
return "—"
end
local function statusStyle(statusText)
local s = lower(statusText)
if s:find("critical", 1, true) or s:find("red", 1, true) or s:find("closed", 1, true) or s:find("no%-go") then
return ' style="background-color:#f8d7da;"'
end
if s:find("high", 1, true) or s:find("orange", 1, true) or s:find("restricted", 1, true) or s:find("limited", 1, true) then
return ' style="background-color:#fff3cd;"'
end
if s:find("yellow", 1, true) or s:find("medium", 1, true) or s:find("slow", 1, true) then
return ' style="background-color:#fff3cd;"'
end
return ' style="background-color:#d4edda;"'
end
--------------------------------------------------------------------------------
-- Source parsers
--------------------------------------------------------------------------------
local function parseWarLeagueRows(text, args)
local rows = {}
local flagSize = tonumber(args.flagsize) or 20
local filterRows = tostring(args.filter or "yes"):lower() ~= "no"
local currentStyle = ""
for line in tostring(text or ""):gmatch("[^\r\n]+") do
local trimmed = trim(line)
if trimmed:match("^|%-") then
currentStyle = trimmed:gsub("^|%-", "")
elseif trimmed:match("^|") and not trimmed:match("^|}") then
local cells = splitWikiCells(trimmed)
-- WarLeagueDivisionOpsBVR expected:
-- Date, Division, City / Node, Daily event trigger, Urgency,
-- Operation, Ground Forces, Naval Forces, Aerial Forces, Oversight,
-- Compliance / Notes
if #cells >= 10 and lower(cells[1]) ~= "date" then
local combined = table.concat(cells, " ")
if (not filterRows) or rowContainsSouthernStrait(combined) then
local division = firstNonEmpty(cells[2])
local urgency = firstNonEmpty(cells[5])
local operation = firstNonEmpty(cells[6])
local forces = table.concat({
"'''Ground:''' " .. firstNonEmpty(cells[7]),
"'''Naval:''' " .. firstNonEmpty(cells[8]),
"'''Aerial:''' " .. firstNonEmpty(cells[9])
}, "<br>")
local notes = table.concat({
firstNonEmpty(cells[4]),
firstNonEmpty(cells[10]),
firstNonEmpty(cells[11])
}, "<br>")
table.insert(rows, {
style = currentStyle ~= "" and currentStyle or statusStyle(urgency .. " " .. notes),
source = "'''War League'''",
date = firstNonEmpty(cells[1]),
unit = division,
city = myleciaCell(flagSize),
status = urgency,
tasking = operation .. "<br>" .. forces,
notes = notes,
})
end
end
end
end
return rows
end
local function parseTempleRows(text, args)
local rows = {}
local flagSize = tonumber(args.flagsize) or 20
local filterRows = tostring(args.filter or "yes"):lower() ~= "no"
local currentStyle = ""
for line in tostring(text or ""):gmatch("[^\r\n]+") do
local trimmed = trim(line)
if trimmed:match("^|%-") then
currentStyle = trimmed:gsub("^|%-", "")
elseif trimmed:match("^|") and not trimmed:match("^|}") then
local cells = splitWikiCells(trimmed)
-- MissionaryDailyOpsBVR expected:
-- Date, City, Region, Ops Alert, Mystery (Cult), Unit,
-- Tasking, Temple Bank Notes, optional Threat Watch, Severity
if #cells >= 9 and lower(cells[1]) ~= "date" then
local combined = table.concat(cells, " ")
if (not filterRows) or rowContainsSouthernStrait(combined) then
local severity = cells[#cells]
local threat = (#cells >= 10) and cells[#cells - 1] or ""
local bankNotes = (#cells >= 10) and cells[#cells - 2] or cells[8]
table.insert(rows, {
style = currentStyle ~= "" and currentStyle or statusStyle(cells[4] .. " " .. severity),
source = "'''Temple Bank'''",
date = firstNonEmpty(cells[1]),
unit = firstNonEmpty(cells[5], cells[6]),
city = myleciaCell(flagSize),
status = firstNonEmpty(cells[4], severity),
tasking = "'''Unit:''' " .. firstNonEmpty(cells[6]) .. "<br>" .. firstNonEmpty(cells[7]),
notes = firstNonEmpty(bankNotes) .. (threat ~= "" and ("<br>'''Threat Watch:''' " .. threat) or ""),
})
end
end
end
end
return rows
end
local function parseHatchRows(text, args)
local rows = {}
local flagSize = tonumber(args.flagsize) or 20
local filterRows = tostring(args.filter or "yes"):lower() ~= "no"
local currentStyle = ""
for line in tostring(text or ""):gmatch("[^\r\n]+") do
local trimmed = trim(line)
if trimmed:match("^|%-") then
currentStyle = trimmed:gsub("^|%-", "")
elseif trimmed:match("^|") and not trimmed:match("^|}") then
local cells = splitWikiCells(trimmed)
-- HatchMinistryDailyOps expected:
-- Privateer Flag, Captain, Home City, Current Station,
-- Ops Alert, Rotation, Today's Activity
if #cells >= 7 and lower(cells[2]) ~= "captain" then
local combined = table.concat(cells, " ")
if (not filterRows) or rowContainsSouthernStrait(combined) then
table.insert(rows, {
style = currentStyle ~= "" and currentStyle or statusStyle(cells[5] .. " " .. cells[7]),
source = "'''Hatch Ministry'''",
date = firstNonEmpty(cells[6]),
unit = firstNonEmpty(cells[2]),
city = myleciaCell(flagSize),
status = firstNonEmpty(cells[5]),
tasking = firstNonEmpty(cells[7]),
notes = "'''Home city:''' " .. firstNonEmpty(cells[3]) .. "<br>'''Current station:''' " .. firstNonEmpty(cells[4]),
})
end
end
end
end
return rows
end
--------------------------------------------------------------------------------
-- Source loaders
--------------------------------------------------------------------------------
local function getWarLeagueRows(args)
local wl = safeRequire("Module:WarLeagueDivisionOpsBVR")
if not wl or type(wl.makeTable) ~= "function" then
return {}
end
local year = tostring(args.year or "")
local day = tostring(args.day or "")
local seed = tostring(args.seed or "")
local callArgs = {
rows = tostring(args.warRows or args.rows or "48"),
showlegend = "no",
}
if seed ~= "" then
callArgs.seed = seed
elseif year ~= "" and day ~= "" then
callArgs.seed = tostring((tonumber(year) or 0) * 1000 + (tonumber(day) or 0))
end
local ok, result = pcall(wl.makeTable, { args = callArgs })
if not ok then
return {}
end
return parseWarLeagueRows(result, args)
end
local function getTempleRows(args)
local miss = safeRequire("Module:MissionaryDailyOpsBVR")
if not miss or type(miss.makeTable) ~= "function" then
return {}
end
local callArgs = {
region = tostring(args.templeRegion or args.region or "Haifan Bassaridia"),
includeThreat = tostring(args.includeThreat or "no"),
showEcon = "no",
showlegend = "no",
limit = tostring(args.templeLimit or "80"),
}
if args.year then callArgs.year = tostring(args.year) end
if args.day then callArgs.day = tostring(args.day) end
local ok, result = pcall(miss.makeTable, { args = callArgs })
if not ok then
return {}
end
return parseTempleRows(result, args)
end
local function getHatchRows(args)
local hatch = safeRequire("Module:HatchMinistryDailyOps")
if not hatch or type(hatch.dailyReport) ~= "function" then
return {}
end
local callArgs = {
legend = "no",
}
if args.year then callArgs.year = tostring(args.year) end
if args.day then callArgs.day = tostring(args.day) end
if args.captain then callArgs.captain = tostring(args.captain) end
local ok, result = pcall(hatch.dailyReport, { args = callArgs })
if not ok then
return {}
end
return parseHatchRows(result, args)
end
--------------------------------------------------------------------------------
-- Rendering
--------------------------------------------------------------------------------
local function addRows(target, sourceRows, limit)
for _, row in ipairs(sourceRows) do
if #target >= limit then
return
end
table.insert(target, row)
end
end
local function renderTable(rows)
local out = {}
table.insert(out, "{| class='wikitable sortable' style='width:100%;'")
table.insert(out, "! Source !! Date / Rotation !! Unit !! City !! Status !! Tasking !! Notes")
if #rows == 0 then
table.insert(out, "|-")
table.insert(out, "| colspan='7' style='text-align:center;' | ''No Southern Strait corridor rows were returned by the source modules for this invocation.''")
else
for _, row in ipairs(rows) do
table.insert(out, "|-" .. (row.style or ""))
table.insert(out, string.format(
"| %s || %s || %s || %s || %s || %s || %s",
firstNonEmpty(row.source),
firstNonEmpty(row.date),
firstNonEmpty(row.unit),
firstNonEmpty(row.city),
firstNonEmpty(row.status),
firstNonEmpty(row.tasking),
firstNonEmpty(row.notes)
))
end
end
table.insert(out, "|}")
return table.concat(out, "\n")
end
local function renderLegend()
return table.concat({
"<div style='margin-top:0.5em; font-size:90%;'>",
"<b>Display note:</b> Southern Strait corridor rows are shown through ",
myleciaCell(20),
". Source-module tasking, Op-IDs, captains, units, and compliance notes are preserved; only the displayed corridor city is normalized for this page.",
"</div>"
}, "")
end
--------------------------------------------------------------------------------
-- Public entry points
--------------------------------------------------------------------------------
function p.makeTable(frame)
local args = (frame and frame.args) or {}
local limit = tonumber(args.limit) or DEFAULT_LIMIT
local showLegend = tostring(args.showlegend or args.legend or "yes"):lower() ~= "no"
local showHeader = tostring(args.header or "no"):lower() == "yes"
local rows = {}
local includeWar = tostring(args.war or "yes"):lower() ~= "no"
local includeTemple = tostring(args.temple or "yes"):lower() ~= "no"
local includeHatch = tostring(args.hatch or "yes"):lower() ~= "no"
if includeWar then
addRows(rows, getWarLeagueRows(args), limit)
end
if includeTemple then
addRows(rows, getTempleRows(args), limit)
end
if includeHatch then
addRows(rows, getHatchRows(args), limit)
end
local out = {}
if showHeader then
table.insert(out, "'''Southern Strait Corridor Daily Operations'''")
table.insert(out, "")
end
table.insert(out, renderTable(rows))
if showLegend then
table.insert(out, renderLegend())
end
return table.concat(out, "\n")
end
function p.dailyReport(frame)
return p.makeTable(frame)
end
function p.generateTable(frame)
return p.makeTable(frame)
end
function p.cityCell(frame)
local args = (frame and frame.args) or {}
return myleciaCell(args.flagsize or 20)
end
function p.dailyReport(frame)
return p.makeTable(frame)
end
function p.generateTable(frame)
return p.makeTable(frame)
end
function p.cityCell(frame)
local args = (frame and frame.args) or {}
return myleciaCell(args.flagsize or 20)
end
function p.southernStrait(frame)
return p.makeTable(frame)
end
return p