src/cm/activity.py
author Simon Descarpentries <sid@sopinspace.com>
Tue, 06 May 2014 13:52:01 +0200
changeset 651 9bbc657f6837
parent 606 52f3e090eed9
permissions -rw-r--r--
Replace DISABLE_TRACKING and TRACKING_HTML by a TRACKING_ID variable in configuration files

from cm.models import Activity, Text
from django.contrib.auth.models import User
from django.db.models import signals
from datetime import datetime, timedelta
from time import mktime
import django.dispatch
import logging
from cm.cm_settings import STORE_ACTIVITY_IP

def register_activity(request, type, text=None, comment=None, user=None, text_version=None):
    signal_activity.send(sender=text, request=request, type=type, comment=comment, user=user, text_version=text_version)
    
# activity signal

signal_activity = django.dispatch.Signal(providing_args=["request", "type", "comment"])

def _save_activity(sender, **kwargs):
    request = kwargs['request']
    type = kwargs['type']
    comment = kwargs['comment']
    user = kwargs['user']
    
    text = sender
    text_version = kwargs.get('text_version', None)
    if not text_version and text:
        text_version = text.last_text_version
        
    if request.user.is_anonymous():
        originator_user = None
    else:
        originator_user = request.user
    
    if STORE_ACTIVITY_IP:
        ip = request.META.get('REMOTE_ADDR', '0.0.0.0')
    else:
        ip = None
    
    Activity.objects.create(text=text, user=user, text_version=text_version, comment=comment, type=type, ip=ip, originator_user=originator_user)
    
def connect_all():
    signal_activity.connect(_save_activity)

connect_all()

# activity processing

def seconds(t_delta):
    return abs(t_delta.seconds + t_delta.days * 86400)

VISIT_DURATION = timedelta(seconds=30 * 60) # 30 minutes

from cm.utils.cache import memoize, dj_memoize

@dj_memoize
def get_activity(text='all', user='all', reference_date=None, nb_slots=31, slot_timedelta=timedelta(days=1), action="all", kind=''):
    """
    text : text: specific text
           'all': all texts
    user : user: specific user
           None: anonymous users
           'all': all users
    """
    # calc activities used    
    if not reference_date:
        reference_date = datetime.now()
    from_date = reference_date - slot_timedelta * nb_slots
    activities = Activity.objects.filter(created__gt=from_date)
    if action != 'all':
        activities = activities.filter(type=action)
    if text != 'all':
        activities = activities.filter(text=text)
    if user != 'all':
        activities = activities.filter(originator_user=user)
    activities = activities.order_by('created').only('created', 'originator_user', 'text')
    #print 'got %d activities' % len(activities), [a.created for a in activities]
    
    if kind == 'raw':
        visits = activities
    else:
        # calc visits
        visits = []
        if activities:
            for i in range(len(activities)):
                activity = activities[i]
                found = False
                for j in range(i - 1, -1, -1):
                    prev_act = activities[j]                
                    if activity.created > prev_act.created + VISIT_DURATION: # out of session bounds: add act
                        visits.append(activity)
                        found = True
                        break
                    else:
                        if not activity.is_same_user(prev_act): # another user: just ignore prev_act
                            continue
                        else: # in session: do not count act
                            found = True
                            break
                if not found:                    
                    visits.append(activity)
        #print 'got %d visits' % len(visits), [(v.created, v.user) for v in visits]
    
    # hist by slot_timedelta
    slots = [seconds(from_date - v.created) // seconds(slot_timedelta) for v in visits]
    
    # TODO: could be more efficient...
    res = [slots.count(index) for index in range(nb_slots)]
    return res