UniSquat_Python/app.py

287 lines
8.3 KiB
Python
Raw Normal View History

################
### UniSquat ###
################
"""
Indique toutes les salles disponibles dans les différents départements de
l'Université de Strasbourg.
"""
### Fichier de l'interface Web Flask ###
# Modules :
import datetime as dti
import time
from flask import Flask
from flask import render_template
from flask import url_for
from flask import request
# Fichiers locaux :
import date_tools
import rooms_get as ro
# Constantes :
MAX_DEPT = 5 # Le maximum de départements qu'il est possible de sélectionner
2022-06-13 22:49:31 +02:00
MAX_LOG_DAYS = 30 # Le nombre de jours pendant lesquels les logs sont conservés
2022-06-14 11:53:17 +02:00
MAX_LOG_DEPT = 3 # Le nombre maximum affiché de départements qui ont été le plus cherché
2022-06-14 16:47:57 +02:00
PING_WARN = 500 # Nombre d'utilisations à partir du quel un message d'avertissement est affiché
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["CREDITSLINK"] = "https://forge.chapril.org/Wantoo" # Le lien de l'organisation
GLOBAL_CONTEXT["CREDITSNAME"] = "Wantoo" # Le nom de l'organisation
2022-06-15 13:52:16 +02:00
GLOBAL_CONTEXT["DEBUG"] = True # Fait en sorte que le logiciel soit un peu plus expressif
2022-06-13 22:49:31 +02:00
# Globales
logs = [] # Stoque les différentes requêtes faite sur la route /free_rooms/, sous la forme {"timestamp":timestamp,"depts":[]}
app = Flask(__name__)
@app.route("/")
def home() :
"""
Page d'accueil du site Web.
Parameters
----------
None.
Returns
-------
flask.render_template
"""
return render_template("index.html", **GLOBAL_CONTEXT)
@app.route("/app")
def select_dept() :
"""
Permet de sélectionner un ou plusieurs départements dans lesquels
chercher des salles libres.
Parameters
----------
None.
Returns
-------
flask.render_template
"""
dept_filen = "data/dept_list.txt"
dept_list = ro.get_depts(dept_filen)
content = {"dept_list":dept_list}
url_for("static", filename="style.css")
return render_template("dept-select.html", **content, **GLOBAL_CONTEXT)
2022-06-14 11:53:17 +02:00
@app.route("/stats")
def stats():
"""
Statistiques d'utilisation de l'instance
Parameters
----------
None. (Reads from the global "logs")
Returns
-------
flask.render_template
"""
# Compte le nombre de fois que les différents départements ont été cherché
pings = 0
counts = {}
for log in logs:
for dept in log["depts"]:
pings+=1
if dept.name in counts.keys():
counts[dept.name]+=1
else:
counts[dept.name]=1
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
context = {"MAX_LOG_DAYS":MAX_LOG_DAYS,"PING_WARN":PING_WARN,"depts":sort[:MAX_LOG_DEPT],"nbping":pings}
return render_template("stats.html",**context, **GLOBAL_CONTEXT)
2022-06-14 11:53:17 +02:00
@app.route("/app/free-rooms", methods=["POST", "GET"])
def free_rooms() :
"""
Affiche les salles libres dans les départements sélectionnés
dans la page précédente.
Parameters
----------
None.
Returns
-------
flask.render_template
"""
# Récupération des ID des départements depuis le formulaire :
dident_list = request.args.getlist("dept")
if len(dident_list)>MAX_DEPT:
return render_template("error.html", error="Trop de départements sélectionnés ! Vous pouvez en sélectionner "+str(MAX_DEPT)+" au maximum.")
if len(dident_list)==0:
return render_template("error.html", error="Il faut choisir au moins un département !")
# Récupération de l'éventuelle date personnalisée (depuis la page de sélection de date :
date_uf = request.args.get("date")
if date_uf == None :
date_uf = [""]
else :
date_uf = date_uf.split("-")
time_uf = request.args.get("time")
if time_uf == None :
time_uf = [""]
else :
time_uf = time_uf.split(":")
2022-06-15 13:52:16 +02:00
# Récupére les IDs des salles favorites
2022-06-15 21:48:25 +02:00
favs_ids = request.args.getlist("favs")
2022-06-15 13:52:16 +02:00
if favs_ids==None:
favs_ids = []
date = dti.datetime.now()
date_str = "" # Date affichée sur la page (si personnalisée)
if date_uf != [""] :
date = date.replace(year = int(date_uf[0]), month = int(date_uf[1]), day = int(date_uf[2]))
date_str += date_uf[2] + "/" + date_uf[1] + "/" + date_uf[0]
if time_uf != [""] :
date = date.replace(hour = int(time_uf[0]), minute = int(time_uf[1]))
date_str += ", à " + time_uf[0] + ":" + time_uf[1]
# Récupération de la liste des départements :
dept_filen = "data/dept_list.txt"
dept_list = ro.get_depts(dept_filen)
# Vérifie qu'il n'y a pas de mauvais départements demandés
for d in dident_list:
try:
int(d)
except:
return render_template("error.html",error="Identifiant de département invalide !", **GLOBAL_CONTEXT)
if int(d)<0 or int(d)>=len(dept_list):
return render_template("error.html",error="Identifiant de département invalide !", **GLOBAL_CONTEXT)
dident_list.sort()
# Récupération des départements choisis à partir des données du formulaire :
i = 0
depts = list()
depts_str = "" # Noms des départements pour l'affichage
for d in dept_list :
if i < len(dident_list) and d.ident == int(dident_list[i]) :
depts.append(d)
depts_str += d.name
if (i + 1) < len(dident_list) :
depts_str += ", "
i += 1
ignore_list = ["salle non définie", "salle en Distanciel"]
free_rooms = ro.getrooms(date, depts, ignore_list)
frooms_disp = dict() # Mise en forme des infos pour la page Web
i = 0
for r in free_rooms :
remain_time_str = ""
if r.is_free :
remain_time_str = date_tools.remain_time(date, r.end)
else :
remain_time_str = date_tools.remain_time(date, r.start)
frooms_disp[r.name] = {"start":date_tools.hour_disp(r.start),
"end":date_tools.hour_disp(r.end),
"rtime":remain_time_str}
2022-06-15 13:52:16 +02:00
2022-05-14 21:24:14 +02:00
change_date_str = "?"
i = 0
for v in dident_list:
change_date_str += "dept="+str(v)
if i<len(dident_list)-1:
change_date_str += "&"
i+=1
2022-06-15 20:23:53 +02:00
# Générer le lien pour enlever les favoris séléctionnés
nofavslink = "/app/free-rooms?"
for dept in dident_list:
nofavslink+="dept="+str(dept)+"&"
nofavslink = nofavslink[:-1] # Enlever le dernier &
# Trier les salles selon leurs catégories
favs_free_rooms = []
favs_soon_rooms = []
soon_rooms = []
final_rooms = []
for r in free_rooms:
[[soon_rooms,final_rooms],[favs_soon_rooms,favs_free_rooms]][r.id in favs_ids][r.is_free].append(r)
context = {"favs_free_rooms":favs_free_rooms, "favs_soon_rooms":favs_soon_rooms, "free_rooms":final_rooms, "soon_rooms":soon_rooms, "frooms_disp":frooms_disp, "depts_str":depts_str, "dident_list":dident_list, "date_str":date_str, "change_date_str":change_date_str, "favs":len(favs_ids)>0,"nofavslink":nofavslink}
2022-06-13 22:49:31 +02:00
# Crée un log de la date et des départements demandés ( pour des futures statistiques )
log = {}
log["timestamp"] = dti.datetime.now().timestamp()
log["depts"] = depts
logs.append(log)
# Vide les logs vieux de MAX_LOG_DAYS
while (log["timestamp"]-logs[0]["timestamp"])/(60*60*24)>MAX_LOG_DAYS:
del(logs[0])
url_for("static", filename="style.css")
return render_template("free-rooms.html", **context, **GLOBAL_CONTEXT)
2022-05-12 17:58:06 +02:00
@app.route("/app/date-select", methods=["POST", "GET"])
2022-05-12 17:58:06 +02:00
def date_select() :
"""
Permet de sélectionner une date à laquelle
chercher des salles libres.
Parameters
----------
None.
Returns
-------
flask.render_template
"""
dident_list = request.args.getlist("dept")
context = {"dident_list":dident_list}
return render_template("date-select.html", **context, **GLOBAL_CONTEXT)
2022-05-13 15:17:23 +02:00
2022-05-13 15:17:23 +02:00
@app.errorhandler(404)
def error(e):
"""
Affiche la page d'erreur
Parameters
----------
None.
Returns
-------
flask.render_template
"""
return render_template("error.html", error="Page non trouvée !", **GLOBAL_CONTEXT)