Modulo:Demografia

Da Wikipedia, l'enciclopedia libera.
Vai alla navigazione Vai alla ricerca
local mWikidata = require('Modulo:Wikidata')
local mChart = require('Modulo:Graph/sandbox')

local p = {}

local function dump(t, ...)
    local args = {...}
    for _, s in ipairs(args) do
        table.insert(t, s)
    end
end

local function max_pop(data)
    local max = 0
    for _,d in ipairs(data) do
        if d.population > max then max = d.population end
    end
    return max
end

-- Converte una stringa di valori numerici separati da "," in una lista
-- Eventuali valori non numerici sono ignorati
local function read_array(args)
    local raw_data = {}
    if args.anni and args.popolazione then
        local years = mw.text.split(args.anni, ",")
        local populations = mw.text.split(string.gsub(args.popolazione, "%s", ""), ",")
        if #years == #populations then
            for i = 1, #years do
                raw_data[i] = {year=string.gsub(years[i], "%s", "") , population = tonumber(populations[i]) or 0 }
            end
        end
    end
    if #raw_data == 0 then -- vecchio metodo di inserimento
        for i=1,20 do
            local index = tonumber(i)
            local year = tonumber(args['a' .. index])
            if year then
                raw_data[#raw_data+1] = { year = year, population = tonumber(args['p' .. index]) or 0 }
            end
        end
    end
    return raw_data
end

local function comp_year(d1, d2)
    return d1.year < d2.year
end

local function get_wikidata(from)
    local claims 
    local raw_data = {}

    claims = mWikidata._getClaims('P1082', { from = from, rank = 'normal' }) or {}
    for _, claim in ipairs(claims) do
        raw_data[#raw_data + 1] = {
            population = tonumber(mWikidata._formatStatement(claim)) or 0,
            year = mWikidata._formatQualifiers(claim, 'P585')
        }
    end
    table.sort(raw_data, comp_year)

    return raw_data
end

local function default_table(popmax, n)
    local default = {}
    local log_p = math.ceil(math.log10(popmax))
    if log_p == 0 then log_p = 1 end
    local first_digit = math.floor(popmax / 10 ^ (log_p - 1))
    if first_digit == 9 then
        default.popmax = 10 ^ (log_p)
    else
        default.popmax = (first_digit +1 ) * 10 ^ (log_p-1)
    end
    if log_p < 2 then log_p = 2 end
    if first_digit <=5 then
        default.passo1 = (10 ^ (log_p-1)) / 2
        default.passo2 = 10 ^ (log_p-2)
    else
        default.passo1 = (10 ^ (log_p-1))
        default.passo2 = 2 * 10 ^ (log_p-2)     
    end
    default.dimx = 488
    if n > 15 then default.dimx = 488 + (n-15) * 20 end
    return default
end

local function draw_graph(raw_data, args, default)
    local populations = {}
    local years = {}
    for i,d in ipairs(raw_data) do
        years[i], populations[i] = d.year, d.population
    end
    local graph = {
        graphwidth = tonumber(args.dimx) or default.dimx,
        graphheight = tonumber(args.dimy) or 280,
        ygrid = true,
        ymax = args.popmax or tostring(default.popmax),
        xtitle = 'anni',
        ytitle = 'popolazione',
        y = { populations },
        x =  years,
        graph_type = 'rect',
        seriesTitles = {'Popolazione'},
        colors = {'#4682B4'},
        showValue = true
    }
    local graph_json = mChart.chart_json(graph)
    if args.raw then return graph_json end
    return mw.getCurrentFrame():extensionTag('graph', graph_json)
end

local function draw_timeline(raw_data, args, default)
    local graph = {}
    dump(graph, 'Colors=\n id:lightgrey value:gray(0.9)\n id:darkgrey  value:gray(0.7)\n id:sfondo value:rgb(1,1,1)\n id:barra value:rgb(0.6,0.7,0.8)\n\n')
    dump(graph, 'ImageSize = width:', args.dimx or tostring(default.dimx), ' height:', args.dimy or '373', '\n')
    dump(graph, 'PlotArea   = left:50 bottom:50 top:30 right:30\nDateFormat = x.y\n')
    dump(graph, 'Period = from:0 till:', args.popmax or tostring(default.popmax), '\n')
    dump(graph, 'TimeAxis   = orientation:vertical\nAlignBars  = justify\n')
    dump(graph, 'ScaleMajor = gridcolor:darkgrey increment:', args.passo1 or tostring(default.passo1), ' start:0\n' )
    dump(graph, 'ScaleMinor = gridcolor:lightgrey increment:', args.passo2 or tostring(default.passo2), ' start:0\n')
    dump(graph, 'BackgroundColors = canvas:sfondo\n')
    dump(graph, 'BarData=\n')
    for _,data in ipairs(raw_data) do
        dump(graph, string.format(' bar: %s text:%s\n', data.year, data.year))
    end
    dump(graph, '\n')
    dump(graph, 'PlotData=\n color:barra width:20 align:left\n\n')
    for _,data in ipairs(raw_data) do
        dump(graph, string.format(' bar:%s from:0 till:%d\n', data.year, data.population))
    end
    dump(graph, '\n')
    local lang = mw.language.new('it')
    dump(graph, 'PlotData=\n')
    for _,data in ipairs(raw_data) do
        local p_formatted = lang:formatNum(math.floor(data.population + 0,5) )
        dump(graph, string.format(' bar: %s at: %d fontsize:S text: %s shift:(-10,5)|n.d. shift:(-8,5)\n',
                                    data.year, data.population, p_formatted))
    end
    dump(graph, '\n')
    if args.fonte then
        dump(graph, 'TextData=\n fontsize:S pos:(20,20)\n text:fonte ', args.fonte, '\n')
    end
    local draw_graph
    if args.raw then
        draw_graph = '<nowiki>'.. table.concat(graph) .. '</nowiki>'
    else
        draw_graph = mw.getCurrentFrame():extensionTag('timeline', table.concat(graph))
    end
    return draw_graph
end

function p._demografia(args)
    local graph
    local raw_data = read_array(args)
    local from_wikidata = false
    if #raw_data == 0 then
        raw_data = get_wikidata(args.from)
        from_wikidata = true
        -- if true then return mw.text.jsonEncode(raw_data, mw.text.JSON_PRETTY) end
    end
    if #raw_data == 0 then return '' end
    local popmax = max_pop(raw_data)
    local is_thousand = false
    if from_wikidata and popmax >= 900000 then
        popmax = popmax / 1000
        for i,data in ipairs(raw_data) do
            raw_data[i].population = raw_data[i].population / 1000
            is_thousand = true
        end
    end
    -- calcolo default per la popolazione
    local default = default_table(popmax, #raw_data)
    -- generazione del grafico
    local titolo = "''Abitanti censiti''<br />"
    if is_thousand then
        titolo =  "''Abitanti censiti (migliaia)''<br />"
    end
    if args.titolo then
        titolo = "''" .. args.titolo .. "''<br />"
    end
    if args.graph then
        graph = draw_graph(raw_data, args, default)
    else
        graph = draw_timeline(raw_data, args, default)
    end
    return titolo .. graph
end

function p.demografia(frame)
    local args = require('Modulo:Arguments').getArgs(frame)
    return p._demografia(args)
end

return p