ADD Support de plusieurs fichiers par film
[pompage.git] / src / film.rb
index a7bcc54..1eaa33f 100644 (file)
@@ -11,24 +11,44 @@ require 'personne.rb'
 require 'constantes.rb'\r
 \r
 class Film\r
-   attr_accessor :titre, :fichier, :annee, :realisateurs, :acteurs, :pays, :duree, :critiquePresse, :critiqueSpectateur, :genres, :synopsis, :budget\r
+   attr_accessor :id, :titre, :fichiers, :annee, :realisateurs, :acteurs, :pays, :duree, :critiquePresse, :critiqueSpectateur, :genres, :synopsis, :budget\r
       \r
    # Les films indexés par leur titre\r
    @@films = {}\r
    \r
-   # Les films indexés par leur nom de fichier\r
+   # Les films indexés 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
+   @@filmsPlusieursReponses = []\r
 \r
    @@mutex = Mutex::new\r
    @@threadsWait = ThreadsWait::new\r
    @@nbConn = 0\r
-\r
+   \r
+   # le prochain id disponible\r
+   @@idDisponible = 1\r
+   \r
+   # retourne un nouvel id, utilisé lors de la création d'un nouveau film\r
+   def Film::getNewId\r
+      id = @@idDisponible\r
+      @@idDisponible += 1\r
+      return id\r
+   end\r
 \r
    # Lit un repertoire de manière recursive\r
    def Film::litRepertoire(r)\r
       Film::litRepertoireR(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
+      # l'utilisateur doit faire un choix\r
+      @@filmsPlusieursReponses.each{|f|\r
+         if f.reglerConflitPlusieursReponses\r
+            Film::ajouterFilm(f)\r
+         end\r
+      }\r
    end\r
    \r
    # Charge les films contenus dans un fichier XML.\r
@@ -39,28 +59,33 @@ class Film
       end\r
             \r
       racine = REXML::Document::new(File::new(xmlFile)).root\r
-      racine.each_element{|e|\r
-         fichier = e.get_elements('fichier')[0].get_text\r
-         next if fichier == nil\r
+      racine.each_element{|e|       \r
+         id = e.attribute('id').to_s().to_i()\r
+       \r
+         @@idDisponible = id + 1         \r
          titre = e.get_elements('titre')[0].get_text\r
+         \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
          critiquePresse = e.get_elements('critiquePresse')[0].get_text\r
          critiqueSpectateur = e.get_elements('critiqueSpectateur')[0].get_text\r
          synopsis = e.get_elements('synopsis')[0].get_text\r
          budget = e.get_elements('budget')[0].get_text  \r
-         realisateurs = e.get_elements('realisateur')\r
-         acteurs = e.get_elements('acteur')\r
-         pays = e.get_elements('pays')\r
-         genres = e.get_elements('genres')\r
+         realisateurs = e.get_elements('realisateurs')[0].get_elements('realisateur')\r
+         acteurs = e.get_elements('acteurs')[0].get_elements('acteur')\r
+         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
          \r
-      \r
-         film = Film::new(fichier.value)\r
          film.titre = titre.value unless titre.nil?\r
+         film.id = id\r
+         fichiers.each{|e|\r
+            film.addFichier(e.get_text.value)\r
+            @@filmsFichier[e.get_text.value] = film\r
+         }\r
          film.annee = annee.value unless annee.nil?\r
-         realisateurs.each{|e|\r
-            film.realisateurs << Personne::ajouter(e.get_text.value)\r
-         }        \r
          acteurs.each{|e|\r
             film.acteurs << Personne::ajouter(e.get_text.value)\r
          }\r
@@ -71,13 +96,12 @@ class Film
          film.critiquePresse = critiquePresse.value unless critiquePresse.nil?\r
          film.critiqueSpectateur = critiqueSpectateur.value unless critiqueSpectateur.nil?\r
          genres.each{|e|\r
-            film.genres << Genre::ajouter(e.get_text.value)\r
+            film.genres << Genre::ajouter(e.get_text.value) if e.get_text != nil\r
          }\r
          film.synopsis = synopsis.value unless synopsis.nil?\r
          film.budget = budget.value unless budget.nil?\r
          @@films[film.titre] = film\r
-         @@filmsFichier[film.fichier] = film\r
-      }   \r
+      }\r
    end\r
 \r
    # Renvoie tous les films sous la forme d'un document XML.\r
@@ -86,10 +110,12 @@ class Film
       docXml = REXML::Document::new\r
       docXml.xml_decl().encoding = "UTF-8"  # normalement UTF-8\r
       docXml.xml_decl().dowrite\r
-      \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
@@ -105,7 +131,8 @@ private
    def Film::filmsFactory(fichier)\r
       /^.*?\.(.{3,4})$/ =~ fichier\r
       if FILMS_EXTENSIONS.include?($1)\r
-         Film::new(fichier).loadData\r
+         #convertit le code latin-1 en UTF8\r
+         Film::new(fichier.unpack("C*").pack("U*")).loadData\r
       end\r
     end\r
     \r
@@ -119,7 +146,7 @@ private
          \r
             #si le film n'existe pas déjà dans la liste\r
             if film = @@filmsFichier[fichier]\r
-               puts "[i] Already exists in DB : #{film.titre} (#{film.fichier})"\r
+               puts "[i] Already exists in DB : #{film.titre} (#{film.fichiers[0]})"\r
                next\r
             end\r
             \r
@@ -130,20 +157,13 @@ private
                Thread::new{    \r
                   begin\r
                      @@mutex.lock if @@nbConn >= NB_CONN_MAX                     \r
-                     film = Film::filmsFactory(fichier)\r
-                     unless film.nil?\r
-                        if @@films.has_key?(film.titre)\r
-                           puts "[!] Duplicate movie : #{film.titre} (#{film.fichier})"\r
-                        else\r
-                           puts "[i] movie added : #{film.titre} (#{film.fichier})"\r
-                           @@films[film.titre] = film\r
-                           @@filmsFichier[film.fichier] = film\r
-                        end\r
+                     film = Film::filmsFactory(fichier)                     \r
+                     unless film.nil? # le film a été correctement construit\r
+                        Film::ajouterFilm(film)\r
                      end\r
                      @@nbConn -= 1\r
-                     #p @@nbConn\r
                      @@mutex.unlock\r
-                  rescue  Exception => e\r
+                  rescue Exception => e\r
                      puts e.message\r
                      puts e.backtrace\r
                   end\r
@@ -151,13 +171,36 @@ private
             )\r
          end\r
       }\r
-    end\r
-\r
+   end\r
+   \r
+   def Film::ajouterFilm(film)\r
+      if film.plusieursReponses?\r
+         @@filmsPlusieursReponses << film\r
+         return\r
+      end\r
+      \r
+      # le film existe déjà\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
+            @@filmsFichier[film.fichiers[0]] = @@films[film.titre]                     \r
+         else\r
+            puts "[!] Duplicate movie : #{film.titre} (#{film.fichier})"\r
+         end\r
+      else\r
+         puts "[i] movie added : #{film.titre} (#{film.fichiers[0]})"\r
+         @@films[film.titre] = film\r
+         @@filmsFichier[film.fichiers[0]] = film\r
+      end\r
+   end\r
+      \r
    \r
    def initialize(fichier)\r
-      #convertit le code latin-1 en UTF8\r
-      @fichier = fichier.unpack("C*").pack("U*")\r
+      @fichiers = [fichier]\r
            \r
+      @id = 0\r
       @titre = ''\r
       @annee = nil\r
       @realisateurs = []\r
@@ -171,22 +214,46 @@ private
       @budget = nil      \r
       @budgetUnite = 'euro'\r
       @url\r
+      \r
+      @aPlusieursReponses = false\r
+      # mémorise les tuples {nom => id} dans le cas ou il y a plusieurs réponses\r
+      @idsAllocine = {}\r
    end\r
 \r
 public \r
 \r
+   def plusieursReponses?\r
+      return @aPlusieursReponses\r
+   end \r
+   \r
+   # demande à l'utilisateur de faire un choix\r
+   # ret : true si le conflit à été résolu sinon false\r
+   def reglerConflitPlusieursReponses\r
+      puts "prout"\r
+      \r
+      return false\r
+   end\r
+   \r
+   def addFichier(fichier)\r
+      if (!@fichiers.include?(fichier))\r
+         @fichiers << fichier\r
+      end\r
+   end\r
+\r
    # Charge les informations du films à partir d'allocine.fr\r
    # ret [Film]\r
    def loadData\r
       unless LOAD_DATA\r
-         @titre = @fichier\r
+         @titre = @fichiers[0]\r
          return self\r
       end\r
+      \r
+      @id = Film::getNewId\r
 \r
-      connexionHttp = Net::HTTP::new('www.allocine.fr');\r
+      connexionHttp = Net::HTTP::new('www.allocine.fr')\r
    \r
       #extrait le nom à partir du nom du fichier\r
-      /^.*?([^\/]*?)\.(.{3,4})$/ =~ @fichier\r
+      /^.*?([^\/]*?)\.(.{3,4})$/ =~ @fichiers[0]\r
       #remplace undescores et points par des espaces\r
       titre = $1.gsub(/[_\.]/, ' ')\r
       #remplace les suites d'espaces par un seul\r
@@ -201,13 +268,19 @@ public
       \r
       donneesHtml = nil\r
       begin\r
-         reponse, donneesHtml = connexionHttp.get("/recherche/?motcle=#{CGI::escape(titre)}")\r
+         begin\r
+            reponse, donneesHtml = connexionHttp.get("/recherche/?motcle=#{CGI::escape(titre)}")\r
+         rescue Exception => e\r
+            p e\r
+            puts "[!] Connexion lost, retry.."\r
+            retry\r
+         end\r
          \r
          #convertit le code latin-1 en UTF8\r
          donneesHtml = donneesHtml.unpack("C*").pack("U*")\r
          \r
          #si pas trouvé alors on enlève un mot à la fin\r
-         if /.*?Pas de résultats.*?/ =~ donneesHtml\r
+         if /.*?Pas de résultats.*?/ =~ donneesHtml || ! donneesHtml.include?("<h3><b>Films <h4>")\r
             /(.*?)[^ ]+?$/ =~ titre.strip\r
             titre = $1\r
             titre.strip!\r
@@ -217,78 +290,101 @@ public
       end while not titre.nil? and not titre.empty?\r
       \r
       unless titre.nil? or titre.empty?\r
-         /<a href="\/film\/fichefilm_gen_cfilm=(\d+)\.html" class="link1">/ =~ donneesHtml\r
-         if $1\r
-            r, ficheHtml = connexionHttp.get("/film/fichefilm_gen_cfilm=#{$1}.html") \r
-            \r
-            #convertit le code latin-1 en UTF8\r
-            ficheHtml = ficheHtml.unpack("C*").pack("U*")\r
-\r
-            #url\r
-            @url = "http://www.allocine.fr/film/fichefilm_gen_cfilm=#{$1}.html"\r
-            \r
-            # Titre\r
-            /<title>(.*?)<\/title>/ =~ ficheHtml\r
-            @titre = $1 unless $1.nil?\r
-            \r
-            puts "Movie found : #{@titre} (#{@fichier})"\r
-            \r
-            # Année\r
-            /<h4>Année de production : (\d+)<\/h4>/ =~ ficheHtml\r
-            @annee = $1.to_i unless $1.nil?\r
-            \r
-            # Réalisateurs\r
-            /<h4>Réalisé par(.*?)<\/h4>/ =~ ficheHtml\r
-            $1.scan(/<a class="link1" href=".*?">(.*?)<\/a>/m){|a|\r
-              @realisateurs << Personne::ajouter(a[0]) unless a[0].nil?\r
-            } unless $1.nil?\r
             \r
-            # Acteurs\r
-            /<h4>Avec(.*?)<\/h4>/ =~ ficheHtml\r
-            $1.scan(/<a class="link1" href="\/personne\/fichepersonne_gen_cpersonne=\d+\.html">(.+?)<\/a>/m){|a|\r
-               @acteurs << Personne::ajouter(a[0]) unless a[0].nil? \r
-            } unless $1.nil? \r
-                      \r
-                      \r
-            # Pays\r
-            /<h4>Film (.*?)\.&nbsp;<\/h4>/ =~ ficheHtml\r
-            $1.split(',').each{|pays|\r
-               @pays << Pays::ajouter(pays) unless pays.nil?\r
-            } unless $1.nil? \r
-            \r
-            # Duree\r
-            /<h4>Durée : (\d+)h (\d+)min./ =~ ficheHtml\r
-            @duree = $1.nil? ? $2.to_i : $1.to_i * 60 + $2.to_i\r
-            \r
-            # Critiques presse et spectateur\r
-            /Presse.*etoile_([012345]).*Spectateurs.*etoile_([012345])"/m =~ ficheHtml\r
-            @critiquePresse = $1.to_i unless $1.nil?\r
-            @critiqueSpectateur = $2.to_i unless $2.nil?\r
-            \r
-            # Genre\r
-            /<h4>Genre : (.*?)<\/h4>/ =~ ficheHtml\r
-            $1.scan(/<a href="\/film\/alaffiche_genre_gen_genre=.*?" class="link1">(.+?)<\/a>/m){|g|\r
-               @genres << Genre::ajouter(g[0]) unless g[0].nil?\r
-            } unless $1.nil?     \r
-            \r
-            # Synopsis            \r
-            /Synopsis.*?<h4>(.+?)<\/h4>/m =~ ficheHtml\r
-            @synopsis = $1 unless $1.nil?\r
-            \r
-            # Budget       \r
-            /Budget<\/b> : (.+?) millions d'euros<\/h4>/ =~ ficheHtml\r
-            @budget = $1.to_i unless $1.nil?\r
-         else         \r
+         #/<a href="\/film\/fichefilm_gen_cfilm=(\d+)\.html" class="link1">/ =~ donneesHtml\r
+         r = donneesHtml.scan(/<a href="\/film\/fichefilm_gen_cfilm=(\d+)\.html" class="link1">(.*?)<\/a>/)\r
+         \r
+         if r.length > 1\r
+            @aPlusieursReponses = true\r
+            r.each{|f|\r
+               @idsAllocine[f[1].gsub(/<(.*?)>/, '')] = f[0]\r
+            }\r
+         elsif r.length == 1\r
+            loadDepuisIdAllocine(r[0][0], connexionHttp) \r
+         else\r
             puts "[!] Movie not found : #{@titre} (#{@fichier})"\r
          end\r
       end\r
       self\r
    end\r
    \r
+private\r
+   def loadDepuisIdAllocine(id, connexionHttp)\r
+      r, ficheHtml = connexionHttp.get("/film/fichefilm_gen_cfilm=#{id}.html") \r
+      \r
+      #convertit le code latin-1 en UTF8\r
+      ficheHtml = ficheHtml.unpack("C*").pack("U*")\r
+\r
+      #url\r
+      @url = "http://www.allocine.fr/film/fichefilm_gen_cfilm=#{id}.html"\r
+      \r
+      # Titre\r
+      /<title>(.*?)<\/title>/ =~ ficheHtml\r
+      @titre = $1 unless $1.nil?\r
+      \r
+      puts "Movie found : #{@titre} (#{@fichier})"\r
+      \r
+      # Année\r
+      /<h4>Année de production : (\d+)<\/h4>/ =~ ficheHtml\r
+      @annee = $1.to_i unless $1.nil?\r
+      \r
+      # Réalisateurs\r
+      /<h4>Réalisé par(.*?)<\/h4>/ =~ ficheHtml\r
+      $1.scan(/<a class="link1" href=".*?">(.*?)<\/a>/m){|a|\r
+        @realisateurs << Personne::ajouter(a[0]) unless a[0].nil?\r
+      } unless $1.nil?\r
+      \r
+      # Acteurs\r
+      /<h4>Avec(.*?)<\/h4>/ =~ ficheHtml\r
+      $1.scan(/<a class="link1" href="\/personne\/fichepersonne_gen_cpersonne=\d+\.html">(.+?)<\/a>/m){|a|\r
+         @acteurs << Personne::ajouter(a[0]) unless a[0].nil? \r
+      } unless $1.nil? \r
+                \r
+                \r
+      # Pays\r
+      /<h4>Film (.*?)\.&nbsp;<\/h4>/ =~ ficheHtml\r
+      $1.split(',').each{|pays|\r
+         @pays << Pays::ajouter(pays) unless pays.nil?\r
+      } unless $1.nil? \r
+      \r
+      # Duree\r
+      /<h4>Durée : (\d+)h (\d+)min./ =~ ficheHtml\r
+      @duree = $1.nil? ? $2.to_i : $1.to_i * 60 + $2.to_i\r
+      \r
+      # Critiques presse et spectateur\r
+      /Presse.*etoile_([012345]).*Spectateurs.*etoile_([012345])"/m =~ ficheHtml\r
+      @critiquePresse = $1.to_i unless $1.nil?\r
+      @critiqueSpectateur = $2.to_i unless $2.nil?\r
+      \r
+      # Genre\r
+      /<h4>Genre : (.*?)<\/h4>/ =~ ficheHtml\r
+      $1.scan(/<a href="\/film\/alaffiche_genre_gen_genre=.*?" class="link1">(.+?)<\/a>/m){|g|\r
+         @genres << Genre::ajouter(g[0]) unless g[0].nil?\r
+      } unless $1.nil?     \r
+      \r
+      # Synopsis            \r
+      /Synopsis.*?<h4>(.+?)<\/h4>/m =~ ficheHtml\r
+      @synopsis = $1 unless $1.nil?\r
+      \r
+      # Budget       \r
+      /Budget<\/b> : (.+?) millions d'euros<\/h4>/ =~ ficheHtml\r
+      @budget = $1.to_i unless $1.nil?\r
+   end     \r
+      \r
+public\r
+   \r
    # Renvoie un film sous la forme d'un élément XML de type REXML\r
    def getXml\r
+      \r
       racine = REXML::Element::new('film')\r
-      racine.add(REXML::Element::new('fichier').add_text(@fichier))\r
+      racine.add_attribute('id', @id.to_s)\r
+      \r
+      fichiers = REXML::Element::new('fichiers')\r
+      @fichiers.each{|f|\r
+         fichiers.add(REXML::Element::new('fichier').add_text(f))  \r
+      }\r
+      racine.add(fichiers)      \r
+      \r
       racine.add(REXML::Element::new('titre').add_text(@titre))\r
       racine.add(REXML::Element::new('annee').add_text(@annee.to_s))\r
 \r