Module:SouthernStraitCorridorOps: Difference between revisions
From MicrasWiki
Jump to navigationJump to search
NewZimiaGov (talk | contribs) No edit summary |
NewZimiaGov (talk | contribs) No edit summary |
||
| Line 1: | Line 1: | ||
-- Module:SouthernStraitCorridorOps | -- Module:SouthernStraitCorridorOps | ||
-- Southern Strait | -- 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. | |||
-- War League and Hatch Ministry rows | |||
local p = {} | 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 | local function trim(s) | ||
return mw.text.trim(tostring(s or "")) | |||
end | end | ||
local function | local function lower(s) | ||
return | return mw.ustring.lower(tostring(s or "")) | ||
end | end | ||
local function safeRequire( | local function safeRequire(name) | ||
local ok, mod = pcall(require, | local ok, mod = pcall(require, name) | ||
if ok and mod then | if ok and mod then | ||
return mod | return mod | ||
end | end | ||
return nil | return nil | ||
end | end | ||
local function | local function flagIcon(fileName, size) | ||
size = tonumber(size) or 20 | |||
if not | if not fileName or fileName == "" then | ||
return | return "" | ||
end | 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 | |||
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 | end | ||
return | return false | ||
end | end | ||
local function | 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 | end | ||
return parts | |||
end | end | ||
local function | local function firstNonEmpty(...) | ||
for _, v in ipairs({ ... }) do | |||
v = trim(v) | |||
if v ~= "" then | |||
return v | |||
end | |||
end | end | ||
return "—" | |||
return " | |||
end | end | ||
local function | local function statusStyle(statusText) | ||
local | local s = lower(statusText) | ||
if | 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;"' | |||
return | |||
end | 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 | end | ||
return ' style="background-color:#d4edda;"' | |||
end | end | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- Source parsers | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
local | 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 | return rows | ||
end | end | ||
local function | 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 | 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 | ||
end | end | ||
return rows | |||
return | |||
end | end | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- Source loaders | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
local | local function getWarLeagueRows(args) | ||
local wl = safeRequire("Module:WarLeagueDivisionOpsBVR") | |||
if not wl or type(wl.makeTable) ~= "function" then | |||
return {} | |||
end | |||
local | 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", | |||
local | |||
} | } | ||
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 | local ok, result = pcall(wl.makeTable, { args = callArgs }) | ||
if not | if not ok then | ||
return | return {} | ||
end | end | ||
return parseWarLeagueRows(result, args) | |||
end | |||
local function getTempleRows(args) | |||
local miss = safeRequire("Module:MissionaryDailyOpsBVR") | |||
local | if not miss or type(miss.makeTable) ~= "function" then | ||
return {} | |||
end | end | ||
local | 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 | if args.year then callArgs.year = tostring(args.year) end | ||
if args.day then callArgs.day = tostring(args.day) end | |||
end | |||
local | local ok, result = pcall(miss.makeTable, { args = callArgs }) | ||
if not ok then | |||
return {} | |||
if | |||
end | end | ||
return | return parseTempleRows(result, args) | ||
end | end | ||
local function | local function getHatchRows(args) | ||
if not | local hatch = safeRequire("Module:HatchMinistryDailyOps") | ||
return | if not hatch or type(hatch.dailyReport) ~= "function" then | ||
return {} | |||
end | end | ||
local | 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 | local ok, result = pcall(hatch.dailyReport, { args = callArgs }) | ||
if not ok then | |||
return {} | |||
if not | |||
return | |||
end | end | ||
return parseHatchRows(result, args) | |||
end | end | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- Rendering | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
local function | local function addRows(target, sourceRows, limit) | ||
for _, row in ipairs(sourceRows) do | |||
if #target >= limit then | |||
return | |||
end | |||
table.insert(target, row) | |||
end | end | ||
end | end | ||
local function renderTable(rows) | |||
local out = {} | 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) | |||
)) | |||
table.insert(out, | |||
end | end | ||
end | end | ||
table.insert(out, "|}") | |||
return table.concat(out, "\n") | 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 | end | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- Public entry points | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
function p.makeTable(frame) | function p.makeTable(frame) | ||
local args = (frame and frame.args) or {} | 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 | local rows = {} | ||
local | local includeWar = tostring(args.war or "yes"):lower() ~= "no" | ||
local | 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 | end | ||
if | if includeTemple then | ||
addRows(rows, getTempleRows(args), limit) | |||
end | end | ||
if includeHatch then | if includeHatch then | ||
addRows(rows, getHatchRows(args), limit) | |||
end | end | ||
local out = {} | |||
if | if showHeader then | ||
table.insert(out, "'''Southern Strait Corridor Daily Operations'''") | |||
table.insert(out, "") | |||
table.insert(out, | |||
table.insert(out, | |||
end | end | ||
table.insert(out, renderTable(rows)) | |||
if showLegend then | if showLegend then | ||
table.insert(out, renderLegend()) | |||
table.insert(out, | |||
end | end | ||
| Line 785: | Line 457: | ||
end | end | ||
function p.dailyReport(frame) | |||
return p.makeTable(frame) | |||
function p. | |||
return p.makeTable( | |||
end | end | ||
function p. | function p.generateTable(frame) | ||
return p.makeTable(frame) | |||
return p.makeTable | |||
end | end | ||
function p. | function p.cityCell(frame) | ||
local args = (frame and frame.args) or {} | local args = (frame and frame.args) or {} | ||
args. | return myleciaCell(args.flagsize or 20) | ||
end | end | ||
return p | return p | ||
Revision as of 19:52, 5 June 2026
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
return p