git-svn-id: svn://euphorik.ch/pompage@45 02bbb61a-6d21-0410-aba0-cb053bdfd66a
[pompage.git] / src / films.rb
index a934dbb..7d9c17e 100644 (file)
@@ -1,4 +1,4 @@
-# Représente un ensemble de films\r
+# coding: utf-8\r
 \r
 require 'rexml/document'\r
 require 'thwait'\r
@@ -8,55 +8,98 @@ require 'pays.rb'
 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)\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és par leur titre\r
+      # Les films indexé par leur titre\r
       @films = {}\r
       \r
-      # Les films indexés par leur nom de fichier, deux fichiers différents peuvent pointer sur le même film\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és à la fin\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
+   # 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
-      # traite les films qui avaient plusieurs réponses lors de la recherche\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
-         if f.reglerConflitPlusieursReponses\r
-            ajouterFilm(f)\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
@@ -73,7 +116,7 @@ class Films
       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
+      # on ajoute chaque film à la racine\r
       @films.each{|nom, f|\r
          racine.add(f.getXml)\r
       } \r
@@ -86,21 +129,21 @@ class Films
       \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
+      # si le fichier n'existe pas il n'y a rien à charger\r
       if !File.exists?(@xmlFile)\r
          return\r
       end\r
-      \r
+            \r
       racine = REXML::Document::new(File::new(@xmlFile)).root\r
       racine.each_element{|e|       \r
          id = e.attribute('id').to_s.to_i\r
        \r
-         if id > @idDisponible\r
+         if id >= @idDisponible\r
             @idDisponible = id + 1   \r
          end\r
          \r
          titre = e.get_elements('titre')[0].get_text\r
-         \r
+         url = e.get_elements('url')[0].get_text         \r
          fichiers = e.get_elements('fichiers')[0].get_elements('fichier')\r
          annee = e.get_elements('annee')[0].get_text\r
          duree = e.get_elements('duree')[0].get_text\r
@@ -113,10 +156,13 @@ class Films
          pays = e.get_elements('lespays')[0].get_elements('pays')\r
          genres = e.get_elements('genres')[0].get_elements('genre')\r
          \r
-         film = Film::new(fichiers[0].get_text.value)\r
+         film = Film::new(fichiers[0].get_text.value, @modClasse::new)\r
          \r
-         film.titre = titre.value unless titre.nil?\r
          film.id = id\r
+         film.titre = titre.value unless titre.nil?\r
+         \r
+         film.url = url.value unless url.nil?\r
+         \r
          fichiers.each{|e|\r
             film.addFichier(e.get_text.value)\r
             @filmsFichier[e.get_text.value] = film\r
@@ -146,23 +192,26 @@ class Films
       }\r
    end\r
    \r
-   # Retourne un nouvel id, utilisé lors de la création d'un nouveau film\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\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
-      # le film existe déjà\r
+      if film.nbReponses == 0\r
+         @filmsAucuneReponse << film\r
+         return\r
+      end\r
+      \r
       if @films.has_key?(film.titre)\r
-         # le fichier n'est pas connu -> nième partie d'un film\r
          if !@filmsFichier.has_key?(film.fichiers[0])\r
             puts "[i] movie #{film.titre} has a another file part : #{film.fichiers[0]}"\r
             @films[film.titre].addFichier(film.fichiers[0])\r
@@ -177,50 +226,52 @@ class Films
       end\r
    end\r
    \r
-   # Appelé par 'pomper'. Cette méthode est récursive.\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
-            litRepertoireR(fichier) \r
+            pomperR(fichier) \r
          else\r
             \r
-            # vérification de l'extension\r
-            /^.*?\.(.{3,4})$/ =~ fichier\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
-            fichier = CGI::escapeHTML(fichier.unpack("C*").pack("U*"))\r
-            \r
-            # on skip si le film est déjàa dans la BD\r
+                        \r
+            # on skip si le film est déjà dans la BD\r
             if film = @filmsFichier[fichier]\r
                puts "[i] Already exists in DB : #{film.titre} (#{fichier})"\r
                next\r
             end\r
-            \r
-            film = nil\r
              \r
-            # pour limiter le nombre de connexion simultanée\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::new{\r
+               Thread::start{\r
                   begin                  \r
-                     film = Film::new(fichier).loadData\r
-                     film.id = getNewId # on lui donne un nouvel ID\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
-                     unless film.nil? # le film a été correctement construit\r
+                     @mutexAjout.synchronize {\r
                         ajouterFilm(film)\r
-                     end\r
+                     }                     \r
                   rescue Exception => e\r
                      puts e.message\r
                      puts e.backtrace\r
-                  end      \r
+                  end\r
                   @nbConn -= 1\r
                }\r
             )\r