Closed gyuris closed 9 years ago
Ez igy tökéletes.
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:
Kedves Gellért! Te aztán nem lazsálsz! :-)
A csomagolt könyvtárak szerintem jók.
A file nevekkel kapcsolatban...
É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.
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);
});
};
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...
É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.
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?
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.
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.
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. :-)
OK, a funkció elkészült és a refactor-build
branch-ben van:
/master
mappából a /songbooks
mappába. Közben módosítja az XML-t, hogy csak az adott <songbook />
bejegyzés maradjon az állományban.7z
állományba csomagolja.A futtatásról a wiki oldalra írtam segédletet.
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
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.:Készüljön egy
build
szkript (nem tudom milyen nyelven), amely végiglépdel az összes éneken és/songbooks/Szent András Énekfüzet
(ezt kizárjuk a git forrásból),/Szent András Énekfüzet.zip
,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.