Modulo:Bio/sandbox

Versione del 4 mar 2014 alle 13:42 di Rotpunkt (discussione | contributi) (abilitato wikidata per test)
--[[
* Modulo per implementare le funzionalità di Bio
* Traduce in lua:
* Template:Bio
* Template:Bio/categorie_attività
* Template:Bio/cat
* Template:Bio/catnatimorti
* Template:Bio/epoca
* Template:Bio/articolo
* Template:Bio/articolo_F
* Template:Bio/link attività
* Template:Bio/link nazionalità
* Template:Bio/plurale_attività
* Template:Bio/plurale_nazionalità
* Template:Bio/warning_A
* Template:Bio/warning_N
* Template:Primo del mese
*
* utilizza:
* Template:Avviso
]]

-- Variabili globali
local p = {}          -- per l'esportazione delle funzioni del modulo
local args            -- argomenti passati al template
local textTable = {}  -- table per contenere la risposta da ritornare
local SPACE = " " -- HTML Entity Code per lo spazio

-- Configurazione
local cfg
local link_attivita
local link_nazionalita
local plurale_attivita
local plurale_nazionalita

-------------------------------------------------------------------------------
--                           Funzioni di utilità
-------------------------------------------------------------------------------

-- Aggiunge testo alla risposta, svolge anche la funzione di concatenatore
local function dumpText(...)
    local arg = {...}

    for _, val in ipairs(arg) do
        table.insert(textTable, val)
    end
end

-- Aggiunge una categoria alla risposta
local function dumpCategory(category)
    dumpText("[[Categoria:", category, "]]", "\n")
end

-- Aggiunge un wlink alla risposta, se target è nil utilizza label come target
local function dumpWlink(target, label)
    if target and label then
       dumpText("[[", target, "|", label, "]]")
    else
       dumpText("[[", target or label, "]]")
    end
end

-- Aggiunge una immagine alla risposta, size e caption sono opzionali
local function dumpImage(name, size, caption)
    dumpText("[[File:", name, "|thumb")

    if size then
        dumpText("|", size, "px")
    end
    if caption then
        dumpText("|", caption)
    end

    dumpText("]]", "\n")
end

-- Aggiunge l'output del [[Template:Avviso]] e una categoria di warning alla risposta
local function dumpAvviso(tipo, immagine, immagine_a_destra, testo)
    local text

    text = mw.getCurrentFrame():expandTemplate {
        title = "Avviso",
        args = {
            ["tipo"] = tipo,
            ["immagine"] = immagine,
            ["immagine a destra"] = immagine_a_destra,
            ["testo"] = testo
        }
    }

    dumpText(text)
    dumpCategory(cfg.categorie["warning"])
end

-- Wrapper di mw.title.exists, verifica sia che name sia valido, sia che esista
local function titleExists(name)
    local title = mw.title.new(name)

    return title and title.exists
end

-- Traduzione in lua del [[Template:Primo del mese]]
-- Se date inizia con "1 " o "1°" ritorna una nuova data che inizia per "1º", altrimenti date
local function fixFirstOfMonth(date)
    date = date:gsub("^1%s", "1º ")
    date = date:gsub("^1\194\176", "1º")

    return date
end

-- Ritorna "ed" se nextWord inizia con "e", altrimenti "e"
local function getEufonica(nextWord)
    return nextWord:sub(1, 1) == "e" and "ed" or "e"
end

-- Parsifica un TimeValue di Wikidata e ne ritorna "giornomese, anno"
local function parseWikidataTimeValue(property)
    local entity, value, year, month, day, daymonth

    entity = mw.wikibase.getEntityObject()
    if entity and entity.claims and entity.claims[property] and
       entity.claims[property][0].mainsnak.snaktype == "value" then
        value = entity.claims[property][0].mainsnak.datavalue.value
        year, month, day = value.time:match(".+(%d%d%d%d%d)%-(%d%d)%-(%d%d).+")
        if value.precision == 11 then
            month = mw.getLanguage("it"):formatDate("F", tonumber(year) .. "-" .. month .. "-" .. day)
            daymonth = tonumber(day) .. " " .. month
        end
        if value.precision == 9 or value.precision == 11 then
            year = tonumber(year) .. (value.time:sub(1, 1) == "-" and " a.C." or "")
        end
    end

    return daymonth, year
end

-------------------------------------------------------------------------------
--                           Parsing parametri
-------------------------------------------------------------------------------

-- Utilizzata da parseParams per controllare il valore di un parametro.
-- Ritorna true se il valore è valido altrimenti false.
local function checkParamValue(value, paramType, origArgs)
    local ret = true

    if type(paramType) == "function" then
        ret = paramType(value, origArgs)
    elseif type(paramType) == "string" then
        if paramType == "string" then
            -- "string" accetta qualunque valore
        elseif paramType == "number" then
            if not tonumber(value) then
                ret = false
            end
        elseif not value:match(paramType) then
            ret = false
        end
    end

    return ret
end

-- Parsifica i parametri passati al modulo e aggiunge eventuali categorie di errore.
-- Ritorna i parametri conosciuti scartando quelli valorizzati a stringa vuota.
local function parseParams(origArgs)
    local params = require("Modulo:Bio/Parametri")
    local allowedValue, paramKnown = true, true
    local ret = {}

    -- controlla i parametri conosciuti, il loro valore e li copia
    for k, v in pairs(origArgs) do
        if params[k] then
            if v ~= "" then
                if allowedValue then
                    allowedValue = checkParamValue(v, params[k][2], origArgs)
                end
                ret[k] = v
            end
        else
            paramKnown = false
        end
    end
    -- aggiunge eventuali categorie di errore
    if mw.title.getCurrentTitle().namespace == 0 then
        if not paramKnown then
            dumpCategory(cfg.categorie["unknown-params"])
        end
        if not allowedValue then
            dumpCategory(cfg.categorie["wrong-params"])
        end
    end

    return ret
end

-------------------------------------------------------------------------------
--                           Gestione categorie
-------------------------------------------------------------------------------

-- Ritorna il plurale dell'attività o nil se non trovato (con eventuale warning)
local function getPluralAttivita(attivita, warning)
    local plural

    plurale_attivita = plurale_attivita or mw.loadData("Modulo:Bio/Plurale attività")
    plural = plurale_attivita[attivita]
    if not plural and warning then
        dumpAvviso(cfg.warningA.tipo, cfg.warningA.immagine, cfg.warningA.immagine_a_destra,
                   cfg.warningA.testo .. cfg.warningA.testo2a:gsub("$1", attivita) .. cfg.warningA.testo3)
    end

    return plural
end

-- Ritorna il plurale della nazionalità o nil se non trovato (con eventuale warning)
local function getPluralNazionalita(nazionalita, warning)
    local plural

    plurale_nazionalita = plurale_nazionalita or mw.loadData("Modulo:Bio/Plurale nazionalità")
    plural = plurale_nazionalita[nazionalita]
    if not plural and warning then
        dumpAvviso(cfg.warningN.tipo, cfg.warningN.immagine, cfg.warningN.immagine_a_destra,
                   cfg.warningN.testo .. cfg.warningN.testo2a:gsub("$1", nazionalita) .. cfg.warningN.testo3)
    end

    return plural
end

-- Traduzione in lua del [[Template:Bio/cat]]
-- Utilizzata da addAttivitaCategories, aggiunge la categoria (eventualmente con l'epoca)
local function addCat(catname, epoca1, epoca2)
    local added = false

    if epoca1 and titleExists("Categoria:" .. catname .. " " .. epoca1) then
        dumpCategory(catname .. " " .. epoca1)
        added = true
    end
    if epoca2 and titleExists("Categoria:" .. catname .. " " .. epoca2) then
        dumpCategory(catname .. " " .. epoca2)
        added = true
    end
    if not added then
        -- se non è stata aggiunta la categoria per epoca1 e epoca2
        -- aggiunge la cat. semplice, e.g. "Scrittori italiani"
        dumpCategory(catname)
    end
end

-- Traduzione in lua del [[Template:Bio/categorie attività]] con un minimo di refactoring
-- Aggiunge le categorie: Attività nazionalità [del XYZ secolo]
local function addAttivitaCategories()
    local plurals = {} -- contiene la versione plurale dei parametri
    local epoca1, epoca2

    -- controllo argomenti necessari al plurale per le categorie
    -- (nello stesso ordine in cui avvenivano in [[Template:Bio/categorie attività]])
    if args["Nazionalità"] then
        plurals["Nazionalità"] = getPluralNazionalita(args["Nazionalità"], true)
    else
        dumpAvviso(cfg.warningN.tipo, cfg.warningN.immagine, cfg.warningN.immagine_a_destra,
                   cfg.warningN.testo .. cfg.warningN.testo2b .. cfg.warningN.testo3)
    end
    if args["NazionalitàNaturalizzato"] then
        plurals["NazionalitàNaturalizzato"] = getPluralNazionalita(args["NazionalitàNaturalizzato"], true)
    end
    if args["Cittadinanza"] then
        plurals["Cittadinanza"] = getPluralNazionalita(args["Cittadinanza"], true)
    end
    if args["Attività"] then
        plurals["Attività"] = getPluralAttivita(args["Attività"], true)
    else
        dumpAvviso(cfg.warningA.tipo, cfg.warningA.immagine, cfg.warningA.immagine_a_destra,
                   cfg.warningA.testo .. cfg.warningA.testo2b .. cfg.warningA.testo3)
    end
    if args["Attività2"] then
        plurals["Attività2"] = getPluralAttivita(args["Attività2"], true)
    end
    if args["Attività3"] then
        plurals["Attività3"] = getPluralAttivita(args["Attività3"], true)
    end

    -- aggiunta categorie
    epoca1 = args["Epoca"] and cfg.epoche[args["Epoca"]]
    epoca2 = args["Epoca2"] and cfg.epoche[args["Epoca2"]]
    for _, val in ipairs({ "Attività", "Attività2", "Attività3" }) do
        if plurals[val] then
            if plurals["Nazionalità"] then
                addCat(plurals[val] .. " " .. plurals["Nazionalità"], epoca1, epoca2)
            end
            if plurals["NazionalitàNaturalizzato"] then
                addCat(plurals[val] .. " " .. plurals["NazionalitàNaturalizzato"], epoca1, epoca2)
            end
            if plurals["Cittadinanza"] then
                addCat(plurals[val] .. " " .. plurals["Cittadinanza"], epoca1, epoca2)
            end
        end
    end
end

-- Traduzione in lua del [[Template:Bio/catnatimorti]]
-- Aggiunge le categorie: Nati/Morti nell'anno/giorno/luogo
local function addNatiMortiCategories()
    local cat1, cat2

    if args["AnnoNascita"] then
        cat1 = "Nati nel " .. args["AnnoNascita"]
        cat2 = "Nati nell'" .. args["AnnoNascita"]
        if titleExists("Categoria:" .. cat1) then
            dumpCategory(cat1)
        elseif titleExists("Categoria:" .. cat2) then
            dumpCategory(cat2)
        end
    end

    if args["AnnoMorte"] then
        cat1 = "Morti nel " .. args["AnnoMorte"]
        cat2 = "Morti nell'" .. args["AnnoMorte"]    
        if titleExists("Categoria:" .. cat1) then
            dumpCategory(cat1)
        elseif titleExists("Categoria:" .. cat2) then
            dumpCategory(cat2)
        end
    else
        dumpCategory("Persone viventi")
    end

    if args["GiornoMeseNascita"] then
        cat1 = "Nati il " .. fixFirstOfMonth(args["GiornoMeseNascita"])
        cat2 = "Nati l'" .. args["GiornoMeseNascita"]
        if titleExists("Categoria:" .. cat1) then
            dumpCategory(cat1)
        elseif titleExists("Categoria:" .. cat2) then
            dumpCategory(cat2)
        end               
    end
    
    if args["GiornoMeseMorte"] then
        cat1 = "Morti il " .. fixFirstOfMonth(args["GiornoMeseMorte"])
        cat2 = "Morti l'" .. args["GiornoMeseMorte"]
        if titleExists("Categoria:" .. cat1) then
            dumpCategory(cat1)
        elseif titleExists("Categoria:" .. cat2) then
            dumpCategory(cat2)
        end               
    end
    
    if args["LuogoNascitaLink"] then
        cat1 = "Nati a " .. args["LuogoNascitaLink"]
        cat2 = "Nati ad " .. args["LuogoNascitaLink"]
        if titleExists("Categoria:" .. cat1) then
            dumpCategory(cat1)
        elseif titleExists("Categoria:" .. cat2) then
            dumpCategory(cat2)
        end
    elseif args["LuogoNascita"] then
        cat1 = "Nati a " .. args["LuogoNascita"]
        cat2 = "Nati ad " .. args["LuogoNascita"]
        if titleExists("Categoria:" .. cat1) then
            dumpCategory(cat1)
        elseif titleExists("Categoria:" .. cat2) then
            dumpCategory(cat2)
        end
    end

    if args["LuogoMorteLink"] then
        cat1 = "Morti a " .. args["LuogoMorteLink"]
        cat2 = "Morti ad " .. args["LuogoMorteLink"]
        if titleExists("Categoria:" .. cat1) then
            dumpCategory(cat1)
        elseif titleExists("Categoria:" .. cat2) then
            dumpCategory(cat2)
        end
    elseif args["LuogoMorte"] then
        cat1 = "Morti a " .. args["LuogoMorte"]
        cat2 = "Morti ad " .. args["LuogoMorte"]
        if titleExists("Categoria:" .. cat1) then
            dumpCategory(cat1)
        elseif titleExists("Categoria:" .. cat2) then
            dumpCategory(cat2)
        end
    end
end

-------------------------------------------------------------------------------
--                           Creazione incipit
-------------------------------------------------------------------------------

-- Ritorna il link dell'attività o nil se non trovato
local function getLinkAttivita(attivita)
    link_attivita = link_attivita or mw.loadData("Modulo:Bio/Link attività")
    return link_attivita[attivita]
end

-- Ritorna il link della nazionalità o nil se non trovato.
local function getLinkNazionalita(nazionalita)
    link_nazionalita = link_nazionalita or mw.loadData("Modulo:Bio/Link nazionalità")
    return link_nazionalita[nazionalita]
end

-- Prova a ottenere alcuni parametri mancanti da Wikidata
local function checkWikidata()
    local daymonth, year

    -- GiornoMeseNascita e AnnoNascita
    if not args["GiornoMeseNascita"] or not args["AnnoNascita"] then
        daymonth, year = parseWikidataTimeValue("P569")
        args["GiornoMeseNascita"] = args["GiornoMeseNascita"] or daymonth
        args["AnnoNascita"] = args["AnnoNascita"] or year
    end
    -- GiornoMeseMorte e AnnoMorte
    if not args["GiornoMeseMorte"] or not args["AnnoMorte"] then
        daymonth, year = parseWikidataTimeValue("P570")
        args["GiornoMeseMorte"] = args["GiornoMeseMorte"] or daymonth
        args["AnnoMorte"] = args["AnnoMorte"] or year
    end
end

-- Traduzione in lua del [[Template:Bio/articolo]]
local function getArticleMan(attivita)
    local article

    if cfg.articoli_maschili["uno"][attivita] then
        article = "uno"
    elseif cfg.articoli_maschili["una"][attivita] then
        article = "una"
    else
        article = "un"
    end

    return article
end

-- Traduzione in lua del [[Template:Bio/articolo_F]]
-- aggiunge anche uno spazio nel caso non usi l'apostrofo
local function getArticleWoman(attivita)
    local article

    if cfg.articoli_femminili["un"][attivita] then
        article = "un" .. SPACE
    elseif attivita and attivita:match("^[aeiou]") then
        article = "un'"
    else
        article = "una" .. SPACE
    end

    return article
end

local function addImmagine()
    local caption

    if args["Immagine"] then
        if args["Didascalia"] then
            caption = args["Didascalia"]
        else
            if args["Nome"] then
                caption = args["Nome"]
            end
            if args["Cognome"] then
                caption = (caption or "") .. " " .. args["Cognome"]
            end
        end
        if args["Didascalia2"] then
            caption = (caption or "") .. "<hr />" .. args["Didascalia2"]
        end
        dumpImage(args["Immagine"], args["DimImmagine"], caption)
    elseif args["Didascalia2"] then
        -- parentesi () extra per non ritornare anche il gsub.count
        dumpText( (cfg.didascalia2:gsub("$1", args["Didascalia2"])) )
    end
end

local function addNomeCognome()
    if args["Titolo"] then
        dumpText(args["Titolo"], SPACE)
    end

    -- inizio grassetto
    dumpText("'''")

    if args["Nome"] then
        dumpText(args["Nome"])
    end

    if args["Cognome"] then
        dumpText(SPACE, args["Cognome"])
    end

    -- fine grassetto
    dumpText("'''")

    if args["PostCognomeVirgola"] then
        dumpText(",", SPACE, args["PostCognomeVirgola"])
    end

    if args["PostCognome"] then
        dumpText(SPACE, args["PostCognome"])
    end
end

local function addNascitaMorte()
    -- si apre la parentesi
    dumpText(SPACE, "(")

    if args["PreData"] then
         dumpText(args["PreData"], ";", SPACE)
    end

    if args["LuogoNascita"] then
        dumpWlink(args["LuogoNascitaLink"], args["LuogoNascita"])
        if args["LuogoNascitaAlt"] then
            dumpText(SPACE, args["LuogoNascitaAlt"])
        end
        dumpText(",", SPACE)
    end

    if args["GiornoMeseNascita"] then
        if titleExists(args["GiornoMeseNascita"]) then
            dumpWlink(args["GiornoMeseNascita"])
        else
            dumpText(args["GiornoMeseNascita"])
        end
        dumpText(SPACE)
    end

    if args["AnnoNascita"] then
        if titleExists(args["AnnoNascita"]) then
            dumpWlink(args["AnnoNascita"])
        else
            dumpText(args["AnnoNascita"])
        end
    else
        dumpText("...")
    end

    if args["NoteNascita"] then
        dumpText(args["NoteNascita"])
    end

    if args["AnnoMorte"] then
        dumpText(SPACE, "–", SPACE)
        if args["LuogoMorte"] then
            dumpWlink(args["LuogoMorteLink"], args["LuogoMorte"])
            if args["LuogoMorteAlt"] then
                dumpText(SPACE, args["LuogoMorteAlt"])
            end
            dumpText(",", SPACE)
        end

        if args["GiornoMeseMorte"] then
            if titleExists(args["GiornoMeseMorte"]) then
                dumpWlink(args["GiornoMeseMorte"])
            else
                dumpText(args["GiornoMeseMorte"])
            end
            dumpText(SPACE)
        end

        if args["AnnoMorte"] then
            if args["AnnoMorte"] == "?" then
                dumpText("...")
            else
                if titleExists(args["AnnoMorte"]) then
                    dumpWlink(args["AnnoMorte"])
                else
                    dumpText(args["AnnoMorte"])
                end
            end
        end
    end

    if args["NoteMorte"] then
        dumpText(args["NoteMorte"])
    end

    -- si chiude la parentesi
    dumpText(")")
end

local function addAttivita()
    if args["PreAttività"] then
        dumpText(args["PreAttività"], SPACE)
    else
        dumpText("è", SPACE)
        if args["AnnoMorte"] then
            dumpText((not args["Sesso"] or args["Sesso"] == "M")
                     and "stato" or "stata", SPACE)
        end
        if not args["Sesso"] or args["Sesso"] == "M" then
            dumpText(getArticleMan(args["Attività"]), SPACE)
        else
            dumpText(getArticleWoman(args["Attività"]))
        end
    end

    dumpWlink(getLinkAttivita(args["Attività"]), args["Attività"] or "")

    if args["Attività2"] then
        if args["Attività3"] or args["AttivitàAltre"] then
            dumpText(",")
        else
            dumpText(SPACE, getEufonica(args["Attività2"]))
        end
        dumpText(SPACE)
        dumpWlink(getLinkAttivita(args["Attività2"]), args["Attività2"])
    end

    if args["Attività3"] then
        if args["AttivitàAltre"] then
            dumpText(",")
        else
            dumpText(SPACE, getEufonica(args["Attività3"]))
        end
        dumpText(SPACE)
        dumpWlink(getLinkAttivita(args["Attività3"]), args["Attività3"])
    end

    if args["AttivitàAltre"] then
        dumpText(args["AttivitàAltre"])
    end

    dumpText(SPACE)
    dumpWlink(getLinkNazionalita(args["Nazionalità"]), args["Nazionalità"] or "")

    if args["Cittadinanza"] then
        dumpText(SPACE, "con cittadinanza", SPACE)
        dumpWlink(getLinkNazionalita(args["Cittadinanza"]), args["Cittadinanza"])
    end

    if args["NazionalitàNaturalizzato"] then
        dumpText(SPACE)
        dumpWlink("Naturalizzazione",
                  (not args["Sesso"] or args["Sesso"] == "M" or
                  (args["Sesso"] == "F" and getArticleWoman(args["Attività"]) == "un&#32;")) and
                  "naturalizzato" or "naturalizzata")
        dumpText(SPACE)
        dumpWlink(getLinkNazionalita(args["NazionalitàNaturalizzato"]), args["NazionalitàNaturalizzato"])
    end

    if args["PostNazionalità"] then
        dumpText(args["PostNazionalità"])
    end
end

-- Traduzione in lua di [[Template:Bio]]
local function bio()
    local sortkey

    -- lettura configurazione
    cfg = mw.loadData("Modulo:Bio/Configurazione")
    
    -- parsifica i parametri e aggiunge eventuali categorie di errore 
    args = parseParams(mw.getCurrentFrame():getParent().args)

    -- prova a ottenere alcuni parametri mancanti da Wikidata
    if true and cfg.wikidata then
        checkWikidata()
    end

    -- le categorie sono aggiunte solo se la pagina è nel namespace principale (0)
    if mw.title.getCurrentTitle().namespace == 0 then
        -- imposta la magic word defaultsort
        if args["ForzaOrdinamento"] then
            sortkey = args["ForzaOrdinamento"]
        elseif args["Cognome"] and args["Nome"] then
            sortkey = args["Cognome"] .. "&#32;," .. args["Nome"]
        end
        if sortkey then
            mw.getCurrentFrame():preprocess("{{DEFAULTSORT:" .. sortkey .. "}}")
        end
        -- Categorie impostato a "no" disabilita la categorizzazione per attività
        if args["Categorie"] ~= "no" then
            addAttivitaCategories()
        end
        addNatiMortiCategories()
        dumpCategory(cfg.categorie["bot"])
    end

    addImmagine()
    addNomeCognome()
    addNascitaMorte()

    if args["PostCognomeVirgola"] then
        dumpText(",")
    end

    if args["FineIncipit"] ~= "," then
        dumpText(SPACE)
    end

    if args["FineIncipit"] and args["FineIncipit"] ~= "," then
        dumpText(args["FineIncipit"])
    else
        addAttivita()
    end

    if args["Punto"] ~= "no" then
        if args["FineIncipit"] ~= "e" and
           args["FineIncipit"] ~= "ed" and
           args["FineIncipit"] ~= ",=&#32;" then
            dumpText(".")
        end
    end

    return table.concat(textTable)
end

-- Entry-point per {{Bio/link attività}}
function p.linkAttivita(frame)
    return getLinkAttivita(frame:getParent().args[1])
end

-- Entry-point per {{Bio/link nazionalità}}
function p.linkNazionalita(frame)
    return getLinkNazionalita(frame:getParent().args[1])
end

-- Entry-point per {{Bio/plurale attività}}
function p.pluraleAttivita(frame)
    return getPluralAttivita(frame:getParent().args[1])
end

-- Entry-point per {{Bio/plurale nazionalità}}
function p.pluraleNazionalita(frame)
    return getPluralNazionalita(frame:getParent().args[1])
end

-- Entry-point per {{Bio}}
function p.bio(frame)
    return bio()
end

return p