Modulo:ClimaAnnuale
Modulo in Lua per gestire le funzioni di {{ClimaAnnuale}} e {{ClimaAnnualeAustrale}}
local p = {}
local language = mw.language.getContentLanguage()
local getArgs = require('Module:Arguments').getArgs
local index_month = {"01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"}
--carico le tabelle dei colori
local tempo_config = mw.loadData( 'Modulo:ClimaAnnuale/Configurazione' );
local function dump(t, ...)
local args = {...}
for _, s in ipairs(args) do
table.insert(t, s)
end
end
-- Nota il lua non ha una funzione di arrotondamento
-- funzione copiata da http://lua-users.org/wiki/SimpleRound
function round(num, idp)
local mult = 10^(idp or 0)
if num >= 0 then return math.floor(num * mult + 0.5) / mult
else return math.ceil(num * mult - 0.5) / mult end
end
-- prima di provare ad applicare tonumber a una stringa converte
-- eventuali virgole in punti
local function tonumber_comma(s)
if s then
s = string.gsub(s, ',', '.')
s = string.gsub(s, '−', '-')
return tonumber(s)
else
return nil
end
end
-- Per leggere una stringa di dati, si aspetta di leggere una stringa
-- di valori separati da "," o ";" da args[<basename>].
-- In caso contrario controlla se sono presenti come sequenza di
-- parametri i valori "args[<base_name>01] .. "args[<basename>12]"
-- Se legge almeno un valore si assicura di restituire almeno 12 valori
-- sostituendo i mancanti con "0"
local function dataArray(args, base_name)
local list = {}
local csv = args[base_name]
if csv then
if string.find(csv, ";") then
list = mw.text.split(string.gsub(csv, "%s", ""), ";")
else
list = mw.text.split(string.gsub(csv, "%s", ""), ",")
end
for i =1, 12 do
if not list[i] or list[i] == '' then list[i] = "0" end
end
elseif args[base_name .. "01"] then
for i, index_string in ipairs(index_month) do
list[i] = args[base_name .. index_string] or "0"
end
end
return list
end
-- Per leggere una stringa di dati, si aspetta di leggere una stringa
-- di valori separati da "," o ";"
local function noteArray(args, base_name, extend)
local list = {}
local csv = args[base_name]
if csv then
if string.find(csv, ";") then
list = mw.text.split(string.gsub(csv, "%s", ""), ";")
else
list = mw.text.split(string.gsub(csv, "%s", ""), ",")
end
else
for i, index_string in ipairs(index_month) do
list[i] = args[base_name .. index_string] or ""
end
end
return list
end
---------------------------------------------------------------
-- Funzioni di generazione del colore celle
-- Ognuna di queste funzioni riceve un valore e ritorna un valore
-- esadecimale da usare come sfondo per la cella, il valore può essere
-- basato su una tabella memorizzata in Modulo:ClimaAnnuale/Configurazione
-- oppure può essere calcolato sulla base di una formula matematica
---------------------------------------------------------------------------
local function TempToColour(temp)
temp = round(temp)
if temp < -19 then return tempo_config.temperatura[-19] end
return tempo_config.temperatura[temp] or 'FF1F00'
end
local function PressureToColour(press)
press = round(press)
if press < -90 then return tempo_config.pressione[-90] end
return tempo_config.pressione[press] or 'FFFFFF'
end
local function PressureToColour1000(press)
return PressureToColour(press-1000)
end
local function WarmToColour(temp)
temp = round(temp)
if temp < 0 then return tempo_config.warm[0] end
return tempo_config.warm[temp] or 'FF0060'
end
local function CloudToColour(okta)
okta = round(okta, 1)
if okta < 0.0 then return tempo_config.cloud[0.0] end
return tempo_config.cloud[okta] or 'FFF0F0'
end
local function RainToColour(mm)
mm = round(mm, 0)
if mm < 0 then return tempo_config.rain[0] end
return tempo_config.rain[mm] or '0000FF'
end
local function RainToColour10(days)
return RainToColour(days*10)
end
local function SnowToColour(cm)
cm = round(cm, 0)
if cm < 0 then return tempo_config.snow[0] end
return tempo_config.snow[cm] or '0000FF'
end
local function SnowToColour10(days)
return SnowToColour(days*10)
end
local function convert_to_FF(val, base, mult)
local result = round(base - (val or 0) * mult)
return math.max(math.min(result, 255), 0)
end
local function IceToColour(days)
return string.format('%02X%02XE5', convert_to_FF(days, 229, 8), convert_to_FF(days, 230, 1))
end
local function FogToColour(days)
return string.format('%02X%02XE5', convert_to_FF(days, 229, 2), convert_to_FF(days, 230, 0.8))
end
local function HumToColour(hum_percent)
local base_percent = convert_to_FF(hum_percent-50, 255, 4.1)
return string.format('%02X%02XFF', base_percent, base_percent)
end
local function HelioToColour(elio)
return string.format('FF%02X%02X', convert_to_FF(-elio, 128, 6.375), convert_to_FF(-elio, 51, 5.1))
end
local function OreSoleToColour(hours)
return string.format('FF%02X%02X', convert_to_FF(hours, 128, .3), convert_to_FF(hours, 51, .1))
end
local function SunToColour(rad)
rad = round(rad/100, 0) * 100
if rad < 0 then return tempo_config.sun[0] end
return tempo_config.sun[rad] or '0000FF'
end
local function GiorniSerenoToColour(days)
return string.format('FF%02X%02X', convert_to_FF(days, 175, 3), convert_to_FF(days, 81, 2))
end
local function IntensitaToColour(rad)
return 'FFFFFF'
end
--------------------------------------------------------------------------
--Fine funzioni di generazione del colore cella
--------------------------------------------------------------------------
local function format_numero(value, force_decimal)
local value_string = language:formatNum(value)
if force_decimal and value % 1 == 0 then
value_string = value_string .. ',0'
end
value_string = mw.ustring.gsub(value_string, "^-", "−")
return value_string
end
--Calcolo del valore medio degli argomenti in ingresso arrotondato alla prima cifra decimale
local function Media( ... )
local args = { ... }
local sum = 0
for _, s in ipairs(args) do
sum = sum + s
end
return round(sum / #args, 1)
end
--Calcolo del totale degli ingressi
local function Totale( ... )
local args = { ... }
local sum = 0
for _, s in ipairs(args) do
sum = sum + s
end
return round(sum, 1)
end
-- Restituisce il valore esadecimale del colore della cella, riceve:
---- color: funzione da richiamare per resistuire il colore
---- value: il valore da usare per il calcolo del valore
---- aggregate_function: la funzione di aggregazione usata
---- div: il numero per cui dividere il valore (3 per la somma di tre mesi, 12 per la somma annuale) per cui dividere il
---- value se la funzione di aggregazione era Total)
local function Cell_color(color, value, aggregate_function, div)
if aggregate_function == Totale then
return color(round(value / div))
else
return color(value)
end
end
-- Configurazione dei dati da leggere e della corrispondente riga di tabella da generare:
---- name: nome base della variabile che contiene il valore
---- color: funzione che assegna il colore alla cella
---- yearname: presente solo per alcune righe. Il nome base della della variabile con l'anno del dato
----- direction: presente solo per intensità (vento). il nome base della variabile con la direzione del vento
---- aggregate: funzione per il calcolo dei valori aggregati (stagionali e annuali)
---- aggregatelabel: attributo css "title" delle celle dei dati aggregati
---- force_decimal: se forzare o meno i dati/risultato con uno zero decimale (",0") quando sono interi
local data_type = {
{ name = 'tempmax', color = TempToColour, aggregate = Media, label = '[[Temperatura|T. max. media]] ([[Grado Celsius|°C]])', aggregatelabel = 'media' },
{ name = 'tempmedia', color = TempToColour, aggregate = Media, label = '[[Temperatura|T. media]] ([[Grado Celsius|°C]])', aggregatelabel= 'media' },
{ name = 'tempmin', color = TempToColour, aggregate = Media, label = '[[Temperatura|T. min. media]] ([[Grado Celsius|°C]])', aggregatelabel= 'media' },
{ name = 'tempassmax', color = TempToColour, aggregate = math.max, yearname = 'annotempassmax', label = '[[Temperatura|T. max. assoluta]] ([[Grado Celsius|°C]])', aggregatelabel= 'massimo' },
{ name = 'tempassmin', color = TempToColour, aggregate = math.min, yearname = 'annotempassmin', label='[[Temperatura|T. min. assoluta]] ([[Grado Celsius|°C]])', aggregatelabel= 'minimo' },
{ name = 'warm', color = WarmToColour, aggregate = Totale, label = '[[Onda di calore|Giorni di calura]] ([[temperatura|T<sub>max</sub>]] ≥ 30 [[Grado Celsius|°C]])', aggregatelabel = 'totale'},
{ name = 'giornigelo', color =IceToColour, aggregate = Totale, label = '[[Giorno di gelo|Giorni di gelo]] ([[temperatura|T<sub>min</sub>]] ≤ 0 [[Grado Celsius|°C]])', aggregatelabel = 'totale'},
{ name = 'giornighiaccio', color=IceToColour, aggregate = Totale, label ='[[Giorno di ghiaccio|Giorni di ghiaccio]] ([[temperatura|T<sub>max</sub>]] ≤ 0 [[Grado Celsius|°C]])', aggregatelabel='totale'},
{ name = 'nubi', color=CloudToColour, aggregate=Media, label='[[Nuvola#Nuvolosità|Nuvolosità]] ([[okta]] al [[giorno]])', aggregatelabel='media' },
{ name = 'pioggia', color=RainToColour, aggregate=Totale, label='[[Precipitazione (meteorologia)|Precipitazioni]] ([[Metro#Multipli e sottomultipli|mm]])', aggregatelabel='totale'},
{ name = 'giornipioggia', color=RainToColour10, aggregate=Totale, label='[[Giorno di pioggia|Giorni di pioggia]]', aggregatelabel='totale'},
{ name = 'neve', color=SnowToColour, aggregate=Totale, label='[[Neve|Nevicate]] ([[Metro#Multipli e sottomultipli|cm]])', aggregatelabel='totale'},
{ name = 'giornineve', color=SnowToColour10, aggregate=Totale, label='[[Neve|Giorni di neve]]', aggregatelabel='totale'},
{ name = 'mantonevoso', color=SnowToColour10, aggregate=Totale, label='[[Neve|Giorni con manto nevoso]] ≥ 1 [[Metro#Multipli e sottomultipli|cm]]', aggregatelabel='totale'},
{ name = 'giornigrandine', color=SnowToColour10, aggregate=Totale, label='[[Grandine|Giorni di grandine]]', aggregatelabel='totale'},
{ name = 'giorninebbia', color=FogToColour, aggregate=Totale, label='[[Nebbia|Giorni di nebbia]]', aggregatelabel='totale'},
{ name = 'umidomax', color=HumToColour, aggregate=Media, label='[[Umidità relativa|Umidità relativa massima media]] (%)', aggregatelabel='media'},
{ name = 'umido', color=HumToColour, aggregate=Media, label='[[Umidità relativa|Umidità relativa media]] (%)', aggregatelabel="media"},
{ name = 'umidomin', color=HumToColour, aggregate=Media, label='[[Umidità relativa|Umidità relativa minima media]] (%)', aggregatelabel='media'},
{ name = 'giornisereno', color= GiorniSerenoToColour, aggregate = Totale, label ='[[Sole|Giorni di cielo sereno]]', aggregatelabel='totale'},
{ name = 'elio', color=HelioToColour, aggregate=Media, label='[[Eliofania|Eliofania assoluta]] ([[ora|ore]] al [[giorno]])', aggregatelabel='media'},
{ name = 'sole', color=SunToColour, aggregate=Totale, label='[[Radiazione solare|Radiazione solare globale media]] (centesimi di [[Joule|MJ]]/[[metro quadrato|m²]])', aggregatelabel='totale'},
{ name = 'oresoleggiamento', color=OreSoleToColour, aggregate=Totale, label='[[Sole|Ore di soleggiamento mensili]]', aggregatelabel='totale'},
{ name= 'pressionereale', color=PressureToColour1000, aggregate=Media, label='[[Pressione atmosferica|Pressione]] a [[Grado Celsius|0 °C]] ([[Pascal (unità di misura)|hPa]])', aggregatelabel='media'},
{ name= 'pressione', color=PressureToColour1000, aggregate=Media, label='[[Pressione atmosferica|Pressione]] a [[livello del mare|0 metri s.l.m.]] ([[Pascal (unità di misura)|hPa]])', aggregatelabel='media'},
{ name= 'tensionevapore', color=PressureToColour, aggregate=Media, label='[[Pressione di vapore|Tensione di vapore]] ([[Pascal (unità di misura)|hPa]])', aggregatelabel='media'},
{ name= 'intensità', color=IntensitaToColour, aggregate=Media, direction='vento', label='[[Vento]] ([[Rosa dei venti|direzione]]-[[metro|m]]/[[secondo|s]])', aggregatelabel='media'}
}
-- ordine in cui aggregare i valori
local aggregate_index = {12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
-- ordine dei nomi delle stagioni secondo emisfero boreale/australe
local seasons = {
boreale = { "[[Inverno|Inv]]", "[[Primavera|Pri]]", "[[Estate|Est]]", " [[Autunno|Aut]] " },
australe = { "[[Estate|Est]]", "[[Autunno|Aut]]", "[[Inverno|Inv]]", "[[Primavera|Pri]]" }
}
function p.ClimaAnnuale(frame)
-- Se chiamata mediante #invoke, usa gli argomenti passati al template invocante.
-- Altrimenti a scopo di test assume che gli argomenti siano passati direttamente
local args = getArgs(frame)
local emisphere = args.emisfero or 'boreale'
local season = seasons[emisphere] or seasons.borealea
local equatorial = false
if args.equatoriale and (args.equatoriale == 's' or args.equatoriale == 'S') then
equatorial = true
end
local output = {}
-- testata della tabella
dump(output, '<div style="overflow-x:auto" >',
'<table class="wikitable" style="margin-top:.5em; margin-bottom:.5em; text-align: center;">',
'<tr><th rowspan="2" style="border-right-width: 2px;">', args['nome'] or 'Mese', '</th>',
'<th colspan="12"> [[Mese|Mesi]] </th>')
if not equatorial then
dump(output,'<th colspan="4" style="border-left-width: 2px;" > [[Stagione|Stagioni]] </th>')
end
dump(output, '<th rowspan="2" style="border-left-width: 2px; "> [[Anno]] </th>',
'</tr>',
'<tr>',
'<th> [[Gennaio|Gen]] </th>',
'<th> [[Febbraio|Feb]] </th>',
'<th> [[Marzo|Mar]] </th>',
'<th> [[Aprile|Apr]] </th>',
'<th> [[Maggio|Mag]] </th>',
'<th> [[Giugno|Giu]] </th>',
'<th> [[Luglio|Lug]] </th>',
'<th> [[Agosto|Ago]] </th>',
'<th> [[Settembre|Set]] </th>',
'<th> [[Ottobre|Ott]] </th>',
'<th> [[Novembre|Nov]] </th>',
'<th> [[Dicembre|Dic]] </th>')
if not equatorial then
dump(output, '<th style="border-left-width: 2px;" >', season[1], '</th>')
for j = 2, 4 do
dump(output, '<th>', season[j], '</th>')
end
end
dump(output, '</tr>')
-- generazione delle righe
for _,row in ipairs(data_type) do
local values = dataArray(args, row.name)
local force_decimal = false
--check esistenza del tipo di dato della riga
if #values > 0 then
local yearnames = row.yearname and noteArray(args, row.yearname, false)
local directions = row.direction and noteArray(args, row.direction, false)
dump(output, '<tr><th style="border-right-width: 2px"> ', row.label, ' </th>')
-- ciclo per leggere tutti i valori dei mesi
for i,raw_value in ipairs(values) do
if string.find(raw_value, '.', 1, true) or string.find(raw_value, ',', 1, true) then
force_decimal = true
end
-- converto il valore del mese in numero, se non definito lo setto a 0
values[i] = tonumber_comma(raw_value) or 0
-- apro la cella e genero il valore
dump(output, '<td style="background:#', row.color(values[i]), ';">')
-- per la direzione del vento (da mettere prima della velocità)
if row.direction and directions[i] and directions[i]~= "" then
dump(output, '<small>', directions[i], '</small> <br />')
end
-- aggiungo il valore alla cella
dump(output, format_numero(values[i], force_decimal) )
-- check se devo controllare e aggiungere l'anno del dato
if row.yearname and yearnames[i] ~= '' then
dump(output, '<br /><small>(', yearnames[i], ')</small>')
end
dump(output,'</td>')
end
-- ciclo per generare i dati stagionali aggregati
if not equatorial then
for j = 1, 10, 3 do
local aggregate_season = row.aggregate(values[aggregate_index[j]], values[aggregate_index[j+1]], values[aggregate_index[j+2]])
dump(output, '<td title="', row.aggregatelabel, '" style="border-left-width: 2px; background:#',
Cell_color(row.color, aggregate_season, row.aggregate, 3), ';">\'\'\'', format_numero(aggregate_season, force_decimal), "'''</td>" )
end
end
-- genero il dato annuale aggregato
local aggregate_year = row.aggregate(unpack(values))
dump(output, '<td title="', row.aggregatelabel, '" style="border-left-width: 2px; background:#',
Cell_color(row.color, aggregate_year, row.aggregate, 12), ';">\'\'\'', format_numero(aggregate_year, force_decimal), "'''</td>")
dump(output, '</tr>')
end
end
dump(output, '</table></div>')
return table.concat(output)
end
return p
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.
- 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:
- 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.
- 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.
- 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.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.