From cbed0adecad4dc9b3a345fb6cdcbd1a008af29a3 Mon Sep 17 00:00:00 2001
From: buttsaim2005 <buttsaim2005@gmail.com>
Date: Tue, 13 May 2025 20:59:46 +0200
Subject: [PATCH 1/3] add functions and routes

---
 .../src/controllers/userPokemonController.js  | 102 +++++++++++++-----
 backend/src/routes/main.js                    |  38 ++++---
 2 files changed, 96 insertions(+), 44 deletions(-)

diff --git a/backend/src/controllers/userPokemonController.js b/backend/src/controllers/userPokemonController.js
index f327b32..3a0debc 100644
--- a/backend/src/controllers/userPokemonController.js
+++ b/backend/src/controllers/userPokemonController.js
@@ -1,44 +1,35 @@
 import UserPokemon from '../models/userPokemon.js';
+import Entrenador from '../models/entrenador.js';
+import { getEffectiveness } from '../utils/typeEffectiveness.js';
 
 // 1. Listar todos los Pokémon del usuario (con datos de Pokémon)
 export const listUserPokemons = async (req, res) => {
   try {
-    const { userId } = req.params;
-    const userPokemons = await UserPokemon.findOne({ userId }).populate('pokemons.pokemonId');
-    if (!userPokemons) {
-      return res.status(404).json({ message: 'Pokémons no encontrados' });
-    }
-    res.status(200).json(userPokemons.pokemons);
+    const pokemons = await UserPokemon
+      .find({ userId: req.user._id })
+      .populate('pokemonId');
+    res.status(200).json(pokemons);
   } catch (err) {
     console.error(err);
-    res.status(500).json({ message: 'Error al obtener los Pokémon', error: err.message });
+    res.status(500).json({ message: 'Error al obtener tus Pokémon', error: err.message });
   }
 };
 
 // Función auxiliar para actualizar flags
 const updateFlag = async (req, res, flag, value) => {
   try {
-    console.log('userId desde sesión:', req.user.userId);  // Verifica si el userId está presente
-    console.log('pokemonId desde params:', req.params.pokemonId);  // Verifica si el pokemonId es correcto
-
-    const userPokemon = await UserPokemon.findOne({ userId: req.user.userId });
-
-    if (!userPokemon) {
-      return res.status(404).json({ message: 'Usuario no encontrado' });
-    }
+    const filter = { _id: req.params.id, userId: req.user._id };
+    const update = { [flag]: value };
+    const options = { new: true };
 
-    const pokemonIndex = userPokemon.pokemons.findIndex(p => p.pokemonId.toString() === req.params.pokemonId);
-    console.log('Índice del Pokémon encontrado:', pokemonIndex);  // Verifica si el índice es correcto
+    const updated = await UserPokemon
+      .findOneAndUpdate(filter, update, options)
+      .populate('pokemonId');
 
-    if (pokemonIndex === -1) {
-      return res.status(404).json({ message: 'Pokémon no encontrado para este usuario' });
+    if (!updated) {
+      return res.status(404).json({ message: 'Asociación usuario–Pokémon no encontrada' });
     }
-
-    userPokemon.pokemons[pokemonIndex][flag] = value;
-
-    await userPokemon.save();
-
-    res.status(200).json({ message: `Estado de ${flag} actualizado correctamente` });
+    res.status(200).json(updated);
 
   } catch (err) {
     console.error(err);
@@ -46,7 +37,6 @@ const updateFlag = async (req, res, flag, value) => {
   }
 };
 
-
 // 2. Añadir a la caja
 export const addToBox    = (req, res) => updateFlag(req, res, 'isInBox', true);
 // 3. Quitar de la caja
@@ -54,4 +44,62 @@ export const removeFromBox = (req, res) => updateFlag(req, res, 'isInBox', false
 // 4. Añadir al equipo
 export const addToTeam   = (req, res) => updateFlag(req, res, 'isInTeam', true);
 // 5. Quitar del equipo
-export const removeFromTeam = (req, res) => updateFlag(req, res, 'isInTeam', false);
\ No newline at end of file
+export const removeFromTeam = (req, res) => updateFlag(req, res, 'isInTeam', false);
+
+// 6. Obtener ubicaciones únicas de entrenadores
+export const getTrainerLocations = async (req, res) => {
+  try {
+    const locations = await Entrenador.distinct('ubicacion');
+    res.status(200).json(locations);
+  } catch (err) {
+    console.error(err);
+    res.status(500).json({ message: 'Error al obtener ubicaciones', error: err.message });
+  }
+};
+
+// 7. Obtener entrenadores por ubicación
+export const getTrainersByLocation = async (req, res) => {
+  try {
+    const { ubicacion } = req.params;
+    const entrenadores = await Entrenador.find({ ubicacion }).populate('equipo');
+    res.status(200).json(entrenadores);
+  } catch (err) {
+    console.error(err);
+    res.status(500).json({ message: 'Error al obtener entrenadores', error: err.message });
+  }
+};
+
+// 8. Calcular Pokémon efectivos contra entrenadores de una ubicación
+export const getEffectiveUserPokemons = async (req, res) => {
+  try {
+    const { ubicacion } = req.params;
+
+    // 1. Obtener pokémon en caja del usuario
+    const userPokemons = await UserPokemon.find({ userId: req.user._id, isInBox: true }).populate('pokemonId');
+
+    // 2. Obtener entrenadores en esa ubicación con sus equipos
+    const entrenadores = await Entrenador.find({ ubicacion }).populate('equipo');
+
+    // 3. Construir lista de tipos de oponentes
+    const enemyTypes = [];
+    for (const entrenador of entrenadores) {
+      for (const poke of entrenador.equipo) {
+        if (poke.tipo_1) enemyTypes.push(poke.tipo_1);
+        if (poke.tipo_2) enemyTypes.push(poke.tipo_2);
+      }
+    }
+
+    // 4. Evaluar efectividad de cada Pokémon del usuario
+    const efectivos = userPokemons.filter(p => {
+      const types = [p.pokemonId.tipo_1, p.pokemonId.tipo_2].filter(Boolean);
+      const effect = getEffectiveness(types, enemyTypes);
+      return effect > 1; // Solo devolvemos los que sean efectivos
+    });
+
+    res.status(200).json(efectivos);
+
+  } catch (err) {
+    console.error(err);
+    res.status(500).json({ message: 'Error al calcular efectividad', error: err.message });
+  }
+};
\ No newline at end of file
diff --git a/backend/src/routes/main.js b/backend/src/routes/main.js
index 2a0625f..833363e 100644
--- a/backend/src/routes/main.js
+++ b/backend/src/routes/main.js
@@ -3,7 +3,7 @@ import * as userController from '../controllers/userController.js';
 import * as pokemonController from '../controllers/pokemonController.js';
 import * as objectController from '../controllers/objectController.js';
 import * as entrenadorController from '../controllers/entrenadorController.js';
-import * as userPokemonController from '../controllers/userPokemonController.js';  // nuevo
+import * as userPokemonController from '../controllers/userPokemonController.js';
 
 const router = express.Router();
 
@@ -21,17 +21,6 @@ const isAuthenticated = (req, res, next) => {
   return res.status(401).json({ message: 'No autenticado' });
 };
 
-// En el router de Express
-router.get('/api/auth/check', isAuthenticated, (req, res) => {
-  res.json({ username: req.user.username });
-});
-
-// Ruta para obtener el userId del usuario autenticado
-router.get('/userId', isAuthenticated, (req, res) => {
-  res.json({ userId: req.session.user.userId });
-});
-
-
 // --- Rutas públicas ---
 router.get('/', (req, res) => {
   res.json({ message: 'Conexión exitosa desde el backend :)' });
@@ -47,13 +36,22 @@ router.post('/logout', (req, res) => {
   });
 });
 
-// --- Rutas de usuario autenticado ---
+// --- Rutas autenticadas ---
 router.use(isAuthenticated);
 
+// Ruta de comprobación de autenticación
+router.get('/api/auth/check', (req, res) => {
+  res.json({ username: req.user.username });
+});
+
+// Ruta para obtener el userId del usuario autenticado
+router.get('/userId', (req, res) => {
+  res.json({ userId: req.session.user.userId });
+});
+
 // Ruta para obtener los Pokémon de un usuario
 router.get('/user/:userId/pokemons', userPokemonController.listUserPokemons);
 
-
 // Flags caja/equipo
 router.put('/user/pokemon/:pokemonId/box', (req, res, next) => {
   console.log('Ruta accedida:', req.originalUrl);
@@ -62,6 +60,12 @@ router.put('/user/pokemon/:pokemonId/box', (req, res, next) => {
 router.delete('/user/pokemon/:pokemonId/box', userPokemonController.removeFromBox);
 router.put('/user/pokemon/:pokemonId/team', userPokemonController.addToTeam);
 router.delete('/user/pokemon/:pokemonId/team', userPokemonController.removeFromTeam);
+
+// --- Rutas adicionales del usuario ---
+router.get('/trainer-locations', userPokemonController.getTrainerLocations);
+router.get('/trainers/:ubicacion', userPokemonController.getTrainersByLocation);
+router.get('/effective-pokemons/:ubicacion', userPokemonController.getEffectiveUserPokemons);
+
 // --- Rutas de administrador ---
 router.use('/admin', isAdmin);
 
@@ -72,11 +76,11 @@ router.put('/admin/editPokemon/:id', pokemonController.editPokemon);
 router.delete('/admin/pokemons/:id', pokemonController.deletePokemon);
 
 // Objetos
-router.post(  '/admin/objects', objectController.createObject);
-router.put(   '/admin/objects/:id', objectController.editObject);
+router.post('/admin/objects', objectController.createObject);
+router.put('/admin/objects/:id', objectController.editObject);
 router.delete('/admin/objects/:id', objectController.deleteObject);
 
 // Entrenadores
-router.get(   '/admin/getEntrenadores', entrenadorController.listEntrenadores);
+router.get('/admin/getEntrenadores', entrenadorController.listEntrenadores);
 
 export default router;
\ No newline at end of file
-- 
GitLab


From 951658bffddad66db3f3754ec1d96062d63db4b6 Mon Sep 17 00:00:00 2001
From: SAIM2005 <buttsaim2005@gmail.com>
Date: Wed, 14 May 2025 15:36:12 +0200
Subject: [PATCH 2/3] arreglar funcion

---
 backend/data/entrenadores.json                |  34 ++-
 backend/data/pokemons.json                    | 251 ++++++++++++++++--
 .../src/controllers/userPokemonController.js  | 138 +++++++---
 backend/src/routes/main.js                    |   3 +-
 frontend/src/router/AppRoutes.js              |   3 +
 frontend/src/views/Home.js                    |   1 +
 frontend/src/views/PokemonEfectivo.js         | 113 ++++++++
 frontend/src/views/PokemonUserList.js         |  16 +-
 frontend/src/views/TrainerList.js             |   2 +-
 9 files changed, 482 insertions(+), 79 deletions(-)
 create mode 100644 frontend/src/views/PokemonEfectivo.js

diff --git a/backend/data/entrenadores.json b/backend/data/entrenadores.json
index c74bd52..ea14872 100644
--- a/backend/data/entrenadores.json
+++ b/backend/data/entrenadores.json
@@ -1,9 +1,8 @@
 [
   {
-    "nombre": "Rival (elige Charmander)",
+    "nombre": "Rival 1",
     "rol": "Rival",
     "ubicacion": "Laboratorio del Profesor Oak",
-    "obligatorio": true,
     "equipo": [
       {
         "nombre": "Charmander",
@@ -12,10 +11,9 @@
     ]
   },
   {
-    "nombre": "Rival (elige Squirtle)",
+    "nombre": "Rival 2",
     "rol": "Rival",
     "ubicacion": "Laboratorio del Profesor Oak",
-    "obligatorio": true,
     "equipo": [
       {
         "nombre": "Squirtle",
@@ -24,10 +22,9 @@
     ]
   },
   {
-    "nombre": "Rival (elige Bulbasaur)",
+    "nombre": "Rival 3",
     "rol": "Rival",
     "ubicacion": "Laboratorio del Profesor Oak",
-    "obligatorio": true,
     "equipo": [
       {
         "nombre": "Bulbasaur",
@@ -39,7 +36,6 @@
     "nombre": "Brock",
     "rol": "Líder de gimnasio",
     "ubicacion": "Gimnasio de Ciudad Plateada",
-    "obligatorio": true,
     "equipo": [
       {
         "nombre": "Geodude",
@@ -50,5 +46,27 @@
         "nivel": 14
       }
     ]
+  },
+  {
+    "nombre": "Rival 13",
+    "rol": "Opcional",
+    "ubicacion": "Cueva Celeste",
+    "equipo": [
+      {
+        "nombre": "Charizard",
+        "nivel": 50
+      }
+    ]
+  },
+  {
+    "nombre": "Rival 99",
+    "rol": "Opcional",
+    "ubicacion": "Monte Moon",
+    "equipo": [
+      {
+        "nombre": "Blastoise",
+        "nivel": 50
+      }
+    ]
   }
-]
+]
\ No newline at end of file
diff --git a/backend/data/pokemons.json b/backend/data/pokemons.json
index 5e240e5..e59cbd2 100644
--- a/backend/data/pokemons.json
+++ b/backend/data/pokemons.json
@@ -8,81 +8,276 @@
       "tipo_2": "Veneno",
       "ataques": [
         { "nombre": "Látigo Cepa", "tipo": "Planta", "poder": 40 },
-        { "nombre": "Rastrillo", "tipo": "Normal", "poder": 15 }
+        { "nombre": "Residuos", "tipo": "Veneno", "poder": 30 }
       ],
       "evoluciones": [{ "nivel": 16, "pokemon": "Ivysaur" }]
     },
     {
       "id": 2,
+      "nombre": "Ivysaur",
+      "nivel": 16,
+      "tipo_1": "Planta",
+      "tipo_2": "Veneno",
+      "ataques": [
+        { "nombre": "Megaagotar", "tipo": "Planta", "poder": 50 },
+        { "nombre": "Residuos", "tipo": "Veneno", "poder": 30 }
+      ],
+      "evoluciones": [{ "nivel": 36, "pokemon": "Venusaur" }]
+    },
+    {
+      "id": 3,
+      "nombre": "Venusaur",
+      "nivel": 36,
+      "tipo_1": "Planta",
+      "tipo_2": "Veneno",
+      "ataques": [
+        { "nombre": "Gigadrenado", "tipo": "Planta", "poder": 75 },
+        { "nombre": "Bomba Lodo", "tipo": "Veneno", "poder": 80 }
+      ]
+    },
+    {
+      "id": 4,
       "nombre": "Charmander",
       "nivel": 5,
       "tipo_1": "Fuego",
       "tipo_2": null,
       "ataques": [
         { "nombre": "Ascuas", "tipo": "Fuego", "poder": 40 },
-        { "nombre": "Gruñido", "tipo": "Normal", "poder": 0 }
+        { "nombre": "Garra Metal", "tipo": "Acero", "poder": 40 }
       ],
       "evoluciones": [{ "nivel": 16, "pokemon": "Charmeleon" }]
     },
     {
-      "id": 3,
+      "id": 5,
+      "nombre": "Charmeleon",
+      "nivel": 16,
+      "tipo_1": "Fuego",
+      "tipo_2": null,
+      "ataques": [
+        { "nombre": "Pirotecnia", "tipo": "Fuego", "poder": 60 },
+        { "nombre": "Mordisco", "tipo": "Siniestro", "poder": 60 }
+      ],
+      "evoluciones": [{ "nivel": 36, "pokemon": "Charizard" }]
+    },
+    {
+      "id": 6,
+      "nombre": "Charizard",
+      "nivel": 36,
+      "tipo_1": "Fuego",
+      "tipo_2": "Volador",
+      "ataques": [
+        { "nombre": "Lanzallamas", "tipo": "Fuego", "poder": 90 },
+        { "nombre": "Tajo Aéreo", "tipo": "Volador", "poder": 75 }
+      ]
+    },
+    {
+      "id": 7,
       "nombre": "Squirtle",
       "nivel": 5,
       "tipo_1": "Agua",
       "tipo_2": null,
       "ataques": [
         { "nombre": "Pistola Agua", "tipo": "Agua", "poder": 40 },
-        { "nombre": "Gruñido", "tipo": "Normal", "poder": 0 }
+        { "nombre": "Placaje", "tipo": "Normal", "poder": 40 }
       ],
       "evoluciones": [{ "nivel": 16, "pokemon": "Wartortle" }]
     },
     {
-      "id": 4,
-      "nombre": "Rattata",
-      "nivel": 3,
-      "tipo_1": "Normal",
+      "id": 8,
+      "nombre": "Wartortle",
+      "nivel": 16,
+      "tipo_1": "Agua",
       "tipo_2": null,
       "ataques": [
-        { "nombre": "Mordisco", "tipo": "Siniestro", "poder": 60 },
-        { "nombre": "Gruñido", "tipo": "Normal", "poder": 0 }
+        { "nombre": "Hidropulso", "tipo": "Agua", "poder": 60 },
+        { "nombre": "Mordisco", "tipo": "Siniestro", "poder": 60 }
       ],
-      "evoluciones": [{ "nivel": 20, "pokemon": "Raticate" }]
+      "evoluciones": [{ "nivel": 36, "pokemon": "Blastoise" }]
     },
     {
-      "id": 5,
+      "id": 9,
+      "nombre": "Blastoise",
+      "nivel": 36,
+      "tipo_1": "Agua",
+      "tipo_2": null,
+      "ataques": [
+        { "nombre": "Surf", "tipo": "Agua", "poder": 90 },
+        { "nombre": "Rayo Hielo", "tipo": "Hielo", "poder": 90 }
+      ]
+    },
+    {
+      "id": 10,
+      "nombre": "Caterpie",
+      "nivel": 5,
+      "tipo_1": "Bicho",
+      "tipo_2": null,
+      "ataques": [
+        { "nombre": "Placaje", "tipo": "Normal", "poder": 40 },
+        { "nombre": "Disparo Demora", "tipo": "Bicho", "poder": 0 }
+      ],
+      "evoluciones": [{ "nivel": 7, "pokemon": "Metapod" }]
+    },
+    {
+      "id": 11,
+      "nombre": "Metapod",
+      "nivel": 7,
+      "tipo_1": "Bicho",
+      "tipo_2": null,
+      "ataques": [
+        { "nombre": "Placaje", "tipo": "Normal", "poder": 40 },
+        { "nombre": "Fortaleza", "tipo": "Normal", "poder": 0 }
+      ],
+      "evoluciones": [{ "nivel": 10, "pokemon": "Butterfree" }]
+    },
+    {
+      "id": 12,
+      "nombre": "Butterfree",
+      "nivel": 10,
+      "tipo_1": "Bicho",
+      "tipo_2": "Volador",
+      "ataques": [
+        { "nombre": "Picadura", "tipo": "Bicho", "poder": 60 },
+        { "nombre": "Tornado", "tipo": "Volador", "poder": 50 }
+      ]
+    },
+    {
+      "id": 13,
+      "nombre": "Weedle",
+      "nivel": 5,
+      "tipo_1": "Bicho",
+      "tipo_2": "Veneno",
+      "ataques": [
+        { "nombre": "Picotazo Venenoso", "tipo": "Veneno", "poder": 20 },
+        { "nombre": "Cornada", "tipo": "Normal", "poder": 30 }
+      ],
+      "evoluciones": [{ "nivel": 7, "pokemon": "Kakuna" }]
+    },
+    {
+      "id": 14,
+      "nombre": "Kakuna",
+      "nivel": 7,
+      "tipo_1": "Bicho",
+      "tipo_2": "Veneno",
+      "ataques": [
+        { "nombre": "Picotazo Venenoso", "tipo": "Veneno", "poder": 20 },
+        { "nombre": "Fortaleza", "tipo": "Normal", "poder": 0 }
+      ],
+      "evoluciones": [{ "nivel": 10, "pokemon": "Beedrill" }]
+    },
+    {
+      "id": 15,
+      "nombre": "Beedrill",
+      "nivel": 10,
+      "tipo_1": "Bicho",
+      "tipo_2": "Veneno",
+      "ataques": [
+        { "nombre": "Picadura", "tipo": "Bicho", "poder": 60 },
+        { "nombre": "Puya Nociva", "tipo": "Veneno", "poder": 80 }
+      ]
+    },
+    {
+      "id": 16,
       "nombre": "Pidgey",
-      "nivel": 3,
+      "nivel": 5,
       "tipo_1": "Normal",
       "tipo_2": "Volador",
       "ataques": [
-        { "nombre": "Ataque Rápido", "tipo": "Normal", "poder": 40 },
-        { "nombre": "Giro Rapido", "tipo": "Normal", "poder": 40 }
+        { "nombre": "Tornado", "tipo": "Volador", "poder": 40 },
+        { "nombre": "Placaje", "tipo": "Normal", "poder": 40 }
       ],
-      "evoluciones": [{ "nivel": 18, "pokemon": "Pidgeot" }]
+      "evoluciones": [{ "nivel": 16, "pokemon": "Pidgeotto" }]
     },
     {
-      "id": 6,
+      "id": 17,
+      "nombre": "Pidgeotto",
+      "nivel": 16,
+      "tipo_1": "Normal",
+      "tipo_2": "Volador",
+      "ataques": [
+        { "nombre": "Aire Afilado", "tipo": "Volador", "poder": 55 },
+        { "nombre": "Derribo", "tipo": "Normal", "poder": 60 }
+      ],
+      "evoluciones": [{ "nivel": 36, "pokemon": "Pidgeot" }]
+    },
+    {
+      "id": 18,
+      "nombre": "Pidgeot",
+      "nivel": 36,
+      "tipo_1": "Normal",
+      "tipo_2": "Volador",
+      "ataques": [
+        { "nombre": "Vendaval", "tipo": "Volador", "poder": 100 },
+        { "nombre": "Vozarrón", "tipo": "Normal", "poder": 100 }
+      ]
+    },
+    {
+      "id": 19,
+      "nombre": "Rattata",
+      "nivel": 5,
+      "tipo_1": "Normal",
+      "tipo_2": null,
+      "ataques": [
+        { "nombre": "Placaje", "tipo": "Normal", "poder": 40 },
+        { "nombre": "Mordisco", "tipo": "Siniestro", "poder": 40 }
+      ],
+      "evoluciones": [{ "nivel": 20, "pokemon": "Raticate" }]
+    },
+    {
+      "id": 20,
+      "nombre": "Raticate",
+      "nivel": 20,
+      "tipo_1": "Normal",
+      "tipo_2": null,
+      "ataques": [
+        { "nombre": "Derribo", "tipo": "Normal", "poder": 60 },
+        { "nombre": "Triturar", "tipo": "Siniestro", "poder": 70 }
+      ]
+    },
+    {
+      "id": 74,
       "nombre": "Geodude",
-      "nivel": 12,
+      "nivel": 5,
       "tipo_1": "Roca",
       "tipo_2": "Tierra",
       "ataques": [
-        { "nombre": "Lanzarrocas", "tipo": "Roca", "poder": 50 },
-        { "nombre": "Magnitud", "tipo": "Tierra", "poder": 60 }
+        { "nombre": "Lanzarrocas", "tipo": "Roca", "poder": 40 },
+        { "nombre": "Disparo Lodo", "tipo": "Tierra", "poder": 40 }
       ],
-      "evoluciones": [{ "nivel": 25, "pokemon": "Graveler" }]
+      "evoluciones": [{ "nivel": 20, "pokemon": "Graveler" }]
     },
     {
-      "id": 7,
-      "nombre": "Onix",
-      "nivel": 14,
+      "id": 75,
+      "nombre": "Graveler",
+      "nivel": 20,
       "tipo_1": "Roca",
       "tipo_2": "Tierra",
       "ataques": [
-        { "nombre": "Golpe Roca", "tipo": "Roca", "poder": 50 },
-        { "nombre": "Tierra Viva", "tipo": "Tierra", "poder": 100 }
+        { "nombre": "Magnitud", "tipo": "Tierra", "poder": 60 },
+        { "nombre": "Avalancha", "tipo": "Roca", "poder": 60 }
       ],
-      "evoluciones": [{ "nivel": 0, "pokemon": "Steelix" }]
+      "evoluciones": [{ "nivel": 40, "pokemon": "Golem" }]
+    },
+    {
+      "id": 76,
+      "nombre": "Golem",
+      "nivel": 40,
+      "tipo_1": "Roca",
+      "tipo_2": "Tierra",
+      "ataques": [
+        { "nombre": "Roca Afilada", "tipo": "Roca", "poder": 100 },
+        { "nombre": "Terremoto", "tipo": "Tierra", "poder": 100 }
+      ]
+    },
+    {
+      "id": 95,
+      "nombre": "Onix",
+      "nivel": 15,
+      "tipo_1": "Roca",
+      "tipo_2": "Tierra",
+      "ataques": [
+        { "nombre": "Magnitud", "tipo": "Tierra", "poder": 50 },
+        { "nombre": "Antiaéreo", "tipo": "Roca", "poder": 50 }
+      ]
     }
   ]
-}
+}
\ No newline at end of file
diff --git a/backend/src/controllers/userPokemonController.js b/backend/src/controllers/userPokemonController.js
index 3a0debc..148db55 100644
--- a/backend/src/controllers/userPokemonController.js
+++ b/backend/src/controllers/userPokemonController.js
@@ -1,35 +1,45 @@
 import UserPokemon from '../models/userPokemon.js';
-import Entrenador from '../models/entrenador.js';
-import { getEffectiveness } from '../utils/typeEffectiveness.js';
+import Entrenador from '../models/entrenadores.js';
 
 // 1. Listar todos los Pokémon del usuario (con datos de Pokémon)
 export const listUserPokemons = async (req, res) => {
   try {
-    const pokemons = await UserPokemon
-      .find({ userId: req.user._id })
-      .populate('pokemonId');
-    res.status(200).json(pokemons);
+    const { userId } = req.params;
+    const userPokemons = await UserPokemon.findOne({ userId }).populate('pokemons.pokemonId');
+    if (!userPokemons) {
+      return res.status(404).json({ message: 'Pokémons no encontrados' });
+    }
+    res.status(200).json(userPokemons.pokemons);
   } catch (err) {
     console.error(err);
-    res.status(500).json({ message: 'Error al obtener tus Pokémon', error: err.message });
+    res.status(500).json({ message: 'Error al obtener los Pokémon', error: err.message });
   }
 };
 
 // Función auxiliar para actualizar flags
 const updateFlag = async (req, res, flag, value) => {
   try {
-    const filter = { _id: req.params.id, userId: req.user._id };
-    const update = { [flag]: value };
-    const options = { new: true };
+    console.log('userId desde sesión:', req.user.userId);  // Verifica si el userId está presente
+    console.log('pokemonId desde params:', req.params.pokemonId);  // Verifica si el pokemonId es correcto
+
+    const userPokemon = await UserPokemon.findOne({ userId: req.user.userId });
+
+    if (!userPokemon) {
+      return res.status(404).json({ message: 'Usuario no encontrado' });
+    }
 
-    const updated = await UserPokemon
-      .findOneAndUpdate(filter, update, options)
-      .populate('pokemonId');
+    const pokemonIndex = userPokemon.pokemons.findIndex(p => p._id.toString() === req.params.pokemonId);
+    console.log('Índice del Pokémon encontrado:', pokemonIndex);  // Verifica si el índice es correcto
 
-    if (!updated) {
-      return res.status(404).json({ message: 'Asociación usuario–Pokémon no encontrada' });
+    if (pokemonIndex === -1) {
+      return res.status(404).json({ message: 'Pokémon no encontrado para este usuario' });
     }
-    res.status(200).json(updated);
+
+    userPokemon.pokemons[pokemonIndex][flag] = value;
+
+    await userPokemon.save();
+
+    res.status(200).json({ message: `Estado de ${flag} actualizado correctamente` });
 
   } catch (err) {
     console.error(err);
@@ -38,11 +48,14 @@ const updateFlag = async (req, res, flag, value) => {
 };
 
 // 2. Añadir a la caja
-export const addToBox    = (req, res) => updateFlag(req, res, 'isInBox', true);
+export const addToBox = (req, res) => updateFlag(req, res, 'isInBox', true);
+
 // 3. Quitar de la caja
 export const removeFromBox = (req, res) => updateFlag(req, res, 'isInBox', false);
+
 // 4. Añadir al equipo
-export const addToTeam   = (req, res) => updateFlag(req, res, 'isInTeam', true);
+export const addToTeam = (req, res) => updateFlag(req, res, 'isInTeam', true);
+
 // 5. Quitar del equipo
 export const removeFromTeam = (req, res) => updateFlag(req, res, 'isInTeam', false);
 
@@ -72,34 +85,93 @@ export const getTrainersByLocation = async (req, res) => {
 // 8. Calcular Pokémon efectivos contra entrenadores de una ubicación
 export const getEffectiveUserPokemons = async (req, res) => {
   try {
-    const { ubicacion } = req.params;
+    const { ubicacion, entrenadorId } = req.params;
 
-    // 1. Obtener pokémon en caja del usuario
-    const userPokemons = await UserPokemon.find({ userId: req.user._id, isInBox: true }).populate('pokemonId');
+    // 1. Obtener TODOS los Pokémon del usuario
+    const userData = await UserPokemon.findOne({ userId: req.user.userId }).populate('pokemons.pokemonId');
 
-    // 2. Obtener entrenadores en esa ubicación con sus equipos
-    const entrenadores = await Entrenador.find({ ubicacion }).populate('equipo');
+    if (!userData) {
+      return res.status(404).json({ message: 'No se encontró el usuario' });
+    }
+
+    const pokemonsEnCaja = userData.pokemons.filter(p => p.isInBox && p.pokemonId);
+
+    // 2. Obtener entrenador específico
+    const entrenador = await Entrenador.findOne({ _id: entrenadorId, ubicacion }).populate('equipo');
 
-    // 3. Construir lista de tipos de oponentes
+    if (!entrenador) {
+      return res.status(404).json({ message: 'Entrenador no encontrado en esa ubicación' });
+    }
+
+    // 3. Extraer tipos de su equipo
     const enemyTypes = [];
-    for (const entrenador of entrenadores) {
-      for (const poke of entrenador.equipo) {
-        if (poke.tipo_1) enemyTypes.push(poke.tipo_1);
-        if (poke.tipo_2) enemyTypes.push(poke.tipo_2);
-      }
+    for (const poke of entrenador.equipo) {
+      if (poke.tipo_1) enemyTypes.push(poke.tipo_1);
+      if (poke.tipo_2) enemyTypes.push(poke.tipo_2);
     }
 
-    // 4. Evaluar efectividad de cada Pokémon del usuario
-    const efectivos = userPokemons.filter(p => {
+    // 4. Calcular efectividad
+    const efectivos = pokemonsEnCaja.filter(p => {
       const types = [p.pokemonId.tipo_1, p.pokemonId.tipo_2].filter(Boolean);
       const effect = getEffectiveness(types, enemyTypes);
-      return effect > 1; // Solo devolvemos los que sean efectivos
+      return effect >= 1 && effect <= 2;
+    });
+
+    // 5. Filtrar última evolución
+    const lastEvolutions = [];
+    const seenNames = new Set();
+    const pokemonMap = new Map();
+
+    efectivos.forEach(pokemon => {
+      const { nombre, evoluciones } = pokemon.pokemonId;
+      if (!seenNames.has(nombre)) {
+        seenNames.add(nombre);
+        if (evoluciones.length > 0) {
+          const lastEvo = evoluciones.sort((a, b) => b.nivel - a.nivel)[0];
+          pokemonMap.set(nombre, lastEvo);
+        } else {
+          pokemonMap.set(nombre, pokemon.pokemonId);
+        }
+      }
     });
 
-    res.status(200).json(efectivos);
+    pokemonMap.forEach((evolution, nombre) => {
+      lastEvolutions.push({
+        ...evolution,
+        nombre,
+      });
+    });
 
+    res.status(200).json(lastEvolutions);
   } catch (err) {
     console.error(err);
     res.status(500).json({ message: 'Error al calcular efectividad', error: err.message });
   }
+};
+
+// -------------------------
+// Función local de efectividad
+// -------------------------
+const typeChart = {
+  Agua: { Fuego: 2, Planta: 0.5, Tierra: 2 },
+  Fuego: { Planta: 2, Agua: 0.5, Hielo: 2 },
+  Planta: { Agua: 2, Fuego: 0.5, Tierra: 2 },
+  Eléctrico: { Agua: 2, Tierra: 0, Volador: 2 },
+  Tierra: { Fuego: 2, Eléctrico: 2, Planta: 0.5 },
+  Hielo: { Planta: 2, Dragón: 2, Fuego: 0.5 },
+  Volador: { Planta: 2, Eléctrico: 0.5 },
+  Psíquico: { Lucha: 2, Fantasma: 0.5 },
+  Lucha: { Normal: 2, Psíquico: 0.5 },
+  Fantasma: { Psíquico: 2, Normal: 0 },
+};
+
+const getEffectiveness = (userTypes, enemyTypes) => {
+  let total = 0;
+  for (const uType of userTypes) {
+    for (const eType of enemyTypes) {
+      const mult = typeChart[uType]?.[eType] ?? 1;
+      total += mult;
+    }
+  }
+  return total / (userTypes.length * enemyTypes.length || 1); // promedio
 };
\ No newline at end of file
diff --git a/backend/src/routes/main.js b/backend/src/routes/main.js
index 833363e..e7d3332 100644
--- a/backend/src/routes/main.js
+++ b/backend/src/routes/main.js
@@ -64,8 +64,7 @@ router.delete('/user/pokemon/:pokemonId/team', userPokemonController.removeFromT
 // --- Rutas adicionales del usuario ---
 router.get('/trainer-locations', userPokemonController.getTrainerLocations);
 router.get('/trainers/:ubicacion', userPokemonController.getTrainersByLocation);
-router.get('/effective-pokemons/:ubicacion', userPokemonController.getEffectiveUserPokemons);
-
+router.get('/effective-pokemons/:ubicacion/:entrenadorId', userPokemonController.getEffectiveUserPokemons);
 // --- Rutas de administrador ---
 router.use('/admin', isAdmin);
 
diff --git a/frontend/src/router/AppRoutes.js b/frontend/src/router/AppRoutes.js
index da1d814..89df38e 100644
--- a/frontend/src/router/AppRoutes.js
+++ b/frontend/src/router/AppRoutes.js
@@ -9,6 +9,8 @@ import AdminHome from "../views/AdminHome.js";
 import AdminPokemon from "../views/AdminPokemon.js";
 import AdminPokemonAdd from "../views/AdminPokemonAdd.js";
 import AdminPokemonEdit from "../views/AdminPokemonEdit.js";
+import EffectivePokemonSelector from "../views/PokemonEfectivo.js";
+
 const AppRoutes = () => (
   <Routes>
     <Route path="/" element={<Navigate to="/login" />} />
@@ -22,6 +24,7 @@ const AppRoutes = () => (
     <Route path="/admin/pokemon" element={<AdminPokemon />} />
     <Route path="/admin/pokemon/add" element={<AdminPokemonAdd />} />
     <Route path="/admin/pokemon/edit/:id" element={<AdminPokemonEdit />} />
+    <Route path="/pokemonEfectivo" element={<EffectivePokemonSelector />} />
   </Routes>
 );
 
diff --git a/frontend/src/views/Home.js b/frontend/src/views/Home.js
index 348969b..f5b056f 100644
--- a/frontend/src/views/Home.js
+++ b/frontend/src/views/Home.js
@@ -11,6 +11,7 @@ const Home = () => (
       <Link to="/pokemons" className="btn btn-secondary btn-lg mx-2">Pokemons</Link>
       <Link to="/trainers" className="btn btn-secondary btn-lg mx-2">Entrenadores</Link>
       <Link to="/user/pokemons" className="btn btn-secondary btn-lg mx-2">Pokemons del usuario</Link>
+      <Link to="/pokemonEfectivo" className="btn btn-secondary btn-lg mx-2">Pokemon Efectivo</Link>
     </div>
   </div>
 );
diff --git a/frontend/src/views/PokemonEfectivo.js b/frontend/src/views/PokemonEfectivo.js
new file mode 100644
index 0000000..2ec4858
--- /dev/null
+++ b/frontend/src/views/PokemonEfectivo.js
@@ -0,0 +1,113 @@
+import React, { useEffect, useState } from 'react';
+import axios from 'axios';
+
+const EffectivePokemonSelector = () => {
+  const [locations, setLocations] = useState([]);
+  const [selectedLocation, setSelectedLocation] = useState('');
+  const [trainers, setTrainers] = useState([]);
+  const [selectedTrainer, setSelectedTrainer] = useState('');
+  const [effectivePokemons, setEffectivePokemons] = useState([]);
+  const [loading, setLoading] = useState(false);
+
+  // Obtener ubicaciones
+  const fetchLocations = async () => {
+    try {
+      const res = await axios.get('http://localhost:5000/trainer-locations', {
+        withCredentials: true
+      });
+      setLocations(res.data);
+    } catch (err) {
+      console.error('Error al obtener ubicaciones:', err);
+    }
+  };
+
+  // Obtener entrenadores en la ubicación seleccionada
+  const fetchTrainers = async (location) => {
+    try {
+      const res = await axios.get(`http://localhost:5000/trainers/${location}`, {
+        withCredentials: true
+      });
+      setTrainers(res.data);
+    } catch (err) {
+      console.error('Error al obtener entrenadores:', err);
+    }
+  };
+
+  // Obtener Pokémon efectivos contra el entrenador seleccionado
+  const fetchEffectivePokemons = async (location, trainerId) => {
+    setLoading(true);
+    try {
+      const res = await axios.get(`http://localhost:5000/effective-pokemons/${location}/${trainerId}`, {
+        withCredentials: true
+      });
+      setEffectivePokemons(res.data);
+    } catch (err) {
+      console.error('Error al obtener Pokémon efectivos:', err);
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  useEffect(() => {
+    fetchLocations();
+  }, []);
+
+  useEffect(() => {
+    if (selectedLocation) {
+      fetchTrainers(selectedLocation);
+      setEffectivePokemons([]);
+      setSelectedTrainer('');
+    }
+  }, [selectedLocation]);
+
+  useEffect(() => {
+    if (selectedLocation && selectedTrainer) {
+      fetchEffectivePokemons(selectedLocation, selectedTrainer);
+    }
+  }, [selectedTrainer]);
+
+  return (
+    <div>
+      <h2>Selecciona una ubicación</h2>
+      <select onChange={(e) => setSelectedLocation(e.target.value)} value={selectedLocation}>
+        <option value="">-- Ubicación --</option>
+        {locations.map((loc) => (
+          <option key={loc} value={loc}>
+            {loc}
+          </option>
+        ))}
+      </select>
+
+      {trainers.length > 0 && (
+        <>
+          <h2>Selecciona un entrenador</h2>
+          <select onChange={(e) => setSelectedTrainer(e.target.value)} value={selectedTrainer}>
+            <option value="">-- Entrenador --</option>
+            {trainers.map((trainer) => (
+              <option key={trainer._id} value={trainer._id}>
+                {trainer.nombre}
+              </option>
+            ))}
+          </select>
+        </>
+      )}
+
+      {loading ? (
+        <p>Cargando Pokémon efectivos...</p>
+      ) : (
+        <>
+          <h2>Pokémon efectivos</h2>
+          <ul>
+            {effectivePokemons.map((pokemon, idx) => (
+              <li key={idx}>
+                {pokemon.nombre} {pokemon.tipo_1 && `(${pokemon.tipo_1}`}{pokemon.tipo_2 && ` / ${pokemon.tipo_2}`}{(pokemon.tipo_1 || pokemon.tipo_2) && ')'}
+              </li>
+            ))}
+          </ul>
+        </>
+      )}
+    </div>
+  );
+};
+
+export default EffectivePokemonSelector;
\ No newline at end of file
diff --git a/frontend/src/views/PokemonUserList.js b/frontend/src/views/PokemonUserList.js
index 3541d26..e71ff37 100644
--- a/frontend/src/views/PokemonUserList.js
+++ b/frontend/src/views/PokemonUserList.js
@@ -1,6 +1,6 @@
 import { useState, useEffect } from 'react';
 import axios from 'axios';
-
+import { Link } from 'react-router-dom';
 const UserPokemonList = () => {
   const [pokemons, setPokemons] = useState([]);
   const [loading, setLoading] = useState(true);
@@ -81,37 +81,39 @@ const UserPokemonList = () => {
 
   return (
     <div className="container py-5">
+            <Link to="/pokemonEfectivo" className="btn btn-secondary btn-lg mx-2">Pokemon Efectivo</Link>
       <h2 className="text-center mb-4">Mis Pokémon</h2>
       <ul className="list-group">
         {pokemons.map(pokemon => (
-          <li key={pokemon.pokemonId._id} className="list-group-item d-flex justify-content-between align-items-center">
+          <li key={pokemon._id} className="list-group-item d-flex justify-content-between align-items-center">
             <div>
-              <strong>{pokemon.pokemonId.nombre}</strong> - Nivel: {pokemon.nivel ? pokemon.nivel : 'Desconocido'} - Tipo: {pokemon.pokemonId.tipo_1}
+              <strong>{pokemon.pokemonId.nombre}</strong> - Nivel: {pokemon.nivel ?? 'Desconocido'} - Tipo: {pokemon.pokemonId.tipo_1}
               {pokemon.pokemonId.tipo_2 ? ` / ${pokemon.pokemonId.tipo_2}` : ''}
             </div>
             <div>
               {pokemon.isInBox ? (
-                <button className="btn btn-outline-danger btn-sm me-2" onClick={() => removeFromBox(pokemon.pokemonId._id)}>
+                <button className="btn btn-outline-danger btn-sm me-2" onClick={() => removeFromBox(pokemon._id)}>
                   Quitar de Caja
                 </button>
               ) : (
-                <button className="btn btn-outline-primary btn-sm me-2" onClick={() => addToBox(pokemon.pokemonId._id)}>
+                <button className="btn btn-outline-primary btn-sm me-2" onClick={() => addToBox(pokemon._id)}>
                   Añadir a Caja
                 </button>
               )}
 
               {pokemon.isInTeam ? (
-                <button className="btn btn-outline-danger btn-sm" onClick={() => removeFromTeam(pokemon.pokemonId._id)}>
+                <button className="btn btn-outline-danger btn-sm" onClick={() => removeFromTeam(pokemon._id)}>
                   Quitar del Equipo
                 </button>
               ) : (
-                <button className="btn btn-outline-success btn-sm" onClick={() => addToTeam(pokemon.pokemonId._id)}>
+                <button className="btn btn-outline-success btn-sm" onClick={() => addToTeam(pokemon._id)}>
                   Añadir al Equipo
                 </button>
               )}
             </div>
           </li>
         ))}
+
       </ul>
     </div>
   );
diff --git a/frontend/src/views/TrainerList.js b/frontend/src/views/TrainerList.js
index 1ed47d8..4114738 100644
--- a/frontend/src/views/TrainerList.js
+++ b/frontend/src/views/TrainerList.js
@@ -16,7 +16,7 @@ const EntrenadorList = () => {
         } else {
           setError('La respuesta de la API no es un array');
         }
-        setLoading(false);
+        setLoading(false); 
       })
       .catch((err) => {
         if (err.response && err.response.status === 401) {
-- 
GitLab


From 28664c111d043f1ead07f0b26054daa90ee727a5 Mon Sep 17 00:00:00 2001
From: SAIM2005 <buttsaim2005@gmail.com>
Date: Thu, 15 May 2025 11:26:56 +0200
Subject: [PATCH 3/3]  acabado

---
 backend/data/typeChart.js                     |  22 ++
 .../src/controllers/entrenadorController.js   |  18 ++
 .../src/controllers/userPokemonController.js  | 114 +++-----
 backend/src/routes/main.js                    |  16 +-
 frontend/src/views/PokemonEfectivo.js         | 248 ++++++++++++------
 5 files changed, 263 insertions(+), 155 deletions(-)
 create mode 100644 backend/data/typeChart.js

diff --git a/backend/data/typeChart.js b/backend/data/typeChart.js
new file mode 100644
index 0000000..e6b9e30
--- /dev/null
+++ b/backend/data/typeChart.js
@@ -0,0 +1,22 @@
+const typeChart = {
+  Normal:     { Roca: 0.5, Fantasma: 0, Acero: 0.5 },
+  Fuego:      { Planta: 2, Hielo: 2, Bicho: 2, Acero: 2, Fuego: 0.5, Agua: 0.5, Roca: 0.5, Dragón: 0.5 },
+  Agua:       { Fuego: 2, Tierra: 2, Roca: 2, Agua: 0.5, Planta: 0.5, Dragón: 0.5 },
+  Planta:     { Agua: 2, Tierra: 2, Roca: 2, Fuego: 0.5, Planta: 0.5, Veneno: 0.5, Volador: 0.5, Bicho: 0.5, Dragón: 0.5, Acero: 0.5 },
+  Eléctrico:  { Agua: 2, Volador: 2, Planta: 0.5, Eléctrico: 0.5, Dragón: 0.5, Tierra: 0 },
+  Hielo:      { Planta: 2, Tierra: 2, Volador: 2, Dragón: 2, Fuego: 0.5, Agua: 0.5, Hielo: 0.5, Acero: 0.5 },
+  Lucha:      { Normal: 2, Hielo: 2, Roca: 2, Siniestro: 2, Acero: 2, Veneno: 0.5, Volador: 0.5, Psíquico: 0.5, Bicho: 0.5, Fantasma: 0 },
+  Veneno:     { Planta: 2, Hada: 2, Veneno: 0.5, Tierra: 0.5, Roca: 0.5, Fantasma: 0.5, Acero: 0 },
+  Tierra:     { Fuego: 2, Eléctrico: 2, Veneno: 2, Roca: 2, Acero: 2, Planta: 0.5, Bicho: 0.5, Volador: 0 },
+  Volador:    { Planta: 2, Lucha: 2, Bicho: 2, Eléctrico: 0.5, Roca: 0.5, Acero: 0.5 },
+  Psíquico:   { Lucha: 2, Veneno: 2, Psíquico: 0.5, Acero: 0.5, Siniestro: 0 },
+  Bicho:      { Planta: 2, Psíquico: 2, Siniestro: 2, Fuego: 0.5, Lucha: 0.5, Veneno: 0.5, Volador: 0.5, Fantasma: 0.5, Acero: 0.5, Hada: 0.5 },
+  Roca:       { Fuego: 2, Hielo: 2, Volador: 2, Bicho: 2, Lucha: 0.5, Tierra: 0.5, Acero: 0.5 },
+  Fantasma:   { Fantasma: 2, Psíquico: 2, Siniestro: 0.5, Normal: 0 },
+  Dragón:     { Dragón: 2, Acero: 0.5, Hada: 0 },
+  Siniestro:  { Psíquico: 2, Fantasma: 2, Lucha: 0.5, Siniestro: 0.5, Hada: 0.5 },
+  Acero:      { Hielo: 2, Roca: 2, Hada: 2, Fuego: 0.5, Agua: 0.5, Eléctrico: 0.5, Acero: 0.5 },
+  Hada:       { Lucha: 2, Dragón: 2, Siniestro: 2, Fuego: 0.5, Veneno: 0.5, Acero: 0.5 }
+};
+
+export default typeChart;
\ No newline at end of file
diff --git a/backend/src/controllers/entrenadorController.js b/backend/src/controllers/entrenadorController.js
index 4cc282d..71a6092 100644
--- a/backend/src/controllers/entrenadorController.js
+++ b/backend/src/controllers/entrenadorController.js
@@ -66,3 +66,21 @@ export const listEntrenadores = async (req, res) => {
     res.status(500).json({ message: 'Error al obtener los entrenadores', error: err });
   }
 };
+
+// Obtener Pokémon de un entrenador por su ID
+export const getPokemonsByEntrenadorId = async (req, res) => {
+  try {
+    const { entrenadorId } = req.params;
+
+    // Populate usando 'equipo', que es el campo correcto en tu esquema
+    const entrenador = await Entrenador.findById(entrenadorId).populate('equipo');
+
+    if (!entrenador) return res.status(404).json({ message: 'Entrenador no encontrado' });
+
+    // Devolver el array de Pokémon
+    res.json(entrenador.equipo);
+  } catch (error) {
+    console.error('Error al obtener Pokémon del entrenador:', error);
+    res.status(500).json({ message: 'Error interno del servidor' });
+  }
+};
\ No newline at end of file
diff --git a/backend/src/controllers/userPokemonController.js b/backend/src/controllers/userPokemonController.js
index 148db55..950dca9 100644
--- a/backend/src/controllers/userPokemonController.js
+++ b/backend/src/controllers/userPokemonController.js
@@ -1,5 +1,6 @@
 import UserPokemon from '../models/userPokemon.js';
 import Entrenador from '../models/entrenadores.js';
+import typeChart from '../../data/typeChart.js'; // Asegúrate de que esta ruta sea correcta
 
 // 1. Listar todos los Pokémon del usuario (con datos de Pokémon)
 export const listUserPokemons = async (req, res) => {
@@ -19,9 +20,6 @@ export const listUserPokemons = async (req, res) => {
 // Función auxiliar para actualizar flags
 const updateFlag = async (req, res, flag, value) => {
   try {
-    console.log('userId desde sesión:', req.user.userId);  // Verifica si el userId está presente
-    console.log('pokemonId desde params:', req.params.pokemonId);  // Verifica si el pokemonId es correcto
-
     const userPokemon = await UserPokemon.findOne({ userId: req.user.userId });
 
     if (!userPokemon) {
@@ -29,7 +27,6 @@ const updateFlag = async (req, res, flag, value) => {
     }
 
     const pokemonIndex = userPokemon.pokemons.findIndex(p => p._id.toString() === req.params.pokemonId);
-    console.log('Índice del Pokémon encontrado:', pokemonIndex);  // Verifica si el índice es correcto
 
     if (pokemonIndex === -1) {
       return res.status(404).json({ message: 'Pokémon no encontrado para este usuario' });
@@ -87,91 +84,62 @@ export const getEffectiveUserPokemons = async (req, res) => {
   try {
     const { ubicacion, entrenadorId } = req.params;
 
-    // 1. Obtener TODOS los Pokémon del usuario
     const userData = await UserPokemon.findOne({ userId: req.user.userId }).populate('pokemons.pokemonId');
+    if (!userData) return res.status(404).json({ message: 'No se encontró el usuario' });
 
-    if (!userData) {
-      return res.status(404).json({ message: 'No se encontró el usuario' });
-    }
-
-    const pokemonsEnCaja = userData.pokemons.filter(p => p.isInBox && p.pokemonId);
-
-    // 2. Obtener entrenador específico
     const entrenador = await Entrenador.findOne({ _id: entrenadorId, ubicacion }).populate('equipo');
+    if (!entrenador) return res.status(404).json({ message: 'Entrenador no encontrado en esa ubicación' });
 
-    if (!entrenador) {
-      return res.status(404).json({ message: 'Entrenador no encontrado en esa ubicación' });
-    }
-
-    // 3. Extraer tipos de su equipo
+    // Tipos del equipo enemigo
     const enemyTypes = [];
-    for (const poke of entrenador.equipo) {
+    entrenador.equipo.forEach(poke => {
       if (poke.tipo_1) enemyTypes.push(poke.tipo_1);
       if (poke.tipo_2) enemyTypes.push(poke.tipo_2);
-    }
-
-    // 4. Calcular efectividad
-    const efectivos = pokemonsEnCaja.filter(p => {
-      const types = [p.pokemonId.tipo_1, p.pokemonId.tipo_2].filter(Boolean);
-      const effect = getEffectiveness(types, enemyTypes);
-      return effect >= 1 && effect <= 2;
     });
 
-    // 5. Filtrar última evolución
-    const lastEvolutions = [];
-    const seenNames = new Set();
-    const pokemonMap = new Map();
-
-    efectivos.forEach(pokemon => {
-      const { nombre, evoluciones } = pokemon.pokemonId;
-      if (!seenNames.has(nombre)) {
-        seenNames.add(nombre);
-        if (evoluciones.length > 0) {
-          const lastEvo = evoluciones.sort((a, b) => b.nivel - a.nivel)[0];
-          pokemonMap.set(nombre, lastEvo);
+    const pokemonsEnCaja = userData.pokemons.filter(p => p.isInBox && p.pokemonId);
+
+    // Identificar últimas evoluciones que posee el usuario
+    const latestEvolutionsMap = new Map();
+    for (const p of pokemonsEnCaja) {
+      const baseName = p.pokemonId.nombre;
+      const evoList = p.pokemonId.evoluciones;
+      if (evoList.length > 0) {
+        const sortedEvos = evoList.sort((a, b) => b.nivel - a.nivel);
+        const userOwnedEvo = sortedEvos.find(evo =>
+          pokemonsEnCaja.some(up => up.pokemonId.nombre === evo.nombre)
+        );
+        if (userOwnedEvo) {
+          latestEvolutionsMap.set(baseName, userOwnedEvo);
         } else {
-          pokemonMap.set(nombre, pokemon.pokemonId);
+          latestEvolutionsMap.set(baseName, p.pokemonId);
         }
+      } else {
+        latestEvolutionsMap.set(baseName, p.pokemonId);
       }
-    });
+    }
 
-    pokemonMap.forEach((evolution, nombre) => {
-      lastEvolutions.push({
-        ...evolution,
-        nombre,
-      });
-    });
+    const x2 = [];
+    const x1 = [];
+
+    for (const [_, pokemon] of latestEvolutionsMap.entries()) {
+      const types = [pokemon.tipo_1, pokemon.tipo_2].filter(Boolean);
+      // Revisar multiplicadores para cada tipo
+      let maxMultiplier = 0;
+      for (const uType of types) {
+        for (const eType of enemyTypes) {
+          const mult = typeChart[uType]?.[eType] ?? 1;
+          if (mult > maxMultiplier) maxMultiplier = mult;
+        }
+      }
+
+      if (maxMultiplier === 2) x2.push(pokemon);
+      else if (maxMultiplier === 1) x1.push(pokemon);
+    }
 
-    res.status(200).json(lastEvolutions);
+    res.status(200).json({ x2, x1 });
   } catch (err) {
     console.error(err);
     res.status(500).json({ message: 'Error al calcular efectividad', error: err.message });
   }
-};
-
-// -------------------------
-// Función local de efectividad
-// -------------------------
-const typeChart = {
-  Agua: { Fuego: 2, Planta: 0.5, Tierra: 2 },
-  Fuego: { Planta: 2, Agua: 0.5, Hielo: 2 },
-  Planta: { Agua: 2, Fuego: 0.5, Tierra: 2 },
-  Eléctrico: { Agua: 2, Tierra: 0, Volador: 2 },
-  Tierra: { Fuego: 2, Eléctrico: 2, Planta: 0.5 },
-  Hielo: { Planta: 2, Dragón: 2, Fuego: 0.5 },
-  Volador: { Planta: 2, Eléctrico: 0.5 },
-  Psíquico: { Lucha: 2, Fantasma: 0.5 },
-  Lucha: { Normal: 2, Psíquico: 0.5 },
-  Fantasma: { Psíquico: 2, Normal: 0 },
-};
-
-const getEffectiveness = (userTypes, enemyTypes) => {
-  let total = 0;
-  for (const uType of userTypes) {
-    for (const eType of enemyTypes) {
-      const mult = typeChart[uType]?.[eType] ?? 1;
-      total += mult;
-    }
-  }
-  return total / (userTypes.length * enemyTypes.length || 1); // promedio
 };
\ No newline at end of file
diff --git a/backend/src/routes/main.js b/backend/src/routes/main.js
index e7d3332..5a336cb 100644
--- a/backend/src/routes/main.js
+++ b/backend/src/routes/main.js
@@ -39,32 +39,30 @@ router.post('/logout', (req, res) => {
 // --- Rutas autenticadas ---
 router.use(isAuthenticated);
 
-// Ruta de comprobación de autenticación
+// Comprobación de autenticación
 router.get('/api/auth/check', (req, res) => {
   res.json({ username: req.user.username });
 });
 
-// Ruta para obtener el userId del usuario autenticado
+// Obtener userId del usuario autenticado
 router.get('/userId', (req, res) => {
   res.json({ userId: req.session.user.userId });
 });
 
-// Ruta para obtener los Pokémon de un usuario
+// --- User Pokémon ---
 router.get('/user/:userId/pokemons', userPokemonController.listUserPokemons);
 
 // Flags caja/equipo
-router.put('/user/pokemon/:pokemonId/box', (req, res, next) => {
-  console.log('Ruta accedida:', req.originalUrl);
-  next();
-}, userPokemonController.addToBox);
+router.put('/user/pokemon/:pokemonId/box', userPokemonController.addToBox);
 router.delete('/user/pokemon/:pokemonId/box', userPokemonController.removeFromBox);
 router.put('/user/pokemon/:pokemonId/team', userPokemonController.addToTeam);
 router.delete('/user/pokemon/:pokemonId/team', userPokemonController.removeFromTeam);
 
-// --- Rutas adicionales del usuario ---
+// --- Funciones de efectividad y entrenadores ---
 router.get('/trainer-locations', userPokemonController.getTrainerLocations);
 router.get('/trainers/:ubicacion', userPokemonController.getTrainersByLocation);
 router.get('/effective-pokemons/:ubicacion/:entrenadorId', userPokemonController.getEffectiveUserPokemons);
+
 // --- Rutas de administrador ---
 router.use('/admin', isAdmin);
 
@@ -81,5 +79,5 @@ router.delete('/admin/objects/:id', objectController.deleteObject);
 
 // Entrenadores
 router.get('/admin/getEntrenadores', entrenadorController.listEntrenadores);
-
+router.get('/trainers/:entrenadorId/pokemons', entrenadorController.getPokemonsByEntrenadorId);
 export default router;
\ No newline at end of file
diff --git a/frontend/src/views/PokemonEfectivo.js b/frontend/src/views/PokemonEfectivo.js
index 2ec4858..efd82b9 100644
--- a/frontend/src/views/PokemonEfectivo.js
+++ b/frontend/src/views/PokemonEfectivo.js
@@ -1,112 +1,214 @@
 import React, { useEffect, useState } from 'react';
 import axios from 'axios';
+import {
+  Container,
+  Row,
+  Col,
+  Form,
+  Spinner,
+  ListGroup,
+  Card,
+} from 'react-bootstrap';
 
 const EffectivePokemonSelector = () => {
   const [locations, setLocations] = useState([]);
   const [selectedLocation, setSelectedLocation] = useState('');
   const [trainers, setTrainers] = useState([]);
   const [selectedTrainer, setSelectedTrainer] = useState('');
-  const [effectivePokemons, setEffectivePokemons] = useState([]);
+  const [effectivePokemons, setEffectivePokemons] = useState({ x2: [], x1: [] });
   const [loading, setLoading] = useState(false);
 
-  // Obtener ubicaciones
-  const fetchLocations = async () => {
-    try {
-      const res = await axios.get('http://localhost:5000/trainer-locations', {
-        withCredentials: true
-      });
-      setLocations(res.data);
-    } catch (err) {
-      console.error('Error al obtener ubicaciones:', err);
-    }
-  };
+  // Estado y carga de Pokémon del entrenador
+  const [trainerPokemons, setTrainerPokemons] = useState([]);
+  const [loadingTrainerPokemons, setLoadingTrainerPokemons] = useState(false);
 
-  // Obtener entrenadores en la ubicación seleccionada
-  const fetchTrainers = async (location) => {
-    try {
-      const res = await axios.get(`http://localhost:5000/trainers/${location}`, {
-        withCredentials: true
-      });
-      setTrainers(res.data);
-    } catch (err) {
-      console.error('Error al obtener entrenadores:', err);
-    }
-  };
+  useEffect(() => {
+    const fetchLocations = async () => {
+      try {
+        const res = await axios.get('http://localhost:5000/trainer-locations', {
+          withCredentials: true,
+        });
+        setLocations(res.data);
+      } catch (err) {
+        console.error('Error al obtener ubicaciones:', err);
+      }
+    };
+    fetchLocations();
+  }, []);
+
+  useEffect(() => {
+    const fetchTrainers = async () => {
+      if (!selectedLocation) return;
+      try {
+        const res = await axios.get(`http://localhost:5000/trainers/${selectedLocation}`, {
+          withCredentials: true,
+        });
+        setTrainers(res.data);
+        setSelectedTrainer('');
+        setEffectivePokemons({ x2: [], x1: [] });
+        setTrainerPokemons([]);
+      } catch (err) {
+        console.error('Error al obtener entrenadores:', err);
+      }
+    };
+    fetchTrainers();
+  }, [selectedLocation]);
 
-  // Obtener Pokémon efectivos contra el entrenador seleccionado
-  const fetchEffectivePokemons = async (location, trainerId) => {
+  // Efecto para cargar Pokémon efectivos
+useEffect(() => {
+  const fetchEffectivePokemons = async () => {
+    if (!selectedLocation || !selectedTrainer) return;
     setLoading(true);
+    console.log('Fetching effective pokemons with params:', {
+      selectedLocation,
+      selectedTrainer,
+    }); // <-- Log params enviados
+
     try {
-      const res = await axios.get(`http://localhost:5000/effective-pokemons/${location}/${trainerId}`, {
-        withCredentials: true
-      });
+      const res = await axios.get(
+        `http://localhost:5000/effective-pokemons/${encodeURIComponent(selectedLocation)}/${selectedTrainer}`,
+        {
+          withCredentials: true,
+        }
+      );
+      console.log('Respuesta recibida de Pokémon efectivos:', res.data); // <-- Log respuesta
       setEffectivePokemons(res.data);
     } catch (err) {
       console.error('Error al obtener Pokémon efectivos:', err);
+      setEffectivePokemons({ x2: [], x1: [] });
     } finally {
       setLoading(false);
     }
   };
+  fetchEffectivePokemons();
+}, [selectedTrainer, selectedLocation]);
 
+  // Nuevo efecto para cargar Pokémon del entrenador
   useEffect(() => {
-    fetchLocations();
-  }, []);
-
-  useEffect(() => {
-    if (selectedLocation) {
-      fetchTrainers(selectedLocation);
-      setEffectivePokemons([]);
-      setSelectedTrainer('');
-    }
-  }, [selectedLocation]);
-
-  useEffect(() => {
-    if (selectedLocation && selectedTrainer) {
-      fetchEffectivePokemons(selectedLocation, selectedTrainer);
-    }
+    const fetchTrainerPokemons = async () => {
+      if (!selectedTrainer) {
+        setTrainerPokemons([]);
+        return;
+      }
+      setLoadingTrainerPokemons(true);
+      try {
+        const res = await axios.get(`http://localhost:5000/trainers/${selectedTrainer}/pokemons`, {
+          withCredentials: true,
+        });
+        setTrainerPokemons(res.data);
+      } catch (err) {
+        console.error('Error al obtener Pokémon del entrenador:', err);
+        setTrainerPokemons([]);
+      } finally {
+        setLoadingTrainerPokemons(false);
+      }
+    };
+    fetchTrainerPokemons();
   }, [selectedTrainer]);
 
   return (
-    <div>
-      <h2>Selecciona una ubicación</h2>
-      <select onChange={(e) => setSelectedLocation(e.target.value)} value={selectedLocation}>
-        <option value="">-- Ubicación --</option>
-        {locations.map((loc) => (
-          <option key={loc} value={loc}>
-            {loc}
-          </option>
-        ))}
-      </select>
+    <Container className="py-4 text-center">
+      <h2 className="text-primary mb-4">Selecciona una ubicación</h2>
+      <Row className="justify-content-center">
+        <Col xs={12} md={6}>
+          <Form.Select
+            value={selectedLocation}
+            onChange={(e) => setSelectedLocation(e.target.value)}
+            className="mb-4"
+          >
+            <option value="">-- Ubicación --</option>
+            {locations.map((loc) => (
+              <option key={loc} value={loc}>
+                {loc}
+              </option>
+            ))}
+          </Form.Select>
+        </Col>
+      </Row>
 
       {trainers.length > 0 && (
         <>
-          <h2>Selecciona un entrenador</h2>
-          <select onChange={(e) => setSelectedTrainer(e.target.value)} value={selectedTrainer}>
-            <option value="">-- Entrenador --</option>
-            {trainers.map((trainer) => (
-              <option key={trainer._id} value={trainer._id}>
-                {trainer.nombre}
-              </option>
-            ))}
-          </select>
+          <h2 className="text-primary mb-4">Selecciona un entrenador</h2>
+          <Row className="justify-content-center">
+            <Col xs={12} md={6}>
+              <Form.Select
+                value={selectedTrainer}
+                onChange={(e) => setSelectedTrainer(e.target.value)}
+                className="mb-4"
+              >
+                <option value="">-- Entrenador --</option>
+                {trainers.map((trainer) => (
+                  <option key={trainer._id} value={trainer._id}>
+                    {trainer.nombre}
+                  </option>
+                ))}
+              </Form.Select>
+            </Col>
+          </Row>
         </>
       )}
 
+      {/* Mostrar Pokémon del entrenador */}
+      {selectedTrainer && (
+        <Row className="justify-content-center mt-4">
+          <Col xs={12} md={8}>
+            <Card className="border-info">
+              <Card.Header className="bg-info text-white">
+                {loadingTrainerPokemons ? 'Cargando Pokémon del entrenador...' : 'Pokémon del entrenador'}
+              </Card.Header>
+              <ListGroup variant="flush">
+                {!loadingTrainerPokemons && trainerPokemons.length === 0 && (
+                  <ListGroup.Item>El entrenador no tiene Pokémon.</ListGroup.Item>
+                )}
+                {trainerPokemons.map((pokemon) => (
+                  <ListGroup.Item key={pokemon._id}>
+                    {pokemon.nombre}
+                    {pokemon.tipo_1 && ` (${pokemon.tipo_1}${pokemon.tipo_2 ? ` / ${pokemon.tipo_2}` : ''})`}
+                  </ListGroup.Item>
+                ))}
+              </ListGroup>
+            </Card>
+          </Col>
+        </Row>
+      )}
+
+      {/* Mostrar Pokémon efectivos con la estructura x2 y x1 */}
       {loading ? (
-        <p>Cargando Pokémon efectivos...</p>
-      ) : (
+        <Spinner animation="border" variant="primary" className="mt-4" />
+      ) : (effectivePokemons.x2?.length > 0 || effectivePokemons.x1?.length > 0) ? (
         <>
-          <h2>Pokémon efectivos</h2>
-          <ul>
-            {effectivePokemons.map((pokemon, idx) => (
-              <li key={idx}>
-                {pokemon.nombre} {pokemon.tipo_1 && `(${pokemon.tipo_1}`}{pokemon.tipo_2 && ` / ${pokemon.tipo_2}`}{(pokemon.tipo_1 || pokemon.tipo_2) && ')'}
-              </li>
-            ))}
-          </ul>
+          {effectivePokemons.x2.length > 0 && (
+            <Card className="border-primary mt-4">
+              <Card.Header className="bg-primary text-white">Pokémon x2 (Muy efectivos)</Card.Header>
+              <ListGroup variant="flush">
+                {effectivePokemons.x2.map((pokemon) => (
+                  <ListGroup.Item key={pokemon._id}>
+                    {pokemon.nombre}
+                    {pokemon.tipo_1 && ` (${pokemon.tipo_1}${pokemon.tipo_2 ? ` / ${pokemon.tipo_2}` : ''})`}
+                  </ListGroup.Item>
+                ))}
+              </ListGroup>
+            </Card>
+          )}
+
+          {effectivePokemons.x1.length > 0 && (
+            <Card className="border-secondary mt-4">
+              <Card.Header className="bg-secondary text-white">Pokémon x1 (Efectivos)</Card.Header>
+              <ListGroup variant="flush">
+                {effectivePokemons.x1.map((pokemon) => (
+                  <ListGroup.Item key={pokemon._id}>
+                    {pokemon.nombre}
+                    {pokemon.tipo_1 && ` (${pokemon.tipo_1}${pokemon.tipo_2 ? ` / ${pokemon.tipo_2}` : ''})`}
+                  </ListGroup.Item>
+                ))}
+              </ListGroup>
+            </Card>
+          )}
         </>
+      ) : (
+        selectedTrainer && <p className="mt-4 text-muted">No hay Pokémon efectivos para este entrenador.</p>
       )}
-    </div>
+    </Container>
   );
 };
 
-- 
GitLab