[stats_cableurs] on affiche les stats sur les machines, par mois

Ignore-this: 3e3d76242fcd7250d97409abb5b53fdb

darcs-hash:20090328124206-bd074-d5a2a44d0daf538ece093e91ce6deb5407128e24.gz
This commit is contained in:
Antoine Durand-Gasselin 2009-03-28 13:42:06 +01:00
parent 4a03074f05
commit f1cb76f449

View file

@ -1,8 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
# -*- mode: python; coding: utf-8 -*- # -*- mode: python; coding: utf-8 -*-
# #
# $Id: stats_cableurs.py,v 1.2 2007-09-29 17:50:09 dimino Exp $
#
# stats_cableurs.py # stats_cableurs.py
# ----------------- # -----------------
# #
@ -25,228 +23,306 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. # Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
import sys, re import sys, re, datetime, time
sys.path.append("/usr/scripts/gestion/") sys.path.append("/usr/scripts/gestion/")
from ldap_crans import crans_ldap from ldap_crans import CransLdap
from config import ann_scol from affich_tools import cprint
from affich_tools import cprint, anim
import time
db = crans_ldap() db = CransLdap()
date_debut_ann_scol = time.mktime((ann_scol, 8, 1, 0, 0, 0, 0, 0, 0))
paiement_ann_scol = "paiement+%d" % ann_scol __DAYS_IN_PREVIOUS_MONTH = [datetime.timedelta(days) for days in
[ 31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 ] ]
def parse_ligne_histo(ligne):
u"""Parse une ligne d'historique et renvoie (['dd', 'mm', 'yyyy'],
['date', 'heure', 'who', 'what'])"""
champ = ligne.replace(',', '').replace(': ', '').split(' ')
sdate = champ[0].split('/')
date = datetime.date(int(sdate[2]), int(sdate[1]), int(sdate[0]))
return date, champ
def parse_historique(truc):
u"""Parse l'historique"""
return [ parse_ligne_histo(ligne) for ligne in truc.historique() ]
def dec_date(date):
u"""retranche un mois à la date."""
return (date - __DAYS_IN_PREVIOUS_MONTH[date.month -1])
class ActionsCableurs:
u"""Cette classe s'occupe de recenser l'activité des différents
câbleurs."""
class StatsCableursBase:
u"""Classe prototype pour afficher des stats de câbleurs."""
colonnes = [('score', u'Son score')]
nbmois = 4
stats = {} stats = {}
sablier = None
def __init__(self, mois): def __init__(self, mois = -4):
self.sablier = anim(u"Récupération de la liste des câbleurs") if mois > 0:
ldap_cableurs = db.search("droits=cableur")['adherent'] # si on demande depuis 09 (septembre) , on remonte
for i in ldap_cableurs: # jusqu'à septembre
self.stats[i.nom()] = [] self.nbmois = (datetime.date.today().month + 12 - mois) % 12
self.sablier.reinit()
cprint('OK', 'vert')
self.get_stats(mois)
self.print_results()
def ajoute_actions(self, mois, machine):
u"""Ajoute dans les stats la liste des actions effectués par
chacuns des câbleurs sur la machine pendant les mois."""
for hist in machine.historique():
# On decoupe pour avoir un truc utilisable
champ = hist.replace(',', '').replace(': ', '').split(' ')
date = champ[0].split('/')
# On inspecte la date
if (int (date[1]), int(date[2])) in mois:
if self.stats.has_key(champ[2]):
self.stats[champ[2]].append(champ[3])
else: else:
self.stats[champ[2]] = [champ[3]] # si on demande les stats sur 4 mois, on remonte sur 4
# mois
self.nbmois = - mois
def get_stats(self, mois): # On récupère les statistiques
u"""Récupère les statistiques des différents câbleurs sur les self.get_stats()
différentes machines"""
self.sablier = anim(u"Récupération de la liste des machines") # On les affiche
all_machines = db.search('host=*') self.print_stats()
self.sablier.cycle()
machines = all_machines['machineFixe'] + all_machines['machineWifi']
self.sablier.reinit()
cprint('OK', 'vert')
self.sablier = anim(u"Récupération des actions sur les machines", iter = len (machines))
for becane in machines:
self.ajoute_actions(mois, becane)
self.sablier.cycle()
self.sablier.reinit()
cprint('OK', 'vert')
def print_results(self, nombre= 0): def get_stats(self):
u"""Affiche les statistiques d'activité des différents câbleurs""" u"""Génération dummy de statistiques"""
self.stats = {}
def print_stats(self):
u"""Affiche pour chaque cableur les valeurs de ses différentes colonnes
définies dans self.colonnes."""
stats = self.stats
cableurs = stats.keys()
### Si quelqu'un trouve une manière plus élégante de faire…
try:
cableurs.sort(lambda x, y : cmp(stats[x]['score'], stats[y]['score']), reverse=True)
except TypeError:
cableurs.sort(lambda x, y : cmp(stats[x][0], stats[y][0]), reverse=True)
cableurs = self.stats.keys()
cableurs.sort(lambda x, y : cmp(len (self.stats[x]), len (self.stats[y])), reverse=True)
long_max = reduce(lambda m, c : max(m, len(c)), cableurs, len('cableur')) long_max = reduce(lambda m, c : max(m, len(c)), cableurs, len('cableur'))
colonnes = [('actions', u'Actions'),
('ins', u'Inscription'),
('mac', u'Change MAC'),
('host', u'Change DNS'),
('ip', u'Change IP')]
# Titres des colonnes # Titres des colonnes
ligne = "%-*s" % (long_max, u'Câbleur') ligne = "%-*s" % (long_max, u'Câbleur')
for typ, nom in colonnes: for typ, nom in self.colonnes:
ligne += " | %s" % nom ligne += " | %s" % nom
cprint(ligne) cprint(ligne)
# Ligne pour délimiter # Ligne pour délimiter
ligne = ''.center(long_max, '-') ligne = ''.center(long_max, '-')
for typ, nom in colonnes: for typ, nom in self.colonnes:
ligne += "-+-%s" % ''.center(len(nom), '-') ligne += "-+-%s" % ''.center(len(nom), '-')
cprint(ligne) cprint(ligne)
# Statiqtiques par câbleur # Statiqtiques par câbleur
for cableur in cableurs: for cableur in cableurs:
acts = self.stats[cableur] acts = stats[cableur]
score_cableur = {}
score_cableur['actions'] = len (acts)
for key, chaine in colonnes[1:]:
score_cableur[key] = len ([i for i in acts if re.search(key, i)])
ligne = "%-*s" % (long_max, cableur) ligne = "%-*s" % (long_max, cableur)
for typ, nom in colonnes: for typ, nom in self.colonnes:
ligne += " | %*d" % (len(nom), score_cableur[typ]) ligne += " | %*d" % (len(nom), acts[typ])
cprint(ligne) cprint(ligne)
def sort_events(self, events):
u"""Split une liste d'évènements selon les mois"""
sorted_events = []
since = datetime.date.replace(datetime.date.today(), day = 1)
backwards = self.nbmois
def donne_cableur(mois, adherent): while backwards > 0:
u""" Cherche le cableur qui a inscrit ou réinscrit un adhérent. """ sorted_events.append([ ev for ev in events if ev[0] >= since ])
cableur = None events = [ ev for ev in events if ev[0] < since ]
# Est-ce qu'on recherche une inscription ou une reinscription? backwards -= 1
if adherent.dateInscription() < date_debut_ann_scol: since = dec_date(since)
action = 'reinscription'
action_filtre = paiement_ann_scol
else:
action = 'inscription'
action_filtre = 'inscription'
for hist in adherent.historique(): sorted_events.append(events)
# On decoupe pour avoir un truc utilisable return sorted_events
champ = hist.replace(',', '').replace(': ', '').split(' ')
# On inspecte la date
date = champ[0].split('/')
if int(date[1]) in mois and int(date[2]) == ann_scol:
# Maintenant on regarde si l'action recherchee est ici
if action_filtre in champ[3:]:
return action, champ[2]
return action, None
def calcul_score(mois): class StatsCableursMachines(StatsCableursBase):
u""" Calcul le score de tous les cableurs ayant inscrit ou u"""Cette classe s'occupe de recenser l'activité des différents
réinscrit quelqu'un pour l'année en cours. """ câbleurs sur les machines, ce qui représente le travail typique du
câbleur en milieu d'année"""
liste = db.search("paiement=2008")['adherent'] def ajoute_actions(self, machine, hist):
u"""Ajoute dans hist la liste des actions effectués par
chacuns des câbleurs sur la machine pendant les mois."""
score = {} for date, champ in parse_historique(machine):
for adherent in liste:
action, cableur = donne_cableur(mois, adherent)
if cableur:
if not score.has_key(cableur):
score[cableur] = { 'inscription': 0,
'reinscription': 0 }
score[cableur][action] += 1
# On calcul le score total pour chaque cableur # on ne va pas non plus compter les actions qu'on fait sur
for s in score.values(): # ses propres machines.
s['total'] = 2 * s['inscription'] + s['reinscription'] if machine.proprietaire().compte() != champ[2]:
return score # Il se peut qu'une personne sans les droits câbleur ait
# effectué une action.
try:
hist[champ[2]].append( (date, champ[3]) )
except KeyError:
hist[champ[2]] = [ (date, champ[3]) ]
def classe(score={}): def get_stats(self):
u""" Retourne la liste des câbleurs classé par score total décroisant. """ u"""Récupère les statistiques des différents câbleurs sur les
cableurs = score.keys() différentes machines"""
cableurs.sort(lambda x, y : cmp(score[x]['total'], score[y]['total']), reverse=True)
return cableurs # La liste des câbleurs en tant qu'entité ldap, histoire de bien
# faire apparaître ceux qui n'ont rien fait
ldap_cableurs = db.search("droits=cableur")['adherent']
# On récupère la liste des machines
all_machines = db.search('mid=*')
machines = all_machines['machineFixe'] + all_machines['machineWifi']
# hists permet de répartir toutes les actions sur les différents
# câbleurs.
hists = {}
for i in ldap_cableurs:
hists[i.compte()] = []
# on récupère l'historique des machines que l'on met dans hists
for becane in machines:
self.ajoute_actions(becane, hists)
split_hist = {}
for cableur in hists.keys():
split_hist[cableur] = self.sort_events(hists[cableur])
self.stats[cableur] = [ len(i) for i in split_hist[cableur] ]
score = sum (self.stats[cableur][:-1])
self.stats[cableur].insert(0, score)
month = datetime.date.today()
for i in range(self.nbmois):
self.colonnes.append( (i + 1, "%d/%02d" % (month.month, month.year - 2000)))
month = dec_date(month)
self.colonnes[0] = (0, "%d last" % self.nbmois)
self.colonnes.append( (self.nbmois +1, "< " + self.colonnes[-1][1]) )
if __name__ == "__main__": if __name__ == "__main__":
nb_affiche = 10 StatsCableursMachines()
mois = range(8, 11)
if len(sys.argv) > 1:
if sys.argv[1] == '-e':
mois = range(8, 13)
if len(sys.argv) > 2:
try:
nb_affiche = int(sys.argv[2])
except ValueError:
nb_affiche = 10
else:
try:
nb_affiche = int(sys.argv[1])
except ValueError:
nb_affiche = 10
if sys.argv[1] == '--efficiency': ## class StatsCableursAdherents:
ActionsCableurs([(1, 2009), (2, 2009), (3, 2009)]) ## u"""Cette classe s'occupe de recenser les actions que les câbleurs
sys.exit(0) ## font sur les adhérents (en fait les {,re}adhésions)."""
##
score = calcul_score(mois) ## colonnes = [('inscription', u'inscription'),
classement = classe(score) ## ('reinscription', u'réinscription'),
## ('total', u'score total')]
if nb_affiche > 0: ##
classement = classement[0:nb_affiche] ## date_debut_ann_scol = time.mktime((ann_scol, 8, 1, 0, 0, 0, 0, 0, 0))
## paiement_ann_scol = "paiement+%d" % ann_scol
# On cherche les noms des câbleurs parceque c'est quand même mieux ##
nom_reel = {} ## def donne_cableur(mois, adherent):
for cableur in classement: ## u""" Cherche le cableur qui a inscrit ou réinscrit un adhérent. """
nom_reel[cableur] = db.search('uid=%s' % cableur)['adherent'][0].Nom() ## cableur = None
##
# Calcul des statistiques ## # Est-ce qu'on recherche une inscription ou une reinscription?
total_inscription = 0 ## if adherent.dateInscription() < self.date_debut_ann_scol:
total_reinscription = 0 ## action = 'reinscription'
total = 0 ## action_filtre = self.paiement_ann_scol
for s in score.values(): ## else:
total_inscription += s['inscription'] ## action = 'inscription'
total_reinscription += s['reinscription'] ## action_filtre = 'inscription'
total += s['total'] ##
cprint(u"""Statistiques globales: ## for hist in adherent.historique():
- inscriptions: %(inscription)d ## # On decoupe pour avoir un truc utilisable
- réinscription: %(reinscription)d ## champ = hist.replace(',', '').replace(': ', '').split(' ')
- total: %(total)d ## # On inspecte la date
## date = champ[0].split('/')
""" % { 'inscription': total_inscription, ## if int(date[1]) in mois and int(date[2]) == ann_scol:
'reinscription': total_reinscription, ## # Maintenant on regarde si l'action recherchee est ici
'total': total }, newline=False) ## if action_filtre in champ[3:]:
## return action, champ[2]
# Calcul la longueur du nom le plus long ##
long_max = reduce(lambda m, c : max(m, len(c)), nom_reel.values(), len('cableur')) ## return action, None
##
colonnes = [('inscription', u'inscription'), ## def calcul_score(mois):
('reinscription', u'réinscription'), ## u""" Calcul le score de tous les cableurs ayant inscrit ou
('total', u'score total')] ## réinscrit quelqu'un pour l'année en cours. """
##
# Titres des colonnes ## liste = db.search("paiement=2008")['adherent']
ligne = "%-*s" % (long_max, u'câbleur') ##
for typ, nom in colonnes: ## score = {}
ligne += " | %s" % nom ## for adherent in liste:
cprint(ligne) ## action, cableur = donne_cableur(mois, adherent)
# Ligne pour délimiter ## if cableur:
ligne = ''.center(long_max, '-') ## if not score.has_key(cableur):
for typ, nom in colonnes: ## score[cableur] = { 'inscription': 0,
ligne += "-+-%s" % ''.center(len(nom), '-') ## 'reinscription': 0 }
cprint(ligne) ## score[cableur][action] += 1
# Statiqtiques par câbleur ##
for cableur in classement: ## # On calcul le score total pour chaque cableur
score_cableur = score[cableur] ## for s in score.values():
ligne = "%-*s" % (long_max, nom_reel[cableur]) ## s['total'] = 2 * s['inscription'] + s['reinscription']
for typ, nom in colonnes: ##
ligne += " | %*d" % (len(nom), score_cableur[typ]) ## return score
cprint(ligne) ##
## def classement(score={}):
## u""" Retourne la liste des câbleurs classé par score total décroisant. """
## cableurs = score.keys()
## cableurs.sort(lambda x, y : cmp(score[x]['total'], score[y]['total']), reverse=True)
## return cableurs
##
##
##
## if __name__ == "__main__":
## nb_affiche = 10
## mois = range(8, 11)
## if len(sys.argv) > 1:
## if sys.argv[1] == '-e':
## mois = range(8, 13)
## if len(sys.argv) > 2:
## try:
## nb_affiche = int(sys.argv[2])
## except ValueError:
## nb_affiche = 10
## else:
## try:
## nb_affiche = int(sys.argv[1])
## except ValueError:
## nb_affiche = 10
##
## if sys.argv[1] == '--efficiency':
## ActionsCableurs([(1, 2009), (2, 2009), (3, 2009)])
## sys.exit(0)
##
## score = calcul_score(mois)
## classement = classe(score)
##
## if nb_affiche > 0:
## classement = classement[0:nb_affiche]
##
## # On cherche les noms des câbleurs parceque c'est quand même mieux
## nom_reel = {}
## for cableur in classement:
## nom_reel[cableur] = db.search('uid=%s' % cableur)['adherent'][0].Nom()
##
## # Calcul des statistiques
## total_inscription = 0
## total_reinscription = 0
## total = 0
## for s in score.values():
## total_inscription += s['inscription']
## total_reinscription += s['reinscription']
## total += s['total']
## cprint(u"""Statistiques globales:
## - inscriptions: %(inscription)d
## - réinscription: %(reinscription)d
## - total: %(total)d
##
## """ % { 'inscription': total_inscription,
## 'reinscription': total_reinscription,
## 'total': total }, newline=False)
##
## # Calcul la longueur du nom le plus long
## long_max = reduce(lambda m, c : max(m, len(c)), nom_reel.values(), len('cableur'))
##
##
## # Titres des colonnes
## ligne = "%-*s" % (long_max, u'câbleur')
## for typ, nom in colonnes:
## ligne += " | %s" % nom
## cprint(ligne)
## # Ligne pour délimiter
## ligne = ''.center(long_max, '-')
## for typ, nom in colonnes:
## ligne += "-+-%s" % ''.center(len(nom), '-')
## cprint(ligne)
## # Statiqtiques par câbleur
## for cableur in classement:
## score_cableur = score[cableur]
## ligne = "%-*s" % (long_max, nom_reel[cableur])
## for typ, nom in colonnes:
## ligne += " | %*d" % (len(nom), score_cableur[typ])
## cprint(ligne)