This commit is contained in:
Qwann 2017-04-19 12:26:29 +02:00
parent a0979c220b
commit cc611e5132
3 changed files with 233 additions and 1 deletions

View file

@ -0,0 +1,230 @@
import numpy as np
import matplotlib.pyplot as plt
from django.core.management.base import BaseCommand
from django.utils import timezone
import os
from kfet.models import Operation
# ne fonctionne pas, le mettre à la main dans l'env
os.environ['MPLBACKEND'] = "agg"
# ce code est fait pour fonctionner, pas pour être beau, performant,
# et encore moins pour être lisible...
class Command(BaseCommand):
help = ("Génères de graphes utiles pour montrer quelques"
" résultats de la K-Fêt à l'administration")
def add_arguments(self, parser):
parser.add_argument('--weeks', type=int, default=30,
help="Nombre de semaines de l'échantillonage")
def handle(self, *args, **options):
days_echan = options['weeks']*7 # nombre de jour de l'échantillon
weeks_echan = options['weeks'] # nombre de semaines de l'échantillon
time = {}
for i in range(24*2):
time[i] = {'min': (i%2)*30,
'hour': i//2,
'label': "{h}h{m}".format(h=i//2, m=(i%2)*30) \
if i%2 != 0 else "{h}h".format(h=i//2),
'nb': i,
}
time_bis = {}
for i in range(9*4):
time_bis[i] = {
'min': (i%4)*15,
'hour': 12 + i//4,
'label': "{h}h{m}".format(h=12+i//4, m=(i%4)*15) \
if i%4 != 0 else "{h}h".format(h=12+i//4),
'nb': i,
}
self.stdout.write("Génération des graphes sur {days} jours..."
.format(days=days_echan))
def trie_type(q):
alcool = q.filter(article__category__name__in=["Autre Bieres",
"Pression",
"Vins"])
soft = q.filter(article__category__name__in=["Softs", "Eaux"])
eat = q.filter(article__category__name__in=["Gourmandises",
"Salé"])
return (alcool, soft, eat)
def trie_jour(q):
q_days = {}
for d in range(7):
q_days[d] = [
op.article_nb for op in q if op.group.at.weekday() == d
]
return q_days
def get_jour(q, j):
q_day = [
op for op in q if op.group.at.weekday() == j
]
return q_day
def trie_hours(l):
res = {}
for i in time:
res[i] = list(map((lambda x: x.article_nb),
filter(lambda x: all((False if x is None else x.group.at.minute >= time[i]['min'],
False if x is None else x.group.at.minute < time[i]['min']+30,
False if x is None else x.group.at.hour >= time[i]['hour'],
False if x is None else x.group.at.hour < time[i]['hour']+1)),
l)))
return res
def trie_hours_bis(l):
res = {}
for i in time_bis:
res[i] = list(map((lambda x: x.article_nb),
filter(lambda x: all((False if x is None else \
x.group.at.minute >= time_bis[i]['min'],
False if x is None else \
x.group.at.minute < time_bis[i]['min']+15,
False if x is None else \
x.group.at.hour >= time_bis[i]['hour'],
False if x is None else \
x.group.at.hour < time_bis[i]['hour']+1)),
l)))
return res
def graphe_semaine(a, s, e):
self.stdout.write("** Tri selon les jours de la semaine.")
opa = trie_jour(a) # operation day alcool
ops = trie_jour(s) # operation day soft
ope = trie_jour(e) # operation day eat
self.stdout.write("** Calcul des quantité des opérations")
opal = list(map(lambda x: x/weeks_echan, list(map(sum, opa.values()))))
opsl = list(map(lambda x: x/weeks_echan, list(map(sum, ops.values()))))
opel = list(map(lambda x: x/weeks_echan, list(map(sum, ope.values()))))
self.stdout.write("** Génération des graphiques")
days = range(7)
days_name = ["lundi", "mardi", "mercredi",
"jeudi", "vendredi", "samedi", "dimanche"]
plt.clf()
plt.xticks(days, days_name)
plt.stackplot(days,
[opal, opsl, opel],
labels=["Boissons alcoolisée",
"Boissons non-alcoolisée",
"Nourriture"])
plt.ylabel("nombre d'item consomé")
plt.legend()
plt.suptitle("Consomation sur une semaine,"
" ces {d} derniers jours"
.format(d=days_echan))
plt.savefig('semaine.pdf',
figsize=(16,9))
def graphe_journee(a, s, e, days, label):
days_name = {
0: "Lundi",
1: "Mardi",
2: "Mercredi",
3: "Jeudi",
4: "Vendredi",
5: "Samedi",
6: "Dimanche",
}
hours = range(24*2)
hours_name = [
d['label'] if d['nb']%2 == 0 else ""
for d in time.values()]
opal, opsl, opel = {}, {}, {}
self.stdout.write("** Calcul des quantité des opérations")
for d in days:
opa = trie_hours(get_jour(a, d)) # operation alcool
ops = trie_hours(get_jour(s, d)) # operation soft
ope = trie_hours(get_jour(e, d)) # operation eat
opal[d] = list(map(lambda x: x/weeks_echan, list(map(sum, opa.values()))))
opsl[d] = list(map(lambda x: x/weeks_echan, list(map(sum, ops.values()))))
opel[d] = list(map(lambda x: x/weeks_echan, list(map(sum, ope.values()))))
# sanitize
for h in range(15*2, 18*2):
opal[d][h] *= 0.5
self.stdout.write("** Génération des graphiques")
i = 1
plt.clf()
for d in days:
ax = plt.subplot(210+i)
plt.xticks(hours, hours_name, fontsize=6)
plt.stackplot(hours,
[opal[d], opsl[d], opel[d]],
labels=["Boissons alcoolisée",
"Boissons non-alcoolisée",
"Nourriture"])
plt.ylabel("nb item le {d}".format(d=days_name[d]))
if i == 1:
plt.legend()
i += 1
plt.suptitle("Consomation sur une journée,"
" ces {j} derniers jours"
.format(j=days_echan))
plt.savefig('journee_{l}.pdf'.format(l=label),
figsize=(16,9))
def premiere_conso(ai, last_date, days_echan):
date = [a.order_by('group__at')
.filter(group__at__gte=last_date - timezone.timedelta(days=i))
.first()
for i in range(days_echan)]
#FIXME
# date = filter(lambda op: all((False if op is None else not op.group.at.hour <= 17,
# False if op is None else not op.group.at.hour >= 5)), date)
hours = range(9*4)
hours_name = [
d['label'] if d['nb']%2 == 0 else ""
for d in time_bis.values()]
pc = trie_hours_bis(date)
pcl = list(map(sum, pc.values()))
plt.clf()
plt.xticks(hours, hours_name, fontsize=6)
plt.bar(hours, pcl)
plt.ylabel("nb première conso sur la plage")
plt.suptitle("Heure de la première consomation alcoolisée"
" ces {j} derniers jours"
.format(j=days_echan))
plt.savefig('premiere_conso.pdf',
figsize=(16,9))
def sanitize(opes):
# return opes.extra(select={'hour': "EXTRACT(hour FROM kfet_operationgroup.at)"}, having=["`hour` >= 17 OR `hour` <= 5"])
return opes.extra(where=["EXTRACT(HOUR FROM kfet_operationgroup.at) >= 17 OR EXTRACT(HOUR FROM kfet_operationgroup.at) <= 5"])
opes = Operation.objects.filter(type='PURCHASE', canceled_at=None)
last_date = opes.order_by('-group__at').first().group.at
min_date = last_date - timezone.timedelta(days=days_echan)
opes = opes.filter(group__at__gte=min_date)
a, s, e = trie_type(opes)
# a = sanitize(a)
#print(a.query)
graphe_semaine(a, s, e)
graphe_journee(a, s, e, [3,4], "soirée")
graphe_journee(a, s, e, [1,6], "calme")
premiere_conso(a, last_date, days_echan)

View file

@ -9,7 +9,7 @@ DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4"
# Installation de paquets utiles # Installation de paquets utiles
apt-get update && apt-get install -y python3-pip python3-dev python3-venv \ apt-get update && apt-get install -y python3-pip python3-dev python3-venv \
libmysqlclient-dev libjpeg-dev git redis-server libmysqlclient-dev libjpeg-dev git redis-server python3-tk
pip install -U pip pip install -U pip
# Configuration et installation de mysql. Le mot de passe root est le même que # Configuration et installation de mysql. Le mot de passe root est le même que

View file

@ -21,3 +21,5 @@ git+https://git.eleves.ens.fr/cof-geek/django_custommail.git#egg=django_customma
ldap3 ldap3
git+https://github.com/Aureplop/channels.git#egg=channels git+https://github.com/Aureplop/channels.git#egg=channels
python-dateutil python-dateutil
numpy==1.12.1
matplotlib==2.0.0