Share to:

Modul:WeatherBox/row

local math_mod = require('Module:Math')

local traceText
local Value
Value = {
	lang = mw.getContentLanguage(),
	getDisplay = function (self, second)
		if not self:isValid() then
			return nil
		end
		local display = self.string
		if display == 'trace' then
			if second then
				-- If a cell displays "cm (inch)", show "trace" not "trace (trace)".
				return nil
			end
			return traceText or 'trace'
		end
		if math.abs(self.number) >= 1000 then
			display = self.lang:formatNum(math.abs(self.number))
			if self.number < 0 then
				display = '−' .. display
			end
		elseif self.number < 0 then
			display = '−' .. display:sub(2)
		end
		return display
	end,
	getPrecision = function (self)
		local result = rawget(self, 'precision')
		if not result then
			if self:isValid() then
				result = math.max(0, math_mod._precision(self.string))
			else
				result = 0
			end
			rawset(self, 'precision', result)
		end
		return result
	end,
	isValid = function (self)
		return self.number ~= nil and self.number ~= -9999
	end,
	new = function (v)
		local val, str, precision
		if type(v) == 'string' then
			if v == 'trace' then
				val, str, precision = 0, 'trace', 0
			else
				val, str = math_mod._cleanNumber(v)
			end
		elseif type(v) == 'number' then
			val, str = v, tostring(v)
		end
		if not val then
			val, str = -9999, ''
		end
		return setmetatable({
			number = val,
			string = str,
			precision = precision,
		}, Value)
	end,
	converts = {
		in2cm = { factor = 2.54              },
		in2mm = { factor = 25.4              },
		cm2in = { factor = 1/2.54, p2max = 1 },
		mm2in = { factor = 1/25.4, p2max = 0 },
	},
	setConvert = function (self, invalue, units)
		-- Use method modified from [[Module:Convert]] to determine precision.
		if invalue.string == 'trace' then
			self.number, self.string, self.precision = 0, 'trace', 0
			return
		end
		local convert = self.converts[units] or error('Neznane enote')
		local outnum = invalue.number * convert.factor
		local precision = invalue:getPrecision()
		if outnum > 0 then
			local adjust = math.log10(1/convert.factor) + math.log10(2)
			local p1 = math.floor(precision + adjust)
			local p2 = 1 - math.floor(math.log10(outnum))
			if convert.p2max then
				p2 = math.min(p2, convert.p2max)
			end
			precision = math.max(p1, p2)
		end
		self:setNumberRounded(outnum, precision)
	end,
	setNumberRounded = function (self, number, precision)
		if precision > 2 then
			precision = 2
		end
		self.number = math_mod._round(number, precision)
		if precision < 0 then
			self.string = tostring(self.number)
		else
			local fmt = '%.' .. string.format('%d', precision) .. 'f'
			self.string = string.format(fmt, self.number)
		end
	end,
}
Value.__index = Value

local function checkFlag(flag, default)
	if flag == nil then
		return default
	elseif type(flag) == 'boolean' then
		return flag
	elseif type(flag) == 'string' then
		flag = flag:lower()
		if flag == '0' or flag == 'false' or
				flag == '' or flag == 'no' or
				flag == 'n' then
			return false
		else
			return true
		end
	else
		return error('Neveljavna vrsta zastave')
	end
end

local function makeLine(label, first_values, second_values, color_values)
	local result = {'|- style="text-align: center;"\n! scope="row" style="height: 16px;" | ', label, "\n"}
	for i = 1, 13 do
		local color_str = color_values[i]
		if i == 13 then
			table.insert(result, table.concat( {'|style="', color_str, ' border-left-width:medium" | '} ))
		else
			table.insert(result, table.concat( {'|style="', color_str, '" | '} ))
		end
		local display = first_values[i]:getDisplay()
		if display then
			table.insert(result, display)
			if second_values ~= nil then
				display = second_values[i]:getDisplay(true)
				if display then
					table.insert(result, "<br />(" .. display .. ")")
				end
			end
		else
			table.insert(result, '—')
		end
		table.insert(result, "\n")
	end
	return table.concat(result)
end

local function getInputs(args, group_name, suffix, include_space)
	local month_names = { 'Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun',
		'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec', 'leto' }
	local str
	local values = {}
	if suffix == nil then
		for i, mon in ipairs(month_names) do
			if include_space then
				str = args[ mon .. ' ' .. group_name ] or ''
			else
				str = args[ mon .. group_name ] or ''
			end
			values[i] = Value.new(str)
		end
	else
		for i, mon in ipairs(month_names) do
			local value, updated
			for var, suf in ipairs(suffix) do
				if include_space then
					str = args[ mon .. ' ' .. group_name .. ' ' .. suf ]
				else
					str = args[ mon .. group_name .. ' ' .. suf ]
				end
				if str ~= nil and str ~= '' then
					value = Value.new(str)
					value.variant = var
					updated = true
					break
				end
			end
			if not updated then
				value = Value.new()
				value.variant = 0
			end
			values[i] = value
		end
	end
	return values
end

local function getAnnualValue(values, mode)
	if mode == 'avg' or mode == 'sum' then
		local total = 0
		local p1, p2, variant
		p1 = 0
		for i = 1, 12 do
			if not values[i]:isValid() then
				return Value.new()
			end
			if not variant then
				local var = values[i].variant
				if var and var ~= 0 then
					variant = var
				end
			end
			p2 = values[i]:getPrecision()
			if p2 > p1 then
				p1 = p2
			end
			total = total + values[i].number
		end
		local value = Value.new(total)
		if mode == 'avg' then
			value:setNumberRounded(total / 12, p1)
		end
		value.variant = variant
		return value
	elseif mode == 'min' then
		local target
		for i = 1, 12 do
			if values[i]:isValid() then
				if target == nil or values[i].number < target.number then
					target = values[i]
				end
			end
		end
		return target or Value.new()
	elseif mode == 'max' then
		local target
		for i = 1, 12 do
			if values[i]:isValid() then
				if target == nil or values[i].number > target.number then
					target = values[i]
				end
			end
		end
		return target or Value.new()
	else
		error('Neprepoznan letni način')
	end
end

local function reconcileTemperature(C_values, F_values)
	for i = 1, 13 do
		local p
		if C_values[i].string == '' then
			if F_values[i]:isValid() then
				p = F_values[i]:getPrecision()
				C_values[i]:setNumberRounded((F_values[i].number - 32)*5/9, p)
			end
		elseif F_values[i].string == '' then
			if C_values[i]:isValid() then
				p = C_values[i]:getPrecision()
				F_values[i]:setNumberRounded(C_values[i].number*9/5 + 32, p)
			end
		end
	end
end

local function reconcilePrecipitation(M_values, I_values, prefer_cm)
	local v_class = 0
	for i = 1, 13 do
		if M_values[i].variant == 1 then
			v_class = 1
		elseif M_values[i].variant == 2 then
			v_class = 2
		end
	end
	if v_class == 0 then
		if prefer_cm then
			v_class = 1
		else
			v_class = 2
		end
	end
	for i = 1, 13 do
		local units
		if M_values[i].string == '' then
			if I_values[i]:isValid() then
				if v_class == 1 then
					units = 'in2cm'
				else
					units = 'in2mm'
				end
				M_values[i]:setConvert(I_values[i], units)
				M_values[i].variant = v_class
			end
		elseif I_values[i].string == '' then
			if M_values[i]:isValid() then
				if M_values[i].variant == 1 then
					units = 'cm2in'
				else
					units = 'mm2in'
				end
				I_values[i]:setConvert(M_values[i], units)
			end
		end
	end
end

local function _buildRow(definition, args, options)
	options = options or {}
	local wbc = require('Modul:Weather_box/colors' .. (options.sandbox or ''))
	local mode = (definition.mode or 'basic'):lower()
	local group_name = definition.group_name
	local first_values, second_values
	local color_values
	local color_scheme = definition.color_scheme or 't'
	local scale_factor = math_mod._cleanNumber(definition.scale_factor) or 1
	local date_mode = checkFlag(definition.date_mode, false)
	local label = definition.label or ''
	local annual_mode = (definition.annual_mode or 'avg'):lower()
	local include_space = checkFlag(definition.include_space, true)
	local second_line = checkFlag(definition.second_line, false)
	local prefer_cm = checkFlag(definition.prefer_cm, false)
	local imperial_first = checkFlag(args['imperial first'])
	local metric_first = checkFlag(args['metric first'])
	local wantSingleLine = options.wantSingleLine or checkFlag(args['single line'])
	local trace = args.trace
	if trace and trace ~= '' then
		traceText = trace
	end
	if imperial_first == nil then
		imperial_first = metric_first == nil and true or not metric_first
	end
	if mode == 'basic' then
		first_values = getInputs(args, group_name, nil, include_space)
		second_values = nil
	elseif mode == 'temperature' then
		first_values = getInputs(args, group_name, {'C'}, include_space)
		second_values = getInputs(args, group_name, {'F'}, include_space)
		reconcileTemperature(first_values, second_values)
	elseif mode == "precipitation" then
		first_values = getInputs(args, group_name, {'cm', 'mm'}, include_space)
		second_values = getInputs(args, group_name, {'inch'}, include_space)
		reconcilePrecipitation(first_values, second_values, prefer_cm)
	else
		error('Neprepoznan zahtevani način')
	end
	local good = false
	for i = 1, 13 do
		if first_values[i].string ~= '' then
			good = true
			break
		end
	end
	if not good then
		return ''
	end
	if first_values[13].string == '' then
		first_values[13] = getAnnualValue(first_values, annual_mode)
	end
	if second_values ~= nil then
		if second_values[13].string == '' then
			second_values[13] = getAnnualValue(second_values, annual_mode)
		end
	end
	color_scheme = wbc.interpret_color_code(color_scheme)
	color_values = {}
	local month_adj = { 31/30, 28.25/30, 31/30, 1, 31/30, 1,
		31/30, 31/30, 1, 31/30, 1, 31/30, 365.25/30 }
	for i = 1, 13 do
		if first_values[i]:isValid() then
			local adj = scale_factor
			if date_mode then
				adj = adj / month_adj[i]
			end
			if mode == "precipitation" then
				if first_values[i].variant == 1 then
					adj = adj * 10
				end
			end
			table.insert(color_values, color_scheme(first_values[i].number * adj))
		else
			table.insert(color_values, color_scheme(nil))
		end
	end
	if imperial_first and second_values ~= nil then
		first_values, second_values = second_values, first_values
	end
	if not wantSingleLine then
		if second_line and second_values ~= nil then
			first_values = second_values
		end
		second_values = nil
	end
	return makeLine(label, first_values, second_values, color_values)
end

local function buildRow(frame)
	return _buildRow(frame.args, frame:getParent().args)  -- row definition, template parameters
end

return {
	buildRow = buildRow,
	_buildRow = _buildRow,
}

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.
Prefix: a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9

Portal di Ensiklopedia Dunia

Kembali kehalaman sebelumnya