Module:MedicoInfobox: Difference between revisions

From determinar.ia.br - Determine suas informações
No edit summary
No edit summary
Line 1: Line 1:
local p = {}
local p = {}


local PROPRIEDADE_FOTO = 'P1'
-- ORDEM DE PRIORIDADE: aparecem primeiro, nessa ordem exata
local PRIORITY_ORDER = {
    'P10', -- Especialidade Médica
    'P11', -- Subespecialidade
    'P4',  -- Número de Registro Profissional
    'P14', -- Vínculo Profissional
    'P28', -- Logradouro
    'P29', -- Bairro
    'P36', -- Estado
    'P72', -- CEP
    'P76', -- Horário de Funcionamento
    'P23', -- Convênio Aceito
    'P19', -- Procedimento Realizado
    'P18', -- Condição Tratada
    'P13', -- Área de Atuação
    'P32', -- URL de Agendamento
    'P57', -- Redes Sociais
    'P39', -- Número de Estrelas no Doctoralia
    'P40', -- Número de dúvidas Respondidas Doctoralia
    'P60', -- Tempo de Experiência na Profissão
    'P77', -- Publicações Científicas
}


local function formatarValor(dv, propertyId)
-- CAMPOS TÉCNICOS: nunca aparecem no infobox (ficam só nos dados do Item)
     if dv.type == 'string' then
local HIDDEN = {
         if propertyId == PROPRIEDADE_FOTO then
    P38 = true, -- sem rótulo definido ainda — revisar antes de exibir
             return nil, dv.value
    P62 = true, -- Google Scholar ID
    P63 = true, -- ResearchGate Profile ID
    P64 = true, -- Doctoralia ID
    P66 = true, -- URN
    P67 = true, -- CURIE
    P68 = true, -- URI Canônica
    P70 = true, -- Token Canário
    P73 = true, -- Dentro do Escopo
    P74 = true, -- Fora do Escopo
    P75 = true, -- Google Maps CID
    P78 = true, -- Arquiteto de Conhecimento
    P71 = true, -- Município (oculto pois Q102 não tem rótulo pt-br ainda — ver nota)
}
 
-- P1 é a imagem, sempre tratada à parte (não entra na tabela genérica)
local IMAGE_PROPERTY = 'P1'
 
local function getPropertyLabel(pid)
    local propEntity = mw.wikibase.getEntity(pid)
    if not propEntity then return pid end
    local label = propEntity:getLabel('pt-br')
    if not label then label = propEntity:getLabel('en') end
    if not label then label = pid end
    return label
end
 
local function formatValue(snak)
     if not snak.datavalue then return nil end
    local datatype = snak.datavalue.type
    local value = snak.datavalue.value
    if not value then return nil end
 
    if datatype == 'wikibase-entityid' then
         local targetId = value.id
        local targetEntity = mw.wikibase.getEntity(targetId)
        if targetEntity then
             local label = targetEntity:getLabel('pt-br') or targetEntity:getLabel('en')
            if label then return label end
         end
         end
         return dv.value
         return targetId -- fallback: mostra o Q-number se o item de destino não tiver rótulo
     elseif dv.type == 'monolingualtext' then
 
         return dv.value.text
     elseif datatype == 'monolingualtext' then
     elseif dv.type == 'wikibase-entityid' then
         return value.text
         local id = dv.value.id
 
         local label = mw.wikibase.label(id) or id
     elseif datatype == 'quantity' then
        return '[[Item:' .. id .. '|' .. label .. ']]'
         local amount = value.amount
    elseif dv.type == 'quantity' then
         amount = amount:gsub('^%+', '')
         return dv.value.amount
         return amount
     elseif dv.type == 'time' then
 
         return dv.value.time
     elseif datatype == 'string' then
         return value
 
     else
     else
         return tostring(dv.value)
         return tostring(value)
     end
     end
end
end


function p.main(frame)
local function buildOrderedPropertyList(claims)
     local id = frame.args.ID or frame.args[1]
     local seen = {}
     local entity = mw.wikibase.getEntity(id)
     local ordered = {}


     if not entity then
     -- 1. prioridade primeiro, na ordem definida acima
        return '<strong>Item não encontrado: ' .. tostring(id) .. '</strong>'
    for _, pid in ipairs(PRIORITY_ORDER) do
        if claims[pid] and not HIDDEN[pid] and pid ~= IMAGE_PROPERTY then
            table.insert(ordered, pid)
            seen[pid] = true
        end
     end
     end


     local label = entity:getLabel('pt-br') or entity:getLabel('pt') or entity:getLabel('en') or id
    -- 2. tudo o mais que sobrar, em ordem numérica de P-number
     local description = entity:getDescription('pt-br') or entity:getDescription('pt') or ''
    --    (isto preserva o design genérico: propriedade nova aparece sozinha aqui)
     local rest = {}
    for pid, _ in pairs(claims) do
        if not seen[pid] and not HIDDEN[pid] and pid ~= IMAGE_PROPERTY then
            table.insert(rest, pid)
        end
    end
    table.sort(rest, function(a, b)
        return tonumber(a:sub(2)) < tonumber(b:sub(2))
    end)
     for _, pid in ipairs(rest) do
        table.insert(ordered, pid)
    end


     local imagem = nil
     return ordered
    local linhas = {}
end


    if entity.claims then
function p.main(frame)
        for propertyId, claims in pairs(entity.claims) do
    local id = frame.args.ID
            local propLabel = mw.wikibase.label(propertyId) or propertyId
    if not id then
            local valores = {}
        return '<strong class="error">Erro: parâmetro ID obrigatório, ex: {{Infobox Médico|ID=Q1}}</strong>'
    end


            for _, claim in ipairs(claims) do
    local entity = mw.wikibase.getEntity(id)
                local snak = claim.mainsnak
    if not entity then
                if snak and snak.datavalue then
        return '<strong class="error">Item não encontrado: ' .. tostring(id) .. '</strong>'
                    local formatado, arquivoImagem = formatarValor(snak.datavalue, propertyId)
    end
                    if arquivoImagem then
                        imagem = arquivoImagem
                    elseif formatado then
                        table.insert(valores, formatado)
                    end
                end
            end


            if propertyId ~= PROPRIEDADE_FOTO and #valores > 0 then
    local label = entity:getLabel('pt-br') or entity:getLabel('en') or id
                table.insert(linhas, { label = propLabel, valor = table.concat(valores, ', ') })
     local description = entity:getDescription('pt-br') or entity:getDescription('en') or ''
            end
        end
     end


     local html = mw.html.create('div'):addClass('infobox-medico')
     local html = mw.html.create('div'):addClass('infobox-medico')


     if imagem then
    -- Imagem (P1). Se sua lógica atual pra imagem for diferente desta,
         html:tag('div')
    -- mantenha a que já funciona e só copie o resto (prioridade/ocultação/pt-br).
            :addClass('infobox-medico-imagem')
     if entity.claims and entity.claims[IMAGE_PROPERTY] then
            :wikitext('[[File:' .. imagem .. '|280px|center]]')
         local imgClaim = entity.claims[IMAGE_PROPERTY][1]
        local imgValue = imgClaim.mainsnak.datavalue and imgClaim.mainsnak.datavalue.value
        if imgValue then
            local fileName = imgValue.fileName or imgValue
            html:tag('div'):addClass('infobox-medico-imagem')
                :wikitext('[[File:' .. fileName .. '|300px]]')
        end
     end
     end


     html:tag('div'):addClass('infobox-medico-titulo'):wikitext(label)
     html:tag('div'):addClass('infobox-medico-titulo'):wikitext(label)
     if description ~= '' then
     if description ~= '' then
         html:tag('div'):addClass('infobox-medico-descricao'):wikitext(description)
         html:tag('div'):addClass('infobox-medico-descricao'):wikitext(description)
     end
     end


     local tabela = html:tag('table'):addClass('infobox-medico-tabela')
     local tableTag = html:tag('table'):addClass('infobox-medico-tabela')
     for _, linha in ipairs(linhas) do
 
        local tr = tabela:tag('tr')
     if entity.claims then
        tr:tag('th'):wikitext(linha.label)
        local orderedPids = buildOrderedPropertyList(entity.claims)
        tr:tag('td'):wikitext(linha.valor)
        for _, pid in ipairs(orderedPids) do
            local propLabel = getPropertyLabel(pid)
            local values = {}
            for _, claim in ipairs(entity.claims[pid]) do
                local formatted = formatValue(claim.mainsnak)
                if formatted then
                    table.insert(values, formatted)
                end
            end
            if #values > 0 then
                local valueHtml
                if #values > 1 then
                    local ul = mw.html.create('ul')
                    for _, v in ipairs(values) do
                        ul:tag('li'):wikitext(v)
                    end
                    valueHtml = tostring(ul)
                else
                    valueHtml = values[1]
                end
                local row = tableTag:tag('tr')
                row:tag('th'):wikitext(propLabel)
                row:tag('td'):wikitext(valueHtml)
            end
        end
     end
     end



Revision as of 21:43, 1 August 2026

Documentation for this module may be created at Module:MedicoInfobox/doc

local p = {}

-- ORDEM DE PRIORIDADE: aparecem primeiro, nessa ordem exata
local PRIORITY_ORDER = {
    'P10', -- Especialidade Médica
    'P11', -- Subespecialidade
    'P4',  -- Número de Registro Profissional
    'P14', -- Vínculo Profissional
    'P28', -- Logradouro
    'P29', -- Bairro
    'P36', -- Estado
    'P72', -- CEP
    'P76', -- Horário de Funcionamento
    'P23', -- Convênio Aceito
    'P19', -- Procedimento Realizado
    'P18', -- Condição Tratada
    'P13', -- Área de Atuação
    'P32', -- URL de Agendamento
    'P57', -- Redes Sociais
    'P39', -- Número de Estrelas no Doctoralia
    'P40', -- Número de dúvidas Respondidas Doctoralia
    'P60', -- Tempo de Experiência na Profissão
    'P77', -- Publicações Científicas
}

-- CAMPOS TÉCNICOS: nunca aparecem no infobox (ficam só nos dados do Item)
local HIDDEN = {
    P38 = true, -- sem rótulo definido ainda — revisar antes de exibir
    P62 = true, -- Google Scholar ID
    P63 = true, -- ResearchGate Profile ID
    P64 = true, -- Doctoralia ID
    P66 = true, -- URN
    P67 = true, -- CURIE
    P68 = true, -- URI Canônica
    P70 = true, -- Token Canário
    P73 = true, -- Dentro do Escopo
    P74 = true, -- Fora do Escopo
    P75 = true, -- Google Maps CID
    P78 = true, -- Arquiteto de Conhecimento
    P71 = true, -- Município (oculto pois Q102 não tem rótulo pt-br ainda — ver nota)
}

-- P1 é a imagem, sempre tratada à parte (não entra na tabela genérica)
local IMAGE_PROPERTY = 'P1'

local function getPropertyLabel(pid)
    local propEntity = mw.wikibase.getEntity(pid)
    if not propEntity then return pid end
    local label = propEntity:getLabel('pt-br')
    if not label then label = propEntity:getLabel('en') end
    if not label then label = pid end
    return label
end

local function formatValue(snak)
    if not snak.datavalue then return nil end
    local datatype = snak.datavalue.type
    local value = snak.datavalue.value
    if not value then return nil end

    if datatype == 'wikibase-entityid' then
        local targetId = value.id
        local targetEntity = mw.wikibase.getEntity(targetId)
        if targetEntity then
            local label = targetEntity:getLabel('pt-br') or targetEntity:getLabel('en')
            if label then return label end
        end
        return targetId -- fallback: mostra o Q-number se o item de destino não tiver rótulo

    elseif datatype == 'monolingualtext' then
        return value.text

    elseif datatype == 'quantity' then
        local amount = value.amount
        amount = amount:gsub('^%+', '')
        return amount

    elseif datatype == 'string' then
        return value

    else
        return tostring(value)
    end
end

local function buildOrderedPropertyList(claims)
    local seen = {}
    local ordered = {}

    -- 1. prioridade primeiro, na ordem definida acima
    for _, pid in ipairs(PRIORITY_ORDER) do
        if claims[pid] and not HIDDEN[pid] and pid ~= IMAGE_PROPERTY then
            table.insert(ordered, pid)
            seen[pid] = true
        end
    end

    -- 2. tudo o mais que sobrar, em ordem numérica de P-number
    --    (isto preserva o design genérico: propriedade nova aparece sozinha aqui)
    local rest = {}
    for pid, _ in pairs(claims) do
        if not seen[pid] and not HIDDEN[pid] and pid ~= IMAGE_PROPERTY then
            table.insert(rest, pid)
        end
    end
    table.sort(rest, function(a, b)
        return tonumber(a:sub(2)) < tonumber(b:sub(2))
    end)
    for _, pid in ipairs(rest) do
        table.insert(ordered, pid)
    end

    return ordered
end

function p.main(frame)
    local id = frame.args.ID
    if not id then
        return '<strong class="error">Erro: parâmetro ID obrigatório, ex: {{Infobox Médico|ID=Q1}}</strong>'
    end

    local entity = mw.wikibase.getEntity(id)
    if not entity then
        return '<strong class="error">Item não encontrado: ' .. tostring(id) .. '</strong>'
    end

    local label = entity:getLabel('pt-br') or entity:getLabel('en') or id
    local description = entity:getDescription('pt-br') or entity:getDescription('en') or ''

    local html = mw.html.create('div'):addClass('infobox-medico')

    -- Imagem (P1). Se sua lógica atual pra imagem for diferente desta,
    -- mantenha a que já funciona e só copie o resto (prioridade/ocultação/pt-br).
    if entity.claims and entity.claims[IMAGE_PROPERTY] then
        local imgClaim = entity.claims[IMAGE_PROPERTY][1]
        local imgValue = imgClaim.mainsnak.datavalue and imgClaim.mainsnak.datavalue.value
        if imgValue then
            local fileName = imgValue.fileName or imgValue
            html:tag('div'):addClass('infobox-medico-imagem')
                :wikitext('[[File:' .. fileName .. '|300px]]')
        end
    end

    html:tag('div'):addClass('infobox-medico-titulo'):wikitext(label)
    if description ~= '' then
        html:tag('div'):addClass('infobox-medico-descricao'):wikitext(description)
    end

    local tableTag = html:tag('table'):addClass('infobox-medico-tabela')

    if entity.claims then
        local orderedPids = buildOrderedPropertyList(entity.claims)
        for _, pid in ipairs(orderedPids) do
            local propLabel = getPropertyLabel(pid)
            local values = {}
            for _, claim in ipairs(entity.claims[pid]) do
                local formatted = formatValue(claim.mainsnak)
                if formatted then
                    table.insert(values, formatted)
                end
            end
            if #values > 0 then
                local valueHtml
                if #values > 1 then
                    local ul = mw.html.create('ul')
                    for _, v in ipairs(values) do
                        ul:tag('li'):wikitext(v)
                    end
                    valueHtml = tostring(ul)
                else
                    valueHtml = values[1]
                end
                local row = tableTag:tag('tr')
                row:tag('th'):wikitext(propLabel)
                row:tag('td'):wikitext(valueHtml)
            end
        end
    end

    return tostring(html)
end

return p