From cdfb02e0011d4543c95fe671553e8c2fd108fef2 Mon Sep 17 00:00:00 2001 From: Simon Junod Date: Wed, 24 Sep 2025 12:28:43 +0200 Subject: [PATCH] choix du preset par les resetteurs --- pyproject.toml | 1 + spoutnik.py | 43 ++++++++++++++++++++++++++++++------------- uv.lock | 11 +++++++++++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8ef285b..f9785f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ dependencies = [ "requests==2.31.0", "shapely>=2.1.1", "soupsieve==2.5", + "tabulate>=0.9.0", "typing-extensions==4.11.0", "unidecode==1.3.8", "urllib3==2.2.1", diff --git a/spoutnik.py b/spoutnik.py index fe40337..900a24d 100644 --- a/spoutnik.py +++ b/spoutnik.py @@ -11,6 +11,8 @@ from geopy.distance import geodesic from geopy.geocoders import Nominatim from math import sinh, atan, pi, log, tan, cos, ceil from PIL import Image +from itertools import chain +from tabulate import tabulate geolocator = Nominatim(user_agent="discord-bot-spoutnik") @@ -49,7 +51,7 @@ class Game: self.winner = None self.last_player = None self.last_datetime = None - self.resetters = set() + self.reset_data = {key.lower(): [value["label"], set()] for key, value in SPOUTNIK_PRESETS.items()} self.jump_url = None async def reset(self, preset, force=False): @@ -81,7 +83,7 @@ class Game: self.winner = None self.last_player = None self.last_datetime = None - self.resetters = set() + self.reset_data = {key.lower(): [value["label"], set()] for key, value in SPOUTNIK_PRESETS.items()} output += f":satellite_orbital: Il y a un nouveau lieu à trouver ! Le terrain de jeu est {self.preset["label"]}." output += f"\n\nDonnez-moi les coordonnées GPS du centre de l'image, à {self.preset["max_distance"]} m près." output += f"\n\n*Sur le site Google Maps, clic droit puis clic sur les coordonnées.*" @@ -92,17 +94,32 @@ class Game: guess = unidecode(message.content.strip()).upper() # if it's the special keyword 'reset', consider resetting - if guess == "RESET" and SPOUTNIK_RESETTERS_NEEDED != 0: - if message.author in self.resetters: + if (regex := re.match(r"^RESET( [A-Z]+)?$", guess)) and SPOUTNIK_RESETTERS_NEEDED != 0: + if message.author in set(chain.from_iterable(value[1] for value in self.reset_data.values())): + await self.channel.send(f"{message.author.mention} : tu as déjà proposé une réinitialisation") return - self.resetters.add(message.author) - await self.channel.send(f"Réinitialisation : {len(self.resetters)}/{SPOUTNIK_RESETTERS_NEEDED}") - if len(self.resetters) >= SPOUTNIK_RESETTERS_NEEDED: - try: - preset = self.preset - except NameError: - preset = list(SPOUTNIK_PRESETS)[0] - await self.reset(preset=preset, force=True) + + choice = (regex.group(1) or "").strip().lower() + if choice not in self.reset_data.keys(): + options = [] + for key, value in self.reset_data.items(): + options.append(f"* `{key}` : {value[0]}") + await self.channel.send(f"{message.author.mention} : je ne connais pas ce preset, les options sont :\n{'\n'.join(options)}") + return + + self.reset_data[choice][1].add(message.author) + + chosen = None + table = [] + for key, value in self.reset_data.items(): + table.append([key, value[0], f"{len(value[1])}/{SPOUTNIK_RESETTERS_NEEDED}"]) + if len(value[1]) >= SPOUTNIK_RESETTERS_NEEDED: + chosen = key + table = "```\n" + tabulate(table, tablefmt="rounded_grid") + "\n```" + await self.channel.send(f"Réinitialisation :\n{table}") + + if chosen: + await self.reset(preset=SPOUTNIK_PRESETS[chosen], force=True) return # if somebody has already won, return silently @@ -139,7 +156,7 @@ class Game: zoom = self.preset["zoom"] if distance <= self.preset["max_distance"]: self.winner = message.author - self.resetters = set() + self.reset_data = set() output = f":trophy: YOUPI ! {message.author.mention} a trouvé le lieu ! :trophy:" output += f"\n\n[Lieu exact]()" await self.channel.send(output) diff --git a/uv.lock b/uv.lock index cc3cfec..967e949 100644 --- a/uv.lock +++ b/uv.lock @@ -123,6 +123,7 @@ dependencies = [ { name = "requests" }, { name = "shapely" }, { name = "soupsieve" }, + { name = "tabulate" }, { name = "typing-extensions" }, { name = "unidecode" }, { name = "urllib3" }, @@ -149,6 +150,7 @@ requires-dist = [ { name = "requests", specifier = "==2.31.0" }, { name = "shapely", specifier = ">=2.1.1" }, { name = "soupsieve", specifier = "==2.5" }, + { name = "tabulate", specifier = ">=0.9.0" }, { name = "typing-extensions", specifier = "==4.11.0" }, { name = "unidecode", specifier = "==1.3.8" }, { name = "urllib3", specifier = "==2.2.1" }, @@ -523,6 +525,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4c/f3/038b302fdfbe3be7da016777069f26ceefe11a681055ea1f7817546508e3/soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7", size = 36131, upload-time = "2023-09-02T12:48:20.552Z" }, ] +[[package]] +name = "tabulate" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090, upload-time = "2022-10-06T17:21:48.54Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252, upload-time = "2022-10-06T17:21:44.262Z" }, +] + [[package]] name = "typing-extensions" version = "4.11.0"