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