From 0d56d356adf02bb6ca4fbdec5c1fb7640eec56e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl-David=20Lasseri?= Date: Sun, 12 Jan 2014 23:31:44 +0100 Subject: [PATCH] On rajoute un lien symbolique de l'ancien stats_cableurs vers le nouveau --- archive/utils/stats_cableurs.py | 431 +++++++++++++++++++++++++++++++ utils/stats_cableurs.py | 432 +------------------------------- 2 files changed, 432 insertions(+), 431 deletions(-) create mode 100755 archive/utils/stats_cableurs.py mode change 100755 => 120000 utils/stats_cableurs.py diff --git a/archive/utils/stats_cableurs.py b/archive/utils/stats_cableurs.py new file mode 100755 index 00000000..ef1d6fed --- /dev/null +++ b/archive/utils/stats_cableurs.py @@ -0,0 +1,431 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# stats_cableurs.py +# ----------------- +# +# Copyright (C) 2008, 2009 François Bobot , +# Jeremie Dimino , +# Michel Blockelet , +# Antoine Durand-Gasselin +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + +import sys, re, datetime +# hack temporaire pour pallier avoir la version 2.5 de optparse +#from optparse import OptionParser +sys.path.append('/usr/scripts/lib') +from optparse import OptionParser, OptionGroup + +sys.path.append("/usr/scripts/gestion/") +from ldap_crans import CransLdap, Adherent +from config import ann_scol + + + +db = CransLdap() + +__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 et renvoie la liste des actions sous la forme + (['dd', 'mm', 'yyyy'], ['date', 'heure', 'who', 'what'])""" + 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 StatsCableursBase: + u"""Classe prototype pour afficher des stats de câbleurs.""" + + colonnes = [] + nbmois = 4 + stats = {} + score = {} + kwargs = {} + + def __init__(self, **kwargs): + + self.kwargs.update(kwargs) + self.affiche (self.kwargs, 'd') + + # On regarde s'il y a un mois à partir duquel on veuille partir. + mois = kwargs.get("mois", -4) + + # On compte ensuite combien de mois ça fait + if mois > 0: + # si on demande depuis 09 (septembre) , on remonte + # jusqu'à septembre + self.nbmois = (datetime.date.today().month + 12 - mois) % 12 + else: + # si on demande les stats sur 4 mois, on remonte sur 4 + # mois + self.nbmois = - mois + + # On regarde si on avait pas déjà précisé sur combien de mois on + # voulait partir. + self.nbmois = kwargs.get("nbmois", self.nbmois) + + # bout de code à mon avis explicite + self.def_columns() + self.affiche("Génération des stats") + self.get_stats() + self.calc_score() + cableurs = self.sort_cableurs() + self.print_stats(cableurs) + + + def def_columns(self): + u"""Fonction qui sera appelée pour éventuellement mettre à jour + self.colonnes""" + pass + + def get_stats(self): + u"""Fonction censée récupérer les stats des différents câbleurs, + et les fouttre dans self.stats""" + raise NotImplementedError + + def calc_score(self): + u"""Fonction censée calculer le score en fonction des stats, et + le mettre dans self.score""" + raise NotImplementedError + + def sort_cableurs(self): + u"""Renvoie la liste des câbleurs triés, en fonction de leur score""" + cableurs = self.stats.keys() + cableurs.sort(lambda x, y : cmp(self.score[x], self.score[y]), reverse=True) + + if self.kwargs.get('top', 10) != 0: + cableurs = cableurs[:self.kwargs.get('top', 10)] + return cableurs + + def print_stats(self, cableurs): + u"""Affiche pour chaque cableur les valeurs de ses différentes colonnes + définies dans self.colonnes.""" + + # On génère la liste des noms sous lesquels on va afficher nos câbleurs + noms = {} + for cableur in cableurs: + try: + ldap_cableur = db.search('login=%s' % cableur)['adherent'][0] + ids = { 'nom' : ldap_cableur.nom(), + 'prenom' : ldap_cableur.prenom(), + 'droits' : reduce(unicode.__add__, + [d[0] for d in ldap_cableur.droits()], u''), + 'tel' : ldap_cableur.tel(), + 'login' : cableur } + noms[cableur] = self.kwargs.get("fqn", "%(prenom)s %(nom)s") % ids + except IndexError: + self.affiche ("Unknown cableur %s!" % cableur, 'd') + noms[cableur] = cableur+'*' + + # On récupère la liste des câbleurs, triés en fonction de leur score + long_max = reduce(lambda m, c : max(m, len(c)), noms.values(), len('cableur')) + + # Titres des colonnes + ligne = u"%-*s" % (long_max, u'Câbleur') + ligne += u" | Score" + for col in self.colonnes: + ligne += u" | %s" % col + print(ligne) + + # Ligne pour délimiter + ligne = u'-' * long_max + ligne += u"-+-%s" % (u'-' * len ("score")) + for col in self.colonnes: + ligne += u"-+-%s" % (u'-' * len(col)) + print(ligne) + + # Statiqtiques par câbleur + for cableur in cableurs: + acts = self.stats[cableur] + ligne = u"%-*s" % (long_max, noms[cableur]) + ligne += u" | %*d" % (len ("score"), self.score[cableur]) + for i in range (len (self.colonnes)): + ligne += u" | %*d" % (len(self.colonnes[i]), acts[i]) + print(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 + + while backwards > 0: + sorted_events.append([ ev for ev in events if ev[0] >= since ]) + events = [ ev for ev in events if ev[0] < since ] + backwards -= 1 + since = dec_date(since) + + sorted_events.append(events) + return sorted_events + + def affiche(self, msg, reqs= 'v'): + u"""Fonction de print qui n'affiche que si on est dans un mode + kikoolol, debug ou verbose suffisamment avancé.""" + try: + pool = list (self.kwargs.get('flags', '')) + for i in reqs: + pool.remove(i) + print msg + except ValueError: + return + + +class StatsCableursMachines(StatsCableursBase): + u"""Cette classe s'occupe de recenser l'activité des différents + câbleurs sur les machines, ce qui représente le travail typique du + câbleur en milieu d'année""" + + kwargs = { 'fqn' : '%(login)s' , 'top' : 0 } + + 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.""" + + for date, champ in parse_historique(machine): + + # on ne va pas non plus compter les actions qu'on fait sur + # ses propres machines. + proprio = machine.proprietaire() + if isinstance(proprio, Adherent) and proprio.compte() != champ[2]: + # 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 def_columns(self): + u"""Simplement une par mois, plus une pour toutes les actions + d'avant.""" + + month = datetime.date.replace(datetime.date.today(), day=1) + for i in range(self.nbmois): + self.colonnes.append("%d/%02d" % (month.month, month.year - 2000)) + month = dec_date(month) + + self.colonnes.append("< " + self.colonnes[-1]) + + + def get_stats(self): + u"""Récupère les statistiques des différents câbleurs sur les + différentes machines""" + + # 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] ] + + + def calc_score(self): + u"""Le calcul se fait simplement comme la somme des actions + (indépendamment de leur type pour l'instant) sur les mois + concernés.""" + + for cableur in self.stats.keys(): + self.score[cableur] = sum (self.stats[cableur][:-1]) + + + +class StatsCableursAdherents(StatsCableursBase): + u"""Cette classe s'occupe de recenser les actions que les câbleurs + font sur les adhérents (en fait les {,re}adhésions).""" + + colonnes = [ u'Inscriptions', u'Réadhésions' ] + + debut_ann_scol = datetime.date(ann_scol, 8, 1) + paiement_ann_scol = "paiement+%d" % ann_scol + + def donne_cableur(self, adherent): + u""" Cherche le cableur qui a inscrit ou réinscrit un adhérent. """ + + # Est-ce qu'on recherche une inscription ou une reinscription? + date_inscr = datetime.date.fromtimestamp(adherent.dateInscription()) + if date_inscr < self.debut_ann_scol: + action = 1 # 'reinscription' + action_filtre = self.paiement_ann_scol + else: + action = 0 # 'inscription' + action_filtre = 'inscription' + + for date, champ in parse_historique(adherent): + if date >= self.debut_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 get_stats(self): + u"""Calcule le nombre d'inscriptions et réinscription pour tous + les cableurs ayant inscrit ou réinscrit quelqu'un pour l'année + en cours.""" + + liste = db.search("paiement=%s" % ann_scol)['adherent'] + + for adherent in liste: + action, cableur = self.donne_cableur(adherent) + if cableur: + if not self.stats.has_key(cableur): + self.stats[cableur] = [0, 0] + self.stats[cableur][action] += 1 + + + def calc_score(self): + u"""Calcule le score d'un câbleur, en fonction du nombre + d'adhésions qu'il a effectué""" + + # On calcule le score total pour chaque cableur + for cableur in self.stats.keys(): + self.score[cableur] = 2 * self.stats[cableur][0] + self.stats[cableur][1] + + + + +def update_fqn(option, opt_str, value, this, fmt): + u"""Utilisée dans le parser, cette fonction permet de mettre à jour + correctement la chaîne de format""" + try: + if opt_str not in ['-d', '--droits']: + if re.match ('^ \(%\(droits\)s\)', this.values.fqn): + this.values.fqn = fmt + this.values.fqn + else: + this.values.fqn = this.values.fqn + (' (%s)' % fmt) + else: + this.values.fqn = this.values.fqn + fmt + except TypeError: + this.values.fqn = fmt + +def notimplerr(option, opt_str, value, parseur): + u"""Un callback pour le parser pour renvoyer un NotImplementedError""" + raise NotImplementedError + +if __name__ == "__main__": + usage = "usage: %prog [options]\n %prog [options] [--efficiency -e]" + parser = OptionParser(usage=usage) + + # options pour décider le nombre de câbleurs à afficher + group = OptionGroup(parser, "Options de filtrage", + u"Option pour filtrer les câbleurs à afficher") + group.add_option('-a', '--all', help= u"Affiche tous les câbleurs", + action='store_const', const=0, dest='top') + group.add_option('-t', '--top', metavar= "NB", type= 'int', dest='top', + help= u"N'affiche que les NB meilleurs câbleurs") + parser.add_option_group(group) + + # options pour le format d'affichage des câbleurs + group = OptionGroup(parser, u"Format d'affichage", + u"Pour définir le format d'affichage des câbleurs") + group.add_option('-d', '--droits', help= u"Affiche les droits du câbleur", + action='callback', callback= update_fqn, + callback_kwargs= { 'fmt': ' (%(droits)s)'}) + group.add_option('-F', '--full-name', + help=u"Affiche Prenom Nom des câbleurs", + action='callback', callback= update_fqn, + callback_kwargs= { 'fmt': '%(prenom)s %(nom)s'}) + group.add_option('-l', '--login', help= u"Affiche le login des câbleurs", + action='callback', callback= update_fqn, + callback_kwargs= { 'fmt': '%(login)s'}) + parser.add_option('-T', '--tel', help= u"Affiche le n° de téléphone", + action='callback', callback= update_fqn, + callback_kwargs= { 'fmt': '%(tel)s'}) + group.add_option('--fqn', dest='fqn', + help= u"Définit le format d'affichage du nom du câbleur, les champs possibles sont %(droits)s, %(nom)s, %(prenom)s, %(login)s, %(tel)s") + parser.add_option_group(group) + + # options de verbosité + group = OptionGroup(parser, u"Commander la verbosité", + u"Pour définir ce que le script doit afficher en plus") + group.add_option('-D', '--debug', + help= u"Affiche des informations de debuggage", + action='store_const', const='d', dest= 'debug') + group.add_option('-k', '--kikoolol', help="Affiche des trucs kikoolol", + action='callback', callback= notimplerr) + group.add_option('-v', '--verbose', help= u"Augmente la verbosité", + action='store_const', const= 'v', dest= 'verbose') + parser.add_option_group(group) + + # options sur la durée étudiée + group = OptionGroup(parser, u"Durée étudiée", + u"Pour définir la durée sur laquelle on travaille") + group.add_option('-f', '--for', metavar= 'N', + help= u"Affiche les statistiqes depuis N mois", + type= 'int', dest='nbmois') + group.add_option('-s', '--since', metavar= 'MM', + help= u'Affiche les stats depuis MOIS', + type= 'int', dest='mois') + parser.add_option_group(group) + + # Devrait plutôt être un argument qu'une option + parser.add_option('-e', '--efficiency', + help= u"Compte les actions effectuées sur les machines", + action= 'store_const', + const= StatsCableursMachines, + dest= 'default_stats', + default= StatsCableursAdherents) + + # on parse, enfin, on laisse optparse le faire pour nous + (options, args) = parser.parse_args() + + # Parce que les clefs ont par défaut la valeur None + kwargs = {} + for lbl, field in options.__dict__.items(): + if field is not None and lbl != 'default_stats': + kwargs[lbl] = field + + # XXX: l'action append_const dans optparse est ajoutée en Python 2.5 + flaglist = [] + if options.verbose: + flaglist.append("v") + if options.debug: + flaglist.append("D") + flags = "".join(flaglist) + + kwargs["flags"] = flags + + # On apelle les stats que l'on veut calculer + options.default_stats(**kwargs) diff --git a/utils/stats_cableurs.py b/utils/stats_cableurs.py deleted file mode 100755 index ef1d6fed..00000000 --- a/utils/stats_cableurs.py +++ /dev/null @@ -1,431 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# stats_cableurs.py -# ----------------- -# -# Copyright (C) 2008, 2009 François Bobot , -# Jeremie Dimino , -# Michel Blockelet , -# Antoine Durand-Gasselin -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This file is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - -import sys, re, datetime -# hack temporaire pour pallier avoir la version 2.5 de optparse -#from optparse import OptionParser -sys.path.append('/usr/scripts/lib') -from optparse import OptionParser, OptionGroup - -sys.path.append("/usr/scripts/gestion/") -from ldap_crans import CransLdap, Adherent -from config import ann_scol - - - -db = CransLdap() - -__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 et renvoie la liste des actions sous la forme - (['dd', 'mm', 'yyyy'], ['date', 'heure', 'who', 'what'])""" - 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 StatsCableursBase: - u"""Classe prototype pour afficher des stats de câbleurs.""" - - colonnes = [] - nbmois = 4 - stats = {} - score = {} - kwargs = {} - - def __init__(self, **kwargs): - - self.kwargs.update(kwargs) - self.affiche (self.kwargs, 'd') - - # On regarde s'il y a un mois à partir duquel on veuille partir. - mois = kwargs.get("mois", -4) - - # On compte ensuite combien de mois ça fait - if mois > 0: - # si on demande depuis 09 (septembre) , on remonte - # jusqu'à septembre - self.nbmois = (datetime.date.today().month + 12 - mois) % 12 - else: - # si on demande les stats sur 4 mois, on remonte sur 4 - # mois - self.nbmois = - mois - - # On regarde si on avait pas déjà précisé sur combien de mois on - # voulait partir. - self.nbmois = kwargs.get("nbmois", self.nbmois) - - # bout de code à mon avis explicite - self.def_columns() - self.affiche("Génération des stats") - self.get_stats() - self.calc_score() - cableurs = self.sort_cableurs() - self.print_stats(cableurs) - - - def def_columns(self): - u"""Fonction qui sera appelée pour éventuellement mettre à jour - self.colonnes""" - pass - - def get_stats(self): - u"""Fonction censée récupérer les stats des différents câbleurs, - et les fouttre dans self.stats""" - raise NotImplementedError - - def calc_score(self): - u"""Fonction censée calculer le score en fonction des stats, et - le mettre dans self.score""" - raise NotImplementedError - - def sort_cableurs(self): - u"""Renvoie la liste des câbleurs triés, en fonction de leur score""" - cableurs = self.stats.keys() - cableurs.sort(lambda x, y : cmp(self.score[x], self.score[y]), reverse=True) - - if self.kwargs.get('top', 10) != 0: - cableurs = cableurs[:self.kwargs.get('top', 10)] - return cableurs - - def print_stats(self, cableurs): - u"""Affiche pour chaque cableur les valeurs de ses différentes colonnes - définies dans self.colonnes.""" - - # On génère la liste des noms sous lesquels on va afficher nos câbleurs - noms = {} - for cableur in cableurs: - try: - ldap_cableur = db.search('login=%s' % cableur)['adherent'][0] - ids = { 'nom' : ldap_cableur.nom(), - 'prenom' : ldap_cableur.prenom(), - 'droits' : reduce(unicode.__add__, - [d[0] for d in ldap_cableur.droits()], u''), - 'tel' : ldap_cableur.tel(), - 'login' : cableur } - noms[cableur] = self.kwargs.get("fqn", "%(prenom)s %(nom)s") % ids - except IndexError: - self.affiche ("Unknown cableur %s!" % cableur, 'd') - noms[cableur] = cableur+'*' - - # On récupère la liste des câbleurs, triés en fonction de leur score - long_max = reduce(lambda m, c : max(m, len(c)), noms.values(), len('cableur')) - - # Titres des colonnes - ligne = u"%-*s" % (long_max, u'Câbleur') - ligne += u" | Score" - for col in self.colonnes: - ligne += u" | %s" % col - print(ligne) - - # Ligne pour délimiter - ligne = u'-' * long_max - ligne += u"-+-%s" % (u'-' * len ("score")) - for col in self.colonnes: - ligne += u"-+-%s" % (u'-' * len(col)) - print(ligne) - - # Statiqtiques par câbleur - for cableur in cableurs: - acts = self.stats[cableur] - ligne = u"%-*s" % (long_max, noms[cableur]) - ligne += u" | %*d" % (len ("score"), self.score[cableur]) - for i in range (len (self.colonnes)): - ligne += u" | %*d" % (len(self.colonnes[i]), acts[i]) - print(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 - - while backwards > 0: - sorted_events.append([ ev for ev in events if ev[0] >= since ]) - events = [ ev for ev in events if ev[0] < since ] - backwards -= 1 - since = dec_date(since) - - sorted_events.append(events) - return sorted_events - - def affiche(self, msg, reqs= 'v'): - u"""Fonction de print qui n'affiche que si on est dans un mode - kikoolol, debug ou verbose suffisamment avancé.""" - try: - pool = list (self.kwargs.get('flags', '')) - for i in reqs: - pool.remove(i) - print msg - except ValueError: - return - - -class StatsCableursMachines(StatsCableursBase): - u"""Cette classe s'occupe de recenser l'activité des différents - câbleurs sur les machines, ce qui représente le travail typique du - câbleur en milieu d'année""" - - kwargs = { 'fqn' : '%(login)s' , 'top' : 0 } - - 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.""" - - for date, champ in parse_historique(machine): - - # on ne va pas non plus compter les actions qu'on fait sur - # ses propres machines. - proprio = machine.proprietaire() - if isinstance(proprio, Adherent) and proprio.compte() != champ[2]: - # 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 def_columns(self): - u"""Simplement une par mois, plus une pour toutes les actions - d'avant.""" - - month = datetime.date.replace(datetime.date.today(), day=1) - for i in range(self.nbmois): - self.colonnes.append("%d/%02d" % (month.month, month.year - 2000)) - month = dec_date(month) - - self.colonnes.append("< " + self.colonnes[-1]) - - - def get_stats(self): - u"""Récupère les statistiques des différents câbleurs sur les - différentes machines""" - - # 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] ] - - - def calc_score(self): - u"""Le calcul se fait simplement comme la somme des actions - (indépendamment de leur type pour l'instant) sur les mois - concernés.""" - - for cableur in self.stats.keys(): - self.score[cableur] = sum (self.stats[cableur][:-1]) - - - -class StatsCableursAdherents(StatsCableursBase): - u"""Cette classe s'occupe de recenser les actions que les câbleurs - font sur les adhérents (en fait les {,re}adhésions).""" - - colonnes = [ u'Inscriptions', u'Réadhésions' ] - - debut_ann_scol = datetime.date(ann_scol, 8, 1) - paiement_ann_scol = "paiement+%d" % ann_scol - - def donne_cableur(self, adherent): - u""" Cherche le cableur qui a inscrit ou réinscrit un adhérent. """ - - # Est-ce qu'on recherche une inscription ou une reinscription? - date_inscr = datetime.date.fromtimestamp(adherent.dateInscription()) - if date_inscr < self.debut_ann_scol: - action = 1 # 'reinscription' - action_filtre = self.paiement_ann_scol - else: - action = 0 # 'inscription' - action_filtre = 'inscription' - - for date, champ in parse_historique(adherent): - if date >= self.debut_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 get_stats(self): - u"""Calcule le nombre d'inscriptions et réinscription pour tous - les cableurs ayant inscrit ou réinscrit quelqu'un pour l'année - en cours.""" - - liste = db.search("paiement=%s" % ann_scol)['adherent'] - - for adherent in liste: - action, cableur = self.donne_cableur(adherent) - if cableur: - if not self.stats.has_key(cableur): - self.stats[cableur] = [0, 0] - self.stats[cableur][action] += 1 - - - def calc_score(self): - u"""Calcule le score d'un câbleur, en fonction du nombre - d'adhésions qu'il a effectué""" - - # On calcule le score total pour chaque cableur - for cableur in self.stats.keys(): - self.score[cableur] = 2 * self.stats[cableur][0] + self.stats[cableur][1] - - - - -def update_fqn(option, opt_str, value, this, fmt): - u"""Utilisée dans le parser, cette fonction permet de mettre à jour - correctement la chaîne de format""" - try: - if opt_str not in ['-d', '--droits']: - if re.match ('^ \(%\(droits\)s\)', this.values.fqn): - this.values.fqn = fmt + this.values.fqn - else: - this.values.fqn = this.values.fqn + (' (%s)' % fmt) - else: - this.values.fqn = this.values.fqn + fmt - except TypeError: - this.values.fqn = fmt - -def notimplerr(option, opt_str, value, parseur): - u"""Un callback pour le parser pour renvoyer un NotImplementedError""" - raise NotImplementedError - -if __name__ == "__main__": - usage = "usage: %prog [options]\n %prog [options] [--efficiency -e]" - parser = OptionParser(usage=usage) - - # options pour décider le nombre de câbleurs à afficher - group = OptionGroup(parser, "Options de filtrage", - u"Option pour filtrer les câbleurs à afficher") - group.add_option('-a', '--all', help= u"Affiche tous les câbleurs", - action='store_const', const=0, dest='top') - group.add_option('-t', '--top', metavar= "NB", type= 'int', dest='top', - help= u"N'affiche que les NB meilleurs câbleurs") - parser.add_option_group(group) - - # options pour le format d'affichage des câbleurs - group = OptionGroup(parser, u"Format d'affichage", - u"Pour définir le format d'affichage des câbleurs") - group.add_option('-d', '--droits', help= u"Affiche les droits du câbleur", - action='callback', callback= update_fqn, - callback_kwargs= { 'fmt': ' (%(droits)s)'}) - group.add_option('-F', '--full-name', - help=u"Affiche Prenom Nom des câbleurs", - action='callback', callback= update_fqn, - callback_kwargs= { 'fmt': '%(prenom)s %(nom)s'}) - group.add_option('-l', '--login', help= u"Affiche le login des câbleurs", - action='callback', callback= update_fqn, - callback_kwargs= { 'fmt': '%(login)s'}) - parser.add_option('-T', '--tel', help= u"Affiche le n° de téléphone", - action='callback', callback= update_fqn, - callback_kwargs= { 'fmt': '%(tel)s'}) - group.add_option('--fqn', dest='fqn', - help= u"Définit le format d'affichage du nom du câbleur, les champs possibles sont %(droits)s, %(nom)s, %(prenom)s, %(login)s, %(tel)s") - parser.add_option_group(group) - - # options de verbosité - group = OptionGroup(parser, u"Commander la verbosité", - u"Pour définir ce que le script doit afficher en plus") - group.add_option('-D', '--debug', - help= u"Affiche des informations de debuggage", - action='store_const', const='d', dest= 'debug') - group.add_option('-k', '--kikoolol', help="Affiche des trucs kikoolol", - action='callback', callback= notimplerr) - group.add_option('-v', '--verbose', help= u"Augmente la verbosité", - action='store_const', const= 'v', dest= 'verbose') - parser.add_option_group(group) - - # options sur la durée étudiée - group = OptionGroup(parser, u"Durée étudiée", - u"Pour définir la durée sur laquelle on travaille") - group.add_option('-f', '--for', metavar= 'N', - help= u"Affiche les statistiqes depuis N mois", - type= 'int', dest='nbmois') - group.add_option('-s', '--since', metavar= 'MM', - help= u'Affiche les stats depuis MOIS', - type= 'int', dest='mois') - parser.add_option_group(group) - - # Devrait plutôt être un argument qu'une option - parser.add_option('-e', '--efficiency', - help= u"Compte les actions effectuées sur les machines", - action= 'store_const', - const= StatsCableursMachines, - dest= 'default_stats', - default= StatsCableursAdherents) - - # on parse, enfin, on laisse optparse le faire pour nous - (options, args) = parser.parse_args() - - # Parce que les clefs ont par défaut la valeur None - kwargs = {} - for lbl, field in options.__dict__.items(): - if field is not None and lbl != 'default_stats': - kwargs[lbl] = field - - # XXX: l'action append_const dans optparse est ajoutée en Python 2.5 - flaglist = [] - if options.verbose: - flaglist.append("v") - if options.debug: - flaglist.append("D") - flags = "".join(flaglist) - - kwargs["flags"] = flags - - # On apelle les stats que l'on veut calculer - options.default_stats(**kwargs) diff --git a/utils/stats_cableurs.py b/utils/stats_cableurs.py new file mode 120000 index 00000000..81889c3f --- /dev/null +++ b/utils/stats_cableurs.py @@ -0,0 +1 @@ +stats_cableurs2.py \ No newline at end of file