Module:Storm categories: Difference between revisions
adjust aliases |
better demo |
||
Line 459: | Line 459: | ||
icons["stss"] = icons["swiosts"] |
icons["stss"] = icons["swiosts"] |
||
icons["tc"] = icons["swiotc"] |
icons["tc"] = icons["swiotc"] |
||
local customKeys = {} |
|||
for k, v in pairs(colors) do |
|||
table.insert(customKeys, k) |
|||
⚫ | |||
for k, v in pairs(icons) do |
|||
table.insert(customKeys, k) |
|||
⚫ | |||
TableTools.removeDuplicates(customKeys) |
|||
function p.color(frame) |
function p.color(frame) |
||
return p._color(frame.args[1] or frame:getParent().args[1]) |
return p._color(frame.args[1] or frame:getParent().args[1], false) |
||
end |
end |
||
Line 467: | Line 476: | ||
return p._name( |
return p._name( |
||
frame.args[1] or frame:getParent().args[1], |
frame.args[1] or frame:getParent().args[1], |
||
frame.args[2] or frame:getParent().args[2] |
frame.args[2] or frame:getParent().args[2], |
||
false |
|||
) |
) |
||
end |
end |
||
function p.sortkey(frame) |
function p.sortkey(frame) |
||
return p._sortkey(frame.args[1] or frame:getParent().args[1]) |
return p._sortkey(frame.args[1] or frame:getParent().args[1], false) |
||
end |
end |
||
function p.icon(frame) |
function p.icon(frame) |
||
return p._icon(frame.args[1] or frame:getParent().args[1]) |
return p._icon(frame.args[1] or frame:getParent().args[1], false) |
||
end |
end |
||
function p._color(colorCode) |
function p._color(colorCode, nullIfMissing) |
||
-- This looks confusing, but it's actually nested ternaries (for nil checks) |
-- This looks confusing, but it's actually nested ternaries (for nil checks) |
||
local color = (colorCode ~= nil and string.len(colorCode) ~= 0) and |
local color = (colorCode ~= nil and string.len(colorCode) ~= 0) and |
||
Line 485: | Line 495: | ||
or defaultCategory |
or defaultCategory |
||
return colors[color] or ((cats[color] or |
return colors[color] or ((cats[color] or ( |
||
nullIfMissing |
|||
and { color = nil } |
|||
or cats[defaultCategory] |
|||
)).color) |
|||
end |
end |
||
function p._name(category, basin) |
function p._name(category, basin, nullIfMissing) |
||
local name_def = (cats[ |
local name_def = (cats[ |
||
(category ~= nil and string.len(category) ~= 0) and |
(category ~= nil and string.len(category) ~= 0) and |
||
Line 498: | Line 512: | ||
name_def[string.lower(basin or "default")] |
name_def[string.lower(basin or "default")] |
||
or name_def["default"] |
or name_def["default"] |
||
or error("No default name for basin-based category name.") |
or (nullIfMissing and nil or error("No default name for basin-based category name.")) |
||
) |
) |
||
or name_def |
or name_def |
||
end |
end |
||
function p._sortkey(category) |
function p._sortkey(category, nullIfMissing) |
||
-- This looks confusing, but it's actually nested ternaries (for nil checks) |
-- This looks confusing, but it's actually nested ternaries (for nil checks) |
||
return (cats[ |
return (cats[ |
||
Line 509: | Line 523: | ||
string.gsub(string.lower(category), "[^%w]", "") |
string.gsub(string.lower(category), "[^%w]", "") |
||
or defaultCategory |
or defaultCategory |
||
] or cats[defaultCategory]).sortkey |
] or (nullIfMissing and { sortkey = nil } or cats[defaultCategory])).sortkey |
||
end |
end |
||
function p._icon(iconCode) |
function p._icon(iconCode, nullIfMissing) |
||
-- This looks confusing, but it's actually nested ternaries (for nil checks) |
-- This looks confusing, but it's actually nested ternaries (for nil checks) |
||
local icon = (iconCode ~= nil and string.len(iconCode) ~= 0) and |
local icon = (iconCode ~= nil and string.len(iconCode) ~= 0) and |
||
Line 520: | Line 534: | ||
return icons[icon] or (cats[icon] ~= nil and ( |
return icons[icon] or (cats[icon] ~= nil and ( |
||
cats[icon].icon or cats["tropicalcyclone"].icon |
cats[icon].icon or cats["tropicalcyclone"].icon |
||
) or cats[defaultCategory].icon) |
) or (nullIfMissing and nil or cats[defaultCategory].icon)) |
||
end |
end |
||
Line 724: | Line 738: | ||
end |
end |
||
for name, |
for name, _ in TableTools.sortedPairs(TableTools.listToSet(customKeys)) do |
||
if cats[name] == nil then |
if cats[name] == nil then |
||
local row = mw.html.create("tr") |
local row = mw.html.create("tr") |
||
local icon = p._icon(name, true) |
|||
row |
|||
:node(mw.html.create("td") |
:node(mw.html.create("td") |
||
:wikitext( |
:wikitext( |
||
icon ~= nil |
|||
and icon |
|||
⚫ | |||
)) |
|||
:node(mw.html.create("td"):wikitext(name)) |
:node(mw.html.create("td"):wikitext(name)) |
||
⚫ | |||
local color = p._color(name, true) |
|||
⚫ | |||
-- Add more conditions eventually |
|||
⚫ | |||
⚫ | |||
:node(mw.html.create("td") |
|||
row |
|||
:attr("style", "background-color: #" .. color .. "; padding: 0; width: 1.8em")) |
|||
:node(mw.html.create("td") |
:node(mw.html.create("td") |
||
: |
:attr("colspan", "2") |
||
⚫ | |||
:node(mw.html.create("td") |
|||
: |
:node(mw.html.create("td") |
||
: |
:attr("style", "background-color: #" .. color .. "; padding: 0; width: 1.8em")) |
||
:node(mw.html.create("td") |
|||
:wikitext("#" .. color)) |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
:wikitext("''<span style=\"color:gray\">not available</span>''")) |
|||
for name, icon in TableTools.sortedPairs(icons) do |
|||
else |
|||
⚫ | |||
row |
|||
local row = mw.html.create("tr") |
|||
:node(mw.html.create("td") |
:node(mw.html.create("td") |
||
: |
:attr("colspan", "6") |
||
:wikitext("''<span style=\"color:gray\">not available</span>''")) |
|||
:node(mw.html.create("td"):wikitext(name)) |
|||
end |
|||
:node(mw.html.create("td") |
|||
:attr("colspan", "6") |
|||
⚫ | |||
out:node(row) |
out:node(row) |
||
end |
end |
Revision as of 06:42, 23 January 2022
![]() | This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
![]() | This Lua module is used on approximately 5,600 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them. |
![]() | In order to conform to Wikipedia:Manual of Style/Accessibility#Color guidelines, do not use storm colors in conjunction with links. This is necessary to avoid problems related to lack of contrast. |
![]() | This module depends on the following other modules: |
This template is used to control a multitude of tropical cyclone-related templates: {{storm colour}}, {{storm name}}, and {{storm icon}}. It acts as a centralized location for storm categories to avoid discrepancies between templates, allowing for the same ID to be used across all related templates.
Data is located in the following submodules:
- Module:Storm categories/categories for fully-detailed storm categories
- Module:Storm categories/colors for color-only IDs
- Module:Storm categories/icons for icon-only IDs
Usage
This module exports three functions for templates: p.color
, p.name
, p.sortkey
, and p.icon
. It also provides p._color
, p._name
, p._sortkey
, and p._icon
for use in other modules.
All input IDs are case-insensitive, and all non-alphanumeric characters are stripped.
Color
Provides the color of the given tropical cyclone category code. This comes in the format of their raw hexadecimal code. This function is available as a template at {{storm colour}}.
Code | Output |
---|---|
<span style="padding:4px;border:1px solid black;background-color:#{{#invoke:Storm categories|color|depression}}">depression</span>
|
depression |
Name
Provides the name of the given tropical cyclone category code. A optional basin argument can be provided as the second argument in order to slightly tweak the name of the category, if the given category definition supports it. This function is available as a template at {{storm name}}.
Code | Interpreted | Output | |
---|---|---|---|
ID | Basin | ||
{{#invoke:Storm categories|name|severe}}
|
severe | (default) | Severe tropical storm |
{{#invoke:Storm categories|name|spr - cYcL -s TorM}}
|
sprcyclstorm | (default) | Super cyclonic storm |
{{#invoke:Storm categories|name|cat5}}
|
cat5 | (default) | Category 5-equivalent tropical cyclone |
{{#invoke:Storm categories|name|cat5|ATl}}
|
cat5 | ATl | Category 5 hurricane |
{{#invoke:Storm categories|name|cat5|WPac}}
|
cat5 | WPac | Category 5-equivalent super typhoon |
Sortkey
The sortkey is a number that aids in sorting categories. Using the sortkey, it is possible to automatically sort a table of tropical cyclones given their category code. Due to the ambiguous nature of sortkeys, tables may be sorted incorrectly if values from other basins were used. For categories that span multiple basins, however, (e.g. depression
and storm
) they are given the lowest possible sortkeys in order to achieve maximum compatibility.
This sortkey is used in {{Tropical cyclone season effects (cyclone)}}, a subtemplate of {{Tropical cyclone season effects}}.
The sortkey format is as follows. Note that not all values between the given ranges were used. The arrangement of these were determined by their positions in the {{Storm colour}} template.
Basin | Sortkey range |
---|---|
Global (unused) | 90000 to 99999 |
Atl/EPac/SAtl | 80000 to 89999 |
WPac | 60000 to 69999 |
Nio | 50000 to 59999 |
Aus/Fiji | 40000 to 49999 |
SWio | 30000 to 39999 |
Historical | 20000 to 29999 |
Global | 0 to 9999 |
A demonstration of a sortable table using these sortkeys can be found below. Note that it does not use categories outside of its own basin (in this case, the Atl/EPac/SAtl basin) and the global range.
Category | Sortkey | Code |
---|---|---|
cat3 | 80,006 | {{#invoke:Storm categories|sortkey|cat3}}
|
cat1 | 80,002 | {{#invoke:Storm categories|sortkey|cat1}}
|
cat5 | 80,020 | {{#invoke:Storm categories|sortkey|cat5}}
|
cat4 | 80,008 | {{#invoke:Storm categories|sortkey|cat4}}
|
depression | 90 | {{#invoke:Storm categories|sortkey|depression}}
|
cat2 | 80,004 | {{#invoke:Storm categories|sortkey|cat2}}
|
Sorting table which uses different basins
| ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Icon
Icons exist for some Storm categories for presentation purposes. This function is available as a template at {{storm icon}}. p.icon
will return wikitext of an image or formatted text.
Full list of available values
The following table is generated by invoking the demo
function of this module. Some IDs are only available as colors or icons because they existed as parameters on old non-module template implementations and cannot be feasibly aliased to a specific tropical cyclone category.
It will show any color errors, including colors which aren't compliant with the minimal Web Content Accessibility Guidelines 2.0 AA color standards (see MOS:COLOR for more information).
- * – Overriden from original icon.
- ** – Overriden from original color.
- L – Color has contrast issues with links (#0645ad).
local colorRatio = require("Module:Color contrast")._ratio
local TableTools = require("Module:TableTools")
local p = {}
-- Define categories
-- All sortkeys have been guessed. They may be changed by common sense
-- or consensus at [[Wikipedia talk:WikiProject Tropical cyclones]]
local cats = {
severe = {
color = "ccffff",
name = "Severe tropical storm",
sortkey = 120,
icon = "[[File:Severe tropical storm icon.png|18px]]"
},
mtstorm = {
color = "00faf4", -- Old {{storm colour}} did not support. Value guessed.
name = "Moderate tropical storm",
sortkey = 105,
icon = "[[File:Moderate tropical storm icon.png|18px]]"
},
storm = {
color = "00faf4",
name = "Tropical storm",
sortkey = 100,
icon = "[[File:Tropical storm icon.png|18px]]"
},
severedep = {
color = "5ebaff", -- Old {{storm colour}} did not support. Value guessed.
name = "Severe tropical depression",
sortkey = 120
},
moddepression = {
color = "5ebaff", -- Old {{storm colour}} did not support. Value guessed.
name = "Moderate tropical depression",
sortkey = 95
},
depression = {
color = "5ebaff",
name = "Tropical depression",
sortkey = 90,
icon = "[[File:Tropical Depression.png|25px]]"
},
disturbance = {
color = "80ccff",
name = "Tropical disturbance",
sortkey = 80,
icon = "[[File:Disturbance icon.png|25px]]"
},
subtropicalcyclone = {
color = "00faf4",
name = "Subtropical cyclone",
sortkey = 70
},
subtropical = {
color = "00faf4",
name = "Subtropical storm",
sortkey = 65,
icon = "[[File:Subtropical storm icon.png|18px]]"
},
subdepression = {
color = "5ebaff",
name = "Subtropical depression",
sortkey = 60,
icon = "[[File:Subtropical Depression icon.png|25px]]"
},
subdisturbance = {
color = "80ccff",
name = "Subtropical disturbance",
sortkey = 55,
icon = "[[File:Disturbance icon.png|25px]]"
},
extratropical = {
color = "cccccc",
name = "Extratropical cyclone",
sortkey = 50,
icon = "[[File:Extratropical cyclone icon.png|18px]]"
},
monsoondepression = {
color = "5ebaff",
name = "Monsoon depression",
sortkey = 30,
icon = "[[File:Monsoon Depression icon.png|25px]]"
},
potential = {
color = "80ccff",
name = "Potential tropical cyclone",
sortkey = 25,
icon = "[[File:Potential tropical cyclone icon.png|25px]]"
},
posttropical = {
color = "cccccc",
name = "Post-tropical depression",
sortkey = 70,
icon = "[[File:Post tropical cyclone icon.png|25px]]"
},
remnant = {
color = "cccccc",
name = "Post-tropical depression",
sortkey = 70,
icon = "[[File:Remnant low icon.png|25px]]"
},
unknown = {
color = "c0c0c0",
name = "Unknown strength tropical cyclone",
sortkey = 0,
icon = "'''?'''"
},
cat5 = {
color = "ff6060",
name = {
atl = "Category 5 hurricane",
epac = "Category 5 hurricane",
satl = "Category 5 hurricane",
wpac = "Category 5-equivalent super typhoon",
default = "Category 5-equivalent tropical cyclone"
},
sortkey = 80020,
icon = "[[File:Category 5 hurricane icon.png|18px]]"
},
cat4 = {
color = "ff8f20",
name = {
atl = "Category 4 hurricane",
epac = "Category 4 hurricane",
satl = "Category 4 hurricane",
wpac = "Category 4-equivalent typhoon",
default = "Category 4-equivalent tropical cyclone"
},
sortkey = 80008,
icon = "[[File:Category 4 hurricane icon.png|18px]]"
},
cat3 = {
color = "ffc140",
name = {
atl = "Category 3 hurricane",
epac = "Category 3 hurricane",
satl = "Category 3 hurricane",
wpac = "Category 3-equivalent typhoon",
default = "Category 3-equivalent tropical cyclone"
},
sortkey = 80006,
icon = "[[File:Category 3 hurricane icon.png|18px]]"
},
cat2 = {
color = "ffe775",
name = {
atl = "Category 2 hurricane",
epac = "Category 2 hurricane",
satl = "Category 2 hurricane",
wpac = "Category 2-equivalent typhoon",
default = "Category 2-equivalent tropical cyclone"
},
sortkey = 80004,
icon = "[[File:Category 2 hurricane icon.png|18px]]"
},
cat1 = {
color = "ffffcc",
name = {
atl = "Category 1 hurricane",
epac = "Category 1 hurricane",
satl = "Category 1 hurricane",
wpac = "Category 1-equivalent typhoon",
default = "Category 1-equivalent tropical cyclone"
},
sortkey = 80002,
icon = "[[File:Category 1 hurricane icon.png|18px]]"
},
supertyphoon = {
color = "ff6060",
name = "Category 4 super typhoon",
sortkey = 80015
},
typhoon = {
color = "fdaf9a",
name = "Typhoon",
sortkey = 60010
},
vstyphoon = {
color = "fe887d",
name = "Very strong typhoon",
sortkey = 60020
},
vityphoon = {
color = "ff6060",
name = "Violent typhoon",
sortkey = 60030
},
-- PAGASA
styphoon = {
color = "ff6060",
name = "Supertyphoon",
sortkey = 60050
},
sprcyclstorm = {
color = "ff6060",
name = "Super cyclonic storm",
sortkey = 50020,
icon = "[[File:Super cyclonic storm icon.png|18px]]"
},
esvrcyclstorm = {
color = "ffc140",
name = "Extremely severe cyclonic storm",
sortkey = 50015,
icon = "[[File:Extremely severe cyclonic storm icon.png|18px]]"
},
vsvrcyclstorm = {
color = "ffffcc",
name = "Very severe cyclonic storm",
sortkey = 50010,
icon = "[[File:Very severe cyclonic storm icon.png|18px]]"
},
svrcyclstorm = {
color = "ccffff",
name = "Severe cyclonic storm",
sortkey = 50008,
icon = "[[File:Severe cyclonic storm icon.png|18px]]"
},
niocyclone = {
color = "00faf4",
name = "Cyclonic storm",
sortkey = 50006,
icon = "[[File:Cyclonic storm icon.png|18px]]"
},
deepdepression = {
color = "5ebaff",
name = "Deep depression",
sortkey = 50002,
icon = "[[File:Deep depression icon.png|25px]]"
},
niodepression = {
color = "80ccff",
name = "Depression",
sortkey = 50001,
icon = "[[File:Depression icon.png|25px]]"
},
nioland = {
color = "80ccff",
name = "Land depression",
sortkey = 50000,
icon = "[[File:Land depression icon.png|25px]]"
},
aus5 = {
color = "ff6060",
name = "Category 5 severe tropical cyclone",
sortkey = 40015,
icon = "[[File:Aus 5 icon.png|18px]]"
},
aus4 = {
color = "ffc140",
name = "Category 4 severe tropical cyclone",
sortkey = 40013,
icon = "[[File:Aus 4 icon.png|18px]]"
},
aus3 = {
color = "ffffcc",
name = "Category 3 severe tropical cyclone",
sortkey = 40010,
icon = "[[File:Aus 3 icon.png|18px]]"
},
aus2 = {
color = "ccffff",
name = "Category 2 tropical cyclone",
sortkey = 40008,
icon = "[[File:Aus 2 icon.png|18px]]"
},
aus1 = {
color = "00faf4",
name = "Category 1 tropical cyclone",
sortkey = 40006,
icon = "[[File:Aus 1 icon.png|18px]]"
},
low = {
color = "5ebaff",
name = "Tropical low",
sortkey = 40002,
icon = "[[File:Tropical Low.png|25px]]"
},
sublow = {
color = "5ebaff",
name = "Subtropical low",
sortkey = 40000
},
vintense = {
color = "ff6060",
name = "Very intense tropical cyclone",
sortkey = 30010,
icon = "[[File:Very intense tropical cyclone icon.png|18px]]"
},
intense = {
color = "ffc140",
name = "Intense tropical cyclone",
sortkey = 30008,
icon = "[[File:Intense tropical cyclone icon.png|18px]]"
},
tropicalcyclone = {
color = "ffffcc",
name = "Tropical cyclone",
sortkey = 30006,
icon = "'''TC'''"
},
mstorm = {
color = "00faf4",
name = "Moderate tropical storm",
sortkey = 30004,
icon = "[[File:Moderate tropical storm icon.png|18px]]"
},
zodw = {
color = "80ccff",
name = "Zone of disturbed weather",
sortkey = 30000,
icon = "[[File:Disturbed weather icon.png|25px]]"
},
shemsvrtc = {
color = "ffe775",
name = "Severe tropical cyclone",
sortkey = 20020
},
shem5 = {
color = "ff6060",
name = "Severe tropical cyclone",
sortkey = 20010
},
shem4 = {
color = "ffc140",
name = "Tropical cyclone",
sortkey = 20008
},
shem2 = {
color = "ccffff",
name = "Tropical cyclone",
sortkey = 20008
},
shem1 = {
color = "00faf4",
name = "Tropical cyclone",
sortkey = 20008
}
}
-- Default
local defaultCategory = "unknown"
-- Define aliases
-- All non-alphanumeric characters are already stripped, and the string is
-- already set to lowercase, so additional aliases for those are no longer
-- required.
cats["sty"] = cats["supertyphoon"]
cats["nwpsevere"] = cats["severe"]
cats["strong"] = cats["severe"]
cats["swiosts"] = cats["severe"]
cats["sts"] = cats["severe"]
cats["severets"] = cats["severe"]
cats["ty"] = cats["typhoon"]
cats["td"] = cats["depression"]
cats["ts"] = cats["storm"]
cats["nwpstorm"] = cats["storm"]
cats["d"] = cats["depression"]
cats["spdepression"] = cats["depression"]
cats["shdepression"] = cats["depression"]
cats["shemdepression"] = cats["depression"]
cats["swiodepression"] = cats["depression"]
cats["spdepression"] = cats["depression"]
cats["nwpdepression"] = cats["depression"]
cats["swsubdep"] = cats["subdepression"]
cats["sd"] = cats["subdepression"]
cats["ss"] = cats["subtropical"]
cats["et"] = cats["extratropical"]
cats["ex"] = cats["extratropical"]
cats["md"] = cats["monsoondepression"]
cats["pt"] = cats["potential"]
cats["potentialtropicalcyclone"] = cats["potential"]
cats["potentialtropicalcyclone"] = cats["potential"]
cats["post"] = cats["posttropical"]
cats["post-tropical"] = cats["posttropical"]
cats["remnantlow"] = cats["remnant"]
cats["rl"] = cats["remnant"]
cats["sucs"] = cats["sprcyclstorm"]
cats["escs"] = cats["esvrcyclstorm"]
cats["vscs"] = cats["vsvrcyclstorm"]
cats["scs"] = cats["svrcyclstorm"]
cats["cs"] = cats["niocyclone"]
cats["dd"] = cats["deepdepression"]
cats["cyclstorm"] = cats["niocyclone"]
cats["landdepression"] = cats["nioland"]
cats["land"] = cats["nioland"]
cats["ld"] = cats["nioland"]
cats["fiji5"] = cats["aus5"]
cats["fiji4"] = cats["aus4"]
cats["fiji3"] = cats["aus3"]
cats["fiji2"] = cats["aus2"]
cats["fiji1"] = cats["aus1"]
cats["tl"] = cats["low"]
cats["di"] = cats["disturbance"]
cats["swiodisturbance"] = cats["disturbance"]
cats["mts"] = cats["mstorm"]
cats["sub"] = cats["mstorm"]
cats["vitc"] = cats["vintense"]
cats["itc"] = cats["intense"]
cats["tc"] = cats["tropicalcyclone"]
cats["swiotc"] = cats["tropicalcyclone"]
cats["shem3"] = cats["tropicalcyclone"]
cats["shemtc"] = cats["tropicalcyclone"]
-- Ambiguous color names. This is because the old {[storm colour}} itself is
-- extremely ambiguous. This is also used to override the output of some codes.
local colors = {
-- Basin colors
["5"] = cats["cat5"].color,
["4"] = cats["cat4"].color,
["3"] = cats["cat3"].color,
["2"] = cats["cat2"].color,
["1"] = cats["cat1"].color,
-- Enhanced Fujita scale
["ef5"] = cats["cat5"].color,
["ef4"] = cats["cat4"].color,
["ef3"] = cats["cat3"].color,
["ef2"] = cats["cat2"].color,
["ef1"] = cats["cat1"].color,
["ef0"] = cats["ts"].color,
-- Depression
["d"] = "80ccff",
-- FMS scale
["a5"] = cats["aus5"].color,
["a4"] = cats["aus4"].color,
["a3"] = cats["aus3"].color,
["a2"] = cats["aus2"].color,
["a1"] = cats["aus1"].color
}
-- Icon overrides for old {{Tropical cyclone status icons}} that don't have a
-- viable category.
local icons = {
-- Ambiguious 5-tier scale
["1"] = cats["cat1"].icon,
["2"] = cats["cat2"].icon,
["3"] = cats["cat3"].icon,
["4"] = cats["cat4"].icon,
["5"] = cats["cat5"].icon,
-- FMS scale
["a5"] = cats["aus5"].icon,
["a4"] = cats["aus4"].icon,
["a3"] = cats["aus3"].icon,
["a2"] = cats["aus2"].icon,
["a1"] = cats["aus1"].icon,
-- Misc
["extratropical2"] = "[[File:Extratropical storm icon.png|18px]]",
["typhoon"] = "[[File:Typhoon icon.png|18px]]",
["swiosts"] = "[[File:Severe tropical storm south icon.png|18px]]",
["swiotc"] = "[[File:SWIO tropical cyclone icon.png|18px]]"
}
icons["et2"] = icons["extratropical2"]
icons["ex2"] = icons["extratropical2"]
icons["ty"] = icons["typhoon"]
icons["stss"] = icons["swiosts"]
icons["tc"] = icons["swiotc"]
local customKeys = {}
for k, v in pairs(colors) do
table.insert(customKeys, k)
end
for k, v in pairs(icons) do
table.insert(customKeys, k)
end
TableTools.removeDuplicates(customKeys)
function p.color(frame)
return p._color(frame.args[1] or frame:getParent().args[1], false)
end
function p.name(frame)
return p._name(
frame.args[1] or frame:getParent().args[1],
frame.args[2] or frame:getParent().args[2],
false
)
end
function p.sortkey(frame)
return p._sortkey(frame.args[1] or frame:getParent().args[1], false)
end
function p.icon(frame)
return p._icon(frame.args[1] or frame:getParent().args[1], false)
end
function p._color(colorCode, nullIfMissing)
-- This looks confusing, but it's actually nested ternaries (for nil checks)
local color = (colorCode ~= nil and string.len(colorCode) ~= 0) and
string.gsub(string.lower(colorCode), "[^%w]", "")
or defaultCategory
return colors[color] or ((cats[color] or (
nullIfMissing
and { color = nil }
or cats[defaultCategory]
)).color)
end
function p._name(category, basin, nullIfMissing)
local name_def = (cats[
(category ~= nil and string.len(category) ~= 0) and
string.gsub(string.lower(category), "[^%w]", "")
or defaultCategory
] or cats[defaultCategory]).name
return type(name_def) == "table" and
(
name_def[string.lower(basin or "default")]
or name_def["default"]
or (nullIfMissing and nil or error("No default name for basin-based category name."))
)
or name_def
end
function p._sortkey(category, nullIfMissing)
-- This looks confusing, but it's actually nested ternaries (for nil checks)
return (cats[
(category ~= nil and string.len(category) ~= 0) and
string.gsub(string.lower(category), "[^%w]", "")
or defaultCategory
] or (nullIfMissing and { sortkey = nil } or cats[defaultCategory])).sortkey
end
function p._icon(iconCode, nullIfMissing)
-- This looks confusing, but it's actually nested ternaries (for nil checks)
local icon = (iconCode ~= nil and string.len(iconCode) ~= 0) and
string.gsub(string.lower(iconCode), "[^%w]", "")
or defaultCategory
return icons[icon] or (cats[icon] ~= nil and (
cats[icon].icon or cats["tropicalcyclone"].icon
) or (nullIfMissing and nil or cats[defaultCategory].icon))
end
function count(_table)
local n = 0
for _ in pairs(_table) do
n = n + 1
end
return n
end
function inlineWarning(details, icon)
return mw.html.create("span")
:css("color", "darkred")
:wikitext("(")
:node(
mw.html.create("span")
:attr("title", details)
:css("text-decoration", "underline")
:css("text-decoration-style", "dotted")
:wikitext(icon or "!")
)
:wikitext(")")
end
function p.demo(frame)
local out = mw.html.create("table")
:addClass("wikitable")
:addClass("sortable")
:attr("style", "width: 100%")
out
:node(
mw.html.create("tr")
:node(mw.html.create("th"):wikitext("Icon")
:attr("class", "unsortable")
:attr("rowspan", "2")
:css("width", "0"))
:node(mw.html.create("th"):wikitext("ID")
:attr("rowspan", "2"))
:node(mw.html.create("th"):wikitext("Name")
:attr("colspan", "2"))
:node(mw.html.create("th"):wikitext("Color")
:attr("rowspan", "2")
:attr("colspan", "2"))
:node(mw.html.create("th"):wikitext("Sortkey")
:attr("colspan", "2"))
):node(
mw.html.create("tr")
:node(mw.html.create("th"):wikitext("Basin"))
:node(mw.html.create("th"):wikitext("Name"))
:node(mw.html.create("th"):wikitext("Basin"))
:node(mw.html.create("th"):wikitext("Sortkey")
:attr("data-sort-type", "number"))
)
local legends = {}
for name, cat in TableTools.sortedPairs(cats) do
local rows = { mw.html.create("tr") }
local row = rows[1]
local actualIcon = p._icon(name)
local icon = mw.html.create("td")
:wikitext(actualIcon)
if cat["icon"] ~= nil and actualIcon ~= cat["icon"] then
icon
:wikitext(" ")
:node(
mw.html.create("span")
:css("text-decoration", "underline")
:css("text-decoration-style", "dotted")
:attr("title", "Overriden from original icon (" .. cat["icon"] .. ")")
:wikitext("*")
)
legends["*"] = "Overriden from original icon."
end
local id = mw.html.create("td")
:wikitext(name)
local actualColor = p._color(name)
local colorPreview = mw.html.create("td")
:attr("style", "background-color: #" .. actualColor .. "; padding: 0; width: 1.8em")
local color = mw.html.create("td")
:wikitext("#" .. actualColor)
if actualColor ~= cat["color"] then
color
:node(
mw.html.create("span")
:css("text-decoration", "underline")
:css("text-decoration-style", "dotted")
:attr("title", "Overriden from original color (#" .. cat["color"] .. ")")
:wikitext("**")
)
legends["**"] = "Overriden from original color."
end
local catColorBlackRatio = colorRatio({ "#" .. actualColor, "black" })
local catColorLinkRatio = colorRatio({ "#" .. actualColor, "#0645ad" })
local catColorVisitedLinkRatio = colorRatio({ "#" .. actualColor, "#0b0080" })
if catColorBlackRatio == "?" or catColorLinkRatio == "?" or catColorVisitedLinkRatio == "?" then
color
:wikitext(" ")
:node(inlineWarning("This color must be a hexadecimal color.", "E"))
legends["E"] = "Not a valid hexadecimal color code."
else
if catColorBlackRatio < 4.5 then
color
:wikitext(" ")
:node(inlineWarning("This color has contrast issues with black (not WCAG 2.0 AA-compatible).", "C"))
legends["C"] = "Color has contrast issues with black."
end
if catColorLinkRatio < 4.5 then
color
:wikitext(" ")
:node(inlineWarning("This color has contrast issues with links (not WCAG 2.0 AA-compatible).", "L"))
legends["L"] = "Color has contrast issues with links (#0645ad)."
end
if catColorVisitedLinkRatio < 4.5 then
color
:wikitext(" ")
:node(inlineWarning("This color has contrast issues with visited links (not WCAG 2.0 AA-compatible).", "V"))
legends["V"] = "Color has contrast issues with visited links (#0b0080)."
end
end
local sortkeyCategory = mw.html.create("td")
:attr("data-sort-value", cat["sortkey"])
local sortkey = mw.html.create("td")
:attr("data-sort-value", cat["sortkey"])
:wikitext(cat["sortkey"])
if cat["sortkey"] < 0 then
sortkeyCategory:wikitext("Invalid")
elseif cat["sortkey"] < 20000 then
sortkeyCategory:wikitext("Global")
elseif cat["sortkey"] < 30000 then
sortkeyCategory:wikitext("Historical")
elseif cat["sortkey"] < 40000 then
sortkeyCategory:wikitext("SWIO")
elseif cat["sortkey"] < 50000 then
sortkeyCategory:wikitext("Aus/Fiji")
elseif cat["sortkey"] < 60000 then
sortkeyCategory:wikitext("NIO")
elseif cat["sortkey"] < 80000 then
sortkeyCategory:wikitext("WPAC")
elseif cat["sortkey"] < 90000 then
sortkeyCategory:wikitext("Atl/EPac/SAtl")
elseif cat["sortkey"] < 100000 then
sortkeyCategory:attr("style", "color: gray")
sortkeyCategory:wikitext("''Global''")
else
sortkeyCategory:wikitext("Invalid")
end
if type(cat["name"]) == "string" then
local name = mw.html.create("td")
:attr("colspan", "2")
:wikitext(cat["name"])
row:node(icon)
row:node(id)
row:node(name)
else
local nameTableLength = count(cat["name"])
icon:attr("rowspan", nameTableLength)
id:attr("rowspan", nameTableLength)
colorPreview:attr("rowspan", nameTableLength)
color:attr("rowspan", nameTableLength)
sortkeyCategory:attr("rowspan", nameTableLength)
sortkey:attr("rowspan", nameTableLength)
row:node(icon)
row:node(id)
local firstDone = false
for key, basinName in TableTools.sortedPairs(cat["name"]) do
if firstDone then
local nameRow = mw.html.create("tr")
nameRow
:node(mw.html.create("td"):wikitext(key))
:node(mw.html.create("td"):wikitext(basinName))
table.insert(rows, nameRow)
else
firstDone = true
row
:node(mw.html.create("td"):wikitext(key))
:node(mw.html.create("td"):wikitext(basinName))
end
end
end
row:node(colorPreview)
row:node(color)
row:node(sortkeyCategory)
row:node(sortkey)
for _, _row in TableTools.sortedPairs(rows) do
out:node(_row)
end
end
for name, _ in TableTools.sortedPairs(TableTools.listToSet(customKeys)) do
if cats[name] == nil then
local row = mw.html.create("tr")
local icon = p._icon(name, true)
row
:node(mw.html.create("td")
:wikitext(
icon ~= nil
and icon
or "''<span style=\"color:gray\">N/A</span>''"
))
:node(mw.html.create("td"):wikitext(name))
local color = p._color(name, true)
-- Add more conditions eventually
if color ~= nil then
row
:node(mw.html.create("td")
:attr("colspan", "2")
:wikitext("''<span style=\"color:gray\">not available</span>''"))
:node(mw.html.create("td")
:attr("style", "background-color: #" .. color .. "; padding: 0; width: 1.8em"))
:node(mw.html.create("td")
:wikitext("#" .. color))
:node(mw.html.create("td")
:attr("colspan", "2")
:wikitext("''<span style=\"color:gray\">not available</span>''"))
else
row
:node(mw.html.create("td")
:attr("colspan", "6")
:wikitext("''<span style=\"color:gray\">not available</span>''"))
end
out:node(row)
end
end
local legendsCompiled = mw.html.create("ul")
local showLegend = false
legendsCompiled
:css("list-style-icon", "none")
:css("list-style-type", "none")
for legend, details in TableTools.sortedPairs(legends) do
showLegend = true
legendsCompiled:node(
mw.html.create("li")
-- en dash
:wikitext("'''" .. legend .. "''' – " .. details)
)
end
return (showLegend and tostring(legendsCompiled) or "") .. tostring(out)
end
p.cats = cats
return p