Frontend: Interfície de l’Usuari

Construcció del Giny (Frontend/HTML)

Per donar vida al chatbot de la LAN Party Castellbisbal 2026, he dissenyat una interfície personalitzada (widget) des de zero, utilitzant un stack net d’HTML, CSS i JavaScript. Com que tota la infraestructura de la nostra IA resideix a Google Colab, el Frontend s’ha optimitzat per integrar-se directament en el flux de treball del notebook. Això s’aconsegueix mitjançant la llibreria IPython.display, que permet renderitzar l’experiència visual sense necessitat de servidors externs.

Disseny i Experiència d’Usuari (CSS)

M’he allunyat de les plantilles genèriques per apostar per un codi modular i lleuger. En aquesta versió, hem evolucionat la identitat visual cap a una estètica basada en tonalitats liles i morats, que aporten un aire més modern, creatiu i diferencial per a l’esdeveniment.

  • Diferenciació visual: S’ha implementat un contrast clar en les bombolles de xat per facilitar la lectura.
  • Color de l’usuari: Els missatges de l’usuari utilitzen un morat intens (vibrant), destacant la seva interacció.
  • Color del bot: Les respostes de l’IA es presenten en un lila suau o lavanda, creant un entorn de lectura relaxat i tecnològic.

– Lògica d’Interacció i Experiència d’Usuari (JavaScript)

El motor de JavaScript s’ha dissenyat per ser robust, net i totalment orientat a facilitar la comunicació durant la LAN Party Castellbisbal 2026. Hem integrat funcionalitats d’autocorrecció i feedback visual per millorar la interacció.

Funcionalitats Principals:

  • enviarMissatge() (Amb Validació): Captura el text de l’usuari de manera eficient. Hem implementat el mètode .trim() per netejar espais en blanc innecessaris, evitant que s’enviïn missatges buits per error i assegurant que la base de dades no rebi dades irrellevants.
  • netejarXat(): Permet als usuaris buidar la pantalla de conversa instantàniament. Mitjançant la manipulació directa del DOM amb innerHTML, l’entorn es reinicia de forma lleugera sense haver de recarregar la cel·la de Google Colab.
  • Gestió d’Esdeveniments (Enter): Per a una navegació més fluida, s’ha programat un listener que detecta la tecla “Enter”. Això permet que l’usuari enviï les seves consultes de forma natural, tal com ho faria en qualsevol aplicació de missatgeria moderna.
  • Auto-scroll Intel·ligent: Mitjançant la propietat scrollTop, la finestra del xat llisca automàticament cap a la part inferior amb cada nou missatge, garantint que l’usuari sempre visualitzi l’última resposta de la IA sense haver de desplaçar-se manualment.

Millores d’Infraestructura i UX:

  1. Indicador de Càrrega (Typing Animation): Hem afegit un indicador visual (tres punts animats en lila) que s’activa mentre la IA processa la resposta. Això redueix l’ansietat de l’usuari en confirmar que el sistema està treballant.
  2. Bloqueig de Seguretat (Input Control): Mentre el bot està generant una resposta, el camp d’entrada i el botó d’enviament es desactiven temporalment. Això evita col·lapses per enviaments múltiples i garanteix un flux de conversa ordenat.
from IPython.display import display, HTML # [ÚS DE LA IA] – Estructura basada en l’exemple de l’usuari però evolucionada a tons morats i funcionalitats UX avançades. codi_frontend = “”” <!DOCTYPE html> <html lang=”ca”> <head> <meta charset=”UTF-8″> <style> /* PALETA DE COLORS: Evolució del Blau al Morat Tecnològic */ :root { –primary-purple: #6a1b9a; /* Morat corporatiu */ –dark-purple: #4a148c; /* Morat fosc per a hover */ –light-purple: #f3e5f5; /* Fons per a missatges del bot */ –accent-purple: #9c27b0; /* Detalls i botons */ –bg-light: #f8f9fa; } body { font-family: ‘Segoe UI’, Roboto, Helvetica, Arial, sans-serif; background-color: transparent; } #chat-widget { width: 100%; max-width: 450px; background: #ffffff; border-radius: 12px; border: 1px solid #e0e0e0; box-shadow: 0 10px 25px rgba(0,0,0,0.1); display: flex; flex-direction: column; overflow: hidden; margin: 10px auto; } /* Capçalera amb degradat lila */ #chat-header { background: linear-gradient(135deg, var(–primary-purple), var(–accent-purple)); color: white; padding: 18px; text-align: center; font-weight: bold; font-size: 1.1em; letter-spacing: 0.5px; } #chat-messages { height: 380px; overflow-y: auto; padding: 20px; display: flex; flex-direction: column; gap: 12px; background: var(–bg-light); } .message { padding: 12px 16px; border-radius: 15px; max-width: 80%; word-wrap: break-word; font-size: 14.5px; line-height: 1.4; box-shadow: 0 2px 4px rgba(0,0,0,0.05); } /* Estil Bot: Lila claret */ .bot-msg { background: var(–light-purple); color: #4a148c; border-bottom-left-radius: 2px; align-self: flex-start; border: 1px solid #e1bee7; } /* Estil Usuari: Morat vibrant */ .user-msg { background: var(–primary-purple); color: white; border-bottom-right-radius: 2px; align-self: flex-end; } /* Indicador de càrrega */ #typing-indicator { font-size: 12px; color: var(–accent-purple); font-style: italic; margin-left: 20px; margin-bottom: 10px; display: none; } #chat-controls { display: flex; padding: 15px; border-top: 1px solid #eee; background: #fff; align-items: center; } #user-input { flex: 1; padding: 12px; border: 1px solid #ddd; border-radius: 25px; outline: none; font-size: 14px; transition: border 0.3s; } #user-input:focus { border-color: var(–accent-purple); } /* Botons estilitzats */ button { padding: 10px 18px; margin-left: 8px; border: none; border-radius: 20px; cursor: pointer; font-weight: bold; transition: all 0.3s ease; } .btn-send { background: var(–primary-purple); color: white; } .btn-send:hover { background: var(–dark-purple); transform: scale(1.05); } .btn-send:disabled { background: #ccc; cursor: not-allowed; } .btn-clear { background: transparent; color: #888; font-size: 12px; text-decoration: underline; } .btn-clear:hover { color: #d32f2f; } </style> </head> <body> <div id=”chat-widget”> <div id=”chat-header”>👾 LAN Party Castellbisbal 2026</div> <div id=”chat-messages”> <div class=”message bot-msg”>Hola! Soc en **Xabot**. Preparat per a la millor LAN Party? Estic a punt per ajudar-te amb el ping, els horaris o la normativa.</div> </div> <div id=”typing-indicator”>Xabot està processant…</div> <div id=”chat-controls”> <input type=”text” id=”user-input” placeholder=”Escriu aquí…” onkeypress=”gestionarEnter(event)”> <button class=”btn-send” id=”btn-send” onclick=”enviarMissatge()”>Enviar</button> <button class=”btn-clear” onclick=”netejarXat()”>Netejar</button> </div> </div> <script> // 1. Funció Enviar Missatge (Millorada amb validació i bloqueig) function enviarMissatge() { const inputElement = document.getElementById(“user-input”); const btnSend = document.getElementById(“btn-send”); const typing = document.getElementById(“typing-indicator”); const missatge = inputElement.value.trim(); if (missatge === “”) return; // Afegir missatge d’usuari afegirMissatgeAlDOM(“user-msg”, missatge); inputElement.value = “”; // Bloqueig de seguretat i indicador de càrrega (Millora UX) inputElement.disabled = true; btnSend.disabled = true; typing.style.display = “block”; // Simulem resposta del bot (Aquí anirà la connexió real amb Gemini) setTimeout(() => { typing.style.display = “none”; afegirMissatgeAlDOM(“bot-msg”, “Entesos! Estic analitzant la teva petició al servidor central… 🚀”); inputElement.disabled = false; btnSend.disabled = false; inputElement.focus(); }, 1500); } // 2. Funció per gestionar el DOM i Auto-scroll function afegirMissatgeAlDOM(classeRemitent, text) { const contenidor = document.getElementById(“chat-messages”); const nouMissatge = document.createElement(“div”); nouMissatge.classList.add(“message”, classeRemitent); nouMissatge.innerText = text; contenidor.appendChild(nouMissatge); // Auto-scroll cap avall contenidor.scrollTop = contenidor.scrollHeight; } // 3. Funció Netejar (UX ràpida) function netejarXat() { const contenidor = document.getElementById(“chat-messages”); contenidor.innerHTML = ‘<div class=”message bot-msg”>Socket reiniciat. Com et puc ajudar ara?</div>’; } // 4. Gestió de tecla Enter function gestionarEnter(event) { if (event.key === “Enter”) { enviarMissatge(); } } </script> </body> </html> “”” display(HTML(codi_frontend))

Gestió de Dades: Estructura i Optimització JSON

Per emmagatzemar tota la informació crítica de la LAN Party Castellbisbal 2026, he optat per una arquitectura basada en un fitxer dades_lan.json. Aquesta solució és la més eficient i lleugera per a un entorn de xat, ja que permet una organització jeràrquica sense la complexitat tècnica d’una base de dades SQL tradicional.

Organització i Eficiència

He estructurat el fitxer en nodes lògics (horaris, configuracions d’IP, normativa de residu zero, tornejos de videojocs…). Gràcies a aquesta categorització, el script de Python pot realitzar consultes indexades a una velocitat de “ping” gairebé instantània, trobant la resposta exacta que l’usuari necessita.

Seguretat i Robustesa (Protocol de xarxa)

Per garantir que el sistema no caigui (“pete”) durant l’esdeveniment, he implementat una gestió d’errors avançada mitjançant blocs try-except, actuant com un tallafocs de seguretat:

  • FileNotFoundError: Si el fitxer de dades desapareix o es mou per error, el sistema emet un avís crític per consola en lloc de col·lapsar.
  • JSONDecodeError: Si el fitxer està corrupte (per exemple, si falta una coma o un claudàtor), el bot detecta automàticament l’error de sintaxi i protegeix la integritat de l’execució.

El paper de la Intel·ligència Artificial

En aquesta fase, la IA no només actua com a interfície de resposta, sinó com a arquitecte de dades. He utilitzat models de llenguatge per:

  1. Netejar i estructurar les dades en brut de l’esdeveniment dins del format JSON.
  2. Optimitzar les consultes, assegurant que el chatbot entengui el context de la pregunta abans d’anar a buscar la dada específica al fitxer.
  3. Generar respostes naturals a partir de dades rígides, convertint una simple llista d’horaris en una interacció fluida i “geek”.

3.1 – El BackEnd: Flask, ngrok i la Generative AI (Gemini)

Nota de desenvolupament: El disseny d’aquesta arquitectura, la redacció del codi i la resolució de conflictes crítics (com l’error CORS i la validació de tokens d’ngrok) s’han realitzat amb l’assistència de la IA, utilitzant el model Gemini 3 Flash com a copilot de programació.

Per aconseguir que el nostre assistent virtual (Xatbot) funcioni de manera estable des d’un entorn extern (com Google Sites) connectat a Google Colab, hem dissenyat una arquitectura Client-Servidor d’alt rendiment:

  1. Servidor Flask: Actua com el “cervell” que rep les preguntes i gestiona la lògica.
  2. Middleware de Seguretat (CORS): Hem implementat flask-cors per permetre que el navegador del client pugui comunicar-se amb el servidor sense bloquejos de seguretat.
  3. Túnel ngrok: Crea un pont segur entre el núvol de Google Colab i el món exterior, proporcionant una URL pública (.ngrok-free.dev).
  4. Model d’IA: Utilitzem el model d’última generació gemini-2.0-flash per obtenir respostes ultra-ràpides amb un estil “gamer” personalitzat.

import json
from flask import Flask, request, jsonify
from flask_cors import CORS
from google import genai
from google.colab import userdata
app = Flask(name)
CORS(app) # Solució crucial per permetre connexions des de Google Sites
Configuració del model i seguretat
try:
API_KEY = userdata.get(“GOOGLE_API_KEY”)
client = genai.Client(api_key=API_KEY)
# Utilitzem la darrera versió 2.0 per a major velocitat i intel·ligència MODEL_ID = "gemini-2.0-flash"
except Exception as e:
print(f”⚠️ Error en la configuració de les claus: {e}”)
Lògica del Xatbot amb memòria de sessió
@app.route(‘/chat’, methods=[‘POST’])
def handle_chat():
try:
user_msg = request.json.get(“message”, “”)
# El sistema utilitza un ‘System Instruction’ amb el JSON de la LAN Party
response = chat_session.send_message(user_msg)
return jsonify({“reply”: response.text.strip()})
except Exception as e:
return jsonify({“reply”: “⚠️ Error de connexió. Torna a intentar-ho.”})

3.2 – El FrontEnd: Interfície d’Usuari i Connexió HTTP Asíncrona

La interfície del Xatbot s’ha dissenyat per ser lleugera, moderna i totalment integrada en el navegador de l’usuari (client). Està construïda utilitzant una combinació d’HTML5, CSS3 per a l’estètica “gamer” i JavaScript (ES6+) per a la lògica de comunicació.

L’objectiu principal d’aquest FrontEnd és capturar les consultes de l’usuari i enviar-les de forma asíncrona al BackEnd mitjançant l’API fetch, permetent una experiència de xat fluida sense necessitat de recarregar la pàgina (tecnologia AJAX).

Desafiaments Tècnics i Solucions:

Durant el desenvolupament, ens vam enfrontar a dos obstacles crítics que impedien la comunicació:

  1. Bloqueig de CORS (Cross-Origin Resource Sharing): El navegador bloquejava les peticions perquè el FrontEnd (Google Sites/Colab) i el BackEnd (ngrok) estaven en dominis diferents. La solució va ser configurar el BackEnd amb la llibreria flask-cors.
  2. Intercepció d’ngrok (Pantalla d’advertència): Inicialment, ngrok interceptava la primera petició mostrant una pàgina de “Visit Site”, cosa que trencava el codi ja que el JavaScript esperava un objecte JSON i rebia un fitxer HTML. La solució aplicada ha estat l’ús de dominis ngrok-free.dev i una estructura de petició que assegura el lliurament directe de dades al codi Flask, garantint que el Xatbot respongui a l’instant.

3.3 – Configuració de la API de Gemini: Gestió de Límits i Prevenció d’Al·lucinacions

L’última fase del projecte va consistir a establir la comunicació directa entre el nostre servidor Flask i la Google Generative AI SDK. En aquesta etapa, va ser necessari resoldre dos reptes tècnics crítics derivats de la naturalesa dels Grans Models de Llenguatge (LLM) i les polítiques de consum d’API de Google Cloud.

3.3.1 – Diagnòstic i Resolució de l’Error HTTP 429 (Límite de Cuota)

Inicialment, el sistema es va configurar per utilitzar el model gemini-pro. Tot i que l’estructura del codi era sintàcticament correcta, la API retornava de manera sistemàtica un error HTTP 429 (Too Many Requests) amb el missatge “Quota exceeded”.

Després d’analitzar el payload de l’error i consultar la consola de Google Cloud, es va identificar que la capa gratuïta (Free Tier) per a aquest model específic presentava restriccions regionals o límits de seguretat fixats en zero (limit: 0).

Solució Tècnica: Es va decidir migrar la implementació al model Gemini 2.0 Flash. Aquesta versió està optimitzada per a aplicacions en temps real, oferint una latència mínima i, el més important, una quota gratuïta molt més generosa que va restaurar immediatament la funcionalitat del xat.

3.3.2 – Control del Context i Reducció d’Al·lucinacions

Per evitar que el Xatbot inventés informació sobre la LAN Party (fenomen conegut com a “al·lucinació”), s’ha implementat una tècnica de Prompt Engineering basada en el context:

  • System Instruction: En lloc de deixar que la IA respongui de manera general, se li injecta un “Prompt de Sistema” que conté tota la informació del fitxer informacio_completa.json.
  • Restricció de Domini: S’ha programat el bot perquè només respongui preguntes basades en les dades oficials de l’esdeveniment, ignorant qualsevol petició que estigui fora de la normativa o els horaris establerts.