Difference between revisions of "Module:Weather/sandbox"

From blackwiki
Jump to navigation Jump to search
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 add_unit_names()
+
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 add_message(new_message)
+
local function addMessage(new_message)
 
if show then
 
if show then
if check_for_string(message) then
+
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 get_format (frame)
+
local function getFormat (frame)
local input_parameter = frame.args.input
+
local inputParameter = frame.args.input
local output_parameter = frame.args.output
+
local outputParameter = frame.args.output
 
 
if input_parameter == nil then
+
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(input_parameter, "(%d+)")) -- Find digits in the input parameter.
+
length = tonumber(string.match(inputParameter, "(%d+)")) -- Find digits in the input parameter.
input_unit = string.match(input_parameter, "([CF])") -- C or F
+
inputUnit = string.match(inputParameter, "([CF])") -- C or F
if string.find(input_parameter, "[^CF%d%s]") then
+
if string.find(inputParameter, "[^CF%d%s]") then
add_message("There are extraneous characters in the <span style=\"background-color: #EEE; font-family: monospace;\">output</span> parameter.")
+
addMessage("There are extraneous characters in the <span style=\"background-color: #EEE; font-family: monospace;\">output</span> parameter.")
 
end
 
end
 
end
 
end
 
 
if input_unit == "C" then
+
if inputUnit == "C" then
output_unit = "F"
+
outputUnit = "F"
elseif input_unit == "F" then
+
elseif inputUnit == "F" then
output_unit = "C"
+
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 ("get_format has not found a length value in the input parameter")
+
error ("getFormat has not found a length value in the input parameter")
 
end
 
end
 
 
if output_parameter == nil then
+
if outputParameter == nil then
add_message("No output format has been provided in the <span style=\"background-color: #EEE; font-family: monospace;\">output</span> parameter.")
+
addMessage("No output format has been provided in the <span style=\"background-color: #EEE; font-family: monospace;\">output</span> parameter.")
 
else
 
else
cell_format = {}
+
cellFormat = {}
 
local n = 1
 
local n = 1
for unit in output_parameter:gmatch("[CF]") do
+
for unit in outputParameter:gmatch("[CF]") do
cell_format[n] = unit
+
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 set_format(key, formatVariable, formatValue1, formatValue2)
+
local function setFormat(key, formatVariable, formatValue1, formatValue2)
if string.find(output_parameter, key) then
+
if string.find(outputParameter, key) then
cell_format[formatVariable] = formatValue1
+
cellFormat[formatVariable] = formatValue1
 
else
 
else
cell_format[formatVariable] = formatValue2
+
cellFormat[formatVariable] = formatValue2
 
end
 
end
 
end
 
end
if cell_format[1] then
+
if cellFormat[1] then
cell_format.first = cell_format[1]
+
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 cell_format[2] == nil then
+
if cellFormat[2] == nil then
cell_format["convert_units"] = "no"
+
cellFormat["convertUnits"] = "no"
 
else
 
else
if cell_format[2] == cell_format[1] then
+
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
cell_format["convert_units"] = "yes"
+
cellFormat["convertUnits"] = "yes"
 
end
 
end
 
end
 
end
set_format("unit", "unit_names", "yes", "no")
+
setFormat("unit", "unitNames", "yes", "no")
set_format("no ?color", "color", "no", "yes")
+
setFormat("no ?color", "color", "no", "yes")
set_format("sort", "sortable", "yes", "no")
+
setFormat("sort", "sortable", "yes", "no")
set_format("full ?size", "small_font", "no", "yes")
+
setFormat("full ?size", "smallFont", "no", "yes")
set_format("no ?brackets", "brackets", "no", "yes")
+
setFormat("no ?brackets", "brackets", "no", "yes")
set_format("round", "decimals", "0", "")
+
setFormat("round", "decimals", "0", "")
if string.find(output_parameter, "line break") then
+
if string.find(outputParameter, "line break") then
cell_format["line_break"] = "yes"
+
cellFormat["lineBreak"] = "yes"
elseif string.find(output_parameter, "one line") then
+
elseif string.find(outputParameter, "one line") then
cell_format["line_break"] = "no"
+
cellFormat["lineBreak"] = "no"
 
else
 
else
cell_format["line_break"] = "auto"
+
cellFormat["lineBreak"] = "auto"
 
end
 
end
if string.find(output_parameter, "one line") and string.find(output_parameter, "line break") then
+
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, input_unit, output_unit
+
return length, inputUnit, outputUnit
 
end
 
end
  
 
-- Number and string-handling functions
 
-- Number and string-handling functions
local function check_for_number(value)
+
local function checkForNumber(value)
 
return type(tonumber(value)) == "number"
 
return type(tonumber(value)) == "number"
 
end
 
end
  
function check_for_string(string)
+
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"
add_message("Format was asked to operate on " .. value .. ", which cannot be converted to a number.", 2)
+
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 input_unit.
+
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 = input_unit
+
unit = inputUnit
 
end
 
end
if check_for_number(value) then
+
if checkForNumber(value) then
 
local value = tonumber(value)
 
local value = tonumber(value)
 
if unit == "C" then
 
if unit == "C" then
add_message(value .. " " .. degree .. unit .. " was converted.")
+
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
add_message(value .. " " .. degree .. unit .. " was converted.")
+
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 make_array(parameter, array, frame)
+
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
add_message("There are not " .. length .. " values in the " .. parameter .. " parameter.")
+
addMessage("There are not " .. length .. " values in the " .. parameter .. " parameter.")
 
end
 
end
 
return array, precision
 
return array, precision
 
end
 
end
  
function make_arrays(frame)
+
function makeArrays(frame)
get_format(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 = make_array(parameter_a, a, frame)
+
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 = make_array(parameter_b, b, frame)
+
b = makeArray(parameter_b, b, frame)
 
else
 
else
add_message("There is no content in parameter <span style=\"background-color: #EEE; font-family: monospace;\">b</span>.")
+
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 = make_array(parameter_c, c, frame)
+
c = makeArray(parameter_c, c, frame)
 
else
 
else
add_message("There is no content in parameter <span style=\"background-color: #EEE; font-family: monospace;\">c</span>.")
+
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, out_rgb)
+
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 background_color, text_color
+
local backgroundColor, textColor
 
value = tonumber(value)
 
value = tonumber(value)
 
if value == nil then
 
if value == nil then
background_color, text_color = 'FFF', '000'
+
backgroundColor, textColor = 'FFF', '000'
add_message("Value supplied to <span style=\"background-color: #EEE; font-family: monospace;\">temperature_color</span> is not recognized.")
+
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
text_color = 'FFF'
+
textColor = 'FFF'
 
else
 
else
text_color = '' -- This assumes that black text color is the default for most readers.
+
textColor = '' -- This assumes that black text color is the default for most readers.
 
end
 
end
  
local background_rgb = out_rgb or {}
+
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
background_rgb[i] = 0
+
backgroundRGB[i] = 0
 
elseif value < b then
 
elseif value < b then
background_rgb[i] = (value - a) * 255 / (b - a)
+
backgroundRGB[i] = (value - a) * 255 / (b - a)
 
elseif value <= c then
 
elseif value <= c then
background_rgb[i] = 255
+
backgroundRGB[i] = 255
 
elseif value < d then
 
elseif value < d then
background_rgb[i] = 255 - ( (value - c) * 255 / (d - c) )
+
backgroundRGB[i] = 255 - ( (value - c) * 255 / (d - c) )
 
else
 
else
background_rgb[i] = 0
+
backgroundRGB[i] = 0
 
end
 
end
 
end
 
end
background_color = string.format('%02X%02X%02X', background_rgb[1], background_rgb[2], background_rgb[3])
+
backgroundColor = string.format('%02X%02X%02X', backgroundRGB[1], backgroundRGB[2], backgroundRGB[3])
 
end
 
end
if text_color == "" then
+
if textColor == "" then
return background_color
+
return backgroundColor
 
else
 
else
return background_color, text_color
+
return backgroundColor, textColor
 
end
 
end
 
end
 
end
  
local function color_CSS(background_color, text_color)
+
local function colorCSS(backgroundColor, textColor)
if background_color and text_color then
+
if backgroundColor and textColor then
return 'background: #' .. background_color .. '; color: #' .. text_color .. ';'
+
return 'background: #' .. backgroundColor .. '; color: #' .. textColor .. ';'
elseif background_color then
+
elseif backgroundColor then
return 'background: #' .. background_color .. ';'
+
return 'background: #' .. backgroundColor .. ';'
 
else
 
else
 
return ''
 
return ''
Line 277: Line 277:
 
end
 
end
  
local function temperature_color_CSS(palette, value, out_rgb)
+
local function temperatureColorCSS(palette, value, outRGB)
return color_CSS(temperature_color(palette, value, out_rgb))
+
return colorCSS(temperature_color(palette, value, outRGB))
 
end
 
end
  
function temperature_CSS(value, unit, palette)
+
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;\">temperature_CSS</span> is receiving a nil value")
+
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 color_CSS(temperature_color(palette, value))
+
return colorCSS(temperature_color(palette, value))
 
elseif unit == 'F' then
 
elseif unit == 'F' then
return color_CSS(temperature_color(palette, convert(value, decimals, 'F')))
+
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 style_attribute(palette, value, out_rgb)
+
local function styleAttribute(palette, value, outRGB)
 
local font_size = "font-size: 85%;"
 
local font_size = "font-size: 85%;"
local color = temperature_color_CSS(palette, value, out_rgb)
+
local color = temperatureColorCSS(palette, value, outRGB)
 
return 'style=\"' .. color .. ' ' .. font_size .. '\"'
 
return 'style=\"' .. color .. ' ' .. font_size .. '\"'
 
end
 
end
  
function export.temperature_style(frame) -- used by Template:Average temperature table/color
+
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 style_attribute(palette, value)
+
return styleAttribute(palette, value)
 
elseif unit == 'F' then
 
elseif unit == 'F' then
return style_attribute(palette, convert(value, 1, 'F'))
+
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",
convert_units = "yes",
+
convertUnits = "yes",
unit_names = "no",
+
unitNames = "no",
 
color = "yes",
 
color = "yes",
small_font = "yes",
+
smallFont = "yes",
 
sortable = "yes",
 
sortable = "yes",
 
decimals = "0",
 
decimals = "0",
 
brackets = "yes",
 
brackets = "yes",
line_break = "auto", },
+
lineBreak = "auto", },
 
high_low_average_C =
 
high_low_average_C =
 
{ first = "C",
 
{ first = "C",
convert_units = "yes",
+
convertUnits = "yes",
unit_names = "no",
+
unitNames = "no",
 
color = "yes",
 
color = "yes",
small_font = "yes",
+
smallFont = "yes",
 
sortable = "yes",
 
sortable = "yes",
 
decimals = "0",
 
decimals = "0",
 
brackets = "yes",
 
brackets = "yes",
line_break = "auto", },
+
lineBreak = "auto", },
 
high_low_F =
 
high_low_F =
 
{ first = "F",
 
{ first = "F",
convert_units = "yes",
+
convertUnits = "yes",
unit_names = "no",
+
unitNames = "no",
 
color = "no",
 
color = "no",
small_font = "yes",
+
smallFont = "yes",
 
sortable = "no",
 
sortable = "no",
 
decimals = "",
 
decimals = "",
 
brackets = "yes",
 
brackets = "yes",
line_break = "auto", },
+
lineBreak = "auto", },
 
high_low_C =
 
high_low_C =
 
{ first = "C",
 
{ first = "C",
convert_units = "yes",
+
convertUnits = "yes",
unit_names = "no",
+
unitNames = "no",
 
color = "no",
 
color = "no",
small_font = "yes",
+
smallFont = "yes",
 
sortable = "no",
 
sortable = "no",
 
decimals = "0",
 
decimals = "0",
 
brackets = "yes",
 
brackets = "yes",
line_break = "auto", },
+
lineBreak = "auto", },
 
average_F =
 
average_F =
 
{ first = "F",
 
{ first = "F",
convert_units = "yes",
+
convertUnits = "yes",
unit_names = "no",
+
unitNames = "no",
 
color = "yes",
 
color = "yes",
small_font = "yes",
+
smallFont = "yes",
 
sortable = "no",
 
sortable = "no",
 
decimals = "0",
 
decimals = "0",
 
brackets = "yes",
 
brackets = "yes",
line_break = "auto", },
+
lineBreak = "auto", },
 
average_C =
 
average_C =
 
{ first = "C",
 
{ first = "C",
convert_units = "yes",
+
convertUnits = "yes",
unit_names = "no",
+
unitNames = "no",
 
color = "yes",
 
color = "yes",
small_font = "yes",
+
smallFont = "yes",
 
sortable = "no",
 
sortable = "no",
 
decimals = "0",
 
decimals = "0",
 
brackets = "yes",
 
brackets = "yes",
line_break = "auto", },
+
lineBreak = "auto", },
 
}
 
}
  
local function add_unit_names(value, unit)
+
local function add_unitNames(value, unit)
if not unit then unit = input_unit end
+
if not unit then unit = inputUnit end
if output_format.unit_names == "yes" then
+
-- Don't add a unit name to an empty string
if check_for_string(value) then
+
value = output_format.unitNames == "yes" and checkForString(value) and value .. "&nbsp;" .. degree .. unit or value
return value .. "&nbsp;" .. degree .. unit
+
return value
else
 
return value -- Don't add a unit name to an empty string
 
end
 
else
 
return value
 
end
 
 
end
 
end
  
Line 410: Line 408:
 
else
 
else
 
parameter = ""
 
parameter = ""
add_message("<span style=\"background-color: #EEE; font-family: monospace;\">if_yes</span> needs at least one realization")
+
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 color_CSS, other_CSS, title_attribute, sortkey, attribute_separator, converted_units_separator = "", "", "", "", "", "", ""
+
local colorCSS, other_CSS, title_attribute, sortkey, attribute_separator, converted_units_separator = "", "", "", "", "", "", ""
local style_attribute, high_low_separator, brackets, values, converted_units = {"", ""}, {"", ""}, {"", ""}, {"", ""}, {"", ""}
+
local styleAttribute, high_low_separator, brackets, values, converted_units = {"", ""}, {"", ""}, {"", ""}, {"", ""}, {"", ""}
+
-- Distinguish styleAttribute variable from styleAttribute function above.
if check_for_number(output_format.decimals) then
+
decimals = ( checkForNumber(output_format.decimals) and output_format.decimals ) or precision
decimals = output_format.decimals
 
 
--[[ 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. ]]
else
 
decimals = precision
 
end
 
 
 
if check_for_number(b) and check_for_number(a) then
+
if checkForNumber(b) and checkForNumber(a) then
values, high_low_separator = { round(a, decimals), round(b, decimals) }, { thinSpace .. "/" .. thinSpace, if_yes(output_format.convert_units, thinSpace .. "/" .. thinSpace) }
+
values, high_low_separator = { round(a, decimals), round(b, decimals) }, { thinSpace .. "/" .. thinSpace, if_yes(output_format.convertUnits, thinSpace .. "/" .. thinSpace) }
elseif check_for_number(a) then
+
elseif checkForNumber(a) then
 
values = { round(a, decimals), "" }
 
values = { round(a, decimals), "" }
elseif check_for_number(c) then
+
elseif checkForNumber(c) then
 
values = { round(c, decimals), "" }
 
values = { round(c, decimals), "" }
 
end
 
end
if output_format.first == input_unit then
+
if output_format.first == inputUnit then
if output_format.convert_units == "yes" then
+
if output_format.convertUnits == "yes" then
converted_units = { add_unit_names(convert(values[1], decimals), output_unit), add_unit_names(convert(values[2], decimals), output_unit) }
+
converted_units = { add_unitNames(convert(values[1], decimals), outputUnit), add_unitNames(convert(values[2], decimals), outputUnit) }
 
end
 
end
values = { add_unit_names(values[1]), add_unit_names(values[2]) }
+
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.convert_units == "yes" then
+
if output_format.convertUnits == "yes" then
converted_units = { add_unit_names(values[1]), add_unit_names(values[2]) }
+
converted_units = { add_unitNames(values[1]), add_unitNames(values[2]) }
 
end
 
end
values = { add_unit_names(convert(values[1], decimals), output_unit), add_unit_names(convert(values[2], decimals), output_unit) }
+
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
add_message("<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.")
+
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.convert_units == "yes" then
+
if output_format.convertUnits == "yes" then
 
brackets = if_yes(output_format.brackets, "(", ")" )
 
brackets = if_yes(output_format.brackets, "(", ")" )
if output_format.line_break == "auto" then
+
if output_format.lineBreak == "auto" then
if check_for_string(values[2]) or decimals ~= "0" or output_format.show_units == "yes" then
+
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 = "&nbsp;"
 
converted_units_separator = "&nbsp;"
 
end
 
end
elseif output_format.line_break == "yes" then
+
elseif output_format.lineBreak == "yes" then
 
converted_units_separator = "<br>"
 
converted_units_separator = "<br>"
elseif output_format.line_break == "no" then
+
elseif output_format.lineBreak == "no" then
 
converted_units_separator = "&nbsp;"
 
converted_units_separator = "&nbsp;"
 
else
 
else
error("Value for line_break not recognized")
+
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 check_for_number(c) then
+
if checkForNumber(c) then
color_CSS = if_yes(output_format.color, temperature_CSS(c, input_unit, palette))
+
colorCSS = if_yes(output_format.color, temperatureCSS(c, inputUnit, palette))
if check_for_number(b) and check_for_number(a) then
+
if checkForNumber(b) and checkForNumber(a) then
 
local attribute_value
 
local attribute_value
if output_format.first == input_unit then
+
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 check_for_number(b) then
+
elseif checkForNumber(b) then
color_css = ""
+
colorCSS = ""
elseif check_for_number(a) then
+
elseif checkForNumber(a) then
color_CSS = if_yes(output_format.color, temperature_CSS(a, input_unit, palette))
+
colorCSS = if_yes(output_format.color, temperatureCSS(a, inputUnit, palette))
 
else
 
else
add_message("Neither a nor b nor c are strings.")
+
addMessage("Neither a nor b nor c are strings.")
 
end
 
end
other_CSS = if_yes(output_format.small_font, "font-size: 85%;")
+
other_CSS = if_yes(output_format.smallFont, "font-size: 85%;")
if check_for_string(color_CSS) or check_for_string(other_CSS) then
+
if checkForString(colorCSS) or checkForString(other_CSS) then
style_attribute = { "style=\"", "\"" }
+
styleAttribute = { "style=\"", "\"" }
 
end
 
end
 
 
if check_for_string(other_CSS) or check_for_string(color_CSS) or check_for_string(title_attribute) or check_for_string(sortkey) then
+
if checkForString(other_CSS) or checkForString(colorCSS) or checkForString(title_attribute) or checkForString(sortkey) then
 
attribute_separator = " | "
 
attribute_separator = " | "
 
end
 
end
cell = "\n| " .. style_attribute[1] .. color_CSS .. other_CSS .. style_attribute[2] .. title_attribute .. sortkey .. attribute_separator .. cell_content
+
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)
make_arrays(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 cell_format then
+
if cellFormat then
output_format = cell_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)
make_arrays(frame)
+
makeArrays(frame)
 
local output = "{| class=\"wikitable center nowrap\""
 
local output = "{| class=\"wikitable center nowrap\""
if cell_format then
+
if cellFormat then
output_format = cell_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 background_rgb = {}
+
local backgroundRGB = {}
local style = style_attribute(palette, celsius, background_rgb)
+
local style = styleAttribute(palette, celsius, backgroundRGB)
local R = math.floor(background_rgb[1])
+
local R = math.floor(backgroundRGB[1])
local G = math.floor(background_rgb[2])
+
local G = math.floor(backgroundRGB[2])
local B = math.floor(background_rgb[3])
+
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

Average daily high and low temperatures in °F (°C)
for locations in California,
colored and sortable by average monthly temperature
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

Average Temperatures in Minnesota in °Fahrenheit (°Celsius), 1971–2000
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>


  1. Template:WRCC
  2. Template:WRCC
  3. Template:WRCC
  4. Template:WRCC
  5. Template:WRCC
  6. Template:WRCC
  7. Template:WRCC
  8. Template:WRCC
  9. Template:WRCC
  10. Template:WRCC
  11. Template:WRCC
  12. Template:WRCC
  13. Template:WRCC
  14. Template:WRCC
  15. Template:WRCC
  16. Template:WRCC
  17. Template:WRCC
  18. Ross, Douglas (1971–2000). "Daily Normals for Alexandria, Minnesota". NCDC. Retrieved 2007-06-07.
  19. Ross, Douglas (1971–2000). "Daily Normals for Brainerd, Minnesota". NCDC. Retrieved 2007-12-27.
  20. Ross, Douglas (1971–2000). "Daily Normals for Duluth, Minnesota". NCDC. Retrieved 2007-06-07.
  21. Ross, Douglas (1971–2000). "Daily Normals for Grand Marais, Minnesota". NCDC. Retrieved 2007-12-27.
  22. Ross, Douglas (1971–2000). "Daily Normals for International Falls, Minnesota". NCDC. Retrieved 2007-06-07.
  23. Ross, Douglas (1971–2000). "Daily Normals for Redwood Falls, Minnesota". NCDC. Retrieved 2007-06-07.
  24. Ross, Douglas (1971–2000). "Daily Normals for Thief River Falls, Minnesota". NCDC. Retrieved 2007-06-07.
  25. Ross, Douglas (1971–2000). "Daily Normals for the Twin Cities". NCDC. Retrieved 2007-06-07.
  26. Ross, Douglas (1971–2000). "Daily Normals for Winona, Minnesota". NCDC. Retrieved 2007-06-07.
  27. 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 .. "&nbsp;" .. 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 = "&nbsp;"
			end
		elseif output_format.lineBreak == "yes" then
			converted_units_separator = "<br>"
		elseif output_format.lineBreak == "no" then
			converted_units_separator = "&nbsp;"
		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