Modul:Taksoboks/Taksonomidata frå Wikidata

Frå Wikipedia – det frie oppslagsverket

Dokumentasjon for modulen kan opprettast på Modul:Taksoboks/Taksonomidata frå Wikidata/dok


-- Gjeremål:

-- Når eit takson har fleire foreledertakson (t.d. Cetartiodactyla (Q27850))
-- går ikkje alle stigane innom alle rangane

local utdata = {}
local IDEALTAL = 8 -- kor mange rangar som skal synast til vanleg
local TAKSONID = 'Q16521'; KLADEID = 'Q713623'
local IGNORER = {Q2382443 = true, Q146481 = true, Q22666877 = true, Q19858692 = true}
local RANGTYPEIDAR = {underart = 'Q68947', art = 'Q7432', seksjon_over_art = 'Q3181348', underslekt = 'Q3238261', slekt = 'Q34740', understamme = 'Q3965313',
	stamme = 'Q227936', overstamme = 'Q14817220', underfamilie = 'Q164280',
	familie = 'Q35409', overfamilie = 'Q2136103', infraorden = 'Q2889003', parvorden = 'Q6311258', underorden = 'Q5867959', orden = 'Q36602',
	overorden = 'Q5868144',  infraklasse = 'Q2007442', underklasse = 'Q5867051', klasse = 'Q37517', megaklasse  = 'Q60922428',
	overklasse = 'Q3504061', infrarekkje = 'Q2361851', underrekkje = 'Q1153785', rekkje = 'Q38348', overrekkje = 'Q3978005',
	infrarike = 'Q3150876', underrike = 'Q2752679', rike = 'Q36732', overrike = 'Q19858692', domene = 'Q146481',
	varietet = 'Q767728', form ='Q279749', kultivar = 'Q4886', potetkultivar = 'Q16682342', rosekultivar ='Q26817508'
}
RANGTYPEIDAR['klade'] ='Q713623' -- ikkje eigentleg ein rangtype
RANGTYPEIDAR['urangert'] = 'urangert' 
local RANGNAMN = {}
for i, j in pairs(RANGTYPEIDAR) do
	RANGNAMN[j] = i
end
local DIVISJONIDAR = {overdivisjon = 'Q23760204', divisjon = 'Q334460', underdivisjon = 'Q3491997'}
local DIVISJONUTBYTE = {overdivisjon = 'overrekkje', divisjon = 'rekkje', underdivisjon = 'underrekkje'}
local DIVISJONNAMN = {}
for i, j in pairs(DIVISJONIDAR) do
	DIVISJONNAMN[j] = i
end

function utdata.hovud(ID)
	local ranghierarki = {}
	local byrjeID = ID or mw.wikibase.getEntityIdForCurrentPage()
	laegsteRangen = nil
	rangnummer = 1
	rike = nil
	domene = nil
	data = utdata.rekursjon(byrjeID, ranghierarki, true)[1] -- hent ranghierarkiet rekursivt
		
	if #data == 0 then -- fann ikkje noko taksonomisk hierarki
		return {}
	end
	
	-- rangane som i utgangspunktet skal vera med
	standardinnhald = {}
	standardinnhald[RANGTYPEIDAR['underart']] = true
	standardinnhald[RANGTYPEIDAR['art']] = true
	standardinnhald[RANGTYPEIDAR['seksjon_over_art']] = true
	standardinnhald[RANGTYPEIDAR['slekt']] = true
	standardinnhald[RANGTYPEIDAR['underslekt']] = true
	standardinnhald[RANGTYPEIDAR['familie']] = true
	standardinnhald[RANGTYPEIDAR['orden']] = true
	standardinnhald[RANGTYPEIDAR['klasse']] = true
	standardinnhald[RANGTYPEIDAR['underrekkje']] = true
	standardinnhald[RANGTYPEIDAR['rekkje']] = true
	standardinnhald[RANGTYPEIDAR['rike']]  = true
	laegsteRangnamn = RANGNAMN[laegsteRangen] or DIVISJONUTBYTE[DIVISJONNAMN[laegsteRangen]]
	standardinnhald[laegsteRangnamn] = true
	if rike == 'Bacteria' or rike == 'Archaea' or domene == 'Bacteria' or domene == 'Archaea' or mw.ustring.find(laegsteRangnamn, 'rike') then
		standardinnhald[RANGTYPEIDAR['domene']] = true -- unnatak
	end
	if mw.ustring.find(laegsteRangnamn, 'rike') then
		standardinnhald[RANGTYPEIDAR['overrike']] = true
	end
	
	local tekMed = {tal = 0}
	local unytta = {}
	for i = 1, #data do -- sjå kva standardrangar me har
		tekMed[i] = false
		rangtypeID = data[i][1]
		nykel = RANGNAMN[rangtypeID] or DIVISJONUTBYTE[DIVISJONNAMN[rangtypeID]]
		if standardinnhald[rangtypeID] and not tekMed[nykel] then
			tekMed[i] = true
			tekMed[nykel] = true
			tekMed.tal = tekMed.tal + 1
		elseif not IGNORER[rangtypeID] then
			table.insert(unytta, {i, rangtypeID, nykel})
		end
	end
	i = 1
	while (tekMed.tal < IDEALTAL and i <= #unytta) do -- freist å få det ideelle talet på rangar
		local rangnr = unytta[i][1]
		local rangtypeID = unytta[i][2]
		local nykel = unytta[i][3]
		if (RANGNAMN[rangtypeID] or DIVISJONNAMN[rangtypeID]) and not tekMed[nykel] 
		and not (RANGNAMN[rangtypeID] == 'klade' and laegsteRangnamn ~= 'klade') -- berre ha med klade om artikkelemne
		then
			tekMed[rangnr] = true
			tekMed.tal = tekMed.tal + 1
			tekMed[nykel] = true
		end
		i = i + 1
	end

	local taksonomitabell = {}
	local ubrotenMonotypi = true
	for i = 1, #data do
		rangtypeID = data[i][1]
		nykel = RANGNAMN[rangtypeID] or DIVISJONUTBYTE[DIVISJONNAMN[rangtypeID]]
		
		local vitNamn = data[i][2]; norskNamn = data[i][3];  side = data[i][4]
		local monotypisk = data[i][6]; utdoeydd = data[i][7]
		if i == 1 then
			ubrotenMonotypi = false
		elseif (i == 2 and monotypisk) or (ubrotenMonotypi and monotypisk) then
			ubrotenMonotypi = true
		else
			ubrotenMonotypi = false
		end
		
		local innhaldsdata =  {vitNamn, norskNamn, side, ubrotenMonotypi, utdoeydd}

		if tekMed[i] then
			if not taksonomitabell[nykel] and tekMed[i] then
				taksonomitabell[nykel] = innhaldsdata
			end
		end
	end
	taksonomitabell['lægste rangen'] = laegsteRangnamn
	return taksonomitabell
end

function utdata.rekursjon(rangID, ranghierarki, tving)
	local taksonomielement = mw.wikibase.getEntity(rangID)
	local monotypisk = false
	local utdoeydd = false
	local rangtypeID = nil
	local ikkjerang -- for bruk ved urangerte taksonomiske einingar
	if not taksonomielement.claims then return {ranghierarki, false} end -- fann feil element eller noko er gale med elementet
	if not taksonomielement.claims.P105 then return {ranghierarki, false} end -- taksonomisk rang ikkje oppgjeve (ikkje det same som ingen verdi)
	if taksonomielement:getBestStatements('P105')[1]['mainsnak']['datavalue'] then
		rangtypeID = taksonomielement:getBestStatements('P105')[1]['mainsnak']['datavalue']['value']['id'] -- kva type rang
		rang = mw.wikibase.label(rangtypeID)
		if not laegsteRangen then laegsteRangen = rangtypeID end
	else
		foerekomstAvID = taksonomielement:getBestStatements('P31')[1]['mainsnak']['datavalue']['value']['id']
		if foerekomstAvID == KLADEID then
			ikkjerang = 'klade'
		elseif foerekomstAvID == TAKSONID then
			ikkjerang = 'urangert'
		else
			ikkjerang = 'urangert'
		end

		if not laegsteRangen then -- artikkelen handlar om ei urangert taksonomisk eining
			laegsteRangen = RANGTYPEIDAR[ikkjerang]
			rang = ikkjerang
		else
			rang = ''
		end
		if not tving then -- fann ei urangert taksonomisk eining, vil helst ikkje gå vidare
			return {ranghierarki, false}
		end
	end
	
	if not rangtypeID then -- urangerte taksonomiske einingar har ingen oppgjeven rangtype
		rangtypeID = RANGTYPEIDAR[ikkjerang]
	end
	
	local vitskaplegRangnamn = ''
	if taksonomielement.claims.P225 then
		vitskaplegRangnamn = taksonomielement.claims.P225[1]['mainsnak']['datavalue']['value']
	end
	if taksonomielement.claims.P31 then -- «førekomst av»
		if taksonomielement.claims.P31[1]['mainsnak']['datavalue']['value']['id'] == 'Q310890' then
			monotypisk = true
		end
		if taksonomielement.claims.P31[1]['mainsnak']['datavalue']['value']['id'] == 'Q23038290' then -- fossilt takson
			utdoeydd = true
		end
	end

	if taksonomielement.claims.P141 and taksonomielement.claims.P141[1]['mainsnak']['datavalue']['value']['id'] == 'Q237350' then -- utdøydd
		utdoeydd = true
	end
	
	local norskRangnamn
	if taksonomielement.labels['nn'] and taksonomielement.labels['nn']['language'] == 'nn' then -- vil ikkje ha merkelapp frå eit anna språk enn nynorsk
		norskRangnamn = taksonomielement:getLabel('nn')
	else
		norskRangnamn = nil
	end
	if norskRangnamn == vitskaplegRangnamn then -- vitskapleg namn er sett som merkelapp
		norskRangnamn = nil
	end
	
	wikipediasidetittel = taksonomielement:getSitelink('nnwiki') -- tittelen til lokal artikkel, om han finst
	if rang ~= '' then
		ranghierarki[rangnummer] = {rangtypeID, vitskaplegRangnamn, norskRangnamn, wikipediasidetittel, rangID, monotypisk, utdoeydd} -- sank inn informasjonen som skal nyttast
		rangnummer = rangnummer + 1
	end
	
	if rangtypeID == RANGTYPEIDAR['rike'] then
		rike = vitskaplegRangnamn
	end
	if rangtypeID == RANGTYPEIDAR['domene'] then
		domene = vitskaplegRangnamn
	end
	
	if taksonomielement.claims.P171 and taksonomielement.claims.P171[1]['mainsnak']['snaktype'] ~= 'novalue'  then
		foreldrerangar = taksonomielement:getBestStatements('P171') -- hent berre dei beste forelderrangane
		
		rettVeg = false -- om gjeldande foreldertakson er ein klade
		i = 1
		while (rettVeg == false and i <= #foreldrerangar) do
			nesteRangID = foreldrerangar[1]['mainsnak']['datavalue']['value']['id']
			if i == #foreldrerangar then -- har ikkje noko val anna enn å gå gjennom kladen
				tving = true
			else
				tving = false
			end
			
			neste = utdata.rekursjon(nesteRangID, ranghierarki, tving)
			rettVeg = neste[2]
			i = i + 1
		end
		return neste
	else  -- toppen nådd
		return {ranghierarki, rettVeg = true}
	end
end

return utdata