NotesEdit

This is a version of Module:Sandbox/Erutuon/Temperature arrays that creates tables using the MediaWiki HTML library instead of wikitext. It generates the exact same content, and I think it takes a little more time.

TestcasesEdit

Lua error at line 230: variable 'temperature_CSS' is not declared. Lua error at line 230: variable 'temperature_CSS' is not declared. Lua error at line 241: variable 'temperature_CSS' is not declared.

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.


local p = {}

local degree = "°"
local m_weather = require("Module:Weather/sandbox")

local format

local message = ""

local function add_message(new_message)
	if message == "" then
		message = "Notices: " .. new_message
	else
		message = message .. " " .. new_message
	end
end

local function get_format (frame)
	local input_format_parameter = frame.args.input_format
	local input_unit, output_unit, length, output_format, display_unit, array_names
	
	if input_format_parameter == nil then
		input_unit = frame.args.input_unit
		length = tonumber(frame.args.length)
	else
		length = string.match(input_format_parameter, '(%d+)') -- find digits in the input_format parameter
		length = tonumber(length)
		
		input_unit = string.match(input_format_parameter, '([CF])') -- C or F
	end
	
	if input_unit == "C" then
		output_unit = "F"
	elseif input_unit == "F" then
		output_unit = "C"
	else
		error ("Input unit is not recognized. Please choose F for Fahrenheit or C for Celsius", 0)
	end
	
	output_format = tostring(frame.args.output_format)
	display_unit = frame.args.display_unit
	
	if length == nil then
		error ("get_format has not found a length value in the length or input_format parameter")
	end
	
	return { input_unit = input_unit, output_unit = output_unit,
		length = length, output_format = output_format,
		display_unit = display_unit, array_names = array_names }
end

local function precision(value, decimals)
	local string = string.format('%.' .. decimals .. 'f', value)
	return string
end

local function check_for_string(string)
	return string ~= "" and string ~= nil
end

local function check_for_number(value)
	return type(tonumber(value)) == "number"
end

local function convert(value, decimals, unit) -- Unit is the unit being converted from. It defaults to input_unit.
	if not unit then
		unit = format.input_unit
	end
	if check_for_number(value) then
		local value = tonumber(value)
		if unit == "C" then
			return precision(value * 9/5 + 32, decimals)
		elseif unit == "F" then
			return precision((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

local function make_array(parameter, array, frame)
	format = get_format(frame)
	local array = {}
	local n = 1
	for number in parameter:gmatch('%-?%d+%.?%d?') do
		local number = number
		table.insert(array, n, number)
		if array[n] == nil then
			if n > 1 then
				error("There should be " .. length .. " values in the " .. parameter .. " parameter, but there are only " .. n .. " values")
			else
				error("There should be " .. length .. " values in the " .. parameter .. " parameter, but there is only " .. n .. " value")
			end
		end
		n = n + 1
		if n > format.length then
			break
		end
	end
	return array
end

local function make_arrays(frame)
	local a, b, c
	get_format(frame)
	local parameter_a = frame.args.a
	local parameter_b = frame.args.b
	local parameter_c = frame.args.c
	if parameter_a then
		a = make_array(parameter_a, a, frame)
	else
		error("Please provide a set of numbers in parameter <span style=\"background-color: #EEE; font-family: monospace;\">a</span>")
	end
	if parameter_b then
		b = make_array(parameter_b, b, frame)
	else
		add_message("There is no content in parameter <span style=\"background-color: #EEE; font-family: monospace;\">b</span>.")
	end
	if parameter_c then
		c = make_array(parameter_c, c, frame)
	else
		add_message("There is no content in parameter <span style=\"background-color: #EEE; font-family: monospace;\">c</span>.")
	end
	return a, b, c
end

local output_formats = {
	high_low_average_F = 
		{ first = "F",
		line_break = "yes",
		convert_units = "yes",
		unit_names = "no",
		brackets = "yes",
		tooltip = "yes",
		add_color = "yes",
		small_font = "no",
		sortable = "yes", },
	high_low_F =
		{ line_break = "yes",
		first = "F",
		convert_units = "yes",
		unit_names = "no",
		brackets = "yes",
		tooltip = "no",
		add_color = "no",
		small_font = "no",
		sortable = "yes", },
	average_F = 
		{ first = "F",
		line_break = "yes",
		convert_units = "yes",
		unit_names = "yes",
		brackets = "yes",
		tooltip = "no",
		add_color = "yes",
		small_font = "no",
		sortable = "no", },
	}

local function add_unit_names(value, unit)
	if not unit then
		unit = format.input_unit
	end
	if format.output_format.unit_names == "yes" then
		if value == "" then
			return value -- Don't add a unit name to an empty string
		else
			return value .. degree .. unit
		end
	else
		return value
	end
end

local function interpret_format(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 = ""
		add_message("<span style=\"background-color: #EEE; font-family: monospace;\">interpret_format</span> needs at least one realization")
	end
	return parameter
end

local function make_cell(row, output_format, a, b, c)
	local cell, CSS, cell_content = "", "", ""
	local title_content, sort_attribute, sortkey, attribute_separator
	local style_attribute, title_attribute, values_separator = {}, {}, {}
	
	local values, converted_units
	local line_break, brackets = interpret_format(output_format.line_break, "<br>"), interpret_format(output_format.brackets, "(", ")" )
	if a then
		if b then
			values, values_separator = { a, b  }, { "/", interpret_format(output_format.convert_units, "/") }
		else
			values, values_separator = { a, "" }, { "", "" } -- Empty values must be strings, or concatenation will not work.
		end
	end
	if format.input_unit == output_format.first then
		converted_units = interpret_format(
			output_format.convert_units,
			add_unit_names(convert(values[1], 1), format.output_unit),
			add_unit_names(convert(values[2], 1), format.output_unit)
		)
		values = { add_unit_names(values[1]), add_unit_names(values[2]) }
	elseif output_format.first == "C" or output_format.first == "F" then
		converted_units = interpret_format(output_format.convert_units, add_unit_names(values[1]), add_unit_names(values[2]) )
		values = { add_unit_names(convert(values[1], 1), output_unit), add_unit_names(convert(values[2], 1), output_unit) }
	else
		add_message("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
	
	cell_content = values[1] .. values_separator[1] .. values[2] .. line_break .. brackets[1] .. converted_units[1] .. values_separator[2] .. converted_units[2] .. brackets[2]
	
	if a and b and c then
		CSS = interpret_format(output_format.add_color, temperature_CSS(c, input_unit))
		if input_unit == output_format.first then
			title_content = "Average temperature: " .. c .. interpret_format(output_format.convert_units, degree .. input_unit)
			sortkey = c
		else
			title_content = "Average temperature: " .. convert(c, 1) .. interpret_format(output_format.convert_units, degree .. output_unit)
			sortkey = convert(c, 1)
		end
		title_content = interpret_format(output_format.tooltip, title_content)
		sortkey = interpret_format(output_format.sortable, sortkey)
	elseif a and not b then
		CSS = interpret_format(output_format.add_color, temperature_CSS(a, input_unit))
	end
	CSS = CSS .. interpret_format(output_format.small_font, "font-size: 85%;")
	--[[
	if color_CSS == "" and other_CSS == "" then
		style_attribute = { "", "" }
	else
		style_attribute = { "style=\"", "\"" }
	end
	]]
	
	--[[
	if other_CSS == "" and color_CSS == "" and title_content == "" and sort_attribute == "" then
		attribute_separator = ""
	else
		attribute_separator = " | "
	end
	]]
	
	local td = row:tag("td")
		if check_for_string(cell_content) then
			td:wikitext (cell_content)
		else
			add_message("<span style=\"background-color: #EEE; font-family: monospace;\">cell_content</span> is not defined.")
		end
		if check_for_string(CSS) then
			td:cssText (CSS)
		end
		if check_for_string(title_content) then
			td:attr ("title", title_content)
		end
		if check_for_string(sortkey) then
			td:attr ("data-sort-value", sortkey)
		end
	-- cell = "\n| " .. style_attribute[1] ..  .. style_attribute[2] .. title_attribute[1] .. title_content .. title_attribute[2] .. sort_attribute .. attribute_separator .. cell_content
	return td
end

function p.print_arrays(frame)
	local a, b, c = make_arrays(frame)
	local classes = "wikitable"
	if format.sortable == "yes" then
		classes = classes .. " sortable"
	end
	
	local t = mw.html.create("table")
		t:addClass(classes)
	local tr = t:tag("tr")
	if a and b and c then
		for i = 1, format.length do
			make_cell(tr, output_formats.high_low_average_F, a[i], b[i], c[i])
		end
	elseif a and b then
		for i = 1, format.length do
			make_cell(tr, output_formats.high_low_F, a[i], b[i])
		end
	elseif a then
		for i = 1, format.length do
			make_cell(tr, output_formats.average_F, a[i])
		end
	end
	return tostring(t) .. "\n\n<span style=\"color: red; font-size: 80%; line-height: 100%;\">" .. message .. "</span>"
end

return p