git-svn-id: svn://euphorik.ch/pompage@35 02bbb61a-6d21-0410-aba0-cb053bdfd66a
[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 if f.reglerConflitPlusieursReponses
64 ajouterFilm(f)
65 end
66 i += 1
67 }
68
69 i = 1
70 @filmsAucuneReponse.each{|f|
71 puts
72 puts "Plop, Ce film n'a pas été trouvé{i} / #{@filmsAucuneReponse.length} :"
73 if f.reglerConflitPlusieursReponses
74 ajouterFilm(f)
75 end
76 i += 1
77 }
78
79 Dir::chdir(repPrecedant)
80 end
81
82 # Sauve les films dans un fichier XML
83 def sauverFilms
84 # le document
85 docXml = REXML::Document::new
86 docXml.xml_decl().encoding = "UTF-8" # normalement UTF-8
87 docXml.xml_decl().dowrite
88
89 # la racine du document
90 racine = REXML::Element::new('filmographie')
91 docXml.add(racine)
92 pi = REXML::Instruction.new("xml-stylesheet", "type=\"text/xsl\" href=\"../xsl/yopyop.xsl\"")
93 racine.previous_sibling = pi
94
95 # on ajoute chaque film à la racine
96 @films.each{|nom, f|
97 racine.add(f.getXml)
98 }
99
100 # sauve le document
101 docXml.write(File::new(@xmlFile, 'w'), 0)
102 end
103
104 private
105
106 # Charge les films depuis le fichier XML
107 def chargerFilms
108 # si le fichier n'existe pas il n'y a rien à charger
109 if !File.exists?(@xmlFile)
110 return
111 end
112
113 racine = REXML::Document::new(File::new(@xmlFile)).root
114 racine.each_element{|e|
115 id = e.attribute('id').to_s.to_i
116
117 if id > @idDisponible
118 @idDisponible = id + 1
119 end
120
121 titre = e.get_elements('titre')[0].get_text
122 url = e.get_elements('url')[0].get_text
123 fichiers = e.get_elements('fichiers')[0].get_elements('fichier')
124 annee = e.get_elements('annee')[0].get_text
125 duree = e.get_elements('duree')[0].get_text
126 critiquePresse = e.get_elements('critiquePresse')[0].get_text
127 critiqueSpectateur = e.get_elements('critiqueSpectateur')[0].get_text
128 synopsis = e.get_elements('synopsis')[0].get_elements('p')
129 budget = e.get_elements('budget')[0].get_text
130 realisateurs = e.get_elements('realisateurs')[0].get_elements('realisateur')
131 acteurs = e.get_elements('acteurs')[0].get_elements('acteur')
132 pays = e.get_elements('lespays')[0].get_elements('pays')
133 genres = e.get_elements('genres')[0].get_elements('genre')
134
135 film = Film::new(fichiers[0].get_text.value)
136
137 film.id = id
138 film.titre = titre.value unless titre.nil?
139
140 film.url = url.value unless url.nil?
141
142 fichiers.each{|e|
143 film.addFichier(e.get_text.value)
144 @filmsFichier[e.get_text.value] = film
145 }
146 film.annee = annee.value unless annee.nil?
147 acteurs.each{|e|
148 film.acteurs << Personne::ajouter(e.get_text.value)
149 }
150 pays.each{|e|
151 film.pays << Pays::ajouter(e.get_text.value)
152 }
153 film.duree = duree.value unless duree.nil?
154 film.critiquePresse = critiquePresse.value unless critiquePresse.nil?
155 film.critiqueSpectateur = critiqueSpectateur.value unless critiqueSpectateur.nil?
156 genres.each{|e|
157 film.genres << Genre::ajouter(e.get_text.value) if e.get_text != nil
158 }
159 debut = true
160 film.synopsis = ""
161 synopsis.each{|e|
162 film.synopsis += "\n" unless debut
163 film.synopsis += e.get_text.value if e.get_text != nil
164 debut = false
165 }
166 film.budget = budget.value unless budget.nil?
167 @films[film.titre] = film
168 }
169 end
170
171 # Retourne un nouvel id, utilisé alors de la création d'un nouveau film
172 def getNewId
173 id = @idDisponible
174 @idDisponible += 1
175 return id
176 end
177
178 # Ajoute un film
179 def ajouterFilm(film)
180 if film.plusieursReponses?
181 @filmsPlusieursReponses << film
182 return
183 end
184
185 if film.nbReponses == 0
186 @filmsAucuneReponse << film
187 return
188 end
189
190 if @films.has_key?(film.titre)
191 # le fichier n'est pas connu -> nième partie d'un film
192 if !@filmsFichier.has_key?(film.fichiers[0])
193 puts "[i] movie #{film.titre} has a another file part : #{film.fichiers[0]}"
194 @films[film.titre].addFichier(film.fichiers[0])
195 @filmsFichier[film.fichiers[0]] = @films[film.titre]
196 else
197 puts "[!] Duplicate movie : #{film.titre} (#{film.fichiers[0]})"
198 end
199 else
200 puts "[i] movie added : #{film.titre} (#{film.fichiers[0]})"
201 @films[film.titre] = film
202 @filmsFichier[film.fichiers[0]] = film
203 end
204 end
205
206 # Appelé par 'pomper'. Cette méthode est récursive.
207 def pomperR(r)
208 Dir::foreach(r){|f|
209 next if f[0,1] == '.'
210 fichier = (r == '.' ? '' : r + "/") + f
211 if File::directory?(fichier)
212 litRepertoireR(fichier)
213 else
214
215 # véfication de l'extension
216 /^.*?\.(.{3,4})$/ =~ fichier
217 if !FILMS_EXTENSIONS.include?($1)
218 next
219 end
220
221 fichier = CGI::escapeHTML(Iconv.iconv("UTF-8", "ISO-8859-1", fichier)[0])
222
223 # on skip si le film est déjà dans la BD
224 if film = @filmsFichier[fichier]
225 puts "[i] Already exists in DB : #{film.titre} (#{fichier})"
226 next
227 end
228
229 film = nil
230
231 # pour limiter le nombre de connexion simultanée
232 if @nbConn >= NB_CONN_MAX
233 @threadsWait.next_wait
234 end
235
236 @nbConn += 1
237 @threadsWait.join_nowait(
238 Thread::new{
239 begin
240 film = Film::new(fichier).loadData
241 film.id = getNewId # on lui donne un nouvel ID
242
243 unless film.nil? # le film a été correctement construit
244 ajouterFilm(film)
245 end
246 rescue Exception => e
247 puts e.message
248 puts e.backtrace
249 end
250 @nbConn -= 1
251 }
252 )
253 end
254 }
255 end
256 end