ADD mise à jour de la liste des films
[pompage.git] / src / films.rb
index 01dce5e..7b1e625 100644 (file)
-# 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'), 1)\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
-            #fichier = Iconv.iconv("UTF-8", "ISO-8859-1", fichier)[0] // sous windows il faut décommenter cette ligne\r
-                        \r
-            # véfication de l'extension\r
-            /^.*?\.([^.]{3,4})$/ =~ fichier\r
-            if !FILMS_EXTENSIONS.include?($1)\r
-               next\r
+# 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
-                                    \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
-                     \r
-                     film.loadData # chargement de 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
+                                    
+            # 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