Modulo che implementa i template {{Grafico}} e {{Grafico a torta}}.

Ha una sottopagina di configurazione: Modulo:Graph/Configurazione.


local p = {}

local cfg = mw.loadData( 'Modulo:Sandbox/moroboshi/Chart/Configurazione' );

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

-- ===============================================================================
-- Costruisce una struttura dati da codificare in json per realizzare un grafico
-- a torta visualizzabile utilizzando il tag graph
-- https://www.mediawiki.org/wiki/Extension:Graph
-- i nomi dei parametri sono localizzati in base a chart/Config
--
-- ===============================================================================
function build_pie_chart_json(data, args)
  local graph = {
        name = args[cfg.localization.name] or 'grafico a torta',
        data = {
            {  
                name = "table",
                values = data,
                transform = { { type = "pie", value = "data.x" } }
            }
        },
        marks = {
            {
                type = "arc",
                from = { data = "table"},
                properties = {
                    enter = {
                        x = { field = "data.x", group = "width", mult = 0.5 },
                        y = { field = "data.x", group = "height", mult = 0.5 },
                        startAngle = {field = "startAngle"},
                        endAngle = {field = "endAngle"},
                        innerRadius = {value = 0},
                        outerRadius = {value = tonumber(args[cfg.localization.radius]) or cfg.radius_default },
                        stroke = {value = "#fff"},                       
                    },
                    update = { fill = { field = "data.color"} },
                    hover = { fill = {value = "pink"} }
                },
             }
        }
    }
    if args[cfg.localization.show_label] then
        graph.marks[#graph.marks+1] = {type = "text",
                from = { data = "table"},
                properties = {  
                    enter = {
                        x = { field = "data.x", group = "width", mult = 0.5 },
                        y = { field = "data.x", group = "height", mult = 0.5 },
                        radius = { value = tonumber(args[cfg.localization.radius]) or cfg.radius_default, offset = 8 },
                        theta = { field = "midAngle"},
                        fill = { value = "#000" },
                        align = { value = "center" },
                        baseline = { value = "middle" },
                        text = { field = "data.label"}
                    }
                }
            }
    end
    return graph
end


local function legend_item(color, text)
    local item = mw.html.create('p'):cssText('margin:0px;font-size:100%;text-align:left')
    item:tag('span'):cssText(string.format('border:none;background-color:%s;color:%s;', color, color)):wikitext("██")
    item:wikitext(string.format(" %s", text))
    return item
end

local function build_legend(data, args)
    local legend = mw.html.create('div'):addClass('thumbcaption')
    legend:wikitext(args[cfg.localization.caption] or '')
    for _,datum in ipairs(data) do
        legend:node(legend_item(datum.color, mw.ustring.format('%s (%s %%)', datum.label, tostring(datum.x))))
    end
    return legend
end


function p.pie_chart(frame)
    args = require('Modulo:Arguments').getArgs(frame)
    local value_string = cfg.localization.value
    local label_string = cfg.localization.label
    local color_string = cfg.localization.color
    local index = 1
    local data = {}
    local colors = {}
    local labels = {}
    while true do
        local index_s = tostring(index)
        local value = tonumber(args[value_string .. index_s])
        if  value then
            data[index] = {
                x = value,
                label = args[label_string .. index_s] or '',
                color = args[color_string .. index_s] or cfg.default_colors[index] or cfg.default_color
            }
            index = index + 1
        else
            break
        end
    end
    -- Se è definito 'other' assumo che sia calcolato su base %, calcolo il suo valore e l'aggiungo alla tabella dati
    if args[cfg.localization.other] then 
        local total = 0
        for _,datum in ipairs(data) do
            total = total + datum.x
        end
        local other_value = math.max(0, 100 - total)
        data[index] = { 
            x = other_value,
            label = args[cfg.localization.label_other] or 'altri',
            color = args[cfg.localization.color_other] or cfg.default_colors[index] or cfg.default_color
        }
    end 
    if #data == 0 then
        return ''
    end
    local graph = build_pie_chart_json(data, args)
    local json
    -- se il parametro debug_json è stato valorizzato ritorna il codice json generato invece di generare il grafico
    if args.debug_json then
        return  frame:extensionTag('syntaxhighlight', mw.text.jsonEncode(graph, mw.text.JSON_PRETTY), {lang='json'})
    end
    local legend = build_legend(data, args)
    local html = mw.html.create('div')
        :addClass(string.format('thumb t%s', args[cfg.localization.thumb] or 'right'))
        :attr('float', args[cfg.localization.thumb] or 'right')
            :tag('div')
                :addClass('thumbinner')
                :cssText('width:202px')
                :tag('div')
                    :cssText("background-color:white;margin:auto;position:relative;width:200px;height:200px;overflow:hidden")
                    :wikitext(frame:extensionTag( 'graph', mw.text.jsonEncode(graph) ))
                    :done()
                :node(legend)
    return html
end

return p