Compare commits
2 Commits
b781ebe8cf
...
5330b27e5d
Author | SHA1 | Date |
---|---|---|
theo@manjaro | 5330b27e5d | |
theo@manjaro | 31aaeca2e2 |
|
@ -3,3 +3,4 @@ __pycache__/
|
||||||
*$py.class
|
*$py.class
|
||||||
cache/
|
cache/
|
||||||
push_to_server.sh
|
push_to_server.sh
|
||||||
|
log.json
|
||||||
|
|
55
app.py
55
app.py
|
@ -14,6 +14,8 @@
|
||||||
# Modules :
|
# Modules :
|
||||||
import datetime as dti
|
import datetime as dti
|
||||||
import pytz
|
import pytz
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask import render_template
|
from flask import render_template
|
||||||
|
@ -28,8 +30,10 @@ import rooms_get as ro
|
||||||
# Constantes :
|
# Constantes :
|
||||||
MAX_DEPT = 5 # Le maximum de départements qu'il est possible de sélectionner
|
MAX_DEPT = 5 # Le maximum de départements qu'il est possible de sélectionner
|
||||||
MAX_LOG_DAYS = 30 # Le nombre de jours pendant lesquels les logs sont conservés
|
MAX_LOG_DAYS = 30 # Le nombre de jours pendant lesquels les logs sont conservés
|
||||||
MAX_LOG_DEPT = 3 # Le nombre maximum affiché de départements qui ont été le plus cherché
|
MAX_LOG_DEPT = 5 # Le nombre maximum affiché de départements qui ont été le plus cherché
|
||||||
|
MAX_LOG_FAVS = 10 # Le nombre maximum affiché de salles qui ont été le plus mises en favoris
|
||||||
PING_WARN = 500 # Nombre d'utilisations à partir du quel un message d'avertissement est affiché
|
PING_WARN = 500 # Nombre d'utilisations à partir du quel un message d'avertissement est affiché
|
||||||
|
LOG_FILE = "log.json" # Contient des stats sur les salles les plus mises en favoris, et les départements
|
||||||
GLOBAL_CONTEXT = {} # Contexte constant pour les templates Jinja
|
GLOBAL_CONTEXT = {} # Contexte constant pour les templates Jinja
|
||||||
GLOBAL_CONTEXT["SOURCE"] = "https://forge.chapril.org/Wantoo/UniSquat_Python" # Le lien du code source
|
GLOBAL_CONTEXT["SOURCE"] = "https://forge.chapril.org/Wantoo/UniSquat_Python" # Le lien du code source
|
||||||
GLOBAL_CONTEXT["CREDITSLINK"] = "https://forge.chapril.org/Wantoo" # Le lien de l'organisation
|
GLOBAL_CONTEXT["CREDITSLINK"] = "https://forge.chapril.org/Wantoo" # Le lien de l'organisation
|
||||||
|
@ -38,12 +42,18 @@ GLOBAL_CONTEXT["DEBUG"] = False # Fait en sorte que le logiciel soit un peu plus
|
||||||
GLOBAL_CONTEXT["DOMAIN"] = "https://unisquat.alwaysdata.net" # Le domaine sur lequel est host l'instance
|
GLOBAL_CONTEXT["DOMAIN"] = "https://unisquat.alwaysdata.net" # Le domaine sur lequel est host l'instance
|
||||||
|
|
||||||
# Globales
|
# Globales
|
||||||
logs = [] # Stoque les différentes requêtes faite sur la route /free_rooms/, sous la forme {"timestamp":timestamp,"depts":[]}
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
logs = [] # Stoque les différentes requêtes faite sur la route /free_rooms/, sous la forme {"timestamp":timestamp,"depts":[]}
|
||||||
|
if os.path.isfile(LOG_FILE):
|
||||||
|
with open(LOG_FILE,"r") as f:
|
||||||
|
logs = json.loads(f.read())
|
||||||
|
|
||||||
# Fonctions :
|
# Fonctions :
|
||||||
|
def save_logs(logs):
|
||||||
|
with open(LOG_FILE,"w") as f:
|
||||||
|
f.write(json.dumps(logs))
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def home() :
|
def home() :
|
||||||
|
@ -101,18 +111,32 @@ def stats():
|
||||||
# Compte le nombre de fois que les différents départements ont été cherchés
|
# Compte le nombre de fois que les différents départements ont été cherchés
|
||||||
pings = 0
|
pings = 0
|
||||||
counts = {}
|
counts = {}
|
||||||
|
counts_favs = {}
|
||||||
|
def fmap(fav):
|
||||||
|
return fav[0]+";"+fav[1]
|
||||||
for log in logs:
|
for log in logs:
|
||||||
|
if log["type"]=="deptcount":
|
||||||
for dept in log["depts"]:
|
for dept in log["depts"]:
|
||||||
pings+=1
|
pings+=1
|
||||||
if dept.name in counts.keys():
|
if dept in counts.keys():
|
||||||
counts[dept.name]+=1
|
counts[dept]+=1
|
||||||
else:
|
else:
|
||||||
counts[dept.name]=1
|
counts[dept]=1
|
||||||
|
elif log["type"]=="favs":
|
||||||
|
for fav in log["favs"]:
|
||||||
|
if fmap(fav) in counts_favs.keys():
|
||||||
|
counts_favs[fmap(fav)][2] += 1
|
||||||
|
else:
|
||||||
|
fav.append(1)
|
||||||
|
counts_favs[fmap(fav)]=fav
|
||||||
|
|
||||||
sort = [ [x,counts[x]] for x in counts.keys() ]
|
sort = [ [x,counts[x]] for x in counts.keys() ]
|
||||||
sort.sort(key = lambda x: x[1],reverse = True ) # Trie selon la valeur du deuxieme élément de la liste
|
sort.sort(key = lambda x: x[1],reverse = True ) # Trie selon la valeur du deuxieme élément de la liste
|
||||||
|
|
||||||
context = {"MAX_LOG_DAYS":MAX_LOG_DAYS,"PING_WARN":PING_WARN,"depts":sort[:MAX_LOG_DEPT],"nbping":pings}
|
sort_favs = [ counts_favs[x] for x in counts_favs.keys() ]
|
||||||
|
sort_favs.sort(key = lambda x: x[2],reverse = True )
|
||||||
|
|
||||||
|
context = {"MAX_LOG_DAYS":MAX_LOG_DAYS,"PING_WARN":PING_WARN,"depts":sort[:MAX_LOG_DEPT],"favs":sort_favs[:MAX_LOG_FAVS],"nbping":pings}
|
||||||
return render_template("stats.html",**context, **GLOBAL_CONTEXT)
|
return render_template("stats.html",**context, **GLOBAL_CONTEXT)
|
||||||
|
|
||||||
|
|
||||||
|
@ -274,15 +298,28 @@ def free_rooms() :
|
||||||
"favs":len(favs_ids)>0,"nofavslink":nofavslink}
|
"favs":len(favs_ids)>0,"nofavslink":nofavslink}
|
||||||
|
|
||||||
# Création d'un log de la date et des départements demandés (pour les stats du site) :
|
# Création d'un log de la date et des départements demandés (pour les stats du site) :
|
||||||
|
ctimestamp = dti.datetime.now().timestamp()
|
||||||
log = {}
|
log = {}
|
||||||
log["timestamp"] = dti.datetime.now().timestamp()
|
log["timestamp"] = ctimestamp
|
||||||
log["depts"] = depts
|
log["depts"] = [ x.name for x in depts ] # Liste les noms de départements
|
||||||
|
log["type"] = "deptcount" # Type du log
|
||||||
|
logs.append(log)
|
||||||
|
# Création d'un log de la date et des salles favorites
|
||||||
|
favs = favs_soon_rooms+favs_free_rooms
|
||||||
|
if len(favs)>0:
|
||||||
|
log = {}
|
||||||
|
log["timestamp"] = ctimestamp
|
||||||
|
log["favs"] = [ [x.name,x.dept_name] for x in favs] # Liste les noms des salles favorites
|
||||||
|
log["type"] = "favs" # Type du log
|
||||||
logs.append(log)
|
logs.append(log)
|
||||||
|
|
||||||
# Suppression des logs vieux de MAX_LOG_DAYS :
|
# Suppression des logs vieux de MAX_LOG_DAYS :
|
||||||
while (log["timestamp"] - logs[0]["timestamp"]) / (60*60*24) > MAX_LOG_DAYS :
|
while (ctimestamp - logs[0]["timestamp"]) / (60*60*24) > MAX_LOG_DAYS :
|
||||||
del(logs[0])
|
del(logs[0])
|
||||||
|
|
||||||
|
# Sauvegarde les logs dans un fichier cache
|
||||||
|
save_logs(logs)
|
||||||
|
|
||||||
url_for("static", filename="style.css")
|
url_for("static", filename="style.css")
|
||||||
return render_template("free-rooms.html", **context, **GLOBAL_CONTEXT)
|
return render_template("free-rooms.html", **context, **GLOBAL_CONTEXT)
|
||||||
|
|
||||||
|
|
|
@ -49,13 +49,17 @@ class Room :
|
||||||
|
|
||||||
id : string
|
id : string
|
||||||
Identifiant 'unique' (avec un très faible risque de conflit) de la salle (généré à partir de son nom)
|
Identifiant 'unique' (avec un très faible risque de conflit) de la salle (généré à partir de son nom)
|
||||||
|
|
||||||
|
dept_name : string
|
||||||
|
Le nom du département auquel la salle appartient
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, start, end, is_free) :
|
def __init__(self, name, start, end, is_free, dept_name="DEFAULT DEPT") :
|
||||||
self.name = name
|
self.name = name
|
||||||
self.start = start
|
self.start = start
|
||||||
self.end = end
|
self.end = end
|
||||||
self.is_free = is_free
|
self.is_free = is_free
|
||||||
self.id = self.getId(name)
|
self.id = self.getId(name)
|
||||||
|
self.dept_name = dept_name
|
||||||
|
|
||||||
def getId(self,name):
|
def getId(self,name):
|
||||||
random.seed(name)
|
random.seed(name)
|
||||||
|
|
|
@ -241,6 +241,7 @@ def get_tot_rooms(datet, depts, ignore_list) :
|
||||||
roomnames = [] # Contient le nom de toutes les salles indiquées dans la section "LOCATION"
|
roomnames = [] # Contient le nom de toutes les salles indiquées dans la section "LOCATION"
|
||||||
|
|
||||||
# Parcours de ces calendriers, pour faire la liste de toutes les salles :
|
# Parcours de ces calendriers, pour faire la liste de toutes les salles :
|
||||||
|
dept_index = 0
|
||||||
for cal in cals :
|
for cal in cals :
|
||||||
for comp in cal.walk() : # Événements
|
for comp in cal.walk() : # Événements
|
||||||
if comp.name == "VEVENT" :
|
if comp.name == "VEVENT" :
|
||||||
|
@ -268,7 +269,8 @@ def get_tot_rooms(datet, depts, ignore_list) :
|
||||||
start = start.astimezone(pytz.timezone('Europe/Paris'))
|
start = start.astimezone(pytz.timezone('Europe/Paris'))
|
||||||
end = end.astimezone(pytz.timezone('Europe/Paris'))
|
end = end.astimezone(pytz.timezone('Europe/Paris'))
|
||||||
|
|
||||||
total_rooms.append(Room(rname, start, end, is_free))
|
total_rooms.append(Room(rname, start, end, is_free, depts[dept_index].name))
|
||||||
|
dept_index += 1
|
||||||
|
|
||||||
return total_rooms
|
return total_rooms
|
||||||
|
|
||||||
|
|
|
@ -9,18 +9,26 @@
|
||||||
<body>
|
<body>
|
||||||
{% include "base.html" %}
|
{% include "base.html" %}
|
||||||
<main>
|
<main>
|
||||||
<h1>Statistiques d'utilisation du site</h1>
|
<h1><span aria-hidden="true">🔢 </span>Statistiques d'utilisation du site</h1>
|
||||||
<p>Ces {{MAX_LOG_DAYS}} derniers jours, des salles ont été recherchées {{nbping}} fois.</p>
|
<p>Ces {{MAX_LOG_DAYS}} derniers jours, des salles ont été recherchées {{nbping}} fois.</p>
|
||||||
{% if nbping>PING_WARN %}
|
{% if nbping>PING_WARN %}
|
||||||
<p>⚠ Ce site commence a être <strong>surchargé</strong> ! N'hésitez pas à héberger votre propre instance d'UniSquat :) <a href="https://forge.chapril.org/Wantoo/UniSquat_Python">En savoir plus</a></p>
|
<p>⚠ Ce site commence a être <strong>surchargé</strong> ! N'hésitez pas à héberger votre propre instance d'UniSquat :) <a href="https://forge.chapril.org/Wantoo/UniSquat_Python">En savoir plus</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if depts != [] : %}
|
{% if depts != [] : %}
|
||||||
<h1>Départements les plus recherchés</h1>
|
<h1><span aria-hidden="true">🏫 </span>Départements les plus recherchés</h1>
|
||||||
<ul>
|
<ul>
|
||||||
{% for dept in depts: %}
|
{% for dept in depts: %}
|
||||||
<li><strong>{{ dept[0] }}</strong> (recherché {{dept[1]}} fois)</li>
|
<li><strong>{{ dept[0] }}</strong> (recherché {{dept[1]}} fois)</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% if favs != [] : %}
|
||||||
|
<h1><span aria-hidden="true">⭐ </span>Salles préférées des utilisateurices</h1>
|
||||||
|
<ul>
|
||||||
|
{% for fav in favs: %}
|
||||||
|
<li><strong>{{ fav[0] }}</strong> ({{fav[1]}}, recherchée {{fav[2]}} fois)</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</main>
|
</main>
|
||||||
{% include "footer.html" %}
|
{% include "footer.html" %}
|
||||||
|
|
Loading…
Reference in New Issue