Difference between revisions of "Module:Weather/sandbox"
blackwiki>Erutuon m (mismatch between old and new convert function was causing an error) |
blackwiki>Erutuon (changing function and variable names to remove underscores; begin replacing some if-statements with simpler and-or expressions) |
||
| Line 1: | Line 1: | ||
export = {} | export = {} | ||
| − | degree = "°" -- used by | + | degree = "°" -- used by add_unitNames() |
minus = "−" -- used by makeRow() and makeTable() | minus = "−" -- used by makeRow() and makeTable() | ||
thinSpace = mw.ustring.char(0x2009) -- used by makeCell() | thinSpace = mw.ustring.char(0x2009) -- used by makeCell() | ||
| Line 7: | Line 7: | ||
message = "" | message = "" | ||
| − | local function | + | local function addMessage(new_message) |
if show then | if show then | ||
| − | if | + | if checkForString(message) then |
message = message .. " " .. new_message | message = message .. " " .. new_message | ||
else | else | ||
| Line 18: | Line 18: | ||
-- Input and output parameters | -- Input and output parameters | ||
| − | local function | + | local function getFormat (frame) |
| − | local | + | local inputParameter = frame.args.input |
| − | local | + | local outputParameter = frame.args.output |
| − | if | + | if inputParameter == nil then |
error("Please provide the number of values and a unit in the input parameter") | error("Please provide the number of values and a unit in the input parameter") | ||
else | else | ||
| − | length = tonumber(string.match( | + | length = tonumber(string.match(inputParameter, "(%d+)")) -- Find digits in the input parameter. |
| − | + | inputUnit = string.match(inputParameter, "([CF])") -- C or F | |
| − | if string.find( | + | if string.find(inputParameter, "[^CF%d%s]") then |
| − | + | addMessage("There are extraneous characters in the <span style=\"background-color: #EEE; font-family: monospace;\">output</span> parameter.") | |
end | end | ||
end | end | ||
| − | if | + | if inputUnit == "C" then |
| − | + | outputUnit = "F" | |
| − | elseif | + | elseif inputUnit == "F" then |
| − | + | outputUnit = "C" | |
else | else | ||
error ("Please provide an input unit in the input parameter: F for Fahrenheit or C for Celsius", 0) | error ("Please provide an input unit in the input parameter: F for Fahrenheit or C for Celsius", 0) | ||
| Line 41: | Line 41: | ||
if length == nil then | if length == nil then | ||
| − | error (" | + | error ("getFormat has not found a length value in the input parameter") |
end | end | ||
| − | if | + | if outputParameter == nil then |
| − | + | addMessage("No output format has been provided in the <span style=\"background-color: #EEE; font-family: monospace;\">output</span> parameter.") | |
else | else | ||
| − | + | cellFormat = {} | |
local n = 1 | local n = 1 | ||
| − | for unit in | + | for unit in outputParameter:gmatch("[CF]") do |
| − | + | cellFormat[n] = unit | |
n = n + 1 | n = n + 1 | ||
if n > 2 then | if n > 2 then | ||
| Line 56: | Line 56: | ||
end | end | ||
end | end | ||
| − | local function | + | local function setFormat(key, formatVariable, formatValue1, formatValue2) |
| − | if string.find( | + | if string.find(outputParameter, key) then |
| − | + | cellFormat[formatVariable] = formatValue1 | |
else | else | ||
| − | + | cellFormat[formatVariable] = formatValue2 | |
end | end | ||
end | end | ||
| − | if | + | if cellFormat[1] then |
| − | + | cellFormat.first = cellFormat[1] | |
else | else | ||
error("C or F not found in output parameter") | error("C or F not found in output parameter") | ||
end | end | ||
| − | if | + | if cellFormat[2] == nil then |
| − | + | cellFormat["convertUnits"] = "no" | |
else | else | ||
| − | if | + | if cellFormat[2] == cellFormat[1] then |
error("There should not be two of the same unit name in the output parameter.") | error("There should not be two of the same unit name in the output parameter.") | ||
else | else | ||
| − | + | cellFormat["convertUnits"] = "yes" | |
end | end | ||
end | end | ||
| − | + | setFormat("unit", "unitNames", "yes", "no") | |
| − | + | setFormat("no ?color", "color", "no", "yes") | |
| − | + | setFormat("sort", "sortable", "yes", "no") | |
| − | + | setFormat("full ?size", "smallFont", "no", "yes") | |
| − | + | setFormat("no ?brackets", "brackets", "no", "yes") | |
| − | + | setFormat("round", "decimals", "0", "") | |
| − | if string.find( | + | if string.find(outputParameter, "line break") then |
| − | + | cellFormat["lineBreak"] = "yes" | |
| − | elseif string.find( | + | elseif string.find(outputParameter, "one line") then |
| − | + | cellFormat["lineBreak"] = "no" | |
else | else | ||
| − | + | cellFormat["lineBreak"] = "auto" | |
end | end | ||
| − | if string.find( | + | if string.find(outputParameter, "one line") and string.find(outputParameter, "line break") then |
error("Place either \"one line\" or \"line break\" in the output parameter, not both") | error("Place either \"one line\" or \"line break\" in the output parameter, not both") | ||
end | end | ||
| Line 106: | Line 106: | ||
end | end | ||
| − | return length, | + | return length, inputUnit, outputUnit |
end | end | ||
-- Number and string-handling functions | -- Number and string-handling functions | ||
| − | local function | + | local function checkForNumber(value) |
return type(tonumber(value)) == "number" | return type(tonumber(value)) == "number" | ||
end | end | ||
| − | function | + | function checkForString(string) |
string = tostring(string) | string = tostring(string) | ||
return string ~= "" and string ~= nil | return string ~= "" and string ~= nil | ||
| Line 126: | Line 126: | ||
elseif value == nil then | elseif value == nil then | ||
value = "nil" | value = "nil" | ||
| − | + | addMessage("Format was asked to operate on " .. value .. ", which cannot be converted to a number.", 2) | |
return "" | return "" | ||
end | end | ||
end | end | ||
| − | local function convert(value, decimals, unit) -- Unit is the unit being converted from. It defaults to | + | local function convert(value, decimals, unit) -- Unit is the unit being converted from. It defaults to inputUnit. |
if not unit then | if not unit then | ||
| − | unit = | + | unit = inputUnit |
end | end | ||
| − | if | + | if checkForNumber(value) then |
local value = tonumber(value) | local value = tonumber(value) | ||
if unit == "C" then | if unit == "C" then | ||
| − | + | addMessage(value .. " " .. degree .. unit .. " was converted.") | |
return round(value * 9/5 + 32, decimals) | return round(value * 9/5 + 32, decimals) | ||
elseif unit == "F" then | elseif unit == "F" then | ||
| − | + | addMessage(value .. " " .. degree .. unit .. " was converted.") | |
return round((value - 32) * 5/9, decimals) | return round((value - 32) * 5/9, decimals) | ||
else | else | ||
| Line 152: | Line 152: | ||
-- Input parsing | -- Input parsing | ||
| − | function | + | function makeArray(parameter, array, frame) |
local array = {} | local array = {} | ||
local n = 1 | local n = 1 | ||
| Line 172: | Line 172: | ||
end | end | ||
if not array[length] then | if not array[length] then | ||
| − | + | addMessage("There are not " .. length .. " values in the " .. parameter .. " parameter.") | |
end | end | ||
return array, precision | return array, precision | ||
end | end | ||
| − | function | + | function makeArrays(frame) |
| − | + | getFormat(frame) | |
local parameter_a = frame.args.a | local parameter_a = frame.args.a | ||
local parameter_b = frame.args.b | local parameter_b = frame.args.b | ||
local parameter_c = frame.args.c | local parameter_c = frame.args.c | ||
if parameter_a then | if parameter_a then | ||
| − | a = | + | a = makeArray(parameter_a, a, frame) |
else | else | ||
error("Please provide a set of numbers in parameter a") | error("Please provide a set of numbers in parameter a") | ||
end | end | ||
if parameter_b then | if parameter_b then | ||
| − | b = | + | b = makeArray(parameter_b, b, frame) |
else | else | ||
| − | + | addMessage("There is no content in parameter <span style=\"background-color: #EEE; font-family: monospace;\">b</span>.") | |
end | end | ||
if parameter_c then | if parameter_c then | ||
| − | c = | + | c = makeArray(parameter_c, c, frame) |
else | else | ||
| − | + | addMessage("There is no content in parameter <span style=\"background-color: #EEE; font-family: monospace;\">c</span>.") | |
end | end | ||
return a, b, c | return a, b, c | ||
| Line 227: | Line 227: | ||
} | } | ||
| − | local function temperature_color(palette, value, | + | local function temperature_color(palette, value, outRGB) |
--[[ Return style for a table cell based on the given value which | --[[ Return style for a table cell based on the given value which | ||
should be a temperature in °C. ]] | should be a temperature in °C. ]] | ||
| − | local | + | local backgroundColor, textColor |
value = tonumber(value) | value = tonumber(value) | ||
if value == nil then | if value == nil then | ||
| − | + | backgroundColor, textColor = 'FFF', '000' | |
| − | + | addMessage("Value supplied to <span style=\"background-color: #EEE; font-family: monospace;\">temperature_color</span> is not recognized.") | |
else | else | ||
local min, max = unpack(palette.white or { -23, 35 }) | local min, max = unpack(palette.white or { -23, 35 }) | ||
if value < min or value >= max then | if value < min or value >= max then | ||
| − | + | textColor = 'FFF' | |
else | else | ||
| − | + | textColor = '' -- This assumes that black text color is the default for most readers. | |
end | end | ||
| − | local | + | local backgroundRGB = outRGB or {} |
for i, v in ipairs(palette) do | for i, v in ipairs(palette) do | ||
local a, b, c, d = unpack(v) | local a, b, c, d = unpack(v) | ||
if value <= a then | if value <= a then | ||
| − | + | backgroundRGB[i] = 0 | |
elseif value < b then | elseif value < b then | ||
| − | + | backgroundRGB[i] = (value - a) * 255 / (b - a) | |
elseif value <= c then | elseif value <= c then | ||
| − | + | backgroundRGB[i] = 255 | |
elseif value < d then | elseif value < d then | ||
| − | + | backgroundRGB[i] = 255 - ( (value - c) * 255 / (d - c) ) | |
else | else | ||
| − | + | backgroundRGB[i] = 0 | |
end | end | ||
end | end | ||
| − | + | backgroundColor = string.format('%02X%02X%02X', backgroundRGB[1], backgroundRGB[2], backgroundRGB[3]) | |
end | end | ||
| − | if | + | if textColor == "" then |
| − | return | + | return backgroundColor |
else | else | ||
| − | return | + | return backgroundColor, textColor |
end | end | ||
end | end | ||
| − | local function | + | local function colorCSS(backgroundColor, textColor) |
| − | if | + | if backgroundColor and textColor then |
| − | return 'background: #' .. | + | return 'background: #' .. backgroundColor .. '; color: #' .. textColor .. ';' |
| − | elseif | + | elseif backgroundColor then |
| − | return 'background: #' .. | + | return 'background: #' .. backgroundColor .. ';' |
else | else | ||
return '' | return '' | ||
| Line 277: | Line 277: | ||
end | end | ||
| − | local function | + | local function temperatureColorCSS(palette, value, outRGB) |
| − | return | + | return colorCSS(temperature_color(palette, value, outRGB)) |
end | end | ||
| − | function | + | function temperatureCSS(value, unit, palette) |
local palette = palettes[palette] or palettes.cool | local palette = palettes[palette] or palettes.cool | ||
local value = tonumber(value) | local value = tonumber(value) | ||
if value == nil then | if value == nil then | ||
| − | error("The function <span style=\"background-color: #EEE; font-family: monospace;\"> | + | error("The function <span style=\"background-color: #EEE; font-family: monospace;\">temperatureCSS</span> is receiving a nil value") |
else | else | ||
if unit == 'C' then | if unit == 'C' then | ||
| − | return | + | return colorCSS(temperature_color(palette, value)) |
elseif unit == 'F' then | elseif unit == 'F' then | ||
| − | return | + | return colorCSS(temperature_color(palette, convert(value, decimals, 'F'))) |
else | else | ||
unit_error(unit or "nil") | unit_error(unit or "nil") | ||
| Line 297: | Line 297: | ||
end | end | ||
| − | local function | + | local function styleAttribute(palette, value, outRGB) |
local font_size = "font-size: 85%;" | local font_size = "font-size: 85%;" | ||
| − | local color = | + | local color = temperatureColorCSS(palette, value, outRGB) |
return 'style=\"' .. color .. ' ' .. font_size .. '\"' | return 'style=\"' .. color .. ' ' .. font_size .. '\"' | ||
end | end | ||
| − | function export. | + | style_attribute = styleAttribute |
| + | |||
| + | function export.temperatureStyle(frame) -- used by Template:Average temperature table/color | ||
local palette = palettes[frame.args.palette] or palettes.cool | local palette = palettes[frame.args.palette] or palettes.cool | ||
local unit = frame.args.unit or 'C' | local unit = frame.args.unit or 'C' | ||
local value = tonumber(frame.args[1]) | local value = tonumber(frame.args[1]) | ||
if unit == 'C' then | if unit == 'C' then | ||
| − | return | + | return styleAttribute(palette, value) |
elseif unit == 'F' then | elseif unit == 'F' then | ||
| − | return | + | return styleAttribute(palette, convert(value, 1, 'F')) |
else | else | ||
unit_error(unit) | unit_error(unit) | ||
end | end | ||
end | end | ||
| + | |||
| + | export.temperature_style = export.temperatureStyle | ||
--[[ ==== Cell, row, table generation ==== ]] | --[[ ==== Cell, row, table generation ==== ]] | ||
| Line 320: | Line 324: | ||
high_low_average_F = | high_low_average_F = | ||
{ first = "F", | { first = "F", | ||
| − | + | convertUnits = "yes", | |
| − | + | unitNames = "no", | |
color = "yes", | color = "yes", | ||
| − | + | smallFont = "yes", | |
sortable = "yes", | sortable = "yes", | ||
decimals = "0", | decimals = "0", | ||
brackets = "yes", | brackets = "yes", | ||
| − | + | lineBreak = "auto", }, | |
high_low_average_C = | high_low_average_C = | ||
{ first = "C", | { first = "C", | ||
| − | + | convertUnits = "yes", | |
| − | + | unitNames = "no", | |
color = "yes", | color = "yes", | ||
| − | + | smallFont = "yes", | |
sortable = "yes", | sortable = "yes", | ||
decimals = "0", | decimals = "0", | ||
brackets = "yes", | brackets = "yes", | ||
| − | + | lineBreak = "auto", }, | |
high_low_F = | high_low_F = | ||
{ first = "F", | { first = "F", | ||
| − | + | convertUnits = "yes", | |
| − | + | unitNames = "no", | |
color = "no", | color = "no", | ||
| − | + | smallFont = "yes", | |
sortable = "no", | sortable = "no", | ||
decimals = "", | decimals = "", | ||
brackets = "yes", | brackets = "yes", | ||
| − | + | lineBreak = "auto", }, | |
high_low_C = | high_low_C = | ||
{ first = "C", | { first = "C", | ||
| − | + | convertUnits = "yes", | |
| − | + | unitNames = "no", | |
color = "no", | color = "no", | ||
| − | + | smallFont = "yes", | |
sortable = "no", | sortable = "no", | ||
decimals = "0", | decimals = "0", | ||
brackets = "yes", | brackets = "yes", | ||
| − | + | lineBreak = "auto", }, | |
average_F = | average_F = | ||
{ first = "F", | { first = "F", | ||
| − | + | convertUnits = "yes", | |
| − | + | unitNames = "no", | |
color = "yes", | color = "yes", | ||
| − | + | smallFont = "yes", | |
sortable = "no", | sortable = "no", | ||
decimals = "0", | decimals = "0", | ||
brackets = "yes", | brackets = "yes", | ||
| − | + | lineBreak = "auto", }, | |
average_C = | average_C = | ||
{ first = "C", | { first = "C", | ||
| − | + | convertUnits = "yes", | |
| − | + | unitNames = "no", | |
color = "yes", | color = "yes", | ||
| − | + | smallFont = "yes", | |
sortable = "no", | sortable = "no", | ||
decimals = "0", | decimals = "0", | ||
brackets = "yes", | brackets = "yes", | ||
| − | + | lineBreak = "auto", }, | |
} | } | ||
| − | local function | + | local function add_unitNames(value, unit) |
| − | if not unit then unit = | + | if not unit then unit = inputUnit end |
| − | + | -- Don't add a unit name to an empty string | |
| − | + | value = output_format.unitNames == "yes" and checkForString(value) and value .. " " .. degree .. unit or value | |
| − | + | return value | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
end | end | ||
| Line 410: | Line 408: | ||
else | else | ||
parameter = "" | parameter = "" | ||
| − | + | addMessage("<span style=\"background-color: #EEE; font-family: monospace;\">if_yes</span> needs at least one realization") | |
end | end | ||
return parameter | return parameter | ||
| Line 417: | Line 415: | ||
function makeCell(output_format, a, b, c) | function makeCell(output_format, a, b, c) | ||
local cell, cell_content = "", "" | local cell, cell_content = "", "" | ||
| − | local | + | local colorCSS, other_CSS, title_attribute, sortkey, attribute_separator, converted_units_separator = "", "", "", "", "", "", "" |
| − | local | + | local styleAttribute, high_low_separator, brackets, values, converted_units = {"", ""}, {"", ""}, {"", ""}, {"", ""}, {"", ""} |
| − | + | -- Distinguish styleAttribute variable from styleAttribute function above. | |
| − | + | decimals = ( checkForNumber(output_format.decimals) and output_format.decimals ) or precision | |
| − | |||
--[[ Precision is the number of decimals in the first number of the last array. | --[[ Precision is the number of decimals in the first number of the last array. | ||
This may be a problem for data from Weatherbase, | This may be a problem for data from Weatherbase, | ||
which seems to inappropriately remove .0 from numbers that have it. ]] | which seems to inappropriately remove .0 from numbers that have it. ]] | ||
| − | |||
| − | |||
| − | |||
| − | if | + | if checkForNumber(b) and checkForNumber(a) then |
| − | values, high_low_separator = { round(a, decimals), round(b, decimals) }, { thinSpace .. "/" .. thinSpace, if_yes(output_format. | + | values, high_low_separator = { round(a, decimals), round(b, decimals) }, { thinSpace .. "/" .. thinSpace, if_yes(output_format.convertUnits, thinSpace .. "/" .. thinSpace) } |
| − | elseif | + | elseif checkForNumber(a) then |
values = { round(a, decimals), "" } | values = { round(a, decimals), "" } | ||
| − | elseif | + | elseif checkForNumber(c) then |
values = { round(c, decimals), "" } | values = { round(c, decimals), "" } | ||
end | end | ||
| − | if output_format.first == | + | if output_format.first == inputUnit then |
| − | if output_format. | + | if output_format.convertUnits == "yes" then |
| − | converted_units = { | + | converted_units = { add_unitNames(convert(values[1], decimals), outputUnit), add_unitNames(convert(values[2], decimals), outputUnit) } |
end | end | ||
| − | values = { | + | values = { add_unitNames(values[1]), add_unitNames(values[2]) } |
elseif output_format.first == "C" or output_format.first == "F" then | elseif output_format.first == "C" or output_format.first == "F" then | ||
| − | if output_format. | + | if output_format.convertUnits == "yes" then |
| − | converted_units = { | + | converted_units = { add_unitNames(values[1]), add_unitNames(values[2]) } |
end | end | ||
| − | values = { | + | values = { add_unitNames(convert(values[1], decimals), outputUnit), add_unitNames(convert(values[2], decimals), outputUnit) } |
else | else | ||
if output_format.first == nil then | if output_format.first == nil then | ||
output_format.first = "nil" | output_format.first = "nil" | ||
end | end | ||
| − | + | addMessage("<span style=\"background-color: #EEE; font-family: monospace;\">" .. output_format.first .. "</span>, the value for <span style=\"background-color: #EEE; font-family: monospace;\">first</span> in <span style=\"background-color: #EEE; font-family: monospace;\">output_format</span> is not recognized.") | |
end | end | ||
--[[ | --[[ | ||
| Line 462: | Line 456: | ||
even more so when more than one of these things are true. | even more so when more than one of these things are true. | ||
]] | ]] | ||
| − | if output_format. | + | if output_format.convertUnits == "yes" then |
brackets = if_yes(output_format.brackets, "(", ")" ) | brackets = if_yes(output_format.brackets, "(", ")" ) | ||
| − | if output_format. | + | if output_format.lineBreak == "auto" then |
| − | if | + | if checkForString(values[2]) or decimals ~= "0" or output_format.show_units == "yes" then |
converted_units_separator = "<br>" | converted_units_separator = "<br>" | ||
else | else | ||
converted_units_separator = " " | converted_units_separator = " " | ||
end | end | ||
| − | elseif output_format. | + | elseif output_format.lineBreak == "yes" then |
converted_units_separator = "<br>" | converted_units_separator = "<br>" | ||
| − | elseif output_format. | + | elseif output_format.lineBreak == "no" then |
converted_units_separator = " " | converted_units_separator = " " | ||
else | else | ||
| − | error("Value for | + | error("Value for lineBreak not recognized") |
end | end | ||
end | end | ||
| Line 481: | Line 475: | ||
cell_content = values[1] .. high_low_separator[1] .. values[2] .. converted_units_separator .. brackets[1] .. converted_units[1] .. high_low_separator[2] .. converted_units[2] .. brackets[2] | cell_content = values[1] .. high_low_separator[1] .. values[2] .. converted_units_separator .. brackets[1] .. converted_units[1] .. high_low_separator[2] .. converted_units[2] .. brackets[2] | ||
| − | if | + | if checkForNumber(c) then |
| − | + | colorCSS = if_yes(output_format.color, temperatureCSS(c, inputUnit, palette)) | |
| − | if | + | if checkForNumber(b) and checkForNumber(a) then |
local attribute_value | local attribute_value | ||
| − | if output_format.first == | + | if output_format.first == inputUnit then |
attribute_value = c | attribute_value = c | ||
else | else | ||
| Line 493: | Line 487: | ||
title_attribute = " title=\"Average temperature: " .. attribute_value .. " " .. degree .. output_format.first .. "\"" | title_attribute = " title=\"Average temperature: " .. attribute_value .. " " .. degree .. output_format.first .. "\"" | ||
end | end | ||
| − | elseif | + | elseif checkForNumber(b) then |
| − | + | colorCSS = "" | |
| − | elseif | + | elseif checkForNumber(a) then |
| − | + | colorCSS = if_yes(output_format.color, temperatureCSS(a, inputUnit, palette)) | |
else | else | ||
| − | + | addMessage("Neither a nor b nor c are strings.") | |
end | end | ||
| − | other_CSS = if_yes(output_format. | + | other_CSS = if_yes(output_format.smallFont, "font-size: 85%;") |
| − | if | + | if checkForString(colorCSS) or checkForString(other_CSS) then |
| − | + | styleAttribute = { "style=\"", "\"" } | |
end | end | ||
| − | if | + | if checkForString(other_CSS) or checkForString(colorCSS) or checkForString(title_attribute) or checkForString(sortkey) then |
attribute_separator = " | " | attribute_separator = " | " | ||
end | end | ||
| − | cell = "\n| " .. | + | cell = "\n| " .. styleAttribute[1] .. colorCSS .. other_CSS .. styleAttribute[2] .. title_attribute .. sortkey .. attribute_separator .. cell_content |
return cell | return cell | ||
end | end | ||
function export.makeRow(frame) | function export.makeRow(frame) | ||
| − | + | makeArrays(frame) | |
local output = "" | local output = "" | ||
if frame.args[1] then | if frame.args[1] then | ||
| Line 522: | Line 516: | ||
end | end | ||
end | end | ||
| − | if | + | if cellFormat then |
| − | output_format = | + | output_format = cellFormat |
end | end | ||
if a and b and c then | if a and b and c then | ||
| Line 552: | Line 546: | ||
function export.makeTable(frame) | function export.makeTable(frame) | ||
| − | + | makeArrays(frame) | |
local output = "{| class=\"wikitable center nowrap\"" | local output = "{| class=\"wikitable center nowrap\"" | ||
| − | if | + | if cellFormat then |
| − | output_format = | + | output_format = cellFormat |
end | end | ||
if a and b and c then | if a and b and c then | ||
| Line 644: | Line 638: | ||
local columns = 0 | local columns = 0 | ||
for celsius = first, last do | for celsius = first, last do | ||
| − | local | + | local backgroundRGB = {} |
| − | local style = | + | local style = styleAttribute(palette, celsius, backgroundRGB) |
| − | local R = math.floor( | + | local R = math.floor(backgroundRGB[1]) |
| − | local G = math.floor( | + | local G = math.floor(backgroundRGB[2]) |
| − | local B = math.floor( | + | local B = math.floor(backgroundRGB[3]) |
xvals:add(celsius) | xvals:add(celsius) | ||
reds:add(R) | reds:add(R) | ||
Revision as of 18:54, 6 October 2016
Testcases
Random examples
|output=nocolor sortable one line round CF
| −4 / −14 (25 / 6) | −2 / −12 (28 / 10) | 2 / −7 (36 / 19) | 8 / −1 (47 / 30) | 13 / 3 (56 / 38) | 18 / 7 (64 / 44) | 22 / 11 (71 / 52) | 22 / 12 (72 / 54) | 18 / 8 (64 / 47) | 11 / 2 (52 / 36) | 4 / −4 (39 / 25) | 0 / −11 (32 / 12) | 9 / −1 (49 / 31) |
|output=FC line break round units
| 16 °F (−9 °C) |
19 °F (−7 °C) |
28 °F (−2 °C) |
39 °F (4 °C) |
47 °F (8 °C) |
54 °F (12 °C) |
62 °F (17 °C) |
63 °F (17 °C) |
56 °F (13 °C) |
44 °F (7 °C) |
32 °F (0 °C) |
20 °F (−7 °C) |
40 °F (4 °C) |
|output=F
| 15.6 | 19.1 | 27.7 | 38.8 | 47.0 | 53.8 | 61.5 | 63.2 | 55.8 | 44.2 | 32.3 | 20.0 | 40.0 |
|output=nocolor sortable round F
| 25 / 6 | 28 / 10 | 36 / 19 | 47 / 30 | 56 / 38 | 64 / 44 | 71 / 52 | 72 / 54 | 64 / 47 | 52 / 36 | 39 / 25 | 32 / 12 | 49 / 31 |
|output=sortable C units
| −4.1 °C / −14.2 °C | −2.0 °C / −12.3 °C | 2.4 °C / −7.2 °C | 8.6 °C / −1.1 °C | 13.3 °C / 3.3 °C | 17.6 °C / 6.7 °C | 21.8 °C / 10.9 °C | 22.3 °C / 12.4 °C | 17.9 °C / 8.6 °C | 11.2 °C / 2.4 °C | 4.1 °C / −3.8 °C | −2.2 °C / −11.1 °C | 9.3 °C / −0.4 °C |
|a=,|b=,|c=
| 25 / 6 (−4 / −14) |
28 / 10 (−2 / −12) |
36 / 19 (2 / −7) |
47 / 30 (8 / −1) |
56 / 38 (13 / 3) |
64 / 44 (18 / 7) |
71 / 52 (22 / 11) |
72 / 54 (22 / 12) |
64 / 47 (18 / 8) |
52 / 36 (11 / 2) |
39 / 25 (4 / −4) |
28 / 12 (−2 / −11) |
40 (4) |
|a=,|b=
| 24.7 / 6.5 (−4.1 / −14.2) |
28.4 / 9.9 (−2.0 / −12.3) |
36.3 / 19.0 (2.4 / −7.2) |
47.4 / 30.1 (8.6 / −1.1) |
56.0 / 37.9 (13.3 / 3.3) |
63.6 / 44.0 (17.6 / 6.7) |
71.2 / 51.7 (21.8 / 10.9) |
72.1 / 54.3 (22.3 / 12.4) |
64.3 / 47.4 (17.9 / 8.6) |
52.1 / 36.4 (11.2 / 2.4) |
39.3 / 25.2 (4.1 / −3.8) |
28.0 / 12.0 (−2.2 / −11.1) |
48.7 / 31.3 (9.3 / −0.4) |
|messages=show
| 24.7 / 6.5 (−4.1 / −14.2) |
28.4 / 9.9 (−2.0 / −12.3) |
36.3 / 19.0 (2.4 / −7.2) |
47.4 / 30.1 (8.6 / −1.1) |
56.0 / 37.9 (13.3 / 3.3) |
63.6 / 44.0 (17.6 / 6.7) |
71.2 / 51.7 (21.8 / 10.9) |
72.1 / 54.3 (22.3 / 12.4) |
64.3 / 47.4 (17.9 / 8.6) |
52.1 / 36.4 (11.2 / 2.4) |
39.3 / 25.2 (4.1 / −3.8) |
28.0 / 12.0 (−2.2 / −11.1) |
48.7 / 31.3 (9.3 / −0.4) |
Notices: There is no content in parameter c. 24.7 °F was converted. 6.5 °F was converted. 28.4 °F was converted. 9.9 °F was converted. 36.3 °F was converted. 19 °F was converted. 47.4 °F was converted. 30.1 °F was converted. 56 °F was converted. 37.9 °F was converted. 63.6 °F was converted. 44 °F was converted. 71.2 °F was converted. 51.7 °F was converted. 72.1 °F was converted. 54.3 °F was converted. 64.3 °F was converted. 47.4 °F was converted. 52.1 °F was converted. 36.4 °F was converted. 39.3 °F was converted. 25.2 °F was converted. 28 °F was converted. 12 °F was converted. 48.7 °F was converted. 31.3 °F was converted.
California
| Place | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec | Year |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Alturas[1] | 44 / 18 (7 / −8) |
48 / 21 (9 / −6) |
54 / 25 (12 / −4) |
60 / 28 (16 / −2) |
70 / 34 (21 / 1) |
79 / 40 (26 / 4) |
90 / 44 (32 / 7) |
89 / 42 (32 / 6) |
80 / 36 (27 / 2) |
68 / 28 (20 / −2) |
52 / 22 (11 / −6) |
42 / 18 (6 / −8) |
47 (8) |
| Bakersfield[2] | 56 / 39 (13 / 4) |
63 / 42 (17 / 6) |
69 / 46 (21 / 8) |
75 / 50 (24 / 10) |
84 / 58 (29 / 14) |
91 / 64 (33 / 18) |
97 / 70 (36 / 21) |
96 / 69 (36 / 21) |
90 / 64 (32 / 18) |
79 / 55 (26 / 13) |
66 / 45 (19 / 7) |
57 / 39 (14 / 4) |
65 (18) |
| Bishop[3] | 54 / 23 (12 / −5) |
58 / 26 (14 / −3) |
66 / 31 (19 / −1) |
73 / 36 (23 / 2) |
82 / 44 (28 / 7) |
92 / 51 (33 / 11) |
98 / 56 (37 / 13) |
96 / 54 (36 / 12) |
88 / 47 (31 / 8) |
76 / 37 (24 / 3) |
63 / 28 (17 / −2) |
53 / 22 (12 / −6) |
57 (14) |
| Bodie[4] | 40 / 5 (4 / −15) |
41 / 7 (5 / −14) |
45 / 11 (7 / −12) |
51 / 17 (11 / −8) |
61 / 24 (16 / −4) |
70 / 30 (21 / −1) |
78 / 34 (26 / 1) |
77 / 32 (25 / 0) |
71 / 26 (22 / −3) |
60 / 18 (16 / −8) |
49 / 11 (9 / −12) |
41 / 6 (5 / −14) |
38 (3) |
| Death Valley[5] | 67 / 40 (19 / 4) |
73 / 46 (23 / 8) |
82 / 55 (28 / 13) |
90 / 62 (32 / 17) |
100 / 73 (38 / 23) |
110 / 81 (43 / 27) |
116 / 88 (47 / 31) |
115 / 86 (46 / 30) |
106 / 76 (41 / 24) |
93 / 62 (34 / 17) |
77 / 48 (25 / 9) |
65 / 38 (18 / 3) |
77 (25) |
| Eureka[6] | 56 / 41 (13 / 5) |
56 / 42 (13 / 6) |
57 / 43 (14 / 6) |
58 / 44 (14 / 7) |
60 / 48 (16 / 9) |
62 / 50 (17 / 10) |
63 / 52 (17 / 11) |
64 / 53 (18 / 12) |
64 / 50 (18 / 10) |
62 / 47 (17 / 8) |
58 / 44 (14 / 7) |
55 / 41 (13 / 5) |
53 (12) |
| Fresno[7] | 55 / 38 (13 / 3) |
62 / 42 (17 / 6) |
68 / 46 (20 / 8) |
75 / 49 (24 / 9) |
84 / 56 (29 / 13) |
92 / 62 (33 / 17) |
98 / 68 (37 / 20) |
97 / 66 (36 / 19) |
91 / 62 (33 / 17) |
80 / 53 (27 / 12) |
65 / 43 (18 / 6) |
55 / 38 (13 / 3) |
64 (18) |
| Los Angeles[8] | 68 / 48 (20 / 9) |
69 / 49 (21 / 9) |
70 / 51 (21 / 11) |
73 / 54 (23 / 12) |
74 / 57 (23 / 14) |
78 / 60 (26 / 16) |
83 / 64 (28 / 18) |
84 / 64 (29 / 18) |
83 / 63 (28 / 17) |
78 / 59 (26 / 15) |
73 / 52 (23 / 11) |
68 / 48 (20 / 9) |
65 (18) |
| Needles[9] | 65 / 44 (18 / 7) |
70 / 47 (21 / 8) |
77 / 52 (25 / 11) |
85 / 59 (29 / 15) |
95 / 68 (35 / 20) |
104 / 77 (40 / 25) |
109 / 84 (43 / 29) |
107 / 83 (42 / 28) |
100 / 74 (38 / 23) |
88 / 62 (31 / 17) |
73 / 50 (23 / 10) |
63 / 42 (17 / 6) |
74 (23) |
| Redding[10] | 55 / 36 (13 / 2) |
60 / 39 (16 / 4) |
64 / 43 (18 / 6) |
70 / 46 (21 / 8) |
81 / 54 (27 / 12) |
90 / 62 (32 / 17) |
98 / 66 (37 / 19) |
97 / 63 (36 / 17) |
90 / 58 (32 / 14) |
78 / 49 (26 / 9) |
62 / 41 (17 / 5) |
54 / 36 (12 / 2) |
62 (17) |
| Riverside[11] | 69 / 43 (21 / 6) |
70 / 45 (21 / 7) |
73 / 46 (23 / 8) |
78 / 50 (26 / 10) |
82 / 55 (28 / 13) |
89 / 59 (32 / 15) |
95 / 64 (35 / 18) |
96 / 64 (36 / 18) |
92 / 61 (33 / 16) |
83 / 55 (28 / 13) |
75 / 46 (24 / 8) |
68 / 42 (20 / 6) |
67 (19) |
| Sacramento[12] | 54 / 39 (12 / 4) |
60 / 41 (16 / 5) |
65 / 44 (18 / 7) |
71 / 46 (22 / 8) |
80 / 51 (27 / 11) |
87 / 56 (31 / 13) |
92 / 58 (33 / 14) |
91 / 58 (33 / 14) |
87 / 56 (31 / 13) |
78 / 50 (26 / 10) |
64 / 43 (18 / 6) |
54 / 38 (12 / 3) |
61 (16) |
| San Diego[13] | 65 / 49 (18 / 9) |
65 / 51 (18 / 11) |
66 / 53 (19 / 12) |
68 / 56 (20 / 13) |
68 / 59 (20 / 15) |
71 / 62 (22 / 17) |
75 / 65 (24 / 18) |
76 / 67 (24 / 19) |
76 / 65 (24 / 18) |
73 / 61 (23 / 16) |
69 / 54 (21 / 12) |
65 / 48 (18 / 9) |
64 (18) |
| San Francisco[14] |
57 / 46 (14 / 8) |
60 / 48 (16 / 9) |
62 / 48 (17 / 9) |
63 / 49 (17 / 9) |
64 / 51 (18 / 11) |
66 / 53 (19 / 12) |
66 / 54 (19 / 12) |
68 / 55 (20 / 13) |
70 / 55 (21 / 13) |
69 / 54 (21 / 12) |
63 / 50 (17 / 10) |
57 / 46 (14 / 8) |
57 (14) |
| San Jose[15] | 58 / 42 (14 / 6) |
62 / 45 (17 / 7) |
66 / 47 (19 / 8) |
69 / 49 (21 / 9) |
74 / 52 (23 / 11) |
79 / 56 (26 / 13) |
82 / 58 (28 / 14) |
82 / 58 (28 / 14) |
80 / 57 (27 / 14) |
74 / 52 (23 / 11) |
64 / 46 (18 / 8) |
58 / 42 (14 / 6) |
61 (16) |
| Santa Rosa[16] | 59 / 39 (15 / 4) |
63 / 41 (17 / 5) |
67 / 43 (19 / 6) |
70 / 45 (21 / 7) |
74 / 48 (23 / 9) |
80 / 52 (27 / 11) |
82 / 52 (28 / 11) |
83 / 53 (28 / 12) |
83 / 52 (28 / 11) |
78 / 48 (26 / 9) |
67 / 43 (19 / 6) |
59 / 39 (15 / 4) |
59 (15) |
| South Lake Tahoe[17] |
43 / 16 (6 / −9) |
44 / 18 (7 / −8) |
48 / 22 (9 / −6) |
54 / 27 (12 / −3) |
64 / 32 (18 / 0) |
72 / 37 (22 / 3) |
81 / 41 (27 / 5) |
80 / 40 (27 / 4) |
74 / 34 (23 / 1) |
63 / 28 (17 / −2) |
50 / 22 (10 / −6) |
43 / 16 (6 / −9) |
44 (7) |
Minnesota
| Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sept | Oct | Nov | Dec | Annual | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Alexandria[18] | 8 (−13) | 15 (−9) | 27 (−3) | 43 (6) | 56 (13) | 65 (18) | 70 (21) | 68 (20) | 58 (14) | 45 (7) | 28 (−2) | 14 (−10) | 41 (5) |
| Brainerd[19] | 6 (−14) | 13 (−11) | 26 (−3) | 42 (6) | 56 (13) | 64 (18) | 69 (21) | 66 (19) | 56 (13) | 44 (7) | 28 (−2) | 13 (−11) | 40 (4) |
| Duluth[20] | 10 (−12) | 17 (−8) | 26 (−3) | 39 (4) | 48 (9) | 58 (14) | 66 (19) | 65 (18) | 56 (13) | 45 (7) | 31 (−1) | 17 (−8) | 40 (4) |
| Grand Marais[21] | 14 (−10) | 19 (−7) | 28 (−2) | 38 (3) | 47 (8) | 53 (12) | 61 (16) | 63 (17) | 55 (13) | 45 (7) | 32 (0) | 19 (−7) | 39 (4) |
| International Falls[22] | 3 (−16) | 11 (−12) | 24 (−4) | 39 (4) | 53 (12) | 62 (17) | 66 (19) | 64 (18) | 53 (12) | 42 (6) | 24 (−4) | 9 (−13) | 32 (0) |
| Redwood Falls[23] | 13 (−11) | 20 (−7) | 32 (0) | 47 (8) | 60 (16) | 70 (21) | 74 (23) | 71 (22) | 62 (17) | 49 (9) | 32 (0) | 18 (−8) | 46 (8) |
| Thief River Falls[24] | 3 (−16) | 11 (−12) | 24 (−4) | 42 (6) | 56 (13) | 64 (18) | 69 (21) | 67 (19) | 56 (13) | 44 (7) | 24 (−4) | 9 (−13) | 39 (4) |
| Twin Cities[25] | 13 (−11) | 20 (−7) | 32 (0) | 47 (8) | 59 (15) | 68 (20) | 73 (23) | 71 (22) | 61 (16) | 49 (9) | 32 (0) | 19 (−7) | 45 (7) |
| Winona[26] | 18 (−8) | 24 (−4) | 36 (2) | 50 (10) | 62 (17) | 71 (22) | 76 (24) | 73 (23) | 64 (18) | 52 (11) | 32 (0) | 23 (−5) | 49 (9) |
| Worthington[27] | 11 (−12) | 18 (−8) | 29 (−2) | 44 (7) | 57 (14) | 67 (19) | 71 (22) | 68 (20) | 59 (15) | 47 (8) | 30 (−1) | 17 (−8) | 43 (6) |
Show function
| −90 | −89 | −88 | −87 | −86 | −85 | −84 | −83 | −82 | −81 |
| −80 | −79 | −78 | −77 | −76 | −75 | −74 | −73 | −72 | −71 |
| −70 | −69 | −68 | −67 | −66 | −65 | −64 | −63 | −62 | −61 |
| −60 | −59 | −58 | −57 | −56 | −55 | −54 | −53 | −52 | −51 |
| −50 | −49 | −48 | −47 | −46 | −45 | −44 | −43 | −42 | −41 |
| −40 | −39 | −38 | −37 | −36 | −35 | −34 | −33 | −32 | −31 |
| −30 | −29 | −28 | −27 | −26 | −25 | −24 | −23 | −22 | −21 |
| −20 | −19 | −18 | −17 | −16 | −15 | −14 | −13 | −12 | −11 |
| −10 | −9 | −8 | −7 | −6 | −5 | −4 | −3 | −2 | −1 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
| 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
| 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
<graph>{"legends":[],"scales":[{"type":"linear","name":"x","zero":false,"domain":{"data":"chart","field":"x"},"range":"width","nice":true},{"type":"linear","name":"y","domain":{"data":"chart","field":"y"},"zero":false,"range":"height","nice":true},{"domain":{"data":"chart","field":"series"},"type":"ordinal","name":"color","range":["red"]}],"version":2,"marks":[{"type":"line","properties":{"hover":{"stroke":{"value":"red"}},"update":{"stroke":{"scale":"color","field":"series"}},"enter":{"y":{"scale":"y","field":"y"},"x":{"scale":"x","field":"x"},"stroke":{"scale":"color","field":"series"},"strokeWidth":{"value":2.5}}},"from":{"data":"chart"}}],"height":180,"axes":[{"type":"x","title":"Celsius","scale":"x","format":"d","properties":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"grid":false},{"type":"y","title":"Red","scale":"y","format":"d","properties":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"grid":false}],"data":[{"format":{"parse":{"y":"integer","x":"integer"},"type":"json"},"name":"chart","values":[{"y":0,"series":"y","x":-90},{"y":0,"series":"y","x":-89},{"y":0,"series":"y","x":-88},{"y":0,"series":"y","x":-87},{"y":0,"series":"y","x":-86},{"y":0,"series":"y","x":-85},{"y":0,"series":"y","x":-84},{"y":0,"series":"y","x":-83},{"y":0,"series":"y","x":-82},{"y":0,"series":"y","x":-81},{"y":0,"series":"y","x":-80},{"y":0,"series":"y","x":-79},{"y":0,"series":"y","x":-78},{"y":0,"series":"y","x":-77},{"y":0,"series":"y","x":-76},{"y":0,"series":"y","x":-75},{"y":0,"series":"y","x":-74},{"y":0,"series":"y","x":-73},{"y":0,"series":"y","x":-72},{"y":0,"series":"y","x":-71},{"y":0,"series":"y","x":-70},{"y":0,"series":"y","x":-69},{"y":0,"series":"y","x":-68},{"y":0,"series":"y","x":-67},{"y":0,"series":"y","x":-66},{"y":0,"series":"y","x":-65},{"y":0,"series":"y","x":-64},{"y":0,"series":"y","x":-63},{"y":0,"series":"y","x":-62},{"y":0,"series":"y","x":-61},{"y":0,"series":"y","x":-60},{"y":0,"series":"y","x":-59},{"y":0,"series":"y","x":-58},{"y":0,"series":"y","x":-57},{"y":0,"series":"y","x":-56},{"y":0,"series":"y","x":-55},{"y":0,"series":"y","x":-54},{"y":0,"series":"y","x":-53},{"y":0,"series":"y","x":-52},{"y":0,"series":"y","x":-51},{"y":0,"series":"y","x":-50},{"y":0,"series":"y","x":-49},{"y":0,"series":"y","x":-48},{"y":0,"series":"y","x":-47},{"y":0,"series":"y","x":-46},{"y":0,"series":"y","x":-45},{"y":0,"series":"y","x":-44},{"y":0,"series":"y","x":-43},{"y":4,"series":"y","x":-42},{"y":9,"series":"y","x":-41},{"y":14,"series":"y","x":-40},{"y":20,"series":"y","x":-39},{"y":25,"series":"y","x":-38},{"y":31,"series":"y","x":-37},{"y":36,"series":"y","x":-36},{"y":41,"series":"y","x":-35},{"y":47,"series":"y","x":-34},{"y":52,"series":"y","x":-33},{"y":58,"series":"y","x":-32},{"y":63,"series":"y","x":-31},{"y":68,"series":"y","x":-30},{"y":74,"series":"y","x":-29},{"y":79,"series":"y","x":-28},{"y":85,"series":"y","x":-27},{"y":90,"series":"y","x":-26},{"y":95,"series":"y","x":-25},{"y":101,"series":"y","x":-24},{"y":106,"series":"y","x":-23},{"y":112,"series":"y","x":-22},{"y":117,"series":"y","x":-21},{"y":122,"series":"y","x":-20},{"y":128,"series":"y","x":-19},{"y":133,"series":"y","x":-18},{"y":139,"series":"y","x":-17},{"y":144,"series":"y","x":-16},{"y":149,"series":"y","x":-15},{"y":155,"series":"y","x":-14},{"y":160,"series":"y","x":-13},{"y":166,"series":"y","x":-12},{"y":171,"series":"y","x":-11},{"y":176,"series":"y","x":-10},{"y":182,"series":"y","x":-9},{"y":187,"series":"y","x":-8},{"y":193,"series":"y","x":-7},{"y":198,"series":"y","x":-6},{"y":203,"series":"y","x":-5},{"y":209,"series":"y","x":-4},{"y":214,"series":"y","x":-3},{"y":220,"series":"y","x":-2},{"y":225,"series":"y","x":-1},{"y":230,"series":"y","x":0},{"y":236,"series":"y","x":1},{"y":241,"series":"y","x":2},{"y":247,"series":"y","x":3},{"y":252,"series":"y","x":4},{"y":255,"series":"y","x":5},{"y":255,"series":"y","x":6},{"y":255,"series":"y","x":7},{"y":255,"series":"y","x":8},{"y":255,"series":"y","x":9},{"y":255,"series":"y","x":10},{"y":255,"series":"y","x":11},{"y":255,"series":"y","x":12},{"y":255,"series":"y","x":13},{"y":255,"series":"y","x":14},{"y":255,"series":"y","x":15},{"y":255,"series":"y","x":16},{"y":255,"series":"y","x":17},{"y":255,"series":"y","x":18},{"y":255,"series":"y","x":19},{"y":255,"series":"y","x":20},{"y":255,"series":"y","x":21},{"y":255,"series":"y","x":22},{"y":255,"series":"y","x":23},{"y":255,"series":"y","x":24},{"y":255,"series":"y","x":25},{"y":255,"series":"y","x":26},{"y":255,"series":"y","x":27},{"y":255,"series":"y","x":28},{"y":255,"series":"y","x":29},{"y":255,"series":"y","x":30},{"y":255,"series":"y","x":31},{"y":255,"series":"y","x":32},{"y":255,"series":"y","x":33},{"y":255,"series":"y","x":34},{"y":255,"series":"y","x":35},{"y":255,"series":"y","x":36},{"y":255,"series":"y","x":37},{"y":255,"series":"y","x":38},{"y":255,"series":"y","x":39},{"y":255,"series":"y","x":40},{"y":255,"series":"y","x":41},{"y":248,"series":"y","x":42},{"y":234,"series":"y","x":43},{"y":220,"series":"y","x":44},{"y":206,"series":"y","x":45},{"y":192,"series":"y","x":46},{"y":179,"series":"y","x":47},{"y":165,"series":"y","x":48},{"y":151,"series":"y","x":49},{"y":137,"series":"y","x":50},{"y":124,"series":"y","x":51},{"y":110,"series":"y","x":52},{"y":96,"series":"y","x":53},{"y":82,"series":"y","x":54},{"y":68,"series":"y","x":55},{"y":55,"series":"y","x":56},{"y":41,"series":"y","x":57},{"y":27,"series":"y","x":58},{"y":13,"series":"y","x":59}]}],"width":600}</graph>
<graph>{"legends":[],"scales":[{"type":"linear","name":"x","zero":false,"domain":{"data":"chart","field":"x"},"range":"width","nice":true},{"type":"linear","name":"y","domain":{"data":"chart","field":"y"},"zero":false,"range":"height","nice":true},{"domain":{"data":"chart","field":"series"},"type":"ordinal","name":"color","range":["green"]}],"version":2,"marks":[{"type":"line","properties":{"hover":{"stroke":{"value":"red"}},"update":{"stroke":{"scale":"color","field":"series"}},"enter":{"y":{"scale":"y","field":"y"},"x":{"scale":"x","field":"x"},"stroke":{"scale":"color","field":"series"},"strokeWidth":{"value":2.5}}},"from":{"data":"chart"}}],"height":180,"axes":[{"type":"x","title":"Celsius","scale":"x","format":"d","properties":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"grid":false},{"type":"y","title":"Green","scale":"y","format":"d","properties":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"grid":false}],"data":[{"format":{"parse":{"y":"integer","x":"integer"},"type":"json"},"name":"chart","values":[{"y":0,"series":"y","x":-90},{"y":0,"series":"y","x":-89},{"y":0,"series":"y","x":-88},{"y":0,"series":"y","x":-87},{"y":0,"series":"y","x":-86},{"y":0,"series":"y","x":-85},{"y":0,"series":"y","x":-84},{"y":0,"series":"y","x":-83},{"y":0,"series":"y","x":-82},{"y":0,"series":"y","x":-81},{"y":0,"series":"y","x":-80},{"y":0,"series":"y","x":-79},{"y":0,"series":"y","x":-78},{"y":0,"series":"y","x":-77},{"y":0,"series":"y","x":-76},{"y":0,"series":"y","x":-75},{"y":0,"series":"y","x":-74},{"y":0,"series":"y","x":-73},{"y":0,"series":"y","x":-72},{"y":0,"series":"y","x":-71},{"y":0,"series":"y","x":-70},{"y":0,"series":"y","x":-69},{"y":0,"series":"y","x":-68},{"y":0,"series":"y","x":-67},{"y":0,"series":"y","x":-66},{"y":0,"series":"y","x":-65},{"y":0,"series":"y","x":-64},{"y":0,"series":"y","x":-63},{"y":0,"series":"y","x":-62},{"y":0,"series":"y","x":-61},{"y":0,"series":"y","x":-60},{"y":0,"series":"y","x":-59},{"y":0,"series":"y","x":-58},{"y":0,"series":"y","x":-57},{"y":0,"series":"y","x":-56},{"y":0,"series":"y","x":-55},{"y":0,"series":"y","x":-54},{"y":0,"series":"y","x":-53},{"y":0,"series":"y","x":-52},{"y":0,"series":"y","x":-51},{"y":0,"series":"y","x":-50},{"y":0,"series":"y","x":-49},{"y":0,"series":"y","x":-48},{"y":0,"series":"y","x":-47},{"y":0,"series":"y","x":-46},{"y":0,"series":"y","x":-45},{"y":0,"series":"y","x":-44},{"y":0,"series":"y","x":-43},{"y":4,"series":"y","x":-42},{"y":9,"series":"y","x":-41},{"y":14,"series":"y","x":-40},{"y":20,"series":"y","x":-39},{"y":25,"series":"y","x":-38},{"y":31,"series":"y","x":-37},{"y":36,"series":"y","x":-36},{"y":41,"series":"y","x":-35},{"y":47,"series":"y","x":-34},{"y":52,"series":"y","x":-33},{"y":58,"series":"y","x":-32},{"y":63,"series":"y","x":-31},{"y":68,"series":"y","x":-30},{"y":74,"series":"y","x":-29},{"y":79,"series":"y","x":-28},{"y":85,"series":"y","x":-27},{"y":90,"series":"y","x":-26},{"y":95,"series":"y","x":-25},{"y":101,"series":"y","x":-24},{"y":106,"series":"y","x":-23},{"y":112,"series":"y","x":-22},{"y":117,"series":"y","x":-21},{"y":122,"series":"y","x":-20},{"y":128,"series":"y","x":-19},{"y":133,"series":"y","x":-18},{"y":139,"series":"y","x":-17},{"y":144,"series":"y","x":-16},{"y":149,"series":"y","x":-15},{"y":155,"series":"y","x":-14},{"y":160,"series":"y","x":-13},{"y":166,"series":"y","x":-12},{"y":171,"series":"y","x":-11},{"y":176,"series":"y","x":-10},{"y":182,"series":"y","x":-9},{"y":187,"series":"y","x":-8},{"y":193,"series":"y","x":-7},{"y":198,"series":"y","x":-6},{"y":203,"series":"y","x":-5},{"y":209,"series":"y","x":-4},{"y":214,"series":"y","x":-3},{"y":220,"series":"y","x":-2},{"y":225,"series":"y","x":-1},{"y":230,"series":"y","x":0},{"y":236,"series":"y","x":1},{"y":241,"series":"y","x":2},{"y":247,"series":"y","x":3},{"y":252,"series":"y","x":4},{"y":251,"series":"y","x":5},{"y":244,"series":"y","x":6},{"y":237,"series":"y","x":7},{"y":230,"series":"y","x":8},{"y":223,"series":"y","x":9},{"y":217,"series":"y","x":10},{"y":210,"series":"y","x":11},{"y":203,"series":"y","x":12},{"y":196,"series":"y","x":13},{"y":189,"series":"y","x":14},{"y":182,"series":"y","x":15},{"y":175,"series":"y","x":16},{"y":168,"series":"y","x":17},{"y":161,"series":"y","x":18},{"y":155,"series":"y","x":19},{"y":148,"series":"y","x":20},{"y":141,"series":"y","x":21},{"y":134,"series":"y","x":22},{"y":127,"series":"y","x":23},{"y":120,"series":"y","x":24},{"y":113,"series":"y","x":25},{"y":106,"series":"y","x":26},{"y":99,"series":"y","x":27},{"y":93,"series":"y","x":28},{"y":86,"series":"y","x":29},{"y":79,"series":"y","x":30},{"y":72,"series":"y","x":31},{"y":65,"series":"y","x":32},{"y":58,"series":"y","x":33},{"y":51,"series":"y","x":34},{"y":44,"series":"y","x":35},{"y":37,"series":"y","x":36},{"y":31,"series":"y","x":37},{"y":24,"series":"y","x":38},{"y":17,"series":"y","x":39},{"y":10,"series":"y","x":40},{"y":3,"series":"y","x":41},{"y":0,"series":"y","x":42},{"y":0,"series":"y","x":43},{"y":0,"series":"y","x":44},{"y":0,"series":"y","x":45},{"y":0,"series":"y","x":46},{"y":0,"series":"y","x":47},{"y":0,"series":"y","x":48},{"y":0,"series":"y","x":49},{"y":0,"series":"y","x":50},{"y":0,"series":"y","x":51},{"y":0,"series":"y","x":52},{"y":0,"series":"y","x":53},{"y":0,"series":"y","x":54},{"y":0,"series":"y","x":55},{"y":0,"series":"y","x":56},{"y":0,"series":"y","x":57},{"y":0,"series":"y","x":58},{"y":0,"series":"y","x":59}]}],"width":600}</graph>
<graph>{"legends":[],"scales":[{"type":"linear","name":"x","zero":false,"domain":{"data":"chart","field":"x"},"range":"width","nice":true},{"type":"linear","name":"y","domain":{"data":"chart","field":"y"},"zero":false,"range":"height","nice":true},{"domain":{"data":"chart","field":"series"},"type":"ordinal","name":"color","range":["blue"]}],"version":2,"marks":[{"type":"line","properties":{"hover":{"stroke":{"value":"red"}},"update":{"stroke":{"scale":"color","field":"series"}},"enter":{"y":{"scale":"y","field":"y"},"x":{"scale":"x","field":"x"},"stroke":{"scale":"color","field":"series"},"strokeWidth":{"value":2.5}}},"from":{"data":"chart"}}],"height":180,"axes":[{"type":"x","title":"Celsius","scale":"x","format":"d","properties":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"grid":false},{"type":"y","title":"Blue","scale":"y","format":"d","properties":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"grid":false}],"data":[{"format":{"parse":{"y":"integer","x":"integer"},"type":"json"},"name":"chart","values":[{"y":0,"series":"y","x":-90},{"y":5,"series":"y","x":-89},{"y":10,"series":"y","x":-88},{"y":16,"series":"y","x":-87},{"y":21,"series":"y","x":-86},{"y":27,"series":"y","x":-85},{"y":32,"series":"y","x":-84},{"y":37,"series":"y","x":-83},{"y":43,"series":"y","x":-82},{"y":48,"series":"y","x":-81},{"y":54,"series":"y","x":-80},{"y":59,"series":"y","x":-79},{"y":64,"series":"y","x":-78},{"y":70,"series":"y","x":-77},{"y":75,"series":"y","x":-76},{"y":81,"series":"y","x":-75},{"y":86,"series":"y","x":-74},{"y":91,"series":"y","x":-73},{"y":97,"series":"y","x":-72},{"y":102,"series":"y","x":-71},{"y":108,"series":"y","x":-70},{"y":113,"series":"y","x":-69},{"y":118,"series":"y","x":-68},{"y":124,"series":"y","x":-67},{"y":129,"series":"y","x":-66},{"y":135,"series":"y","x":-65},{"y":140,"series":"y","x":-64},{"y":145,"series":"y","x":-63},{"y":151,"series":"y","x":-62},{"y":156,"series":"y","x":-61},{"y":162,"series":"y","x":-60},{"y":167,"series":"y","x":-59},{"y":172,"series":"y","x":-58},{"y":178,"series":"y","x":-57},{"y":183,"series":"y","x":-56},{"y":189,"series":"y","x":-55},{"y":194,"series":"y","x":-54},{"y":199,"series":"y","x":-53},{"y":205,"series":"y","x":-52},{"y":210,"series":"y","x":-51},{"y":216,"series":"y","x":-50},{"y":221,"series":"y","x":-49},{"y":226,"series":"y","x":-48},{"y":232,"series":"y","x":-47},{"y":237,"series":"y","x":-46},{"y":243,"series":"y","x":-45},{"y":248,"series":"y","x":-44},{"y":253,"series":"y","x":-43},{"y":255,"series":"y","x":-42},{"y":255,"series":"y","x":-41},{"y":255,"series":"y","x":-40},{"y":255,"series":"y","x":-39},{"y":255,"series":"y","x":-38},{"y":255,"series":"y","x":-37},{"y":255,"series":"y","x":-36},{"y":255,"series":"y","x":-35},{"y":255,"series":"y","x":-34},{"y":255,"series":"y","x":-33},{"y":255,"series":"y","x":-32},{"y":255,"series":"y","x":-31},{"y":255,"series":"y","x":-30},{"y":255,"series":"y","x":-29},{"y":255,"series":"y","x":-28},{"y":255,"series":"y","x":-27},{"y":255,"series":"y","x":-26},{"y":255,"series":"y","x":-25},{"y":255,"series":"y","x":-24},{"y":255,"series":"y","x":-23},{"y":255,"series":"y","x":-22},{"y":255,"series":"y","x":-21},{"y":255,"series":"y","x":-20},{"y":255,"series":"y","x":-19},{"y":255,"series":"y","x":-18},{"y":255,"series":"y","x":-17},{"y":255,"series":"y","x":-16},{"y":255,"series":"y","x":-15},{"y":255,"series":"y","x":-14},{"y":255,"series":"y","x":-13},{"y":255,"series":"y","x":-12},{"y":255,"series":"y","x":-11},{"y":255,"series":"y","x":-10},{"y":255,"series":"y","x":-9},{"y":255,"series":"y","x":-8},{"y":255,"series":"y","x":-7},{"y":255,"series":"y","x":-6},{"y":255,"series":"y","x":-5},{"y":255,"series":"y","x":-4},{"y":255,"series":"y","x":-3},{"y":255,"series":"y","x":-2},{"y":255,"series":"y","x":-1},{"y":255,"series":"y","x":0},{"y":255,"series":"y","x":1},{"y":255,"series":"y","x":2},{"y":255,"series":"y","x":3},{"y":255,"series":"y","x":4},{"y":248,"series":"y","x":5},{"y":234,"series":"y","x":6},{"y":220,"series":"y","x":7},{"y":206,"series":"y","x":8},{"y":192,"series":"y","x":9},{"y":179,"series":"y","x":10},{"y":165,"series":"y","x":11},{"y":151,"series":"y","x":12},{"y":137,"series":"y","x":13},{"y":124,"series":"y","x":14},{"y":110,"series":"y","x":15},{"y":96,"series":"y","x":16},{"y":82,"series":"y","x":17},{"y":68,"series":"y","x":18},{"y":55,"series":"y","x":19},{"y":41,"series":"y","x":20},{"y":27,"series":"y","x":21},{"y":13,"series":"y","x":22},{"y":0,"series":"y","x":23},{"y":0,"series":"y","x":24},{"y":0,"series":"y","x":25},{"y":0,"series":"y","x":26},{"y":0,"series":"y","x":27},{"y":0,"series":"y","x":28},{"y":0,"series":"y","x":29},{"y":0,"series":"y","x":30},{"y":0,"series":"y","x":31},{"y":0,"series":"y","x":32},{"y":0,"series":"y","x":33},{"y":0,"series":"y","x":34},{"y":0,"series":"y","x":35},{"y":0,"series":"y","x":36},{"y":0,"series":"y","x":37},{"y":0,"series":"y","x":38},{"y":0,"series":"y","x":39},{"y":0,"series":"y","x":40},{"y":0,"series":"y","x":41},{"y":0,"series":"y","x":42},{"y":0,"series":"y","x":43},{"y":0,"series":"y","x":44},{"y":0,"series":"y","x":45},{"y":0,"series":"y","x":46},{"y":0,"series":"y","x":47},{"y":0,"series":"y","x":48},{"y":0,"series":"y","x":49},{"y":0,"series":"y","x":50},{"y":0,"series":"y","x":51},{"y":0,"series":"y","x":52},{"y":0,"series":"y","x":53},{"y":0,"series":"y","x":54},{"y":0,"series":"y","x":55},{"y":0,"series":"y","x":56},{"y":0,"series":"y","x":57},{"y":0,"series":"y","x":58},{"y":0,"series":"y","x":59}]}],"width":600}</graph>
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Template:WRCC
- ↑ Ross, Douglas (1971–2000). "Daily Normals for Alexandria, Minnesota". NCDC. Retrieved 2007-06-07.
- ↑ Ross, Douglas (1971–2000). "Daily Normals for Brainerd, Minnesota". NCDC. Retrieved 2007-12-27.
- ↑ Ross, Douglas (1971–2000). "Daily Normals for Duluth, Minnesota". NCDC. Retrieved 2007-06-07.
- ↑ Ross, Douglas (1971–2000). "Daily Normals for Grand Marais, Minnesota". NCDC. Retrieved 2007-12-27.
- ↑ Ross, Douglas (1971–2000). "Daily Normals for International Falls, Minnesota". NCDC. Retrieved 2007-06-07.
- ↑ Ross, Douglas (1971–2000). "Daily Normals for Redwood Falls, Minnesota". NCDC. Retrieved 2007-06-07.
- ↑ Ross, Douglas (1971–2000). "Daily Normals for Thief River Falls, Minnesota". NCDC. Retrieved 2007-06-07.
- ↑ Ross, Douglas (1971–2000). "Daily Normals for the Twin Cities". NCDC. Retrieved 2007-06-07.
- ↑ Ross, Douglas (1971–2000). "Daily Normals for Winona, Minnesota". NCDC. Retrieved 2007-06-07.
- ↑ Ross, Douglas (1971–2000). "Daily Normals for Worthington, Minnesota". NCDC. Retrieved 2007-06-07.
export = {}
degree = "°" -- used by add_unitNames()
minus = "−" -- used by makeRow() and makeTable()
thinSpace = mw.ustring.char(0x2009) -- used by makeCell()
-- Error message handling
message = ""
local function addMessage(new_message)
if show then
if checkForString(message) then
message = message .. " " .. new_message
else
message = "Notices: " .. new_message
end
end
end
-- Input and output parameters
local function getFormat (frame)
local inputParameter = frame.args.input
local outputParameter = frame.args.output
if inputParameter == nil then
error("Please provide the number of values and a unit in the input parameter")
else
length = tonumber(string.match(inputParameter, "(%d+)")) -- Find digits in the input parameter.
inputUnit = string.match(inputParameter, "([CF])") -- C or F
if string.find(inputParameter, "[^CF%d%s]") then
addMessage("There are extraneous characters in the <span style=\"background-color: #EEE; font-family: monospace;\">output</span> parameter.")
end
end
if inputUnit == "C" then
outputUnit = "F"
elseif inputUnit == "F" then
outputUnit = "C"
else
error ("Please provide an input unit in the input parameter: F for Fahrenheit or C for Celsius", 0)
end
if length == nil then
error ("getFormat has not found a length value in the input parameter")
end
if outputParameter == nil then
addMessage("No output format has been provided in the <span style=\"background-color: #EEE; font-family: monospace;\">output</span> parameter.")
else
cellFormat = {}
local n = 1
for unit in outputParameter:gmatch("[CF]") do
cellFormat[n] = unit
n = n + 1
if n > 2 then
break
end
end
local function setFormat(key, formatVariable, formatValue1, formatValue2)
if string.find(outputParameter, key) then
cellFormat[formatVariable] = formatValue1
else
cellFormat[formatVariable] = formatValue2
end
end
if cellFormat[1] then
cellFormat.first = cellFormat[1]
else
error("C or F not found in output parameter")
end
if cellFormat[2] == nil then
cellFormat["convertUnits"] = "no"
else
if cellFormat[2] == cellFormat[1] then
error("There should not be two of the same unit name in the output parameter.")
else
cellFormat["convertUnits"] = "yes"
end
end
setFormat("unit", "unitNames", "yes", "no")
setFormat("no ?color", "color", "no", "yes")
setFormat("sort", "sortable", "yes", "no")
setFormat("full ?size", "smallFont", "no", "yes")
setFormat("no ?brackets", "brackets", "no", "yes")
setFormat("round", "decimals", "0", "")
if string.find(outputParameter, "line break") then
cellFormat["lineBreak"] = "yes"
elseif string.find(outputParameter, "one line") then
cellFormat["lineBreak"] = "no"
else
cellFormat["lineBreak"] = "auto"
end
if string.find(outputParameter, "one line") and string.find(outputParameter, "line break") then
error("Place either \"one line\" or \"line break\" in the output parameter, not both")
end
end
if frame.args.palette == nil then
palette = "cool2avg"
else
palette = frame.args.palette
end
if frame.args.messages == "show" then
show = true
else
show = false
end
return length, inputUnit, outputUnit
end
-- Number and string-handling functions
local function checkForNumber(value)
return type(tonumber(value)) == "number"
end
function checkForString(string)
string = tostring(string)
return string ~= "" and string ~= nil
end
local function round(value, decimals)
value = tonumber(value)
if type(value) == "number" then
local string = string.format("%." .. decimals .. "f", value)
return string
elseif value == nil then
value = "nil"
addMessage("Format was asked to operate on " .. value .. ", which cannot be converted to a number.", 2)
return ""
end
end
local function convert(value, decimals, unit) -- Unit is the unit being converted from. It defaults to inputUnit.
if not unit then
unit = inputUnit
end
if checkForNumber(value) then
local value = tonumber(value)
if unit == "C" then
addMessage(value .. " " .. degree .. unit .. " was converted.")
return round(value * 9/5 + 32, decimals)
elseif unit == "F" then
addMessage(value .. " " .. degree .. unit .. " was converted.")
return round((value - 32) * 5/9, decimals)
else
error("Input unit not recognized", 2)
end
else
return "" -- Setting result to empty string if value is not a number avoids concatenation errors.
end
end
-- Input parsing
function makeArray(parameter, array, frame)
local array = {}
local n = 1
for number in parameter:gmatch("%-?%d+%.?%d?") do
local number = number
if n == 1 then
local decimals = number:match("%.(%d+)")
if decimals == nil then
precision = "0"
else
precision = #decimals
end
end
table.insert(array, n, number)
n = n + 1
if n > length then
break
end
end
if not array[length] then
addMessage("There are not " .. length .. " values in the " .. parameter .. " parameter.")
end
return array, precision
end
function makeArrays(frame)
getFormat(frame)
local parameter_a = frame.args.a
local parameter_b = frame.args.b
local parameter_c = frame.args.c
if parameter_a then
a = makeArray(parameter_a, a, frame)
else
error("Please provide a set of numbers in parameter a")
end
if parameter_b then
b = makeArray(parameter_b, b, frame)
else
addMessage("There is no content in parameter <span style=\"background-color: #EEE; font-family: monospace;\">b</span>.")
end
if parameter_c then
c = makeArray(parameter_c, c, frame)
else
addMessage("There is no content in parameter <span style=\"background-color: #EEE; font-family: monospace;\">c</span>.")
end
return a, b, c
end
-- Color generation
palettes = {
-- The first three arrays in each palette defines background color using a table of four numbers,
-- say { 11, 22, 33, 44 } (values in °C).
-- That means the color is 0 below 11 and above 44, and is 255 from 22 to 33.
-- The color rises from 0 to 255 between 11 and 22, and falls between 33 and 44.
cool = {
{ -42.75, 4.47, 41.5, 60 },
{ -42.75, 4.47, 4.5, 41.5 },
{ -90 , -42.78, 4.5, 23 },
white = { -23.3, 37.8 },
},
cool2 = {
{ -42.75, 4.5 , 41.5, 56 },
{ -42.75, 4.5 , 4.5, 41.5 },
{ -90 , -42.78, 4.5, 23 },
white = { -23.3, 35 },
},
cool2avg = {
{ -38, 4.5, 25 , 45 },
{ -38, 4.5, 4.5, 30 },
{ -70, -38 , 4.5, 23 },
white = { -23.3, 25 },
},
}
local function temperature_color(palette, value, outRGB)
--[[ Return style for a table cell based on the given value which
should be a temperature in °C. ]]
local backgroundColor, textColor
value = tonumber(value)
if value == nil then
backgroundColor, textColor = 'FFF', '000'
addMessage("Value supplied to <span style=\"background-color: #EEE; font-family: monospace;\">temperature_color</span> is not recognized.")
else
local min, max = unpack(palette.white or { -23, 35 })
if value < min or value >= max then
textColor = 'FFF'
else
textColor = '' -- This assumes that black text color is the default for most readers.
end
local backgroundRGB = outRGB or {}
for i, v in ipairs(palette) do
local a, b, c, d = unpack(v)
if value <= a then
backgroundRGB[i] = 0
elseif value < b then
backgroundRGB[i] = (value - a) * 255 / (b - a)
elseif value <= c then
backgroundRGB[i] = 255
elseif value < d then
backgroundRGB[i] = 255 - ( (value - c) * 255 / (d - c) )
else
backgroundRGB[i] = 0
end
end
backgroundColor = string.format('%02X%02X%02X', backgroundRGB[1], backgroundRGB[2], backgroundRGB[3])
end
if textColor == "" then
return backgroundColor
else
return backgroundColor, textColor
end
end
local function colorCSS(backgroundColor, textColor)
if backgroundColor and textColor then
return 'background: #' .. backgroundColor .. '; color: #' .. textColor .. ';'
elseif backgroundColor then
return 'background: #' .. backgroundColor .. ';'
else
return ''
end
end
local function temperatureColorCSS(palette, value, outRGB)
return colorCSS(temperature_color(palette, value, outRGB))
end
function temperatureCSS(value, unit, palette)
local palette = palettes[palette] or palettes.cool
local value = tonumber(value)
if value == nil then
error("The function <span style=\"background-color: #EEE; font-family: monospace;\">temperatureCSS</span> is receiving a nil value")
else
if unit == 'C' then
return colorCSS(temperature_color(palette, value))
elseif unit == 'F' then
return colorCSS(temperature_color(palette, convert(value, decimals, 'F')))
else
unit_error(unit or "nil")
end
end
end
local function styleAttribute(palette, value, outRGB)
local font_size = "font-size: 85%;"
local color = temperatureColorCSS(palette, value, outRGB)
return 'style=\"' .. color .. ' ' .. font_size .. '\"'
end
style_attribute = styleAttribute
function export.temperatureStyle(frame) -- used by Template:Average temperature table/color
local palette = palettes[frame.args.palette] or palettes.cool
local unit = frame.args.unit or 'C'
local value = tonumber(frame.args[1])
if unit == 'C' then
return styleAttribute(palette, value)
elseif unit == 'F' then
return styleAttribute(palette, convert(value, 1, 'F'))
else
unit_error(unit)
end
end
export.temperature_style = export.temperatureStyle
--[[ ==== Cell, row, table generation ==== ]]
local output_formats = {
high_low_average_F =
{ first = "F",
convertUnits = "yes",
unitNames = "no",
color = "yes",
smallFont = "yes",
sortable = "yes",
decimals = "0",
brackets = "yes",
lineBreak = "auto", },
high_low_average_C =
{ first = "C",
convertUnits = "yes",
unitNames = "no",
color = "yes",
smallFont = "yes",
sortable = "yes",
decimals = "0",
brackets = "yes",
lineBreak = "auto", },
high_low_F =
{ first = "F",
convertUnits = "yes",
unitNames = "no",
color = "no",
smallFont = "yes",
sortable = "no",
decimals = "",
brackets = "yes",
lineBreak = "auto", },
high_low_C =
{ first = "C",
convertUnits = "yes",
unitNames = "no",
color = "no",
smallFont = "yes",
sortable = "no",
decimals = "0",
brackets = "yes",
lineBreak = "auto", },
average_F =
{ first = "F",
convertUnits = "yes",
unitNames = "no",
color = "yes",
smallFont = "yes",
sortable = "no",
decimals = "0",
brackets = "yes",
lineBreak = "auto", },
average_C =
{ first = "C",
convertUnits = "yes",
unitNames = "no",
color = "yes",
smallFont = "yes",
sortable = "no",
decimals = "0",
brackets = "yes",
lineBreak = "auto", },
}
local function add_unitNames(value, unit)
if not unit then unit = inputUnit end
-- Don't add a unit name to an empty string
value = output_format.unitNames == "yes" and checkForString(value) and value .. " " .. degree .. unit or value
return value
end
local function if_yes(parameter, realization1, realization2)
if realization1 then
if realization2 then
if parameter == "yes" then
parameter = { realization1, realization2 }
else
parameter = { "", "" }
end
else
if parameter == "yes" then
parameter = realization1
else
parameter = ""
end
end
else
parameter = ""
addMessage("<span style=\"background-color: #EEE; font-family: monospace;\">if_yes</span> needs at least one realization")
end
return parameter
end
function makeCell(output_format, a, b, c)
local cell, cell_content = "", ""
local colorCSS, other_CSS, title_attribute, sortkey, attribute_separator, converted_units_separator = "", "", "", "", "", "", ""
local styleAttribute, high_low_separator, brackets, values, converted_units = {"", ""}, {"", ""}, {"", ""}, {"", ""}, {"", ""}
-- Distinguish styleAttribute variable from styleAttribute function above.
decimals = ( checkForNumber(output_format.decimals) and output_format.decimals ) or precision
--[[ Precision is the number of decimals in the first number of the last array.
This may be a problem for data from Weatherbase,
which seems to inappropriately remove .0 from numbers that have it. ]]
if checkForNumber(b) and checkForNumber(a) then
values, high_low_separator = { round(a, decimals), round(b, decimals) }, { thinSpace .. "/" .. thinSpace, if_yes(output_format.convertUnits, thinSpace .. "/" .. thinSpace) }
elseif checkForNumber(a) then
values = { round(a, decimals), "" }
elseif checkForNumber(c) then
values = { round(c, decimals), "" }
end
if output_format.first == inputUnit then
if output_format.convertUnits == "yes" then
converted_units = { add_unitNames(convert(values[1], decimals), outputUnit), add_unitNames(convert(values[2], decimals), outputUnit) }
end
values = { add_unitNames(values[1]), add_unitNames(values[2]) }
elseif output_format.first == "C" or output_format.first == "F" then
if output_format.convertUnits == "yes" then
converted_units = { add_unitNames(values[1]), add_unitNames(values[2]) }
end
values = { add_unitNames(convert(values[1], decimals), outputUnit), add_unitNames(convert(values[2], decimals), outputUnit) }
else
if output_format.first == nil then
output_format.first = "nil"
end
addMessage("<span style=\"background-color: #EEE; font-family: monospace;\">" .. output_format.first .. "</span>, the value for <span style=\"background-color: #EEE; font-family: monospace;\">first</span> in <span style=\"background-color: #EEE; font-family: monospace;\">output_format</span> is not recognized.")
end
--[[
Regarding line breaks:
If there are two values, there will be at least three characters: 9/1.
If there is one decimal, numbers will be three to five characters long
and there will be 3 to 10 characters total even without unit conversion:
1.1, 116.5/88.0.
If there are units, that adds three characters per number: 25 °C/20 °C.
In each of these cases, a line break is needed so that table cells are not too wide;
even more so when more than one of these things are true.
]]
if output_format.convertUnits == "yes" then
brackets = if_yes(output_format.brackets, "(", ")" )
if output_format.lineBreak == "auto" then
if checkForString(values[2]) or decimals ~= "0" or output_format.show_units == "yes" then
converted_units_separator = "<br>"
else
converted_units_separator = " "
end
elseif output_format.lineBreak == "yes" then
converted_units_separator = "<br>"
elseif output_format.lineBreak == "no" then
converted_units_separator = " "
else
error("Value for lineBreak not recognized")
end
end
cell_content = values[1] .. high_low_separator[1] .. values[2] .. converted_units_separator .. brackets[1] .. converted_units[1] .. high_low_separator[2] .. converted_units[2] .. brackets[2]
if checkForNumber(c) then
colorCSS = if_yes(output_format.color, temperatureCSS(c, inputUnit, palette))
if checkForNumber(b) and checkForNumber(a) then
local attribute_value
if output_format.first == inputUnit then
attribute_value = c
else
attribute_value = convert(c, decimals)
end
sortkey = if_yes(output_format.sortable, " data-sort-value=\"" .. attribute_value .. "\"")
title_attribute = " title=\"Average temperature: " .. attribute_value .. " " .. degree .. output_format.first .. "\""
end
elseif checkForNumber(b) then
colorCSS = ""
elseif checkForNumber(a) then
colorCSS = if_yes(output_format.color, temperatureCSS(a, inputUnit, palette))
else
addMessage("Neither a nor b nor c are strings.")
end
other_CSS = if_yes(output_format.smallFont, "font-size: 85%;")
if checkForString(colorCSS) or checkForString(other_CSS) then
styleAttribute = { "style=\"", "\"" }
end
if checkForString(other_CSS) or checkForString(colorCSS) or checkForString(title_attribute) or checkForString(sortkey) then
attribute_separator = " | "
end
cell = "\n| " .. styleAttribute[1] .. colorCSS .. other_CSS .. styleAttribute[2] .. title_attribute .. sortkey .. attribute_separator .. cell_content
return cell
end
function export.makeRow(frame)
makeArrays(frame)
local output = ""
if frame.args[1] then
output = "\n|-"
output = output .. "\n! " .. frame.args[1]
if frame.args[2] then
output = output .. " !! " .. frame.args[2]
end
end
if cellFormat then
output_format = cellFormat
end
if a and b and c then
for i = 1, length do
if not output_format then
output_format = output_formats.high_low_average_F
end
output = output .. makeCell(output_format, a[i], b[i], c[i])
end
elseif a and b then
for i = 1, length do
if not output_format then
output_format = output_formats.high_low_F
end
output = output .. makeCell(output_format, a[i], b[i])
end
elseif a then
for i = 1, length do
if not output_format then
output_format = output_formats.average_F
end
output = output .. makeCell(output_format, a[i])
end
end
output = mw.ustring.gsub(output, "([%p%s])-(%d)", "%1" .. minus .. "%2")
return output
end
function export.makeTable(frame)
makeArrays(frame)
local output = "{| class=\"wikitable center nowrap\""
if cellFormat then
output_format = cellFormat
end
if a and b and c then
for i = 1, length do
if not output_format then
output_format = output_formats.high_low_average_F
end
output = output .. makeCell(output_format, a[i], b[i], c[i])
end
elseif a and b then
for i = 1, length do
if not output_format then
output_format = output_formats.high_low_F
end
output = output .. makeCell(output_format, a[i], b[i])
end
elseif a then
for i = 1, length do
if not output_format then
output_format = output_formats.average_F
end
output = output .. makeCell(output_format, a[i])
end
end
output = mw.ustring.gsub(output, "([%p%s])-(%d)", "%1" .. minus .. "%2")
--[[ Replaces hyphens that have a punctuation or space character before them and a number after them,
making sure that hyphens in "data-sort-type" are not replaced with minuses.
If Lua had (?<=), a capture would not be necessary. ]]
output = output .. "\n|}"
if show then
output = output .. "\n\n<span style=\"color: red; font-size: 80%; line-height: 100%;\">" .. message .. "</span>"
end
return output
end
local chart = [[
{{Graph:Chart
|width=600
|height=180
|xAxisTitle=Celsius
|yAxisTitle=__COLOR
|type=line
|x=__XVALUES
|y=__YVALUES
|colors=__COLOR
}}
]]
function export.show(frame)
-- For testing, return wikitext to show graphs of how the red/green/blue colors
-- vary with temperature, and a table of the resulting colors.
local function collection()
-- Return a table to hold items.
return {
n = 0,
add = function (self, item)
self.n = self.n + 1
self[self.n] = item
end,
join = function (self, sep)
return table.concat(self, sep)
end,
}
end
local function make_chart(result, color, xvalues, yvalues)
result:add('\n')
result:add(frame:preprocess((chart:gsub('__[A-Z]+', {
__COLOR = color,
__XVALUES = xvalues:join(','),
__YVALUES = yvalues:join(','),
}))))
end
local function with_minus(value)
if value < 0 then
return minus .. tostring(-value)
end
return tostring(value)
end
local args = frame.args
local first = args[1] or -90
local last = args[2] or 59
local palette = palettes[args.palette] or palettes.cool
local xvals, reds, greens, blues = collection(), collection(), collection(), collection()
local wikitext = collection()
wikitext:add('{| class="wikitable"\n|-\n')
local columns = 0
for celsius = first, last do
local backgroundRGB = {}
local style = styleAttribute(palette, celsius, backgroundRGB)
local R = math.floor(backgroundRGB[1])
local G = math.floor(backgroundRGB[2])
local B = math.floor(backgroundRGB[3])
xvals:add(celsius)
reds:add(R)
greens:add(G)
blues:add(B)
wikitext:add('| ' .. style .. ' | ' .. with_minus(celsius) .. '\n')
columns = columns + 1
if columns >= 10 then
columns = 0
wikitext:add('|-\n')
end
end
wikitext:add('|}\n')
make_chart(wikitext, 'Red', xvals, reds)
make_chart(wikitext, 'Green', xvals, greens)
make_chart(wikitext, 'Blue', xvals, blues)
return wikitext:join()
end
return export