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 | -- 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 | -- CAMPOS TÉCNICOS: nunca aparecem no infobox (ficam só nos dados do Item) | ||
if | local HIDDEN = { | ||
P38 = true, -- sem rótulo definido ainda — revisar antes de exibir | |||
return | 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 | return targetId -- fallback: mostra o Q-number se o item de destino não tiver rótulo | ||
elseif | |||
return | elseif datatype == 'monolingualtext' then | ||
elseif | return value.text | ||
local | |||
elseif datatype == 'quantity' then | |||
local amount = value.amount | |||
amount = amount:gsub('^%+', '') | |||
return | return amount | ||
elseif | |||
return | elseif datatype == 'string' then | ||
return value | |||
else | else | ||
return tostring( | return tostring(value) | ||
end | end | ||
end | end | ||
function | local function buildOrderedPropertyList(claims) | ||
local | local seen = {} | ||
local | local ordered = {} | ||
if not | -- 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 | end | ||
local | -- 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') | local html = mw.html.create('div'):addClass('infobox-medico') | ||
if | -- 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). | ||
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 | 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 | local tableTag = html:tag('table'):addClass('infobox-medico-tabela') | ||
for _, | |||
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 | 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
