Módulo:Weather
Este módulo pode ter sua documentação deficiente. Por favor, documente-o ou melhore suas explicações caso o saiba usar ou tenha conhecimentos para tal. |
Este módulo está classificado como pronto para uso geral. Ele chegou a uma forma madura e pensa-se que está livre de erros e pronto para ser usado onde é apropriado. Ele está pronto para ser mencionado nas páginas de discussão e em outros recursos da Wikipédia como opção para novos usuários aprenderem. Para reduzir cargas nos servidores e mostrar texto estragado, ele deve ser melhorado pelo Exemplos para testes em vez de tentativas de edição a experimentar e erro. |
Descrição
Esta módulo pode ser utilizado para mostrar temperaturas em um tabela.
Uso
Outra documentação:
-- Efficient (fast) functions to implement cells in tables of weather data.
-- Temperature conversion is built-in, but for simplicity, temperatures
-- are assumed to be for habitable locations (from -100 to 100 °C).
local MINUS = '−' -- Unicode U+2212 MINUS SIGN
local function temperature_style(palette, value, out_rgb)
-- Return style for a table cell based on the given value which
-- should be a temperature in °C.
local function style(bg, fg)
local min, max = unpack(palette.white or { -23, 35 })
if not fg and value and (value < min or value >= max) then
fg = 'FFFFFF'
end
if fg then
fg = 'color:#' .. fg .. ';'
else
fg = ''
end
return 'style="background:#' .. bg .. ';' .. fg .. ' font-size:100%;"'
end
if type(value) ~= 'number' then
return style('FFFFFF', '000000')
end
local rgb = out_rgb or {}
for i, v in ipairs(palette) do
local a, b, c, d = unpack(v)
if value <= a then
rgb[i] = 0
elseif value < b then
rgb[i] = (value - a) * 255 / (b - a)
elseif value <= c then
rgb[i] = 255
elseif value < d then
rgb[i] = 255 - ( (value - c) * 255 / (d - c) )
else
rgb[i] = 0
end
end
return style(string.format('%02X%02X%02X', rgb[1], rgb[2], rgb[3]))
end
local function format_cell(palette, value, intext, outtext)
-- Return one line of wikitext to make a cell in a table.
if not value then
return '|\n'
end
local text
if outtext then
text = intext .. '<br>(' .. outtext .. ')'
else
text = intext
end
return '| ' .. temperature_style(palette, value) .. ' | ' .. text .. '\n'
end
local function process_temperature(intext, inunit, swap)
-- Convert °C to °F or vice versa, assuming the temperature is for a
-- habitable location, well inside the range -100 to 100 °C.
-- That simplifies determining precision and formatting (no commas are needed).
-- Return (celsius_value, intext, outtext) if valid; otherwise return nil.
-- The returned input and output are swapped if requested.
-- Each returned string has a Unicode MINUS as sign, if negative.
local invalue = tonumber(intext)
if not invalue then return nil end
local integer, dot, decimals = intext:match('^%s*%-?(%d+)(%.?)(%d*)%s*$')
if not integer then return nil end
if invalue < 0 then
intext = MINUS .. integer .. dot .. decimals
end
local outtext
if inunit == 'C' or inunit == 'F' then
local celsius_value, outvalue
if inunit == 'C' then
outvalue = invalue * (9/5) + 32
celsius_value = invalue
else
outvalue = (invalue - 32) * (5/9)
celsius_value = outvalue
end
local precision = dot == '' and 0 or #decimals
outtext = string.format('%.' .. precision .. 'f', math.abs(outvalue) + 2e-14)
if outvalue < 0 and tonumber(outtext) ~= 0 then
-- Don't show minus if result is negative but rounds to zero.
outtext = MINUS .. outtext
end
if swap then
return celsius_value, outtext, intext
end
return celsius_value, intext, outtext
end
-- LATER Think about whether a no-conversion option would be useful.
return invalue, intext, outtext
end
local function temperature_row(palette, row, inunit, swap)
-- Return 13 lines specifying the style/content of 13 table cells.
-- Input is 13 space-separated words, each a number (°C or °F).
-- Any word that is not a number gives a blank cell ("M" for a missing cell).
-- Any excess words are ignored.
--
-- Function Input Output
-- ------------------------
-- CtoF C C/F
-- FfromC C F/C
-- CfromF F C/F
-- FtoC F F/C
local nrcol = 13
local results, n = {}, 0
for word in row:gmatch('%S+') do
n = n + 1
if n > nrcol then
break
end
results[n] = format_cell(palette, process_temperature(word, inunit, swap))
end
for i = n + 1, nrcol do
results[i] = format_cell()
end
return table.concat(results)
end
local palettes = {
-- A background color entry in a palette is 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 temperatures(frame, inunit, swap)
local palette = palettes[frame.args.palette] or palettes.cool
return temperature_row(palette, frame.args[1], inunit, swap)
end
local function CtoF(frame)
return temperatures(frame, 'C')
end
local function CfromF(frame)
return temperatures(frame, 'F', true)
end
local function FtoC(frame)
return temperatures(frame, 'F')
end
local function FfromC(frame)
return temperatures(frame, 'C', true)
end
local chart = [[
{{Graph:Chart
|width=600
|height=180
|xAxisTitle=Celsius
|yAxisTitle=__COLOR
|type=line
|x=__XVALUES
|y=__YVALUES
|colors=__COLOR
}}
]]
local function 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 rgb = {}
local style = temperature_style(palette, celsius, rgb)
local R = math.floor(rgb[1])
local G = math.floor(rgb[2])
local B = math.floor(rgb[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 {
CtoF = CtoF,
CfromF = CfromF,
FtoC = FtoC,
FfromC = FfromC,
show = show,
}