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.

  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.