Hopp til innhold

Modul:WikidataListe/test

Fra Wikipedia, den frie encyklopedi


local conf = mw.loadData( 'Module:WikidataListe/test/conf' )
local WikidataDato = require( 'Module:WikidataDato' )
local refs = require 'Module:Reference score'
local p = {}

local kvalUtelat = conf.kvalUtelat
local kvalProp = conf.kvalProp

-- The value given to the properties in the table are not significant, they just need to exist
local useReferences = {
	["P19"] = "fødested",		-- fødested
	["P20"] = "dødssted",		-- dødssted
	["P22"] = "far",			-- far
	["P25"] = "mor",			-- mor
	["P26"] = "ektefelle",		-- ektefelle
	["P40"] = "barn",			-- barn
	["P69"] = "utdannet ved",	-- utdannet ved
	["P84"] = "arkitekt",		-- arkitekt
	["P102"] = "medlem av politisk parti",	-- medlem av politisk parti
	["P106"] = "beskjeftigelse",	-- beskjeftigelse
	["P119"] = "gravsted",			-- gravsted
	["P161"] = "medvirkende",		-- medvirkende
	["P166"] = "utmerkelse",		-- utmerkelse
	["P3373"] = "søsken"			-- søsken
}

local useCountry = {
	["P19"] = "fødested",		-- fødested
	["P20"] = "dødssted"		-- dødssted
}	

local linktext = 'Rediger på Wikidata'
local linktarget = 'https://www.wikidata.org/wiki/%s?uselang=%s#%s'

local kollapsNum = 5

local kategori = nil
local kategorier = ""

function addKat(kat)
	kategorier = kategorier .. kat
end

-- filter(function, table)
function filter(func, tbl)
	local newtbl= {}
	for i, v in pairs(tbl) do
		if func(v) then
			table.insert(newtbl, v)
		end
	end
	return newtbl
 end

function makeLink(label,sitelink,first,link,langlab)
	if first and label then
		local lang = mw.language.getContentLanguage()
		label = lang:ucfirst( label )
	end

	if not link then
		-- Vi ønsker kun tekst, ikke wikilenke
		if label then
			return label
		end
		return ''
	end

	if label and sitelink then
		return '[[' .. sitelink .. '|' .. label .. ']]'
	end
	if label and not sitelink then
		local ll = ""
		if langlab and langlab ~= "nb" then
			ll = " (" .. langlab .. ")"
			--addKat("[[Kategori:Wikidata testing]]")
		end
		return label .. ll
	end
	if sitelink and not label then
		return '[[' .. sitelink .. ']]'
	end

	return ''
end
function kollaps(num)
	if kollapsNum>0 then
		if num>kollapsNum then
			return true
		end
	end
	return false
end

-- Returns an array of non-deprecated claims for the given property.
-- If there's no Wikidata entity or no claims, an empty array is returned.
function getBestStatements( property, qid )
	assert( property )

	local entity = mw.wikibase.getEntity(qid)
	if not entity then
		return {}
	end
	return entity:getBestStatements(property)

end

function getOkStatements(pid,qid)
	local entity = mw.wikibase.getEntity(qid)
	if not entity then
		return {}
	end
	local claims =  entity:getAllStatements(pid)
	local tbl = {}
	for i,claim in ipairs(claims) do
		if claim.rank == "normal" or claim.rank == "preferred" then
			table.insert(tbl,claim)
		end
	end
	return tbl
end

function hasQualifer( claim, qualifier )
	assert( claim )
	assert( qualifier )

	local qualifiers = claim.qualifiers or {}
	local snaks = qualifiers[qualifier] or {}
	
	return not not snaks[1]
end

function isStrange( snak )
	if not snak then
		return nil
	end

	return snak.snaktype == 'novalue'
		or snak.snaktype == 'somevalue'
		or nil
end

function getStrange( snak )
	return (snak.snaktype == 'novalue' and 'ingen')
		or (snak.snaktype == 'somevalue' and 'ukjent')
		or nil
end

function getQualifier( claim, qualifier, strip )
	if not claim.qualifiers then
		return nil
	end
	
	local qualifiers = claim.qualifiers or {}
	if not qualifiers[qualifier] then
		return nil
	end
	
	local snaks = qualifiers[qualifier] or {}
	if not snaks[1] then
		return nil
	end
	
	local snak = snaks[1] or {}
	if isStrange( snak ) then
		return getStrange( snak )
	end
	
	if not strip then
		return mw.wikibase.formatValue( snak )
	end
	
	-- this is to simple for more complex cases
	return tostring( mw.wikibase.formatValue( snak ) ):gsub("%b<>", "")
end

function formatYearQualifier(claim, qualifier)
	assert( claim )
	assert( qualifier )

	local snaks = ( claim.qualifiers or {} )[qualifier] or {}
	if not snaks[1] then
		return nil
	end

	local snak = snaks[1] or {}
	if isStrange( snak ) then
		return getStrange( snak )
	end

	return WikidataDato.aarFraClaim( snak )
end

-- Returns either "ingen", "ukjent", "" or "Qxxxxxx"
function getValue(claim)
	assert( claim )

	local mainsnak = claim.mainsnak or {}
	if isStrange( mainsnak ) then
		return getStrange( mainsnak )
	end

	-- check datatype
	if mainsnak.datatype ~= 'wikibase-item' then
		return nil
	end
	
	local datavalue = mainsnak.datavalue or {}
	if datavalue.type ~= 'wikibase-entityid' then
		return nil
	end
	
	local value = datavalue.value or {}
	if value['entity-type'] ~= 'item' then
		return nil
	end

	-- at this point there should be an ordinary value, but be safe
	return 'Q' .. ( value["numeric-id"] or 'xxxx')
end

function formatValue(value, first, link)
	assert( value )
	--assert( first )
	
	-- setter link til true som default hvis ingen verdi er angitt
	if type( link ) ~= 'boolean' then
		link = true
	end

	if string.sub(value, 1, 1) ~= "Q" then
		-- Verdien er enten "ukjent" eller "ingen"
		return string.format("''%s''", value)
	end

	local label = mw.wikibase.label( value )
	local sitelink = mw.wikibase.sitelink( value )
	if first and label then
		local lang = mw.language.getContentLanguage()
		label = lang:ucfirst( label )
	end

	if not link then
		-- Vi ønsker kun tekst, ikke wikilenke
		if label then
			return label
		end
		return ''
	end

	if label and sitelink then
		return '[[' .. sitelink .. '|' .. label .. ']]'
	end
	if label and not sitelink then
		return label
	end
	if sitelink and not label then
		return '[[' .. sitelink .. ']]'
	end

	return ''
end

function formatTimePeriod( claim, first, second )
	local startYear = formatYearQualifier(claim, first)  -- fra dato
			or formatYearQualifier(claim, 'P1319') -- tidligste dato
			or '' -- all fail
	--do return mw.dumpObject(claim.qualifiers['P1326']) end
	local startTitle = (hasQualifer(claim, first) and getQualifier(claim, first, true))
			or (hasQualifer(claim, 'P1319') and getQualifier(claim, 'P1319', true))
			or nil
	local endYear = formatYearQualifier(claim, second)  -- til dato
			or formatYearQualifier(claim, 'P1326') -- seneste dato
			or '' -- all fail
	local endTitle = (hasQualifer(claim, second) and getQualifier(claim, second, true))
			or (hasQualifer(claim, 'P1326') and getQualifier(claim, 'P1326', true))
			or nil
	local asterix = mw.html.create( 'sup' ):wikitext( '*' )
	if startTitle then
		local useFallback = (first == 'P1319') or not hasQualifer(claim, first)
		startYear = mw.html.create( 'span' )
			:attr( 'title', string.format("%s: %s", mw.wikibase.getLabel( useFallback and 'P1319' or first ), startTitle ))
			:wikitext( startYear .. (useFallback and tostring( asterix ) or ''))
	end
	if endTitle then
		local useFallback = (second == 'P1326') or not hasQualifer(claim, second)
		endYear = mw.html.create( 'span' )
			:attr( 'title', string.format("%s: %s", mw.wikibase.getLabel( useFallback and 'P1326' or second ), endTitle ))
			:wikitext( endYear .. (useFallback and tostring( asterix ) or ''))
	end
	return string.format("(%s–%s)", tostring(startYear), tostring(endYear))
end

function formatTimePoint( claim, prop )
	if prop == "P813" then -- P813 (besøksdato) skal inn i sjekkliste etter omskrivning av kallende funksjon
		addKat("[[Kategori:Wikidata testing]]")
	end
	local pointYear = formatYearQualifier(claim, prop)
			or '' -- all fail
	local pointTitle = (hasQualifer(claim, prop) and getQualifier(claim, prop, true))
			or nil
	if pointYear == "" then
		addKat("[[Kategori:Wikidata testing]]")
		pointYear = pointTitle
	end
	if pointTitle then
		pointYear = mw.html.create( 'span' )
			:attr( 'title', string.format("%s: %s", mw.wikibase.getLabel( prop ), pointTitle ))
			:wikitext( pointYear )
	end
	return string.format("(%s)", tostring(pointYear))
end

function formatEdit( qid, langCode, prop )
	if not qid then
		return ''
	end

	local link = mw.ustring.format( linktarget, qid, langCode, prop )

	local text = '[[File:OOjs UI icon edit-ltr-progressive.svg'
		.. '|frameless|text-top|10px'
		.. '|alt=' .. mw.text.nowiki( linktext )
		.. '|link=' .. mw.text.nowiki( link )
		.. '|' .. mw.text.nowiki( linktext )
		.. ']]'

	local html = mw.html.create( 'span' )
		:addClass( 'wb-edithandle' )
		-- @todo this must be adjusted
		-- :attr( 'data-bridge-edit-flow', 'single-best-value' )
		:wikitext( text )

	return tostring( html )
end

-- Returns all values from Wikidata for the given property
-- If no values are found, an empty string is returned.
function getFormattedValues(frame, prop, param, link,calcRefs,qid)
	local claims = getBestStatements(prop,qid)

	local i = 0
	local manglerOversettelse = false
	local formattedValues = {}
	
	for i, claim in ipairs(claims) do
		local value = getValue(claim)
		if value then
			local formattedValue = formatValue(value, i == 1, link)

			if formattedValue == '' then
				-- Målet har ikke en etikett på norsk bokmål, ei heller en artikkel på nowiki.
				-- Vi skriver ut en lenke til Wikidata for å gjøre det enkelt å legge til en etikett.
				-- For vanlige lesere kan det imidlertid være forvirrende med en Wikidata-lenke,
				-- så det er ikke helt optimalt. Vi marker derfor også at artikkelen skal legges til
				--  i en vedlikeholdskategori.
				manglerOversettelse = true
				formattedValue = "[[d:" .. value .. '|' .. value .. ']]'
			end
			
			if useCountry[prop] then
				if (hasQualifer(claim, 'P17') or hasQualifer(claim, 'P131')) then
				
					local country = getQualifier(claim,"P17")
					if not country or country == "" then
						country = getQualifier(claim,"P131")
					end
					if country and country ~= '' then
						formattedValue = formattedValue .. ', ' .. country
						.. "[[Kategori:Artikler hvor sted presiseres med kvalifikator fra Wikidata]]"
					end
				end
			end

			-- Dette er egentlig valg av en algoritme, dvs det burde skrives som et pattern
			if hasQualifer(claim, 'P523') or hasQualifer(claim, 'P524') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P523', 'P524' )
			elseif hasQualifer(claim, 'P580') or hasQualifer(claim, 'P582') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P580', 'P582' )
			elseif hasQualifer(claim, 'P729') or hasQualifer(claim, 'P730') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P729', 'P730' )
			elseif hasQualifer(claim, 'P2031') or hasQualifer(claim, 'P2032') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P2031', 'P2032' )
			elseif hasQualifer(claim, 'P3415') or hasQualifer(claim, 'P3416') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P3415', 'P3416' )
			elseif hasQualifer(claim, 'P575') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P575' )
			elseif hasQualifer(claim, 'P585') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P585' )
			elseif hasQualifer(claim, 'P606') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P606' )
			elseif hasQualifer(claim, 'P813') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P813' )
			elseif hasQualifer(claim, 'P1191') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P1191' )
			elseif hasQualifer(claim, 'P1249') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P1249' )
			elseif hasQualifer(claim, 'P3999') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P3999' )
			elseif hasQualifer(claim, 'P1319') or hasQualifer(claim, 'P1326') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P1319', 'P1326' )
			end

			if formattedValue ~= '' then
				local tmp = nil
				if  calcRefs == 'Y' and useReferences[prop]
				then
					tmp = refs.render(frame, claim.references)
				end
				table.insert(formattedValues, formattedValue..(tmp or ''))
			end
			
		end
	end

	local resultat = table.concat(formattedValues, ", ")

	local qid = mw.wikibase.getEntityIdForCurrentPage()
	local langCode = mw.language.getContentLanguage():getCode()

	if #formattedValues > 0 then
		resultat = resultat .. formatEdit( qid, langCode, prop )
	end

	-- use of # to get count will fail in the future
	if kollaps(#formattedValues) then
		resultat = string.format([[
			<div class="mw-collapsible mw-collapsed">
				<div class="sentrert">%s oppføringer</div>
				<div class="mw-collapsible-content">%s</div>
			</div>
		]], #formattedValues, resultat)
	end

	if manglerOversettelse then
		resultat = resultat .. "[[Kategori:Artikler hvor " .. param .. " mangler oversettelse]]"
	end

	return resultat
end

function getFrameValue(frame, params)
	local args = frame.args
	if args[1] == nil then
		local pFrame = frame:getParent();
		args = pFrame.args;
		for k,v in pairs( frame.args ) do
			args[k] = v;
		end
	end
	
	-- params kan være én enkelt verdi eller flere verdier adskilt med komma.
	-- F.eks. vil "religion,livssyn" sjekke både "religion" og "livssyn".
	for param in mw.text.gsplit( params, ',', true ) do
		 if args[param] then
			return mw.text.trim( args[param] )
		 end
	end
	return ""
end

function _strip( str )
	return string.sub( str, 2 , string.len( str )-1 )
end

function strip( str )
	local lang = mw.language.getContentLanguage()
	-- Fjern mest mulig formatering fra den lokale verdien
	local stripped = str:gsub("<span[^>]-wb%-edithandle[^>]*>.-</span>", "")
			:gsub("%[%[([^%[%]%{%}%|]+)%|([^%[%]%{%}%|]+)%]%]", "%2")
	stripped = stripped:gsub("%b<>", "")
	local last = nil
	repeat
		last = stripped
		stripped = stripped:gsub( "(%b[])", _strip )
				:gsub( "(%b{})", _strip ) -- not sure if this should be escaped
				:gsub( "(%b())", _strip )
	until ( last == stripped )
	stripped = stripped:gsub("''+", "")
			:gsub("^%s+", "")
			:gsub("%s+$", "")
			:gsub("(%s)%s+", "%1")
	stripped = lang:uc(stripped)
	return stripped
end

function velg(frame, prop, param, link, qid)
	local verdiFraFrame = getFrameValue(frame, param)
	if verdiFraFrame == "uten" then
		-- Hvis malargumentet er satt til "uten" betyr det at det ikke er ønskelig
		-- at feltet vises, selv om det finnes data på Wikidata.
		return "[[Kategori:Artikler hvor " .. param .. " spesifisert som uten]]"
	end
    local calcRefs = 'Y'	
	if verdiFraFrame ~= '' then
		-- Hvis malargumentet er satt til en lokal verdi betyr det at det ikke er ønskelig
		-- at feltet vises med lokal data, selv om det finnes data på Wikidata.
		-- Ikke beregn referanser for at de ikke skal komme med i referanselisten
		-- Lag Wikidata resultatene slik at det kan sammenlignes og lages vedlikeholdkategorier
		calcRefs = 'N'
	end

	local verdiFraWikidata = getFormattedValues(frame, prop, param, link,calcRefs,qid)
	if verdiFraWikidata == "" then
		-- No value at Wikidata.
		if verdiFraFrame == "" then
			return ""
		end
		return verdiFraFrame .. "[[Kategori:Artikler hvor " .. param .. " mangler på Wikidata]]"
	end

	if verdiFraFrame == "" then
		if verdiFraWikidata == "" then
			return ""
		end
		return verdiFraWikidata .. "[[Kategori:Artikler hvor " .. param .. " hentes fra Wikidata]]"
	end

	if strip(verdiFraFrame) == strip(verdiFraWikidata) then
		-- Den lokale verdien er helt lik Wikidata-verdien
		return verdiFraWikidata -- .. "[[Kategori:Artikler hvor " .. param .. " samme som på Wikidata]]"
	end

	-- Den lokale verdien er ikke *helt* lik Wikidata-verdien, men vi vet ikke om det er
	-- snakk om betydningsforskjeller.
	return verdiFraFrame .. "[[Kategori:Artikler hvor " .. param .. " forskjellig fra Wikidata]]"
end

function rad( frame, prop, param, link, displayName, qid )
	assert( frame )
	local lang = mw.language.getContentLanguage()
	local verdiFraFrame = getFrameValue( frame, param )
	local value = velg( frame, prop, param, link, qid )
	displayName = displayName or lang:ucfirst(param)
	if verdiFraFrame == "uten" then
		-- I dette tilfellet har velg() returnert en kategori av typen
		-- [[Kategori:Artikler hvor {param} spesifisert som uten]].
		-- Vi sender denne videre.
		return value
	end
	if value == "" then
		return ""
	end
	return string.format([[
		<tr class="rad" valign="top">
			<th colspan="2" class="nowrap">%s</th>
			<td colspan="2">%s</td>
		</tr>
	]], displayName, value)
end

function p.radOld(frame)
	assert( frame )
	if frame.args['ref'] then
		useReferences[frame.args['wdp']] = "frame.args['param']"
	end
    local qid = nil
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end
    
	return rad(frame, frame.args['wdp'], frame.args['param'], nil, frame.args['tekst'], qid)
end
function p.values(frame)
	assert( frame )
	if frame.args['ref'] then
		useReferences[frame.args['wdp']] = "frame.args['param']"
	end
	if frame.args['kollaps'] then
    	kollapsNum = tonumber(frame.args['kollaps'])
    end
    local qid = nil
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end

	return velg(frame, frame.args['wdp'], frame.args['param'], true, qid)
end


-- nye metoder


local ucfirst = "1"
local present = "1"

local sprakNb = {
	["nb"] = "bokmål",
}
local sprakNo = {
	["nb"] = "",     -- bokmål
	["nn"] = " ([[nynorsk|nn]])",
	["se"] = " ([[nordsamisk|se]])",
}
log = ""

local datoForEgenskap = {
	["P19"] = "P569",
	["P20"] = "P570",
}
function filterClaimsByDate(claims,date,precision)
	local claims2 = {}
	for i,claim in ipairs(claims) do
		if okDate(claim,date,precision,"P580",1) then
			log = log .. "<br />P580:" .. date .. "  -> claims2"
			table.insert(claims2,claim)
		end
	end
	local claims3 = {}
	for i,claim in ipairs(claims2) do
		if okDate(claim,date,precision,"P582",-1) then
			log = log .. "<br />P582:" .. date .. "  -> claims3"
			table.insert(claims3,claim)
		end
	end

	local claims4 = {}
	for i,claim in ipairs(claims3) do
		if okDate(claim,date,precision,"P585",0) then
			log = log .. "<br />P585:" .. date .. "  -> claims4"
			table.insert(claims4,claim)
		end
	end
	
	return claims4
end

function getDatov(claimsDate)
	for i, claimDate in ipairs(claimsDate) do
		local snakDate = claimDate.mainsnak
		local timestamp = snakDate.datavalue.value.time
		local presisjon = snakDate.datavalue.value.precision
		return timestamp,presisjon
	end
	return "1","1"
end

function ref(txt)
	return "" -- txt
end

slutt = {}
slutt[11] = 11
slutt[10] = 8
slutt[9]  = 5


-- fungerer kun for datoer etter år null.
function cmpTime(time1,precision1,time2,precision2)
	if not time1 or not time2 then
		return 0
	end
	local prec = math.min(precision1,precision2)
	if not slutt[prec] then
		return 0
	end
	local str2 = string.sub(time2,2,slutt[prec])
	local str1 = string.sub(time1,2,slutt[prec])
	--log = log .. date .. " " .. pr1 .. "  " .. time .. "  "  .. pr2 .. "<br/>"
	if str1 > str2 then
		log = log .. "cmp: " .. str1 .. " " .. str2 .. " 1<br/>"
		return -1
	end
	if str1 == str2 then
		log = log .. "cmp: " .. str1 .. " " .. str2 ..  " 0<br/>"
		return 0
	end
	if str1 < str2 then
		log = log .. "cmp: " .. str1 .. " " .. str2 ..  " -1<br/>"
		return 1
	end
	return 0
end

function cmpDate(claim,date,precision,pid)
	local qu = claim.qualifiers
	if not qu then
		return 0
	end
	datepid = qu[pid] or nil
	--local snak = datepid or nil
	if datepid and datepid[1].snaktype == "value" then
		local time = datepid[1].datavalue.value.time
		local pr2 = tonumber(datepid[1].datavalue.value.precision)
		local pr1 = tonumber(precision)
		local prec = math.min(pr2,pr1)
		if not slutt[prec] then
			return 0
		end
		local str2 = string.sub(date,2,slutt[prec])
		local str1 = string.sub(time,2,slutt[prec])
		--log = log .. date .. " " .. pr1 .. "  " .. time .. "  "  .. pr2 .. "<br/>"
		if str1 > str2 then
			
			log = log .. "cmp: " .. str1 .. " " .. str2 .. " 1<br/>"
			return -1
		end
		if str1 == str2 then
			log = log .. "cmp: " .. str1 .. " " .. str2 ..  " 0<br/>"
			return 0
		end
		if str1 < str2 then
			log = log .. "cmp: " .. str1 .. " " .. str2 ..  " -1<br/>"
			return 1
		end
		return 0
	end
	log = log .. "novalue " .. " 0<br/>"
	return 0
end
function okDate(claim,date,precision,pid,mode)
	local cmp = cmpDate(claim,date,precision,pid)
	if cmp == 0 or cmp == mode then
		return true
	end
	return false
end
function filterByDate(pid,pidDate,qid,qidDate)
	local claims = getOkStatements(pid,qid)
--	log = log .. "claims:  " .. dump(claims)
	local claimsDate = getOkStatements(pidDate,qidDate)
--	log = log .. "claimsDate:  " .. pidDate .. "  " .. dump(qidDate) .. dump(claimsDate)
	local date,precision = getDatov(claimsDate)
--	log = log .. "date: " .. date .. "  presisjon: " .. precision .. "  qid: " .. qid .. "  pid: " .. pid .. "<br/>" 
	local claims2 = filterClaimsByDate(claims,date,precision)
	-- .. "<pre>" .. mw.text.jsonEncode(claimsDate, mw.text.JSON_PRETTY) .. "</pre><br />" 
	return claims2
end

function placeStatus(pidStart,pidSlutt,qid,atDate,atDatePrecision)
	if true then
	--	return pidStart .. " " .. pidSlutt .. " " .. qid .. " " .. dump(atDate) .. " " .. dump(atDatePrecision)
	end
	local etablert = getOkStatements(pidStart,qid)
	local startDate,startPrecision = getDatov(etablert)
	local cmpStart = cmpTime(atDate,atDatePrecision,startDate,startPrecision)
	local slutt = getOkStatements(pidSlutt,qid)
	local sluttDate,sluttPrecision = getDatov(slutt)
	local cmpSlutt = cmpTime(atDate,atDatePrecision,sluttDate,sluttPrecision)
	if false then
		return "<br />Start: " .. dump(etablert) .. dump(startDate) .. " At: " .. dump(atDate) .. " cmp: " .. cmpStart
		.. "Slutt: " .. dump(slutt) .. dump(sluttDate) .. " cmp: " .. cmpSlutt
--		return " [" .. cmpStart .. " " .. cmpSlutt .. "]"
	end
	if (etablert and #etablert>0) or (slutt and #slutt>0) then
	
	
		if cmpStart == 1 and cmpSlutt == 0  then  -- atdato < startdato  & ingen sluttdato
			return ref(" [1: nåværende (før start & uten slutt)]")
		end
		if cmpStart == 1 and cmpSlutt == 1  then  -- atdato < startdato & atdato < sluttdato
			return ref(" [2: senere (før start & før slutt)]")
		end
		if cmpStart == 1 and cmpSlutt == -1  then  -- atdato < startdato & atdato > sluttdato
			return ref(" [3: før opprettet & etter avsluttet???]")
		end

		if cmpStart == 0 and cmpSlutt == 0  then  -- ingen startdato & ingen sluttdato
			return ref(" [4: vanlig (ingen start & ingen slutt)]")
		end
		if cmpStart == 0 and cmpSlutt == 1  then  -- ingen startdato & atdato < sluttdato
			return ref(" [5: daværende (ingen start & før slutt)]")
		end
		if cmpStart == 1 and cmpSlutt == -1  then  -- ingen startdato & atdato > sluttdato
			return ref(" [6: tidligere (ingen start & etter slutt)]")
		end
	
		if cmpStart == -1 and cmpSlutt == 0  then  -- atdato > startdato  & ingen sluttdato
			return ref(" [7: vanlig (etter start & uten slutt)]")
		end
		if cmpStart == -1 and cmpSlutt == 1  then  -- atdato > startdato & atdato < sluttdato
			return ref(" [8: daværende (etter start & før slutt)]")
		end
		if cmpStart == -1 and cmpSlutt == -1  then  -- atdato > startdato & atdato > sluttdato
			return ref(" [9: tidligere (etter start & etter slutt)]")
		end

	end

	return ""
end

function placeName(snak,qidG,pid,fdato,fprecision)
--	log = log .. "<br /> P19 start:"
	--local pid = "P1448"
	local placeQid = snak.datavalue.value.id
	local claims = getOkStatements(pid,placeQid)
--	local fdate = getOkStatements("P569",qidG)
--	local fdato,fprecision = getDatov(fdate)
	--local claim = {}
	--claim[1] = snak
	if not claims or #claims == 0 then
		local txt = placeStatus("P571","P576",placeQid,fdato,fprecision) .. " " ..
		placeStatus("P580","P582",placeQid,fdato,fprecision)
		return mw.wikibase.formatValue(snak) .. txt
	end
	local claims2 = filterByDate(pid,"P569",snak.datavalue.value.id,qidG)
--	log = log .. "<br /> P19 slutt:"
	local sorterteClaims = sorterClaims(claims2)
	local norskClaims = filtrerClaims(sorterteClaims,sprakNb)
	if norskClaims and #norskClaims>0 then
		sorterteClaims = norskClaims
	end
	local navn = mw.wikibase.formatValue(sorterteClaims[1].mainsnak)
	local lnk = snak.datavalue.value.id
	local sitelink = mw.wikibase.sitelink( lnk )
	if sitelink and sitelink == "" then
		sitelink = nil
	end
	return makeLink(navn,sitelink,false,true)
end

function formatQitem(snak,uc)
	local q = snak.datavalue.value.id

	local label,lang = mw.wikibase.getLabelWithLang(q)
	local sitelink = mw.wikibase.sitelink( q )
	if label and label ~= "" then
		return  makeLink(label,sitelink,uc,true,lang)
	end
end	

function countryName(claim)
	local prop = "P0"
	if claim and claim.P17 then
		return formatQitem(claim.P17[1],false)
	end
	return ""
end

function placeAndCountry(snak,qu,qidG,atDate,atDatePrecision)
	local name = placeName(snak,qidG,"P1448",atDate,atDatePrecision)
	local country = countryName(qu)
	local txt = name
	if country ~= "" then
		txt = txt .. ", " .. country
	end
	return txt
end


-- todo - spesialhåndtering av varighet. Slik som for P2415
-- todo - Kategorier? for mangler 
function fmtValue(snak)
	local res = nil
	if snak.snaktype == "value" and snak.datatype == "quantity" then
		local value = snak.datavalue.value or nil
		local q = string.match( value.unit, "Q[0-9]*")
		local prop = getBestStatements("P5061",q)
		prop = filtrerClaims(prop,sprakNo)
		--return "<pre>" .. mw.text.jsonEncode(prop, mw.text.JSON_PRETTY) .. "</pre>"
		if prop and prop[1] then
			local label = prop[1].mainsnak.datavalue.value.text
			local sitelink = mw.wikibase.sitelink( q )
			local txt =  makeLink(label,sitelink,false,true)
			return tostring(tonumber(value.amount)) .. " " .. txt
		end
--		res = mw.wikibase.label(q)
	end
	return res
end

function formatUrl(url)
	local urltext = url
	local j1 = string.find(urltext,'//',1,true)
	if j1 then urltext = string.sub(urltext,j1+2,string.len(urltext)) else urltext = '' end
	if urltext ~= '' then
		local i1 = string.find(urltext,'/',1,true)
		if i1 then urltext = string.sub(urltext,1,i1-1) end
	else
		urltext = url
	end
	return "[" .. url .. " " .. urltext .. "]"
end


function formatAsLabel(qid)
	return mw.wikibase.label(qid) 
end

function formatUrl(url)
	local urltext = url
	local j1 = string.find(urltext,'//',1,true)
	if j1 then urltext = string.sub(urltext,j1+2,string.len(urltext)) else urltext = '' end
	if urltext ~= '' then
		local i1 = string.find(urltext,'/',1,true)
		if i1 then urltext = string.sub(urltext,1,i1-1) end
	else
		urltext = url
	end
	return "[" .. url .. " " .. urltext .. "]"
end

function p.formatLenke(sitelink,label)
	if label and sitelink then
		return '[[' .. sitelink .. '|' .. label .. ']]'
	end
	if label and not sitelink then
		return label
	end
	if sitelink and not label then
		return '[[' .. sitelink .. ']]'
	end
	return ''
end

--  Todo: Skriv om
function formatTime(claim)
			-- Dette er egentlig valg av en algoritme, dvs det burde skrives som et pattern
			local formattedValue = ""
			if hasQualifer(claim, 'P523') or hasQualifer(claim, 'P524') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P523', 'P524' )
			elseif hasQualifer(claim, 'P580') or hasQualifer(claim, 'P582') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P580', 'P582' )
			elseif hasQualifer(claim, 'P729') or hasQualifer(claim, 'P730') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P729', 'P730' )
			elseif hasQualifer(claim, 'P2031') or hasQualifer(claim, 'P2032') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P2031', 'P2032' )
			elseif hasQualifer(claim, 'P3415') or hasQualifer(claim, 'P3416') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P3415', 'P3416' )
			elseif hasQualifer(claim, 'P575') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P575' )
			elseif hasQualifer(claim, 'P585') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P585' )
			elseif hasQualifer(claim, 'P606') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P606' )
			elseif hasQualifer(claim, 'P813') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P813' )
			elseif hasQualifer(claim, 'P1191') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P1191' )
			elseif hasQualifer(claim, 'P1249') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P1249' )
			elseif hasQualifer(claim, 'P3999') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P3999' )
			elseif hasQualifer(claim, 'P1319') or hasQualifer(claim, 'P1326') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P1319', 'P1326' )
			end
	return formattedValue
end

function fSpraak(spraakid,propid)
	local prop = getBestStatements(propid,spraakid) 
	if prop then
		if not prop[1] then
			return nil
		end
		local mainsnak = prop[1].mainsnak
		if not mainsnak or mainsnak.snaktype ~= "value" then
			return nil
		end
		local kortnavn = mainsnak.datavalue.value or nil
		local sitelink = mw.wikibase.sitelink( spraakid )
		return p.formatLenke(sitelink,kortnavn)
	end	
	return nil
end

function p.formatSpraak(snak)
	assert( snak )
	
	local spraakid = snak.datavalue.value.id or nil
	if not spraakid then
		return nil
	end
	local props = {"P218","P220"}
	for ix,prop in ipairs(props) do
		local res = fSpraak(spraakid,prop)
		if res then
			return res
		end
	end
	local lab = mw.wikibase.label(spraakid)

	return lab
end

function formatQualifierSnak(snak,pval,sep)
	if true then
		--return dump(snak)
	end
	if snak and snak.snaktype == "value" then
		if pval == "P407" then
			return p.formatSpraak(snak)
		end
		if snak.datatype == "wikibase-item" then
			return formatAsLabel(snak.datavalue.value.id)
		end
		if snak.datatype == "time" then
			return ""
		end
		return "" --mw.wikibase.formatValues(qv)
	end
end
function formatQualifierProp(quals,pval,sep,props)
	local txt = ""
	if quals and pval and not kvalUtelat[pval] then
		local qv = quals[pval]
		if qv then
			local proplab,lang = mw.wikibase.getLabelWithLang(pval)
			local pq = kvalProp[pval]
			if ( props and props[pval] ) then
				pq = props[pval]
			end
			if pq then
				if pq["tittel"] then
					proplab = pq["tittel"]
				end
			end
			if proplab and proplab ~= "" then
				sep = sep .. proplab .. ": "
			end
			for ix,snak in ipairs(qv) do
				local qualTxt = formatQualifierSnak(snak,pval,sep)
				if qualTxt and qualTxt ~= "" then
					txt = txt .. sep .. qualTxt
					sep = ", "
				end
			end
		end
	end
	return txt
end
function formatQualifiers(quals,props)
	if not quals then
		return ""
	end
	local txt = ""
	local kat = ""
	if kategori then
		kat = "[[Kategori:Artikler hvor kvalifikator hentes fra Wikidata]]"
	end
	local sep = " ("
	if not props or #props == 0 then
		for prop, qual in pairs(quals) do
			local qualTxt = formatQualifierProp(quals,prop,sep)
			if qualTxt and qualTxt ~= "" then
				txt = txt ..  qualTxt 
					if not kvalProp[prop] then
						addKat(kat)
						txt = txt .. kat
					end
				sep = ", "
			end
		end
	else
		--txt = txt .. dump(props)
		for ix,prop in ipairs(props) do
			local qualTxt = formatQualifierProp(quals,prop,sep,props)
			if qualTxt and qualTxt ~= "" then
				txt = txt .. qualTxt
				sep = ", "
			end
		end
	end
	if txt ~= "" then
		txt = txt .. ")"
	end
	return txt
end

function filtrerMonolingualtext(claim,lang)
	local snak = claim.mainsnak
	if lang[snak.datavalue.value.language] then
		return claim
	end
	return nil
end

function filtrerClaim(claim,filterLang)
	local snak = claim.mainsnak
	local lang = filterLang or sprakNo
	if snak.snaktype ~= "value" then
		return nil
	end
	local datatype = snak.datatype 
	if datatype == 'monolingualtext' then
		return filtrerMonolingualtext(claim,lang)
	end
	return claim
end

function filtrerClaims(claims)
	local resultat = {}
	for i, claim in ipairs(claims) do
		local filtrert = filtrerClaim(claim)
		if filtrert then
			table.insert(resultat, filtrert)
		end
	end
	return resultat
end
function sorterClaims(claims)
	local resultat = {}
	for i, claim in ipairs(claims) do
		table.insert(resultat, claim)
	end
	return resultat
end
function dump(item)
	return "<pre>" .. mw.text.jsonEncode(item, mw.text.JSON_PRETTY) .. "</pre>"
end
function formaterClaim(claim,claims,qualifierProps,uc)
	local snak = claim.mainsnak
	local qu = claim.qualifiers
	local rf = claim.references
	local pr = snak.property
	local lang = mw.language.getContentLanguage()

	local fmtClaim = mw.wikibase.formatValue(snak)
	local doFmtQual = true
	if snak.snaktype ~= "value" then
			--	refValue = datatype .. ": Ingen verdi"
	else
		
		local datatype = snak.datatype 
		if datatype == 'url' then
		 	fmtClaim = formatUrl(snak.datavalue.value)
		 	local qt = formatQualifiers(qu,{"P407"})
			if qt and qt ~= "" then
				fmtClaim = fmtClaim .. qt
			end
			doFmtQual = false
		elseif datatype == 'time' then
			fmtClaim = WikidataDato.norskDatoFraClaim(snak)
		elseif datatype == 'monolingualtext' then
			local txt = sprakNo[snak.datavalue.value.language]
			if txt then
				fmtClaim = fmtClaim .. txt
			end
		elseif datatype == 'quantity' then
			local val = fmtValue(snak)
			if val then
				fmtClaim = val
			end
		elseif datatype == 'wikibase-item' then
			if pr == "P19" or pr == "P20" 
			then
				local prDato = datoForEgenskap[pr]
				local date = getOkStatements(prDato,qidG)
				local dato,precision = getDatov(date)

				return --prDato .. " " .. dato .. " " ..
				placeAndCountry(snak,qu,qidG,dato,precision)
			end

			local q = snak.datavalue.value.id
			local label,lang = mw.wikibase.getLabelWithLang(q)
			local sitelink = mw.wikibase.sitelink( q )
			if label and label ~= "" then
				fmtClaim =  makeLink(label,sitelink,uc,true,lang)
			end

			--refValue = formatItem(property)
		end
	end
	local formatertKval = ""
	if doFmtQual then
		formatertKval = formatQualifiers(qu,qualifierProps)
	end
	local formatertTid = formatTime(claim)
	fmtClaim = fmtClaim .. formatertTid .. formatertKval

	return fmtClaim
end

function formaterClaims(claims,qualifierProps)
	if not claims then
		return ""
	end
	local formattedValues = {}
	local uc = true
	-- ucfirst: 1 : ingen uc; 2 : uc for første claim; 3 : uc for alle
	if ucfirst == "1" then
		uc = false
	end
	for i, claim in ipairs(claims) do
		local resultat = formaterClaim(claim,claims,qualifierProps,uc)
		if resultat then
			if useReferences[claim.mainsnak.property] then
				local ref = refs.render(mw.getCurrentFrame(), claim.references)
				resultat = resultat .. ref
			end
			table.insert(formattedValues, resultat)
			if ucfirst == "2" then
				uc = false
			end
		end
	end	return formattedValues
end

function getWikidataVerdi(qid,pid,qualifierProps,vis)
	local verdiListe = ""
	local claims = nil
	if vis and vis == "beste" then
		claims = getBestStatements(pid,qid)
	else
		claims = getOkStatements(pid,qid)
	end


	local i = 0
	local manglerOversettelse = false
	local filtrerteClaims = filtrerClaims(claims)
	local sorterteClaims = sorterClaims(filtrerteClaims)
	local formattedValues = formaterClaims(sorterteClaims,qualifierProps)
	
	if present == "løpende tekst" and #formattedValues > 2 then
		verdiListe = " "
		local sep = ""
		for i,val in ipairs(formattedValues) do
			if i == #formattedValues then
				sep = " og "
			end
			verdiListe = verdiListe .. sep .. val
			sep = ", "
		end
		return verdiListe
	end

	local sep = "<br/>"
	if kollaps(#formattedValues) then
		sep = "<br/>"
	end
	
	verdiListe = table.concat(formattedValues, sep)
	
	if kollaps(#formattedValues) then
		verdiListe = string.format([[
			<div class="mw-collapsible mw-collapsed">
				<div class="sentrert">%s oppføringer</div>
				<div class="mw-collapsible-content">%s</div>
			</div>
		]], #formattedValues, verdiListe)
	end

	return verdiListe
end

function p._verdi(frame,qid,pid,param,ref,sprak,qualifierProps,vis)
	local verdi = getFrameValue(frame, param)
	if verdi == "uten" then
		-- Hvis malargumentet er satt til "uten" betyr det at det ikke er ønskelig
		-- at feltet vises, selv om det finnes data på Wikidata.
		addKat("[[Kategori:Artikler hvor parameter spesifisert som uten]]")
		return ""
	end
	if verdi ~= '' then
		return verdi .. ""
	end
	if not pid or pid=="" then
		return ""
	end
	useReferences[pid] = "ja"
	if ref and ref == 'nei' then
		useReferences[pid] = nil
	end
	verdi = getWikidataVerdi(qid,pid,qualifierProps,vis)
 	return verdi
end

function p._rad2(frame,qid,pid,param,ref,sprak,displayName,qualifierProps,vis)
	local verdi = p._verdi(frame,qid,pid,param,ref,sprak,qualifierProps,vis)
	if not verdi then
		return ""
	end
	if verdi == '' then
		return verdi .. ""
	end
 	return '<tr class="rad" valign="top">' ..
			'<th colspan="2" class="nowrap">' ..  displayName .. '</th>' ..
			'<td colspan="2">' .. verdi .. '</td>' ..
		'</tr>' -- lagRad(verdi,displayName)

end

function qualpropargs(qp,txt)
	if not txt or txt == "" then
		return
	end
	local xxx = mw.text.split(txt, ',', true )
	for j,pkval in ipairs(xxx) do
		local pk = mw.text.split(pkval, ':', true )
		
		qp[pk[1]] = pk[2]
	end
end	
function qualargs(qual,args)
	if not qual or qual == "" then
		return nil
	end
	local qp = mw.text.split(qual, ',', true )
	for i,prop in ipairs(qp) do
		if args[prop] then
			qp[prop] = {} --args[prop]
			if true then
				qualpropargs(qp[prop],args[prop])
			else
			local ap = args[prop] or ""
			for j,pkval in mw.text.split(ap, ',', true ) do
				local pk = mw.text.split(pkval, ':', true )
				qp[prop][pk[1]] = pk[2]
			end
			end
		end
	end
	return qp
end

function p.verdi(frame)
	assert( frame )
	if frame.args['kollaps'] then
    	kollapsNum = tonumber(frame.args['kollaps'])
    end
    local qid = nil
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end
    local pid = frame.args['pid'] or frame.args['wdp'] or nil
    local ref = frame.args['ref'] or nil
    local param = frame.args['param'] or "xxx"
    local sprak = frame.args['språk'] or nil
    local vis = frame.args['vis'] or nil
    present = frame.args['presenter'] or "1"
	local argsp = frame.args
	local qualifierProps = qualargs(argsp['kval'],argsp )
    local resultat = p._verdi(frame,qid,pid,param,ref,sprak,qualifierProps,vis)
	return resultat
end

function p.rad(frame)
	assert( frame )
	if frame.args['kollaps'] then
    	kollapsNum = tonumber(frame.args['kollaps'])
    end
    local qid = nil
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end
    local pid = frame.args['pid'] or frame.args['wdp'] or nil
    local ref = frame.args['ref'] or nil
    ucfirst = frame.args['ucfirst'] or "1"
    local param = frame.args['param'] or "xxx"
    local sprak = frame.args['språk'] or nil
    local vis = frame.args['vis'] or nil
    kategori = frame.args['kat'] or nil
	local lang = mw.language.getContentLanguage()
	local displayName = frame.args['tekst'] or lang:ucfirst(param)
	local argsp = frame.args
	local qualifierProps = qualargs(argsp['kval'],argsp )
    local resultat = p._rad2(frame,qid,pid,param,ref,sprak,displayName,qualifierProps,vis) --{"P1686","P1706","P1552"})
    --resultat = dump(qp)
	return resultat .. kategorier
end


return p