diff options
-rw-r--r-- | app.py | 64 | ||||
-rw-r--r-- | config.py | 24 | ||||
-rw-r--r-- | data_textes.py | 22 | ||||
-rw-r--r-- | gere_erreurs.py | 37 | ||||
-rw-r--r-- | gere_grille.py | 101 | ||||
-rw-r--r-- | static/outilspage.js | 153 | ||||
-rw-r--r-- | static/style.css | 38 | ||||
-rw-r--r-- | templates/base.html | 31 | ||||
-rw-r--r-- | templates/custom.html | 35 | ||||
-rw-r--r-- | templates/faq.html | 30 | ||||
-rw-r--r-- | templates/index.html | 42 |
11 files changed, 577 insertions, 0 deletions
@@ -0,0 +1,64 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # -*- coding: utf-8 -*- | ||
3 | """ | ||
4 | Created on Mon Jul 26 17:31:48 2021 | ||
5 | |||
6 | @author: sekhmet | ||
7 | """ | ||
8 | |||
9 | #!/usr/bin/env python3 | ||
10 | # -*- coding: utf-8 -*- | ||
11 | |||
12 | import flask | ||
13 | from data_textes import liste_textes | ||
14 | import gere_grille as g | ||
15 | import gere_erreurs as e | ||
16 | from config import DEFAUT, CONFIG | ||
17 | |||
18 | |||
19 | def initialise_mode_beta(): | ||
20 | global beta | ||
21 | hote = flask.request.host | ||
22 | if hote[:4] == "beta": | ||
23 | print("** Mode bêta !**") | ||
24 | return True | ||
25 | else: | ||
26 | return False | ||
27 | |||
28 | |||
29 | app = flask.Flask(__name__) | ||
30 | |||
31 | |||
32 | @app.route('/', methods=["GET", "POST"]) | ||
33 | def index(): | ||
34 | liste_err = e.initialise_erreurs() | ||
35 | idg = flask.request.args.get("grille", "") # Id de grille passée en param (ou pas) | ||
36 | if idg != "": # Si on a mis un url de grille | ||
37 | conf = g.decode_grille(idg, liste_err) | ||
38 | if conf == {}: # Erreur à la génération | ||
39 | bingo = g.genere_grille(DEFAUT, liste_textes) | ||
40 | conf = DEFAUT.copy() | ||
41 | e.erreur("L'url de la grille n'est pas valide...", liste_err) | ||
42 | else: | ||
43 | bingo=conf["grille"] | ||
44 | else: | ||
45 | # On récupère les données post (et ça sera défaut si y'a rien) | ||
46 | if flask.request.method == "POST": | ||
47 | conf = g.gere_donnees_custom(flask.request.form, liste_err) | ||
48 | else: | ||
49 | conf= DEFAUT.copy() | ||
50 | bingo = g.genere_grille(conf, liste_textes) # aléatoire | ||
51 | |||
52 | chainecode = g.encode_grille(conf, bingo, liste_err) | ||
53 | |||
54 | return flask.render_template("index.html", bingo=bingo, chainecode=chainecode, conf=conf, e=liste_err[0]+liste_err[1]+liste_err[2]) | ||
55 | |||
56 | |||
57 | @app.route('/custom') | ||
58 | def custom(): | ||
59 | liste_err = e.initialise_erreurs() | ||
60 | return flask.render_template("custom.html", DEFAUT=DEFAUT,CONFIG=CONFIG, e=liste_err[0]+liste_err[1]+liste_err[2]) | ||
61 | |||
62 | if __name__ == "__main__": | ||
63 | # print("Mode debug maison : "+str(niveau_debug)) | ||
64 | app.run(host='0.0.0.0',debug=True) \ No newline at end of file | ||
diff --git a/config.py b/config.py new file mode 100644 index 0000000..deb461a --- /dev/null +++ b/config.py | |||
@@ -0,0 +1,24 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # -*- coding: utf-8 -*- | ||
3 | """ | ||
4 | Configuration générale | ||
5 | """ | ||
6 | |||
7 | # Configuration par défaut | ||
8 | DEFAUT = {} | ||
9 | |||
10 | DEFAUT["titre"] = "Le bingo de l'allaitement" | ||
11 | |||
12 | DEFAUT["nblignes"] = 4 | ||
13 | DEFAUT["nbcolonnes"] = 3 | ||
14 | DEFAUT["nbcasesvides"] = 0 | ||
15 | |||
16 | |||
17 | # Configuration | ||
18 | |||
19 | CONFIG = {} | ||
20 | CONFIG["lmax_titre"] = 50 | ||
21 | CONFIG["maxlignes"] = 20 | ||
22 | CONFIG["minlignes"] = 1 | ||
23 | CONFIG["maxcolonnes"] = 20 | ||
24 | CONFIG["mincolonnes"] = 1 \ No newline at end of file | ||
diff --git a/data_textes.py b/data_textes.py new file mode 100644 index 0000000..8082ecf --- /dev/null +++ b/data_textes.py | |||
@@ -0,0 +1,22 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # -*- coding: utf-8 -*- | ||
3 | """ | ||
4 | Created on Mon Jul 26 22:50:08 2021 | ||
5 | |||
6 | @author: sekhmet | ||
7 | """ | ||
8 | |||
9 | liste_textes = [ | ||
10 | "Tu vas pas l'allaiter jusqu'à [âge quelconque] !", | ||
11 | "Tu es sûre que tu as assez de lait ?", | ||
12 | "Quand est-ce que tu vas lui donner du lait normal ?", | ||
13 | "Il/elle fait ses nuits ?", | ||
14 | "Il/elle dort encore avec vous ?", | ||
15 | "Laisse le/la pleurer il/elle finira bien par dormir (et/ou ça lui fera les poumons).", | ||
16 | "Ton lait n'est pas/plus assez nourrissant.", | ||
17 | "Il/elle doit apprendre à se détacher de maman.", | ||
18 | "Tu as pris combien de kilos ?", | ||
19 | "Donne lui un biberon, il/elle fera ses nuits.", | ||
20 | "Tu arrêteras quand il/elle aura des dents, puisqu'il/elle va te mordre", | ||
21 | |||
22 | ] \ No newline at end of file | ||
diff --git a/gere_erreurs.py b/gere_erreurs.py new file mode 100644 index 0000000..0a12018 --- /dev/null +++ b/gere_erreurs.py | |||
@@ -0,0 +1,37 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # -*- coding: utf-8 -*- | ||
3 | """ | ||
4 | Created on Tue Jul 27 11:16:54 2021 | ||
5 | |||
6 | @author: sekhmet | ||
7 | """ | ||
8 | |||
9 | ## Gestion des erreurs en flask | ||
10 | import sys | ||
11 | |||
12 | niveau_debug = ("debug" in sys.argv) | ||
13 | |||
14 | def initialise_erreurs(): | ||
15 | """ retourne trois listes vides, erreurs fatales (0), warnings(1), debug(2):""" | ||
16 | return ([],[],[]) | ||
17 | |||
18 | |||
19 | def erreur(message,listeerreurs): | ||
20 | """ en cas d'erreur où on ne peut pas continuer | ||
21 | message est une chaîne""" | ||
22 | print("** Erreur fatale : "+message) | ||
23 | listeerreurs[0].append("** Erreur : "+message) | ||
24 | |||
25 | def warning(message,listeerreurs): | ||
26 | """ En cas d'avertissement mais on peut quand même continuer """ | ||
27 | print("** Warning : "+message) | ||
28 | message = "Alerte : "+message | ||
29 | if message not in listeerreurs[1]: | ||
30 | listeerreurs[1].append(message) | ||
31 | |||
32 | def debug(message,listeerreurs): | ||
33 | global niveau_debug | ||
34 | if niveau_debug: | ||
35 | print("##Debug : "+message) | ||
36 | listeerreurs[2].append("# Debug : "+message) | ||
37 | \ No newline at end of file | ||
diff --git a/gere_grille.py b/gere_grille.py new file mode 100644 index 0000000..9a472ed --- /dev/null +++ b/gere_grille.py | |||
@@ -0,0 +1,101 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # -*- coding: utf-8 -*- | ||
3 | """ | ||
4 | Created on Mon Jul 26 22:58:28 2021 | ||
5 | |||
6 | @author: sekhmet | ||
7 | """ | ||
8 | import random | ||
9 | import zlib, base64, json | ||
10 | import gere_erreurs as e | ||
11 | from config import DEFAUT, CONFIG | ||
12 | |||
13 | def genere_grille(config, textes): | ||
14 | """ génère une grille avec des éléments aléatoires du tableau textes. Si y'a pas assez, on complète aléatoirement avec des 0. | ||
15 | config contient tout ce qu'on veut pour la grille""" | ||
16 | |||
17 | nblignes, nbcol = config["nblignes"], config["nbcolonnes"] | ||
18 | |||
19 | # Créer la grille | ||
20 | grille = [ [""]*nbcol for i in range(nblignes)] | ||
21 | |||
22 | nbdata = nbcol*nblignes - config["nbcasesvides"] # Nombre d'entrées | ||
23 | |||
24 | # Créer le sous-tableau | ||
25 | if len(textes)>= nbdata: # Si y'a assez de textes | ||
26 | soustab = random.sample(textes, nbdata) + ["0"]*config["nbcasesvides"] | ||
27 | else: | ||
28 | # On met tous les textes + complète avec des "0" | ||
29 | soustab = textes + ["0"]*(nbcol*nblignes - len(textes)) | ||
30 | random.shuffle(soustab) | ||
31 | #print(soustab) | ||
32 | |||
33 | # On met tout ça dans la grille | ||
34 | for i in range(nblignes): | ||
35 | for j in range(nbcol): | ||
36 | grille[i][j] = soustab[i*nbcol+j] | ||
37 | |||
38 | return grille | ||
39 | |||
40 | def encode_grille(config, grille, liste_err): | ||
41 | """ grille est un tableau double qu'on veut sauvegarder. | ||
42 | config est la configuration (on va garder le titre avec) | ||
43 | Renvoie une chaîne de caractères qui encode cette grille | ||
44 | de manière condensée. Renvoie une chaîne cheloue""" | ||
45 | # Chaîne de caractère | ||
46 | data = {"titre": config["titre"], "grille": grille} | ||
47 | chaine = json.dumps(data) | ||
48 | code = zlib.compress(chaine.encode()) | ||
49 | chaineencodee = str(base64.urlsafe_b64encode(code)) | ||
50 | e.debug(chaineencodee, liste_err) | ||
51 | return chaineencodee[2:-1] # Enlever le b' devant et le ' à la fin | ||
52 | |||
53 | def decode_grille(chaineencodee, liste_err): | ||
54 | """ l'inverse de la fonction précédente : renvoie le dictionnaire | ||
55 | avec les params et la grille reconstituée | ||
56 | """ | ||
57 | e.debug(chaineencodee, liste_err) | ||
58 | b2 = base64.urlsafe_b64decode(chaineencodee) | ||
59 | try: | ||
60 | decodee = zlib.decompress(b2) | ||
61 | except: | ||
62 | e.erreur("Impossible de décoder la chaîne : "+chaineencodee, liste_err) | ||
63 | return {} | ||
64 | # Remettre ça en python | ||
65 | data = json.loads(decodee) | ||
66 | return data | ||
67 | |||
68 | ########################### | ||
69 | |||
70 | def gere_donnees_custom(data, liste_err): | ||
71 | """ data est le dictionnaire de requête. Gère les données reçues | ||
72 | et en fait un dictionnaire propre, en mettant les défauts là où | ||
73 | c'est pas bon""" | ||
74 | |||
75 | conf =DEFAUT.copy() | ||
76 | |||
77 | ## Le titre | ||
78 | t = data.get("titre", "") | ||
79 | if len(t) > 0: | ||
80 | conf["titre"] = t[0:CONFIG["lmax_titre"]] | ||
81 | |||
82 | # Les dimensions | ||
83 | conf["nblignes"] = minimaxi(data.get("nblignes",""), CONFIG["minlignes"], CONFIG["maxlignes"], DEFAUT["nblignes"], liste_err) | ||
84 | conf["nbcolonnes"] = minimaxi(data.get("nbcolonnes",""), CONFIG["mincolonnes"], CONFIG["maxcolonnes"], DEFAUT["nbcolonnes"], liste_err) | ||
85 | |||
86 | # Les cases vides | ||
87 | conf["nbcasesvides"] = minimaxi(data.get("nbcasesvides",""), 0, CONFIG["maxlignes"]*CONFIG["maxcolonnes"], DEFAUT["nbcasesvides"], liste_err) | ||
88 | |||
89 | return conf | ||
90 | ### | ||
91 | def minimaxi(donnee, mini, maxi, defaut, liste_err): | ||
92 | """ donnee est une chaine qui est censée être un nombre entier. | ||
93 | On vérifie que la donnée est valide, qu'elle est bien dans l'inter | ||
94 | valle mini, maxi et si ça foire on met le défaut""" | ||
95 | try: | ||
96 | x = int(donnee) | ||
97 | except: | ||
98 | e.warning("La donnée "+donnee+ "est invalide !", liste_err) | ||
99 | x = defaut | ||
100 | x = max(mini, min(x, maxi)) | ||
101 | return x \ No newline at end of file | ||
diff --git a/static/outilspage.js b/static/outilspage.js new file mode 100644 index 0000000..b8db8b3 --- /dev/null +++ b/static/outilspage.js | |||
@@ -0,0 +1,153 @@ | |||
1 | /* Calcul des scores */ | ||
2 | var points_par_case = 1 ; | ||
3 | var points_par_ligne = 10 ; | ||
4 | |||
5 | |||
6 | |||
7 | // Couleurs des cases | ||
8 | var couleur_base = "rgb(238, 238, 238)" ; | ||
9 | var couleur_valide = 'rgb(255, 136, 136)' ; | ||
10 | |||
11 | |||
12 | // Valide la case et la colore en rouge | ||
13 | function validecase(elem) { | ||
14 | elem.style.backgroundColor = couleur_valide ; | ||
15 | |||
16 | detectelignes() ; | ||
17 | } | ||
18 | |||
19 | // efface la grille | ||
20 | function effacegrille() { | ||
21 | var table=document.getElementById("grille") ; | ||
22 | var listetd = table.getElementsByTagName("td") ; | ||
23 | for (var i=0; i< listetd.length; i++){ | ||
24 | listetd[i].style.backgroundColor = couleur_base ; | ||
25 | } | ||
26 | metscore(0) ; | ||
27 | } | ||
28 | |||
29 | // mettre à jour le score si on veut | ||
30 | function metscore(score) { | ||
31 | document.getElementById("score").innerHTML = score ; | ||
32 | } | ||
33 | |||
34 | // Compte les lignes, colonnes et diagonales de la grille et met à jour le score | ||
35 | function detectelignes(elem) { | ||
36 | var table=document.getElementById("grille") ; | ||
37 | var listelignes = table.getElementsByTagName("tr") ; | ||
38 | var nblignes = listelignes.length ; | ||
39 | var nbcolonnes = listelignes[0].children.length ; | ||
40 | var i, j ; | ||
41 | |||
42 | // lignes | ||
43 | var nb_lignes_completes = 0 ; | ||
44 | var remplie ; | ||
45 | for(i=0; i<nblignes; i++) { | ||
46 | remplie = true ; | ||
47 | for(j=0; j<nbcolonnes; j++) { | ||
48 | //alert(j) ; | ||
49 | //alert(listelignes[i].children[j].style.backgroundColor) ; | ||
50 | if(listelignes[i].children[j].style.backgroundColor != couleur_valide) { | ||
51 | // c'est pas une ligne, dommage | ||
52 | remplie = false ; | ||
53 | //alert("la ligne "+i+"n'est pas remplie, vu à la colonne "+j) ; | ||
54 | break | ||
55 | } | ||
56 | } | ||
57 | if(remplie) { | ||
58 | nb_lignes_completes+=1 ; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | // Colonnes | ||
63 | var nb_colonnes_completes = 0 ; | ||
64 | for(j=0; j<nbcolonnes; j++) { | ||
65 | remplie = true ; | ||
66 | for (i=0; i<nblignes; i++) { | ||
67 | if(listelignes[i].children[j].style.backgroundColor != couleur_valide) { | ||
68 | // c'est pas une colonne, dommage | ||
69 | remplie = false ; | ||
70 | break | ||
71 | } | ||
72 | } | ||
73 | if (remplie) { | ||
74 | nb_colonnes_completes+=1 ; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | // Diagonales. | ||
79 | var nb_diagonales_1 = 0 ; | ||
80 | var nb_diagonales_2 = 0 ; | ||
81 | if(nblignes <= nbcolonnes) { | ||
82 | // Les diagonales se comptent horizontalement : "\\\" et "///" | ||
83 | for(i=0; i<nbcolonnes - nblignes +1; i++) { | ||
84 | // diagonales "\" | ||
85 | remplie=true ; | ||
86 | for(j=0; j<nblignes; j++) { | ||
87 | if(listelignes[j].children[i+j].style.backgroundColor != couleur_valide) { | ||
88 | remplie = false | ||
89 | break | ||
90 | } | ||
91 | } | ||
92 | if (remplie) { | ||
93 | nb_diagonales_1+=1 | ||
94 | } | ||
95 | |||
96 | // diagonales "/" | ||
97 | remplie=true ; | ||
98 | for(j=0; j<nblignes; j++) { | ||
99 | if(listelignes[j].children[nbcolonnes-i-j-1].style.backgroundColor != couleur_valide) { | ||
100 | remplie = false | ||
101 | break | ||
102 | } | ||
103 | } | ||
104 | if (remplie) { | ||
105 | nb_diagonales_2+=1 | ||
106 | } | ||
107 | } | ||
108 | |||
109 | } else { // les diagonales vont se compter "verticalement" | ||
110 | for(i=0; i<nblignes - nbcolonnes +1; i++) { | ||
111 | // diagonales "\" | ||
112 | remplie=true ; | ||
113 | for(j=0; j<nbcolonnes; j++) { | ||
114 | if(listelignes[i+j].children[j].style.backgroundColor != couleur_valide) { | ||
115 | remplie = false | ||
116 | break | ||
117 | } | ||
118 | } | ||
119 | if (remplie) { | ||
120 | nb_diagonales_1+=1 | ||
121 | } | ||
122 | |||
123 | // diagonales "/" | ||
124 | remplie=true ; | ||
125 | for(j=0; j<nbcolonnes; j++) { | ||
126 | if(listelignes[nblignes -i-j-1].children[j].style.backgroundColor != couleur_valide) { | ||
127 | remplie = false | ||
128 | break | ||
129 | } | ||
130 | } | ||
131 | if (remplie) { | ||
132 | nb_diagonales_2+=1 | ||
133 | } | ||
134 | } | ||
135 | |||
136 | |||
137 | } | ||
138 | // Compter les cases utilisées | ||
139 | var nbcases = 0 ; | ||
140 | for(i=0; i<nblignes; i++) { | ||
141 | for(j=0; j<nbcolonnes; j++) { | ||
142 | if (listelignes[i].children[j].style.backgroundColor == couleur_valide) { | ||
143 | nbcases+=1 | ||
144 | } | ||
145 | } | ||
146 | |||
147 | } | ||
148 | |||
149 | |||
150 | // Mettre le score à jour | ||
151 | score = (nb_lignes_completes + nb_colonnes_completes + nb_diagonales_1 + nb_diagonales_2) *points_par_ligne + nbcases ; | ||
152 | metscore(score) ; | ||
153 | } | ||
diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..fa5f191 --- /dev/null +++ b/static/style.css | |||
@@ -0,0 +1,38 @@ | |||
1 | /* Styles divers */ | ||
2 | .cliquable { | ||
3 | cursor: pointer; | ||
4 | text-decoration: underline; | ||
5 | } | ||
6 | |||
7 | .petit { | ||
8 | font-size: 0.8em; | ||
9 | } | ||
10 | |||
11 | |||
12 | /* Grille du bingo */ | ||
13 | #grille { | ||
14 | background-color: #F8F8F8 ; | ||
15 | padding: 1px ; | ||
16 | margin: 30px ; | ||
17 | border: 1px solid black ; | ||
18 | } | ||
19 | |||
20 | #grille td { | ||
21 | background-color:#EEEEEE; | ||
22 | border: 1px solid black; | ||
23 | margin: 0px; | ||
24 | padding: 3px ; | ||
25 | text-align: center ; | ||
26 | } | ||
27 | |||
28 | #grille td.vide { | ||
29 | background-color:#999999 ; | ||
30 | } | ||
31 | |||
32 | /* Formulaire page custom */ | ||
33 | .texte { | ||
34 | width:20em | ||
35 | } | ||
36 | |||
37 | .data { | ||
38 | width:3em | ||
diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..028aaa9 --- /dev/null +++ b/templates/base.html | |||
@@ -0,0 +1,31 @@ | |||
1 | <!DOCTYPE html> | ||
2 | |||
3 | <html lang="fr"> | ||
4 | <head> | ||
5 | <meta charset="UTF-8" > | ||
6 | <title>Le bingo de l'allaitement</title> | ||
7 | <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css"> | ||
8 | <!--<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">--> | ||
9 | |||
10 | <script src="static/outilspage.js"></script> | ||
11 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
12 | |||
13 | </head> | ||
14 | |||
15 | <body> | ||
16 | |||
17 | {% block contenu %}{% endblock %} | ||
18 | |||
19 | <hr> | ||
20 | <div id="basdepage"> | ||
21 | <nav> | ||
22 | <a href="/">Grille aléatoire</a> | | ||
23 | <a href="/custom">Créer une grille personnalisée</a> | | ||
24 | <!-- <a href="/apropos">À propos</a> |--> | ||
25 | |||
26 | </nav> | ||
27 | </div> | ||
28 | |||
29 | |||
30 | </body> | ||
31 | </html> | ||
diff --git a/templates/custom.html b/templates/custom.html new file mode 100644 index 0000000..cc5521c --- /dev/null +++ b/templates/custom.html | |||
@@ -0,0 +1,35 @@ | |||
1 | {% extends "base.html" %} | ||
2 | {% block contenu %} | ||
3 | <h1>Créer une grille personnalisée</h1> | ||
4 | |||
5 | {% if e | length >0 %} | ||
6 | <div id="erreurs"> | ||
7 | <h2>Log d'erreurs</h2> | ||
8 | <ul> | ||
9 | {% for err in e %} | ||
10 | <li>{{ err }}</li> | ||
11 | {% endfor %} | ||
12 | </ul> | ||
13 | </div> | ||
14 | {% endif %} | ||
15 | |||
16 | <div id="contenu"> | ||
17 | |||
18 | <form action="/" method="POST"> | ||
19 | |||
20 | <ul> | ||
21 | <li>Titre de la page : <input class="texte" type="text" name="titre" value="{{ DEFAUT.titre }}"></li> | ||
22 | <li>Nombre de lignes : <input class="data" type="number" min="{{ CONFIG.minlignes }}" max="{{ CONFIG.maxlignes}}" name="nblignes" value="{{ DEFAUT.nblignes }}"></li> | ||
23 | <li>Nombre de colonnes : <input class="data" type="number" min="{{ CONFIG.mincolonnes }}" max="{{ CONFIG.maxcolonnes }}" name="nbcolonnes" value="{{ DEFAUT.nbcolonnes }}"></li> | ||
24 | <li>Nombre de cases vides : <input class="data" type="number" min="0" name="nbcasesvides" value="{{ DEFAUT.nbcasesvides }}"> <span class="petit">Remarque : s'il n'y a pas assez de données, la grille sera automatiquement complétée par des cass vides.</span></li> | ||
25 | |||
26 | |||
27 | </ul> | ||
28 | <input type="submit" name="zou" value="Je veux une grille !"> | ||
29 | |||
30 | </form> | ||
31 | |||
32 | </div> | ||
33 | |||
34 | |||
35 | {% endblock %} | ||
diff --git a/templates/faq.html b/templates/faq.html new file mode 100644 index 0000000..162f68d --- /dev/null +++ b/templates/faq.html | |||
@@ -0,0 +1,30 @@ | |||
1 | {% extends "base.html" %} | ||
2 | {% block contenu %} | ||
3 | <h2>Foire Aux Questions (FAQ)</h2> | ||
4 | |||
5 | <div id="sommaire"> | ||
6 | <ul>{% for cat in lcateg %} | ||
7 | <li><a href="#{{ cat }}">{{ cat }}</a></li> | ||
8 | {% endfor %} | ||
9 | </ul> | ||
10 | </div> | ||
11 | |||
12 | <div id="questionsreponses"> | ||
13 | {% for i in range(lcateg|length) %} | ||
14 | {% set qr = tableqr[i] %} | ||
15 | |||
16 | <h3 id="{{ lcateg[i] }}">{{ lcateg[i] }}</h3> | ||
17 | <ul> | ||
18 | {% for (q,r) in qr %} | ||
19 | <li><p><strong>Q : </strong>{{ q|safe }}</p> | ||
20 | <p><strong>R : </strong>{{ r|safe }}</p> | ||
21 | </li> | ||
22 | {% endfor %} | ||
23 | </ul> | ||
24 | |||
25 | |||
26 | {% endfor %} | ||
27 | </div> | ||
28 | |||
29 | |||
30 | {% endblock %} | ||
diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..852fdd7 --- /dev/null +++ b/templates/index.html | |||
@@ -0,0 +1,42 @@ | |||
1 | {% extends "base.html" %} | ||
2 | {% block contenu %} | ||
3 | <h1>{{ conf.titre }}</h1> | ||
4 | |||
5 | {% if e | length >0 %} | ||
6 | <div id="erreurs"> | ||
7 | <h2>Log d'erreurs</h2> | ||
8 | <ul> | ||
9 | {% for err in e %} | ||
10 | <li>{{ err }}</li> | ||
11 | {% endfor %} | ||
12 | </ul> | ||
13 | </div> | ||
14 | {% endif %} | ||
15 | |||
16 | <div id="contenu"> | ||
17 | |||
18 | <p>Cochez la case dès que vous entendez une réplique idiote !</p> | ||
19 | <table id="grille"> | ||
20 | {% for ligne in bingo %} | ||
21 | <tr>{% for elt in ligne %} | ||
22 | {% if elt == "0" %} | ||
23 | <td class="vide"></td> | ||
24 | {% else %} | ||
25 | <td onclick='validecase(this)'>{{ elt }}</td> | ||
26 | {% endif %} | ||
27 | {% endfor %} | ||
28 | </tr> | ||
29 | {% endfor %} | ||
30 | </table> | ||
31 | |||
32 | <p>Score : <span id="score">0</span></p> | ||
33 | |||
34 | <p onclick="effacegrille()" class="cliquable">Effacer la grille</p> | ||
35 | |||
36 | <hr> | ||
37 | <a href="/?grille={{ chainecode }}">Lien permanent vers cette grille</a> | ||
38 | |||
39 | </div> | ||
40 | |||
41 | |||
42 | {% endblock %} | ||