Skip to content

Commit e0ba30a

Browse files
committed
Update classement + Command test get_result
1 parent 6f6e4de commit e0ba30a

File tree

11 files changed

+310
-167
lines changed

11 files changed

+310
-167
lines changed
1.8 KB
Binary file not shown.
1.23 KB
Binary file not shown.
139 Bytes
Binary file not shown.

app/_app.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ async def leaderboard(interaction: discord.Interaction):
124124
await interaction.response.defer()
125125
embed = ldb.Leaderboard()
126126
await interaction.followup.send(content=None,embed=embed)
127+
logger.info(f'{interaction.user} à regarder le leaderbord')
127128

128129
# _______________________________________________________________________________________________________________________________
129130

@@ -214,6 +215,34 @@ async def session(interaction: discord.Interaction, saison: int, location: str,
214215

215216
# _______________________________________________________________________________________________________________________________
216217

218+
@tree.command(name="admin_getresult", description="Mettre à jour l'api")
219+
async def maj_api(interaction: discord.Interaction):
220+
interaction.response.defer()
221+
if interaction.user.guild_permissions.administrator:
222+
await interaction.response.send_message("⏳ Mise à jour en cours...")
223+
224+
try:
225+
result = f1api.getResults()
226+
227+
if result == 0:
228+
await interaction.followup.send("✅ Résultats mis à jour avec succès.")
229+
elif result == 1:
230+
await interaction.followup.send("⚠️ Les résultats ne sont pas encore disponibles. Réessaie plus tard.")
231+
elif result == 2:
232+
await interaction.followup.send("❌ L'API FastF1 ne prend pas en charge cette session.")
233+
elif result == 3:
234+
await interaction.followup.send("❌ Erreur lors du chargement de la session FastF1.")
235+
else:
236+
await interaction.followup.send("❌ Une erreur inattendue est survenue.")
237+
238+
except Exception as e:
239+
await interaction.followup.send(f"Erreur : {str(e)}")
240+
else:
241+
await interaction.followup.send(embeds=await embed.permError(interaction))
242+
243+
# _______________________________________________________________________________________________________________________________
244+
245+
217246
@tree.command(name="admin_status", description="Retourne le status du bot")
218247
async def status(interaction: discord.Interaction):
219248
await interaction.response.defer(ephemeral=True)

app/classement.py

Lines changed: 134 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -3,166 +3,168 @@
33
from thefuzz import fuzz
44
import discord
55
from config import logger, EMBED_COLOR_RED, EMBED_THUMBNAIL, EMBED_FOOTER_TEXT, EMBED_IMAGE
6+
import pronos as pr
67

7-
8-
def saveResults():
9-
8+
def load_json_file(path):
9+
"""Charge un fichier JSON, retourne un dict vide si fichier absent ou invalide."""
10+
if not os.path.exists(path):
11+
logger.warning(f"Fichier {path} non trouvé, création d'un dict vide.")
12+
return {}
1013
try:
11-
with open('../data/Results.json', 'r', encoding='utf-8') as f:
12-
results = json.load(f)
13-
with open('../data/Pronos.json', 'r', encoding='utf-8') as f:
14-
pronos = json.load(f)
14+
with open(path, 'r', encoding='utf-8') as f:
15+
return json.load(f)
16+
except (ValueError, json.JSONDecodeError) as e:
17+
logger.error(f"Erreur lors du chargement du fichier {path}: {e}")
18+
return {}
1519

16-
except ValueError:
17-
logger.info("Files cannot be accessed, are you sure pronostics exist ?")
20+
def match_position(entry: str, target: str, threshold: int) -> bool:
21+
"""Compare les noms avec tolérance, utilise fuzzy matching sur prénom ou nom."""
22+
parts = entry.strip().split(' ', 1)
23+
if len(parts) == 2:
24+
prenom, nom = parts
25+
else:
26+
prenom = nom = parts[0]
27+
28+
target_parts = target.strip().split(' ', 1)
29+
if len(target_parts) != 2:
30+
logger.warning(f"Format inattendu pour target '{target}'")
31+
return False
32+
target_prenom, target_nom = target_parts
33+
34+
return (fuzz.ratio(target_prenom.lower(), prenom.lower()) >= 90 or
35+
fuzz.ratio(target_nom.lower(), nom.lower()) >= threshold)
36+
37+
def save_results(race_type):
38+
"""
39+
race_type doit être une des chaînes : 'Qualif', 'CourseSprint', 'Course'
40+
"""
41+
42+
logger.info(f"save_results appelée avec race_type = {race_type}")
43+
44+
country = pr.country_fonction()
45+
46+
results = load_json_file('data/Results.json')
47+
pronos = load_json_file(f'data/pronos_{country}.json')
48+
barem = load_json_file('data/Barem.json')
49+
50+
if not results or not pronos or not barem:
51+
logger.info("Fichiers nécessaires absents ou invalides, arrêt de la fonction.")
1852
return
19-
20-
try:
21-
with open('data/Barem.json', 'r', encoding='utf-8') as f:
22-
barem = json.load(f)
23-
except ValueError:
24-
logger.info("Problem with Barem")
53+
54+
if race_type not in barem:
55+
logger.error(f"Type de course '{race_type}' non supporté dans le barème.")
2556
return
26-
27-
Premier = results['1']
28-
Second = results['2']
29-
Troisième = results['3']
30-
31-
for key in pronos.keys():
57+
58+
bar = barem[race_type]
59+
premier = results.get('1', '')
60+
second = results.get('2', '')
61+
troisieme = results.get('3', '')
62+
63+
leaderboard_path = 'data/Leaderbord.json'
64+
leaderboard = load_json_file(leaderboard_path)
65+
66+
for key, user_pronos in pronos.items():
3267
points = 0
33-
complex = False
34-
logger.info(key)
35-
Premier_Pronos = False
36-
Second_Pronos = False
37-
Troisième_Pronos = False
38-
39-
def match_Position(entry: str, target: str, threshold: int) -> bool:
40-
parts = entry.strip().split(' ', 1)
41-
42-
if (len(parts) == 2):
43-
prenom, nom = parts
44-
else:
45-
prenom = nom = parts[0]
46-
47-
target_prenom, target_nom = target.strip().split(' ', 1)
48-
return fuzz.ratio(target_prenom.lower(), prenom.lower()) >= 90 or fuzz.ratio(target_nom.lower(), nom.lower()) >= threshold
49-
50-
Premier_Pronos = match_Position(pronos[key]['1'], Premier, 90)
51-
Second_Pronos = match_Position(pronos[key]['2'], Second, 90)
52-
Troisième_Pronos = match_Position(pronos[key]['3'], Troisième, 90)
53-
54-
try:
55-
if Premier_Pronos and Second_Pronos and Troisième_Pronos:
56-
logger.info("Tout juste pour "+pronos[key]["Pseudo"])
57-
points += barem["allCorrect"]
58-
complex = True
59-
60-
elif Premier_Pronos and Second_Pronos:
61-
logger.info("Le premier et le deuxième sont bon pour " +
62-
pronos[key]['Pseudo']+" + "+str(barem["first2Correct"])+" Points")
63-
points += barem["first2Correct"]
64-
complex = True
65-
66-
elif Second_Pronos and Troisième_Pronos:
67-
68-
logger.info(
69-
"Le premier est bon"+pronos[key]['Pseudo']+" + "+str(barem["last2Correct"])+" Points")
70-
points += barem["last2Correct"]
71-
complex = True
72-
73-
elif (Troisième_Pronos and Premier_Pronos):
74-
75-
logger.info("Le premier et le dernier sont bons pour " +
76-
pronos[key]['Pseudo']+" + "+str(barem["1and3Correct"])+" Points")
77-
points += barem["1and3Correct"]
78-
complex = True
79-
80-
except KeyError as e:
81-
logger.info(str(e) + "is missing")
82-
pass
83-
except TypeError as e:
84-
logger.info(e)
85-
pass
86-
87-
try:
88-
if (Premier_Pronos and not complex):
89-
logger.info("Le premier est bon pour " +
90-
pronos[key]['Pseudo']+" + "+str(barem["firstCorrect"])+" Points")
91-
points += barem["firstCorrect"]
92-
93-
if (Second_Pronos and not complex):
94-
logger.info("Le deuxième est bon pour " +
95-
pronos[key]['Pseudo']+" + "+str(barem["secondCorrect"])+" Points")
96-
points += barem["secondCorrect"]
97-
98-
if (Troisième_Pronos and not complex):
99-
logger.info("Le troisième est bon pour " +
100-
pronos[key]['Pseudo']+" + "+str(barem["thirdCorrect"])+" Points")
101-
points += barem["thirdCorrect"]
102-
103-
except KeyError as e:
104-
logger.info(str(e) + "is missing")
105-
return
106-
107-
except TypeError as e:
108-
logger.info(e)
109-
return
110-
111-
file_path = 'data/Leaderbord.json'
112-
113-
if not os.path.exists(file_path):
114-
pointsPronos = {
115-
key: {
116-
"Pseudo": pronos[key]["Pseudo"],
117-
"Points": points
118-
}
119-
}
68+
pseudo = user_pronos.get('Pseudo', 'Inconnu')
69+
70+
logger.info(f"Calcul des points pour l'utilisateur {key} ({pseudo})")
71+
72+
premier_in_top3 = premier in [user_pronos.get('1', ''), user_pronos.get('2', ''), user_pronos.get('3', '')]
73+
second_in_top3 = second in [user_pronos.get('1', ''), user_pronos.get('2', ''), user_pronos.get('3', '')]
74+
troisieme_in_top3 = troisieme in [user_pronos.get('1', ''), user_pronos.get('2', ''), user_pronos.get('3', '')]
75+
76+
premier_correct = match_position(user_pronos.get('1', ''), premier, 90)
77+
second_correct = match_position(user_pronos.get('2', ''), second, 90)
78+
troisieme_correct = match_position(user_pronos.get('3', ''), troisieme, 90)
79+
80+
all_correct = premier_correct and second_correct and troisieme_correct
81+
82+
if all_correct:
83+
points += bar.get('allCorrect', 0)
84+
logger.info(f"Tout juste pour {pseudo}, +{bar.get('allCorrect', 0)} pts")
12085
else:
121-
with open(file_path, 'r', encoding='utf-8') as f:
122-
pointsPronos = json.load(f)
123-
if key not in pointsPronos:
124-
pointsPronos[key] = {
125-
"Pseudo": pronos[key]["Pseudo"],
126-
"Points": points
127-
}
128-
else:
129-
pointsPronos[key]["Pseudo"] = pronos[key]["Pseudo"]
130-
pointsPronos[key]["Points"] += points
86+
if premier_correct:
87+
points += bar.get('correctPosition', 0)
88+
logger.info(f"Premier à la bonne place pour {pseudo}, +{bar.get('correctPosition', 0)} pts")
89+
elif premier_in_top3:
90+
points += bar.get('inTop3', 0)
91+
logger.info(f"Premier dans le top 3 pour {pseudo}, +{bar.get('inTop3', 0)} pts")
13192

132-
with open(file_path, 'w', encoding='utf-8') as f:
133-
json.dump(pointsPronos, f, ensure_ascii=False, indent=4)
93+
if second_correct:
94+
points += bar.get('correctPosition', 0)
95+
logger.info(f"Deuxième à la bonne place pour {pseudo}, +{bar.get('correctPosition', 0)} pts")
96+
elif second_in_top3:
97+
points += bar.get('inTop3', 0)
98+
logger.info(f"Deuxième dans le top 3 pour {pseudo}, +{bar.get('inTop3', 0)} pts")
13499

100+
if troisieme_correct:
101+
points += bar.get('correctPosition', 0)
102+
logger.info(f"Troisième à la bonne place pour {pseudo}, +{bar.get('correctPosition', 0)} pts")
103+
elif troisieme_in_top3:
104+
points += bar.get('inTop3', 0)
105+
logger.info(f"Troisième dans le top 3 pour {pseudo}, +{bar.get('inTop3', 0)} pts")
135106

107+
if key not in leaderboard:
108+
leaderboard[key] = {"Pseudo": pseudo, "Points": points}
109+
else:
110+
leaderboard[key]["Points"] += points
111+
112+
113+
try:
114+
with open(leaderboard_path, 'w', encoding='utf-8') as f:
115+
json.dump(leaderboard, f, ensure_ascii=False, indent=4)
116+
logger.info(f"Leaderboard mis à jour avec {len(leaderboard)} utilisateurs.")
117+
except Exception as e:
118+
logger.error(f"Erreur lors de la sauvegarde du leaderboard: {e}")
119+
120+
136121
def Leaderboard():
137-
138122
try:
139123
with open("data/Leaderbord.json", 'r', encoding='utf-8') as f:
140124
pointsPronos = json.load(f)
141125
pronosLeaderboard = dict(
142-
sorted(pointsPronos.items(), key=lambda item: item[1]['Points'], reverse=True))
143-
126+
sorted(pointsPronos.items(), key=lambda item: item[1]['Points'], reverse=True)
127+
)
144128
except FileNotFoundError:
145129
logger.info("The file doesn't exist")
146-
return
147-
130+
return None
131+
except json.JSONDecodeError:
132+
logger.info("Le fichier Leaderbord.json est vide ou mal formé")
133+
return None
148134
except KeyError:
149135
logger.info("Erreur dans la lecture des points")
150-
return
151-
136+
return None
137+
138+
if not pronosLeaderboard:
139+
embed = discord.Embed(
140+
title="🏆 Classement des Pronostics",
141+
description="Aucun résultat à afficher pour le moment.",
142+
color=EMBED_COLOR_RED
143+
)
144+
embed.set_footer(text=EMBED_FOOTER_TEXT)
145+
embed.set_image(url=EMBED_IMAGE)
146+
embed.set_thumbnail(url=EMBED_THUMBNAIL)
147+
return embed
148+
149+
# Extraction sécurisée des pseudos et points
150+
try:
151+
pseudos, points = zip(*[(val['Pseudo'], val['Points']) for val in pronosLeaderboard.values()])
152+
except ValueError:
153+
logger.info("Erreur lors de l'extraction des pseudos et points.")
154+
return None
155+
152156
embed = discord.Embed(
153157
title="🏆 Classement des Pronostics",
154158
color=EMBED_COLOR_RED
155159
)
156-
pseudos, points = zip(*[(val['Pseudo'], val['Points'])
157-
for val in pronosLeaderboard.values()])
158-
pseudos = list(pseudos)
159-
points = list(points)
160160
position = 1
161161
for i in range(len(pseudos)):
162162
embed.add_field(name=f"{position}ᵉ - {pseudos[i]}",
163163
value=f"Score : **{points[i]}**", inline=False)
164-
if (i+1 < len(pseudos) and points[i] != points[i+1]):
164+
# Incrément de la position seulement si le prochain score est différent
165+
if (i + 1 < len(pseudos)) and (points[i] != points[i + 1]):
165166
position += 1
167+
166168
embed.set_footer(text=EMBED_FOOTER_TEXT)
167169
embed.set_image(url=EMBED_IMAGE)
168170
embed.set_thumbnail(url=EMBED_THUMBNAIL)

0 commit comments

Comments
 (0)