jueves, 16 de octubre de 2025

Html y Prolog

 Aquí tienes un ejemplo realista y práctico: un pequeño servidor web de recomendaciones de películas que utiliza una base de conocimientos en Prolog.

Imagina que tienes una base de datos de películas y quieres que los usuarios puedan encontrar una película introduciendo un género y una calificación mínima. Prolog es perfecto para este tipo de consultas lógicas. library(http) nos permite poner esto en la web.


El Escenario Realista

Crearemos un servidor web local que:

  1. Define un conocimiento base sobre películas (título, género, calificación).

  2. Inicia un servidor web en un puerto específico (ej. 8000).

  3. Escucha peticiones en una ruta, por ejemplo /recomendacion.

  4. Recibe parámetros de la URL, como genero y calificacion_minima.

  5. Consulta la base de conocimientos de Prolog para encontrar películas que coincidan.

  6. Devuelve una página HTML dinámica con los resultados al usuario.


El Código Completo

Copia y pega este código en un archivo llamado servidor_peliculas.pl.

Prolog
% Cargar las bibliotecas necesarias para el servidor HTTP y el manejo de HTML
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_parameters)).
:- use_module(library(http/html_write)).

% --- 1. Base de Conocimientos ---
% Hechos: pelicula(Título, Género, Calificación)
pelicula('The Matrix', scifi, 8.7).
pelicula('Inception', scifi, 8.8).
pelicula('The Godfather', crimen, 9.2).
pelicula('Pulp Fiction', crimen, 8.9).
pelicula('Forrest Gump', drama, 8.8).
pelicula('The Dark Knight', accion, 9.0).
pelicula('Interstellar', scifi, 8.6).
pelicula('Parasite', drama, 8.5).

% --- 2. Lógica de Búsqueda ---
% Regla: encontrar_peliculas(Genero, CalificacionMin, Peliculas)
% Encuentra todas las películas que cumplen con el género y la calificación mínima.
encontrar_peliculas(Genero, CalificacionMin, Peliculas) :-
    findall(
        pelicula(Titulo, Genero, Calificacion),
        (pelicula(Titulo, Genero, Calificacion), Calificacion >= CalificacionMin),
        Peliculas
    ).

% --- 3. Manejador de la Petición HTTP ---
% Este predicado se ejecuta cuando alguien visita /recomendacion
manejador_recomendacion(Request) :-
    % Obtener los parámetros de la URL (ej. ?genero=scifi&calificacion=8.7)
    http_parameters(Request,
                    [ genero(Genero, [default('scifi')]),
                      calificacion(CalificacionStr, [default('8.0')])
                    ]),
    % Convertir la calificación de texto a número
    atom_number(CalificacionStr, CalificacionMin),

    % Ejecutar la lógica de búsqueda
    encontrar_peliculas(Genero, CalificacionMin, Resultados),

    % Generar y enviar la respuesta HTML
    reply_html_page(
        title('Recomendador de Películas'),
        [ h1('Recomendador de Películas en Prolog'),
          h2('Resultados de tu búsqueda:'),
          p(['Buscando películas de género: ', b(Genero), ' con calificación mínima de: ', b(CalificacionMin)]),
          \generar_tabla_resultados(Resultados) % Llama a un predicado para crear la tabla
        ]).

% Predicado auxiliar para generar la tabla HTML con los resultados
generar_tabla_resultados([]) --> !, % Si no hay resultados
    html(p(b('No se encontraron películas con esos criterios.'))).
generar_tabla_resultados(Peliculas) --> % Si hay resultados
    html(table([border(1)],
               [ tr([th('Título'), th('Género'), th('Calificación')])
               | \filas_peliculas(Peliculas) % Generar las filas de la tabla
               ])).

% Genera una fila <tr> por cada película en la lista
filas_peliculas([]) --> [].
filas_peliculas([pelicula(Titulo, Genero, Calificacion)|Resto]) -->
    html(tr([td(Titulo), td(Genero), td(Calificacion)])),
    filas_peliculas(Resto).

% --- 4. Configuración y Arranque del Servidor ---
% Definir las rutas (handlers)
:- http_handler('/recomendacion', manejador_recomendacion, []).

% Predicado para iniciar el servidor
servidor(Puerto) :-
    http_server(http_dispatch, [port(Puerto)]).

% Para iniciar, ejecuta: ?- servidor(8000).

¿Cómo Funciona?

Paso 1: Ejecutar el Servidor

  1. Abre SWI-Prolog.

  2. Carga el archivo: ?- [servidor_peliculas].

  3. Inicia el servidor en el puerto 8000: ?- servidor(8000).

Verás un mensaje en la consola indicando que el servidor está corriendo, algo como: % HTTP server running on port 8000

Paso 2: Usar la Aplicación

Abre tu navegador web y ve a la siguiente URL:

http://localhost:8000/recomendacion?genero=scifi&calificacion=8.7

El servidor Prolog recibirá esta petición, ejecutará la lógica y te devolverá una página HTML con este resultado:

Recomendador de Películas en Prolog

Resultados de tu búsqueda:

Buscando películas de género: scifi con calificación mínima de: 8.7

TítuloGéneroCalificación
The Matrixscifi8.7
Inceptionscifi8.8

Si cambias la URL, por ejemplo a ?genero=crimen&calificacion=9.0, obtendrás resultados diferentes, demostrando que la página es totalmente dinámica y controlada por la lógica de Prolog.


Explicación del Código

  • library(http/...): Son las librerías que nos dan todas las herramientas para crear el servidor, manejar las peticiones (Request) y generar respuestas en HTML.

  • pelicula(...): Son nuestros "hechos" en la base de conocimientos. La base de todo.

  • encontrar_peliculas(...): Esta es la lógica principal. Utiliza findall/3 para recopilar en una lista todas las soluciones que cumplen con las condiciones, actuando como un motor de búsqueda.

  • manejador_recomendacion(Request): Es el "controlador". Se activa cuando se visita /recomendacion.

    • http_parameters/2: Extrae los valores de la URL de forma segura (con valores por defecto si no se proporcionan).

    • reply_html_page/2: Es una forma muy cómoda de construir una página HTML. El segundo argumento es una lista de elementos HTML que se renderizan automáticamente.

  • servidor(Puerto): Es el predicado que inicia todo el proceso, creando un servidor que escucha peticiones y las redirige al manejador correcto (http_dispatch).

Este ejemplo muestra perfectamente la separación de responsabilidades: la base de conocimientos (hechos), el motor de inferencia (reglas) y la capa de presentación (el servidor web) trabajan juntos, cada uno haciendo lo que mejor sabe hacer.

No hay comentarios:

Publicar un comentario