Modul:Briefspielreihe

Aus KoschWiki
Zur Navigation springen Zur Suche springen
Dokumentation und Testfälle unter Modul:Briefspielreihe/Doku.
require("Modul:Hilfsfunktionen")
require("Modul:Text")
require("Modul:Titelblock")

local p = {}

--Hole alle Kapitel per Subobject ohne Vorgeschichte und Folgehandlung
function holeKapitel(reihe)
	if reihe=='' then return '' end
	local kapitel=mw.smw.ask("[[-has subobject::+]] [[Reihe ist::"..reihe.."]] [[Kapitelnummer ist::>-10]] [[Kapitelnummer ist::<510]]"
		.."|mainlabel=-"
		.."|?#-="
		.."|?Kapitelnummer ist#="
		.."|?Briefspiel-Zeitindex ist#="
		.."|link=none"
		.."|format=list"
		.."|sort=Reihenkapitel,Briefspiel-Zeitindex ist"
		.."|order=asc,asc"
		.."|searchlabel="
		.."|limit=500"
	)
	if kapitel==nil then
		return {}
	end
	return kapitel
end

--Hole die Viewbox eines Handlungsortes oder Lehens
function holeViewbox(ort)
	if ort=='' then return '' end
	local a=mw.smw.ask("[["..ort.."]]|mainlabel=-|?Viewbox#=")
	if a==nil then return "" end
	if a[1]==nil then return "" end
	if a[1][1]==nil then return "" end
	return a[1][1]
end

--Errechne den Mittelpunkt der Viewbox als Koordinaten für die Kartenanzeige
function viewboxToKoordinaten(viewbox)
	if viewbox=="" then return "" end
	local result=""
	local width=10000000
	for k,token in pairs(split(viewbox,",")) do
		local subtokens={}
		local i=0
		for k,subtoken in pairs(split(token,"%s")) do
			subtokens[i]=tonumber(subtoken)
			i=i+1
		end
		if subtokens[3] then
			if subtokens[3]<width then
				width=subtokens[3]
				local x=subtokens[0]+subtokens[2]/2
				local y=subtokens[1]+subtokens[3]/2
				result=x.." "..y
			end
		end
	end
	return result
end

--Tabelle (key->anzahl) absteigend nach Häufigkeitsverteilung sortieren für Pivot
function sorted(t)
	s={}
	for k,v in pairs(t) do
		table.insert(s,{k,v})
	end
	table.sort(s,function(k1,k2) return k1[2]>k2[2] end)
	return s
end

--Hole weitere Details zu den einzelnen Kapiteln
--ermittle dabei statistische Daten (min/max) und zähle Orte, Jahre, Autoren, Darsteller für Pivots
function holeDetails(kapitel)
	--Statistik initialisieren
	local minzeitindex=1000000000
	local minzeittext=""
	local maxzeitindex=-1000000000
	local maxzeittext=""
	local minerstelltindex="3000-01-01T00:00:00"
	local minerstellttext=""
	local maxerstelltindex="0000-01-01T00:00:00"
	local maxerstellttext=""
	--Pivots initialisieren
	local darsteller={}
	local handlungsorte={}
	local autoren={}
	local jahre={}
	
	--wenn keine Kapitel vorhanden, abbrechen
	if(#kapitel==0) then
		return {}
	end
	
	--sortiert durch die Kapitel gehen
	local tkeys=getSortKeys(kapitel)
	for _,k in ipairs(tkeys) do
		--Artikelname korrigieren
		kapitel[k][1]=mw.text.split(kapitel[k][1],"#",true)[1]
		--Daten abfragen
		local det=mw.smw.ask("[["..kapitel[k][1].."]]"
			.."|mainlabel=-"
			.."|?Handlungszeittext ist#="
			.."|?Briefspieler#="
			.."|?Kapitelname ist#="
			.."|?Kurzbeschreibung#="
			.."|?Hauptdarsteller ist#="
			.."|?Handlungsort ist#="
			.."|?Handlungsort indirekt#="
			.."|?Erstellt#="
			.."|?Erstellt#LOCL#TO="
			.."|?Wappen ist#="
			.."|?Category#="
		)
		--alle Daten als Tabellen, um später Mehrfach- und Einfachsetzungen gleich behandeln zu können
		kapitel[k][4]=noniltable(det[1][1])
		kapitel[k][5]=noniltable(det[1][2])
		kapitel[k][6]=noniltable(det[1][3])
		kapitel[k][7]=noniltable(det[1][4])
		kapitel[k][8]=noniltable(det[1][5])
		kapitel[k][9]=noniltable(det[1][6])
		kapitel[k][10]=noniltable(det[1][7])
		kapitel[k][11]=noniltable(det[1][8])
		kapitel[k][12]=noniltable(det[1][9])
		kapitel[k][13]=noniltable(det[1][10])
		kapitel[k][14]=noniltable(det[1][11])

		--Min/Max-Abfragen für die Statistik
		if(kapitel[k][2]>=0)and(kapitel[k][2]<=96) then
			if kapitel[k][3]<minzeitindex then
				minzeitindex=kapitel[k][3]
				minzeittext=kapitel[k][4][1]
			end
			if kapitel[k][3]>maxzeitindex then
				maxzeitindex=kapitel[k][3]
				maxzeittext=kapitel[k][4][1]
			end
		end
		if kapitel[k][11][1]<minerstelltindex then
			minerstelltindex=kapitel[k][11][1]
			minerstellttext=kapitel[k][12][1]
		end
		if kapitel[k][11][1]>maxerstelltindex then
			maxerstelltindex=kapitel[k][11][1]
			maxerstellttext=kapitel[k][12][1]
		end

		--Auszählen von Werten für die Pivots
		if #kapitel[k][5]>0 then
			for k,v in ipairs(kapitel[k][5]) do
				if autoren[v]==nil then
					autoren[v]=1
				else
					autoren[v]=autoren[v]+1
				end
			end
		end
		if #kapitel[k][8]>0 then
			for k,v in ipairs(kapitel[k][8]) do
				if darsteller[v]==nil then
					darsteller[v]=1
				else
					darsteller[v]=darsteller[v]+1
				end
			end
		end
		
		--zusätzlich Koordinaten für direkte Handlungsorte ermitteln
		local coords={}
		if #kapitel[k][9]>0 then
			for k,v in ipairs(kapitel[k][9]) do
				table.insert(coords,viewboxToKoordinaten(holeViewbox(v)))
				if handlungsorte[v]==nil then
					handlungsorte[v]=1
				else
					handlungsorte[v]=handlungsorte[v]+1
				end
			end
		end
		if #kapitel[k][10]>0 then
			for k,v in ipairs(kapitel[k][10]) do
				if handlungsorte[v]==nil then
					handlungsorte[v]=1
				else
					handlungsorte[v]=handlungsorte[v]+1
				end
			end
		end
		if #kapitel[k][14]>0 then
			for k,v in ipairs(kapitel[k][14]) do
				if(v:find('^Kategorie:Geschichten ')~=nil) then
					if jahre[v]==nil then
						jahre[v]=1
					else
						jahre[v]=jahre[v]+1
					end
				end
			end
		end
		kapitel[k][15]=coords
	end
	
	--Median des Zeitindex errechnen
	local kanz=#kapitel
	local medzeitindex=0
	if (kanz%2)==0 then
		--Gerade Anzahl
		local m1=kapitel[kanz/2][3]
		local m2=kapitel[kanz/2+1][3]
		medzeitindex=(m1+m2)/2
	else
		--Ungerade Anzahl
		medzeitindex=kapitel[math.ceil(kanz/2)][3]
	end

	--Statistik in die Tabelle in nicht-numerischen Key
	if(minzeittext==nil) then minzeittext="" end
	if(maxzeittext==nil) then maxzeittext="" end
	if(minerstellttext==nil) then minerstellttext="" end
	if(maxerstellttext==nil) then maxerstellttext="" end
	kapitel["statistik"]={}
	kapitel["statistik"]["minzeit"]=minzeittext
	kapitel["statistik"]["medzeitindex"]=tostringd(medzeitindex)
	kapitel["statistik"]["maxzeit"]=maxzeittext
	kapitel["statistik"]["minerstellt"]=minerstellttext
	kapitel["statistik"]["maxerstellt"]=maxerstellttext
	kapitel["statistik"]["autoren"]=sorted(autoren)
	kapitel["statistik"]["darsteller"]=sorted(darsteller)
	kapitel["statistik"]["handlungsorte"]=sorted(handlungsorte)
	kapitel["statistik"]["jahre"]=sorted(jahre)
	
	return kapitel
end

--Umrechnung der angezeigten Kapitelnummern
function kapitelno(k)
	local result=""
	local k=tonumber(k)
	if (k==nil) then return "" end
	if (k>=-100)and(k<-10) then result="Vorgeschichte "..tostring(k+101) end
	if (k>=-10)and(k<1) then result="Prolog "..tostring(k+11) end
	if (k>=1)and(k<500) then result="Kapitel "..tostring(k) end
	if (k>=501)and(k<=510) then result="Epilog "..tostring(k-500) end
	if (k>=511)and(k<=520) then result="Anhang "..tostring(k-510) end
	if (k>=521) then result="Folgehandlung "..tostring(k-520) end
	return result
end

--Umrechnung der angezeigten Kapitelnummern
function kapitelnokurz(k)
	local result=""
	local k=tonumber(k)
	if (k==nil) then return "" end
	if (k>=-100)and(k<-10) then result="V"..tostring(k+101) end
	if (k>=-10)and(k<1) then result="P"..tostring(k+11) end
	if (k>=1)and(k<500) then result="K"..tostring(k) end
	if (k>=501)and(k<=510) then result="E"..tostring(k-500) end
	if (k>=511)and(k<=520) then result="A"..tostring(k-510) end
	if (k>=521) then result="F"..tostring(k-520) end
	return result
end

--Ausgabe einer Pivot-Tabelle als Text bis zu maximal Anzahl Einträgen,
--Das oberste Siebtel (aber mindestens der erste Eintrag) bestimmt, bis zu welchem Wert fettgedruckt wird
--Wenn Kategorie auf 1, wird auch passend kategorisiert (bei Handlungsorten), bei 2 nur kategorisiert (bei Jahren)
function outputtabelle(tabelle,anzahl,kategorie)
	local s=""
	local i=0
	if(#tabelle==0) then
		return s
	end
	local tkeys=getSortKeys(tabelle)
	local f=tabelle[tkeys[1]][2]
	for _,k in ipairs(tkeys) do
		if _<(#tabelle/7) then
			f=tabelle[k][2]
		end
		local ft=""
		if tabelle[k][2]>=f then
			ft="'''"
		end
		if kategorie>0 then
			s=s..outputkategorie(tabelle[k][1])
		end
		if kategorie<2 then
			s=s..ft..outputlink(tabelle[k][1]).." ("..tabelle[k][2].."x)"..ft
			if next(tabelle,_)~=nil then
				s=s..",&#32;"
			end
		end
		i=i+1
		if i>anzahl then
			return s
		end
	end
	return s
end

--Ausgabefunktion für die Kapitelreihe
function output(frame,kapitel,reihe,logobild,klappe,sammlung)
	local s="[[Kategorie:Briefspielreihe]]"
	local kp=0
	--Wenn keine Kapitel vorhanden, brich ab
	if(#kapitel==0) then
		return s
	end
	
	--Definition des Titelblocks mit Statistischen Daten
	local z=""
	local autoren=outputtabelle(kapitel['statistik']['autoren'],10000,0)
	z=z..subZeilengruppe('Irdisches',
		subZeile('Irdischer Zeitraum',kapitel['statistik']['minerstellt'].." '''bis''' "..kapitel['statistik']['maxerstellt'])
		..subZeile('Geschrieben von',autoren)
	)
	z=z..subZeilengruppe('Aventurisches',
		subZeile('Zeitraum der Haupthandlung',kapitel['statistik']['minzeit'].." '''bis''' "..kapitel['statistik']['maxzeit'])
		..subZeile('Hauptdarsteller',outputtabelle(kapitel['statistik']['darsteller'],10000,0))
		..subZeile('Handlungsorte',outputtabelle(kapitel['statistik']['handlungsorte'],10000,1))
	)..outputtabelle(kapitel['statistik']['jahre'],10000,2)
	local links=""
	local logo=logobild
	if logo~="" then
		logo='Datei:'..logo
	else
		logo='Datei:Wappen blanko.svg'
	end
	if sammlung~="ja" then
		sammlung="falsch"
	else
		sammlung="wahr"
	end
	links='[['..logo..'|150px|link=]]'
	s=s..subTitelblock('&nbsp;',links,z,'&nbsp;','<div style="text-align:justify;padding:10px;font-size:1.3em;">'..klappe..'</div>',klappe,logobild)
	
	--Ausgabe des Inhaltsverzeichnisses als Tabelle
	s=s..'\n==Inhaltsverzeichnis==\n'
		..'{| class="tabellehuebsch"\n'
		..'|-\n'
		..'!\n'
		..'!Kapitel\n'
		..'!Titel\n'
		..'!Inhalt\n'
		..'!Zeit\n'
		..'!geschrieben von\n'
	local tkeys=getSortKeys(kapitel)
	local map=''
	for _,k in ipairs(tkeys) do
		if k~="statistik" then
			local ka=""
			if kapitel[k][2]==0 then
				kp=kp+1
				ka=kapitelno(kp)
			else
				ka=kapitelno(kapitel[k][2])
			end
			s=s.."|-\n"
				..'||[['..kapitel[k][13][1].."|30px|link=]]"
				.."||"..ka
				.."||[["..kapitel[k][1].."|"..kapitel[k][6][1].."]]"
				.."||"..nonilstring(kapitel[k][7][1])
				.."||"..nonilstring(kapitel[k][4][1])
				.."||"
			local autoren=""
			if #kapitel[k][5]>0 then
				for _,v in ipairs(kapitel[k][5]) do
					autoren=autoren..outputlink(v)..", "
				end
			end
			s=s..mw.ustring.sub(autoren,1,mw.ustring.len(autoren)-2)
			s=s.."\n"
			if #kapitel[k][15]>0 then
				for _,v in ipairs(kapitel[k][15]) do
					if v~="" then
						map=map.."\nHauptdarsteller:"..kapitel[k][1]..";0!14;;"..v
					end
				end
			end
		end
	end
	s=s.."|}\n"
	map=map..'\n'
	
	--Aufruf der Chronik-Vorlage
	s=s..frame:expandTemplate{title='Abfrage Chronik',args={reihe..' — Briefspielreihe'}}

	--Ausgabe der Übersichtskarte
	s=s..'\n==Übersichtskarte==\n'
	s=s..'<div style="width:100%;text-align:center;">'
		..frame:callParserFunction{name='#mapview',args={'LOD=7\nGws=0\nWld=0\nBrg=0\nGrz=1\nWeg=0\nOrt=0\nBau=0\nFlc=1\nsize=1\nnotload=Berge Gewaesser Waelder Wege Ortschaften Detail',map}}
		..frame:callParserFunction{name='#set',args={
			'Kurzbeschreibung='..klappe,
			'Wappen ist='..logo,
			'Handlungszeittext ist='..kapitel['statistik']['minzeit'].." '''bis''' "..kapitel['statistik']['maxzeit'],
			'Briefspiel-Zeitindex ist='..kapitel['statistik']['medzeitindex'],
			'Reihenautoren='..autoren,
			'Sammlung='..sammlung,
			'Reihe ist='..reihe
		}}
		..'</div>'
		
	return s
end

--Aufzurufende Funktion, erwartet diese Parameter
-- 1: Name der Briefspielreihe (Pflicht)
-- 2: Logo ohne den "Datei:"-Vorsatz
-- 3: Klappentext
function p.briefspielreihe(frame)
	local reihe=robusttrim(frame.args[1])
	local logo=robusttrim(frame.args[2])
	local klappe=robusttrim(frame.args[3])
	local sammlung=robusttrim(frame.args[4])
	if(reihe=='') then return '' end
	local kap=holeKapitel(reihe)
	local inh=holeDetails(kap)
	return output(frame,inh,reihe,logo,klappe,sammlung)
end

--Funktion für den Briefspielindex/Reihenindex, Parameter
-- 1: Kapitelnummer
-- 2: Anzeigeformat 1=lang, 2=kurz
function p.kapitelname(frame)
	local kapitel=robusttrim(frame.args[1])
	local anzeige=robusttrim(frame.args[2])
	if anzeige=='1' then return kapitelno(kapitel) end
	if anzeige=='2' then return kapitelnokurz(kapitel) end
	return ''
end

return p