gyuris / aszaf

Magyar Keresztény OpenLyrics adatbázis
Creative Commons Attribution Share Alike 4.0 International
8 stars 3 forks source link

Egy adatbázis és gyűjtemények #2

Closed gyuris closed 9 years ago

gyuris commented 9 years ago

Számunkra fejlesztőknek cél, hogy egy dalt csak egy helyen tartsunk karban. De az is cél, hogy a felhasználók egy kattintással kész gyűjteményeket tölthessenek le, ne kelljen kimazsolázniuk, hogy mit kérnek és mit nem.

Alakítsuk át a jelenlegi struktúrát build-es rendszerre.

Legyen egy forrásadatbázis (pl. /master mappa) Itt ne legyenek gyűjtemények mappái. Itt minden dalban legyen benne, hogy milyen gyűjteményben hogyan szerepel. A többszörösséget az OpenLyrics most is megengedi. Pl.:

<songbooks>
  <songbook name="Szent András Énekfüzet" entry="156"/>
  <songbook name="Sárga könyv" entry="212"/>
</songbooks>

Készüljön egy build szkript (nem tudom milyen nyelven), amely végiglépdel az összes éneken és

A buildelés kiadásonként történjék. Minden módosítás után ne futassuk le a buildelést, hanem legyenek kiadások.

triszterer commented 9 years ago

Ez igy tökéletes.

gyuris commented 9 years ago

Egy PoC kód NodeJS-ben megvalósítva:

/*
TELEPÍTÉS
sudo apt-get install npm
npm install xpath
npm install xmldom
*/

// csomagok
var fs      = require('fs');
var xpath   = require('xpath');
var dom     = require('xmldom').DOMParser;

// állandók
const MASTER    = '../master/'; // a mester könyvtár helye a util-hoz viszonyítva
const EXPORT = '../songbooks/'; // az export könyvtár helye a util-hoz viszonyítva

// olvassuk az összes fájlt a könyvtárból egyenként
var files = fs.readdirSync(MASTER);
for (var i in files) {
    // kiolvassuk a fájl statisztikai adatait, hogy később az időbélyeget be tudjuk állítani
    var stat = fs.statSync(MASTER + files[i]);
    // megnyitjuk a fájlt
    var data = fs.readFileSync( MASTER + files[i], { encoding : 'UTF-8' });
    // a tartalmát DOM-má alakítjuk
    var doc = new dom().parseFromString(data);
    // kiolvassuk a gyűjteményeket
    var select = xpath.useNamespaces({"song": "http://openlyrics.info/namespace/2009/song"});
    var nodes  = select('//song:songbook[@name]', doc);
    // minden gyűjteményre 
    for (j = 0; j < nodes.length; j++) {
        // kiolvassuk a gyűjtemények nevét és a dal számát
        var name  = select("@name", nodes[j])[0].value;
        var entry = select("@entry", nodes[j])[0].value;
        // ha még nincs a gyűjtemény nevével megegyező mappa, akkor létrehozzuk
        if (!fs.existsSync(EXPORT + name)){
            fs.mkdirSync(EXPORT + name);
        }
        // kiírjuka  fájl tartalmát gyűjtmény nevével megyegező export mappába
        fs.writeFileSync(EXPORT + name + '/' + files[i], data); 
        // szinkronizáljuk az új fájl időbélyegét a régihez
        fs.utimesSync(EXPORT + name + '/' + files[i], stat.atime, stat.mtime);
        // log
        console.log(EXPORT + name + '/' + files[i] + ' -> ' + name + ': ' + entry);
    }
}

Ami még nincs benne:

triszterer commented 9 years ago

Kedves Gellért! Te aztán nem lazsálsz! :-)

A csomagolt könyvtárak szerintem jók.

A file nevekkel kapcsolatban...

  1. Lehetséges volna, hogy a file nekevekből eltávolítsuk az ékezetes karaktereket. Igy tudjuk a ZIP-et is használni. Ez nem volna hátrány mert sokan csak ezt ismerik és windows is támogatja.
  2. Másik megoldás lehet, hogy egy másik tömöritővel készülne a csomag. pl 7z.

Én a régi verziótól megszabulnék. Miért érdekelne a régi énekfüzett, ha van egy javított és bővebb verzió?

Ha felül kell írni egy file-t az exportálás sorána akkor baj van. Ez nem kellene, hogy magtörténjen, mivel a master adatbázisban már egy dal csak egyszer szerepelhet.

gyuris commented 9 years ago

No, megvan a csomagolás 7z-vel és a többszörös gyűjtemények neveinek kigyomlálása az export alatt.

/*
TELEPÍTÉS
sudo apt-get install npm p7zip-full
npm install xpath
npm install xmldom
npm install --save node-7z
*/

// csomagok
var fs      = require('fs');
var xpath   = require('xpath');
var dom     = require('xmldom').DOMParser;
var zip      = require('node-7z');

// állandók
const MASTER    = '../master/'; // a mester könyvtár helye a util-hoz viszonyítva
const EXPORT    = '../songbooks/'; // az export könyvtár helye a util-hoz viszonyítva
const NAMESPACE = 'http://openlyrics.info/namespace/2009/song'

// olvassuk az összes fájlt a könyvtárból egyenként
var files = fs.readdirSync(MASTER);
for (var i in files) {
    // kiolvassuk a fájl statisztikai adatait, hogy később az időbélyeget be tudjuk állítani
    var stat = fs.statSync(MASTER + files[i]);
    // megnyitjuk a fájlt
    var data = fs.readFileSync( MASTER + files[i], { encoding : 'UTF-8' });
    // a tartalmát DOM-má alakítjuk
    var doc = new dom().parseFromString(data);
    // kiolvassuk a gyűjteményeket
    var select = xpath.useNamespaces({"song": NAMESPACE});
    var nodes  = select('//song:songbook[@name]', doc);
    // minden gyűjteményre 
    for (j = 0; j < nodes.length; j++) {
        // kiolvassuk a gyűjtemények nevét és a dal számát
        var name  = select("@name", nodes[j])[0].value;
        var entry = select("@entry", nodes[j])[0].value;
        // ha még nincs a gyűjtemény nevével megegyező mappa, akkor létrehozzuk
        if (!fs.existsSync(EXPORT + name)){
            fs.mkdirSync(EXPORT + name);
        }
        // módosítjuk az XML-t
        if ( nodes.length > 1 ) { // ahol csak egy gyűjtemény van, nem kell változtatni semmit
            // lemásoljuk az XML struktúrát
            var copy = new dom().parseFromString(data);
            // töröljük a gyűjteményeket
            var songbooks = select('//song:songbooks', copy)[0];
            while (songbooks.firstChild) {
                songbooks.removeChild(songbooks.firstChild);
            }
            // az aktuálisat belerakjuk
            var clone = nodes[j].cloneNode();
            songbooks.appendChild(clone);
        }
        // kiírjuka  fájl tartalmát gyűjtmény nevével megyegező export mappába
        fs.writeFileSync(EXPORT + name + '/' + files[i], (nodes.length > 1) ? copy.toString() : data); 
        // szinkronizáljuk az új fájl időbélyegét a régihez
        fs.utimesSync(EXPORT + name + '/' + files[i], stat.atime, stat.mtime);
        // log
        //console.log(EXPORT + name + '/' + files[i] + ' -> ' + name + ': ' + entry);
    }
}
// Csomagolás: listázzuk az össze export könyvtárat
var files = fs.readdirSync(EXPORT);
for (var i in files) {
    // minden gyűjteménynek létrehozunk egy 7z csomagot
    var archive = new zip();
    // beolvasunk mindent xml fájlt és elmentjük a gyökérbe a gyűjtemény nevével
    archive.add( '../' + files[i] + '.7z', EXPORT + files[i] + '/*.xml')
    .progress(function (files) {
      console.log( 'Zipped -> %s', files);
    })
    .catch(function (err) {
        console.error(err);
    });
};
gyuris commented 9 years ago

Már csak a CSV előállítás van hátra. Egy kérdés: Mit kezdjek a többszörös gyűjtemény nevekkel? Egy normális adat így nézne ki:

"Dal címe","Szerző","Gyűjtemény","Száma"
"XY","ZY","Szent András Énekfüzet","212"

De itt vannak a több gyűjteményben is előforduló dalok. Mi legyen a struktúrája a CSV-nek?

Egyiket sem tartom jó megoldásnak...

triszterer commented 9 years ago

Én bele sem tenném a CVS-be a gyüjtemény neveket. A CVS kivonat egy adott ének gyüjtemény tartalom jegyzéke. Nem az a célja, hogy más ének gyüjteményekről adjon információt, hanem csak az adott gyüjtemenyről.

gyuris commented 9 years ago

Hoppá, milyen kényelmi funkciókat gondolsz adni a felhasználóknak :-). Én nem is gondoltam arra, hogy gyűjteményenként adjunk egy tartalomjegyzéket. De igazad van, meg lehet csinálni és hasznos...

Én eredetileg arra gondoltam, hogy nekünk a fejlesztőknek kellene egy összesített, minden egyben tartalomjegyzék, hogy könnyen utána tudjunk járni, hogy egy ének szerepel-e már az adatbázisban egyszer: cím, kezdősor, szerzők... mert hogy a fájlnév alapján simán lennének duplikátumok, mert a cím és a kezdősor gyakran más.

Na szóval, akkor a javaslat:

Jó lesz így?

triszterer commented 9 years ago

Perfecto! :-)

Azt irtad, hogy a "...a fájlnév alapján simán lennének duplikátumok, mert a cím és a kezdősor gyakran más...". Erre figyelni kell. Nem lehet két külömböző éneknek azonos file névvel. A file név egyedi kell hogy legyen.

gyuris commented 9 years ago

Ok, akkor elkezdek ezen dolgozni.

Nem lehet két különböző éneknek azonos fájl névvel. A fájl név egyedi kell hogy legyen.

Igen, egyetértek. Eredetileg pont az ellenkezőjére gondoltam: egy éneket könnyen két példányban is elmenthetünk, anélkül, hogy észrevennénk: egyszer a címe, másik alkalommal meg a kezdősora alapján. Az ilyeneket jól ki lehet majd szűrni a globális jegyzék alapján.

Más: Tamás, maradjon ez a programozó stílusú elnevezés a mappák neveiben: master, songbooks, util vagy csináljunk valami magyarabb elnevezéseket, hogy a felhasználók ne zavarodjanak meg?

Ha ezzel kész leszek, akkor nyitok egy másik branchet neki, hogy lásd te is.

triszterer commented 9 years ago

Nekem mindegy. Szerintem neked is. Akkor legyenek felhasználóbarát nevek. Múltkor úgyis megszóltál, hogy nem gondolok a felhasználókra. :-)

gyuris commented 9 years ago

OK, a funkció elkészült és a refactor-build branch-ben van:

A futtatásról a wiki oldalra írtam segédletet.

gyuris commented 9 years ago

Végül maradtam annál, hogy a repóban a programozós cuccok programozós stílusban legyenek: angol elnevezéssel. A felhasználóknak szánt csomagfájlok lesznek csak rendes szép, beszédes magyar nevekkel.

A hibajegyet lezárom. A további szükséges lépések: #13

gyuris commented 9 years ago

Elkészült a Travis-CI ellenőrzés. Minden kommit után lefut és teszteli a build szkript futását. Ehhez tartoznak a /.travis.yml és a /package.json állományok.