Modul:WikidataListe/sandkasse

Lua-feil i Modul:Documentation, linje 388: message: type error in message cfg.module-sandbox-category (string expected, got nil).


local WikidataDato = require( 'Module:WikidataDato' )
local refs = require 'Module:Reference score'
local p = {}

-- 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
	["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 katNavn = {
	["P22"] = "far"
}

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

local kollapsNum = 5

function kategori(prop,tekst)
	local tparam = katNavn[prop] or "en eller flere egenskaper"
	return "[[Kategori:Artikler hvor " .. tparam .. tekst
	
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)
	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 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 )
	return makeLink(label,sitelink,first,link)
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 )
	local pointYear = formatYearQualifier(claim, 'P585')
			or '' -- all fail
	local pointTitle = (hasQualifer(claim, 'P585') and getQualifier(claim, 'P585', true))
			or nil
	if pointTitle then
		pointYear = mw.html.create( 'span' )
			:attr( 'title', string.format("%s: %s", mw.wikibase.getLabel( 'P585' ), 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 .. ']]  aaa'
			end
			
			if useCountry[prop] then
				--formattedValue = formattedValue .. " xxx"
				--local claim2 = filterByDate("P1448","P569",value,qid)
				--local navn = formaterClaims(claim2) 
				--if (navn) then
					--formattedValue = formattedValue .. "<br />navn:  " .. loc .. navn
				--end
				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(prop," mangler oversettelse]]" )
						--"[[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 p.grenserTil(frame)
	assert( frame )
	return getFormattedValues(frame,'P47',"grenser til")
end

function p.yrker(frame)
	assert( frame )
	return getFormattedValues(frame,'P106',"beskjeftigelse", false)
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(prop, " hentes fra Wikidata]]")
			--"[[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 lagRad(value,displayName)

	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 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.rad(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 sprakNb = {
	["nb"] = "bokmål",
}
local sprakNo = {
	["nb"] = "",     -- bokmål
	["nn"] = " ([[nynorsk|nn]])",
	["se"] = " ([[nordsamisk|se]])",
}

local datoForEgenskap = {
	["P19"] = "P569",
	["P20"] = "P570",
}

-- 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 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 p.formatSpraak(snak)
	assert( snak )
	
	local spraakid = snak.datavalue.value.id or nil
	if not spraakid then
		return nil
	end
	local prop = getBestStatements("P218",spraakid) or getBestStatements("P220",spraakid) or nil
	if prop then
		if not prop[1] then
			return ""
		end
		if not prop[1].mainsnak then
			return ""
		end
		local kortnavn = prop[1].mainsnak.datavalue.value or nil
		local sitelink = mw.wikibase.sitelink( spraakid )
		return p.formatLenke(sitelink,kortnavn)
	end
	local lab = mw.wikibase.label(spraakid)

	return lab
end

function formatQualifier(qual,pval)
	if qual and pval then
		if true then
			--return dump(qual) .. dump(pval)
		end
		local qv = qual[pval]
		local snak = qv[1] or nil
		
		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
end

function formatQualifiers(quals)
	if not quals then
		return "" --.."(-quals)"
	end
	local txt = ""
	local sep = " ("
	for prop, qual in pairs(quals) do
		local qualTxt = formatQualifier(quals,prop)
		if qualTxt and qualTxt ~= "" then
			txt = txt .. sep .. qualTxt
			sep = ", "
		end
	end
	if txt ~= "" then
		txt = txt .. ")"
	end
	return txt
end

function filtrerElementEtterTidspunkt(qid,tid,tidsegenskaper)
end

function filtrerEtterTidspunkt(claim,tid,tidsegenskaper)
	local snak = claim.mainsnak
	if lang[snak.datavalue.value.language] then
		return claim
	end
	return nil
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)
	local snak = claim.mainsnak
	if snak.snaktype ~= "value" then
		return nil
	end
	local datatype = snak.datatype 
	if datatype == 'monolingualtext' then
		return filtrerMonolingualtext(claim,sprakNo)
	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
	log = log .. "Filtrert til: " .. #resultat
	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 placeTooltip(qid,txt)
	local entity = mw.wikibase.getEntity(qid)
	
	if not entity then
		return txt
	end
	local descr = {}
	table.insert(descr,mw.wikibase.label(qid))
	table.insert(descr,mw.wikibase.description(qid))
	txt = table.concat(descr,"; ")
	return mw.getCurrentFrame():expandTemplate{title="Tooltip",args = { " [*]", txt} }
end

function ref(txt)
	return txt
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 countryName(snak,qidG,atDate,atDatePrecision)
	local claims = getOkStatements("P17",snak.datavalue.value.id)
	if not claims or #claims == 0 then
		return ""
	end
	if true then
	--	return dump(claims)
	end
	local claims2 = filterClaimsByDate(claims,atDate,atDatePrecision)
	local country = mw.wikibase.formatValue(claims2[1].mainsnak)
	if claims2[1].mainsnak then
	--	return dump(claims2[1].mainsnak)
	--	.. claims2[1].mainsnak.datavalue.value.id
	end
	local txt = placeStatus("P571","P576",claims2[1].mainsnak.datavalue.value.id,atDate,atDatePrecision) .. " "
		--	..		placeStatus("P580","P582",claims2[1].mainsnak.datavalue.value.id,atDate,atDatePrecision)
	return country --.. " " .. 
	.. " " .. txt
	--placeName(claims2[1].mainsnak,snak.datavalue.value.id,"P2561",atDate,atDatePrecision)
end

function placeAndCountry(snak,qidG,atDate,atDatePrecision)
	local name = placeName(snak,qidG,"P1448",atDate,atDatePrecision)
	local country = countryName(snak,qidG,atDate,atDatePrecision)
	local txt = name
	if country ~= "" then
		txt = txt .. ", " .. country
	end
	return txt
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 sorterteClaime = sorterClaims(claims2)
	local formattedValues = formaterClaims(sorterteClaime)
	local sep = "<br/>"
	if kollaps(#formattedValues) then
		sep = "<br/>"
	end
	local navn = formattedValues[1]
	--table.concat(formattedValues, sep)
	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

local qidG = nil
function formaterClaim(claim,claims)
	local snak = claim.mainsnak
		local qu = claim.qualifiers
		local rf = claim.references
		local pr = snak.property
	if true then
		--return dump(claim.mainsnak)
	end
	local fmtClaim = mw.wikibase.formatValue(snak)
	local doFmtQual = true
	if snak.snaktype ~= "value" then
			--	refValue = datatype .. ": Ingen verdi"
	else
		
		local datatype = snak.datatype 
		if true then
		--	return dump(snak) .. mw.wikibase.formatValues(snak)
		end
		if datatype == 'url' then
		 	fmtClaim = formatUrl(snak.datavalue.value)
		 	local qt = formatQualifier(qu,"P407")
			if qt and qt ~= "" then
				fmtClaim = fmtClaim .. " (" .. qt .. ")"
			end
			doFmtQual = false
		elseif datatype == 'time' then
			fmtClaim = 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
			--fmtClaim = fmtClaim .. "<br />" .. dump(snak)
			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,qidG,dato,precision)
			end
			--refValue = formatAsLabel(snak.datavalue.value.id)
		end
	end
	local formatertKval = ""
	if doFmtQual then
		formatertKval = formatQualifiers(qu)
	end
	local formatertTid = formatTime(claim)
	fmtClaim = fmtClaim .. formatertTid .. formatertKval

--	local fmtClaim = mw.wikibase.formatValues(claim.mainsnak)
	return fmtClaim
end

function formaterClaims(claims)
	local formattedValues = {}
	for i, claim in ipairs(claims) do
		local resultat = formaterClaim(claim)
		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)
		end
	end	return formattedValues
end

function getWikidataVerdi(qid,pid)
	local verdiListe = ""
	
	local claims = getOkStatements(pid,qid)

	local i = 0
	local manglerOversettelse = false
	local filtrerteClaims = filtrerClaims(claims)
	local sorterteClaims = sorterClaims(filtrerteClaims)
	local formattedValues = formaterClaims(sorterteClaims)
	

	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)
	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.
		return "[[Kategori:Artikler hvor parameter spesifisert som uten]]"
	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)
 	return verdi
end

function p._rad2(frame,qid,pid,param,ref,sprak,displayName)
	local verdi = p._verdi(frame,qid,pid,param,ref,sprak)
	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 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
	qidG = qid
    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 resultat = p._verdi(frame,qid,pid,param,ref,sprak)
	return resultat
end

function p.rad2(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 lang = mw.language.getContentLanguage()
	local displayName = frame.args['tekst'] or lang:ucfirst(param)
    local resultat = p._rad2(frame,qid,pid,param,ref,sprak,displayName)
	return resultat
end

function p.dump(frame)
	assert( frame )
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end
	local claims = getBestStatements(frame.args['wdp'],qid)
	--	local claims = mw.wikibase.getAllStatements(frame.args['wdp'],qid)
	return "<pre>" .. mw.text.jsonEncode(claims, mw.text.JSON_PRETTY) .. "</pre>" 	
end
log = ""

	--	if snak and snak.snaktype == "value" then
	--		if snak.datatype == "wikibase-item" then
	--			return formatAsLabel(snak.datavalue.value.id)
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 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 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 p.test(frame)
--	return aa2(frame)
	assert( frame )

	local qid,pid = "Q585","P2561"
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end
	if frame.args['pid'] and frame.args['pid'] ~= "" then
		pid = frame.args['pid']
	end
	-- pid = "P1448"    -- offisielt navn, bruker navn da de er kortere (uten referanser bl.a)
	--pid = "P17"
	local claims = getOkStatements(pid,qid)
	local date,precision = "1814-11-04",11
	if frame.args['param'] and frame.args['param'] ~= "" then
		date = frame.args['param']
	end
	if frame.args['dato'] and frame.args['dato'] ~= "" then
		date = frame.args['dato']
	end
	if frame.args['presisjon'] and frame.args['presisjon'] ~= "" then
		precision = frame.args['presisjon']
	end
	
	local qiddato = nil
	if frame.args['qiddato'] and frame.args['qiddato'] ~= "" then
		qiddato = frame.args['qiddato']
	end
	local piddato = nil
	if frame.args['piddato'] and frame.args['piddato'] ~= "" then
		piddato = frame.args['piddato']
	end
	
	local claims2 = nil
	if piddato then
		claims2 = filterByDate(pid,piddato,qid,qiddato)
		
		local claimsDate = getBestStatements(piddato,qiddato)
		date,precision = getDatov(claimsDate)
	end
	if not piddato then
		claims2 = filterClaimsByDate(claims,date,precision)
	end
		local sorterteClaime = sorterClaims(claims2)
	local formattedValues = formaterClaims(sorterteClaime)
	

	local sep = "<br/>"
	if kollaps(#formattedValues) then
		sep = "<br/>"
	end
	verdiListe = table.concat(formattedValues, sep)

	return --"<br/>Ny test<br/>" .. log .. 
	"date: " .. date .. "  presisjon: " .. precision .. "  qid: " .. qid .. "  pid: " .. pid .. "<br/>" ..
--	"<pre>" .. mw.text.jsonEncode(claims2, mw.text.JSON_PRETTY) .. "</pre>" 
--	.. 
	verdiListe .. "<br/>"
end

function p.label(frame)
	local qid = nil
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end
	local label = mw.wikibase.label( qid )
	return label
end




function p._rader(frame,defs)
	local lang = mw.language.getContentLanguage()
	local txt = ""
    local qid = nil
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end
 	for i,def in ipairs(defs) do
		local param = def["param"]
		local pid = def["pid"]
		local ref = def["ref"]
		local sprak = def["sprak"]
		local displayName = def["displayName"] or lang:ucfirst(param)
		if not def[1] or def[1] == "rad" then
		txt = txt --.. dump(def) --.. " " .. param .. " " .. ref
		--.. "<nowiki>" 
		.. p._rad2(frame,qid,pid,param,ref,sprak,displayName) --.. "<nowiki/>"
		end
	end
	return txt
end

function p.familie(frame)
	local defs = 
	{
		{ "rad",param = 'ektefelle', pid ="P26", ref= 'ja', sprak = nil},
		{ param = 'foreldre', pid =nil, ref= 'ja', sprak = nil, displayName = "Foreldre" },
		{ param = 'partner', pid ="P451", ref= 'ja', sprak = nil, displayName = "Partner" },
		{ "rad",param = 'far', pid ="P22", ref= 'ja', sprak = nil, displayName = "Far" },
		{ param = 'mor', pid ="P25", ref= 'ja', sprak = nil, displayName = "Mor" },
		{ param = 'søsken', pid ="P3373", ref= 'ja', sprak = nil, displayName = "Søsken" },
		{ param = 'barn', pid ="P40", ref= 'ja', sprak = nil, displayName = "Barn" },
	}
	return p._rader(frame,defs)
end

function p.rader(frame)
	return p.familie(frame)
end

return p