Modul:Reference score: Forskjell mellom sideversjoner

Fra Wikisida.no
Hopp til navigering Hopp til søk
(Fjerner revisjon 21897647 av Haros (diskusjon))
(Fikser ref fra f. eks. "mai Mai 20197" til "7. mai 2019".)
Linje 37: Linje 37:
local value = claim.datavalue.value
local value = claim.datavalue.value
local presisjon = value.precision
local presisjon = value.precision
local aar,maaned,dag,fkr = splitTimestamp(value.time)
local aar,_,maaned,dag,fkr,_ = splitTimestamp(value.time)
local utstring = ''
local utstring = ''



Sideversjonen fra 9. okt. 2021 kl. 17:01

Dokumentasjon for denne modulen kan opprettes på Modul:Reference score/dok

---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
}
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

-- 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
	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