local getArgs = require('Module:Arguments').getArgs
local yesno = require("Module:Yesno")
local stormColor = require("Module:Tropical cyclone categories")._color;
local zh = require("Module:Lang-zh")._Zh
local p = {}
--------------------------------------------------------------------------------
-- Global functions
--------------------------------------------------------------------------------
function p.header(country, time)
return mw.html.create("tr"):node(
mw.html.create("th")
:css("font-weight", "normal")
:attr("colspan", 3)
:wikitext("'''" .. country .. "'''" .. (
time and
" (as of " .. time .. ")" or ""
))
)
end
--------------------------------------------------------------------------------
---------------------------- COUNTRY-BASED WARNINGS ----------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- China
--
-- Storm signals in China are defined by the CMA.
--------------------------------------------------------------------------------
-- Note: v (in m/s) = 0.386B^(3/2), where B is the Beaufort force
function p.cma_signals(signal)
if signal == "4" or signal == "blue" or signal == "b" then
return {
level = 4,
color = "#3265FE",
name = "Blue typhoon alert",
name_zh = "台风蓝色预警信号",
image = "Blue typhoon alert - China.svg",
details = "Average of [[Beaufort scale|Beaufort force]] 6 (44 km/h; 27 mph) "
.. "or higher wind speeds on coasts or land, or gusts of up to Beaufort force 8 "
.. "(68 km/h; 42 mph), within 24 hours."
}
elseif signal == "3" or signal == "yellow" or signal == "y" then
return {
level = 3,
color = "#FAEC2C",
name = "Yellow typhoon alert",
name_zh = "台风黄色预警信号",
image = "Yellow typhoon alert - China.svg",
details = "Average of [[Beaufort scale|Beaufort force]] 8 (68 km/h; 42 mph) "
.. "or higher wind speeds on coasts or land, or gusts of up to Beaufort force 10 "
.. "(95 km/h; 59 mph), within 24 hours."
}
elseif signal == "2" or signal == "orange" or signal == "o" then
return {
level = 2,
color = "#F68C1F",
name = "Orange typhoon alert",
name_zh = "台风橙色预警信号",
image = "Orange typhoon alert - China.svg",
details = "Average of [[Beaufort scale|Beaufort force]] 10 (95 km/h; 59 mph) "
.. "or higher wind speeds on coasts or land, or gusts of up to Beaufort force 12 "
.. "(125 km/h; 78 mph), within 12 hours."
}
elseif signal == "1" or signal == "red" or signal == "r" then
return {
level = 1,
color = "#D62F28",
name = "Red typhoon alert",
name_zh = "台风红色预警信号",
image = "Red typhoon alert - China.svg",
details = "Average of [[Beaufort scale|Beaufort force]] 12 (125 km/h; 78 mph) "
.. "or higher wind speeds on coasts or land, or gusts of up to Beaufort force 14 "
.. "(158 km/h; 98 mph), within 6 hours."
}
else
return {
level = 0,
color = "#000000",
name = "Unknown typhoon alert level",
name_zh = "台风未知预警信号",
image = "Stop hand nuvola.svg",
details = "Please make sure that the parameter is a valid signal. "
.. "Consult the [[Template:TyphoonWarningsTable#China|documentation]] for more details."
}
end
end
function p.cma_level_row(signal)
return mw.html.create("tr")
:node(
mw.html.create("td")
:css("width", "700px")
:css("text-align", "center")
:attr("colspan", 3)
:node(
mw.html.create("span")
:css("font-size", "large")
:css("font-weight", "bold")
:wikitext(signal.name)
)
:wikitext("<br/>" .. zh{["c"] = signal.name_zh, ["labels"] = "no"})
:wikitext("<p>[[File:" .. signal.image .. "|100px]]</p>")
:node(
mw.html.create("p")
:css("margin", "0")
:wikitext(signal.details)
)
)
end
function p.china(outputTable, args)
local CNsignal = args["CNsignal"]
if CNsignal then
-- Create the header
outputTable:node(
p.header("China", args["CNtime"])
)
local signalData = p.cma_signals(CNsignal)
outputTable:node(p.cma_level_row(signalData))
-- Create the footer
if args["CNsource"] then
outputTable:node(
mw.html.create("tr"):node(
mw.html.create("td")
:attr("colspan", 3)
:wikitext("Source: " .. args["CNsource"])
)
)
end
end
end
--------------------------------------------------------------------------------
-- Hong Kong
--
-- Storm signals in Hong Kong are defined by the HKO.
--------------------------------------------------------------------------------
function p.hko_signals(signal, direction)
if signal == 1 then
return {
name = "Signal No. 01 - Standby Signal",
image = "No. 01 Standby Signal.png",
summary = "A tropical cyclone is centred within 800 km of the territory."
}
elseif signal == 3 then
return {
name = "Signal No. 03 - Strong Wind Signal",
image = "No. 03 Strong Wind Signal.png",
summary = "Strong winds generally over Hong Kong at sea level are expected in 12 hours.",
details = "Expect strong winds with a sustained speed of 41–62 km/h and gusts of up to 110 km/h."
}
elseif signal == 8 then
local direction = (
(direction == "ne" or direction == "northeast") and "Northeast" or (
(direction == "nw" or direction == "northwest") and "Northwest" or (
(direction == "se" or direction == "southeast") and "Southeast" or (
(direction == "sw" or direction == "southwest") and "Southwest" or (
nil
)))))
if direction then
return {
name = "Signal No. 08 - " .. direction .. " Gale or Storm Signal",
image = "No. 8 " .. direction .. " Gale or Storm Signal.png",
summary = "Gale or storm-force winds are expected.",
details = "Expect strong winds with a sustained speed of 63–117 km/h from the "
.. string.lower(direction) ..
" quadrant and gusts of up to 180 km/h."
}
else
return {
name = "Invalid Hong Kong Observatory Signal Direction",
image = "Stop hand nuvola.svg",
summary = "Signal No. 8 used without providing a valid wind direction.",
details = "Use <code>8NE</code>, <code>8SE</code>, <code>8NW</code>, or <code>8SW</code> instead. "
.. "Consult the [[Template:TyphoonWarningsTable#Hong Kong|documentation]] for more details."
}
end
elseif signal == 9 then
return {
name = "Signal No. 09 - Increasing Gale or Storm Signal",
image = "No. 09 Increasing Gale or Storm Signal.png",
summary = "Gale or storm-force winds are increasing or expected to increase significantly in strength.",
details = "Expect strong winds with a sustained speed of 88–117 km/h and gusts no faster than 220 km/h."
}
elseif signal == 10 then
return {
name = "Signal No. 10 - Hurricane Signal",
image = "No. 10 Hurricane Signal.png",
summary = "Hurricane-force winds.",
details = "Expect strong winds above 117 km/h and gusts of more than 220 km/h."
}
else
return {
name = "Invalid Hong Kong Observatory Signal",
image = "Stop hand nuvola.svg",
summary = "A valid storm signal was not provided in the <code>HKsignal</code> parameter.",
details = "Please make sure that the parameter is a valid signal. "
.. "Consult the [[Template:TyphoonWarningsTable#Hong Kong|documentation]] for more details."
}
end
end
function p.hong_kong(outputTable, args)
local HKsignal = args["HKsignal"]
if HKsignal then
-- Create the header
outputTable:node(
p.header("Hong Kong", args["HKtime"])
)
HKsignal = string.lower(HKsignal)
local signal = nil
if HKsignal == "1" then
signal = p.hko_signals(1)
elseif HKsignal == "3" then
signal = p.hko_signals(3)
elseif HKsignal == "8" then
-- Provide the opportunity for an editor to see that a quadrant is
-- required.
signal = p.hko_signals(8)
elseif HKsignal == "8nw" then
signal = p.hko_signals(8, "nw")
elseif HKsignal == "8ne" then
signal = p.hko_signals(8, "ne")
elseif HKsignal == "8sw" then
signal = p.hko_signals(8, "sw")
elseif HKsignal == "8se" then
signal = p.hko_signals(8, "se")
elseif HKsignal == "9" then
signal = p.hko_signals(9)
elseif HKsignal == "10" then
signal = p.hko_signals(10)
else
signal = p.hko_signals(HKsignal)
end
outputTable
:node(
mw.html.create("tr"):node(
mw.html.create("td")
:css("width", "700px")
:css("text-align", "center")
:attr("colspan", 3)
:node(
mw.html.create("span")
:css("font-size", "large")
:css("font-weight", "bold")
:wikitext(signal.name)
)
:wikitext("<br/>[[File:" .. signal.image .. "|80px]]<br/>")
:node(
mw.html.create("p")
:wikitext(signal.summary)
)
:node(
mw.html.create("p")
:css("font-style", "italic")
:wikitext(signal.details)
)
)
)
-- Create the footer
if args["HKsource"] then
outputTable:node(
mw.html.create("tr"):node(
mw.html.create("td")
:attr("colspan", 3)
:wikitext("Source: " .. args["HKsource"])
)
)
end
else
return ""
end
end
--------------------------------------------------------------------------------
-- Philippines
--
-- Storm signals in the Philippines are defined by the PAGASA.
--------------------------------------------------------------------------------
p.pagasa_signals = {
s5 = {
name = "Signal #5",
color = "#CD77CD",
speed = "over 220 km/h (137 mph)",
time = "12 hours"
},
s4 = {
name = "Signal #4",
color = "#FF6060",
speed = "171–220 km/h (106–137 mph)",
time = "12 hours"
},
s3 = {
name = "Signal #3",
color = "#FFAA00",
speed = "121–170 km/h (74–105 mph)",
time = "18 hours"
},
s2 = {
name = "Signal #2",
color = "#FFF200",
speed = "61–120 km/h (38–73 mph)",
time = "24 hours"
},
s1 = {
name = "Signal #1",
color = "#00AAFF",
speed = "30–60 km/h (20–37 mph)",
time = "36 hours"
}
}
function p.pagasa_row(signal, data, args)
return mw.html.create("tr")
:node(
mw.html.create("td")
:css("width", "12.6em")
:css("text-align", "center")
:css("vertical-align", "middle")
:css("background-color", p.pagasa_signals[signal].color)
:wikitext("'''" .. p.pagasa_signals[signal].name .. "'''<br/>")
:wikitext(
"''Winds of " .. p.pagasa_signals[signal].speed .. (
yesno(args["PHhistorical"]) and "" or " are " .. (
yesno(args["PHactive"]) and "prevailing or " or ""
) .. "expected to occur within " ..
p.pagasa_signals[signal].time
) .. ".''"
)
)
:node(
mw.html.create("td")
:css("vertical-align", "middle")
:wikitext("\n" .. data .. "\n")
)
end
function p.philippines(outputTable, args)
local PH1 = args["PH1"]
local PH2 = args["PH2"]
local PH3 = args["PH3"]
local PH4 = args["PH4"]
local PH5 = args["PH5"]
if PH1 or PH2 or PH3 or PH4 or PH5 then
-- Create the header
outputTable:node(
p.header("Philippines", args["PHtime"])
)
if PH5 then
outputTable:node(p.pagasa_row("s5", PH5, args))
end
if PH4 then
outputTable:node(p.pagasa_row("s4", PH4, args))
end
if PH3 then
outputTable:node(p.pagasa_row("s3", PH3, args))
end
if PH2 then
outputTable:node(p.pagasa_row("s2", PH2, args))
end
if PH1 then
outputTable:node(p.pagasa_row("s1", PH1, args))
end
-- Create the footer
if args["PHsource"] then
outputTable:node(
mw.html.create("tr"):node(
mw.html.create("td")
:attr("colspan", 3)
:wikitext("Source: " .. args["PHsource"])
)
)
end
else
return ""
end
end
--------------------------------------------------------------------------------
---------------------------- AGENCY-BASED WARNINGS -----------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- National Weather Service, Tiyan, Guam
--
-- Storm signals (Typhoon and Tropical Storm Warnings, etc.) issued by the NWS.
--------------------------------------------------------------------------------
p.nws_criteria = {
tyw = {
name = "Typhoon Warning",
color = stormColor("cat5"),
description = "Typhoon conditions ($speed) expected within $duration.",
speed = "over 118 km/h (74 mph)",
duration = "24 hours"
},
tya = {
name = "Typhoon Watch",
color = stormColor("cat4"),
description = "Typhoon conditions ($speed) possible within $duration.",
speed = "over 118 km/h (74 mph)",
duration = "24 hours"
},
trw = {
name = "Tropical Storm Warning",
color = stormColor("cat3"),
description = "Tropical storm conditions ($speed) expected within $duration.",
speed = "88–117 km/h (55–73 mph)",
duration = "24 hours"
},
tra = {
name = "Tropical Storm Watch",
color = stormColor("cat2"),
description = "Tropical storm conditions ($speed) possible within $duration.",
speed = "88–117 km/h (55–73 mph)",
duration = "24 hours"
},
gaw = {
name = "Gale Warning",
color = stormColor("ts"),
description = "Gale conditions ($speed) expected within $duration.",
speed = "63-87 km/h (39–72 mph)",
duration = "24 hours"
}
}
function p.nws_row(signal, data)
return mw.html.create("tr")
:node(
mw.html.create("td")
:css("width", "14em")
:css("text-align", "center")
:css("vertical-align", "middle")
:css("background-color", "#" .. p.nws_criteria[signal].color)
:wikitext("'''" .. p.nws_criteria[signal].name .. "'''<br/>")
:wikitext(
"''" ..
string.gsub(
string.gsub(
p.nws_criteria[signal].description,
"%$speed",
p.nws_criteria[signal].speed
),
"%$duration",
p.nws_criteria[signal].duration
)
.. "''"
)
)
:node(
mw.html.create("td")
:css("vertical-align", "middle")
:wikitext("\n" .. data .. "\n")
)
end
function p.nws(outputTable, args)
local TYW = args["TYW"]
local TYA = args["TYA"]
local TRW = args["TRW"] or args["TSW"]
local TRA = args["TRA"] or args["TSA"]
local GAW = args["GAW"]
if TYW or TYA or TRW or TRA or GAW then
-- Create the header
outputTable:node(
p.header("National Weather Service", args["NWStime"])
)
if TYW then
outputTable:node(p.nws_row("tyw", TYW))
end
if TYA then
outputTable:node(p.nws_row("tya", TYA))
end
if TRW then
outputTable:node(p.nws_row("trw", TRW))
end
if TRA then
outputTable:node(p.nws_row("tra", TRA))
end
if GAW then
outputTable:node(p.nws_row("gaw", GAW))
end
-- Create the footer
if args["NWSsource"] then
outputTable:node(
mw.html.create("tr"):node(
mw.html.create("td")
:attr("colspan", 3)
:wikitext("Source: " .. args["NWSsource"])
)
)
end
else
return ""
end
end
--------------------------------------------------------------------------------
-- Template invocation features
--------------------------------------------------------------------------------
function p.main(frame)
local args = getArgs(frame, {
trim = true,
removeBlanks = true
})
return p._main(frame, args)
end
function p._main(frame, args)
-- Generate table
local finalTable = mw.html.create("table")
:attr("class", "wikitable typhoon-warnings-table")
if yesno(args["float"]) then
finalTable:css("float", args["align"] or "left")
elseif yesno(args["demo"]) then
finalTable:css("float", "right")
end
if args["width"] then
finalTable:css("width", args["width"])
end
-- Save the table prior to row insertion
local premake = tostring(finalTable);
-- Generate rows
p.china(finalTable, args)
p.hong_kong(finalTable, args)
p.philippines(finalTable, args)
p.nws(finalTable, args)
-- Save the table after row insertion
local postmake = tostring(finalTable)
-- If there is no difference between the table before insertion and after
-- insertion, it is fair to assume that there were no arguments given.
if postmake == premake then
finalTable:node(
mw.html.create("tr"):node(
mw.html.create("td")
:attr("colspan", 3)
:css("background-color", "#" .. stormColor("td"))
:wikitext("No '''tropical cyclone watches or warnings''' posted at this time.")
)
)
postmake = tostring(finalTable)
end
-- Output
return tostring(postmake)
.. (yesno(args["clear"]) and ("\n" .. frame:expandTemplate{
title = "clear"
}) or "")
end
return p