Modul:Reference score
Utseende
---Module for chosing the best reference.
--@table for localization
local i18n = mw.loadData( 'Module:Reference score/i18n' )
-- @table for configuration
local conf = mw.loadData( 'Module:Reference score/conf' )
local labeltekst = {
["P50"] = "", -- forfatter
["P123"] = "", -- utgiver
["P248"] = "", -- nevnt i
["P577"] = "utgitt ", -- utgivelsesdato
["P813"] = "besøkt ", -- besøksdato
["P854"] = "", -- referanse-URL
["P2093"] = "" -- forfatternavn
}
local wait = {
["P577"] = true, -- utgivelsesdato
["P813"] = true, -- besøksdato
["P1683"] = true, -- sitat
["Pxxxx"] = true -- dummy
}
local checkLabel = {
["P1810"] = true, -- oppført som
["Pxxxx"] = true -- dummy
}
local unknownItem = 0
local done = {}
local reftxt = ""
local sep = ""
local function norskDatoFraClaim(claim)
if claim.snaktype ~= "value" then
return "ingen verdi"
end
local value = claim.datavalue.value
local presisjon = value.precision
local aar,_,maaned,dag,fkr,_ = splitTimestamp(value.time)
local utstring = ''
if presisjon == 11 then
utstring = string.format( '%s %s %s%s', dag, maaned, tonumber(aar) or aar, fkr )
elseif presisjon == 10 then
utstring = string.format( '%s %s%s', maaned, tonumber(aar) or aar, fkr )
elseif presisjon == 9 then
utstring = (tonumber(aar) or aar)..''..fkr
utstring = string.format( '%s%s', tonumber(aar) or aar, fkr )
elseif presisjon == 8 then
utstring = string.format( '%s-årene%s', math.floor(((tonumber(aar) or 0))/10)*10, fkr )
elseif presisjon == 7 then
utstring = string.format( '%s. århundre%s', math.floor(((tonumber(aar) or 0)+99)/100), fkr )
end
return mw.text.nowiki( utstring ).. kalender(value.calendarmodel)
end
function addRefTxt(pidLabel,refValue)
reftxt = reftxt .. sep .. " " .. pidLabel .. refValue
-- .. " ( " .. datatype .. " )"
sep = ", "
end
local function formatUrl(url)
local reftext = url
local j1 = string.find(reftext,'//',1,true)
if j1 then reftext = string.sub(reftext,j1+2,string.len(reftext)) else reftext = '' end
if reftext ~= '' then
local i1 = string.find(reftext,'/',1,true)
if i1 then reftext = string.sub(reftext,1,i1-1) end
else
reftext = url
end
return "[" .. url .. " " .. reftext .. "]"
end
local function formatItem(property)
local item = nil
if property[1].snaktype == "value" then
item = property[1].datavalue.value or nil
end
if item then
local value = item.id
local label = mw.wikibase.label( value )
local sitelink = mw.wikibase.sitelink( value )
if sitelink or label then
return mw.wikibase.formatValues(property)
end
unknownItem = unknownItem +1
return '[[d:' .. value .. '|' .. value .. ']]'
else
return "ingen verdi"
end
end
function fmtTitle(ref)
if done["P1476"] then
return
end
done["P1476"] = true
title = ref["P1476"] or nil
if title then
local refValue = "«" .. mw.wikibase.formatValues(title) .. "»"
if ref["P854"] then
refValue = "[" .. ref["P854"][1].datavalue.value .. " " .. refValue .. "]"
done["P854"] = true
end
addRefTxt("",refValue)
end
return
end
function fmtQuote(pid,ref)
if done[pid] then
return
end
done[pid] = true
local quote = ref[pid] or nil
if quote then
local refValue = "«" .. mw.wikibase.formatValues(quote) .. "»"
addRefTxt("",refValue)
end
return
end
function fmtTekst(pid,ref)
if done[pid] then
return
end
done[pid] = true
local tekst = ref[pid] or nil
if tekst then
local refValue = mw.wikibase.formatValues(tekst)
addRefTxt("",refValue)
end
return
end
-- Ignore cases where the value is just the label.
function fmtLlabelCheck(pid,ref)
if done[pid] then
return
end
done[pid] = true
local refItem = ref[pid] or nil
if refItem then
local refValue = mw.wikibase.formatValues(refItem)
local pidLabel = labeltekst[pid] or mw.wikibase.getLabel(pid) .. " "
local label = mw.wikibase.label()
local refString = ref[pid][1].datavalue.value
if not (label == refString ) then
addRefTxt(pidLabel,refValue)
end
end
return
end
function fmtItem(pid,ref)
if done[pid] then
return
end
local property = ref[pid] or nil
if property then
local pidLabel = labeltekst[pid] or mw.wikibase.getLabel(pid) .. " "
local refValue = formatItem(property)
addRefTxt(pidLabel,refValue)
end
done[pid] = true
end
function fmtDato(pid,ref)
if done[pid] then
return
end
local property = ref[pid] or nil
if property then
local pidLabel = labeltekst[pid] or mw.wikibase.getLabel(pid) .. " "
local refValue = norskDatoFraClaim(property[1])
addRefTxt(pidLabel,refValue)
end
done[pid] = true
end
function fmtMisc(ref)
for pid, property in pairs(ref) do
if checkLabel[pid] then
fmtLlabelCheck(pid,ref)
elseif not done[pid] and not wait[pid] then
local datatype = property[1].datatype or "xxx"
local pidLabel = labeltekst[pid] or mw.wikibase.getLabel(pid) .. " "
local refValue = mw.wikibase.formatValues(property)
if property[1].snaktype ~= "value" then
refValue = datatype .. ": Ingen verdi"
else
if datatype == 'url' then
refValue = formatUrl(property[1].datavalue.value)
elseif datatype == 'time' then
refValue = norskDatoFraClaim(property[1])
elseif datatype == 'wikibase-item' then
refValue = formatItem(property)
elseif datatype == 'commonsMedia' then
refValue = string.format([[
<div class="mw-collapsible mw-collapsed">
<div>%s</div>
<div class="mw-collapsible-content">%s</div>
</div>
]],property[1].datavalue.value ,refValue)
end
end
addRefTxt(pidLabel,refValue)
done[pid] = true
end
end
end
function fmtSingle(ref)
local num = 0
for pid, property in pairs(ref) do
num = num+1
end
if num~=1 then
return false
end
if not ref["P248"] then
return false
end
local P248 = ref["P248"]
local item = nil
if P248[1].snaktype == "value" then
item = P248[1].datavalue.value or nil
end
if item then
local value = item.id
local label = mw.wikibase.label( value )
local description = mw.wikibase.description( value )
local sitelink = mw.wikibase.sitelink( value )
if label and not sitelink then
local txt ="«" .. label .. "», " .. description
addRefTxt("",txt)
return true
end
end
return false
end
function fmtnew(ref)
reftxt = ""
sep = ""
local args = mw.getCurrentFrame():getParent().args
if args and args["wikidatatesting"] == "ref" then
if fmtSingle(ref) then
return reftxt
end
end
local refValue = nil
fmtItem("P123",ref) -- utgiver
fmtItem("P248",ref) -- nevnt i
fmtItem("P50",ref) -- fortatter
fmtTekst("P2093",ref) -- fortatternavn
fmtTitle(ref)
fmtMisc(ref)
fmtDato("P577",ref) -- utgivelsesdato
fmtDato("P813",ref) -- besøksdato
fmtQuote("P1683",ref) -- sitat
return reftxt .. "<sup><small>[Hentet fra Wikidata]</small></sup>"
-- return mw.wikibase.formatValues( ref )
-- "<pre>" .. mw.text.jsonEncode(ref, mw.text.JSON_PRETTY) .. "</pre>"
end
function fmt(ref)
done = {}
reftxt = ""
sep = ""
-- local args = mw.getCurrentFrame():getParent().args
-- if args and args["wikidatatesting"] == "ref" then
return fmtnew(ref)
-- end
-- return mw.wikibase.formatValues( ref )
end
-- @table for export
local h = {}
--- Make a list of categories.
-- Note this probably should be moved out of this module.
-- @tparam number num of references
-- @treturn table of strings
function h.makeCategories( num )
local t = {}
if num and num > 0 then
table.insert( t, mw.message.newRawMessage( i18n['category-pages-using-references-from-statement'] ):plain() )
if num == 1 then
table.insert( t, mw.message.newRawMessage( i18n['category-pages-using-single-reference-from-statement'] ):plain() )
elseif num > 1 then
table.insert( t, mw.message.newRawMessage( i18n[string.format('category-pages-using-%d-references-from-statement', num )] ):plain() )
end
end
return t
end
--- Generate a language score for the claims.
-- @tparam table claims to process
-- @treturn number best score
function h.scoreLanguage( claims )
local keep = conf.lowScore
for _,v in ipairs( claims ) do
if v.snaktype == 'value'
and v.datatype == 'monolingualtext'
and v.datavalue.type == 'monolingualtext' then
local score = conf.languageScore[v.datavalue.value.language]
if score then
-- note that higher number means lower prority
keep = (keep < score) and keep or score
end
end
end
return keep
end
--- Generate a root domain score for the claims.
-- @tparam table claims to process
-- @treturn number best score
function h.scoreDomain( claims )
local keep = conf.lowScore
for _,v in ipairs( claims ) do
if v.snaktype == 'value'
and v.datatype == 'url'
and v.datavalue.type == 'string' then
local uri = mw.uri.new( v.datavalue.value )
local root = string.match( uri.host, '%.([^.]+)$' )
local score = conf.domainScore[root]
if score then
-- note that higher number means lower prority
keep = (keep < score) and keep or score
end
end
end
return keep
end
--- Generate an entity score for the claims.
-- @tparam table claims to process
-- @treturn number best score
function h.scoreEntity( claims )
local keep = conf.lowScore
for _,v in ipairs(claims) do
if v.snaktype == 'value'
and v.datatype == 'wikibase-item'
and v.datavalue.type == 'wikibase-entityid' then
local score = conf.entityScore[v.datavalue.value.id]
if score then
-- note that higher number means lower prority
keep = (keep < score) and keep or score
end
end
end
return keep
end
--- Generate a property score for the claims.
-- @tparam table claims to process
-- @treturn number best score
function h.scoreProperty( claims )
local keep = conf.lowScore
for _,v in ipairs(claims) do
-- strictly speaking this could be dropped as all should be equal
local score = conf.propertyScore[v.property]
if score then
-- note that higher number means lower prority
keep = (keep < score) and keep or score
end
end
return keep
end
--- Generate scores for the references.
-- Note that the generated list is sparse, and is using false as marker.
-- @tparam table list to process
-- @treturn table of references
function h.score( list )
-- make sure we have a continuous target list
local t = {}
for i=1,conf.lowScore do
t[i] = false
end
-- loop over the source list
for _,v in ipairs( list ) do
-- is the reference excluded?
local exclude = false
for _,w in ipairs( conf.exclude ) do
if v.snaks and v.snaks[w] then
exclude = true
break
end
end
-- only process included (ie not excluded) references
if not exclude then
local keep = conf.lowScore
-- try language of "title"
if v.snaks.P1476 then
local score = h.scoreLanguage(v.snaks.P1476)
if score then
-- note that higher number means lower prority
keep = (keep < score) and keep or score
end
end
-- try root domain of "reference url"
if v.snaks.P854 then
local score = h.scoreDomain(v.snaks.P854)
if score then
-- note that higher number means lower prority
keep = (keep < score) and keep or score
end
end
-- try reference to entity
for _,w in pairs(v.snaks) do
local score = h.scoreEntity( w )
if score then
-- note that higher number means lower prority
keep = (keep < score) and keep or score
end
end
-- some properties that usually imply somewhat quality
for _,w in pairs(v.snaks) do
local score = h.scoreProperty( w )
-- note that higher number means lower prority
keep = (keep < score) and keep or score
end
table.insert( t, keep, v )
end
end
return t
end
--- Compact the sparse list.
-- Note that the input list is sparse, and using false as marker.
-- @tparam table list of any
-- @tparam[limit=conf.maxRefs] nil|number limit for truncation of list
-- @treturn table
function h.compact( list, limit )
limit = limit or conf.maxRefs
local t = {}
local counter = 0
for _,v in ipairs( list ) do
if v then
counter = counter + 1
if limit and counter <= limit then
table.insert( t, v )
elseif not limit then
table.insert( t, v )
end
end
end
return t
end
--- Render references.
-- @tparam table frame
-- @tparam table list of references
-- @treturn string
function h.render( frame, list )
local scored = h.score( list or {} )
local compacted = h.compact( scored )
local wiki = ''
local hits = 0
for i,v in ipairs( compacted ) do
hits = hits + 1
local keys = {}
for k,_ in pairs( v.snaks ) do
table.insert( keys, k )
end
local snaks = {}
for _,k in pairs( mw.wikibase.orderProperties( keys ) ) do
-- lua keeps injection order
snaks[k] = v.snaks[k]
end
-- hash will merge similar entries
-- local content = mw.wikibase.formatValues( snaks )
local content = fmt(snaks)
local attrs = { name = string.format( 'hash-%s', v.hash ) }
wiki = wiki .. frame:extensionTag( 'ref', content, attrs )
end
for _,v in ipairs( h.makeCategories( hits ) ) do
wiki = wiki .. mw.ustring.format('[[Category:%s]]', v )
end
if unknownItem >0 then
wiki = wiki .. "[[Kategori:Artikler hvor referanser mangler oversettelse]]"
end
return wiki
end
return h