Module:StraitsDaily: 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: StraitsDaily | -- Module: StraitsDaily | ||
-- Purpose: Daily, in-world report of Strait of Haifa enforcement | -- Purpose: Daily, in-world report of Strait of Haifa enforcement | ||
local p = {} | local p = {} | ||
| Line 36: | Line 35: | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
local sectors = { | local sectors = { | ||
"Strait South Inbound", "Strait South Outbound", "Strait North Inbound", "Strait North Outbound", | "Strait South Inbound","Strait South Outbound","Strait North Inbound","Strait North Outbound", | ||
"Archipelago Zone", "Sacred Buffer Approaches", "Environmental Buffer", "Northern Approach TSS", "Southern Approach TSS" | "Archipelago Zone","Sacred Buffer Approaches","Environmental Buffer","Northern Approach TSS","Southern Approach TSS" | ||
} | } | ||
| Line 54: | Line 53: | ||
local vessels = { | local vessels = { | ||
"Handymax bulker", "Product tanker", "General cargo ship", "Container feeder", | "Handymax bulker","Product tanker","General cargo ship","Container feeder", | ||
"Ro-Ro ferry", "Research craft", "Declared submarine", "Undeclared submarine" | "Ro-Ro ferry","Research craft","Declared submarine","Undeclared submarine" | ||
} | } | ||
| Line 90: | Line 89: | ||
{code="P-44", weight=4, risk=0.02}, | {code="P-44", weight=4, risk=0.02}, | ||
{code="P-53", weight=3, risk=0.04} | {code="P-53", weight=3, risk=0.04} | ||
} | |||
-- White-Lane corridors (codes + typical windows). Used for annotation only. | |||
local wlCorridors = { | |||
{code="WL-NZ-1", name="Lucíusu–Corum Electric City", win="0700–1100"}, | |||
{code="WL-GM-2", name="Ossyo–Lake Norton South Shore", win="0900–1300"}, | |||
{code="WL-SEA-3", name="Corumia–Western Corum Coastal (short-sea)", win="0600–1800"} | |||
} | |||
-- Neutral observer pool (for WL attestation note) | |||
local observers = { | |||
"Neutral temple auditor","Independent port compliance inspector", | |||
"Community elder (witness)","Straits Convention monitor (civilian)" | |||
} | } | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
-- (C) | -- (C) HELPERS | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
function | local function pick(list) return list[math.random(#list)] end | ||
local function pickWeighted(list) | |||
local total = 0 | |||
for _, item in ipairs(list) do total = total + (item.weight or 1) end | |||
local roll, cumul = math.random(total), 0 | |||
for _, item in ipairs(list) do | |||
cumul = cumul + (item.weight or 1) | |||
if roll <= cumul then return item end | |||
end | end | ||
return list[#list] | |||
end | |||
local | -- Determine if this row qualifies for White-Lane annotation (Annex G eligibility, simplified) | ||
local function isWhiteLane(cargo, tag) | |||
if not cargo or not tag then return false end | |||
-- Green/Amber cargoes likely eligible when not dual-use and tagged time-sensitive | |||
local green = (cargo.name == "Relief supplies (mixed pallets)" or cargo.name == "Agricultural commodities") | |||
local amber = (tag.name == "expedited" or tag.name == "emergency" or tag.name == "perishable") | |||
return (green and not cargo.dual) or (amber and not cargo.dual) | |||
end | |||
-- Build legal basis string per Conventions | |||
local function legalBasis(sector, wl) | |||
if wl then | |||
return "Art III.5 (White-Lane); Annex G; Art X.3 (expedited remedies)" | |||
end | end | ||
if sector == "Sacred Buffer Approaches" or sector == "Environmental Buffer" then | |||
return "Art III.2.3 (Sacred quiet zones); Annex A (delims); Art VII; Annex D" | |||
end | |||
return "Art IV.1–1.2 (PSC); Annex F (SCT/SAC procedures)" | |||
end | |||
-- Appeals column text | |||
local function appealsStatus(sector, wl, tag, cargo) | |||
-- | if wl then | ||
local | -- Expedited track per Art X.3 | ||
if sector == "Sacred Buffer Approaches" or sector == "Environmental Buffer" | local outcome | ||
local relief = 0.60 | |||
if tag and (tag.name=="emergency" or tag.name=="perishable") then relief = relief + 0.12 end | |||
if cargo and cargo.dual then relief = relief - 0.15 end | |||
end | local r = math.random() | ||
if r <= relief * 0.6 then outcome = "clearance granted" | |||
elseif r <= relief then outcome = "expedited with conditions" | |||
else outcome = "conditions imposed" end | |||
return string.format("HCE Review → SCT (72h) → SAC (≤5d) — %s (Art X.3; Annex G)", outcome) | |||
else | |||
local level = (sector=="Sacred Buffer Approaches" or sector=="Environmental Buffer") and "SAC Referral" or | |||
((math.random()<0.5) and "SCT Admin Review" or "PSC reconciliation") | |||
local outcome = (level=="PSC reconciliation") and "notice acknowledged" or | |||
((math.random()<0.5) and "clearance granted" or "conditions imposed") | |||
local cite = (level=="SAC Referral") and "Annex F (SAC)" or "Annex F (SCT)" | |||
return string.format("%s — %s (%s)", level, outcome, cite) | |||
end | |||
end | |||
-- Simple HCE reference (for WL notes) | |||
local function hceRef(dateInfo, corridor) | |||
return string.format("HCE-%03d.%03d-%s", dateInfo.year, dateInfo.dayOfYear, corridor.code) | |||
end | |||
------------------------------------------------------------------------------- | |||
-- (D) MAIN GENERATION | |||
------------------------------------------------------------------------------- | |||
function p.makeTable(frame) | |||
local dateInfo = getPSSCDate() | |||
math.randomseed(dateInfo.year*1000 + dateInfo.dayOfYear) | |||
local rows = tonumber(frame and frame.args and frame.args.rows) or 18 | |||
local out = {} | local out = {} | ||
table.insert(out, "{| class='wikitable sortable'") | table.insert(out, "{| class='wikitable sortable'") | ||
table.insert(out, "! Date !! Sector !! Vessel/Flag !! Action !! Legal Basis !! Outcome !! Appeals/Review (Straits Conventions) !! Notes") | table.insert(out, "! Date !! Sector !! Vessel/Flag !! Action !! Legal Basis !! Outcome !! Appeals/Review (Straits Conventions) !! Notes") | ||
for _ = 1, rows do | for _ = 1, rows do | ||
local sector = pick(sectors) | local sector = pick(sectors) | ||
local flag = pickWeighted(flags) | local flag = pickWeighted(flags) | ||
local vessel = pick(vessels) | local vessel = pick(vessels) | ||
local cargo = pickWeighted(cargoTypes) | local cargo = pickWeighted(cargoTypes) | ||
local tag = pickWeighted(cargoTags) | local tag = pickWeighted(cargoTags) | ||
local partner = pickWeighted(partnerProfiles) | local partner = pickWeighted(partnerProfiles) | ||
local enforce = baseProb( | local wlEligible = isWhiteLane(cargo, tag) | ||
local corridor = wlEligible and pick(wlCorridors) or nil | |||
local obs = wlEligible and pick(observers) or nil | |||
-- Base enforcement probability | |||
local function baseProb() | |||
local q = 0.28 | |||
if flag.risky then q = q + 0.06 end | |||
if sector == "Sacred Buffer Approaches" or sector == "Environmental Buffer" then q = q + 0.08 end | |||
q = q + (cargo and cargo.risk or 0) | |||
if cargo and cargo.dual then q = q + 0.03 end | |||
q = q + (tag and tag.risk or 0) | |||
q = q + (partner and partner.risk or 0) | |||
-- WL usually lowers friction (pre-cleared), but can still be inspected | |||
if wlEligible then q = math.max(q - 0.06, 0.10) end | |||
return math.min(q, 0.72) | |||
end | |||
local enforce = baseProb() | |||
local action, legal, outcome, notes, appealCol | |||
if wlEligible then | |||
action = "WL transit / pilotage verification" | |||
legal = legalBasis(sector, true) | |||
notes = string.format("WL %s (%s) | window %s | Observer: %s | %s | Cargo: %s [%s]; Partner: %s", | |||
corridor.code, corridor.name, corridor.win, (obs or "n/a"), | |||
hceRef(dateInfo, corridor), cargo.name, tag.name, partner.code) | |||
else | |||
action = "Cargo manifest reconciliation audit" | |||
legal = legalBasis(sector, false) | |||
notes = string.format("Cargo: %s [%s]; Partner: %s", cargo.name, tag.name, partner.code) | |||
end | |||
if math.random() > enforce then | if math.random() > enforce then | ||
outcome = "No reports" | outcome = wlEligible and "Cleared WL window" or "No reports" | ||
appealCol = wlEligible and "N/A (WL cleared)" or "N/A" | |||
else | else | ||
outcome = wlEligible and "WL reconciliation check; monitoring" or "Administrative notice issued; monitoring" | |||
-- push to hold if multiple risk factors present | |||
local riskPush = 0 | local riskPush = 0 | ||
if flag.name:match("Imperial Federation") or flag.name:match("Matamoros") then riskPush = riskPush + 1 end | if flag.name:match("Imperial Federation") or flag.name:match("Matamoros") then riskPush = riskPush + 1 end | ||
if cargo.dual or cargo.risk >= 0.12 then riskPush = riskPush + 1 end | if cargo.dual or (cargo.risk or 0) >= 0.12 then riskPush = riskPush + 1 end | ||
if tag.name ~= "standard" then riskPush = riskPush + 1 end | if tag.name ~= "standard" then riskPush = riskPush + 1 end | ||
if partner.risk >= 0.09 then riskPush = riskPush + 1 end | if (partner.risk or 0) >= 0.09 then riskPush = riskPush + 1 end | ||
if wlEligible then riskPush = math.max(riskPush - 1, 0) end | |||
if riskPush >= 2 and math.random() < 0.65 then | if riskPush >= 2 and math.random() < 0.65 then | ||
outcome = "Random audit hold; clearance pending | outcome = (wlEligible and "WL hold; clearance pending expedited review" or "Random audit hold; clearance pending") | ||
if flag.name == "Imperial Federation" or flag.name == "Matamoros (IF)" then | if flag.name == "Imperial Federation" or flag.name == "Matamoros (IF)" then | ||
outcome = outcome .. " [Extended regulatory review]" | outcome = outcome .. " [Extended regulatory review]" | ||
| Line 218: | Line 242: | ||
end | end | ||
appealCol = appealsStatus(sector, wlEligible, tag, cargo) | |||
appealCol = appealsStatus(sector, | |||
end | end | ||
Revision as of 03:24, 10 September 2025
Documentation for this module may be created at Module:StraitsDaily/doc
-- Module: StraitsDaily
-- Purpose: Daily, in-world report of Strait of Haifa enforcement
local p = {}
-------------------------------------------------------------------------------
-- (A) PSSC DATE
-------------------------------------------------------------------------------
local function getPSSCDate()
local startDate = os.time({year = 1999, month = 8, day = 6})
local secondsInDay = 86400
local daysPerYear = 183
local now = os.time()
local totalDaysElapsed = math.floor((now - startDate) / secondsInDay)
local yearFraction = totalDaysElapsed / daysPerYear
local psscYear = math.floor(yearFraction)
local dayOfYear = math.floor((yearFraction - psscYear) * daysPerYear) + 1
local month, dayOfMonth
if dayOfYear <= 61 then
month = 1; dayOfMonth = dayOfYear
elseif dayOfYear <= 122 then
month = 2; dayOfMonth = dayOfYear - 61
else
month = 3; dayOfMonth = dayOfYear - 122
end
local dateString = string.format("%d/%d/%d PSSC", dayOfMonth, month, psscYear)
return { text = dateString, year = psscYear, dayOfYear = dayOfYear }
end
-------------------------------------------------------------------------------
-- (B) STATIC DATA
-------------------------------------------------------------------------------
local sectors = {
"Strait South Inbound","Strait South Outbound","Strait North Inbound","Strait North Outbound",
"Archipelago Zone","Sacred Buffer Approaches","Environmental Buffer","Northern Approach TSS","Southern Approach TSS"
}
local flags = {
{name="Bassaridian-flag", weight=6, risky=false},
{name="Moorland", weight=2, risky=false},
{name="Imperial Federation", weight=5, risky=true},
{name="Matamoros (IF)", weight=2, risky=true},
{name="Neutral Merchant", weight=4, risky=false},
{name="Diaspora Stakeholders- Euranidom", weight=3, risky=true},
{name="Diaspora Stakeholders- Corumia", weight=3, risky=true},
{name="Diaspora Stakeholders- South Keltiania", weight=3, risky=true},
{name="Consortium Registry", weight=2, risky=true},
{name="Independent Coastal State", weight=7, risky=false}
}
local vessels = {
"Handymax bulker","Product tanker","General cargo ship","Container feeder",
"Ro-Ro ferry","Research craft","Declared submarine","Undeclared submarine"
}
local cargoTypes = {
{name="Medical reagents (dual-use precursors)", weight=3, risk=0.14, dual=true},
{name="Industrial oxidizers / nitrates (dual-use)", weight=2, risk=0.16, dual=true},
{name="Precision machine tools & CNC spares (dual-use)", weight=3, risk=0.15, dual=true},
{name="Encrypted electronics & comms modules (dual-use)", weight=2, risk=0.17, dual=true},
{name="Satellite components / sensors (dual-use)", weight=1, risk=0.18, dual=true},
{name="Industrial fasteners (coded)", weight=2, risk=0.12, dual=true},
{name="Hydraulic lubricants (dual-use)", weight=2, risk=0.13, dual=true},
{name="High-frequency alloys (coded)", weight=1, risk=0.14, dual=true},
{name="Aviation fuels & additives", weight=3, risk=0.12, dual=false},
{name="Refined petroleum products", weight=4, risk=0.08, dual=false},
{name="Relief supplies (mixed pallets)", weight=5, risk=0.06, dual=false},
{name="Agricultural commodities", weight=5, risk=0.04, dual=false},
{name="Finished consumer goods", weight=6, risk=0.03, dual=false}
}
local cargoTags = {
{name="standard", weight=6, risk=0.00},
{name="expedited", weight=3, risk=0.05},
{name="emergency", weight=2, risk=0.07},
{name="perishable",weight=2, risk=0.06}
}
local partnerProfiles = {
{code="P-07", weight=4, risk=0.00},
{code="P-12", weight=3, risk=0.03},
{code="P-17", weight=3, risk=0.12},
{code="P-22", weight=3, risk=0.14},
{code="P-31", weight=3, risk=0.05},
{code="P-38", weight=2, risk=0.10},
{code="P-44", weight=4, risk=0.02},
{code="P-53", weight=3, risk=0.04}
}
-- White-Lane corridors (codes + typical windows). Used for annotation only.
local wlCorridors = {
{code="WL-NZ-1", name="Lucíusu–Corum Electric City", win="0700–1100"},
{code="WL-GM-2", name="Ossyo–Lake Norton South Shore", win="0900–1300"},
{code="WL-SEA-3", name="Corumia–Western Corum Coastal (short-sea)", win="0600–1800"}
}
-- Neutral observer pool (for WL attestation note)
local observers = {
"Neutral temple auditor","Independent port compliance inspector",
"Community elder (witness)","Straits Convention monitor (civilian)"
}
-------------------------------------------------------------------------------
-- (C) HELPERS
-------------------------------------------------------------------------------
local function pick(list) return list[math.random(#list)] end
local function pickWeighted(list)
local total = 0
for _, item in ipairs(list) do total = total + (item.weight or 1) end
local roll, cumul = math.random(total), 0
for _, item in ipairs(list) do
cumul = cumul + (item.weight or 1)
if roll <= cumul then return item end
end
return list[#list]
end
-- Determine if this row qualifies for White-Lane annotation (Annex G eligibility, simplified)
local function isWhiteLane(cargo, tag)
if not cargo or not tag then return false end
-- Green/Amber cargoes likely eligible when not dual-use and tagged time-sensitive
local green = (cargo.name == "Relief supplies (mixed pallets)" or cargo.name == "Agricultural commodities")
local amber = (tag.name == "expedited" or tag.name == "emergency" or tag.name == "perishable")
return (green and not cargo.dual) or (amber and not cargo.dual)
end
-- Build legal basis string per Conventions
local function legalBasis(sector, wl)
if wl then
return "Art III.5 (White-Lane); Annex G; Art X.3 (expedited remedies)"
end
if sector == "Sacred Buffer Approaches" or sector == "Environmental Buffer" then
return "Art III.2.3 (Sacred quiet zones); Annex A (delims); Art VII; Annex D"
end
return "Art IV.1–1.2 (PSC); Annex F (SCT/SAC procedures)"
end
-- Appeals column text
local function appealsStatus(sector, wl, tag, cargo)
if wl then
-- Expedited track per Art X.3
local outcome
local relief = 0.60
if tag and (tag.name=="emergency" or tag.name=="perishable") then relief = relief + 0.12 end
if cargo and cargo.dual then relief = relief - 0.15 end
local r = math.random()
if r <= relief * 0.6 then outcome = "clearance granted"
elseif r <= relief then outcome = "expedited with conditions"
else outcome = "conditions imposed" end
return string.format("HCE Review → SCT (72h) → SAC (≤5d) — %s (Art X.3; Annex G)", outcome)
else
local level = (sector=="Sacred Buffer Approaches" or sector=="Environmental Buffer") and "SAC Referral" or
((math.random()<0.5) and "SCT Admin Review" or "PSC reconciliation")
local outcome = (level=="PSC reconciliation") and "notice acknowledged" or
((math.random()<0.5) and "clearance granted" or "conditions imposed")
local cite = (level=="SAC Referral") and "Annex F (SAC)" or "Annex F (SCT)"
return string.format("%s — %s (%s)", level, outcome, cite)
end
end
-- Simple HCE reference (for WL notes)
local function hceRef(dateInfo, corridor)
return string.format("HCE-%03d.%03d-%s", dateInfo.year, dateInfo.dayOfYear, corridor.code)
end
-------------------------------------------------------------------------------
-- (D) MAIN GENERATION
-------------------------------------------------------------------------------
function p.makeTable(frame)
local dateInfo = getPSSCDate()
math.randomseed(dateInfo.year*1000 + dateInfo.dayOfYear)
local rows = tonumber(frame and frame.args and frame.args.rows) or 18
local out = {}
table.insert(out, "{| class='wikitable sortable'")
table.insert(out, "! Date !! Sector !! Vessel/Flag !! Action !! Legal Basis !! Outcome !! Appeals/Review (Straits Conventions) !! Notes")
for _ = 1, rows do
local sector = pick(sectors)
local flag = pickWeighted(flags)
local vessel = pick(vessels)
local cargo = pickWeighted(cargoTypes)
local tag = pickWeighted(cargoTags)
local partner = pickWeighted(partnerProfiles)
local wlEligible = isWhiteLane(cargo, tag)
local corridor = wlEligible and pick(wlCorridors) or nil
local obs = wlEligible and pick(observers) or nil
-- Base enforcement probability
local function baseProb()
local q = 0.28
if flag.risky then q = q + 0.06 end
if sector == "Sacred Buffer Approaches" or sector == "Environmental Buffer" then q = q + 0.08 end
q = q + (cargo and cargo.risk or 0)
if cargo and cargo.dual then q = q + 0.03 end
q = q + (tag and tag.risk or 0)
q = q + (partner and partner.risk or 0)
-- WL usually lowers friction (pre-cleared), but can still be inspected
if wlEligible then q = math.max(q - 0.06, 0.10) end
return math.min(q, 0.72)
end
local enforce = baseProb()
local action, legal, outcome, notes, appealCol
if wlEligible then
action = "WL transit / pilotage verification"
legal = legalBasis(sector, true)
notes = string.format("WL %s (%s) | window %s | Observer: %s | %s | Cargo: %s [%s]; Partner: %s",
corridor.code, corridor.name, corridor.win, (obs or "n/a"),
hceRef(dateInfo, corridor), cargo.name, tag.name, partner.code)
else
action = "Cargo manifest reconciliation audit"
legal = legalBasis(sector, false)
notes = string.format("Cargo: %s [%s]; Partner: %s", cargo.name, tag.name, partner.code)
end
if math.random() > enforce then
outcome = wlEligible and "Cleared WL window" or "No reports"
appealCol = wlEligible and "N/A (WL cleared)" or "N/A"
else
outcome = wlEligible and "WL reconciliation check; monitoring" or "Administrative notice issued; monitoring"
-- push to hold if multiple risk factors present
local riskPush = 0
if flag.name:match("Imperial Federation") or flag.name:match("Matamoros") then riskPush = riskPush + 1 end
if cargo.dual or (cargo.risk or 0) >= 0.12 then riskPush = riskPush + 1 end
if tag.name ~= "standard" then riskPush = riskPush + 1 end
if (partner.risk or 0) >= 0.09 then riskPush = riskPush + 1 end
if wlEligible then riskPush = math.max(riskPush - 1, 0) end
if riskPush >= 2 and math.random() < 0.65 then
outcome = (wlEligible and "WL hold; clearance pending expedited review" or "Random audit hold; clearance pending")
if flag.name == "Imperial Federation" or flag.name == "Matamoros (IF)" then
outcome = outcome .. " [Extended regulatory review]"
end
end
appealCol = appealsStatus(sector, wlEligible, tag, cargo)
end
table.insert(out, "|-")
table.insert(out, string.format("| %s || %s || %s (%s) || %s || %s || %s || %s || %s",
dateInfo.text, sector, vessel, flag.name, action, legal, outcome, appealCol, notes))
end
table.insert(out, "|}")
return table.concat(out, "\n")
end
return p