pokemon-mcp / pokedex.py
Houzeric's picture
Upload 6 files
cd9b20b verified
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