diff --git a/ficheros/contexto_ia_atletas.txt b/ficheros/contexto_ia_atletas.txt index d3f0663..73c2091 100644 --- a/ficheros/contexto_ia_atletas.txt +++ b/ficheros/contexto_ia_atletas.txt @@ -1,14 +1,15 @@ Actúa como un extractor de datos JSON que, a la vez, es experto en deporte olímpico. Analiza el texto que te van a proporcionar. -Devuelve exclusivamente un objeto JSON con esta estructura: -{ - "nombre": "", - "apellidos": "", +Devuelve exclusivamente un objeto JSON para una lista de atletas, en los que la información de atleta tiene esta estructura: +[{ + "nombre": "nombre_del_atleta", + "apellidos": "apellidos_del_atleta", "fecha_nacimiento": "YYYY-MM-DD", "sexo": "H/M", "participaciones": [ { - "disciplina": {"nombre_diciplina": "", + "disciplina": {"codigo_disciplina":"XXX000" + "nombre_diciplina": "", "diciplina_individual": "0/1", } @@ -20,9 +21,12 @@ Devuelve exclusivamente un objeto JSON con esta estructura: "nombre": "Nombre_Mascota", "url_imagen": "https://img.olympics.com/images/image/private/xxx" } - } + }, + "puesto": "puesto_atleta_si_no_hay_datos_devuelve_0" + } ] -} -Si la petición no tiene que ver Atletas olímpicos, devuelve un JSON vacío. +}... +] +Si la petición no tiene que ver Atletas olímpicos, devuelve un JSON vacío. Si en la petición no te viene información completa, la generas. No escribas nada de texto antes o después del JSON. \ No newline at end of file diff --git a/src/main/java/org/lapaloma/jjoo/ClienteSwingProcesamientoJJOO.java b/src/main/java/org/lapaloma/jjoo/ClienteSwingProcesamientoJJOO.java index 666e6a8..fac9279 100644 --- a/src/main/java/org/lapaloma/jjoo/ClienteSwingProcesamientoJJOO.java +++ b/src/main/java/org/lapaloma/jjoo/ClienteSwingProcesamientoJJOO.java @@ -26,7 +26,8 @@ import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.Timer; -import org.lapaloma.jjoo.procesamiento.ProcesadorOrigenDatos; +import org.lapaloma.jjoo.procesamiento.ProcesadorOpcion1; +import org.lapaloma.jjoo.procesamiento.ProcesadorOpcion2; public class ClienteSwingProcesamientoJJOO extends JFrame { @@ -212,7 +213,7 @@ public class ClienteSwingProcesamientoJJOO extends JFrame { // La información de los datos origen para esta opción // se añadirá al fichero juegos.conf - ProcesadorOrigenDatos procesador = new ProcesadorOrigenDatos(); + ProcesadorOpcion1 procesador = new ProcesadorOpcion1(); procesador.procesarDatos(); } @@ -221,6 +222,8 @@ public class ClienteSwingProcesamientoJJOO extends JFrame { System.out.println("Procesando Opción 2: " + txtPeticion.getText()); // La información de los datos origen para esta opción // está configurada en el fichero juegos.conf + ProcesadorOpcion2 procesador = new ProcesadorOpcion2(); + procesador.procesarDatosIA(txtPeticion.getText()); } } diff --git a/src/main/java/org/lapaloma/jjoo/procesamiento/ProcesadorOrigenDatos.java b/src/main/java/org/lapaloma/jjoo/procesamiento/ProcesadorOpcion1.java similarity index 91% rename from src/main/java/org/lapaloma/jjoo/procesamiento/ProcesadorOrigenDatos.java rename to src/main/java/org/lapaloma/jjoo/procesamiento/ProcesadorOpcion1.java index 032b863..9d4a74a 100644 --- a/src/main/java/org/lapaloma/jjoo/procesamiento/ProcesadorOrigenDatos.java +++ b/src/main/java/org/lapaloma/jjoo/procesamiento/ProcesadorOpcion1.java @@ -6,11 +6,11 @@ import java.io.IOException; import java.util.List; import java.util.Scanner; -import org.coi.juegosolimpicos.inm.dao.IAtleta; -import org.coi.juegosolimpicos.inm.dao.IAtletaDisciplinaJuego; -import org.coi.juegosolimpicos.inm.dao.IDisciplina; -import org.coi.juegosolimpicos.inm.dao.IJuegoOlimpico; -import org.coi.juegosolimpicos.inm.dao.IMascota; +import org.coi.juegosolimpicos.inm.dao.IAtletaDAO; +import org.coi.juegosolimpicos.inm.dao.IAtletaDisciplinaJuegoDAO; +import org.coi.juegosolimpicos.inm.dao.IDisciplinaDAO; +import org.coi.juegosolimpicos.inm.dao.IJuegoOlimpicoDAO; +import org.coi.juegosolimpicos.inm.dao.IMascotaDAO; import org.coi.juegosolimpicos.inm.dao.hbnt.AtletaDisciplinaJuegoDaoHibernate; import org.coi.juegosolimpicos.inm.dao.hbnt.DisciplinaDaoHibernate; import org.coi.juegosolimpicos.inm.dao.hbnt.JuegoOlimpicoDaoHibernate; @@ -39,7 +39,7 @@ import org.lapaloma.jjoo.util.UtilidadesJuegosOlimpicos; * */ -public class ProcesadorOrigenDatos { +public class ProcesadorOpcion1 { public void procesarDatos() { try { @@ -87,7 +87,7 @@ public class ProcesadorOrigenDatos { private void tratarDisciplinasOlimpicas() throws JuegosOlimpicosExcepcion { // Consultar disciplinas en MongoDB - IDisciplina iDisciplina = new DisciplinaDaoMongoDB(); + IDisciplinaDAO iDisciplina = new DisciplinaDaoMongoDB(); List listaDisciplinas = iDisciplina.obtenerListaDisciplinas(); System.out.println(listaDisciplinas); @@ -103,8 +103,8 @@ public class ProcesadorOrigenDatos { } private void tratarJSONJuegosMascotas() throws JuegosOlimpicosExcepcion { - IJuegoOlimpico iJuegoOlimpico = null; - IMascota iMascota = null; + IJuegoOlimpicoDAO iJuegoOlimpico = null; + IMascotaDAO iMascota = null; GestorFicheroJSONJuegoMascota gestorFicheroJSON = new GestorFicheroJSONJuegoMascota(); List listaJuegos = null; @@ -144,7 +144,7 @@ public class ProcesadorOrigenDatos { // Saltar cabecera br.readLine(); - IAtleta iAtleta = new AtletaDaoJDBC(); + IAtletaDAO iAtleta = new AtletaDaoJDBC(); while ((linea = br.readLine()) != null) { String[] partes = linea.split("\\|"); @@ -202,18 +202,18 @@ public class ProcesadorOrigenDatos { AtletaDisciplinaJuego atletaDisciplinaJuego = null; // Comprobar existe Atleta - IAtleta iAtleta = new AtletaDaoJDBC(); + IAtletaDAO iAtleta = new AtletaDaoJDBC(); Atleta atleta = iAtleta.obtenerAtletaPorID(idAtleta); // Comprobar existe Disciplina - IDisciplina iDisciplina = new DisciplinaDaoHibernate(); + IDisciplinaDAO iDisciplina = new DisciplinaDaoHibernate(); Disciplina disciplina = iDisciplina.obtenerDisciplinaPorCodigo(codigoDisciplina); // Comprobar existe Juego - IJuegoOlimpico iJuegoOlimpico = new JuegoOlimpicoDaoHibernate(); + IJuegoOlimpicoDAO iJuegoOlimpico = new JuegoOlimpicoDaoHibernate(); JuegoOlimpico juego = iJuegoOlimpico.obtenerJuegoOlimpicoPorCodigo(codigoJuego); // Cuando se ha validado que existen los 3 por separado (Atleta-Diciplina-Juego) // se inserta if (juego != null && disciplina != null && juego != null) { - IAtletaDisciplinaJuego iAtletaDisciplinaJuego = new AtletaDisciplinaJuegoDaoHibernate(); + IAtletaDisciplinaJuegoDAO iAtletaDisciplinaJuego = new AtletaDisciplinaJuegoDaoHibernate(); AtletaDisciplinaJuegoID identificadorADJ = new AtletaDisciplinaJuegoID(idAtleta, codigoDisciplina, codigoJuego); atletaDisciplinaJuego = iAtletaDisciplinaJuego.obtenerAtletaDisciplinaJuegoPorId(identificadorADJ); diff --git a/src/main/java/org/lapaloma/jjoo/procesamiento/ProcesadorOpcion2.java b/src/main/java/org/lapaloma/jjoo/procesamiento/ProcesadorOpcion2.java new file mode 100644 index 0000000..7f829ee --- /dev/null +++ b/src/main/java/org/lapaloma/jjoo/procesamiento/ProcesadorOpcion2.java @@ -0,0 +1,236 @@ +package org.lapaloma.jjoo.procesamiento; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.LocalDate; + +import org.coi.juegosolimpicos.inm.dao.IAtletaDAO; +import org.coi.juegosolimpicos.inm.dao.IAtletaDisciplinaJuegoDAO; +import org.coi.juegosolimpicos.inm.dao.IDisciplinaDAO; +import org.coi.juegosolimpicos.inm.dao.IJuegoOlimpicoDAO; +import org.coi.juegosolimpicos.inm.dao.IMascotaDAO; +import org.coi.juegosolimpicos.inm.dao.hbnt.AtletaDisciplinaJuegoDaoHibernate; +import org.coi.juegosolimpicos.inm.dao.hbnt.DisciplinaDaoHibernate; +import org.coi.juegosolimpicos.inm.dao.hbnt.JuegoOlimpicoDaoHibernate; +import org.coi.juegosolimpicos.inm.dao.hbnt.MascotaDaoHibernate; +import org.coi.juegosolimpicos.inm.dao.jdbc.AtletaDaoJDBC; +import org.coi.juegosolimpicos.inm.excepcion.JuegosOlimpicosExcepcion; +import org.coi.juegosolimpicos.inm.vo.Atleta; +import org.coi.juegosolimpicos.inm.vo.AtletaDisciplinaJuego; +import org.coi.juegosolimpicos.inm.vo.AtletaDisciplinaJuego.AtletaDisciplinaJuegoID; +import org.coi.juegosolimpicos.inm.vo.Disciplina; +import org.coi.juegosolimpicos.inm.vo.JuegoOlimpico; +import org.coi.juegosolimpicos.inm.vo.Mascota; +import org.coi.juegosolimpicos.inm.vo.Sexo; +import org.lapaloma.jjoo.gestores.GestorFicheroConfiguracionProcesamiento; +import org.lapaloma.jjoo.util.UtilidadesJuegosOlimpicos; + +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; + +public class ProcesadorOpcion2 { + public void procesarDatosIA(String contenidoPromptCliente) { + + String urlProveedorIA = GestorFicheroConfiguracionProcesamiento.obtenerValor("url.api.proveedor.ia"); + String apiKey = GestorFicheroConfiguracionProcesamiento.obtenerValor("key.api.proveedor.ia"); + String modeloIA = GestorFicheroConfiguracionProcesamiento.obtenerValor("model.proveedor.ia"); + + try { + + // Se define el prompt del contexto sistema + // para así fijar un comportamiento específico a la IA) + + String ruta = GestorFicheroConfiguracionProcesamiento.obtenerValor("fichero.contexto.ia.atletas"); + String contextoInicialIA = Files.readString(Paths.get(ruta)); + contextoInicialIA = contextoInicialIA.replace("\\", "\\\\").replace("\"", "\\\"").replace("\r", "") + .replace("\n", " ").replace("\t", " "); + + // Se construye el cuerpo de la petición (Payload) + String jsonInformacionEntrada = """ + { + "model": "%s", + "messages": [ + { "role": "system", "content": "%s" }, + { "role": "user", "content": "%s" } + ], + "response_format": { "type": "json_object" } + } + """.formatted(modeloIA, contextoInicialIA, contenidoPromptCliente); + + // 3. Creamos el cliente y la petición HTTP + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder().uri(URI.create(urlProveedorIA)) + .header("Authorization", "Bearer " + apiKey).header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(jsonInformacionEntrada)).build(); + + // Se envía petición + System.out.println("Consultando a Groq..."); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // Se obtiente el resultado + if (response.statusCode() == 200) { + System.out.println("Datos extraídos con éxito:"); + + // Aquí se llama a un método para procesar el JSON recibido, por ejemplo: + procesarRespuestaJSON(response.body()); + + } else { + System.out.println("❌ Error: " + response.statusCode()); + System.out.println(response.body()); + } + + } catch (Exception e) { + e.printStackTrace(); + } + + } + + private void procesarRespuestaJSON(String textoJsonRespuesta) throws JuegosOlimpicosExcepcion { + System.out.println(textoJsonRespuesta); + + ObjectMapper mapper = new ObjectMapper(); + JsonNode rootNode = mapper.readTree(textoJsonRespuesta); + + String contenidoInterno = rootNode.path("choices").get(0).path("message").path("content").asString(); + + JsonNode nodoListaAtletas = mapper.readTree(contenidoInterno); + + for (JsonNode nodoAtleta : nodoListaAtletas) { + tratarDatosAtleta(nodoAtleta); + } + + } + + private void tratarDatosAtleta(JsonNode nodoAtleta) throws JuegosOlimpicosExcepcion { + IAtletaDAO iAtletaDao = new AtletaDaoJDBC(); + + // Creacion atleta + String nombreAtleta = nodoAtleta.path("nombre").asString(); + String apellidosAtleta = nodoAtleta.path("apellidos").asString(); + String fechaAtleta = nodoAtleta.path("fecha_nacimiento").asString(); + LocalDate fechaNacimientoAtleta = LocalDate.parse(fechaAtleta); + String sexo = nodoAtleta.path("sexo").asString(); + + Atleta atletaBBDD = iAtletaDao.obtenerAtletaPorNombreApellidos(nombreAtleta, apellidosAtleta); + if (atletaBBDD == null) { + Atleta atleta = new Atleta(); + atleta.setNombre(nombreAtleta); + atleta.setApellidos(apellidosAtleta); + atleta.setFechaNacimiento(fechaNacimientoAtleta); + atleta.setSexo(Sexo.valueOf(sexo)); + + iAtletaDao.crearAtleta(atleta); + } + // Una vez almacenado se consulta (para obtener el ID) + atletaBBDD = iAtletaDao.obtenerAtletaPorNombreApellidos(nombreAtleta, apellidosAtleta); + + JsonNode nodoParticipaciones = nodoAtleta.path("participaciones"); + + for (JsonNode nodoParticipacion : nodoParticipaciones) { + tratarDatosParticipacion(atletaBBDD, nodoParticipacion); + } + + } + + private void tratarDatosParticipacion(Atleta atletaBBDD, JsonNode nodoParticipacion) throws JuegosOlimpicosExcepcion { + IDisciplinaDAO iDisciplinaDAO = new DisciplinaDaoHibernate(); + IMascotaDAO iMascotaDAO = new MascotaDaoHibernate(); + IJuegoOlimpicoDAO iJuegoOlimpicoDAO = new JuegoOlimpicoDaoHibernate(); + IAtletaDisciplinaJuegoDAO iAtletaDisciplinaJuegoDAO = new AtletaDisciplinaJuegoDaoHibernate(); + + // DISCIPINA + JsonNode nodoDisciplina = nodoParticipacion.path("disciplina"); + + String codigoDisciplina = nodoDisciplina.path("codigo_disciplina").asString(); + String nombreDisciplina = nodoDisciplina.path("nombre_diciplina").asString(); + int esDiscIndv = nodoDisciplina.path("diciplina_individual").asInt(); + boolean esDisciplinaIndividual = true; + if (esDiscIndv == 0) { + esDisciplinaIndividual = false; + } + + // TRATAMIENTO DICIPLINA + Disciplina disciplinaBBDD = iDisciplinaDAO.obtenerDisciplinaPorCodigo(codigoDisciplina); + if (disciplinaBBDD == null) { + Disciplina disciplina = new Disciplina(); + disciplina.setCodigo(codigoDisciplina); + disciplina.setNombre(nombreDisciplina); + disciplina.setDisciplinaIndividual(esDisciplinaIndividual); + + iDisciplinaDAO.crearDisciplina(disciplina); + } + + + // JUEGO OLÍMPICO + JsonNode nodoJuego = nodoParticipacion.path("juego"); + + String paisJuego = nodoJuego.path("pais").asString(); + Integer anyoJuego = nodoJuego.path("anyo").asInt(); + String ciudadJuego = nodoJuego.path("nombre").asString(); + int intEsVerano = nodoJuego.path("verano").asInt(); + + // MASCOTA + JsonNode nodoMascota = nodoJuego.path("mascota"); + String nombreMascota = nodoMascota.path("nombre").asString(); + String urlMascota = nodoMascota.path("url_imagen").asString(); + byte[] imagenMascota = UtilidadesJuegosOlimpicos.obtenerBytesDeURL(urlMascota); + + boolean esVerano = true; + String verinv = "V"; + if (intEsVerano == 0) { + esVerano = false; + verinv = "I"; + } + String codigoJuego = String.valueOf(anyoJuego) + verinv + ciudadJuego; + codigoJuego = codigoJuego.replace(" ", ""); + + // TRATAMIENTO JUEGO-MASCOTA + JuegoOlimpico juegoOlimpicoBBDD = iJuegoOlimpicoDAO.obtenerJuegoOlimpicoPorCodigo(codigoJuego); + // Se crean a la vez Mascota y Juego Olímpico. + if (juegoOlimpicoBBDD == null) { + + Mascota mascota = new Mascota(); + mascota.setNombre(nombreMascota); + mascota.setUrlImagen(urlMascota); + mascota.setImagen(imagenMascota); + + iMascotaDAO.crearMascota(mascota); + + JuegoOlimpico juegoOlimpico = new JuegoOlimpico(); + juegoOlimpico.setCodigo(codigoJuego); + juegoOlimpico.setEsJuegoVerano(esVerano); + juegoOlimpico.setAnio(anyoJuego); + juegoOlimpico.setPais(paisJuego); + juegoOlimpico.setCiudad(ciudadJuego); + juegoOlimpico.setMascotaJuego(mascota); + + iJuegoOlimpicoDAO.crearJuegoOlimpico(juegoOlimpico); + } + + // Se obtiene el código del atleta. + disciplinaBBDD = iDisciplinaDAO.obtenerDisciplinaPorCodigo(codigoDisciplina); + juegoOlimpicoBBDD = iJuegoOlimpicoDAO.obtenerJuegoOlimpicoPorCodigo(codigoJuego); + + int puestoAtletaDisciplinaJuego = nodoParticipacion.get("puesto").asInt(); + AtletaDisciplinaJuegoID atletaDisciplinaJuegoID = new AtletaDisciplinaJuegoID(atletaBBDD.getIdentificador(), + codigoDisciplina, codigoJuego); + AtletaDisciplinaJuego atletaDisciplinaJuegoBBDD = iAtletaDisciplinaJuegoDAO + .obtenerAtletaDisciplinaJuegoPorId(atletaDisciplinaJuegoID); + if (atletaDisciplinaJuegoBBDD == null) { + AtletaDisciplinaJuego atletaDisciplinaJuego = new AtletaDisciplinaJuego(); + atletaDisciplinaJuego.setIdAtletaDisciplinaJuego(atletaDisciplinaJuegoID); + atletaDisciplinaJuego.setAtleta(atletaBBDD); + atletaDisciplinaJuego.setDisciplina(disciplinaBBDD); + atletaDisciplinaJuego.setJuego(juegoOlimpicoBBDD); + atletaDisciplinaJuego.setPuestoCompeticion(puestoAtletaDisciplinaJuego); + + iAtletaDisciplinaJuegoDAO.crearAtletaDisciplinaJuego(atletaDisciplinaJuegoBBDD); + } + + } + +} diff --git a/src/main/resources/juegos.conf b/src/main/resources/juegos.conf index 534e113..a0a145a 100644 --- a/src/main/resources/juegos.conf +++ b/src/main/resources/juegos.conf @@ -1,5 +1,5 @@ -# URL en formato JSON con informacin de los juegos olmpicos y mascotas +# URL en formato JSON con información de los juegos olímpicos y mascotas url.juegos.json=https://dam2.decieloytierra.es/juegos/juegos-olimpicos.json # Informacion de Atletas @@ -7,7 +7,7 @@ ruta.fichero.atletas.csv=ficheros/info-atletas.csv # Fichero para la carga de datos de Atletas con IA (GROQ) -key.api.proveedor.ia=aqu_va_tu_api_key_de_groq +key.api.proveedor.ia=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 url.api.proveedor.ia=https://api.groq.com/openai/v1/chat/completions model.proveedor.ia=openai/gpt-oss-120b fichero.contexto.ia.atletas=ficheros/contexto_ia_atletas.txt