1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import os,os.path,sys,string,logging,htmlentitydefs,bisect
20 import contract
21 import constantes
22 import Donnees.resultatAppli
23 import Controleurs.DGManager
24 import Utile.constantesDonnees
25 from string import Template
26 import utile
27
28 import numpy.oldnumeric as Numeric
29
31 """ Classe centralisant la gestion d'une liste de valeurs fixes """
35 """ Liste des tags """
36 return self._liste
38 return self._liste[pos]
40 """ Nombre de tags """
41 return len(self._liste)
43 """ Renvoie la position du tag dans la liste des tags """
44
45 try: return self._liste.index(item)
46 except ValueError: raise ValueError("list.index(x): x not in list, x="+str(item))
47 - def posToItem(self,pos):
48 """ Renvoie le tag correspondant à cette position dans la liste de tags """
49 if not(0<=pos<=len(self._liste)): raise LookupError("index out of range")
50 else: return self._liste[pos]
51 - def pref(self,item,num):
52 """ renvoie le préfixe de item
53 pre: isinstance(item,str) or isinstance(item,list)
54 """
55 if isinstance(item,str): return self.__pref(item,num)
56 res = []
57 for x in item:
58 res.append(self.__pref(x,num))
59 return res
61 res = item[:num]
62
63
64 if item[-1]=='1' or item[-1]=='2': res += ' T'+item[-1]
65 return res
66
68 """ Classe centralisant la gestion de la liste de tags utilisés """
70 self._liste = ['ABR', 'ADJ', 'ADV', 'DET', 'INT', 'KON', 'NAM', 'NOM', 'NUM',
71 'PRO', 'PRP', 'PUN', 'SENT', 'SYM', 'VER']
73 return [u'Abréviation', 'Adjectif', 'Adverbe', u'Déterminant', 'Interjection',
74 'Conjonction', 'Nom propre', 'Nom', u'Numéral', 'Pronom', u'Préposition',
75 'Ponctuation', 'Mot phrase', 'Symbole', 'Verbe']
76
78 """ Classe centralisant la gestion de la liste de tags utilisés """
80
81 self._liste = ['Modifications', 'BC']
83
84
85 return ['Modifications', 'Blocs Communs']
86
87 -class PartOfTextManager(ListManager):
88 """ Classe centralisant la gestion des différentes parties du texte """
90 self._liste = ['Suppressions', 'Insertions', 'Remplacements1', 'Remplacements2',
91 u'Déplacements1', u'Déplacements2', 'Blocs Communs 1',
92 'Blocs Communs 2', 'Texte1', 'Texte2']
93 - def abreviations(self,num=None):
94 """ Renvoie une abréviation ou toute la liste
95 pre: num==None or num<=len(self._liste) """
96 res = self.pref(self._liste[:2],3) + self.pref(self._liste[2:4],4) + self.pref(self._liste[4:],3)
97 if num==None: return res
98 else: return res[num]
99
100 -class PartOfTextManager2(PartOfTextManager):
101 """ (Sup,Remp1) et (Ins,Remp2) sont fusionnés """
102 - def __init__(self):
103 self._liste = ['Suppressions + Remp1', 'Insertions + Remp2',
104 u'Déplacements1', u'Déplacements2', 'Blocs Communs 1',
105 'Blocs Communs 2', 'Texte1', 'Texte2']
106
107 -class PartOfTextManager3(PartOfTextManager):
108 """ Affiche les BC et les Dep """
109 - def __init__(self):
110 self._liste = ['Blocs Communs 1','Blocs Communs 2',
111 u'Déplacements1', u'Déplacements2',
112 u'BC1 + Dép1', u'BC2 + Dép2',
113 'Texte1', 'Texte2']
114
115 -class PartOfTextManager4(PartOfTextManager):
116 """ (Sup+Remp1)/BC1 et (Ins+Remp2)/BC2 """
117 - def __init__(self):
118 self._liste = ['Texte1', 'Texte2']
119
121 """Classe qui interface le TreeTagger. A partir d'un texte, renovie une liste
122 des tokens étiquetés, en appellant la fonction etiquetage()"""
124 self._REPTAGGER = os.path.join(constantes.REPMEDITE,"TreeTagger")
125 if not os.path.isdir(self._REPTAGGER): raise IOError,"Le dossier TreeTagger est absent."
126
127 self._TAGGER = "tag-french.bat"
128
129
131 """ Exécute la commande cmd en lui passant sur stdin arg et en récupérant le résultat sur stdout
132
133 pre: isinstance(directory,str)
134 isinstance(cmd,str)
135 isinstance(arg,str)
136 os.path.isfile(cmd)
137 post: isinstance(__return__,str)
138 """
139 curDir=os.getcwd()
140 os.chdir(directory)
141
142
143 fi,fo,fe = os.popen3(cmd,'t')
144 assert(fi != None)
145 assert(fo != None)
146
147 fi.close()
148 resultat = fo.readlines()
149 err = fe.readlines()
150 fo.close()
151 fe.close()
152 if 'ERROR' in err: sys.stderr.write(str(err))
153 if len(resultat)==0: raise ValueError,u"Résultat de la commande vide."
154 resultat = ''.join(resultat)
155 os.chdir(curDir)
156 return resultat
157
159 """ Lance l'étiqueteur sur le texte et renvoie une liste [(token,tag)]
160
161 post: isinstance(__return__,list)
162 """
163 nom_fichier_temp = "medTemp.txt"
164 fichier_temp = os.path.join(self._REPTAGGER,"medTemp.txt")
165 ft = open(fichier_temp, 'w')
166 ft.write(texte)
167 ft.close()
168
169
170
171
172 textTagged = self.exec_pipe(self._REPTAGGER,self._TAGGER + ' ' +nom_fichier_temp,'')
173 os.remove(fichier_temp)
174 lLines = textTagged.splitlines()
175 if len(lLines)==0: raise ValueError,u"L'étiquetage a échoué."
176 lTokenTag = []
177 for l in lLines:
178 lTok = l.split()
179 if len(lTok)<=1: continue
180
181
182 end = lTok[1].find(':')
183 if end==-1: end=len(lTok[1])
184 lTokenTag.append((lTok[0],lTok[1][:end]))
185 return lTokenTag
186
187
188
190 """Classe gérant l'étiquetage des textes """
192 """ Constructeur
193
194 pre: isinstance(res,Donnees.resultatAppli.Resultat)
195 """
196
197 self.resultatMedite = res
198 self.tm = TagManager()
199
201 """ Lance l'étiqueteur sur le texte et renvoie une liste [(token,tag)]
202
203 On traite les 2 fichiers séparément car si le 1er ne se termine pas
204 par un séparateur, son denier mot est concaténé au 1er du 2e fichier.
205
206 post: isinstance(__return__,list)
207 """
208 tagger = TreeTaggerWrapper()
209 texte = self.resultatMedite.getTextesConcatenes()
210 lgSource=self.resultatMedite.getLgSource()
211 lTokenTag = []
212 lTokenTag = tagger.etiquetage(texte[:lgSource])
213 self._printTaggerOutput(lTokenTag, 'TreeTaggerOutputGauche.txt')
214
215 a = tagger.etiquetage(texte[lgSource:])
216 self._printTaggerOutput(a, 'TreeTaggerOutputDroite.txt')
217
218 lTokenTag.extend(a)
219 return lTokenTag
220
222 fichier = open(os.path.join(constantes.REPMEDITE,nom),'w')
223 for token,tag in liste:
224 fichier.write(token + '\t' + tag + '\n')
225 fichier.close()
226
228 """ Extrait à partir du texte original une liste [(token, position)]
229
230 Traite le texte source puis le texte cible
231
232 post: isinstance(__return__,list)
233 """
234 texte = self.resultatMedite.getTextesConcatenes()
235 lgSource = self.resultatMedite.getLgSource()
236 lTokenPos = []
237 lTokenPos = self.extractLTokenPos__(texte[:lgSource],0)
238
239 b = self.extractLTokenPos__(texte[lgSource:],lgSource)
240 lTokenPos.extend(b)
241
242 return lTokenPos
243
245 """ Extrait à partir du texte original une liste [(token, position)]
246
247 pre: isinstance(texte,str) and isinstance(debutTexte,int) and debutTexte>=0
248 post: isinstance(__return__,list)
249 """
250 lTokenPos = []
251 currentToken = []
252 debutToken = i = 0
253 while i < len(texte):
254
255 assert len(currentToken) <= len(texte),(len(currentToken), len(texte))
256 assert len(lTokenPos) <= len(texte),(len(lTokenPos), len(texte))
257 if (texte[i] in """ .-'[]{}`"(),;:!?%»«\t\r\n\f"""):
258 if len(currentToken) > 0:
259 lTokenPos.append((''.join(currentToken), debutToken+debutTexte))
260
261
262 currentToken = []
263 debutToken = i
264
265
266 if i < len(texte) and texte[i] in """.-'[]{}`"(),;:!?%»«""":
267 lTokenPos.append((texte[i], debutToken+debutTexte))
268
269 i += 1
270 else:
271 while i < len(texte) and (texte[i] in " \t\r\n\f"): i+=1
272 debutToken = i
273
274 else:
275 currentToken.append(texte[i])
276 i+=1
277 if currentToken != []:
278 lTokenPos.append((''.join(currentToken), debutToken+debutTexte))
279
280 return lTokenPos
281
283 """ Aligne la liste (token,tag) et la liste (token,position) en une liste [(debutToken,finToken,tag)]
284
285 post: isinstance(__return__,list)
286 """
287 lTokenTag = self.etiquetage()
288 lTokenPos = self.extractLTokenPos_()
289 return self.alignement_(lTokenPos, lTokenTag)
290
292 """ Aligne les 2 listes en créant une liste [(debutToken,finToken,tag)]
293
294 pre: isinstance(lTokenTag, list)
295 isinstance(lTokenPos, list)
296 post: isinstance(__return__,list)
297 """
298 res = []
299 maxi = maxj = 0
300 while lTokenPos <> [] or lTokenTag <> []:
301
302 if lTokenPos == []:
303 raise ValueError, "lTokenPos can't be []"
304 elif lTokenTag == []:
305 raise ValueError, "lTokenTag can't be []"
306 elif lTokenPos[0][0] == lTokenTag[0][0]:
307 res.append((lTokenPos[0][1],lTokenPos[0][1]+len(lTokenPos[0][0]),lTokenTag[0][1]))
308 lTokenPos = lTokenPos[1:]
309 lTokenTag = lTokenTag[1:]
310 else:
311 i = j = 0
312 startPos = endPos = lTokenPos[j][1]
313 conclTag = lTokenTag[i][0]
314 conclPos = lTokenPos[j][0]
315 while conclTag != conclPos:
316 if len(conclTag) < len(conclPos):
317 i += 1
318 conclTag += lTokenTag[i][0]
319 endPos += len(lTokenTag[i][0])
320 if i > maxi: maxi = i
321 else:
322 j += 1
323 conclPos += lTokenPos[j][0]
324 endPos += len(lTokenPos[j][0])
325 if j > maxj: maxj = j
326
327
328 res.append((startPos,endPos,lTokenTag[i][1]))
329
330 lTokenTag = lTokenTag[i+1:]
331 lTokenPos = lTokenPos[j+1:]
332 if i > maxi: maxi = i
333 if j > maxj: maxj = j
334
335 sys.stdout.write("len(s1) "+str(len(lTokenPos))+" / len(s2)"+str(len(lTokenTag))+" / maxi="+str(maxi)+"\n")
336 return res
337
339 """ Conversion de la liste [(debut,fin,tag)] en dictionnaire
340 pre: isinstance(liste,list)
341 post: isinstance(__return__,dict)
342 """
343 dic = {}
344 for (debut,fin,tag) in liste:
345 dic[debut] = (fin,tag)
346 return dic
347
349 """ Crée la matrice de fréquences
350 pre: isinstance(la,list)
351 isinstance(da,dict)
352 post: isinstance(__return__,TagFrequencyMatrix)
353 """
354 a = self.__sum_tag(self.resultatMedite.getListeDeplacementsT1(),da),
355 b = self.__sum_tag(self.resultatMedite.getListeDeplacementsT2(),da)
356 L1=[] ; L2=[]
357 for d,f in self.resultatMedite.getListeDeplacementsT1():
358 L1.append(self.resultatMedite.getTextesConcatenes()[d:f])
359 for d,f in self.resultatMedite.getListeDeplacementsT2():
360 L2.append(self.resultatMedite.getTextesConcatenes()[d:f])
361
362 for d,f in self.resultatMedite.getListeDeplacementsT2():
363 c=self.resultatMedite.getTextesConcatenes()[d:f]
364 if c in L1: L1.remove(c)
365 for d,f in self.resultatMedite.getListeDeplacementsT1():
366 d=self.resultatMedite.getTextesConcatenes()[d:f]
367 if d in L2: L2.remove(d)
368 logging.debug('L1='+str(L1))
369 logging.debug('L2='+str(L2))
370
371 L3=[] ; L4=[]
372 for d,f in self.resultatMedite.getBlocsCommunsT1():
373 L3.append(self.resultatMedite.getTextesConcatenes()[d:f])
374 for d,f in self.resultatMedite.getBlocsCommunsT2():
375 L4.append(self.resultatMedite.getTextesConcatenes()[d:f])
376
377 for d,f in self.resultatMedite.getBlocsCommunsT2():
378 c=self.resultatMedite.getTextesConcatenes()[d:f]
379 if c in L3: L3.remove(c)
380 for d,f in self.resultatMedite.getBlocsCommunsT1():
381 d=self.resultatMedite.getTextesConcatenes()[d:f]
382 if d in L4: L4.remove(d)
383 logging.debug('L3='+str(L3))
384 logging.debug('L4='+str(L4))
385 assert len(L3) == len(L4) == 0, (len(L3), len(L4))
386
387 freqGeneticModifs = Numeric.array(
388 [self.__sum_tag(self.resultatMedite.getListeSuppressions(),da),
389 self.__sum_tag(self.resultatMedite.getListeInsertions(),da),
390 self.__sum_tag(self.resultatMedite.getListeRemplacementsT1(),da),
391 self.__sum_tag(self.resultatMedite.getListeRemplacementsT2(),da),
392 self.__sum_tag(self.resultatMedite.getListeDeplacementsT1(),da),
393 self.__sum_tag(self.resultatMedite.getListeDeplacementsT2(),da),
394 self.__sum_tag(self.resultatMedite.getBlocsCommunsT1(),da, False),
395 self.__sum_tag(self.resultatMedite.getBlocsCommunsT2(),da, False)])
396 freqTexts = Numeric.array(
397 [self.__sum_tag(self.__filtre(la,0,self.resultatMedite.getLgSource()),da),
398 self.__sum_tag(self.__filtre(la,self.resultatMedite.getLgSource(),len(self.resultatMedite.getTextesConcatenes())),da)])
399 fm = TagFrequencyMatrix(freqGeneticModifs,freqTexts)
400 fm.setRelation([0,2,4,6],0)
401 fm.setRelation([1,3,5,7],1)
402 print freqGeneticModifs
403
404 return fm
405
406
408 """ Prend une liste [(deb,fin)] et renvoie un array des fréquences des tags dans celle-ci
409
410 pre: isinstance(da,dict)
411 isinstance(liste,list)
412 forall([x in liste], isintance(x[0],int) and isinstance(x[1],int))
413 post: forall([0<=__return__[i]<=len(liste) for i in arrayrange(__return__)])
414 """
415 tab = Numeric.zeros(self.tm.getNbItems())
416 for inter in liste:
417 if p:
418 print self.resultatMedite.getTextesConcatenes()[inter[0]:inter[1]]
419 print inter
420 pos = inter[0]
421 while pos < inter[1]:
422 if da.has_key(pos):
423 (fin,tag) = da[pos]
424
425 tab[self.tm.itemToPos(tag)]+=1
426 if p: print str(da[pos])+ ' ajouté'
427
428 pos = fin
429 else: pos += 1
430 return tab
431
433 """ Renvoie la sous-liste des items de liste compris entre deb et fin """
434 res=[]
435 for x in liste:
436 if deb <= x[0] < fin:
437 res.append(x)
438 return res
439
446
448 """ Matrice de fréquences """
450 """ pre: isinstance(nbLine,int) and isinstance(nbCol,int) and nbLine>0 and nbCol>0 """
451 self.freqGeneticModifs = Numeric.array([[0]*nbCol]*nbLine)
452 self.tm = TagManager()
453 self.potm = PartOfTextManager()
454 self.name = 'FrequencyMatrix'
456 return self.name+'\nfreqGeneticModifs = '+str(self.freqGeneticModifs)
458 """ Nombre total de lignes """
459 return len(self.freqGeneticModifs)
461 """ Nombre de colonnes """
462 return len(self.freqGeneticModifs[0])
464 """ Renvoie une ligne de fréquence cad une ligne correspondant à une partie de texte """
465 if isinstance(index,int):
466 return self.freqGeneticModifs[index]
467 else: return self.freqGeneticModifs[self.potm.itemToPos(index)]
469 """ Renvoie la valeur max sur toute la matrice """
470 res=0
471 for i in xrange(self.getNbLine()):
472 for j in self.getFreqLine(i):
473 if j>res: res=j
474 return res
479
481 """ Matrice de fréquences de tags.
482
483 En ligne les modifications génétiques et en colonne les tags,
484 self.freqGeneticModifs représentes les fréquences de tags pour chaque type de modif génétique,
485 self.freqTexts représentes les fréquences de tags pour les 2 textes
486 chaque ligne de freqGeneticModifs est en relation avec une ligne de freqTexts """
487 - def __init__(self, freqGeneticModifs, freqTexts):
488 """#pre: isinstance(freqGeneticModifs,Numeric.array)
489 # isinstance(freqTexts,Numeric.array) """
490 self.freqGeneticModifs = freqGeneticModifs
491 self.freqTexts = freqTexts
492 self.tm = TagManager()
493 self.potm = PartOfTextManager()
494 self.dRelation = {}
495 self.name = 'TagFrequencyMatrix'
497 return self.name+'\nfreqGeneticModifs = '+str(self.freqGeneticModifs)+ \
498 '\nfreqTexts = '+str(self.freqTexts)
500 """Met en relation une partie du texte et un texte, par exemple insertion et texte cible.
501 pre: isinstance(posGeneticModifs,list)
502 isinstance(posTexts,int) """
503 for pos in posGeneticModifs:
504 self.dRelation[pos] = posTexts
506 """pre: isinstance(posGeneticModifs,int) """
507 try: return self.dRelation[posGeneticModifs]
508 except LookupError: return -1
510 """ Nombre total de lignes """
511 return len(self.freqGeneticModifs)+len(self.freqTexts)
513 """ Renvoie une ligne de fréquence cad une ligne correspondant à une partie de texte """
514 if isinstance(index,int):
515 maxi=len(self.freqGeneticModifs)
516 if index>=maxi: return self.freqTexts[index-maxi]
517 else: return self.freqGeneticModifs[index]
518 else: return self.freqGeneticModifs[self.potm.itemToPos(index)]
519 - def getTextLine(self,index):
520 """ Renvoie la ligne de fréquence du texte source ou cible """
521 if isinstance(index,int):
522 return self.freqTexts[index]
524 """ Renvoie une colonne d'étiquettes """
525 if not isinstance(index,int):
526 index = self.potm.itemToPos(index)
527 res=[]
528 for i in xrange(self.freqGeneticModifs.shape()[0]):
529 res.append(self.freqGeneticModifs[i][index])
530 return Numeric.array(res)
532 """ Renvoie la valeur max sur la matrice de freq genetic"""
533 res=0
534 for i in xrange(len(self.freqGeneticModifs)):
535 for j in self.getFreqLine(i):
536 if j>res: res=j
537 return res
538 - def getMaxText(self):
539 """ Renvoie la valeur max sur la matrice des 2 textes"""
540 res=0
541 for i in xrange(2):
542 for j in self.getTextLine(i):
543 if j>res: res=j
544 return res
545
547 """ Matrice de fréquences où (Sup,Remp1) sont fusionnés et (Ins,Remp2) aussi """
549 """pre: isinstance(fm,FrequencyMatrix) """
550 self.tm = TagManager()
551 self.potm = PartOfTextManager2()
552 self.freqGeneticModifs = Numeric.array([[0]*fm.getNbColumn()]*4)
553
554 for i in xrange(fm.getNbColumn()):
555 self.freqGeneticModifs[0,i] = fm.freqGeneticModifs[0,i] + fm.freqGeneticModifs[2,i]
556 for i in xrange(fm.getNbColumn()):
557 self.freqGeneticModifs[1,i] = fm.freqGeneticModifs[1,i] + fm.freqGeneticModifs[3,i]
558 self.freqGeneticModifs[2] = fm.freqGeneticModifs[4]
559 self.freqGeneticModifs[3] = fm.freqGeneticModifs[5]
560 self.freqTexts = fm.freqTexts
561 self.dRelation = {}
562 fm.setRelation([0,2],0)
563 fm.setRelation([1,3],1)
564 self.name = 'TagFrequencyMatrix2'
565
567 """ Matrice de fréquences avec les lignes BC1, BC2, Dep1, Dep2,
568 BC1+Dep1, BC2+Dep2 et Texte1, Texte2 """
570 """pre: isinstance(fm,FrequencyMatrix) """
571 self.tm = TagManager()
572 self.potm = PartOfTextManager3()
573 self.freqGeneticModifs = Numeric.array([[0]*fm.getNbColumn()]*6)
574
575 self.freqGeneticModifs[0] = fm.freqGeneticModifs[6]
576 self.freqGeneticModifs[1] = fm.freqGeneticModifs[7]
577 self.freqGeneticModifs[2] = fm.freqGeneticModifs[4]
578 self.freqGeneticModifs[3] = fm.freqGeneticModifs[5]
579 for i in xrange(fm.getNbColumn()):
580 self.freqGeneticModifs[4,i] = fm.freqGeneticModifs[6,i] + fm.freqGeneticModifs[4,i]
581 for i in xrange(fm.getNbColumn()):
582 self.freqGeneticModifs[5,i] = fm.freqGeneticModifs[7,i] + fm.freqGeneticModifs[5,i]
583
584 self.freqTexts = fm.freqTexts
585 self.dRelation = {}
586 fm.setRelation([0,2,4],0)
587 fm.setRelation([1,3,5],1)
588 self.name = 'TagFrequencyMatrix3'
589
590 -class TextFrequencyMatrix(FrequencyMatrix):
591 """ Rapports (Sup+Remp1)/BC1 et (Ins+Remp2)/BC2 en caractères et non en tags """
592 - def __init__(self,res):
593 """
594 pre: isinstance(res,Donnees.resultatAppli.Resultat)
595 """
596 FrequencyMatrix.__init__(self,2,2)
597 self.tm = TagManager2()
598 self.potm = PartOfTextManager4()
599
600 for (d,f) in res.getListeSuppressions()+res.getListeRemplacementsT1():
601 self.freqGeneticModifs[0,0] += f-d
602 for (d,f) in res.getBlocsCommunsT1():
603 self.freqGeneticModifs[0,1] += f-d
604 for (d,f) in res.getListeInsertions()+res.getListeRemplacementsT2():
605 self.freqGeneticModifs[1,0] += f-d
606 for (d,f) in res.getBlocsCommunsT2():
607 self.freqGeneticModifs[1,1] += f-d
608 self.name = 'TextFrequencyMatrix'
609
611 """Bloc décrivant une partie de texte
612
613 Les propriétés sont en lecture seule -> Bloc n'est pas mutable."""
614 - def __init__(self, type_, debut, fin, listeDeplacements=[]):
615 assert type_ in ['BC','I','S','R'], "Unauthorized type for Bloc: "+type_
616 self._end_init(type_, debut, fin, listeDeplacements)
617
618 - def _end_init(self, type_, debut, fin, listeDeplacements):
619 """Fin de l'initialisation"""
620 self.type = type_
621 assert 0 <= debut < fin, "Invalid Bloc limits"
622 self.debut = debut
623 self.fin = fin
624 if __debug__ and len(listeDeplacements) > 0:
625 assert debut <= listeDeplacements[0][0] < listeDeplacements[-1][1] <= fin, "Moves outside Bloc limits"
626 for d in listeDeplacements: assert isinstance(d, list),str(type(d))+str(d)
627 self.lDep = listeDeplacements
628
630 return ''.join(['Bloc(',self.type,',',str(self.debut),',',
631 str(self.fin),',',str(self.lDep),')'])
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
651 longueur = property(getLongueur, doc='Longueur du bloc')
652
654 res = 0
655 for (d,f) in self.lDep: res += f - d
656 return res
657 longueur_deplacement = property(getLongueurDep, doc='Longueur totale des deplacements')
658
659
661 """Bloc où le type D est permis"""
662 - def __init__(self, type_, debut, fin, listeDeplacements=[]):
663 assert type_ in ['BC','I','S','R','D'], "Unauthorized type for BlocWD: "+type_
664 self._end_init(type_, debut, fin, listeDeplacements)
665
667 """Si le bloc est D alors pas besoin de voir sa liste de déplacements"""
668 if self.type == 'D': return self.longueur
669 for (d,f) in self.lDep: res += f - d
670 return res
671
673 """ Construit une liste de Bibloc
674
675 Un Bibloc est un tuplet de 2 Bloc alignés.
676 Un Bloc est un objet (type,début,fin,listeDep) ou None si il est vide.
677 type est soit I,S,R,BC
678 debut et fin sont les limites du bloc dans la chaine de texte.
679 listeDep est une liste éventuellement vide listant tous les intervalles de déplacement compris dans le bloc.
680 Les blocs I et S sont alignés forcément avec des blocs None.
681 Les blocs R et BC sont alignés forcément avec des blocs respectivement R et BC. """
683 """ Constructeur
684
685 Si on utilise l'ancien algo d'identification des remplacements et déplacements,
686 on peut avoir des blocs présents uniquement dans resultat.getListeDeplacements().
687 Ceux-ci sont alors ajoutés comme des S ou des I.
688
689 dd: si depOrdonnes=False, pas d'assertion d'ordre sur les déplacement-> recherche d'un dep en O(n) dans __decoreDep1()
690 sinon si depOrdonnes=True, assertion d'ordre respectée -> recherche en O(log n) dans __decoreDep2()
691
692 pre: isinstance(resultat,Donnees.resultatAppli.Resultat)
693 isinstance(planTravail,Donnees.planTravail.PlanTravail) """
694 self.depOrdonnes = depOrdonnes
695
696
697
698 self.texte = resultat.getTextesConcatenes()
699 self.lgSource = resultat.getLgSource()
700 self.planTravail = planTravail
701
702 liste = []
703 lBCT1 = resultat.getBlocsCommunsT1()
704 lBCT2 = resultat.getBlocsCommunsT2()
705 assert len(lBCT1) == len(lBCT2),str(len(lBCT1))+'/'+str(len(lBCT2))
706 lRempT1 = resultat.getListeRemplacementsT1()
707 lRempT2 = resultat.getListeRemplacementsT2()
708 assert len(lRempT1) == len(lRempT2)
709 lIns = resultat.getListeInsertions()
710 lSup = resultat.getListeSuppressions()
711 lDepT1 = resultat.getListeDeplacementsT1()
712 lDepT2 = resultat.getListeDeplacementsT2()
713 i=0
714 len_lBCT1 = len(lBCT1) ; len_lBCT2 = len(lBCT2) ; len_lRempT1 = len(lRempT1)
715 len_lRempT2 = len(lRempT2) ; len_lSup = len(lSup) ; len_lIns = len(lIns)
716 len_lDepT1 = len(lDepT1) ; len_lDepT2 = len(lDepT2)
717 while (len_lBCT1 > 0 or len_lBCT2 > 0 or len_lRempT1 > 0 or
718 len_lRempT2 > 0 or len_lSup > 0 or len_lIns > 0 or
719 len_lDepT1 > 0 or len_lDepT2 > 0):
720 assert len_lBCT1 == len_lBCT2
721 assert len_lRempT1 == len_lRempT2
722
723 c="""print '-----------------------'
724 print len(lSup),len(lRempT1),len(lBCT1),len(lDepT1)
725 print len(lIns),len(lRempT2),len(lBCT2),len(lDepT2)
726 print gg(lSup),gg(lRempT1),gg(lBCT1),gg(lDepT1)
727 print gg(lIns),gg(lRempT2),gg(lBCT2),gg(lDepT2)"""
728
729
730
731 if (len_lSup > 0 and
732 ((len_lBCT1 == 0 and len_lDepT1 == 0) or
733 (len_lBCT1 == 0 and lSup[0][0] <= lDepT1[0][0]) or
734 (len_lDepT1 == 0 and lSup[0][0] < lBCT1[0][0]) or
735 (len_lBCT1 > 0 and len_lDepT1 > 0 and lSup[0][0] < lBCT1[0][0] and lSup[0][0] <= lDepT1[0][0]))):
736 depInBloc1 = self.__decoreDep(lSup[0], lDepT1)
737 liste.append((Bloc('S',lSup[0][0],lSup[0][1],depInBloc1),None))
738 lSup.pop(0) ; len_lSup -= 1 ; len_lDepT1 -= len(depInBloc1)
739 elif (len_lIns > 0 and
740 ((len_lBCT2 == 0 and len_lDepT2 == 0) or
741 (len_lBCT2 == 0 and lIns[0][0] <= lDepT2[0][0]) or
742 (len_lDepT2 == 0 and lIns[0][0] < lBCT2[0][0]) or
743 (len_lBCT2 > 0 and len_lDepT2 > 0 and lIns[0][0] < lBCT2[0][0] and lIns[0][0] <= lDepT2[0][0]))):
744 depInBloc2 = self.__decoreDep(lIns[0], lDepT2)
745 liste.append((None,Bloc('I',lIns[0][0],lIns[0][1],depInBloc2)))
746 lIns.pop(0) ; len_lIns -= 1 ; len_lDepT2 -= len(depInBloc2)
747
748 elif (len_lDepT1 > 0 and
749 ((len_lBCT1 == 0 and len_lRempT1 == 0) or
750 (len_lBCT1 == 0 and lDepT1[0][0] < lRempT1[0][0]) or
751 (len_lRempT1 == 0 and lDepT1[0][0] < lBCT1[0][0]) or
752 (len_lBCT1 > 0 and len_lRempT1 > 0 and lDepT1[0][0] < lBCT1[0][0] and lDepT1[0][0] <lRempT1[0][0]))):
753 liste.append((Bloc('S',lDepT1[0][0],lDepT1[0][1],[[lDepT1[0][0],lDepT1[0][1]]]),None))
754 lDepT1.pop(0) ; len_lDepT1 -= 1
755 elif (len_lDepT2 > 0 and
756 ((len_lBCT2 == 0 and len_lRempT2 == 0) or
757 (len_lBCT2 == 0 and lDepT2[0][0] < lRempT2[0][0]) or
758 (len_lRempT2 == 0 and lDepT2[0][0] < lBCT2[0][0]) or
759 (len_lBCT2 > 0 and len_lRempT2 > 0 and lDepT2[0][0] < lBCT2[0][0] and lDepT2[0][0] <lRempT2[0][0]))):
760 liste.append((None,Bloc('I',lDepT2[0][0],lDepT2[0][1],[[lDepT2[0][0],lDepT2[0][1]]])))
761 lDepT2.pop(0) ; len_lDepT2 -= 1
762 elif (len_lRempT1 > 0 and len_lRempT2 > 0 and
763 ((len_lBCT1 == 0 and len_lBCT2 == 0) or
764 (lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]))):
765 com="""((len_lBCT1 == 0 and len_lBCT2 == 0 and len_lDepT1 == 0 and len_lDepT2 == 0) or
766 (len_lBCT1 == 0 and len_lBCT2 == 0 and len_lDepT1 == 0 and lRempT2[0][0] <= lDepT2[0][0]) or
767 (len_lBCT1 == 0 and len_lBCT2 == 0 and lRempT1[0][0] <= lDepT1[0][0] and len_lDepT2 == 0) or
768 (len_lBCT1 == 0 and len_lBCT2 == 0 and lRempT1[0][0] <= lDepT1[0][0] and lRempT2[0][0] <= lDepT2[0][0]) or
769 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 == 0 and len_lDepT2 == 0 and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or
770 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 == 0 and lRempT2[0][0] <= lDepT2[0][0] and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or
771 (len_lBCT1 > 0 and len_lBCT2 > 0 and lRempT1[0][0] <= lDepT1[0][0] and len_lDepT2 == 0 and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or
772 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 > 0 and len_lDepT2 > 0 and
773 lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0] ))): # and lRempT1[0][0] <= lDepT1[0][0] and lRempT2[0][0] <= lDepT2[0][0]))): # ajout remp
774 """
775 depInBloc1 = self.__decoreDep(lRempT1[0], lDepT1)
776 depInBloc2 = self.__decoreDep(lRempT2[0], lDepT2)
777 liste.append((Bloc('R',lRempT1[0][0],lRempT1[0][1],depInBloc1),
778 Bloc('R',lRempT2[0][0],lRempT2[0][1],depInBloc2)))
779
780 lRempT1.pop(0) ; len_lRempT1 -= 1 ; len_lDepT1 -= len(depInBloc1)
781 lRempT2.pop(0) ; len_lRempT2 -= 1 ; len_lDepT2 -= len(depInBloc2)
782
783
784
785
786
787
788
789 else:
790 liste.append((Bloc('BC',lBCT1[0][0],lBCT1[0][1],[]),Bloc('BC',lBCT2[0][0],lBCT2[0][1],[])))
791 lBCT1.pop(0) ; len_lBCT1 -= 1
792 lBCT2.pop(0) ; len_lBCT2 -= 1
793
794 self.liste = liste
795 if __debug__:
796 assert len_lSup == len_lIns == 0
797 assert len_lRempT1 == len_lRempT2 == 0
798 assert len_lBCT1 == len_lBCT2 == 0
799 assert len_lDepT1 == len_lDepT2 == 0
800 self._testOrdre()
801 self._testNonPerte(resultat)
802
803 if len(resultat.getListeRemplacements()) == 0:
804 self.evaluation()
805 logging.debug('extractRemplacements()')
806 self.extractRemplacements()
807
809 if not self.depOrdonnes:
810 return self.__decoreDep_1(intervalle, lDep)
811 else:
812 return self.__decoreDep_3(intervalle, lDep)
814 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc
815
816 Attention !! modifie lDep
817 Comme sur les déplacements on n'a pas d'assertions sur l'ordre,
818 on parcourt à chaque appel de cette fonction toute la liste des déplacements."""
819
820 if len(lDep) == 0: return []
821 res = []
822 nouvelleLDep = []
823 for [d,f] in lDep:
824
825 if intervalle[0] <= d and f <= intervalle[1] :
826 res.append([d,f])
827 else: nouvelleLDep.append([d,f])
828 assert len(lDep) == len(nouvelleLDep) + len(res)
829 lDep = nouvelleLDep
830
831 return res
832
834 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc
835
836 Attention !! modifie lDep et retourne res2
837 Ici assertion d'ordre sur les dep, recherhe d'un dep en log(n)
838 """
839
840 if len(lDep) == 0: return []
841 deb = bisect.bisect(lDep, intervalle[0])
842 fin = bisect.bisect(lDep, intervalle[1])
843 assert deb <= fin
844 if deb == fin:
845
846 return []
847 else:
848 res2 = lDep[deb:fin]
849 lDep[deb:fin] = []
850
851
852 return res2
853
855 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc
856
857 Attention !! modifie lDep et retourne res2
858 Ici assertion d'ordre sur les dep, recherhe d'un dep en temps linéaire
859 comme lDep[0] est toujours >= intervalle (parce que l'ordre est maintenu par la
860 fonction appelante), on commence la recherche à partir de là
861 """
862 if len(lDep) == 0: return []
863 res2 = []
864 i = 0
865 while lDep[0] < intervalle[1] and lDep[1] <= intervalle[1]:
866 i+= 1
867 res2.append(lDep.pop(0))
868 return res2
869
870
872 """ Teste le bon ordre des blocs dans la liste """
873 posT1 = 0
874 posT2 = self.lgSource
875 prevB1 = prevB2 = (0,0,0,[])
876 for (B1,B2) in self.liste:
877 if B1 is not None:
878
879 assert posT1 <= B1.debut,str(posT1)+' '+str(prevB1)+' '+str(B1)
880 posT1 = B1.fin
881 for dep in B1.lDep:
882 assert B1.debut <= dep[0] <= dep[1] <= B1.fin
883 prevB1 = B1
884 if B2 is not None:
885 assert posT2 <= B2.debut, str(posT2)+' '+str(prevB2)+' '+str(B2)
886 posT2 = B2.fin
887 for dep in B2.lDep:
888 assert B2.debut <= dep[0] <= dep[1] <= B2.fin
889 prevB2 = B2
890
892 """Teste la non-perte de données lors de la création du BiblocList
893
894 On teste si chaque element dans les listes de la donnée en entrée (param Resultat)
895 est bien présent en sortie dans self.liste """
896
897 for (d,f) in resultat.getBlocsCommunsT1():
898 for (B1,B2) in self.liste:
899 if (B1 is not None and B1.type == 'BC' and B1.debut == d and B1.fin == f): break
900 else: raise AssertionError("Bloc BC1 "+str((d,f))+" lost during BiblocList creation")
901
902 for (d,f) in resultat.getBlocsCommunsT2():
903 for (B1,B2) in self.liste:
904 if (B2 is not None and B2.type == 'BC' and B2.debut == d and B2.fin == f): break
905 else: raise AssertionError("Bloc BC2 "+str((d,f))+" lost during BiblocList creation")
906
907 for (d,f) in resultat.getListeSuppressions():
908 for (B1,B2) in self.liste:
909 if (B1 is not None and (B1.type == 'S' or B1.type == 'R') and
910 B1.debut == d and B1.fin == f): break
911 else: raise AssertionError("Bloc S "+str((d,f))+" lost during BiblocList creation")
912
913 for (d,f) in resultat.getListeInsertions():
914 for (B1,B2) in self.liste:
915 if (B2 is not None and (B2.type == 'I' or B2.type == 'R') and
916 B2.debut == d and B2.fin == f): break
917 else: raise AssertionError("Bloc I "+str((d,f))+" lost during BiblocList creation")
918
919 for (d,f) in resultat.getListeRemplacementsT1():
920 for (B1,B2) in self.liste:
921 if (B1 is not None and B1.type == 'R' and B1.debut == d and B1.fin == f): break
922 else: raise AssertionError("Bloc R1 "+str((d,f))+" lost during BiblocList creation")
923
924 for (d,f) in resultat.getListeRemplacementsT2():
925 for (B1,B2) in self.liste:
926 if (B2 is not None and B2.type == 'R' and B2.debut == d and B2.fin == f): break
927 else: raise AssertionError("Bloc R2 "+str((d,f))+" lost during BiblocList creation")
928
929 for (d,f) in resultat.getListeDeplacementsT1():
930 for (B1,B2) in self.liste:
931 if (B1 is not None and ((B1.type == 'D' and B1.debut == d and B1.fin == f) or
932 ((B1.type == 'S' or B1.type == 'R') and [d,f] in B1.lDep) or
933 (B1.type == 'S' and B1.debut == d and B1.fin == f))): break
934 else: raise AssertionError("Bloc Dep1 "+str((d,f))+" lost during BiblocList creation")
935
936 for (d,f) in resultat.getListeDeplacementsT2():
937 for (B1,B2) in self.liste:
938 if (B2 is not None and ((B2.type == 'D' and B2.debut == d and B2.fin == f) or
939 ((B2.type == 'I' or B2.type == 'R') and [d,f] in B2.lDep) or
940 (B2.type == 'I' and B2.debut == d and B2.fin == f))): break
941 else: raise AssertionError("Bloc Dep2 "+str((d,f))+" lost during BiblocList creation")
942
943
945 """ Recherche les S et I correspondant au critère de transformation en R et les convertit.
946
947 Convertit chaque paire de bibloc (S,None) et (None,I) se suivant en un bibloc (R,R)
948 Modifie directement self.liste plutôt que de recréer une nouvelle liste
949 ce qui est memory expensive"""
950 if len(self.liste) == 0: return
951 if __debug__: old_liste = self.liste[:]
952 tool = utile.Utile()
953 ratio_min_remplacement = float(100)/self.planTravail.getParam().getp2()
954 i = len(self.liste) - 2
955 while i >= 0:
956 biBloc = self.liste[i]
957 biBlocSuiv = self.liste[i+1]
958
959
960 if (biBloc[0] is not None and biBloc[0].type == 'S' and biBlocSuiv[1] is not None and biBlocSuiv[1].type == 'I' and
961 tool.adequation_remplacement(self.texte[biBloc[0].debut:biBloc[0].fin],
962 self.texte[biBlocSuiv[1].debut:biBlocSuiv[1].fin], ratio_min_remplacement)):
963 self.liste[i:i+2] = [(Bloc('R',biBloc[0].debut,biBloc[0].fin,biBloc[0].lDep),
964 Bloc('R',biBlocSuiv[1].debut,biBlocSuiv[1].fin,biBlocSuiv[1].lDep))]
965 i -= 1
966
967 if __debug__:
968 self._testOrdre()
969
970 for (B1,B2) in old_liste:
971 if B1 is not None:
972 for (BN1,BN2) in self.liste:
973 if (BN1 != None and B1.debut == BN1.debut and B1.fin == BN1.fin and
974 ((B1.type == 'S' and (BN1.type == 'S' or BN1.type == 'R') or
975 (B1.type == 'BC' and B1.type == 'BC')))): break
976 else: raise AssertionError, "elt B1 lost"+str(B1)+str(B2)
977 if B2 is not None:
978 for (BN1,BN2) in self.liste:
979 if (BN2 != None and B2.debut == BN2.debut and B2.fin == BN2.fin and
980 ((B2.type == 'I' and (BN2.type == 'I' or BN2.type == 'R') or
981 (B2.type == 'BC' and B2.type == 'BC')))): break
982 else: raise AssertionError, "elt B2 lost"+str(B1)+str(B2)
983
985 """ Recherche les S et I correspondant au critère de transformation en R et les convertit.
986
987 Convertit chaque paire de bibloc (S,None) et (None,I) se suivant en un bibloc (R,R) """
988 if len(self.liste) == 0: return
989 tool = utile.Utile()
990 ratio_min_remplacement = float(100)/self.planTravail.getParam().getp2()
991 nouvelleListe = []
992 dernierAjout = 'bloc'
993 for i in xrange(len(self.liste)-1):
994 biBloc = self.liste[i]
995 biBlocSuiv = self.liste[i+1]
996
997
998 if (biBloc[0] is not None and biBloc[0].type == 'S' and biBlocSuiv[1] is not None and biBlocSuiv[1].type == 'I' and
999 tool.adequation_remplacement(self.texte[biBloc[0].debut:biBloc[0].fin],
1000 self.texte[biBlocSuiv[1].debut:biBlocSuiv[1].fin], ratio_min_remplacement)):
1001 nouvelleListe.append((Bloc('R',biBloc[0].debut,biBloc[0].fin,biBloc[0].lDep),
1002 Bloc('R',biBlocSuiv[1].debut,biBlocSuiv[1].fin,biBlocSuiv[1].lDep)))
1003 dernierAjout = 'R'
1004
1005 elif (biBloc[1] is not None and biBloc[1].type == 'I' and dernierAjout == 'R'):
1006 dernierAjout = 'bloc'
1007 else:
1008 nouvelleListe.append(biBloc)
1009 dernierAjout = 'bloc'
1010 if dernierAjout == 'bloc':
1011 nouvelleListe.append(self.liste[-1])
1012 old_liste = self.liste
1013 self.liste = nouvelleListe
1014 if __debug__:
1015 self._testOrdre()
1016
1017 for (B1,B2) in old_liste:
1018 if B1 is not None:
1019 for (BN1,BN2) in self.liste:
1020 if (BN1 != None and B1.debut == BN1.debut and B1.fin == BN1.fin and
1021 ((B1.type == 'S' and (BN1.type == 'S' or BN1.type == 'R') or
1022 (B1.type == 'BC' and B1.type == 'BC')))): break
1023 else: raise AssertionError, "elt B1 lost"+str(B1)+str(B2)
1024 if B2 is not None:
1025 for (BN1,BN2) in self.liste:
1026 if (BN2 != None and B2.debut == BN2.debut and B2.fin == BN2.fin and
1027 ((B2.type == 'I' and (BN2.type == 'I' or BN2.type == 'R') or
1028 (B2.type == 'BC' and B2.type == 'BC')))): break
1029 else: raise AssertionError, "elt B2 lost"+str(B1)+str(B2)
1030
1031
1033 """ Transfomre la liste de biblocs en un Resultat
1034
1035 Attention !! la liste des PAIRES de blocs déplacés n'est pas remplie """
1036 supp = []; ins = []; rempT1 = []; rempT2 = []
1037 BCT1 = [];BCT2 = []; depT1 = []; depT2 = []
1038 for (B1,B2) in self.liste:
1039 if B1 is not None:
1040 B1_type = B1.type
1041 if B1_type == 'S': supp.append([B1.debut,B1.fin])
1042 elif B1_type == 'R': rempT1.append([B1.debut,B1.fin])
1043 elif B1_type == 'D': depT1.append([B1.debut,B1.fin])
1044 else: BCT1.append([B1.debut,B1.fin])
1045 depT1.extend(B1.lDep)
1046 if B2 is not None:
1047 B2_type = B2.type
1048 if B2_type == 'I': ins.append([B2.debut,B2.fin])
1049 elif B2_type == 'R': rempT2.append([B2.debut,B2.fin])
1050 elif B2_type == 'D': depT2.append([B2.debut,B2.fin])
1051 else: BCT2.append([B2.debut,B2.fin])
1052 depT2.extend(B2.lDep)
1053
1054
1055 depT1.extend(depT2) ; del depT2
1056 rempT1.extend(rempT2) ; del rempT2
1057 BCT1.extend(BCT2) ; del BCT2
1058 return Donnees.resultatAppli.Resultat(ins, supp, depT1, rempT1,
1059 self.lgSource, self.texte, BCT1, [])
1060
1062 """Evalue l'alignement"""
1063 seq1 = self.lgSource
1064 seq2 = len(self.texte) - seq1
1065 ins = sup = remp1 = remp2 = bc1 = bc2 = dep1 = dep2 = 0.0
1066 for (B1,B2) in self.liste:
1067 if B1 is not None:
1068 B1_type = B1.type
1069 if B1_type == 'S': sup += B1.longueur
1070 elif B1_type == 'R': remp1 += B1.longueur
1071 elif B1_type == 'BC': bc1 += B1.longueur
1072 if B1_type == 'D': dep1 += B1.longueur
1073 else: dep1 += B1.longueur_deplacement
1074 if B2 is not None:
1075 B2_type = B2.type
1076 if B2_type == 'I': ins += B2.longueur
1077 elif B2_type == 'R': remp2 += B2.longueur
1078 elif B2_type == 'BC': bc2 += B2.longueur
1079 if B2_type == 'D': dep2 += B2.longueur
1080 else: dep2 += B2.longueur_deplacement
1081
1082
1083 formules = ['(bc1 + bc2)',
1084 '(dep1 + dep2)',
1085 '(bc1 + bc2) / (seq1 + seq2)',
1086 '(dep1 + dep2) / (seq1 + seq2)',
1087 '(bc1 + bc2 - dep1 - dep2)',
1088 '(bc1 + bc2 - dep1 - dep2) / (seq1 + seq2)',
1089 '(bc1 + bc2 - sup - ins - remp1 - remp2)',
1090 '(bc1 + bc2 - sup - ins - remp1 - remp2) / (seq1 + seq2)',
1091 '(bc1 + bc2 - sup - ins - remp1 - remp2 - dep1 - dep2)',
1092 '(bc1 + bc2 - sup - ins - remp1 - remp2 - dep1 - dep2) / (seq1 + seq2)',
1093
1094
1095 ]
1096
1097 for f in formules:
1098
1099 logging.info(f + ' = ' + str(round(eval(f),4)))
1100
1101
1102
1104 """ Imprime un rapport html à partir de la liste de biblocs
1105 dossierOutput: dossier où écrire le fichier HTML """
1106 if len(self.liste) > 10:
1107 self.print_html_streaming(dossierOutput)
1108 else:
1109 self.print_html_oneshot(dossierOutput)
1110
1112 """ Imprime un rapport html en plusieurs fois pour éviter de construire
1113 toute la chaine à substituer en mémoire
1114 dossierOutput: dossier où écrire le fichier HTML """
1115
1116 template = os.path.join(Utile.constantesDonnees.REPPRIVE,"template_rapport_stream.html")
1117 ftemplate = open(template,'r')
1118 stemplate = ''.join(ftemplate.readlines())
1119 dgm = Controleurs.DGManager.DGManager()
1120 s = Template(stemplate)
1121
1122 sres = s.safe_substitute(
1123 FILE1 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionSource(),self.planTravail.getEtatSource()),
1124 FILE2 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionCible(),self.planTravail.getEtatCible()),
1125 PARAM_PIVOTS = self.planTravail.getParam().getp1(),
1126 RATIO_REMPLACEMENTS = self.planTravail.getParam().getp2(),
1127 SEUIL_DEPLACEMENTS = self.planTravail.getParam().getp3(),
1128 PARAM_CASSE = self.__paramToON(self.planTravail.getParam().getp5()),
1129 PARAM_SEPARATEURS = self.__paramToON(self.planTravail.getParam().getp6()),
1130 PARAM_DIACRITIQUES = self.__paramToON(self.planTravail.getParam().getp7()))
1131
1132 if dossierOutput is not None:
1133 chemin = os.path.join(dossierOutput,"rapport.html")
1134 else: chemin = os.path.join(constantes.REPMEDITE,"rapport.html")
1135 fres = open(chemin,'w')
1136 fres.write(sres)
1137
1138 self.__listeToHtmlTable(stream=True, fileBuffer=fres)
1139 fres.write('</tbody></table><p></p></body></html>')
1140 fres.close()
1141
1143 """ Imprime un rapport html en une seule fois
1144 dossierOutput: dossier où écrire le fichier HTML """
1145
1146 template = os.path.join(Utile.constantesDonnees.REPPRIVE,"template_rapport.html")
1147 ftemplate = open(template,'r')
1148 stemplate = ''.join(ftemplate.readlines())
1149 dgm = Controleurs.DGManager.DGManager()
1150 s = Template(stemplate)
1151
1152 sres = s.safe_substitute(
1153 FILE1 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionSource(),self.planTravail.getEtatSource()),
1154 FILE2 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionCible(),self.planTravail.getEtatCible()),
1155 PARAM_PIVOTS = self.planTravail.getParam().getp1(),
1156 RATIO_REMPLACEMENTS = self.planTravail.getParam().getp2(),
1157 SEUIL_DEPLACEMENTS = self.planTravail.getParam().getp3(),
1158 PARAM_CASSE = self.__paramToON(self.planTravail.getParam().getp5()),
1159 PARAM_SEPARATEURS = self.__paramToON(self.planTravail.getParam().getp6()),
1160 PARAM_DIACRITIQUES = self.__paramToON(self.planTravail.getParam().getp7()),
1161 TABLE=self.__listeToHtmlTable())
1162
1163 if dossierOutput is not None:
1164 chemin = os.path.join(dossierOutput,"rapport.html")
1165 else: chemin = os.path.join(constantes.REPMEDITE,"rapport.html")
1166 fres = open(chemin,'w')
1167 fres.write(sres)
1168 fres.close()
1169
1171 """ Renvoie 'Oui' ou 'Non' en fonction d'un param booléen """
1172 if param: return "Oui"
1173 else: return "Non"
1174
1176 """ Convertit la liste de BiBlocs en une table html
1177
1178 Chaque Bibloc est convertit en une ligne <tr></tr> d'une table html
1179 Si stream, on ecrit régulièrement dans fileBuffer la table courante et
1180 on la réinitialise ensuite sinon on crée une grosse chaine que l'on renvoie"""
1181 assert stream==False or (stream and fileBuffer is not None)
1182 res = [] ; i = 0
1183 for (B1,B2) in self.liste:
1184 res.append('<tr>')
1185
1186 if B1 is None: res.append('<td></td>')
1187 else:
1188 B1_type = B1.type
1189 if B1_type == 'S': res.extend(['<td style="background-color: #FF0000">',self.__souligneTexte(B1),'</td>'])
1190 elif B1_type == 'R': res.extend(['<td style="background-color: #0000FF"> ',self.__souligneTexte(B1),'</td>'])
1191 elif B1_type == 'D': res.extend(['<td>',self.__souligneTexte(B1),'</td>'])
1192 else: res.extend(['<td>',self.__keepMEP(self.texte[B1.debut:B1.fin]),'</td>'])
1193
1194 if B2 is None: res.append('<td></td>')
1195 else:
1196 B2_type = B2.type
1197 if B2_type == 'I': res.extend(['<td style="background-color: #00FF00">',self.__souligneTexte(B2),'</td>'])
1198 elif B2_type == 'R': res.extend(['<td style="background-color: #0000FF">',self.__souligneTexte(B2),'</td>'])
1199 elif B2_type == 'D': res.extend(['<td>',self.__souligneTexte(B2),'</td>'])
1200 else: res.extend(['<td>',self.__keepMEP(self.texte[B2.debut:B2.fin]),'</td>'])
1201 res.append('</tr>\n')
1202 if stream and i%50 == 0:
1203 fileBuffer.write(''.join(res))
1204 res = []
1205
1206 if stream:
1207 fileBuffer.write(''.join(res))
1208 res = []
1209 else:
1210 return ''.join(res)
1211
1212 - def __souligneTexte(self,bloc):
1213 """ Renvoie une chaine html avec le texte souligné aux caractères déplacés """
1214 if bloc.type == 'D':
1215 return ('<span style="text-decoration: underline; font-weight: bold">'+
1216 self.__keepMEP(self.texte[bloc.debut:bloc.fin])+'</span>')
1217 res = ""
1218 deb = i = bloc.debut
1219 fin = bloc.fin
1220 lDep = bloc.lDep[:]
1221
1222 while i < fin:
1223
1224
1225 if len(lDep) > 0 and lDep[0][0] <= i:
1226 res += '<span style="text-decoration: underline; font-weight: bold">'+self.__keepMEP(self.texte[i:lDep[0][1]])+'</span>'
1227 i = lDep[0][1]
1228 lDep.pop(0)
1229 elif len(lDep) > 0 and lDep[0][0] > i:
1230 res += self.__keepMEP(self.texte[i:lDep[0][0]])
1231 i = lDep[0][0]
1232 else:
1233 assert len(lDep)==0
1234 res += self.__keepMEP(self.texte[i:fin])
1235 i = fin
1236 return res
1237
1239 """ Fonction chargée de conserver la mise en page du texte original
1240
1241 Remplace les retours à la ligne par des <br> et les espaces par des
1242
1243 Le remplacement des espaces par des nbsp est très utile pour visulaiser des
1244 alignements de code source mais plus discutable pour de la langue nat.
1245 De même mais de façon moins importante pour les br."""
1246 return texte
1247 res = ""
1248 for i in xrange(len(texte)):
1249 if texte[i] in '\r\n': res += '<br>'
1250
1251 else:
1252 try: res += '&' + htmlentitydefs.codepoint2name[ord(texte[i])] + ';'
1253 except KeyError: res += texte[i]
1254 return res
1255
1257 """BiblocList avec type déplacement (D) autorisé """
1264
1266 """ Extraction des déplacements
1267
1268 Teste les blocs insérés et supprimés.
1269 Si le rapport des déplacements à l'intérieur d'un bloc est supérieur au seuil
1270 Alors ce bloc est scindé en une liste de blocs (I ou S) et D
1271 Modifie directement self.liste"""
1272 tool = utile.Utile()
1273 ratio_seuil_lissage = float(self.planTravail.getParam().getp3()) /100
1274
1275 i = len(self.liste) - 1
1276 while i >= 0:
1277 (B1,B2) = self.liste[i]
1278 if (B1 is not None and B1.type == 'S'):
1279 assert B2 is None
1280 supMoinsDep = tool.soustr_l_intervalles([[B1.debut,B1.fin]], B1.lDep)
1281 ratio_lissage = float(tool.longueur(supMoinsDep))/(B1.fin-B1.debut)
1282 if ratio_lissage <= ratio_seuil_lissage:
1283 self.liste[i:i+1] = self.__extractDepInsSup(supMoinsDep,B1.lDep,'S')
1284 elif (B2 is not None and B2.type == 'I'):
1285 assert B1 is None
1286 insMoinsDep = tool.soustr_l_intervalles([[B2.debut,B2.fin]], B2.lDep)
1287 ratio_lissage = float(tool.longueur(insMoinsDep))/(B2.fin-B2.debut)
1288 if ratio_lissage <= ratio_seuil_lissage:
1289 self.liste[i:i+1] = self.__extractDepInsSup(insMoinsDep,B2.lDep,'I')
1290 i -= 1
1291 if __debug__:
1292 self._testOrdre()
1293
1295 """ Extraction des déplacements
1296
1297 Teste les blocs insérés et supprimés.
1298 Si le rapport des déplacements à l'intérieur d'un bloc est supérieur au seuil
1299 Alors ce bloc est scindé en une liste de blocs (I ou S) et D"""
1300 tool = utile.Utile()
1301 ratio_seuil_lissage = float(self.planTravail.getParam().getp3()) /100
1302 nouvelleListe = []
1303 for (B1,B2) in self.liste:
1304 if (B1 is not None and B1.type == 'S'):
1305 assert B2 is None
1306 supMoinsDep = tool.soustr_l_intervalles([[B1.debut,B1.fin]], B1.lDep)
1307 ratio_lissage = float(tool.longueur(supMoinsDep))/(B1.fin-B1.debut)
1308 if ratio_lissage > ratio_seuil_lissage:
1309 nouvelleListe.append((B1,None))
1310 else:
1311 nouvelleListe.extend(self.__extractDepInsSup(supMoinsDep,B1.lDep,'S'))
1312 elif (B2 is not None and B2.type == 'I'):
1313 assert B1 is None
1314 insMoinsDep = tool.soustr_l_intervalles([[B2.debut,B2.fin]], B2.lDep)
1315 ratio_lissage = float(tool.longueur(insMoinsDep))/(B2.fin-B2.debut)
1316 if ratio_lissage > ratio_seuil_lissage:
1317 nouvelleListe.append((None,B2))
1318 else:
1319 nouvelleListe.extend(self.__extractDepInsSup(insMoinsDep,B2.lDep,'I'))
1320 else:
1321 nouvelleListe.append((B1,B2))
1322 self.liste = nouvelleListe
1323 if __debug__:
1324 self._testOrdre()
1325
1327 """On scinde effectivement le blocs en une liste de blocs (S ou I) et D
1328
1329 lSupOrIns: liste de (I ou S)
1330 listeDep: liste de D
1331 SorI: traite-on des S ou des I ?
1332 pre: isinstance(lSupOrIns,list) and isinstance(listeDep,list)
1333 (SorI == 'S' or SorI == 'I') """
1334 nouvelleListe = []
1335 len_listeDep = len(listeDep)
1336 prevdeb = nbDep = 0
1337 while len(lSupOrIns) > 0 or len(listeDep) > 0:
1338
1339 if len(listeDep) == 0:
1340 for (deb,fin) in lSupOrIns:
1341 assert prevdeb <= deb
1342 prevdeb = deb
1343 if SorI == 'S': nouvelleListe.append((Bloc('S',deb,fin,[]),None))
1344 else: nouvelleListe.append((None,Bloc('I',deb,fin,[])))
1345 lSupOrIns = []
1346
1347 elif len(lSupOrIns) == 0:
1348 for (deb,fin) in listeDep:
1349 assert prevdeb <= deb
1350 prevdeb = deb
1351 if SorI == 'S': nouvelleListe.append((BlocWD('D',deb,fin,[]),None))
1352 else: nouvelleListe.append((None,BlocWD('D',deb,fin,[])))
1353 nbDep += 1
1354 listeDep = []
1355
1356 elif lSupOrIns[0][0] <= listeDep[0][0]:
1357 assert prevdeb <= lSupOrIns[0][0]
1358 prevdeb = lSupOrIns[0][0]
1359 if SorI == 'S': nouvelleListe.append((Bloc('S',lSupOrIns[0][0],lSupOrIns[0][1],[]),None))
1360 else: nouvelleListe.append((None,Bloc('I',lSupOrIns[0][0],lSupOrIns[0][1],[])))
1361
1362 lSupOrIns.pop(0)
1363 else:
1364 assert prevdeb <= listeDep[0][0]
1365 prevdeb = listeDep[0][0]
1366 if SorI == 'S': nouvelleListe.append((BlocWD('D',listeDep[0][0],listeDep[0][1],[]),None))
1367 else: nouvelleListe.append((None,BlocWD('D',listeDep[0][0],listeDep[0][1],[])))
1368 listeDep.pop(0)
1369 nbDep += 1
1370 assert len(listeDep) == len(lSupOrIns) == 0
1371 assert nbDep == len_listeDep
1372 return nouvelleListe
1373
1374
1376 """ Construit une liste de Bibloc
1377
1378 Un Bibloc est un tuplet de 2 Bloc alignés.
1379 Un Bloc est un objet (type,début,fin,listeDep) ou None si il est vide.
1380 type est soit I,S,R,BC
1381 debut et fin sont les limites du bloc dans la chaine de texte.
1382 listeDep est une liste éventuellement vide listant tous les intervalles de déplacement compris dans le bloc.
1383 Les blocs I et S sont alignés forcément avec des blocs None.
1384 Les blocs R et BC sont alignés forcément avec des blocs respectivement R et BC. """
1386 """ Constructeur
1387
1388 Si on utilise l'ancien algo d'identification des remplacements et déplacements,
1389 on peut avoir des blocs présents uniquement dans resultat.getListeDeplacements().
1390 Ceux-ci sont alors ajoutés comme des S ou des I.
1391
1392 dd: si depOrdonnes=False, pas d'assertion d'ordre sur les déplacement-> recherche d'un dep en O(n) dans __decoreDep1()
1393 sinon si depOrdonnes=True, assertion d'ordre respectée -> recherche en O(log n) dans __decoreDep2()
1394
1395 pre: isinstance(resultat,Donnees.resultatAppli.Resultat)
1396 isinstance(planTravail,Donnees.planTravail.PlanTravail) """
1397 self.depOrdonnes = depOrdonnes
1398
1399
1400
1401 self.texte = resultat.getTextesConcatenes()
1402 self.lgSource = resultat.getLgSource()
1403 self.planTravail = planTravail
1404
1405 liste = []
1406 lBCT1 = resultat.getBlocsCommunsT1()
1407 lBCT2 = resultat.getBlocsCommunsT2()
1408 assert len(lBCT1) == len(lBCT2),str(len(lBCT1))+'/'+str(len(lBCT2))
1409 lRempT1 = resultat.getListeRemplacementsT1()
1410 lRempT2 = resultat.getListeRemplacementsT2()
1411 assert len(lRempT1) == len(lRempT2)
1412 lIns = resultat.getListeInsertions()
1413 lSup = resultat.getListeSuppressions()
1414 lDepT1 = resultat.getListeDeplacementsT1()
1415 lDepT2 = resultat.getListeDeplacementsT2()
1416 i=0
1417 len_lBCT1 = len(lBCT1) ; len_lBCT2 = len(lBCT2) ; len_lRempT1 = len(lRempT1)
1418 len_lRempT2 = len(lRempT2) ; len_lSup = len(lSup) ; len_lIns = len(lIns)
1419 len_lDepT1 = len(lDepT1) ; len_lDepT2 = len(lDepT2)
1420 while (len_lBCT1 > 0 or len_lBCT2 > 0 or len_lRempT1 > 0 or
1421 len_lRempT2 > 0 or len_lSup > 0 or len_lIns > 0 or
1422 len_lDepT1 > 0 or len_lDepT2 > 0):
1423 assert len_lBCT1 == len_lBCT2
1424 assert len_lRempT1 == len_lRempT2
1425
1426 i += 1
1427
1428 c="""print '-----------------------'
1429 print len(lSup),len(lRempT1),len(lBCT1),len(lDepT1)
1430 print len(lIns),len(lRempT2),len(lBCT2),len(lDepT2)
1431 print gg(lSup),gg(lRempT1),gg(lBCT1),gg(lDepT1)
1432 print gg(lIns),gg(lRempT2),gg(lBCT2),gg(lDepT2)"""
1433
1434
1435
1436 if (len_lSup > 0 and
1437 ((len_lBCT1 == 0 and len_lDepT1 == 0) or
1438 (len_lBCT1 == 0 and lSup[0][0] <= lDepT1[0][0]) or
1439 (len_lDepT1 == 0 and lSup[0][0] < lBCT1[0][0]) or
1440 (len_lBCT1 > 0 and len_lDepT1 > 0 and lSup[0][0] < lBCT1[0][0] and lSup[0][0] <= lDepT1[0][0]))):
1441 depInBloc1 = self.__decoreDep(lSup[0], lDepT1)
1442 liste.append((('S',lSup[0][0],lSup[0][1],depInBloc1),None))
1443 lSup.pop(0) ; len_lSup -= 1 ; len_lDepT1 -= len(depInBloc1)
1444 elif (len_lIns > 0 and
1445 ((len_lBCT2 == 0 and len_lDepT2 == 0) or
1446 (len_lBCT2 == 0 and lIns[0][0] <= lDepT2[0][0]) or
1447 (len_lDepT2 == 0 and lIns[0][0] < lBCT2[0][0]) or
1448 (len_lBCT2 > 0 and len_lDepT2 > 0 and lIns[0][0] < lBCT2[0][0] and lIns[0][0] <= lDepT2[0][0]))):
1449 depInBloc2 = self.__decoreDep(lIns[0], lDepT2)
1450 liste.append((None,('I',lIns[0][0],lIns[0][1],depInBloc2)))
1451 lIns.pop(0) ; len_lIns -= 1 ; len_lDepT2 -= len(depInBloc2)
1452
1453 elif (len_lDepT1 > 0 and
1454 ((len_lBCT1 == 0 and len_lRempT1 == 0) or
1455 (len_lBCT1 == 0 and lDepT1[0][0] < lRempT1[0][0]) or
1456 (len_lRempT1 == 0 and lDepT1[0][0] < lBCT1[0][0]) or
1457 (len_lBCT1 > 0 and len_lRempT1 > 0 and lDepT1[0][0] < lBCT1[0][0] and lDepT1[0][0] <lRempT1[0][0]))):
1458 liste.append((('S',lDepT1[0][0],lDepT1[0][1],[[lDepT1[0][0],lDepT1[0][1]]]),None))
1459 lDepT1.pop(0) ; len_lDepT1 -= 1
1460 elif (len_lDepT2 > 0 and
1461 ((len_lBCT2 == 0 and len_lRempT2 == 0) or
1462 (len_lBCT2 == 0 and lDepT2[0][0] < lRempT2[0][0]) or
1463 (len_lRempT2 == 0 and lDepT2[0][0] < lBCT2[0][0]) or
1464 (len_lBCT2 > 0 and len_lRempT2 > 0 and lDepT2[0][0] < lBCT2[0][0] and lDepT2[0][0] <lRempT2[0][0]))):
1465 liste.append((None,('I',lDepT2[0][0],lDepT2[0][1],[[lDepT2[0][0],lDepT2[0][1]]])))
1466 lDepT2.pop(0) ; len_lDepT2 -= 1
1467 elif (len_lRempT1 > 0 and len_lRempT2 > 0 and
1468 ((len_lBCT1 == 0 and len_lBCT2 == 0) or
1469 (lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]))):
1470 com="""((len_lBCT1 == 0 and len_lBCT2 == 0 and len_lDepT1 == 0 and len_lDepT2 == 0) or
1471 (len_lBCT1 == 0 and len_lBCT2 == 0 and len_lDepT1 == 0 and lRempT2[0][0] <= lDepT2[0][0]) or
1472 (len_lBCT1 == 0 and len_lBCT2 == 0 and lRempT1[0][0] <= lDepT1[0][0] and len_lDepT2 == 0) or
1473 (len_lBCT1 == 0 and len_lBCT2 == 0 and lRempT1[0][0] <= lDepT1[0][0] and lRempT2[0][0] <= lDepT2[0][0]) or
1474 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 == 0 and len_lDepT2 == 0 and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or
1475 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 == 0 and lRempT2[0][0] <= lDepT2[0][0] and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or
1476 (len_lBCT1 > 0 and len_lBCT2 > 0 and lRempT1[0][0] <= lDepT1[0][0] and len_lDepT2 == 0 and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or
1477 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 > 0 and len_lDepT2 > 0 and
1478 lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0] ))): # and lRempT1[0][0] <= lDepT1[0][0] and lRempT2[0][0] <= lDepT2[0][0]))): # ajout remp
1479 """
1480 depInBloc1 = self.__decoreDep(lRempT1[0], lDepT1)
1481 depInBloc2 = self.__decoreDep(lRempT2[0], lDepT2)
1482 liste.append((('R',lRempT1[0][0],lRempT1[0][1],depInBloc1),
1483 ('R',lRempT2[0][0],lRempT2[0][1],depInBloc2)))
1484
1485 lRempT1.pop(0) ; len_lRempT1 -= 1 ; len_lDepT1 -= len(depInBloc1)
1486 lRempT2.pop(0) ; len_lRempT2 -= 1 ; len_lDepT2 -= len(depInBloc2)
1487
1488
1489
1490
1491
1492
1493
1494 else:
1495 liste.append((('BC',lBCT1[0][0],lBCT1[0][1],[]),('BC',lBCT2[0][0],lBCT2[0][1],[])))
1496 lBCT1.pop(0) ; len_lBCT1 -= 1
1497 lBCT2.pop(0) ; len_lBCT2 -= 1
1498
1499 self.liste = liste
1500 if False and __debug__:
1501 assert len_lSup == len_lIns == 0
1502 assert len_lRempT1 == len_lRempT2 == 0
1503 assert len_lBCT1 == len_lBCT2 == 0
1504 assert len_lDepT1 == len_lDepT2 == 0
1505 self._testOrdre()
1506 self._testNonPerte(resultat)
1507
1508 if len(resultat.getListeRemplacements()) == 0:
1509 try:
1510 self.evaluation()
1511 except ZeroDivisionError:
1512 logging.debug("Erreur d'evaluation ZeroDivisionError")
1513 logging.debug('extractRemplacements()')
1514 self.extractRemplacements()
1515
1517 if not self.depOrdonnes:
1518 return self.__decoreDep_1(intervalle, lDep)
1519 else:
1520 return self.__decoreDep_3(intervalle, lDep)
1522 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc
1523
1524 Attention !! modifie lDep
1525 Comme sur les déplacements on n'a pas d'assertions sur l'ordre,
1526 on parcourt à chaque appel de cette fonction toute la liste des déplacements."""
1527
1528 if len(lDep) == 0: return []
1529 res = []
1530 nouvelleLDep = []
1531 for [d,f] in lDep:
1532
1533 if intervalle[0] <= d and f <= intervalle[1] :
1534 res.append([d,f])
1535 else: nouvelleLDep.append([d,f])
1536 assert len(lDep) == len(nouvelleLDep) + len(res)
1537 lDep = nouvelleLDep
1538
1539 return res
1540
1542 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc
1543
1544 Attention !! modifie lDep et retourne res2
1545 Ici assertion d'ordre sur les dep, recherhe d'un dep en log(n)
1546 """
1547
1548 if len(lDep) == 0: return []
1549 deb = bisect.bisect(lDep, intervalle[0])
1550 fin = bisect.bisect(lDep, intervalle[1])
1551 assert deb <= fin
1552 if deb == fin:
1553
1554 return []
1555 else:
1556 res2 = lDep[deb:fin]
1557 lDep[deb:fin] = []
1558
1559
1560 return res2
1561
1563 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc
1564
1565 Attention !! modifie lDep et retourne res2
1566 Ici assertion d'ordre sur les dep, recherhe d'un dep en temps linéaire
1567 comme lDep[0] est toujours >= intervalle (parce que l'ordre est maintenu par la
1568 fonction appelante), on commence la recherche à partir de là
1569 """
1570 if len(lDep) == 0: return []
1571 res2 = []
1572 i = 0
1573
1574
1575
1576 while len(lDep)>0 and (lDep[0][0] >= intervalle[0]) and (lDep[0][1] <= intervalle[1]):
1577 i+= 1
1578 res2.append(lDep.pop(0))
1579 return res2
1580
1582 """ Teste le bon ordre des blocs dans la liste """
1583 posT1 = 0
1584 posT2 = self.lgSource
1585 prevB1 = prevB2 = (0,0,0,[])
1586 for (B1,B2) in self.liste:
1587 if B1 is not None:
1588
1589 assert posT1 <= B1[1],str(posT1)+' '+str(prevB1)+' '+str(B1)
1590 posT1 = B1[2]
1591 for dep in B1[3]:
1592 assert B1[1] <= dep[0] <= dep[1] <= B1[2]
1593 prevB1 = B1
1594 if B2 is not None:
1595 assert posT2 <= B2[1], str(posT2)+' '+str(prevB2)+' '+str(B2)
1596 posT2 = B2[2]
1597 for dep in B2[3]:
1598 assert B2[1] <= dep[0] <= dep[1] <= B2[2]
1599 prevB2 = B2
1600
1602 """Teste la non-perte de données lors de la création du BiblocList
1603
1604 On teste si chaque element dans les listes de la donnée en entrée (param Resultat)
1605 est bien présent en sortie dans self.liste """
1606
1607 for (d,f) in resultat.getBlocsCommunsT1():
1608 for (B1,B2) in self.liste:
1609 if (B1 is not None and B1[0] == 'BC' and B1[1] == d and B1[2] == f): break
1610 else: raise AssertionError("Bloc BC1 "+str((d,f))+" lost during BiblocList creation")
1611
1612 for (d,f) in resultat.getBlocsCommunsT2():
1613 for (B1,B2) in self.liste:
1614 if (B2 is not None and B2[0] == 'BC' and B2[1] == d and B2[2] == f): break
1615 else: raise AssertionError("Bloc BC2 "+str((d,f))+" lost during BiblocList creation")
1616
1617 for (d,f) in resultat.getListeSuppressions():
1618 for (B1,B2) in self.liste:
1619 if (B1 is not None and (B1[0] == 'S' or B1[0] == 'R') and
1620 B1[1] == d and B1[2] == f): break
1621 else: raise AssertionError("Bloc S "+str((d,f))+" lost during BiblocList creation")
1622
1623 for (d,f) in resultat.getListeInsertions():
1624 for (B1,B2) in self.liste:
1625 if (B2 is not None and (B2[0] == 'I' or B2[0] == 'R') and
1626 B2[1] == d and B2[2] == f): break
1627 else: raise AssertionError("Bloc I "+str((d,f))+" lost during BiblocList creation")
1628
1629 for (d,f) in resultat.getListeRemplacementsT1():
1630 for (B1,B2) in self.liste:
1631 if (B1 is not None and B1[0] == 'R' and B1[1] == d and B1[2] == f): break
1632 else: raise AssertionError("Bloc R1 "+str((d,f))+" lost during BiblocList creation")
1633
1634 for (d,f) in resultat.getListeRemplacementsT2():
1635 for (B1,B2) in self.liste:
1636 if (B2 is not None and B2[0] == 'R' and B2[1] == d and B2[2] == f): break
1637 else: raise AssertionError("Bloc R2 "+str((d,f))+" lost during BiblocList creation")
1638
1639 for (d,f) in resultat.getListeDeplacementsT1():
1640 for (B1,B2) in self.liste:
1641 if (B1 is not None and ((B1[0] == 'D' and B1[1] == d and B1[2] == f) or
1642 ((B1[0] == 'S' or B1[0] == 'R') and [d,f] in B1[3]) or
1643 (B1[0] == 'S' and B1[1] == d and B1[2] == f))): break
1644 else: raise AssertionError("Bloc Dep1 "+str((d,f))+" lost during BiblocList creation")
1645
1646 for (d,f) in resultat.getListeDeplacementsT2():
1647 for (B1,B2) in self.liste:
1648 if (B2 is not None and ((B2[0] == 'D' and B2[1] == d and B2[2] == f) or
1649 ((B2[0] == 'I' or B2[0] == 'R') and [d,f] in B2[3]) or
1650 (B2[0] == 'I' and B2[1] == d and B2[2] == f))): break
1651 else: raise AssertionError("Bloc Dep2 "+str((d,f))+" lost during BiblocList creation")
1652
1653
1655 """ Recherche les S et I correspondant au critère de transformation en R et les convertit.
1656
1657 Convertit chaque paire de bibloc (S,None) et (None,I) se suivant en un bibloc (R,R)
1658 Modifie directement self.liste plutôt que de recréer une nouvelle liste
1659 ce qui est memory expensive"""
1660 if len(self.liste) == 0: return
1661 if __debug__: old_liste = self.liste[:]
1662 tool = utile.Utile()
1663 ratio_min_remplacement = float(100)/self.planTravail.getParam().getp2()
1664 i = len(self.liste) - 2
1665 while i >= 0:
1666 if i%1000 == 0: logging.debug("itérationR %d",i)
1667 biBloc = self.liste[i]
1668 biBlocSuiv = self.liste[i+1]
1669
1670
1671 if (biBloc[0] is not None and biBloc[0][0] == 'S' and
1672 biBlocSuiv[1] is not None and biBlocSuiv[1][0] == 'I' and
1673 tool.adequation_remplacement(self.texte[biBloc[0][1]:biBloc[0][2]],
1674 self.texte[biBlocSuiv[1][1]:biBlocSuiv[1][2]], ratio_min_remplacement)):
1675 self.liste[i:i+2] = [(('R',biBloc[0][1],biBloc[0][2],biBloc[0][3]),
1676 ('R',biBlocSuiv[1][1],biBlocSuiv[1][2],biBlocSuiv[1][3]))]
1677 i -= 1
1678
1679 if False and __debug__:
1680 self._testOrdre()
1681
1682 for (B1,B2) in old_liste:
1683 if B1 is not None:
1684 for (BN1,BN2) in self.liste:
1685 if (BN1 is not None and B1[1] == BN1[1] and B1[2] == BN1[2] and
1686 (((B1[0] == 'S' or B1[0] == 'D') and (BN1[0] == 'S' or BN1[0] == 'R' or BN1[0] == 'D') or
1687 (B1[0] == 'BC' and B1[0] == 'BC')))): break
1688 else: raise AssertionError, "elt B1 lost"+str(B1)+str(B2)
1689 if B2 is not None:
1690 for (BN1,BN2) in self.liste:
1691 if (BN2 is not None and B2[1] == BN2[1] and B2[2] == BN2[2] and
1692 (((B2[0] == 'I' or B2[0] == 'D') and (BN2[0] == 'I' or BN2[0] == 'R' or BN1[0] == 'D') or
1693 (B2[0] == 'BC' and B2[0] == 'BC')))): break
1694 else: raise AssertionError, "elt B2 lost"+str(B1)+str(B2)
1695
1697 """ Recherche les S et I correspondant au critère de transformation en R et les convertit.
1698
1699 Convertit chaque paire de bibloc (S,None) et (None,I) se suivant en un bibloc (R,R) """
1700 if len(self.liste) == 0: return
1701 tool = utile.Utile()
1702 ratio_min_remplacement = float(100)/self.planTravail.getParam().getp2()
1703 nouvelleListe = []
1704 dernierAjout = 'bloc'
1705 for i in xrange(len(self.liste)-1):
1706 biBloc = self.liste[i]
1707 biBlocSuiv = self.liste[i+1]
1708
1709
1710 if (biBloc[0] is not None and biBloc[0][0] == 'S' and biBlocSuiv[1] is not None and biBlocSuiv[1][0] == 'I' and
1711 tool.adequation_remplacement(self.texte[biBloc[0][1]:biBloc[0][2]],
1712 self.texte[biBlocSuiv[1][1]:biBlocSuiv[1][2]], ratio_min_remplacement)):
1713 nouvelleListe.append((Bloc('R',biBloc[0][1],biBloc[0][2],biBloc[0][3]),
1714 Bloc('R',biBlocSuiv[1][1],biBlocSuiv[1][2],biBlocSuiv[1][3])))
1715 dernierAjout = 'R'
1716
1717 elif (biBloc[1] is not None and biBloc[1][0] == 'I' and dernierAjout == 'R'):
1718 dernierAjout = 'bloc'
1719 else:
1720 nouvelleListe.append(biBloc)
1721 dernierAjout = 'bloc'
1722 if dernierAjout == 'bloc':
1723 nouvelleListe.append(self.liste[-1])
1724 old_liste = self.liste
1725 self.liste = nouvelleListe
1726 if __debug__:
1727 self._testOrdre()
1728
1729 for (B1,B2) in old_liste:
1730 if B1 is not None:
1731 for (BN1,BN2) in self.liste:
1732 if (BN1 != None and B1[1] == BN1[1] and B1[2] == BN1[2] and
1733 ((B1[0] == 'S' and (BN1[0] == 'S' or BN1[0] == 'R') or
1734 (B1[0] == 'BC' and B1[0] == 'BC')))): break
1735 else: raise AssertionError, "elt B1 lost"+str(B1)+str(B2)
1736 if B2 is not None:
1737 for (BN1,BN2) in self.liste:
1738 if (BN2 != None and B2[1] == BN2[1] and B2[2] == BN2[2] and
1739 ((B2[0] == 'I' and (BN2[0] == 'I' or BN2[0] == 'R') or
1740 (B2[0] == 'BC' and B2[0] == 'BC')))): break
1741 else: raise AssertionError, "elt B2 lost"+str(B1)+str(B2)
1742
1743
1745 """ Transfomre la liste de biblocs en un Resultat
1746
1747 Attention !! la liste des PAIRES de blocs déplacés n'est pas remplie """
1748 supp = []; ins = []; rempT1 = []; rempT2 = []
1749 BCT1 = [];BCT2 = []; depT1 = []; depT2 = []
1750 for (B1,B2) in self.liste:
1751 if B1 is not None:
1752 B1_type = B1[0]
1753 if B1_type == 'S': supp.append([B1[1],B1[2]])
1754 elif B1_type == 'R': rempT1.append([B1[1],B1[2]])
1755 elif B1_type == 'D': depT1.append([B1[1],B1[2]])
1756 else: BCT1.append([B1[1],B1[2]])
1757 depT1.extend(B1[3])
1758 if B2 is not None:
1759 B2_type = B2[0]
1760 if B2_type == 'I': ins.append([B2[1],B2[2]])
1761 elif B2_type == 'R': rempT2.append([B2[1],B2[2]])
1762 elif B2_type == 'D': depT2.append([B2[1],B2[2]])
1763 else: BCT2.append([B2[1],B2[2]])
1764 depT2.extend(B2[3])
1765
1766
1767 depT1.extend(depT2) ; del depT2
1768 rempT1.extend(rempT2) ; del rempT2
1769 BCT1.extend(BCT2) ; del BCT2
1770 return Donnees.resultatAppli.Resultat(ins, supp, depT1, rempT1,
1771 self.lgSource, self.texte, BCT1, [])
1772
1774 """Evalue l'alignement"""
1775 assert c1+c2+c3 == 1
1776 sep = """ !\r,\n:\t;-?"'`()"""
1777 seq1 = self.lgSource
1778 seq2 = len(self.texte) - seq1
1779 texte = self.texte
1780 ins = sup = remp1 = remp2 = bc1 = bc2 = dep1 = dep2 = 0.0
1781 nb_bc1 = nb_bc2 = nb_dep1 = nb_dep2 = nb_sup = nb_ins = nb_remp1 = nb_remp2 = 0
1782 front_bloc = front_bloc_sep = 0
1783 lBC = [] ; lDep = [] ; lIns = [] ; lSup = [] ; lRemp = []
1784 for (B1,B2) in self.liste:
1785 if B1 is not None:
1786 B1_type = B1[0]
1787 if B1_type == 'S':
1788 sup += B1[2]-B1[1] ; nb_sup += 1 ; front_bloc += 1
1789 bisect.insort_right(lSup,B1[2]-B1[1])
1790 if B1[1] == 0: front_bloc_sep += 1
1791 elif (texte[B1[1]] in sep) or (texte[B1[1]-1] in sep): front_bloc_sep += 1
1792 elif B1_type == 'R':
1793 remp1 += B1[2]-B1[1] ; nb_remp1 += 1 ; front_bloc += 1
1794 bisect.insort_right(lRemp,B1[2]-B1[1])
1795 if B1[1] == 0: front_bloc_sep += 1
1796 elif (texte[B1[1]] in sep) or (texte[B1[1]-1] in sep): front_bloc_sep += 1
1797 elif B1_type == 'BC':
1798 bc1 += B1[2]-B1[1] ; nb_bc1 += 1 ; front_bloc += 1
1799 bisect.insort_right(lBC,B1[2]-B1[1])
1800 if B1[1] == 0: front_bloc_sep += 1
1801 elif (texte[B1[1]] in sep) or (texte[B1[1]-1] in sep): front_bloc_sep += 1
1802 if B1_type == 'D':
1803 dep1 += B1[2]-B1[1] ; nb_dep1 += 1 ; front_bloc += 1
1804 bisect.insort_right(lDep,B1[2]-B1[1])
1805 if B1[1] == 0: front_bloc_sep += 1
1806 elif (texte[B1[1]] in sep) or (texte[B1[1]-1] in sep): front_bloc_sep += 1
1807 else:
1808 for (d,f) in B1[3]:
1809 dep1 += f-d ; nb_dep1 += 1; bisect.insort_right(lDep,f-d)
1810 if B2 is not None:
1811 B2_type = B2[0]
1812 if B2_type == 'I':
1813 ins += B2[2]-B2[1] ; nb_ins += 1 ; front_bloc += 1
1814 bisect.insort_right(lIns,B2[2]-B2[1])
1815 if B2[1] == seq1: front_bloc_sep += 1
1816 elif (texte[B2[1]] in sep) or (texte[B2[1]-1] in sep): front_bloc_sep += 1
1817 elif B2_type == 'R':
1818 remp2 += B2[2]-B2[1] ; nb_remp2 += 1 ; front_bloc += 1
1819 bisect.insort_right(lRemp,B2[2]-B2[1])
1820 if B2[1] == seq1: front_bloc_sep += 1
1821 elif (texte[B2[1]] in sep) or (texte[B2[1]-1] in sep): front_bloc_sep += 1
1822 elif B2_type == 'BC':
1823 bc2 += B2[2]-B2[1] ; nb_bc2 += 1 ; front_bloc += 1
1824 bisect.insort_right(lBC,B2[2]-B2[1])
1825 if B2[1] == seq1: front_bloc_sep += 1
1826 elif (texte[B2[1]] in sep) or (texte[B2[1]-1] in sep): front_bloc_sep += 1
1827 if B2_type == 'D':
1828 dep2 += B2[2]-B2[1] ; nb_dep2 += 1 ; front_bloc += 1
1829 bisect.insort_right(lDep,B2[2]-B2[1])
1830 if B2[1] == seq1: front_bloc_sep += 1
1831 elif (texte[B2[1]] in sep) or (texte[B2[1]-1] in sep): front_bloc_sep += 1
1832 else:
1833 for (d,f) in B2[3]:
1834 dep2 += f-d ; nb_dep2 += 1 ; bisect.insort_right(lDep,f-d)
1835 assert sum(lBC) == bc1+bc2 and len(lBC) == nb_bc1+nb_bc2
1836 assert sum(lDep) == dep1+dep2 and len(lDep) == nb_dep1+nb_dep2
1837 assert front_bloc_sep <= front_bloc
1838
1839 formules = ['seq1',
1840 'seq2',
1841 '(bc1 + bc2)',
1842 '(nb_bc1 + nb_bc2)',
1843 '(0.0+bc1 + bc2) / (nb_bc1 + nb_bc2)',
1844 'lBC[len(lBC)/2]',
1845 '(dep1 + dep2)',
1846 '(nb_dep1 + nb_dep2)',
1847 '(0.0+dep1 + dep2) / (nb_dep1 + nb_dep2)',
1848 'lDep[len(lDep)/2]',
1849 '(bc1 + bc2) / (seq1 + seq2)',
1850 '(dep1 + dep2) / (seq1 + seq2)',
1851 '(bc1 + bc2 + dep1 + dep2)',
1852 '(nb_bc1 + nb_bc2 + nb_dep1 + nb_dep2)',
1853 '(bc1 + bc2 + dep1 + dep2) / (seq1 + seq2)',
1854 '(bc1 + bc2 - dep1 - dep2)',
1855 '(bc1 + bc2 - dep1 - dep2) / (seq1 + seq2)',
1856 '(bc1 + bc2 - sup - ins - remp1 - remp2)',
1857 '(bc1 + bc2 - sup - ins - remp1 - remp2) / (seq1 + seq2)',
1858 '(bc1 + bc2 - sup - ins - remp1 - remp2 - dep1 - dep2)',
1859 '(bc1 + bc2 - sup - ins - remp1 - remp2 - dep1 - dep2) / (seq1 + seq2)',
1860
1861
1862 ]
1863
1864 for f in formules:
1865 try:
1866
1867 logging.info(f + ' = ' + str(round(eval(f),4)))
1868 except Exception:
1869 continue
1870
1871
1872
1873 dicoSommes = {}
1874 dicoSommes['inv'] = [bc1+bc2,nb_bc1,nb_bc2]
1875 dicoSommes['sup'] = [sup,nb_sup]
1876 dicoSommes['ins'] = [ins,nb_ins]
1877 dicoSommes['remp'] = [remp1+remp2,nb_remp1,nb_remp2]
1878 dicoSommes['dep'] = [dep1+dep2,nb_dep1,nb_dep2]
1879 dicoSommes['lTexte1'] = seq1
1880 dicoSommes['lTexte2'] = seq2
1881 dicoSommes['front'] = (front_bloc, front_bloc_sep)
1882
1883 x = (1.0+((bc1 + bc2 - sup - ins - remp1 - remp2 - dep1 - dep2) / (seq1 +seq2)))/2.0
1884 pri1 = (bc1 + bc2 + dep1 + dep2) / (bc1 + bc2 + dep1 + dep2 + sup + ins + remp1 + remp2)
1885 pri2 = (bc1 + bc2) / (bc1 + bc2 + dep1 + dep2)
1886 pri3 = (remp1 + remp2) / (sup + ins + remp1 + remp2)
1887 pri = (pri1 + pri2 + pri3) / 3.0
1888 assert 0 <= pri1 <= 1, pri1
1889 assert 0 <= pri2 <= 1, pri2
1890 assert 0 <= pri3 <= 1, pri3
1891
1892 if nb_bc1+nb_bc2 > 0: y1 = ((0.0+bc1 + bc2) /(nb_bc1 + nb_bc2))/lBC[-1]
1893 else: y1 = 0
1894 if nb_sup > 0: y2 = ((0.0+sup) / nb_sup) / lSup[-1]
1895 else: y2 = 0
1896 if nb_ins > 0: y3 = ((0.0+ins) / nb_ins) / lIns[-1]
1897 else: y3 = 0
1898 if nb_remp1+nb_remp2 > 0: y4 = ((0.0+remp1+remp2) / (nb_remp1 +nb_remp2))/ lRemp[-1]
1899 else: y4 = 0
1900 if nb_dep1+nb_dep2 > 0: y5 = ((0.0+dep1+dep2) / (nb_dep1 + nb_dep2))/ lDep[-1]
1901 else: y5 = 0
1902 assert 0 <= y1 <= 1, y1
1903 assert 0 <= y2 <= 1, y2
1904 assert 0 <= y3 <= 1, y3
1905 assert 0 <= y4 <= 1, y4
1906 assert 0 <= y5 <= 1, y5
1907
1908
1909
1910
1911
1912
1913 y = (y1 + y2 + y3 + y4 + y5) / 5.0
1914 assert 0 <= y <= 1 ,y
1915 z0 = (0.0+bc1+bc2) / (0.0+bc1+bc2+dep1+dep2)
1916 z1 = (0.0+dep1+dep2) / (dep1+dep2+ins+sup+remp1+remp2)
1917 z2 = (0.0+remp1+remp2) / (sup+ins+remp1+remp2)
1918 z = (0.0+z1+z2)/2.0
1919 assert 0 <= z <= 1,z
1920
1921
1922 sep = (0.0 + front_bloc_sep) / front_bloc
1923 assert 0 <= sep <= 1, sep
1924
1925 sim_old = c1 * x + c2 * y + c3 *z
1926 assert 0 <= sim_old <= 1,sim_old
1927 sim = (pri + y + sep ) / 3.0
1928 assert 0 <= sim <= 1,sim
1929
1930 logging.info('x = ' + str(round(x,4)))
1931 logging.info('y = ' + str(round(y,4)))
1932 logging.info('z = ' + str(round(z,4)))
1933 logging.info('sim_old = ' + str(round(sim_old,4)))
1934 logging.info('pri1 = ' + str(round(pri1,4)))
1935 logging.info('pri2 = ' + str(round(pri2,4)))
1936 logging.info('pri3 = ' + str(round(pri3,4)))
1937 logging.info('pri = ' + str(round(pri,4)))
1938 logging.info('yINV = ' + str(round(y1,4)))
1939 logging.info('ySUP = ' + str(round(y2,4)))
1940 logging.info('yINS = ' + str(round(y3,4)))
1941 logging.info('yREMP = ' + str(round(y4,4)))
1942 logging.info('yDEP = ' + str(round(y5,4)))
1943 logging.info('y = ' + str(round(y,4)))
1944 logging.info('sep = ' + str(round(sep,4)))
1945 logging.info('sim = ' + str(round(sim,4)))
1946 return x,y,z,sim,dicoSommes,[y1,y2,y3,y4,y5],[z0,z1,z2], (pri1,pri2,pri3),sep
1947
1949 """ Imprime un rapport html à partir de la liste de biblocs
1950 dossierOutput: dossier où écrire le fichier HTML """
1951 if len(self.liste) > 10:
1952 self.print_html_streaming(dossierOutput)
1953 else:
1954 self.print_html_oneshot(dossierOutput)
1955
1957 """ Imprime un rapport html en plusieurs fois pour éviter de construire
1958 toute la chaine à substituer en mémoire
1959 dossierOutput: dossier où écrire le fichier HTML """
1960
1961 template = os.path.join(Utile.constantesDonnees.REPPRIVE,"template_rapport_stream.html")
1962 ftemplate = open(template,'r')
1963 stemplate = ''.join(ftemplate.readlines())
1964 dgm = Controleurs.DGManager.DGManager()
1965 s = Template(stemplate)
1966
1967 sres = s.safe_substitute(
1968 FILE1 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionSource(),self.planTravail.getEtatSource()),
1969 FILE2 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionCible(),self.planTravail.getEtatCible()),
1970 PARAM_PIVOTS = self.planTravail.getParam().getp1(),
1971 RATIO_REMPLACEMENTS = self.planTravail.getParam().getp2(),
1972 SEUIL_DEPLACEMENTS = self.planTravail.getParam().getp3(),
1973 PARAM_CASSE = self.__paramToON(self.planTravail.getParam().getp5()),
1974 PARAM_SEPARATEURS = self.__paramToON(self.planTravail.getParam().getp6()),
1975 PARAM_DIACRITIQUES = self.__paramToON(self.planTravail.getParam().getp7()))
1976
1977 if dossierOutput is not None:
1978 chemin = os.path.join(dossierOutput,"rapport.html")
1979 else: chemin = os.path.join(constantes.REPMEDITE,"rapport.html")
1980 fres = open(chemin,'w')
1981 fres.write(sres)
1982 if justPrintEntete:
1983 return fres
1984
1985 self.__listeToHtmlTable(stream=True, fileBuffer=fres)
1986 fres.write('</tbody></table><p></p></body></html>')
1987 fres.close()
1988
1992 fBuffer.write('</tbody></table><p></p></body></html>')
1993 fBuffer.close()
1994
1996 """ Imprime un rapport html en une seule fois
1997 dossierOutput: dossier où écrire le fichier HTML """
1998
1999 template = os.path.join(Utile.constantesDonnees.REPPRIVE,"template_rapport.html")
2000 ftemplate = open(template,'r')
2001 stemplate = ''.join(ftemplate.readlines())
2002 dgm = Controleurs.DGManager.DGManager()
2003 s = Template(stemplate)
2004
2005 sres = s.safe_substitute(
2006 FILE1 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionSource(),self.planTravail.getEtatSource()),
2007 FILE2 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionCible(),self.planTravail.getEtatCible()),
2008 PARAM_PIVOTS = self.planTravail.getParam().getp1(),
2009 RATIO_REMPLACEMENTS = self.planTravail.getParam().getp2(),
2010 SEUIL_DEPLACEMENTS = self.planTravail.getParam().getp3(),
2011 PARAM_CASSE = self.__paramToON(self.planTravail.getParam().getp5()),
2012 PARAM_SEPARATEURS = self.__paramToON(self.planTravail.getParam().getp6()),
2013 PARAM_DIACRITIQUES = self.__paramToON(self.planTravail.getParam().getp7()),
2014 TABLE=self.__listeToHtmlTable())
2015
2016 if dossierOutput is not None:
2017 chemin = os.path.join(dossierOutput,"rapport.html")
2018 else: chemin = os.path.join(constantes.REPMEDITE,"rapport.html")
2019 fres = open(chemin,'w')
2020 fres.write(sres)
2021 fres.close()
2022
2024 """ Renvoie 'Oui' ou 'Non' en fonction d'un param booléen """
2025 if param: return "Oui"
2026 else: return "Non"
2027
2029 """ Convertit la liste de BiBlocs en une table html
2030
2031 Chaque Bibloc est convertit en une ligne <tr></tr> d'une table html
2032 Si stream, on ecrit régulièrement dans fileBuffer la table courante et
2033 on la réinitialise ensuite sinon on crée une grosse chaine que l'on renvoie"""
2034 assert stream==False or (stream and fileBuffer is not None)
2035 res = [] ; i = 0
2036 for (B1,B2) in self.liste:
2037 res.append('<tr>')
2038
2039 if B1 is None: res.append('<td></td>')
2040 else:
2041 B1_type = B1[0]
2042 if B1_type == 'S': res.extend(['<td style="background-color: #FF0000">',self.__souligneTexte(B1),'</td>'])
2043 elif B1_type == 'R': res.extend(['<td style="background-color: #0000FF"> ',self.__souligneTexte(B1),'</td>'])
2044 elif B1_type == 'D': res.extend(['<td>',self.__souligneTexte(B1),'</td>'])
2045 else: res.extend(['<td>',self.__keepMEP(self.texte[B1[1]:B1[2]]),'</td>'])
2046
2047 if B2 is None: res.append('<td></td>')
2048 else:
2049 B2_type = B2[0]
2050 if B2_type == 'I': res.extend(['<td style="background-color: #00FF00">',self.__souligneTexte(B2),'</td>'])
2051 elif B2_type == 'R': res.extend(['<td style="background-color: #0000FF">',self.__souligneTexte(B2),'</td>'])
2052 elif B2_type == 'D': res.extend(['<td>',self.__souligneTexte(B2),'</td>'])
2053 else: res.extend(['<td>',self.__keepMEP(self.texte[B2[1]:B2[2]]),'</td>'])
2054 res.append('</tr>\n')
2055 if stream and i%50 == 0:
2056 fileBuffer.write(''.join(res))
2057 res = []
2058
2059 if stream:
2060 fileBuffer.write(''.join(res))
2061 res = []
2062 else:
2063 return ''.join(res)
2064
2065 - def __souligneTexte(self,bloc):
2066 """ Renvoie une chaine html avec le texte souligné aux caractères déplacés """
2067 if bloc[0] == 'D':
2068 return ('<span style="text-decoration: underline; font-weight: bold">'+
2069 self.__keepMEP(self.texte[bloc[1]:bloc[2]])+'</span>')
2070 res = ""
2071 deb = i = bloc[1]
2072 fin = bloc[2]
2073 lDep = bloc[3][:]
2074
2075 while i < fin:
2076
2077
2078 if len(lDep) > 0 and lDep[0][0] <= i:
2079 res += '<span style="text-decoration: underline; font-weight: bold">'+self.__keepMEP(self.texte[i:lDep[0][1]])+'</span>'
2080 i = lDep[0][1]
2081 lDep.pop(0)
2082 elif len(lDep) > 0 and lDep[0][0] > i:
2083 res += self.__keepMEP(self.texte[i:lDep[0][0]])
2084 i = lDep[0][0]
2085 else:
2086 assert len(lDep)==0
2087 res += self.__keepMEP(self.texte[i:fin])
2088 i = fin
2089 return res
2090
2092 """ Fonction chargée de conserver la mise en page du texte original
2093
2094 Remplace les retours à la ligne par des <br> et les espaces par des
2095
2096 Le remplacement des espaces par des nbsp est très utile pour visulaiser des
2097 alignements de code source mais plus discutable pour de la langue nat.
2098 De même mais de façon moins importante pour les br."""
2099 return texte
2100 res = ""
2101 for i in xrange(len(texte)):
2102 if texte[i] in '\r\n': res += '<br>'
2103
2104 else:
2105 try: res += '&' + htmlentitydefs.codepoint2name[ord(texte[i])] + ';'
2106 except KeyError: res += texte[i]
2107 return res
2108
2109
2111 """BiblocList avec type déplacement (D) autorisé """
2113 BiBlocList.__init__(self,resultat,planTravail,depOrdonnes)
2114 try:
2115 self.evaluation()
2116 except ZeroDivisionError:
2117 logging.debug("Erreur d'evaluation ZeroDivisionError")
2118 logging.debug('extractDeplacements()')
2119 self.extractDeplacements()
2120 try:
2121 self.evaluation()
2122 except ZeroDivisionError:
2123 logging.debug("Erreur d'evaluation ZeroDivisionError")
2124
2126 """ Extraction des déplacements
2127
2128 Teste les blocs insérés et supprimés.
2129 Si le rapport des déplacements à l'intérieur d'un bloc est supérieur au seuil
2130 Alors ce bloc est scindé en une liste de blocs (I ou S) et D
2131 Modifie directement self.liste
2132
2133 AssertionError: 270455 ('D', 270444, 270455, []) ('D', 270450, 270455, [])"""
2134 tool = utile.Utile()
2135 ratio_seuil_lissage = float(self.planTravail.getParam().getp3()) /100
2136
2137 i = len(self.liste) - 1
2138 while i >= 0:
2139 if i%1000 == 0: logging.debug("itérationD %d",i)
2140 (B1,B2) = self.liste[i]
2141 if (B1 is not None and B1[0] == 'S'):
2142 assert B2 is None
2143 supMoinsDep = tool.soustr_l_intervalles([[B1[1],B1[2]]], B1[3])
2144 ratio_lissage = float(tool.longueur(supMoinsDep))/(B1[2]-B1[1])
2145 if ratio_lissage <= ratio_seuil_lissage:
2146 self.liste[i:i+1] = self.__extractDepInsSup(supMoinsDep,B1[3],'S')
2147 elif (B2 is not None and B2[0] == 'I'):
2148 assert B1 is None
2149 insMoinsDep = tool.soustr_l_intervalles([[B2[1],B2[2]]], B2[3])
2150 ratio_lissage = float(tool.longueur(insMoinsDep))/(B2[2]-B2[1])
2151 if ratio_lissage <= ratio_seuil_lissage:
2152 self.liste[i:i+1] = self.__extractDepInsSup(insMoinsDep,B2[3],'I')
2153 i -= 1
2154
2155
2156
2158 """ Extraction des déplacements
2159
2160 Teste les blocs insérés et supprimés.
2161 Si le rapport des déplacements à l'intérieur d'un bloc est supérieur au seuil
2162 Alors ce bloc est scindé en une liste de blocs (I ou S) et D"""
2163 tool = utile.Utile()
2164 ratio_seuil_lissage = float(self.planTravail.getParam().getp3()) /100
2165 nouvelleListe = []
2166 for (B1,B2) in self.liste:
2167 if (B1 is not None and B1[0] == 'S'):
2168 assert B2 is None
2169 supMoinsDep = tool.soustr_l_intervalles([[B1[1],B1[2]]], B1[3])
2170 ratio_lissage = float(tool.longueur(supMoinsDep))/(B1[2]-B1[1])
2171 if ratio_lissage > ratio_seuil_lissage:
2172 nouvelleListe.append((B1,None))
2173 else:
2174 nouvelleListe.extend(self.__extractDepInsSup(supMoinsDep,B1[3],'S'))
2175 elif (B2 is not None and B2[0] == 'I'):
2176 assert B1 is None
2177 insMoinsDep = tool.soustr_l_intervalles([[B2[1],B2[2]]], B2[3])
2178 ratio_lissage = float(tool.longueur(insMoinsDep))/(B2[2]-B2[1])
2179 if ratio_lissage > ratio_seuil_lissage:
2180 nouvelleListe.append((None,B2))
2181 else:
2182 nouvelleListe.extend(self.__extractDepInsSup(insMoinsDep,B2[3],'I'))
2183 else:
2184 nouvelleListe.append((B1,B2))
2185 self.liste = nouvelleListe
2186 if __debug__:
2187 self._testOrdre()
2188
2190 """On scinde effectivement le blocs en une liste de blocs (S ou I) et D
2191
2192 lSupOrIns: liste de (I ou S)
2193 listeDep: liste de D
2194 SorI: traite-on des S ou des I ?
2195 pre: isinstance(lSupOrIns,list) and isinstance(listeDep,list)
2196 (SorI == 'S' or SorI == 'I') """
2197 nouvelleListe = []
2198 len_listeDep = len(listeDep)
2199 prevdeb = nbDep = 0
2200 while len(lSupOrIns) > 0 or len(listeDep) > 0:
2201
2202 if len(listeDep) == 0:
2203 for (deb,fin) in lSupOrIns:
2204 assert prevdeb <= deb
2205 prevdeb = deb
2206 if SorI == 'S': nouvelleListe.append((('S',deb,fin,[]),None))
2207 else: nouvelleListe.append((None,('I',deb,fin,[])))
2208 lSupOrIns = []
2209
2210 elif len(lSupOrIns) == 0:
2211 for (deb,fin) in listeDep:
2212 assert prevdeb <= deb
2213 prevdeb = deb
2214 if SorI == 'S': nouvelleListe.append((('D',deb,fin,[]),None))
2215 else: nouvelleListe.append((None,('D',deb,fin,[])))
2216 nbDep += 1
2217 listeDep = []
2218
2219 elif lSupOrIns[0][0] <= listeDep[0][0]:
2220 assert prevdeb <= lSupOrIns[0][0]
2221 prevdeb = lSupOrIns[0][0]
2222 if SorI == 'S': nouvelleListe.append((('S',lSupOrIns[0][0],lSupOrIns[0][1],[]),None))
2223 else: nouvelleListe.append((None,('I',lSupOrIns[0][0],lSupOrIns[0][1],[])))
2224
2225 lSupOrIns.pop(0)
2226 else:
2227 assert prevdeb <= listeDep[0][0]
2228 prevdeb = listeDep[0][0]
2229 if SorI == 'S': nouvelleListe.append((('D',listeDep[0][0],listeDep[0][1],[]),None))
2230 else: nouvelleListe.append((None,('D',listeDep[0][0],listeDep[0][1],[])))
2231 listeDep.pop(0)
2232 nbDep += 1
2233 assert len(listeDep) == len(lSupOrIns) == 0
2234 assert nbDep == len_listeDep
2235 return nouvelleListe
2236
2238 - def __init__(self, liste, planTravail, texte, lg_texte1):
2249
2251 """ a jeter """
2252 liste = self.liste
2253 lastFin1 = self.lgSource ; lastFin2 = len(self.texte)
2254 lastBC1 = lastBC2 = len(liste)-1
2255 for i in xrange(len(liste)-1,-1,-1):
2256 B1,B2 = liste[i]
2257
2258 if B2 is not None and B2[0] == 'D':
2259 accu = []
2260 while (i-1 >= 0 and liste[i-1][1] is not None and
2261 (liste[i-1][1][0] == 'D' or liste[i-1][1][0] == 'BC')):
2262 accu.append(B2)
2263 i -= 1
2264 B2 = liste[i][1]
2265 accu.append(B2)
2266 if i-1 < 0: start = self.lgSource
2267 else: start = liste[i-1][0][2]
2268 assert i <= lastBC2+1
2269 liste[i:lastBC2+1] = [(None,('I',start,lastFin2,[(B[1],B[2]) for B in accu]))]
2270 lastFin2 = start ; lastBC2 = i
2271 elif B1 is not None and B1[0] == 'D':
2272 accu = []
2273 while (i-1 >= 0 and liste[i-1][0] is not None and
2274 (liste[i-1][0][0] == 'D' or liste[i-1][1][0] == 'BC')):
2275 accu.append(B1)
2276 i -= 1
2277 B1 = liste[i][0]
2278 accu.append(B1)
2279 if i-1 < 0: start = 0
2280 else: start = liste[i-1][1][2]
2281 assert i <= lastBC1+1
2282 liste[i:lastBC1+1] = [(('S',start,lastFin1,[(B[1],B[2]) for B in accu]),None)]
2283 lastFin1 = start ; lastBC1 = i
2284 else:
2285 accu = [(B1,B2)]
2286 print B1,B2
2287 assert B1[0] == 'BC' and B2[0] == 'BC', str(B1)+str(B2)
2288 if liste[lastBC1][0][1] - B1[2] > 0:
2289 accu.append((('S',B1[2],liste[lastBC1][0][1],[]),None))
2290 if liste[lastBC2][1][1] - B2[2] > 0:
2291 accu.append((None,('I',B2[2],liste[lastBC2][1][1],[])))
2292 liste[i:i+1] = accu
2293 lastBC1 = lastBC2 = i
2294 lastFin1 = B1[1] ; lastFin2 = B2[1]
2295 i -= 1
2296 B1,B2 = liste[0]
2297 accu = []
2298 if B1 is not None and B1[1] != 0:
2299 accu.append(())
2300
2301 print liste
2302 self.liste = liste
2303