-# coding: utf-8\r
-\r
-require 'rexml/document'\r
-require 'thwait'\r
-\r
-require 'film.rb'\r
-require 'pays.rb'\r
-require 'genre.rb'\r
-require 'personne.rb'\r
-require 'constantes.rb'\r
-require 'iconv'\r
-\r
-# Représente un ensemble de films.\r
-class Films\r
- def initialize(xmlFile, modClasse)\r
- @xmlFile = xmlFile\r
- \r
- @modClasse = modClasse\r
- \r
- # repertoire de base, par exemple C:/Divx/\r
- @repBase = '' \r
- \r
- # Les films indexé par leur titre\r
- @films = {}\r
- \r
- # Les films indexé par leur nom de fichier, deux fichiers différents peuvent pointer sur le même film\r
- @filmsFichier = {}\r
- \r
- # Les films qui ont plusieurs réponses lors de la recherche, traité à la fin\r
- @filmsPlusieursReponses = []\r
-\r
- # Les films qui n'ont aucune réponse après une recherche, traité à la fin\r
- @filmsAucuneReponse = []\r
-\r
- # permet de traiter facilement des groupes de thread\r
- @threadsWait = ThreadsWait::new\r
- @nbConn = 0 # le nombre de connexion\r
- \r
- @mutexAjout = Mutex::new # mutex pour protéger l'ajout\r
- @mutexId = Mutex::new # mutex pour protéger la génération d'id\r
- \r
- # le prochain id disponible\r
- @idDisponible = 1\r
- \r
- chargerFilms\r
- end\r
- \r
- def each\r
- @films.each{|t,f|\r
- yield f\r
- }\r
- end\r
-\r
- # Lit un repertoire de manière recursive et va chercher les informations concernant le film sur le net\r
- def pomper(r)\r
- @repBase = r\r
- repPrecedant = Dir::getwd\r
- Dir::chdir(r)\r
- \r
- t = Time::now\r
- \r
- pomperR('.')\r
- \r
- # on attends que les threads se terminent\r
- @threadsWait.all_waits\r
- \r
- puts "Pompage terminé, temps : #{Time::now - t} secondes"\r
- \r
- # traite les films qui avaient plusieurs réponses lors de la recherche\r
- # l'utilisateur doit faire un choix\r
- i = 1\r
- @filmsPlusieursReponses.each{|f|\r
- puts\r
- puts "Plop, ya un conflit #{i} / #{@filmsPlusieursReponses.length} :"\r
- case f.reglerConflitPlusieursReponses\r
- when 1\r
- ajouterFilm(f) \r
- when 3\r
- break\r
- end\r
- i += 1\r
- }\r
- \r
- # traite les films qui n'avaient aucune réponse\r
- i = 1\r
- @filmsAucuneReponse.each{|f|\r
- puts\r
- puts "Plop, Ce film n'a pas été trouvé #{i} / #{@filmsAucuneReponse.length} :"\r
- case f.reglerConflitPlusieursReponses\r
- when 1\r
- ajouterFilm(f)\r
- when 3\r
- break\r
- end\r
- i += 1\r
- }\r
- \r
- # annonce à chaque module d'importation que c'est fini\r
- @films.each{|t,f|\r
- f.mod.finish\r
- }\r
- \r
- Dir::chdir(repPrecedant) \r
- end\r
- \r
- # Mise à jour des films dans la BD.\r
- # p1 string : un motif Regex correspondant à un ou plusieurs champs\r
- def update(champ, titre)\r
- @films.each{|t, f|\r
- next if !f.titre.match(Regexp::new(titre, true))\r
- \r
- ## si le film est complet on ne fait rien\r
- if $force || f.url == nil || f.titre == '' || f.annee == nil ||\r
- f.realisateurs.empty? || f.acteurs.empty? || f.pays.empty? ||\r
- f.genres.empty? || f.synopsis == nil || !f.possedeImage?\r
- \r
- f.update(champ)\r
- end\r
- }\r
- end\r
- \r
- # Sauve les films dans un fichier XML\r
- def sauverFilms\r
- # le document\r
- docXml = REXML::Document::new\r
- docXml.xml_decl().encoding = "UTF-8" # normalement UTF-8\r
- docXml.xml_decl().dowrite\r
- \r
- # la racine du document\r
- racine = REXML::Element::new('filmographie')\r
- docXml.add(racine)\r
- pi = REXML::Instruction.new("xml-stylesheet", "type=\"text/xsl\" href=\"../xsl/yopyop.xsl\"")\r
- racine.previous_sibling = pi\r
- \r
- # on ajoute chaque film à la racine\r
- @films.each{|nom, f|\r
- racine.add(f.getXml)\r
- } \r
- \r
- # sauve le document\r
- docXml.write(File::new(@xmlFile, 'w'), 0)\r
- end \r
- \r
- private\r
- \r
- # Charge les films depuis le fichier XML\r
- def chargerFilms\r
- # si le fichier n'existe pas il n'y a rien à charger\r
- if !File.exists?(@xmlFile)\r
- return\r
- end\r
- \r
- racine = REXML::Document::new(File::new(@xmlFile)).root\r
- racine.elements.each("film"){|e| \r
- id = e.attribute('id').to_s.to_i\r
- \r
- if id >= @idDisponible\r
- @idDisponible = id + 1 \r
- end\r
- \r
- film = Film::new(nil, @modClasse::new)\r
- film.id = id\r
- \r
- film.titre = e.get_text('titre')\r
- film.titre = film.titre.value if film.titre != nil\r
- \r
- print "#{film.titre}.. "\r
-\r
- \r
- film.url = e.get_text('url')\r
- film.url = film.url.value if film.url != nil\r
-\r
- film.annee = e.get_text('annee')\r
- film.annee = film.annee.value if film.annee != nil \r
- \r
- film.duree = e.get_text('duree')\r
- film.duree = film.duree.value if film.duree != nil\r
- \r
- film.critiquePresse = e.get_text('critiquePresse')\r
- film.critiquePresse = film.critiquePresse.value if film.critiquePresse != nil\r
- \r
- film.critiqueSpectateur = e.get_text('critiqueSpectateur')\r
- film.critiqueSpectateur = film.critiqueSpectateur.value if film.critiqueSpectateur != nil\r
- \r
- film.budget = e.get_text('budget')\r
- film.budget = film.budget.value if film.budget != nil\r
- \r
- e.elements.each('fichiers/fichier'){|f|\r
- next if f.get_text == nil\r
- film.addFichier(f.get_text.value)\r
- @filmsFichier[f.get_text.value] = film\r
- }\r
- \r
- e.elements.each('realisateurs/realisateur'){|f|\r
- film.realisateurs << Personne::ajouter(f.get_text.value)\r
- }\r
- \r
- e.elements.each('acteurs/acteur'){|f|\r
- film.acteurs << Personne::ajouter(f.get_text.value)\r
- }\r
- \r
- e.elements.each('lespays/pays'){|f|\r
- film.pays << Pays::ajouter(f.get_text.value)\r
- }\r
- \r
- e.elements.each('genres/genre'){|f|\r
- film.genres << Genre::ajouter(f.get_text.value)\r
- } \r
- \r
- debut = true\r
- film.synopsis = ""\r
- e.elements.each('synopsis/p'){|f|\r
- film.synopsis += "\n" unless debut \r
- film.synopsis += f.get_text.value if f.get_text != nil\r
- debut = false\r
- } \r
- film.synopsis = nil if film.synopsis == ""\r
- \r
- @films[film.titre] = film\r
- }\r
- end\r
- \r
- # Retourne un nouvel id, utilisé alors de la création d'un nouveau film\r
- def getNewId\r
- id = @idDisponible\r
- @idDisponible += 1\r
- return id\r
- end \r
- \r
- # Ajoute un film à l'ensemble des films.\r
- def ajouterFilm(film)\r
- if film.plusieursReponses?\r
- @filmsPlusieursReponses << film\r
- return\r
- end\r
- \r
- if film.nbReponses == 0\r
- @filmsAucuneReponse << film\r
- return\r
- end\r
- \r
- if @films.has_key?(film.titre)\r
- if !@filmsFichier.has_key?(film.fichiers[0])\r
- puts "[i] Le film #{film.titre} possède une autre partie : #{film.fichiers[0]}"\r
- @films[film.titre].addFichier(film.fichiers[0])\r
- @filmsFichier[film.fichiers[0]] = @films[film.titre] \r
- else\r
- puts "[!] Film déjà dans la BD : #{film.titre} (#{film.fichiers[0]})"\r
- end\r
- else\r
- puts "[i] Film ajouté : #{film.titre} (#{film.fichiers[0]})"\r
- @films[film.titre] = film\r
- @filmsFichier[film.fichiers[0]] = film\r
- end\r
- end\r
- \r
- # Appelé par 'pomper'. Cette méthode itère récursivement sur l'arborescence d'un repertoire.\r
- def pomperR(r)\r
- Dir::foreach(r){|f|\r
- next if f[0,1] == '.'\r
- fichier = (r == '.' ? '' : r + "/") + f\r
- if File::directory?(fichier)\r
- pomperR(fichier) \r
- else\r
- \r
- #CGI::escapeHTML(\r
- fichier = Iconv.iconv("UTF-8", "ISO-8859-1", fichier)[0]\r
- \r
- # véfication de l'extension\r
- /^.*?\.([^.]{3,4})$/ =~ fichier\r
- if !FILMS_EXTENSIONS.include?($1)\r
- next\r
- end\r
- \r
- # on skip si le film est déjà dans la BD\r
- if film = @filmsFichier[fichier]\r
- puts "[!] Film déjà dans la BD : #{film.titre} (#{film.fichiers[0]})"\r
- next\r
- end\r
- \r
- # pour limiter le nombre de connexion simultanée\r
- if @nbConn >= NB_CONN_MAX\r
- @threadsWait.next_wait\r
- end\r
- \r
- @nbConn += 1 \r
- @threadsWait.join_nowait(\r
- Thread::start{\r
- begin \r
- film = Film::new(fichier, @modClasse::new)\r
- @mutexId.synchronize {\r
- film.id = getNewId # on lui donne un nouvel ID\r
- }\r
- film.loadData # on charge ses données\r
- \r
- @mutexAjout.synchronize {\r
- ajouterFilm(film)\r
- } \r
- rescue Exception => e\r
- puts e.message\r
- puts e.backtrace\r
- end\r
- @nbConn -= 1\r
- }\r
- )\r
- end\r
- }\r
- end\r
-end
\ No newline at end of file
+# coding: utf-8
+
+require 'rexml/document'
+require 'thwait'
+
+require 'film.rb'
+require 'pays.rb'
+require 'genre.rb'
+require 'personne.rb'
+require 'constantes.rb'
+require 'iconv'
+
+# Représente un ensemble de films.
+class Films
+ def initialize(xmlFile, modClasse)
+ @xmlFile = xmlFile
+
+ @modClasse = modClasse
+
+ # repertoire de base, par exemple C:/Divx/
+ @repBase = ''
+
+ # Les films indexé par leur titre
+ @films = {}
+
+ # Les films indexé par leur nom de fichier, deux fichiers différents peuvent pointer sur le même film
+ @filmsFichier = {}
+
+ # Les films qui ont plusieurs réponses lors de la recherche, traité à la fin
+ @filmsPlusieursReponses = []
+
+ # Les films qui n'ont aucune réponse après une recherche, traité à la fin
+ @filmsAucuneReponse = []
+
+ # permet de traiter facilement des groupes de thread
+ @threadsWait = ThreadsWait::new
+ @nbConn = 0 # le nombre de connexion
+
+ @mutexAjout = Mutex::new # mutex pour protéger l'ajout
+ @mutexId = Mutex::new # mutex pour protéger la génération d'id
+
+ # le prochain id disponible
+ @idDisponible = 1
+
+ chargerFilms
+ end
+
+ def each
+ @films.each{|t,f|
+ yield f
+ }
+ end
+
+ # Lit un repertoire de manière recursive et va chercher les informations concernant le film sur le net.
+ def pomper(r)
+ @repBase = r
+ repPrecedant = Dir::getwd
+ Dir::chdir(r)
+
+ t = Time::now
+
+ pomperR('.')
+
+ # on attends que les threads se terminent
+ @threadsWait.all_waits
+
+ puts "Pompage terminé, temps : #{Time::now - t} secondes"
+
+ # traite les films qui avaient plusieurs réponses lors de la recherche
+ # l'utilisateur doit faire un choix
+ i = 1
+ @filmsPlusieursReponses.each{|f|
+ puts
+ puts "Plop, ya un conflit #{i} / #{@filmsPlusieursReponses.length} :"
+ case f.reglerConflitPlusieursReponses
+ when 1
+ ajouterFilm(f)
+ when 3
+ break
+ end
+ i += 1
+ }
+
+ # traite les films qui n'avaient aucune réponse
+ i = 1
+ @filmsAucuneReponse.each{|f|
+ puts
+ puts "Plop, Ce film n'a pas été trouvé #{i} / #{@filmsAucuneReponse.length} :"
+ case f.reglerConflitPlusieursReponses
+ when 1
+ ajouterFilm(f)
+ when 3
+ break
+ end
+ i += 1
+ }
+
+ # annonce à chaque module d'importation que c'est fini
+ @films.each{|t,f|
+ f.mod.finish
+ }
+
+ Dir::chdir(repPrecedant)
+ end
+
+ # Mise à jour des films dans la BD.
+ # p1 string : un motif Regex correspondant à un ou plusieurs champs
+ def update(champ, titre)
+ @films.each{|t, f|
+ next if !f.titre.match(Regexp::new(titre, true))
+
+ ## si le film est complet on ne fait rien
+ if $force || f.url == nil || f.titre == '' || f.annee == nil ||
+ f.realisateurs.empty? || f.acteurs.empty? || f.pays.empty? ||
+ f.genres.empty? || f.synopsis == nil || !f.possedeImage?
+
+ f.update(champ)
+ end
+ }
+ end
+
+ # Sauve les films dans un fichier XML
+ def sauverFilms
+ #puts self # print all files before saving in XML
+
+ # le document
+ docXml = REXML::Document::new
+ docXml.xml_decl().encoding = "UTF-8" # normalement UTF-8
+ docXml.xml_decl().dowrite
+
+ # la racine du document
+ racine = REXML::Element::new('filmographie')
+ docXml.add(racine)
+ pi = REXML::Instruction.new("xml-stylesheet", "type=\"text/xsl\" href=\"../xsl/yopyop.xsl\"")
+ racine.previous_sibling = pi
+
+ # on ajoute chaque film à la racine
+ @films.each{|nom, f|
+ racine.add(f.getXml)
+ }
+
+ # sauve le document
+ docXml.write(File::new(@xmlFile, 'w'))
+ end
+
+ def to_s
+ acc = ""
+ @films.each_value{|f|
+ acc += f.to_s
+ }
+ return acc
+ end
+
+ private
+
+ # Enlève les \n et espace au début et à la fin de 'texte' et retourne le résultat
+ def nettoyer_texte(texte)
+ texte =~ /^[\n ]*(.*?)[\n ]*$/
+ return $1
+ end
+
+ # Charge les films depuis le fichier XML
+ def chargerFilms
+ # si le fichier n'existe pas il n'y a rien à charger
+ if !File.exists?(@xmlFile)
+ return
+ end
+
+ racine = REXML::Document::new(File::new(@xmlFile)).root
+ racine.elements.each("film"){|e|
+ id = e.attribute('id').to_s.to_i
+
+ if id >= @idDisponible
+ @idDisponible = id + 1
+ end
+
+ film = Film::new(nil, @modClasse::new)
+ film.id = id
+
+ film.titre = e.get_text('titre')
+ film.titre = nettoyer_texte(film.titre.value) if film.titre != nil
+
+ print "#{film.titre}.. "
+
+ film.url = e.get_text('url')
+ film.url = nettoyer_texte(film.url.value) if film.url != nil
+
+ film.annee = e.get_text('annee')
+ film.annee = nettoyer_texte(film.annee.value) if film.annee != nil
+
+ film.duree = e.get_text('duree')
+ film.duree = nettoyer_texte(film.duree.value) if film.duree != nil
+
+ film.critiquePresse = e.get_text('critiquePresse')
+ film.critiquePresse = nettoyer_texte(film.critiquePresse.value) if film.critiquePresse != nil
+
+ film.critiqueSpectateur = e.get_text('critiqueSpectateur')
+ film.critiqueSpectateur = nettoyer_texte(film.critiqueSpectateur.value) if film.critiqueSpectateur != nil
+
+ film.budget = e.get_text('budget')
+ film.budget = nettoyer_texte(film.budget.value) if film.budget != nil
+
+ e.elements.each('fichiers/fichier'){|f|
+ next if f.get_text == nil
+ film.addFichier(nettoyer_texte(f.get_text.value))
+ @filmsFichier[nettoyer_texte(f.get_text.value)] = film
+ }
+
+ e.elements.each('realisateurs/realisateur'){|f|
+ film.realisateurs << Personne::ajouter(nettoyer_texte(f.get_text.value))
+ }
+
+ e.elements.each('acteurs/acteur'){|f|
+ film.acteurs << Personne::ajouter(nettoyer_texte(f.get_text.value))
+ }
+
+ e.elements.each('lespays/pays'){|f|
+ film.pays << Pays::ajouter(nettoyer_texte(f.get_text.value))
+ }
+
+ e.elements.each('genres/genre'){|f|
+ film.genres << Genre::ajouter(nettoyer_texte(f.get_text.value))
+ }
+
+ debut = true
+ film.synopsis = ""
+ e.elements.each('synopsis/p'){|f|
+ film.synopsis += "\n" unless debut
+ film.synopsis += nettoyer_texte(f.get_text.value) if f.get_text != nil
+ debut = false
+ }
+ film.synopsis = nil if film.synopsis == ""
+
+ @films[film.titre] = film
+ }
+ end
+
+ # Retourne un nouvel id, utilisé alors de la création d'un nouveau film
+ def getNewId
+ id = @idDisponible
+ @idDisponible += 1
+ return id
+ end
+
+ # Ajoute un film à l'ensemble des films.
+ def ajouterFilm(film)
+ if film.plusieursReponses?
+ @filmsPlusieursReponses << film
+ return
+ end
+
+ if film.nbReponses == 0
+ @filmsAucuneReponse << film
+ return
+ end
+
+ if @films.has_key?(film.titre)
+ if !@filmsFichier.has_key?(film.fichiers[0])
+ puts "[i] Le film #{film.titre} possède une autre partie : #{film.fichiers[0]}"
+ @films[film.titre].addFichier(film.fichiers[0])
+ @filmsFichier[film.fichiers[0]] = @films[film.titre]
+ else
+ puts "[!] Film déjà dans la BD : #{film.titre} (#{film.fichiers[0]})"
+ end
+ else
+ puts "[i] Film ajouté : (#{film.id}) #{film.titre} (#{film.fichiers[0]}) #{film.id}"
+ @films[film.titre] = film
+ @filmsFichier[film.fichiers[0]] = film
+ end
+ end
+
+ # Appelé par 'pomper'. Cette méthode itère récursivement sur l'arborescence d'un repertoire.
+ def pomperR(r)
+ Dir::foreach(r){|f|
+ next if f[0,1] == '.'
+ fichier = (r == '.' ? '' : r + "/") + f
+ if File::directory?(fichier)
+ pomperR(fichier)
+ else
+ #fichier = Iconv.iconv("UTF-8", "ISO-8859-1", fichier)[0]
+
+ # véfication de l'extension
+ /^.*?\.([^.]{3,4})$/ =~ fichier
+ if !FILMS_EXTENSIONS.include?($1)
+ next
+ end
+
+ # on skip si le film est déjà dans la BD
+ if film = @filmsFichier[fichier]
+ puts "[!] Film déjà dans la BD : (#{film.id}) #{film.titre} (#{film.fichiers[0]})"
+ next
+ end
+
+ # pour limiter le nombre de connexion simultanée
+ if @nbConn >= NB_CONN_MAX
+ @threadsWait.next_wait
+ end
+
+ @nbConn += 1
+ @threadsWait.join_nowait(
+ Thread::start{
+ begin
+ film = Film::new(fichier, @modClasse::new)
+ @mutexId.synchronize{
+ film.id = getNewId # on lui donne un nouvel ID
+ }
+
+ film.loadData # chargement de ses données
+
+ @mutexAjout.synchronize{
+ ajouterFilm(film)
+ }
+ rescue Exception => e
+ puts e.message
+ puts e.backtrace
+ end
+ @nbConn -= 1
+ }
+ )
+ end
+ }
+ end
+end