MOD Vitesse de la recherche
[pompage.git] / src / films.rb
1 # Représente un ensemble de films
2
3 require 'rexml/document'
4 require 'thwait'
5
6 require 'film.rb'
7 require 'pays.rb'
8 require 'genre.rb'
9 require 'personne.rb'
10 require 'constantes.rb'
11 require 'iconv'
12
13 class Films
14 def initialize(xmlFile)
15 @xmlFile = xmlFile
16
17 # repertoire de base, par exemple C:/Divx/
18 @repBase = ''
19
20 # Les films indexé par leur titre
21 @films = {}
22
23 # Les films indexé par leur nom de fichier, deux fichiers différents peuvent pointer sur le même film
24 @filmsFichier = {}
25
26 # Les films qui ont plusieurs réponses lors de la recherche, traité à la fin
27 @filmsPlusieursReponses = []
28
29 # Les films qui ont plusieurs réponses lors de la recherche, traité à la fin
30 @filmsAucuneReponse = []
31
32 # permet de traiter facilement des groupes de thread
33 @threadsWait = ThreadsWait::new
34 @nbConn = 0 # le nombre de connexion
35
36 # le prochain id disponible
37 @idDisponible = 1
38
39 chargerFilms
40 end
41
42 # Lit un repertoire de manière recursive et va chercher les informations concernant le film sur le net
43 def pomper(r)
44 @repBase = r
45 repPrecedant = Dir::getwd
46 Dir::chdir(r)
47
48 t = Time::now
49
50 pomperR('.')
51
52 # on attends que les threads se terminent
53 @threadsWait.all_waits
54
55 puts "Pompage terminé, temps : #{Time::now - t} secondes"
56
57 # traite les films qui avaient plusieurs réponses lors de la recherche
58 # l'utilisateur doit faire un choix
59 i = 1
60 @filmsPlusieursReponses.each{|f|
61 puts
62 puts "Plop, ya un conflit #{i} / #{@filmsPlusieursReponses.length} :"
63 case f.reglerConflitPlusieursReponses
64 when 1
65 ajouterFilm(f)
66 when 3
67 break
68 end
69 i += 1
70 }
71
72 i = 1
73 @filmsAucuneReponse.each{|f|
74 puts
75 puts "Plop, Ce film n'a pas été trouvé #{i} / #{@filmsAucuneReponse.length} :"
76 case f.reglerConflitPlusieursReponses
77 when 1
78 ajouterFilm(f)
79 when 3
80 break
81 end
82 i += 1
83 }
84
85 Dir::chdir(repPrecedant)
86 end
87
88 # Sauve les films dans un fichier XML
89 def sauverFilms
90 # le document
91 docXml = REXML::Document::new
92 docXml.xml_decl().encoding = "UTF-8" # normalement UTF-8
93 docXml.xml_decl().dowrite
94
95 # la racine du document
96 racine = REXML::Element::new('filmographie')
97 docXml.add(racine)
98 pi = REXML::Instruction.new("xml-stylesheet", "type=\"text/xsl\" href=\"../xsl/yopyop.xsl\"")
99 racine.previous_sibling = pi
100
101 # on ajoute chaque film à la racine
102 @films.each{|nom, f|
103 racine.add(f.getXml)
104 }
105
106 # sauve le document
107 docXml.write(File::new(@xmlFile, 'w'), 0)
108 end
109
110 private
111
112 # Charge les films depuis le fichier XML
113 def chargerFilms
114 # si le fichier n'existe pas il n'y a rien à charger
115 if !File.exists?(@xmlFile)
116 return
117 end
118
119 racine = REXML::Document::new(File::new(@xmlFile)).root
120 racine.each_element{|e|
121 id = e.attribute('id').to_s.to_i
122
123 if id > @idDisponible
124 @idDisponible = id + 1
125 end
126
127 titre = e.get_elements('titre')[0].get_text
128 url = e.get_elements('url')[0].get_text
129 fichiers = e.get_elements('fichiers')[0].get_elements('fichier')
130 annee = e.get_elements('annee')[0].get_text
131 duree = e.get_elements('duree')[0].get_text
132 critiquePresse = e.get_elements('critiquePresse')[0].get_text
133 critiqueSpectateur = e.get_elements('critiqueSpectateur')[0].get_text
134 synopsis = e.get_elements('synopsis')[0].get_elements('p')
135 budget = e.get_elements('budget')[0].get_text
136 realisateurs = e.get_elements('realisateurs')[0].get_elements('realisateur')
137 acteurs = e.get_elements('acteurs')[0].get_elements('acteur')
138 pays = e.get_elements('lespays')[0].get_elements('pays')
139 genres = e.get_elements('genres')[0].get_elements('genre')
140
141 film = Film::new(fichiers[0].get_text.value)
142
143 film.id = id
144 film.titre = titre.value unless titre.nil?
145
146 film.url = url.value unless url.nil?
147
148 fichiers.each{|e|
149 film.addFichier(e.get_text.value)
150 @filmsFichier[e.get_text.value] = film
151 }
152 film.annee = annee.value unless annee.nil?
153 acteurs.each{|e|
154 film.acteurs << Personne::ajouter(e.get_text.value)
155 }
156 pays.each{|e|
157 film.pays << Pays::ajouter(e.get_text.value)
158 }
159 film.duree = duree.value unless duree.nil?
160 film.critiquePresse = critiquePresse.value unless critiquePresse.nil?
161 film.critiqueSpectateur = critiqueSpectateur.value unless critiqueSpectateur.nil?
162 genres.each{|e|
163 film.genres << Genre::ajouter(e.get_text.value) if e.get_text != nil
164 }
165 debut = true
166 film.synopsis = ""
167 synopsis.each{|e|
168 film.synopsis += "\n" unless debut
169 film.synopsis += e.get_text.value if e.get_text != nil
170 debut = false
171 }
172 film.budget = budget.value unless budget.nil?
173 @films[film.titre] = film
174 }
175 end
176
177 # Retourne un nouvel id, utilisé alors de la création d'un nouveau film
178 def getNewId
179 id = @idDisponible
180 @idDisponible += 1
181 return id
182 end
183
184 # Ajoute un film
185 def ajouterFilm(film)
186 if film.plusieursReponses?
187 @filmsPlusieursReponses << film
188 return
189 end
190
191 if film.nbReponses == 0
192 @filmsAucuneReponse << film
193 return
194 end
195
196 if @films.has_key?(film.titre)
197 # le fichier n'est pas connu -> nième partie d'un film
198 if !@filmsFichier.has_key?(film.fichiers[0])
199 puts "[i] movie #{film.titre} has a another file part : #{film.fichiers[0]}"
200 @films[film.titre].addFichier(film.fichiers[0])
201 @filmsFichier[film.fichiers[0]] = @films[film.titre]
202 else
203 puts "[!] Duplicate movie : #{film.titre} (#{film.fichiers[0]})"
204 end
205 else
206 puts "[i] movie added : #{film.titre} (#{film.fichiers[0]})"
207 @films[film.titre] = film
208 @filmsFichier[film.fichiers[0]] = film
209 end
210 end
211
212 # Appelé par 'pomper'. Cette méthode est récursive.
213 def pomperR(r)
214 Dir::foreach(r){|f|
215 next if f[0,1] == '.'
216 fichier = (r == '.' ? '' : r + "/") + f
217 if File::directory?(fichier)
218 pomperR(fichier)
219 else
220
221 # véfication de l'extension
222 /^.*?\.([^.]{3,4})$/ =~ fichier
223 if !FILMS_EXTENSIONS.include?($1)
224 next
225 end
226
227 fichier = CGI::escapeHTML(Iconv.iconv("UTF-8", "ISO-8859-1", fichier)[0])
228
229 # on skip si le film est déjà dans la BD
230 if film = @filmsFichier[fichier]
231 puts "[i] Already exists in DB : #{film.titre} (#{fichier})"
232 next
233 end
234
235 film = nil
236
237 # pour limiter le nombre de connexion simultanée
238 if @nbConn >= NB_CONN_MAX
239 @threadsWait.next_wait
240 end
241
242 @nbConn += 1
243 @threadsWait.join_nowait(
244 Thread::new{
245 begin
246 film = Film::new(fichier).loadData
247 film.id = getNewId # on lui donne un nouvel ID
248
249 unless film.nil? # le film a été correctement construit
250 ajouterFilm(film)
251 end
252 rescue Exception => e
253 puts e.message
254 puts e.backtrace
255 end
256 @nbConn -= 1
257 }
258 )
259 end
260 }
261 end
262 end