Modul:Dallisták szerzővel

Dallisták szerzővel[mi ez?] • [dokumentáció: mutat, szerkeszt] • [tesztek: létrehozás]

A modul célja egytáblás lekérdezések végrehajtása. A tábla adatait egy program gyűjti össze, és (egyelőre) kézzel kerül a Kották metaadatai modulba. A lekérdezések kimenete wikitáblázat fejléc nélkül (így a feliratokat nem kell paraméterben átadni a modulnak). A hívó sablonban a táblázat rendezhetővé tehető. A táblázat lezárása is a hívó sablon dolga, így több modulhívás tehető egy táblázatba.

A modul által végezhető lekérdezések általános alakja SQL-ben:

select oszloplista from Kották_metaadatai where szűrőfeltételek group by oszlop order by oszloplista;

Miután a kimenet-tábla rendezhető, a modul (egyelőre) nem rendez.

Paraméterek szerkesztés

A modulnak egyetlen belépési pontja van: a dallista függvény.

Oszloplista
Oszlopok = oszlop1, oszlop2, … , ahol oszlopn a Dal infobox valamelyik mezője. A szócikk címe mindig belekerül a kimenet első oszlopába. Ha az Oszlopok-ban meg van adva a Szerző, továbbá a Dallam és Szöveg valamelyike, akkor e három mező egymás melletti két oszlopba kerül, közvetlenül a szócikk címe után. A Szerző oszlopa dupla széles. E kivételtől eltekintve az oszlopok a paraméterben megadott sorrendben íródnak ki.
Szűrőfeltételek
oszlop1 = érték1|oszlop2 = érték2| … , ahol oszlopn jelentése azonos az oszloplistabelivel, értékn a mező értéke. Csonkítás, wildchard nem lehetséges. Az összehasonlítás előtt a modul törli a <ref>…</ref> közötti szöveget és az érték linkjét. A szűrőfeltételek ÉS kapcsolatban állnak. OR-t két modulhívással lehet elérni.
NOT a mező eleji felkiáltójellel adható meg. A két felkiáltójel az eredményből kizárja az üres értékeket.
Ha a szűrőfeltételben az oszlop dallam vagy szöveg, és annak értéke üres, a kiértékelésben az érték a szerző oszlop értéke lesz. Más szóval: a dallam mezőben megadott komponistát akkor is megtalálja a program, ha az infoboxban a szerző mezőben adtuk meg. Ez a tulajdonság NOT-tal (felkiáltójellel) kombinálva esetleg nem várt eredményt okozhat.
Group by
Groupby = oszlop. Kétoszlopos táblázatot hoz létre úgy, hogy az azonos értékű oszlopokat egyszer írja ki, a második oszlopba az előfordulási szám kerül. A Groupby szűrőfeltételekkel kombinálható, de oszloplista nem adható meg (pontosabban: figyelmen kívül marad).
Nosum
Group by használatakor nem ír Összesen sort. A paraméternév után ki kell írni az = jelet, értéket nem kell megadni.
Felsorolás
Felsorolás = szint. Táblázat helyett szint szintű wikifelsorolás használata, ha egy oszlopos lenne a táblázat. (Ha a cikkcímeken kívül más is kerül a táblázatba, akkor ez a paraméter figyelmen kívül marad. Ellenkező esetben a Nosum paramétert automatikusan bekapcsolja, így felsorolásos lista végére soha nem kerül összegsor.) Például a Felsorolás=2 két csillaggal kezdett (második szintű) listát generál.

Példák szerkesztés

{| class="wikitable sortable"
|+ Magyar komolyzenei szócikkek
! Szócikk !! Dallam !! Szöveg
{{#invoke:Dallisták szerzővel|dallista|műfaj=magyar komolyzenei dal|Oszlopok=szerző,dallam,szöveg}}
|}
Magyar népdalok stílus szerint
Szócikk Darab
új 60
régi 100
vegyes 58
nincs megadva 44
Összesen 262

A fenti sablonhívás eredménye a bal oldali táblázatban.

Magyar komolyzenei szócikkek
Szócikk Dallam Szöveg
Szózat Egressy Béni Vörösmarty Mihály
Jancsi belépője Kacsóh Pongrác Heltai Jenő
Furulya nóta Kacsóh Pongrác Heltai Jenő
Magyar ünnepi dal Liszt Ferenc
A francia királylány dala Kacsóh Pongrác Heltai Jenő
Székely himnusz Mihalik Kálmán Csanády György
Hazám, hazám Erkel Ferenc Nádasdy Kálmán
Iluska dala Kacsóh Pongrác Heltai Jenő
Egy rózsaszál Kacsóh Pongrác Heltai Jenő
Kék tó, tiszta tó Kacsóh Pongrác Heltai Jenő
A Reményhez Kossovits József Csokonai Vitéz Mihály
Meghalt a cselszövő Erkel Ferenc Egressy Béni
Hétfő, kedd Bárdos Lajos
Summáját írom Tinódi Lantos Sebestyén
Magyarország himnusza Erkel Ferenc Kölcsey Ferenc
Rákóczi-induló Nikolaus Scholl
Összesen: 16

Példa group by-os lekérdezésre:

{| class="wikitable sortable" align="right"
|+ Magyar népdalok stílus szerint
! Szócikk !! Darab
{{#invoke:Dallisták szerzővel|dallista|műfaj=magyar népdal|Groupby=stílus}}
|}

Az eredmény a jobb oldali táblázatban.

Azok a népdalok, melyeknek üres a kadenciája: …|kadencia=|…. Amelyeknek nem üres: …|kadencia=!|….

A nem négysoros magyar népdalok (beleértve azokat is, ahol a sorok száma nincs megadva: …|dalsor=!4|műfaj=magyar népdal|…

Azok a nem négysoros magyar népdalok, ahol a sorok száma meg van adva: …|dalsor=!!4|műfaj=magyar népdal|…

Teendők szerkesztés

  • Groupby-ba link az 1-darabos tételekre
local p = {}

local dalpar = {}              -- Dal_infobox paraméternevei és a paraméterek típusa
-- A Dal_infobox-ból kapott paraméterek:
dalpar['ambitus'] = ''
dalpar['cím'] = ''
dalpar['dallam'] = ''
dalpar['dobszay'] = ''
dalpar['előadásmód'] = ''
dalpar['év'] = ''
dalpar['fordító'] = ''
dalpar['gyűjtő'] = ''
dalpar['hangfaj'] = ''
dalpar['hangnem'] = ''
dalpar['hely'] = ''
dalpar['helynév'] = ''
dalpar['kadencia'] = ''
dalpar['megye'] = ''
dalpar['mnt'] = ''
dalpar['műfaj'] = ''
dalpar['nyelv'] = ''
dalpar['sorok'] = ''
dalpar['stílus'] = ''
dalpar['szerző'] = ''
dalpar['szótag'] = ''
dalpar['szöveg'] = ''
dalpar['tempó'] = ''
dalpar['bartók'] = ''
dalpar['típus'] = ''
dalpar['vargyas'] = ''
dalpar['vargyas2'] = ''
-- A Dal_infobox-ból át nem vett paraméterek: kép képaláírás képméret
-- Robottól kapott paraméterek ('a': ambitus típus):
dalpar['amb1s1'] = 'a' dalpar['amb1s2'] = 'a' dalpar['amb1sor'] = 'a'
dalpar['amb2s1'] = 'a' dalpar['amb2s2'] = 'a' dalpar['amb2sor'] = 'a'
dalpar['amb3s1'] = 'a' dalpar['amb3s2'] = 'a' dalpar['amb3sor'] = 'a'
dalpar['amb4s1'] = 'a' dalpar['amb4s2'] = 'a' dalpar['amb4sor'] = 'a'
dalpar['amb5s1'] = 'a' dalpar['amb5s2'] = 'a' dalpar['amb5sor'] = 'a'
dalpar['amb6s1'] = 'a' dalpar['amb6s2'] = 'a' dalpar['amb6sor'] = 'a'
dalpar['amb7s1'] = 'a' dalpar['amb7s2'] = 'a' dalpar['amb7sor'] = 'a'
dalpar['ambdal'] = 'a' dalpar['ambmax'] = 'a' dalpar['ambmin'] = 'a'
dalpar['dalsor'] = ''
dalpar['kad1'] = 'a' dalpar['kad2'] = 'a'  dalpar['kad3'] = 'a'  dalpar['kad4'] = 'a' dalpar['kad5'] = 'a' dalpar['kad6'] = 'a'
dalpar['szot1'] = '' dalpar['szot2'] = ''  dalpar['szot3'] = ''  dalpar['szot4'] = '' dalpar['szot5'] = '' dalpar['szot6'] = '' dalpar['szot7'] = ''
dalpar['utmod'] = '' dalpar['creusr'] = '' dalpar['credat'] = ''


local tblsoreleje = '\n|-\n| '
local osszeleje  = "\n|-\n!Összesen"
local ujmezo = ' || '
local frame = mw.getCurrentFrame()


--****************** Helyi függvények ***************

local function sablon(txt)       -- stringbeli sablon feldolgozása
	if txt == nil then return '' end
	return frame:preprocess(txt)
end


local function hasonl(egyik,masik)      -- a paraméterek rendezőfüggvénye
return egyik[2] < masik[2]
end


local function lnkstrip(str)            -- leszedi a wikilinkeket a stringből. Az alternatív szöveget hagyja meg, ha van.
if str then
      ret = string.gsub(str,'%[%[[^|]*|','%[%[')    -- a link törlése, ha van alternatív szöveg
      ret = string.gsub(ret,'%[%[','')              -- [[-k törlése
      return string.gsub(ret,'%]%]','')             -- ]]-k törlése
else  return nil
      end
end


local function felhang(amb)             -- az ambitust félhangra alakítja
if not amb then return '' end
local romai = {}
romai['I'] = -12 romai['II'] = -10 romai['III'] = -8 romai['IV'] = -7 romai['V'] = -5 romai['VI'] = -3 romai['VII'] = -2
local arab = {}
arab[0] = 0 arab[1] = 2 arab[2] = 4 arab[3] = 5 arab[4] = 7 arab[5] = 9 arab[6] = 10
local modjel = {}
modjel["♯"] = 1  modjel["♭"] = -1

local kar = string.sub(amb,1,3) -- kihasznaljuk, hogy a b es a kereszt utf8-kodja egyarant 3 hosszu
local ret = modjel[kar]
if ret then kar = string.sub(amb,4) else ret = 0 kar = amb end          -- a módosítójel kész
if romai[kar] then return ret + romai[kar] end                          -- a római szám kész
local szam = tonumber(kar)
if szam
then    if szam > 0 then szam = szam-1 else szam = 0 end
        return ret + math.floor(szam/7)*12 + arab[szam%7];
end
return 0
end

local function tblcopy(be)   -- shallow copy. Akkor kell, ha "be" írásvédett
ki = {}
for x,y in pairs(be)
do  ki[x] = y
end
return ki
end

--****************** select: az SQL select-részének végrehajtása ***************

local function select(daltomb, oszlopstr, nosum, felsorolas)
	local ret = ''
	local oszlopok = 0

	-- Paraméterátvétel
	oszloptomb = {}
	if oszlopstr then
		if string.sub(oszlopstr,-1,1) ~= ',' then oszlopstr = oszlopstr..',' end
		oszlopstr = string.gsub(oszlopstr,'[%s]*,[%s]*',',')      -- leszedjuk a helyközöket a vessző körülről
		for w in string.gmatch(oszlopstr,'[^,]+') do
			oszlopok = oszlopok + 1
			oszloptomb[ string.gsub(w,',$','') ] = oszlopok
		end
	end
	if oszloptomb['szerző'] and (oszloptomb['dallam'] or oszloptomb['szöveg']) then
		szerzoflg = true     -- két egymás melletti oszlopba a három mezőt
		oszloptomb['szerző'] = nil
		oszloptomb['dallam'] = nil
		oszloptomb['szöveg'] = nil
	else
		szerzoflg = false
	end
	-- Megpróbáljuk számmá alakítani. Ha több oszlopunk van, vagy nem sikerül,
	-- hamis logikai értékű lesz, tehát táblázatot készítünk
	felsorolas = oszlopok == 0 and tonumber(felsorolas)
	if not felsorolas or felsorolas < 1 then
		felsorolas = nil
	end

	-- A paraméterek rendezése. 
	munkatbl = {}       -- áttöltjuk paramtomb-öt normál tömbbe, hogy rendezni lehessen
	for i, t in pairs(oszloptomb) do      
		table.insert(munkatbl, {i, t}) 
	end
	table.sort(munkatbl, hasonl)      -- rendezés

	-- Kiírás
	local darab = 0
	for i, t in pairs(daltomb) do
		darab = darab + 1
		if felsorolas then
			if ret ~= '' then
				-- első sor elé nem kell, hogy egyben maradjon a wikis felsorolás
				ret = ret .. '\n'
			end
			ret = ret .. string.rep('*', felsorolas) .. ' [[' .. i .. ']]'
		else
			ret = ret..tblsoreleje..'[['..i..']]'     -- szócikk címe
			if szerzoflg then                         -- szerző/dallam/szöveg együtt
				if (t['szerző'] or '') ~= '' then
					ret = ret..ujmezo..'colspan="2" align="center" | '..sablon(t['szerző'])        -- ugyanaz a dallam és a szöveg szerzője
				else
					ret = ret..ujmezo..sablon(t['dallam'])..ujmezo..sablon(t['szöveg'])            -- különböző
				end
			end
			for j, u in pairs(munkatbl) do      -- a többi oszlop kiírása
				if dalpar[u[1]] == 'a' then
					partip = 'data-sort-value='..felhang(t[u[1]])..'|'
				else
					partip = ''
				end
				ret = ret..ujmezo..partip..sablon(t[u[1]])
			end
		end
	end
	if not nosum and not felsorolas then
		ret = ret..osszeleje..": "..darab
	end

	return ret
end


--****************** groupby: az SQL group by részének végrehajtása ***************


local function groupby(tomb,oszlop)
local jobbra = ujmezo..'align="right" |'
local ures = 0        -- nincs megadva az oszlop
local darab = 0       -- összesen
local stat = {}       -- darabszámok
local egy  = {}       -- az 1 darabhoz tartozó érték

-- Számlálás
for i,t in pairs(tomb) do
    local str = lnkstrip(t[oszlop])
    if str and string.len(str) > 0
    then stat[str] = (stat[str] or 0) + 1
         egy[str]  = '[['..i..']]'
    else ures = ures+1
    end
    darab = darab + 1
end

-- Kiírás
local ret = ''
for i,t in pairs(stat) do
    ret = ret..tblsoreleje..i..jobbra
    if egy[i] and t == 1
    then    s = string.match(egy[i],'^%[%[[^|%]]+')
            if s ~= nil
            then     ret = ret..s..'|1]]'
            else     ret = ret..t
            end
    else    ret = ret..t
    end
end
if ures > 0 then ret = ret..tblsoreleje.."''nincs megadva''"..jobbra..ures end
return ret..osszeleje..'!! style="text-align: right" | '..darab
end



--****************** where: az SQL where részének végrehajtása ***************


function p.where(daltomb, args)

local partomb = {}                -- A szűrőparamétereket áttesszük partomb-be.
local negtomb = {}                -- !-jel kezdődő (negált) feltételek
local par
--local ret = 'where'

local ret = 'paramtomb<br>'
for i, t in pairs(dalpar)
do      par = args[i]
        if par        -- i szerepel a where-feltételek között, az érték par kell legyen, hogy a where teljesüljön
        then   x,y = string.find(par,'^!%s*')
               --ret = ret..'i='..i..',par='..par..', x='..x..',y='..y..'<br>'
               if x
               then   partomb[i] = string.sub(par,y+1)     -- negálás van a megkívánt értékben
                      negtomb[i] = 1
                      x,y = string.find(partomb[i],'^!%s*')
                      if    x
                      then  negtomb[i] = 2
                            partomb[i] = string.sub(partomb[i],y+1)  -- kettős negálás
                      end
               else   partomb[i] = par                     -- nincs negálás
               end
        --ret = ret..partomb[i]..', '..par..'<br>'
        end
end
-- partomb a where-feltételekbeli értékeket tartalmazza, negtomb azt, van-e negálás. Mindkét tömb kulcsa a Dal_infobox egyik paramétere.
--ret = ret..'paramtomb vege<p>'

local eredm = {}

for i,t in pairs(daltomb)               -- végigmegy a Dal_infoboxon
do      local flg = true
        --ret = ret..i..'<br>'
        for j,p in pairs(partomb)       -- végigmegyünk a where-feltételeken. j a Dal_infobox mezőneve, p a where-ben megkívánt értéke
        do       local ertek = t[j]                     -- a Dal_infobox i nevű mezőjének tényleges értéke
                 if (ertek or '') == '' and (j == 'dallam' or j == 'szöveg') then ertek = t['szerző'] end     -- ha nincs dallam vagy szöveg , a szerző is megteszi
                 local tj = lnkstrip(ertek) or ''       -- a Dal_infobox i nevű mezőjének link nélküli értéke
                 --ret = ret..'*** i = '..i..', j = '..j..', tj = '..(tj or '')..', p = '..(p or '')..'<br>'
                 f = tj == p                              -- f igaz, ha az i paraméterre teljesül a where-feltétel
                 if negtomb[j] then f = not f end         -- de nem szabad igaznak lennie
                 if not f or (negtomb[j] == 2 and tj == '') then flg = false break end
                 --ret = ret..i..', flg = true<br>'
        end
        if flg  then eredm[i] = t 
                     if (eredm[i]['dallam'] or '') == ''
                     then eredm[i] = tblcopy(t)    -- mert t csak olvasható
                          eredm[i]['dallam'] = t['szerző']
                          end
                     if (eredm[i]['szöveg'] or '') == '' 
                     then eredm[i] = tblcopy(eredm[i])    -- mert lehet, hogy eredm[i] csak olvasható
                          eredm[i]['szöveg'] = t['szerző']
                     end
           --ret = ret..'i = '..i..'<br>'
           end  -- az eredménytömb ugyanolyan szerkezetű, mint az eredeti dallistáké
end

--[[   teszt
for i, t in pairs(eredm)
do      ret = ret..i
        for j, u in pairs(partomb)
        do      ret = ret..', '..u
        end
end
return ret..'where vege<br>'
]]

return eredm
end


--****************** dallista: a modul belépési pontja ***************
-- dalpar:  a metaadatnevek
-- daltomb: a metaadatok értékei (r/o)
-- oszloptomb: tisztitott értékek

function p.dallista(frame, daltomb)
	if not daltomb then
		daltomb = mw.loadData('Module:Kották metaadatai')
	end
	local args = require('Modul:Arguments').getArgs(frame, {removeBlanks = false})

	local szurt = p.where(daltomb, args)
	if args['Groupby'] then
		return groupby(szurt, args['Groupby'])
	else
		return select(szurt, args['Oszlopok'], args['Nosum'], args['Felsorolás'])
	end
end

return p