Merge with 4e8c6e580e78179f27cd14d17b0fccf0dab24d5f
authorverrierj
Fri, 27 Jan 2012 14:56:11 +0100
changeset 471 c54a7864a22f
parent 470 b1dd78b59750 (diff)
parent 466 4e8c6e580e78 (current diff)
child 473 a400c401f78b
Merge with 4e8c6e580e78179f27cd14d17b0fccf0dab24d5f
src/ldt/ldt/ldt_utils/templates/front/front_all_contents.html
src/ldt/ldt/ldt_utils/templates/front/front_home.html
--- a/src/ldt/ldt/ldt_utils/admin.py	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/admin.py	Fri Jan 27 14:56:11 2012 +0100
@@ -5,17 +5,13 @@
 from ldt.ldt_utils.contentindexer import ContentIndexer, ProjectIndexer
 from ldt.ldt_utils.fileimport import FileImport, FileImportError
 from ldt.ldt_utils.forms import LdtImportForm, ReindexForm, StatAnnotationForm
-from ldt.ldt_utils.models import Content, Project, Media, Author, AnnotationStat
+from ldt.ldt_utils.models import Content, Project, Media, Author
 import ldt.indexation
 from guardian.admin import GuardedModelAdmin
 
 
-class StatInlineAdmin(admin.TabularInline):
-    model = AnnotationStat
-    extra = 1
-
 class ProjectAdmin(GuardedModelAdmin):
-    inlines = [StatInlineAdmin, ]
+    pass
 
 class AuthorAdmin(GuardedModelAdmin):
     pass
--- a/src/ldt/ldt/ldt_utils/contentindexer.py	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/contentindexer.py	Fri Jan 27 14:56:11 2012 +0100
@@ -3,6 +3,7 @@
 from django.dispatch import receiver
 from ldt.ldt_utils.models import Segment, Content, Project
 from ldt.ldt_utils.utils import reduce_text_node
+from ldt.ldt_utils.stat import update_stat_project
 import ldt.indexation
 import lucene
 import lxml.etree
@@ -82,6 +83,7 @@
 
                 title = reduce_text_node(elementNode, "title/text()")                
                 abstract = reduce_text_node(elementNode, "abstract/text()")
+                polemics = elementNode.xpath('meta/polemics/polemic/text()')
                 
                 author = elementNode.get("author", "")
                 start_ts = int(float(elementNode.get("begin", "-1")))
@@ -119,6 +121,7 @@
                               date=date_str,
                               project_obj=project,
                               project_id=ldt_id)
+                seg.polemics = seg.get_polemic(polemics)
                 seg.save()
                 self.writer.addDocument(doc)
 
@@ -192,8 +195,10 @@
             if instance.state != 2:
                 writer.deleteDocuments(lucene.Term("project_id", instance.ldt_id))
                 Segment.objects.filter(project_obj__ldt_id=instance.ldt_id).delete() #@UndefinedVariable
+                update_stat_project(instance)
             else:
                 projectIndexer = ProjectIndexer([instance], writer)
                 projectIndexer.index_all()
+                update_stat_project(instance)
         finally:
             writer.close()
--- a/src/ldt/ldt/ldt_utils/migrations/0011_gen_stat_annotation.py	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/migrations/0011_gen_stat_annotation.py	Fri Jan 27 14:56:11 2012 +0100
@@ -4,7 +4,6 @@
 from south.db import db
 from south.v2 import DataMigration
 from django.db import models
-from ldt.ldt_utils.stat import update_stat_project, update_stat_content
 
 
 class Migration(DataMigration):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/migrations/0014_auto__del_annotationstat__chg_field_content_last_annotated.py	Fri Jan 27 14:56:11 2012 +0100
@@ -0,0 +1,152 @@
+#@PydevCodeAnalysisIgnore
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        db.delete_column('ldt_utils_annotationstat', 'stat')
+        db.delete_column('ldt_utils_annotationstat', 'nb_annotation')
+        db.rename_table('ldt_utils_annotationstat', 'ldt_utils_project_contents')
+        
+        # Adding field 'Segment.polemics'
+        db.add_column('ldt_utils_segment', 'polemics', self.gf('django.db.models.fields.IntegerField')(default=0, null=True, blank=True), keep_default=False)
+
+
+        
+    def backwards(self, orm):
+        
+        db.rename_table('ldt_utils_project_contents', 'ldt_utils_annotationstat')
+        db.add_column('ldt_utils_annotationstat', 'stat', self.gf('django.db.models.fields.CommaSeparatedIntegerField')(max_length=1024, null=True, blank=True), keep_default=False)
+        db.add_column('ldt_utils_annotationstat', 'nb_annotation', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
+        
+        # Deleting field 'Segment.polemics'
+        db.delete_column('ldt_utils_segment', 'polemics')
+       
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'ldt_utils.author': {
+            'Meta': {'object_name': 'Author'},
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+            'firstname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '512', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lastname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.content': {
+            'Meta': {'ordering': "['title']", 'object_name': 'Content'},
+            'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Author']", 'symmetrical': 'False', 'blank': 'True'}),
+            'content_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'front_project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/contents/content_default_icon.png'", 'max_length': '200'}),
+            'iri_id': ('django.db.models.fields.CharField', [], {'default': "u'eef4f4d1-482b-11e1-b09b-001485352c9a'", 'unique': 'True', 'max_length': '1024'}),
+            'iriurl': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'last_annotated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'blank': 'True'}),
+            'media_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Media']", 'null': 'True', 'blank': 'True'}),
+            'nb_annotation': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'stat_annotation': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.media': {
+            'Meta': {'object_name': 'Media'},
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'external_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_permalink': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_publication_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_src_url': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'media_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'mimetype_field': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'src': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'videopath': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.project': {
+            'Meta': {'ordering': "['title']", 'object_name': 'Project'},
+            'changed_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}),
+            'contents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Content']", 'symmetrical': 'False'}),
+            'created_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/projects/project_default_icon.png'", 'max_length': '200'}),
+            'ldt': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'ldt_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}),
+            'modification_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'state': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
+        },
+        'ldt_utils.segment': {
+            'Meta': {'unique_together': "(('project_id', 'iri_id', 'ensemble_id', 'cutting_id', 'element_id'),)", 'object_name': 'Segment'},
+            'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'author': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Content']"}),
+            'cutting_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'date': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'element_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'ensemble_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'iri_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'polemics': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}),
+            'project_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'project_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']", 'null': 'True'}),
+            'start_ts': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['ldt_utils']
--- a/src/ldt/ldt/ldt_utils/models.py	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/models.py	Fri Jan 27 14:56:11 2012 +0100
@@ -141,6 +141,13 @@
         permissions = (
                        ('view_content', 'Can view content'),
                        )
+        
+    def __init__(self, *args, **kwargs):
+        
+        super(Content, self).__init__(*args, **kwargs)
+        
+        if not hasattr(Content, 'pol_positive'):
+            self.__add_polemic_attributes()
     
     def natural_key(self):
         return self.iri_id
@@ -376,6 +383,65 @@
     def get_tags(self):
         return Tag.objects.get_for_object(self)
     
+    
+    pol_indices = {
+               'annotation_volume_begin' : 0,
+               'annotation_volume_end' : settings.DIVISIONS_FOR_STAT_ANNOTATION,
+               'pol_positive' : settings.DIVISIONS_FOR_STAT_ANNOTATION,
+               'pol_negative' : settings.DIVISIONS_FOR_STAT_ANNOTATION + 1,
+               'pol_reference' : settings.DIVISIONS_FOR_STAT_ANNOTATION + 2,
+               'pol_question' : settings.DIVISIONS_FOR_STAT_ANNOTATION + 3,               
+               }    
+
+    # add polemic attributes and polemic attribute rates to class Content
+    def __add_polemic_attributes(self):
+        for element in self.pol_indices.keys():
+            if element.startswith('pol_'):                    
+                Content.add_to_class(element, property(self.__make_getter(element), self.__make_setter(element)))
+                Content.add_to_class("%s_rate" % element, property(self.__make_rate(element)))  
+
+    def __make_getter(self, i):
+        def inner_getter(self):
+            l = self.__str2list(self.stat_annotation)
+            return l[Content.pol_indices[i]]
+        return inner_getter
+    
+    def __make_setter(self, i):
+        def inner_setter(self, value):
+            l = self.__str2list(self.stat_annotation)
+            l[Content.pol_indices[i]] = value
+            self.stat_annotation = self.__list2str(l)
+        return inner_setter
+    
+    def __make_rate(self, i):
+        def inner_rate(self):
+            if self.nb_annotation <= 0:
+                return 0
+            return int(getattr(self, i) / float(self.nb_annotation) * 100 )
+        return inner_rate   
+    
+    def __list2str(self, l):
+        return ("%s" % l)[1:-1].replace(' ','')
+        
+    def __str2list(self, s):
+        return [int(x) for x in s.split(',')] 
+        
+    def annotation_volume(): #@NoSelf
+        
+        def fget(self):
+            l = self.__str2list(self.stat_annotation)
+            return l[Content.pol_indices['annotation_volume_begin']:Content.pol_indices['annotation_volume_end']]
+        
+        def fset(self, value): # value is a list
+            l = self.__str2list(self.stat_annotation)
+            l[Content.pol_indices['annotation_volume_begin']:Content.pol_indices['annotation_volume_end']] = value
+            self.stat_annotation = self.__list2str(l)
+            
+        return locals()
+    
+    annotation_volume = property(**annotation_volume())    
+    
+ 
 
 
     
@@ -390,7 +456,7 @@
     ldt_id = models.CharField(max_length=1024, unique=True)
     ldt = models.TextField(null=True)
     title = models.CharField(max_length=1024)
-    contents = models.ManyToManyField(Content, through='AnnotationStat')
+    contents = models.ManyToManyField(Content)
     creation_date = models.DateTimeField(auto_now_add=True)
     modification_date = models.DateTimeField(auto_now=True)
     created_by = models.CharField(_("created by"), max_length=70)
@@ -521,25 +587,8 @@
             return True
         else:
             return False
-        
-    def add_contents(self, contents):
-        for content in contents:
-            contribution = AnnotationStat.objects.create(project=self, content=content)
-            contribution.save() 
-            
-    def remove_contents(self, contents):
-        AnnotationStat.objects.filter(project=self, content__in=contents).delete()
-         
-        
-class AnnotationStat(SafeModel):
-    project = models.ForeignKey(Project)
-    content = models.ForeignKey(Content)
-    stat = models.CommaSeparatedIntegerField(max_length=1024, null=True, blank=True, verbose_name=_("content.stat_annotation"))
-    nb_annotation = models.IntegerField(default=0, verbose_name=_("content.nb_annotation"))
     
-    def __unicode__(self):
-        return "%s::%s" % (self.project.ldt_id, self.content.iri_id)
-
+    
 class Segment(SafeModel):
     
     project_obj = models.ForeignKey(Project, null=True)
@@ -556,6 +605,33 @@
     author = models.CharField(max_length=1024, unique=False, null=True, blank=True)
     date = models.CharField(max_length=128, unique=False, null=True, blank=True)
     abstract = models.TextField(null=True, blank=True)
+    polemics = models.IntegerField(null=True, blank=True, default=0)
+    
+    
+    # Mask is 0000, representing OK|KO|Q|REF
+    mask = {
+            'OK': set([8,9,10,11,12,13,14,15]),
+            'KO': set([4,5,6,7,12,13,14,15]),
+            'Q': set([2,3,6,7,10,11,14,15]),
+            'REF': set([1,3,5,7,9,11,13,15]),
+            }
+    
+    def is_polemic(self, polemic_keyword): # OK, KO, Q, REF 
+        if self.polemics in self.mask[polemic_keyword]:
+            return True
+        return False
+    
+    def get_polemic(self, polemic_keywords):
+        value = set(range(16))
+        
+        for keyword in self.mask.keys():
+            if keyword in polemic_keywords:
+                value = value.intersection(self.mask[keyword])
+            else:
+                value.difference_update(self.mask[keyword])
+            
+        return value.pop()
+        
     
     def __unicode__(self):
         return "/".join((unicode(self.project_id), unicode(self.iri_id), unicode(self.ensemble_id), unicode(self.cutting_id), unicode(self.element_id)))
@@ -567,3 +643,4 @@
                        )
 
 
+
--- a/src/ldt/ldt/ldt_utils/segmentserializer.py	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/segmentserializer.py	Fri Jan 27 14:56:11 2012 +0100
@@ -1,5 +1,4 @@
 from django.conf import settings
-from django.utils.datastructures import SortedDict
 from ldt.ldt_utils.models import Project
 import lxml.etree
 import uuid
--- a/src/ldt/ldt/ldt_utils/stat.py	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/stat.py	Fri Jan 27 14:56:11 2012 +0100
@@ -1,68 +1,81 @@
 from django.conf import settings
-from ldt.ldt_utils.models import AnnotationStat, Project
-from django.db.models.signals import pre_delete
-import lxml.etree
+from ldt.ldt_utils.models import Segment
 import datetime
 
-
-def update_stat_project(project, contents=None, doc=None, update_contents=[]):
-
-    if not contents:
-        contents = project.contents.all()
-     
-    if not doc:
-        doc = lxml.etree.fromstring(project.ldt)
+def update_stat_content(content):
+    
+    nb_division = settings.DIVISIONS_FOR_STAT_ANNOTATION
+    
+    segments = Segment.objects.filter(content=content)
+    buckets = [0] * nb_division 
+    
+    size_division = content.duration / nb_division
+    limits = [x * size_division for x in range(nb_division+1)]
+    nb_annotation = len(segments)
+    
+    polemic_positive = 0
+    polemic_negative = 0
 
-    number_division = settings.DIVISIONS_FOR_STAT_ANNOTATION
-    contributions = list(AnnotationStat.objects.filter(project=project))    
+    for segment in segments:
+        
+        begin = segment.start_ts
+        end = segment.start_ts + segment.duration
+        
+        if segment.is_polemic('OK'):
+            polemic_positive += 1
+        if segment.is_polemic('KO'):
+            polemic_negative += 1
+        
+        buckets = find_buckets(buckets, limits, begin, end)
+        
+    content.annotation_volume = buckets
+    content.nb_annotation = nb_annotation
+    content.polemic_positive = polemic_positive
+    content.polemic_negative = polemic_negative
     
-    for content_node in doc.xpath('/iri/annotations/content'):
-        content_name = content_node.get('id')
-        content = filter_list(contents, 'iri_id', content_name)
-
-        # if the content referenced in the xml belongs to the
-        # fields contents of the project
-        if len(content) != 0:
-            content = content[0]
-            contribution_to_content = filter_list(contributions, 'content', content)[0]
+    content.save()     
+ 
+   
+def update_stat_project(project, contents_only=[]):
+        if project.state != 2:
+            return None
+    
+        if contents_only:
+            contents = contents_only
+        else:
+            contents = project.contents.all()
             
-            size_division = content.duration / number_division
-            limits = [x * size_division for x in range(number_division+1)]
-            buckets = [0] * number_division
-            nb_annotation = 0
-            
+        for c in contents:
+            update_stat_content(c)
             
-            for ann in content_node.xpath('ensemble/decoupage/elements/element'):
-                begin = int(ann.get('begin'))
-                end = int(ann.get('dur')) + begin
-                
-                text = ann.xpath('abstract')[0].text
-                if is_polemic(text):
-                    pass
-                        
-                buckets = find_buckets(buckets, limits, begin, end)
-                nb_annotation += 1        
-           
-            buckets = get_string_from_buckets(buckets)
-             
-            if contribution_to_content.stat != buckets or contribution_to_content.nb_annotation != nb_annotation:
-                contribution_to_content.stat = buckets
-                contribution_to_content.nb_annotation = nb_annotation
-                contribution_to_content.save()
-                update_stat_content(content)
+        return True
+    
+
+def add_annotation_to_stat(content, begin, end):
     
-    for content in update_contents:
-        update_stat_content(content)
-        
-        
+    if not content.nb_annotation or not content.stat_annotation:
+        content.nb_annotation = 1
+        content.stat_annotation = get_empty_stat_vector()
+    
+    buckets = find_buckets(content.stat_annotation, begin, end)
+    content.annotation_volume = buckets
+    content.last_annotated = datetime.datetime.now()
+    
+    content.save()        
+    
+
 def get_string_from_buckets(buckets):
     s = "%s" % buckets
     s = s[1:-1].replace(' ', '')
     return s
 
+
 def get_buckets_from_string(string):
     return [int(x) for x in string.split(',')]
 
+def get_empty_stat_vector():
+    return [0] * (settings.DIVISIONS_FOR_STAT_ANNOTATION + 4) # + 4 for polemic syntax
+
 
 def find_buckets(buckets, limits, begin, end):
     
@@ -85,89 +98,3 @@
             
     return buckets
 
-def is_polemic(text):
-    if text:
-        polemic_tags = ['++', '--', '==', '??']
-        for tag in polemic_tags:
-            if tag in text:
-                return True
-    return False
-    
-    
-    
-def filter_list(list, criteria, value):
-    new_list = []
-    for l in list:
-        if getattr(l, criteria) == value:
-            new_list.append(l)
-    
-    return new_list
-       
-        
-def delete_stat_project(sender, instance, **kwargs):
-    
-    contents = list(instance.contents.all())
-    contributions = AnnotationStat.objects.filter(project=instance)
-    
-    for c in contributions:
-        result = [x for x in contents if x.id == c.content.id ]
-        if result:
-            content = result[0]
-            
-            if c.nb_annotation:        
-                content.nb_annotation -= c.nb_annotation
-            
-            if c.stat:
-                content_stat = get_buckets_from_string(content.stat_annotation)
-                proj_stat = get_buckets_from_string(c.stat)
-                content.stat_annotation = get_string_from_buckets([pair[0] - pair[1] for pair in zip(content_stat, proj_stat)])
-            
-            content.save()        
-
-pre_delete.connect(delete_stat_project, sender=Project)    
-        
-            
-def update_stat_content(content):
-    all_contributions = AnnotationStat.objects.filter(content=content)
-    content_stat = [0] * settings.DIVISIONS_FOR_STAT_ANNOTATION
-    nb_annotation = 0
-    
-    for project in all_contributions:
-        if project.stat and project.stat != '':
-            project_stat = get_buckets_from_string(project.stat)
-            content_stat = [sum(pair) for pair in zip(content_stat, project_stat)]
-        nb_annotation += project.nb_annotation  
-    
-    content.nb_annotation = nb_annotation
-    content.stat_annotation = get_string_from_buckets(content_stat)
-    content.last_annotated = datetime.datetime.now()
-    content.save()    
-
-
-def add_annotation_to_stat(content, project, begin, end):
-    contribution_project = AnnotationStat.objects.get(project=project, content=content)
-    
-    if not contribution_project.nb_annotation:
-        contribution_project.nb_annotation = 1
-    else:
-        contribution_project.nb_annotation += 1
-    content.nb_annotation += 1
-        
-    if contribution_project.stat:
-        
-        number_division = settings.DIVISIONS_FOR_STAT_ANNOTATION
-        size_division = content.duration / number_division
-        
-        limits = [x * size_division for x in range(number_division+1)]
-        buckets = [0] * number_division        
-        buckets = find_buckets(buckets, limits, begin, end)
-        
-        content_stat = get_buckets_from_string(content.stat_annotation)
-        content.stat_annotation = get_string_from_buckets([pair[0] + pair[1] for pair in zip(content_stat, buckets)])
-        contribution_project.stat = get_string_from_buckets(buckets)  
-
-    content.last_annotated = datetime.datetime.now()
-    content.save()
-    contribution_project.save()
-    
-
--- a/src/ldt/ldt/ldt_utils/templates/front/front_all_contents.html	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_all_contents.html	Fri Jan 27 14:56:11 2012 +0100
@@ -27,15 +27,15 @@
         {% else %}<h2>{% trans 'All medias' %}</h2>{% endif %}
     </li>
     {% for content in content_list %}
-    <li class="li_media">
+    <li class="li_media">        
         <div class="img_and_overlay">
             <a href="{% url ldt.ldt_utils.views.front.annot_content content.iri_id %}">
                 {% thumbnail content.image "294x165" format="PNG" crop="center" as im %}<img src="{{ im.url }}" class="img_media" width="{{ im.width }}" height="{{ im.height }}" alt="{% trans 'open this media' %}" title="{% trans 'open this media' %}">{% endthumbnail %}
             </a>
             <div class="overlay">
                 <ul class="polemics">
-                    <li class="pol-negative" style="width:0%">0%</li>
-                    <li class="pol-positive" style="width:0%">0%</li>
+                    <li class="pol-negative" style="width:{{content.pol_positive_rate }}%">{{content.pol_positive_rate }}%</li>
+                    <li class="pol-positive" style="width:{{content.pol_negative_rate}}%">{{content.pol_negative_rate}}%</li>
                     <li class="pol-reference" style="width:0%">0%</li>
                     <li class="pol-question" style="width:0%">0%</li>
                 </ul>
--- a/src/ldt/ldt/ldt_utils/templates/front/front_home.html	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_home.html	Fri Jan 27 14:56:11 2012 +0100
@@ -39,8 +39,8 @@
             </a>
             <div class="overlay">
                 <ul class="polemics">
-                    <li class="pol-negative" style="width:0%">0%</li>
-                    <li class="pol-positive" style="width:0%">0%</li>
+                    <li class="pol-negative" style="width:{{content.pol_negative_rate}}%">{{content.pol_negative_rate}}%</li>
+                    <li class="pol-positive" style="width:{{content.pol_positive_rate}}%">{{content.pol_positive_rate}}%</li>
                     <li class="pol-reference" style="width:0%">0%</li>
                     <li class="pol-question" style="width:0%">0%</li>
                 </ul>
@@ -71,8 +71,8 @@
             {% thumbnail content.image "134x75" format="PNG" crop="center" as im %}<img src="{{ im.url }}" class="img_media" width="{{ im.width }}" height="{{ im.height }}" alt="{% trans 'open this media' %}" title="{% trans 'open this media' %}">{% endthumbnail %}</a>
             <div class="overlay">
                 <ul class="polemics">
-                    <li class="pol-negative" style="width:0%">0%</li>
-                    <li class="pol-positive" style="width:0%">0%</li>
+                    <li class="pol-negative" style="width:{{content.pol_negative_rate}}%">{{content.pol_negative_rate}}%</li>
+                    <li class="pol-positive" style="width:{{content.pol_positive_rate}}%">{{content.pol_positive_rate}}%</li>
                     <li class="pol-reference" style="width:0%">0%</li>
                     <li class="pol-question" style="width:0%">0%</li>
                 </ul>
--- a/src/ldt/ldt/ldt_utils/templates/front/front_search_results.html	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_search_results.html	Fri Jan 27 14:56:11 2012 +0100
@@ -30,7 +30,7 @@
                     "duration" : {{segment.duration}},
                 },{% endfor %}
             ],
-            "stats" : [{{ res.content.stat_annotation }}],
+            "stats" : {{ res.content.annotation_volume }},
         },{% endfor %}
     ];
     
--- a/src/ldt/ldt/ldt_utils/views/lignesdetemps.py	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/lignesdetemps.py	Fri Jan 27 14:56:11 2012 +0100
@@ -4,7 +4,7 @@
 from django.http import HttpResponse, HttpResponseRedirect
 from django.shortcuts import render_to_response, get_object_or_404
 from django.template import RequestContext
-from ldt.ldt_utils.models import Content, Project, AnnotationStat
+from ldt.ldt_utils.models import Content, Project
 from ldt.ldt_utils.utils import LdtUtils, LdtSearch, clean_description
 from ldt.security.utils import set_forbidden_stream
 from ldt.ldt_utils.stat import update_stat_project
@@ -285,29 +285,23 @@
             new_contents.append(id)
     
         check_icon_project = False
-        contents_remove = []
         
         #find contents to remove
         for c in ldtproject.contents.all():
             if not c.iri_id in new_contents:
-                contents_remove.append(c)
+                ldtproject.contents.remove(c)
                 if ldtproject.image == c.image:
                     check_icon_project = True
         
-        #remove contents
-        AnnotationStat.objects.filter(content__in=contents_remove, project=ldtproject).delete()
-                
         #add new contents
         contents_id = [c.iri_id for c in ldtproject.contents.all()]
         
         for c in new_contents:
             if c not in contents_id:
                 content = Content.objects.get(iri_id=c)
-                rel = AnnotationStat(project=ldtproject, content=content, stat='')
-                rel.save()
+                ldtproject.contents.add(content)
          
-        #update stats for all contents in this project and contents removed     
-        update_stat_project(ldtproject, ldtproject.contents.all(), update_contents=contents_remove)
+        update_stat_project(ldtproject)
         
         #remove html tags added by flash
         description = ldtproject.get_description(doc)
--- a/src/ldt/ldt/ldt_utils/views/workspace.py	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/workspace.py	Fri Jan 27 14:56:11 2012 +0100
@@ -166,7 +166,8 @@
             return render_to_response('ldt/ldt_utils/init_ldt_full.html', {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': url}, context_instance=RequestContext(request))
         else:
             results = get_results_with_context(field, search) 
-                
+            
+            Segment.safe_objects.check_perm = False # no permission policy for segments
             all_segments = Segment.safe_objects.filter(element_id__in=[e['element_id'] for e in results])
             all_projects = Project.safe_objects.filter(ldt_id__in=[e['project_id'] for e in results], state=2)
             all_contents = Content.safe_objects.filter(iri_id__in=[e['iri_id'] for e in results])
--- a/src/ldt/ldt/management/commands/statannotation.py	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/management/commands/statannotation.py	Fri Jan 27 14:56:11 2012 +0100
@@ -1,23 +1,23 @@
 from django.core.management.base import BaseCommand
-from ldt.ldt_utils.models import Content, Project
-from ldt.ldt_utils.stat import update_stat_content, update_stat_project
+from ldt.ldt_utils.models import Content
+from ldt.ldt_utils.stat import update_stat_content, get_empty_stat_vector
 
 class Command(BaseCommand):
-    help = 'Computes annotation for all contents and all projects'
+    help = 'Computes annotation for all contents'
     
     
     def handle(self, *args, **options):             
        
-        for proj in Project.objects.all():
-            print "Stat for project %s" % proj
-            update_stat_project(proj)
-        
-        # Sets fields nb_annotation and stat_annotation to 0 and 0,0,...,0
-        # for contents that do not have annotations
-        for content in Content.objects.all():
-            if not content.stat_annotation:
-                print "Stat for content %s" % content
-                update_stat_content(content)
-                  
+        empty_stat_vector = get_empty_stat_vector()
+        size_stat = len(empty_stat_vector)
+       
+        for c in Content.objects.all():
+            if not c.stat_annotation or len( c.stat_annotation.split(',')) != size_stat:
+                c.stat_annotation = c.list2str(empty_stat_vector)
+                c.save()
+            
+            update_stat_content(c)
+            
+        print "Done"                  
         return None
     
\ No newline at end of file
--- a/src/ldt/ldt/templatetags/front_tags.py	Fri Jan 27 14:37:10 2012 +0100
+++ b/src/ldt/ldt/templatetags/front_tags.py	Fri Jan 27 14:56:11 2012 +0100
@@ -48,3 +48,7 @@
 @register.filter
 def get_range(value):
     return range(value)
+
+@register.filter
+def list2str(value):
+    return ("%s"%value)[1:-1]