Főmenü megnyitása

Modul:Dallisták szerzővel

Source code project 1171.svg 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éterekSzerkeszté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.

PéldákSzerkeszté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őkSzerkeszté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 = ' || '


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

local function sablon(txt, frame)       -- 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,frame)            -- a select rész végrehajtása

local ret = ''

-- 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
        i = 0
        for w in string.gmatch(oszlopstr,'[^,]+') do
                i = i+1
                oszloptomb[ string.gsub(w,',$','') ] =  i 
        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

-- 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
        ret = ret..tblsoreleje..'[['..i..']]'     -- szócikk címe
        darab = darab + 1
        if szerzoflg then                         -- szerző/dallam/szöveg együtt
               if (t['szerző'] or '') ~= ''
               then    ret = ret..ujmezo..'colspan="2" align="center" | '..sablon(t['szerző'],frame)        -- ugyanaz a dallam és a szöveg szerzője
               else    ret = ret..ujmezo..sablon(t['dallam'],frame)..ujmezo..sablon(t['szöveg'],frame)      -- 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]],frame)
        end
end
if not nosum 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,frame)

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 = frame.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)
local daltomb = mw.loadData( "Module:Kották metaadatai" )

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

return p