Skip to content
Snippets Groups Projects
Commit ca9131c7 authored by COUCHET Thibaud's avatar COUCHET Thibaud
Browse files

Récupération dynamique des défis par journée en fonction du niveau et...

Récupération dynamique des défis par journée en fonction du niveau et classement revue avec gestion en id
parent 27aefec3
No related branches found
No related tags found
No related merge requests found
......@@ -33,8 +33,13 @@
<ul class="space-y-4">
{% for challenge in challenges %}
<li class="flex items-center justify-between p-4 bg-gray-100 rounded-lg shadow-lg hover:shadow-xl transition duration-300">
<span class="text-lg font-medium text-[#102564]">{{ challenge }}</span>
<button onclick="completeChallenge('{{ challenge }}')" class="py-2 px-4 bg-[#102564] text-white font-semibold rounded-lg shadow-md hover:bg-[#000000] transition duration-300">Valider</button>
<div class="flex flex-col">
<span class="text-lg font-medium text-[#102564]">{{ challenge.description }}</span>
<span class="text-sm text-gray-500">Niveau: {{ challenge.level }}</span>
<span class="text-sm text-gray-500">Lieu: {{ challenge.lieu }}</span>
<span class="text-sm text-gray-500">Points: {{ challenge.points }}</span>
</div>
<button onclick="completeChallenge('{{ challenge.id }}')" class="py-2 px-4 bg-[#102564] text-white font-semibold rounded-lg shadow-md hover:bg-[#000000] transition duration-300">Valider</button>
</li>
{% endfor %}
</ul>
......@@ -52,29 +57,52 @@
<h2 class="text-xl font-bold text-[#102564] mb-4">Modifier le Profil</h2>
<label class="block text-sm text-gray-700">Niveau de difficulté</label>
<select id="difficulty" class="w-full p-2 border rounded-lg mb-4">
<option value="facile">Facile</option>
<option value="moyen">Moyen</option>
<option value="difficile">Difficile</option>
<option value="facile" {% if user_difficulty == "facile" %}selected{% endif %}>Facile</option>
<option value="moyen" {% if user_difficulty == "moyen" %}selected{% endif %}>Moyen</option>
<option value="difficile" {% if user_difficulty == "difficile" %}selected{% endif %}>Difficile</option>
</select>
<button onclick="saveProfileSettings()" class="w-full bg-[#102564] text-white py-2 rounded-lg hover:bg-[#000000] transition duration-300">Enregistrer</button>
<button onclick="toggleProfilePopup()" class="w-full mt-2 bg-gray-300 py-2 rounded-lg hover:bg-gray-400 transition duration-300">Annuler</button>
</div>
</div>
<!-- Message de confirmation -->
<div id="confirmationMessage" class="hidden fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center">
<div class="bg-white p-6 rounded-lg shadow-lg w-96">
<h2 class="text-xl font-bold text-[#102564] mb-4">Défi validé</h2>
<p id="confirmationText" class="text-sm text-gray-700"></p>
<button onclick="closeConfirmationMessage()" class="w-full mt-2 bg-gray-300 py-2 rounded-lg hover:bg-gray-400 transition duration-300">OK</button>
</div>
</div>
<script>
function toggleProfilePopup() {
document.getElementById("profilePopup").classList.toggle("hidden");
}
function completeChallenge(challenge) {
function completeChallenge(challengeId) {
fetch("/complete_challenge/", {
method: "POST",
headers: {
"X-CSRFToken": "{{ csrf_token }}",
"Content-Type": "application/x-www-form-urlencoded"
},
body: "challenge=" + challenge
}).then(() => location.reload());
body: "challenge_id=" + challengeId
})
.then(response => response.json())
.then(data => {
if (data.status == "success") {
document.getElementById("confirmationText").innerText = data.message + " (" + data.points + " points)";
document.getElementById("confirmationMessage").classList.remove("hidden");
} else {
alert(data.message);
}
});
}
function closeConfirmationMessage() {
document.getElementById("confirmationMessage").classList.add("hidden");
location.reload();
}
function saveProfileSettings() {
......@@ -86,7 +114,16 @@
"Content-Type": "application/x-www-form-urlencoded"
},
body: "difficulty=" + difficulty
}).then(() => toggleProfilePopup());
})
.then(response => response.json())
.then(data => {
if (data.status == "success") {
alert("Paramètres enregistrés avec succès");
toggleProfilePopup();
} else {
alert(data.message);
}
});
}
</script>
</body>
......
......@@ -8,12 +8,17 @@
<div class="bg-white p-8 rounded-2xl shadow-2xl w-full max-w-3xl">
<h2 class="text-3xl font-bold text-[#102564] text-center mb-6">Classement</h2>
<ul class="space-y-4">
{% for user, score in scores %}
<li class="flex justify-between p-4 bg-gray-100 rounded-lg shadow-md">
<span class="text-lg text-[#102564] font-medium">{{ user }}</span>
<span class="text-lg font-semibold text-[#102564]">{{ score }} points</span>
<!-- Loop through the ranking and display their username and points from [{'username': 'Thibaud', 'score': 49}] and classement far right-->
{% for user in ranking %}
<li class="flex items-center justify-between p-4 bg-gray-100 rounded-lg shadow-lg hover:shadow-xl transition duration-300">
<div class="flex flex-col">
<span class="text-lg font-medium text-[#102564]">{{ user.username }}</span>
<span class="text-sm text-gray-500">Points: {{ user.score }}</span>
</div>
<span class="text-sm text-gray-500">{{ forloop.counter }}</span>
</li>
{% endfor %}
</ul>
</div>
......
......@@ -2,106 +2,304 @@ from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.contrib.auth.models import User
from django.contrib.auth import logout
from django.contrib import messages
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
import csv
import os
import random
from datetime import datetime
# Fichier CSV pour stocker les scores
CSV_FILE = "scores.csv"
USER_FILE = "users.csv"
DIFFICULTY_FILE = "difficulties.csv"
DAILY_CHALLENGE_FILE = "daily_challenges.csv"
def init_csv():
if not os.path.exists(CSV_FILE):
with open(CSV_FILE, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(["username", "score"])
writer.writerow(["user_id", "score"])
def read_scores():
scores = {}
try:
with open(CSV_FILE, 'r') as file:
reader = csv.reader(file)
next(reader) # Ignorer l'en-tête
for row in reader:
scores[row[0]] = int(row[1])
except FileNotFoundError:
init_csv()
return scores
def init_user_csv():
if not os.path.exists(USER_FILE):
with open(USER_FILE, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(["user_id", "username"])
def update_score(username, points):
scores = read_scores()
scores[username] = scores.get(username, 0) + points
with open(CSV_FILE, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(["username", "score"])
for user, score in scores.items():
writer.writerow([user, score])
#################
# Page de Login #
#################
def login_view(request):
# se log ou bien créer un compte si l'utilisateur n'existe pas sans mot de passe
if request.method == "POST":
username = request.POST["username"]
user, created = User.objects.get_or_create(username=username)
username = request.POST.get("username")
user = User.objects.filter(username=username).first()
if user is None:
user = User.objects.create_user(username=username, password=None)
user.save()
add_user_to_csv(username, user.id)
login(request, user)
request.session['user_id'] = user.id
return redirect("challenges")
return render(request, "login.html")
def add_user_to_csv(username, django_user_id):
"""Ajoute un utilisateur avec un ID Django dans le fichier 'users.csv'."""
user_id = django_user_id # Utiliser l'ID Django
with open(USER_FILE, 'a', newline='') as file:
writer = csv.writer(file)
writer.writerow([user_id, username]) # Ajouter l'ID Django et le nom d'utilisateur
return user_id
##################
# Page de Logout #
##################
def logout_view(request):
logout(request)
return redirect('login')
##################
# Page de Result #
##################
def ranking_view(request):
"""Afficher le classement des scores avec les nom d'utilisateur."""
# Lire les scores depuis le fichier CSV
scores = read_scores()
# Lire les utilisateurs depuis la base de données Django
users = read_users()
# Créer le classement en associant le score avec le nom d'utilisateur
ranking = []
for user_id, score in scores.items():
if int(user_id) in users: # Associer le user_id avec l'utilisateur dans le dictionnaire
ranking.append({"username": users[int(user_id)], "score": score})
# Trier le classement par score (du plus élevé au plus bas)
ranking.sort(key=lambda x: x['score'], reverse=True)
print(f"Classement: {ranking}") # Debug : Afficher le classement
# Passer le classement à la vue pour l'afficher
return render(request, "ranking.html", {"ranking": ranking})
def read_users():
"""Lire les utilisateurs depuis django"""
users = {}
for user in User.objects.all():
users[user.id] = user.username
print(f"Utilisateurs: {users}")
return users
#####################
# Page de Challenge #
#####################
def challenges_view(request):
# Redirection vers la page de login en cas de session non authentifié
if not request.user.is_authenticated:
return redirect("login")
challenges = ["Monter les escaliers", "1h de bureau debout", "Faire 5000 pas"]
return render(request, "challenges.html", {"challenges": challenges})
user_id = request.session.get('user_id') # Utiliser l'ID stocké en session
today = datetime.today().strftime('%Y-%m-%d') # Récupérer la date du jour
# Vérifier si l'utilisateur a déjà généré ses défis pour aujourd'hui
user_challenges = read_user_daily_challenges(user_id, today)
if user_challenges:
# Si les défis existent déjà pour aujourd'hui, on les récupère depuis le fichier
selected_challenges = user_challenges
print(f"Défis récupérés pour aujourd'hui: {len(selected_challenges)} défis")
else:
# Sinon, générer de nouveaux défis pour cet utilisateur
print("Aucun défi généré pour aujourd'hui, génération de nouveaux défis.")
selected_challenges = generate_daily_challenges(user_id) # Générer et enregistrer de nouveaux défis
# Rechercher la difficulté de l'user connecté
user_difficulty = get_user_difficulty(user_id)
print(f"Difficulté de l'utilisateur {user_id}: {user_difficulty}")
selected_challenges = read_challenges_from_ids(selected_challenges)
# Passer les défis du jour à la vue
return render(request, "challenges.html", {"challenges": selected_challenges, "user_difficulty": user_difficulty})
def get_user_difficulty(user_id):
"""Récupérer la difficulté de l'utilisateur à partir du fichier 'difficulties.csv'."""
difficulty = "moyen" # Valeur par défaut
if os.path.exists(DIFFICULTY_FILE):
with open(DIFFICULTY_FILE, "r", newline="", encoding="utf-8") as file:
reader = csv.reader(file)
for row in reader:
if len(row) >= 2 and row[0] == str(user_id): # Vérifier l'ID utilisateur
difficulty = row[1] # Récupérer la difficulté
break
return difficulty
def read_user_daily_challenges(user_id, today):
"""Lire les défis du jour pour un utilisateur donné depuis le fichier daily_challenges.csv."""
user_challenges = []
if os.path.exists(DAILY_CHALLENGE_FILE):
with open(DAILY_CHALLENGE_FILE, 'r', newline='', encoding='utf-8') as file:
reader = csv.reader(file)
for row in reader:
if len(row) >= 3 and row[1] == str(user_id) and row[0] == today:
user_challenges = row[2:] # Extraire les IDs des défis du jour
break
return user_challenges
def generate_daily_challenges(user_id):
"""Génère et enregistre les défis du jour pour l'utilisateur."""
challenges = read_challenges()
user_difficulty = get_user_difficulty(user_id)
user_difficulty = user_difficulty.capitalize()
daily_challenges = []
categories = ["Au bureau (poste)", "Au bureau (espaces communs)", "Extérieur"]
random.shuffle(categories) # Mélanger les catégories
for category in categories:
challenges_in_category = [c for c in challenges[user_difficulty] if c["lieu"] == category]
if challenges_in_category:
challenge = random.choice(challenges_in_category)
daily_challenges.append(challenge["id"])
save_daily_challenges_to_csv(user_id, daily_challenges) # Enregistrer les défis du jour
return daily_challenges
def save_daily_challenges_to_csv(user_id, challenge_ids):
"""Sauvegarder les défis du jour dans un fichier CSV"""
today = datetime.today().strftime('%Y-%m-%d')
with open(DAILY_CHALLENGE_FILE, 'a', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
writer.writerow([today, user_id] + challenge_ids)
def update_score(user_id, points):
"""Mettre à jour le score d'un utilisateur."""
scores = read_scores()
if str(user_id) in scores:
scores[str(user_id)] += points
else:
scores[str(user_id)] = points
with open(CSV_FILE, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(["user_id", "score"]) # En-tête
for user_id, score in scores.items():
writer.writerow([user_id, score])
def complete_challenge(request):
if request.method == "POST":
challenge_points = {
"Monter les escaliers": 100,
"1h de bureau debout": 50,
"Faire 5000 pas": 200
}
challenge = request.POST.get("challenge")
if challenge in challenge_points:
update_score(request.user.username, challenge_points[challenge])
return JsonResponse({"success": True})
challenge_id = request.POST.get("challenge_id")
user_id = request.session.get('user_id') # Récupérer l'ID utilisateur depuis la session
points = get_challenge_points(challenge_id)
def ranking_view(request):
scores = read_scores()
sorted_scores = sorted(scores.items(), key=lambda x: x[1], reverse=True)
return render(request, "ranking.html", {"scores": sorted_scores})
if points:
update_score(user_id, points) # Mettre à jour le score de l'utilisateur
return JsonResponse({"status": "success", "points": points})
def logout_view(request):
logout(request) # This logs out the user
return redirect('login')
return JsonResponse({"status": "error", "message": "Invalid request"}, status=400)
def read_challenges():
"""Lire tous les défis depuis un fichier CSV avec des colonnes séparées par des virgules."""
challenges = {"Facile": [], "Moyen": [], "Difficile": []}
if os.path.exists("challenges.csv"):
with open("challenges.csv", 'r', newline='', encoding='utf-8') as file:
reader = csv.reader(file)
for row in reader:
if len(row) >= 6:
challenge = {
"id": row[0],
"description": row[1],
"level": row[2],
"lieu": row[3],
"points": row[4],
"icon": row[5]
}
challenges[challenge["level"]].append(challenge)
return challenges
def read_challenges_from_ids(challenge_ids):
"""Récupérer les défis à partir de leurs IDs."""
challenges = read_challenges()
selected_challenges = []
for level in challenges:
for challenge in challenges[level]:
if challenge["id"] in challenge_ids:
selected_challenges.append(challenge)
return selected_challenges
def get_challenge_points(challenge_id):
"""Récupérer les points associés à un défi donné."""
challenges = read_challenges()
for level in challenges:
for challenge in challenges[level]:
if challenge["id"] == challenge_id:
return int(challenge["points"])
return None
@csrf_exempt
def update_difficulty(request):
if request.method == "POST":
difficulty = request.POST.get("difficulty", "moyen") # Valeur par défaut
user = request.user.username if request.user.is_authenticated else "guest" # Utilisateur authentifié ou invité
scores = []
user_found = False
if os.path.exists(DIFFICULTY_FILE):
with open(DIFFICULTY_FILE, "r", newline="", encoding="utf-8") as file:
reader = csv.reader(file)
for row in reader:
if len(row) < 2:
continue # Ignorer les lignes mal formées, on s'attend à [username, difficulty]
if row[0] == user:
row[1] = difficulty # Modifier uniquement la difficulté (plus de score)
user_found = True
scores.append(row)
if not user_found:
scores.append([user, difficulty]) # Ajouter utilisateur avec difficulté choisie (sans score)
with open(DIFFICULTY_FILE, "w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerows(scores)
user_id = request.session.get('user_id')
difficulty = request.POST.get("difficulty")
if difficulty in ["Facile", "Moyen", "Difficile"]:
save_user_difficulty(user_id, difficulty)
return JsonResponse({"status": "success"})
return JsonResponse({"status": "error", "message": "Invalid request"}, status=400)
#####################
# Page de Mise à jour difficulty #
#####################
return JsonResponse({"status": "success", "difficulty": difficulty})
@csrf_exempt
def update_difficulty(request):
if request.method == "POST":
user_id = request.session.get('user_id')
difficulty = request.POST.get("difficulty")
if difficulty in ["facile", "moyen", "difficile"]:
# Save user difficulty in file or database
save_user_difficulty(user_id, difficulty)
return JsonResponse({"status": "success"})
else:
return JsonResponse({"status": "error", "message": "Invalid difficulty"})
return JsonResponse({"status": "error", "message": "Invalid request"}, status=400)
return JsonResponse({"status": "error", "message": "Invalid request"}, status=400)
\ No newline at end of file
##########
# Commun #
##########
def read_scores():
"""Lire les scores depuis un fichier CSV."""
scores = {}
if os.path.exists(CSV_FILE):
with open(CSV_FILE, 'r', newline='') as file:
reader = csv.reader(file)
next(reader) # Ignorer l'en-tête
for row in reader:
if len(row) >= 2:
scores[row[0]] = int(row[1]) # Ajouter le score à un dictionnaire
return scores
def save_user_difficulty(user_id, difficulty):
"""Remplace si l'user à déjà sauvegarder sa difficulté sinon sauvegarde la le tout dans un fichier CSV."""
data = []
if os.path.exists(DIFFICULTY_FILE):
with open(DIFFICULTY_FILE, "r", newline="", encoding="utf-8") as file:
reader = csv.reader(file)
for row in reader:
if len(row) >= 2 and row[0] == str(user_id):
data.append([user_id, difficulty])
else:
data.append(row)
with open(DIFFICULTY_FILE, "w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
for row in data:
writer.writerow(row)
if [user_id, difficulty] not in data:
writer.writerow([user_id, difficulty])
1,Étirements des bras et épaules (2 min),Facile,Au bureau (poste),5,arrows-move
2,Se tenir droit et contracter les abdos (5 min),Facile,Au bureau (poste),5,user
3,S'asseoir et se lever de sa chaise (10 fois),Facile,Au bureau (poste),6,arrow-up-circle
4,Tenir 30 sec en équilibre sur un pied,Facile,Au bureau (poste),5,accessibility
5,Rotations poignets et épaules (1 min),Facile,Au bureau (poste),5,refresh
6,Prendre les escaliers toute la journée,Facile,Au bureau (espaces communs),8,stairs
7,Marcher 5000 pas dans la journée,Facile,Au bureau (espaces communs),10,footprints
8,Marcher 5 min après chaque réunion,Facile,Au bureau (espaces communs),8,clock
9,Flexions des genoux (10 fois),Facile,Au bureau (espaces communs),6,arrow-down-circle
10,Respiration profonde (5 fois),Facile,Au bureau (espaces communs),5,wind
11,Marche rapide (10 min) pause déjeuner,Facile,Extérieur,10,walk
12,Descendre un arrêt plus tôt,Facile,Extérieur,10,bus
13,Aller voir un collègue au lieu d’un e-mail,Facile,Extérieur,5,mail-opened
14,Balade autour du bureau,Facile,Extérieur,9,trees
15,20 montées de marches en extérieur,Facile,Extérieur,10,stairs
16,10 squats sans quitter son bureau,Moyen,Au bureau (poste),10,run
17,Gainage sur chaise (30 sec),Moyen,Au bureau (poste),10,grip-horizontal
18,20 extensions de mollets,Moyen,Au bureau (poste),10,walk
19,30 contractions abdos assis,Moyen,Au bureau (poste),10,user
20,Alterner assis/debout toutes les 30 min (2h),Moyen,Au bureau (poste),12,clock
21,Escaliers 3 jours d’affilée,Moyen,Au bureau (espaces communs),15,stairs
22,Se lever et marcher 5 min toutes les heures,Moyen,Au bureau (espaces communs),12,clock
23,10 montées de marches,Moyen,Au bureau (espaces communs),12,stairs
24,15 squats en salle de repos,Moyen,Au bureau (espaces communs),12,dumbbell
25,10 rotations de chevilles assis,Moyen,Au bureau (espaces communs),10,refresh
26,Marche rapide (15 min),Moyen,Extérieur,12,walk
27,10 flexions jambes en attendant métro,Moyen,Extérieur,10,bus
28,Aller au travail à pied/vélo (1x/semaine),Moyen,Extérieur,15,bike
29,7500 pas dans la journée,Moyen,Extérieur,15,footprints
30,Balade de 20 min en fin de journée,Moyen,Extérieur,14,trees
31,Gainage contre mur (1 min),Difficile,Au bureau (poste),15,grip-horizontal
32,20 squats en plusieurs fois,Difficile,Au bureau (poste),15,run
33,50 extensions de mollets,Difficile,Au bureau (poste),15,walk
34,Planche sur chaise (2 min),Difficile,Au bureau (poste),18,grip-horizontal
35,50 contractions abdos assis,Difficile,Au bureau (poste),15,user
36,Escaliers uniquement (5 jours consécutifs),Difficile,Au bureau (espaces communs),20,stairs
37,Marche 10 min après déjeuner (3 jours),Difficile,Au bureau (espaces communs),20,walk
38,Défi collectif avec 3 collègues,Difficile,Au bureau (espaces communs),15,users
39,Se lever et marcher toutes les 30 min,Difficile,Au bureau (espaces communs),18,clock
40,3 min de montées de genoux salle de repos,Difficile,Au bureau (espaces communs),18,run
41,10000 pas dans la journée,Difficile,Extérieur,20,footprints
42,Balade de 30 min après le travail,Difficile,Extérieur,20,trees
43,Aller au travail à vélo (3x/semaine),Difficile,Extérieur,25,bike
44,Marcher/courir 5 km en dehors du bureau,Difficile,Extérieur,25,footprints
45,Séance collective sportive extérieure,Difficile,Extérieur,22,users
2025-03-12,2,6,13,2
2025-03-12,,27,25,20
2025-03-12,,27,18,23
2025-03-12,,16,22,26
2025-03-12,,21,18,30
2025-03-12,,17,30,25
2025-03-12,,28,23,18
2025-03-12,,20,27,21
2025-03-12,17,18,21,30
2025-03-12,18,16,22,30
No preview for this file type
2,difficile
17,difficile
user_id,score
2,49
17,10
18,26
12,Bonjour
13,qqqqq
14,dffsd
15,uuuuuuuu
17,oiewuytourytyretyutyttyrtyruryturyturtyruty
18,yyyyy
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment