import requests import math import json import os import chromadb with open("fr_to_en_pokemon.json", "r", encoding="utf-8") as f: FR_TO_EN_MAP = json.load(f) client = chromadb.PersistentClient(path="./chroma_db") collection = client.get_or_create_collection(name="pokemon_cards_clip") print(f"📦 Nombre de cartesen base : {collection.count()}") def get_english_name(pokemon_name: str) -> str: name = pokemon_name.strip().lower().replace(" ", "-") if name in [v.replace(" ", "-") for v in FR_TO_EN_MAP.values()]: return name english = FR_TO_EN_MAP.get(name) if english: return english.lower().replace(" ", "-") return "❌ nom-non-reconnu" def calculate_stat(base, level, iv=31, ev=0, nature=1.0, stat_name="hp"): if stat_name == "hp": return math.floor(((2 * base + iv + (ev // 4)) * level) / 100) + level + 10 else: return math.floor((((2 * base + iv + (ev // 4)) * level) / 100 + 5) * nature) def estimate_level_from_hp(observed_hp, base_hp, iv=31, ev=0, tolerance=1): for level in range(1, 101): computed_hp = math.floor(((2 * base_hp + iv + (ev // 4)) * level) / 100) + level + 10 if abs(computed_hp - observed_hp) <= tolerance: return level return None def get_base_hp(pokemon_name: str) -> int: base_url = "https://pokeapi.co/api/v2/pokemon/" try: res = requests.get(base_url + pokemon_name.lower()) res.raise_for_status() data = res.json() # Trouver la stat HP for stat in data["stats"]: if stat["stat"]["name"] == "hp": return stat["base_stat"] raise ValueError("❌ Stat HP non trouvée.") except requests.exceptions.HTTPError: raise ValueError("❌ Pokémon introuvable. Vérifie le nom.") except Exception as e: raise RuntimeError(f"⚠️ Erreur : {str(e)}") def get_move_details(move_url: str) -> dict: res = requests.get(move_url) res.raise_for_status() move_data = res.json() # Description in French if available, fallback to default effect = next( (entry['effect'] for entry in move_data['effect_entries'] if entry['language']['name'] == 'en'), move_data['effect_entries'][0]['effect'] if move_data['effect_entries'] else "No known effect." ) effect = effect.replace("$effect_chance", str(move_data.get("effect_chance", ""))) return { "name": move_data['name'], "type": move_data['type']['name'], "power": move_data['power'], "accuracy": move_data['accuracy'], "category": move_data['damage_class']['name'], "effect": effect } def get_pokemon_info(pokemon_name: str, level=50, version_group='sword-shield') -> str: base_url = "https://pokeapi.co/api/v2/" try: res_pokemon = requests.get(base_url + f"pokemon/{pokemon_name.lower()}") res_pokemon.raise_for_status() data = res_pokemon.json() res_species = requests.get(base_url + f"pokemon-species/{pokemon_name.lower()}") res_species.raise_for_status() species = res_species.json() evo_url = species['evolution_chain']['url'] res_evo = requests.get(evo_url) res_evo.raise_for_status() evolution_chain = res_evo.json() name = data['name'].capitalize() pokemon_id = data['id'] types = ", ".join([t['type']['name'].capitalize() for t in data['types']]) height = data['height'] / 10 weight = data['weight'] / 10 base_stats = {s['stat']['name']: s['base_stat'] for s in data['stats']} stats_lv = {k: calculate_stat(v, level, stat_name=k) for k, v in base_stats.items()} flavor_text = next( (entry['flavor_text'].replace("\n", " ").replace("\f", " ") for entry in species['flavor_text_entries'] if entry['language']['name'] == 'en'), "No description available." ) def get_evolutions(chain): evols = [chain['species']['name'].capitalize()] if chain['evolves_to']: for evo in chain['evolves_to']: evols.extend(get_evolutions(evo)) return evols def get_moves(data, level_max, version_group): moves = [] for m in data['moves']: for v in m['version_group_details']: if ( v['version_group']['name'] == version_group and v['move_learn_method']['name'] == 'level-up' and v['level_learned_at'] <= level_max ): move_details = get_move_details(m['move']['url']) move_details['level'] = v['level_learned_at'] moves.append(move_details) moves.sort(key=lambda m: m['level']) return moves evolutions = get_evolutions(evolution_chain['chain']) evolution_text = " → ".join(evolutions) moves = get_moves(data, level, version_group) # Markdown attack section if moves: moves_text = "\n".join([ f"### 🔹 Lv {m['level']} : **{m['name']}**\n" f"- Type: {m['type'].capitalize()} \n" f"- Category: {m['category'].capitalize()} \n" f"- Power: {m['power'] or '—'} \n" f"- Accuracy: {m['accuracy'] or '—'} \n" f"- Effect: {m['effect']}" for m in moves ]) else: moves_text = "No available moves at this level." card_image_url = get_card_image_url(pokemon_name) card_image_md = f"![Carte Pokémon]({card_image_url})" if card_image_url else "_Carte non trouvée dans la base._" markdown = f""" # 📘 Pokémon Sheet: **{name}** (#{pokemon_id}) --- {card_image_md} --- **Type(s)**: {types} **Height**: {height} m **Weight**: {weight} kg --- ## 🔢 Base Stats | Stat | Value | |----------------|--------| | HP | {base_stats['hp']} | | Attack | {base_stats['attack']} | | Defense | {base_stats['defense']} | | Sp. Atk | {base_stats['special-attack']} | | Sp. Def | {base_stats['special-defense']} | | Speed | {base_stats['speed']} | --- ## 🎯 Stats at Level {level} | Stat | Value | |----------------|--------| | HP | {stats_lv['hp']} | | Attack | {stats_lv['attack']} | | Defense | {stats_lv['defense']} | | Sp. Atk | {stats_lv['special-attack']} | | Sp. Def | {stats_lv['special-defense']} | | Speed | {stats_lv['speed']} | --- ## 🔁 Evolution Chain {evolution_text} --- ## 📜 Moves up to Level {level} (version: {version_group.replace('-', ' ').title()}) {moves_text} --- ## 📖 Description > {flavor_text} """ return markdown.strip() except requests.exceptions.HTTPError: return "❌ Pokémon not found. Check the name." except Exception as e: return f"⚠️ Error: {str(e)}" # Example usage #print(get_pokemon_info("scyther", level=50)) def get_card_image_url(pokemon_name: str) -> str: """ Recherche dans ChromaDB une carte dont le nom correspond au Pokémon donné. Retourne l'URL de l'image ou None. """ results = collection.get(where={"name": pokemon_name.capitalize()}) if results and results['metadatas']: return results['metadatas'][0].get('image_url') return None