martes, 27 de noviembre de 2018

Administra tus credenciales de Git con Gnome Keyring


Si sueles utilizar servicios de Git en internet para almacenar tu código fuente, seguramente ya te has encontrado con la molestia de tener que introducir constantemente tus credenciales al momento de hacer push de tus cambios hacia el repositorio remoto.

sábado, 13 de octubre de 2018

Instalar Maven en Windows

Apache Maven es una herramienta de manejo de proyectos de software, que permite compilar proyectos, documentarlos y generar reportes a partir del concepto de un Modelo de Objetos de Proyecto (POM).

domingo, 23 de septiembre de 2018

SQL Server Snippets - Aproximación de valor real a N-ésimo decimal superior/inferior

Supóngase que se tiene un valor real o float, que se quiere aproximar al N-ésimo decimal superior. Por ejemplo:

Nuevo proyecto: Juego para Android


Hola. Esta entrada la escribí en mi antiguo blog de WordPress, en marzo de 2013. Tristemente a la fecha no he siquiera iniciado el proyecto, e incluso ha sido reemplazado por otros... pero quién sabe, tal vez algún día retome la idea. Por completitud, les dejo la entrada original a continuación (con algunas notas nuevas en rojo 😅):

Después de algunos sucesos, me he sentido motivado y animado a iniciar un proyecto a mediano-largo plazo, que consiste en un juego para Android. El único detalle está en que jamás en mi vida he hecho un juego, y mucho menos un programa para Android, jejeje... Lo más que hice fue una guardar una tabla de resultados para un proyecto en la materia de Gráficos por Computadora de la universidad. Pero me gusta correr antes que caminar (en este caso en particular), así que quiero hacer un juego 3D. A continuación describo mis ideas.

El juego

De momento, mi idea es que el juego sea más o menos estilo Star Fox 64, pero solamente en el espacio. ¿Por qué? Primero, porque me gustan los aviones. Segundo, porque creo que es más fácil que la nave siga una ruta predefinida, en vez de un mundo abierto. Tercero, porque creo que es difícil hacer un terreno y que el avión interactúe con él, así que mejor contar con la libertad del espacio.

Star Fox 64
Star Fox 64

Por otra parte, quiero tomar las partes más adictivas que se me ocurran de juegos como Space Invaders (variedad de enemigos con dificultad variable), Asteroids (asteroides, jejeje) y Fury 3 (múltiples armas agotables), para hacerlo entretenido. Finalmente, quiero que parte o todo el juego sea de código abierto (open source), pero hasta el momento en que lo termine, o que ya esté considerablemente maduro.

Asteroids
Asteroids

Fury 3
Fury 3

Algo importante que quiero es que las misiones no estén quemadas en el juego, sino que sea posible programarlas mediante algún metalenguaje, como YAML o XML o JSON, o bien un lenguaje de programación, pero de forma completamente externa al juego. Es decir, el kernel sería el juego, y las misiones serían como plugins. E incluso, me gustaría que los usuarios pudieran programar las misiones a su creatividad, dejando abierto todo un mundo de posibilidades. (Se me ocurrió un año antes que anunciaran Super Mario Maker 😮😮😮)

¿Por qué para Android?

Bueno, porque creo que para esta plataforma los gráficos no son lo principal, y considerando que soy un principiante (o menos que eso, jajaja...), creo que es adecuado. En segundo lugar, me llama la atención los juegos en dispositivos móviles, y creo que hay muchas posibilidades. Tercero, espero algún día poder publicar el juego en Google Play, y creo que los usuarios de Android están más abiertos a juegos pequeños.

¿Cómo hacer el juego?

Bueno, usualmente me gusta reinventar la rueda, y hacer todo desde cero, pero para este caso creo que sería muy difícil, así que mejor probaré primero con algún motor de juegos ya existente. Las características que espero del motor son las siguientes:
  • Idealmente que sea de código abierto, y gratuito. Si no es gratuito, que al menos pueda usarlo gratis para la etapa de desarrollo, pruebas y uso personal, y que adquiera la licencia (relativamente barata) en caso de que lo quiera publicar.
  • Que permita importar modelos 3D desde programas como Blender, o bien algún programa CAD gratuito.
  • Que no sea muy pesado o sobrecargue la memoria RAM de los dispositivos móviles.
  • Muy ideal sería que fuera multiplataforma, es decir, que no se limitara a Android, sino que también permitiera desarrollar juegos para computadoras, e incluso para consolas.

¿El plan? ¡Cuál plan!

Son bromas. Ahorita, el plan es simple: conseguir un motor de juegos para Andorid que cumpla los requisitos previos. Una vez lo encuentre, veremos que estrategia seguir...

Saludos.

Publicado originalmente el 2013-03-24, en https://itsouvenirs.wordpress.com/2013/03/24/nuevo-proyecto-juego-para-android/.

domingo, 19 de agosto de 2018

Mi primera aplicación web con React


Bueno, por azares del destino, finalmente fue inevitable tener que adquirir el gusto de React. Es la tendencia, culpa de Facebook. Habiéndome desahogado, empecemos.

Intro a React.js

React.js es una herramienta de JavaScript para construir interfaces de usuario. La forma más fácil de crear el esqueleto de una aplicación de React, es utilizar la herramienta de Node JS llamada create-react-app (😒), la cual podemos instalar de forma global a través de la terminal mediante el siguiente comando (nótese que debe ejecutarse como administrador -en Windows- o root -en Linux-):

# npm install -g create-react-app

Luego, procedemos a crear la aplicación base, con el nombre "peliculas-app" (pronto verán el porqué del nombre):

$ create-react-app peliculas-app

Luego, nos trasladamos al nuevo directorio creado para la app, y la probamos ejecutar:

$ cd peliculas-app/
$ npm start

Esto compila la aplicación con Webpack y la ejecuta con un servidor interno de desarrollo, publicándola localmente en el puerto 3000, por defecto. Al abrir la aplicación web, se muestra lo siguiente:

Al observar la estructura de la aplicación, tenemos algo similar a esto:
La página principal se encuentra en el archivo public/index.html. Por otra parte, el componente principal de React, el cual renderiza todo el contenido mostrado en la página inicial, se encuentra en el archivo src/App.js. En este último archivo, por ejemplo, podemos reemplazar el contenido del párrafo que usa la clase App-intro, con el texto "Hola mundo", así:

Una vez que se guarda el archivo, se recompila la aplicación de forma automática, por lo que podemos ver el cambio reflejado en el navegador de forma casi inmediata:

Creación de la aplicación: lista de películas

Luego de esta rápida introducción práctica a React, procederé a crear mi primera aplicación web con React. La aplicación consistirá en mostrar en pantalla un listado de nombres de películas, obtenidos desde un arreglo de datos. La película incluirá el título, una breve sinopsis y una imagen. El listado, así como cada ítem de este, será un componente distinto. Comencemos:

1. Primero agregaremos el listado de películas en el estado de la aplicación. Pondremos 3 para este ejemplo:


2. Luego crearemos un nuevo componente para mostrar cada ítem de la lista, en el cual mostraremos la imagen, el nombre y la sinopsis de esta. Cada ítem sera un elemento de tipo <li>. Dicho componente se creará en un nuevo archivo de JavaScript, al que llamaremos Item.js, dentro de la carpeta src.


En este componente se recibe como parámetro la variable props, la cual nos sirve para recibir datos de quien invoque este componente. En este caso, dentro de props recibiremos el campo pelicula, el cual contendrá la información de un elemento de la lista de películas: id, nombre, sinopsis y urlImagen. El componente renderiza la vista HTML que definimos en el cuerpo de la función, y en la cual podemos hacer uso de los props al incluirlos entre llaves.

3. Seguidamente procedemos a crear un tercer componente, en un nuevo archivo que nombraremos Lista.js. Este componente será el encargado de renderizar la lista, haciendo uso del componente Item para renderizar cada elemento, de la siguiente forma:


Nótese que este componente recibe el parámetro listaPeliculas dentro de los props, el cual contendrá el arreglo de películas. Este arreglo se itera mediante la función map(), dentro del cuerpo de la lista (<ul></ul>), para convertir cada elemento del arreglo en una vista, haciendo uso del componente Item. Puede observarse que el elemento es pasado a cada Item mediante el atributo pelicula, que es el nombre con el que se le hace referencia en dicho componente. Cabe mencionar que para hacer uso del componente Item, debemos importarlo al inicio del archivo de javascript.

4. Para armar la aplicación final, sustituimos en el componente principal (App.js) el párrafo que contenía la frase "Hola Mundo", por un div, y dentro de este colocamos el elemento Lista, al cual le proporcionaremos el arreglo de películas a través del atributo listaPeliculas, que es el nombre con el cual le hacemos referencia en dicho componente. Cabe recordar que para poder utilizar el componente Lista, debemos importarlo antes.


El resultado final del componente principal contenido en App.js es el siguiente:


5. Finalmente, para mostrar las películas de forma ordenada, agregamos algunos estilos CSS al final del archivo App.css, para aplicarlos globalmente a través del componente principal:


El resultado es el siguiente:
El código fuente de este ejemplo lo pueden encontrar acá: https://github.com/guillegr123/react-primera-app

Intenté que los commits fueran quedando conforme a cada paso descrito en esta entrada del blog. Pueden consultarlos acá: https://github.com/guillegr123/react-primera-app/commits/master

Conclusiones

Después de haber hecho esta primera prueba con React, resulta que se parece a Vue 2, jajaja. Al menos hasta donde pude ver, el concepto de componente es similar. Seguiré viendo qué tan parecido es a medida vaya progresando con esta herramienta.

Saludos. Happy coding!

jueves, 16 de agosto de 2018

SQL Server Snippets - Columna de fecha de última modificación en SQL Server

Supongamos que por cuestiones de control de modificaciones y auditoría, se quiere contar con un campo de fecha de última modificación en todas las tablas de una base de datos de SQL Server.

El inconveniente es que SQL Server no posee nativamente un tipo de dato que guarde la fecha de última modificación de un registro, el cual se actualice automáticamente al modificar una fila de datos. Por ello, una alternativa a esto es definir una columna de tipo datetime en cada tabla que se actualice cada vez que se modifique uno o más registros de esta, a través de un trigger.

Futuros nuevos posts... (viejo post del 2013)

¡Howdy! No pude resistirme, tengo varios posts en mente, pero no he tenido el tiempo de escribirlos, así que para mientras, quiero comentarles mis ideas, que espero alguna vez publicar:
  • Técnicas DRY para SQL Server: Son varias ideas para evitar código repetitivo en SQL Server.
  • Más SQL Server Snippets:Sé que tengo un par más por allí...
  • El regreso de las ventanas DIV: Ventanas DIV móviles, con sombra y otros efectos.
  • Symfony 2 y casos especiales de Symfony 1.4: Casi siento que he traicionado a Symfony por MVC, pero espero retomar el tema en este año, y compartir algunas cosas interesantes sobre la vieja y confiable versión 1.4.
  • Instalación de Oracle en Ubuntu: Ya tengo el PDF, y me gustaría publicarlo. Fue una tarea que hicimos en conjunto con unos amigos para la materia de Administración y Seguridad de Bases de Datos en la universidad. Ha sido el proyecto de computación más frustrante que he hecho hasta la fecha, creo que repetimos la instalación al menos unas 15 veces en dos semanas, hasta que sirvió... Menos mal que existía VirtualBox, porque si no, nos hubiera tocado formatear la computadora de pruebas 15 veces, jajaja...
  • FluentViewModel: La cereza de mi sundae, jejeje. Es un proyecto en C# que hice, que consiste en una interfaz fluida para la definición de Modelos de Vista (View Models) en MVC Framework, que hace uso de clases genéricas y expresiones lambda. Está basado en FluentValidation para .NET. Espero publicar el código fuente como Open Source algún día.
Espero publicar estos posts en un futuro cercano, ojalá lo logre...

Saludos, feliz viernes :)

Publicado originalmente el 2013-03-14, en https://itsouvenirs.wordpress.com/2013/03/14/futuros-nuevos-posts/.

Viejos posts publicados

Saludos a todos. Estuve revisando un poco mis documentos y encontré algunos posts que ya tenía listos para publicar desde hace varios años. Un par de ellos fueron colaboraciones al blog de un amigo de la universidad, y otros en realidad son manuales que escribí para acordarme cómo hacer las cosas. Les dejo abajo los enlaces a dos de estos posts, y espero posteriormente incluir otros más:
Para finalizar esta entrada, les dejo una frase un tanto soberbia de Nikola Tesla, con respecto al trabajo de Thomas Alva Edison:
"If Edison had a needle to find in a haystack, he would proceed at once with the diligence of the bee to examine straw after straw until he found the object of his search... I was a sorry witness of such doings, knowing that a little theory and calculation would have saved him ninety per cent of his labor."
- Nikola Tesla, New York Times, October 19, 1931
Traducido:
"Si Edison tuviera que encontrar una aguja en un pajar, procedería inmediatamente con la diligencia de una abeja a examinar paja por paja hasta que encontrara el objeto de su búsqueda... Fui testigo arrepentido de tales hechos, sabiendo que un poco de teoría y cálculo le hubiera ahorrado el noventa por ciento de su tarea."
- Nikola Tesla, New York Times, 19 de octubre de 1931
Es muy curioso que esta frase parece mostrarse reactiva o contrastante a la siguiente frase de Edison:
"No me equivoqué mil veces para hacer una bombilla, descubrí mil maneras de cómo no hacer una bombilla."
- Thomas Alva Edison
Esta frase la encontré en un archivo viejo en el que tenía una recopilación de frases que me habían llamado la atención. Nikola Tesla es uno de mis científicos favoritos, y según parece sus invenciones no son muy conocidas incluso en la actualidad, en comparación con el trabajo de Thomas Alva Edison.

Feliz día.

Publicado originalmente el 2013-03-04, en https://itsouvenirs.wordpress.com/2013/03/04/viejos-posts-publicados/.

PLT Scheme - Verificar que una cadena contiene solo letras minúsculas

Hola otra vez! Ahora espero no extenderme demasiado, como la primera vez. Bueno, esta es una pequeña “abstracción funcional” en PLT Scheme (ahora Racket), que verifica que una cadena este compuesta solamente por letras minúsculas.



Aunque parezca una función sencilla, contemplad que tiene algo interesante: se transforma la cadena de caracteres a una lista de caracteres (que contiene elementos tipo char), y se envía como parámetro a la función auxiliar, soloMinAux?, donde luego se extrae cada caracter, se transforma en un entero correspondiente al código ASCII en base diez, y he alli la magia, solo se verifica que este número esté entre los correspondientes a las letras minúsculas. Voilá (creo que así se escribe). Esto facilita mucho el trabajo a la hora de verificar si un carácter pertenece a una lista de caracteres consecutivos en el código ASCII. Además, las funciones string->list (que convierte una cadena a lista de caracteres) y char->integer (que convierte un caracter a un entero decimal correspondiente a su código ASCII) pueden ser de utilidad para manipular de muchas formas las cadenas de caracteres y los caracteres por si solos.

Bueno, espero que esta función les sea de utilidad, al menos para ver como se puede trabajar con caracteres y el código ASCII, y también supongo que les alegrará saber que hoy no me extendí mucho (aunque alguien dijo que ojala argumentara bastante cuando hablo, así como cuando escribo), pero bueno... Así que por el momento me despido, y les dejo esta frase, para todos aquellos que tienen una forma particular de ubicar sus cosas en el grandioso desorden que con mucho cariño llaman escritorio.
If a cluttered desk is the sign of a cluttered mind, what is the significance of a clean desk?
- Laurence J. Peter

Publicado originalmente el 2013-03-04, en https://itsouvenirs.wordpress.com/2013/03/04/plt-scheme-verificar-que-una-cadena-contiene-solo-letras-minusculas/.

jueves, 9 de agosto de 2018

Ejecutar aplicaciones con GUI desde Docker en Linux


Hace unos días un amigo me animó a descargar y correr su aplicación que había desarrollado en Python utilizando Tensorflow. Debido a que no tenía instalado Tensorflow, elegí la opción de descargar y ejecutar una imagen de contenedor de Docker ya preparada con Python y TensorFlow, en lugar de instalar todo lo necesario directamente en mi sistema operativo. Cuando llegué al punto de intentar correrlo, descubrí que tenía una interfaz de usuario gráfica (GUI), la cual no podía ser ejecutada desde la línea de comandos de mi contenedor.

Despues de investigar un poco, descubrí que es posible ejecutar aplicaciones con interfaz gráfica desde docker, siguiendo unos simples pasos que detallo a continuación, para el caso de contenedores Linux corriendo sobre host Linux:

  1. Si docker se está ejecutando con el super usuario local (root), es necesario permitir que este se pueda conectar al servidor X encargado de administrar el ambiente gráfico, agregándolo a la lista de usuarios permitidos, mediante el siguiente comando:

    # xhost local:root

  2. Ejecutar un nuevo contenedor, de la siguiente forma:

    $ docker run -ti --net host \
        -v /tmp/.X11-unix:/tmp/.X11-unix \
        -e DISPLAY=unix$DISPLAY \
        ubuntu:latest bash

    Notar las siguientes partes del comando:
    1. Se esta creando y ejecutando un nuevo contenedor con la última imagen estable de Ubuntu (ubuntu:latest), como ejemplo.
    2. Una vez se inicie el contenedor, se ejecutará la línea de comandos de este (bash).
    3. Las opciones -ti indican que se desea asignar una pseudo-terminal al contenedor, y mantener habilitada la entrada estándar mientras el contenedor se esté ejecutando, respectivamente.
    4. Ejecutamos el contenedor utilizando el driver del host para el uso de la red, mediante la opción --net host
    5. Montamos el socket de X11 como un volumen compartido con el contenedor, mediante la opción -v /tmp/.X11-unix:/tmp/.X11-unix
    6. Compartimos la variable de entorno DISPLAY del host, con el contenedor, mediante -e display="unix$DISPLAY
  3. Una vez la línea de comandos del nuevo contenedor se está ejecutando, para probar que podemos iniciar y ver aplicaciones on interfaz gráfica, instalaremos NEdit, que es un editor liviano para X Windows System. Para ello procedemos a actualizar la lista de paquetes de los repositorios de Ubuntu, e instalar el editor:

    # apt-get update & apt-get install nedit

  4. Finalmente ejecutamos el editor desde la línea de comandos:

    # nedit

    Veremos como la interfaz gráfica de la aplicación es lanzada en el sistema operativo host, ya que esta siendo ejecutada en el servidor X de este:


Referencias

domingo, 15 de julio de 2018

Conexión a fuente de datos (PostgreSQL) en iReport 3.7.3


Para crear reportes utilizando el asistente de reportes (Report Wizard), es necesario conectarse previamente a una fuente de datos, y para realizar esto, es necesario crear previamente una conexión a una fuente de datos.

Para crear una conexión a una fuente de datos para generar reportes, es necesario seguir los siguientes pasos:

  1. Presionar el botón Report Datasources, ubicado en la barra de herramientas.

  2. A continuación se muestra una ventana de diálogo que muestra las conexiones y fuentes de datos existentes. Se asumirá que aún no existe una conexión a la fuente de datos que se va a utilizar, y por lo tanto se procederá a crearla. Para ello, se hace clic en el botón New, ubicado en la parte superior derecha de la ventana.
  3. Aparece en pantalla otra ventana de diálogo, que muestra los distintos tipos de fuentes de datos. Para este caso, se elegirá el tipo de fuente más utilizado, Database JDBC Connection. Una vez seleccionado, se hace clic en el botón Next >.
  4. Luego aparecerá una tercera ventana de diálogo, que muestra las propiedades del tipo de conexión seleccionado. Es necesario darle un nombre mnemónico a la conexión. Para este caso, se llamará EjemploCon.
  5. En la misma ventana, se debe seleccionar el tipo de controlador JDBC (JDBC Driver), de acuerdo al sistema gestor de base de datos utilizado. En este ejemplo, se selecciona PostgreSQL (org.postgresql.Driver).
  6. También debe especificarse la URL de la base de datos a utilizar. En este ejemplo se utilizará la siguiente URL: jdbc:postgresql://localhost:5432/ejemplo
    En la URL de conexión a base de datos a través de JDBC, se especifica el protocolo de conexión, el subprotocolo, la dirección del servidor, el puerto y el nombre de la base de datos. En este ejemplo, estos parámetros son, respectivamente: jdbc, postgresql, localhost y ejemplo. Al utilizar la palabra localhost para especificar la dirección del servidor, se está haciendo referencia a la computadora actual, por lo que el servidor será la misma computadora desde la cual se generarán los reportes.
  7. Finalmente, debe detallarse el nombre de usuario y la contraseña, para poder acceder a la base de datos. Para este ejemplo, ambas palabras son postgres. Es posible indicar a iReports que almacene la contraseña, para evitar la molestia de ingresarla cada vez que se intente acceder a la base de datos, marcando la caja de Save password. En este ejemplo, se seleccionará la opción de recordar la contraseña, ya que no interesa la seguridad. A continuación, se ilustra mediante una captura de pantalla, la ventana de diálogo de propiedades de conexión, con todos los campos llenos:
    iReport advierte que la contraseña se almacena como texto plano, sin ninguna clase de encriptación. Por ello no se recomienda utilizar esta opción, a menos que se considere que no se requiere mayor seguridad. Si se elige no almacenar la contraseña, esta se solicitará cada vez que se intente acceder a la base de datos utilizando esta conexión.
  8. Una vez declarados todos estos parámetros, se presiona el botón de prueba (Test), para verificar que es posible realizar la conexión con los datos especificados.
  9. Si la prueba es exitosa, aparecerá el mensaje Connection test succesful!, indicando que fue posible establecer la conexión con la base de datos. En caso contrario, se mostrará un mensaje de error, indicando la posible causa de éste. Si se da esto último, es necesario verificar si los parámetros son correctos, o bien si el software servidor de bases de datos está activo y funcionando correctamente. También debe revisarse que la base de datos especificada exista, y se tengan los permisos adecuados para acceder a ella.
  10. Una vez que la conexión haya sido probada como exitosa, se hace clic en el botón Save, para que iReport guarde la nueva conexión.

Publicado originalmente el 2013-03-04, en https://itsouvenirs.wordpress.com/2013/03/04/conexion-a-fuente-de-datos-postgresql-en-ireport-3-7-3/.

sábado, 14 de julio de 2018

Finch vs Akka Http: Hola mundo en Scala


Hace varios días, buscando artículos sobre Scala en Medium, encontré un artículo sobre cómo crear una aplicación de lista de tareas utilizando Finch, que me llamó la atención. Este tenía un enlace a un artículo titutlado ¿Qué tan rápido es Finch?. En este artículo se mostraba el siguiente tweet con una gráfica comparativa de la velocidad de distintas librerías HTTP de Scala:



Siendo fanático de Scala, y estando acostumbrado a las herramientas más divulgadas para servicios web tales como Play Framework, Spray y Akka HTTP, me llamó bastante la atención que Finch mostrara por mucho un mejor desempeño que estas herramientas, a pesar de que la publicación tiene más de 2 años (publicada en febrero de 2016, vista por mí a principios de 2018). Así que me dio curiosidad de ver qué era Finch, hacer una pequeña prueba, y comparar el código con una aplicación similar con Akka HTTP.

¡Hola Finch!

Finch es una API de Scala para construir servicios HTTP sobre Finagle, la cual es un "sistema RPC extensible para la JVM, utilizado para la construcción de servidores de alta concurrencia", utilizando APIs uniformes de cliente y servidor agnósticas del protocolo (creo q podría describir a Finagle como el WCF para la JVM). En este sentido, Finch provee una delgada capa de bloques para construir APIs HTTP de forma tipada, utilizando conceptos de programación funcional. Esto convierte a Finch en una excelente herramienta para la creación de microservicios, ya que es más fácil integrarlos utilizando tipos compartidos. Cabe mencionar además que Finagle corre sobre Netty, por lo que no requiere de un servidor web separado.

Debido a que Scala es para mí más un pasatiempo, ya que no lo uso en mi trabajo, me costó un poco entender cómo se definía una API en Finch. Después de batallar un par de horas, pude crear el siguiente Hola Mundo, en un solo archivo:



Nótese que la API se compone de un solo endpoint, el cual es pasado como parámetro al servidor HTTP, para ser servido (valga la redundancia). Luego el programa queda en espera mientras el servicio se mantiene en ejecución. Las rutas se definen para cada endpoint, y los separadores utilizados en código son un par de dos puntos (::). Por otra parte, para la serialización de los datos desde y hacia JSON se usa Circe (antes llamada "JSON para gatos", vaya usted a saber por qué, jejeje).

El código completo pueden encontarlo acá: https://github.com/guillegr123/its-hellofinch

El proyecto se ejecuta utilizando SBT, con el siguiente comando:
sbt run
Luego, para probar el servicio, abrimos en el navegador la ruta: http://localhost:8080/api/v1/hello

Lo que más me gustó de Finch es que es que la creación de servicios web requiere poco código, y permite crear una API tipada desde el principio, pudiéndose definir los modelos de datos utilizados en el request y el response. Además, los endpoints son asíncronos, lo que permite una mayor concurrencia, razón de su excelente desempeño.

Pero... luego de algunas pruebas, y de investigar un poco, descubrí que Finch no hace uso de las clases estándares de Scala para programación asíncrona, sino que usa las implementaciones propias del ambiente de Twitter, por lo que obligatoriamente tendremos que hacer uso de sus librerías. Esto además, aunque no imposibilita, hace un poco más engorroso integrar librerías que hacen uso de las clases estándar de Scala. En este sentido, me parece mejor utilizar Finch para aplicaciones pequeñas, o aplicaciones de microservicios en las que hagamos uso extensivo de Finagle y las librerías de Twitter.

¡Hola Akka HTTP!

Descubiertos estos detalles de Finch, y habiendo saciado mi curiosidad de probar el framework, decidí volver a mis raíces con Akka HTTP. Akka HTTP es el reemplazo de Spray, y es considerada más como una librería en lugar de un framework, ya que su principal objetivo es solo proveer herramientas para cubrir las necesidades de integración de una o varias aplicaciones vía HTTP, en lugar de lineamientos sobre los cuáles construir la aplicación. Como tal no provee manejo de componentes como CSS/Javascript, plantillas para creación de vistas y otras herramientas orientadas a aplicaciones para navegadores web.

La construcción del hola mundo utilizando Akka HTTP me costó menos que Finch, debido a que ya había hecho una prueba hace mucho tiempo (y el código fuente estaba en control de versiones). El servicio se creó en un solo archivo, al igual que el ejemplo anterior:



El código completo puede encontrarse acá: https://github.com/guillegr123/its-helloakkahttp

Al igual que con el proyecto de Finch, para ejecutar el servicio, basta ejecutar el comando:

sbt run

Y para probar el servicio, abrimos en el navegador la ruta: http://localhost:8080/api/v1/hello
 
A simple vista, el código es más grande. Esto se debe a que Akka HTTP usa los actores de Akka para el manejo de concurrencia, por lo que es necesario crear un sistema de actores, un materializador de actores, y obtener el contexto de ejecución. Además, para la serialización de los mensajes a JSON, es necesario definir un trait para el formateo del mensaje.

Aparte de eso, en esencia la definición de los endpoints es similar. Las rutas se establecen para cada enpoint, pero usando la barra diagonal (o pleca) como separador, lo que resulta un poco más natural que los dos puntos de Finch, pero que sirven al mismo propósito. Los enpoints son asíncronos, pero a diferencia de Finch, usa la implementación de Futures estándar de Scala.

De forma similar a Finch, la instancia de rutas de la API es pasada como parámetro a su propio servidor web, el cual es iniciado. Sin embargo, en este caso no utiliza una librería externa como Netty, sino que se ejecuta sobre los actores y los flujos de Akka, y activa un puerto para hacer uso directo del protocolo HTTP.

Por otra parte, a diferencia de Finch, al finalizar el servicio web, es necesario desconectar el servidor web explícitamente del puerto, y finalizar el sistema de actores.

Conclusiones

Luego de estas pequeñas pruebas, considero que ambas librerías son excelentes, pero poseen enfoques diferentes, así como implementaciones, por lo que pueden usarse de distintas formas. Akka HTTP parece ser la mejor opción cuando tenemos una aplicación creada utilizando las librerías estándar de Scala, o bien actores de Akka, y solo necesitamos integrar sus componentes u otras aplicaciones vía HTTP. Y Finch parece ser una buena elección cuando necesitamos crear interfaces web tipadas, o sistemas de microservicios que deseamos integrar de forma fácil, ya que también facilita la creación de clientes.

En cuanto al desempeño, según el workbench mostrado por Vladimir Kostyukov, Finch es mucho más rápido que Akka HTTP. Sin embargo, la comparativa fue realizada hace dos años, cuando Akka HTTP aún estaba en pañales, por lo que quedamos a la espera de una comparación más reciente. En lo personal espero más Akka HTTP por ser considerado el reemplazo de Spray.

sábado, 7 de julio de 2018

Cambiar la URL de repositorio GIT remoto

Hola, este es un pequeño snippet para cambiar la URL de un repositorio remoto de GIT, en un repositorio local.

Primero, para listar las URL actuales del repositorio remoto, ejecutamos el siguiente comando, dentro de la carpeta que contiene nuestro repositorio local:

$ git remote -v

Esto mostrará un resultado similar al siguiente:

origin    https://github.com/mi-usuario/mi-repositorio.git (fetch)
origin    https://github.com/mi-usuario/mi-repositorio.git (push)

Puede notarse que el único repositorio remoto referenciado es origin, que suele ser el nombre por defecto asignado al repositorio remoto al clonarlo.

Para asignar una nueva url a dicho remoto, basta ejecutar el siguiente comando:

$ git remote set-url origin https://github.com/mi-usuario/mi-repositorio-nueva-url.git

Para verificar el cambio, podemos listar nuevamente los repositorios remotos, obteniendo el siguiente resultado:

$ git remote -v
origin    https://github.com/mi-usuario/mi-repositorio-nueva-url.git (fetch)
origin    https://github.com/mi-usuario/mi-repositorio-nueva-url.git (push)

Saludos.

Plantilla de Onsen UI para Vue CLI

Hola, en esta ocasión quería compartirles una plantilla de Vue CLI para crear un proyecto de aplicación web progresiva (PWA) con Onsen UI y Vue JS 2. Onsen UI es una librería de componentes para aplicaciones móviles híbridas, es decir, aplicaciones creadas con HTML y Javascript. Dicha librería está adaptada a 4 frameworks para la creación de aplicaciones web dinámicas: Angular JS (1), Angular 2+, React JS y Vue JS 2.

Vue JS 2 ofrece la herramienta de línea de comandos Vue CLI que permite crear la estructura básica de aplicaciones de una sola página (Single Page Applications, o SPA) de forma amigable. Para más detalles sobre la instalación y uso de esta herramienta recomiendo ver los siguientes enlaces:
La plantilla que he creado es un fork de la plantilla de Onsen UI para PWA con Webpack, la cual a su vez se basa en la plantilla para PWA de Vue JS. La plantilla de Onsen UI incluye:
  • Aplicación básica de ejemplo utilizando Onsen UI.
  • Webpack, para empaquetar los componentes del sitio web.
  • Recarga en caliente, para actualizar los cambios realizados en el código de forma inmediata en el navegador.
  • Verificador de sintaxis (lint).
  • Pruebas unitarias y de integración.
  • Extracción de CSS.
  • Manejo de estados utilizando Vuex.
Adicional a esto, he agregado las siguientes características en mi versión de la plantilla:
  • Soporte para TypeScript.
  • Uso de Vue Router para el manejo de rutas en aplicaciones de una sola página.
  • Integración de Vue Router y el componente Ons Navigator, mediante Vuex, para el cambio de páginas, basado en este ejemplo.
  • Axios como cliente HTTP para el consumo de servicios web.
  • La aplicación de ejemplo ha sido extendida para mostrar el manejo de rutas y la descarga de datos desde servicio web.
El código fuente de la plantilla está disponible acá: https://github.com/guillegr123/ons-vue-pwa-webpack-full

Para crear una aplicación utilizando la plantilla, basta ejecutar el siguiente comando, y contestar algunas preguntas:

$ vue init guillegr123/ons-vue-pwa-webpack-full mi-app

Luego, para instalar las dependencias:

$ cd mi-app
$ npm install

Y finalmente, para ejecutar en modo de desarrollo:

$ npm run dev

Con ello se muestra la siguiente aplicación de ejemplo:
Algunos puntos de interés:
  • En el menú lateral existe una sección llamada "internal links", que hace referencia a las páginas dentro de la app. El resto son enlaces externos. 
  • En la página de "Movies" se descarga un listado de películas desde un servicio web utilizando Axios.
Cualquier comentario/sugerencia con respecto a la plantilla, así como cualquier contribución, es bienvenida.
Saludos.

    lunes, 18 de junio de 2018

    Leer N caracteres en C/C++ con scanf + vaciar buffer

    Hola, en esta ocasión quería compartirles un pequeño snippet de código de C/C++ que encontré un día de estos: Como leer una cadena de N caracteres con scanf.

    Supongamos que queremos leer como máximo los primeros 8 caracteres que ingrese el usuario en la entrada estándar (stdin), y guardaremos el resultado en un arreglo de caracteres. Para ello, primero declaramos el arreglo con una longitud de 9 posiciones, que corresponderán a los 8 caracteres que deseamos leer, más una posición más para el caracter nulo, que marcará el fin de la cadena.

    char cadena[9];
    

    Luego procedemos a leer con scanf los 8 caracteres desde la entrada estandar:

    scanf("%8s",cadena); 
    

    Lo importante a notar es el especificador de formato s, que indica que lo que se leerá es una cadena de caracteres (string). La entrada se termina con un espacio en blanco, pero el número 8 indica que solamente se tomarán los primeros 8 caracteres que se encuentran en el buffer de la entrada estándar. Además, un caracter nulo es guardado al final de la cadena de caracteres. Es por ello que el arreglo utilizado debe ser por lo menos un caracter más grande que la longitud de entrada especificada. De no ser así podría darse el caso que se sobrescriban porciones de memorias adyacentes, generando resultados inesperados.

    Finalmente, para limpiar el buffer de la entrada estándar: leer mientras se encuentre el caracter de salto de línea (\n) o el caracter de finalización.

    char c;
    while ((c = getchar()) != '\n' && c != EOF) { }
    

    El código completo es el siguiente:



    Saludos.

    miércoles, 6 de junio de 2018

    Requisitos para trabajadores independientes y de servicio doméstico para cotizar en el ISSS

    Actualmente es posible para trabajadores independientes, así como empleados del servicio doméstico, cotizar en el Instituto Salvadoreño del Seguro Social, para poder acceder a los servicios de salud que brinda.

    Afiliación del trabajador de servicio doméstico

    Los trabajadores del servicio doméstico pueden afiliarse al ISSS desde el 1 de julio de 2010. Las consideraciones son los siguientes:

    Tipo de trabajo

    • Las personas beneficiadas serán aquellas que laboran en los hogares salvadoreños desempeñándose en cargos como cocinera, personal de limpieza, niñera, ama de llaves, mayordomo, jardinero y similares.
    • Estos empleados no deben generar ganancia económica a su empleador, así como lo establece el Artículo 77 del Código de Trabajo de El Salvador.

    Salario

    • El salario mínimo para poder cotizar en el ISSS es de $300 para 30 días, y $310 para 31 días.

    Porcentajes de contribución

    • 3.0% del salario, por parte del trabajador.
    • 7.5% del salario, por parte del patrono.

    Documentación a presentar

    • Por parte del trabajador:
      • Formulario “Aviso de Inscripción de Trabajador” debidamente completado y firmado por empleador y trabajador (puede encontrarse acá).
      • Fotografía reciente de frente tamaño cédula*.
      • Documento Único de Identidad (para el menor de edad Carné de Minoridad extendido por la Alcaldía de su municipio y para extranjero Documento de Identidad del país de origen, Carné de Residente o Pasaporte).
      • Número de Identificación Tributaria (NIT).
    • Por parte del patrono:
      • Formulario “Aviso de Inscripción de Empleador” debidamente completo y firmado por empleador y trabajador.
      • Documento Único de Identidad (para extranjero Documento de Identidad del país de origen, Carné de Residente o Pasaporte).
      • Número de Identificación Tributaria (NIT).
    • Para afiliar a beneficiario:
      • Tarjeta de afiliación del trabajador.
      • Documento Único de Identidad (para extranjero Documento de Identidad del país de origen, Carné de Residente o Pasaporte).
      • Partida de Nacimiento del menor.
      • Fotografía (si es mayor de 2 años)*.
    * No estoy seguro si las fotografías aún son requeridas, pues esta información se extrajo de un artículo del año 2010.

      Edad

      • De14 a 60 años para el trabajador.

      Afiliación del trabajador independiente

      Los trabajadores independientes pueden afiliarse al seguro social desde el 2 de mayo del 2018. Es posible hacerlo en dos modalidades: INDIVIDUAL (sin beneficiarios) y FAMILIAR (con beneficiarios). Es necesario tomar en cuenta las siguientes consideraciones:

      Tipo de trabajo

      • Profesiones libres o realice de forma habitual, personal y directa, una actividad económica, física o intelectual, sin sujeción por ella a contrato de trabajo, ni con trabajadores a su cargo.
      • Que no se encuentre sujeto al régimen general u a ningún de los otros regímenes especiales (no estoy muy seguro a qué se refiere esto, las disculpas del caso). 

      Montos de contribución

      • Cobertura INDIVIDUAL: $40
      • Cobertura FAMILIAR: $56

      Documentación a presentar

      • Documento Único de Identidad.
      • Número de Identificación Tributaria (NIT).
      • Formulario de inscripción según la modalidad: INDIVIDUAL o FAMILIAR (pueden encontrarse al final de esta página).
      • Declaración jurada de Actividad Económica que realiza (NOTARIADA).
      • Declaración jurada no notariada, en caso de inscribir a compañera o compañero de vida.

      Edad

      • De 18 a 60 años de edad.

        ¿Dónde solicitar el servicio?

        Las oficinas de Aseguramiento a nivel nacional, están habilitadas para la inscripción de los trabajadores:
        • Oficinas Administrativas del ISSS San Salvador: Alameda Juan Pablo II y 39 avenida norte, Condominio El Salvador, costado sur de Metrocentro, San Salvador. Horario: De lunes a viernes de 7:00 a.m. a 4:00 p.m.
        • Sucursal Plaza Mundo: Centro Comercial plaza Mundo 1er. nivel parqueo sur local #88, Boulevard del Ejercito Nacional Km 5 1/2, calle Montecarmelo, Soyapango. Horario: De lunes a viernes de 8:00 a.m. a 4:00 p.m. (sin cerrar al mediodía)
        • Sucursal Plaza Merliot: Centro Comercial Plaza Merliot 3a. Planta, local 394, contiguo a Maxi Efectivos, calle Chiltiupán, Ciudad Merliot. Correo electrónico: aseg.merliot@isss.gob.sv. Horario: De lunes a viernes de 8:00 a.m. a 4:00 p.m. (sin cerrar al mediodía).
        • Sucursal San Miguel: 2a. Avenida Norte y 8a Calle oriente, antiguo local del Banco Central de Reserva. Horario: De lunes a viernes de 8:00 a.m. a 4:00 p.m.
        • Sucursal Usulután: 3ra. Av. Norte, Número 9, Barrio la Merced, Usulután. Horario: De lunes a viernes de 7:00 a.m. a 4:00 p.m.
        • Sucursal Santa Ana: Final 10a. Avenida sur, El Palmar. Horario: De lunes a viernes de 7:00 a.m. a 4:00 p.m.
        • Sucursal Sonsonate: Carretera a Acajutla Km 66, contiguo a Metrocentro Sonsonate. Horario: De lunes a viernes de 7:00 a.m. a 4:00 p.m.

        Fuentes

        La presente información fue recopilada a inicios de junio de 2018. Las fuentes de la información mostrada acá son las siguientes:
        Se agradecerá mucho informar mediante comentario si la información acá presentada está desactualizada o es incorrecta.

        martes, 15 de mayo de 2018

        Tutorial de Vue.js 2 - 2. Creación de proyecto desde plantilla

        Índice:

        Hola nuevamente, en esta ocasión continuaré con la segunda entrega del tutorial de Vue.js 2. En esta ocasión trataremos los siguientes puntos:
        • Definición general del ejemplo
        • Descarga de plantilla WebPack.
        • Ejecución de proyecto de ejemplo.
        • Introducción a la estructura del proyecto

        Definición del ejemplo

        Para este tutorial, como ejemplo se elaborará una lista de contactos telefónicos, que permita hacer las operaciones ACME con ellos: Añadir, Consultar, Modificar o Eliminar. Los requerimientos específicos se irán describiendo a medida se vaya avanzando en el tutorial.

        Descarga de plantilla WebPack

        Asumiendo que se instalaron los componentes necesarios indicados en la primera parte del tutorial, podemos proceder a crear la carpeta que contendrá nuestro proyecto en el lugar que deseemos. Luego, abrimos la consola en dicha carpeta, y procedemos a generar el nuevo proyecto a partir de la plantilla de webpack, haciendo uso de la herramienta de línea de comandos de Vue (vue-cli), para ejecutar el siguiente comando:

        $ vue init webpack vue2-tutorial-contactos

        Con ese comando, le indicamos a la línea de comandos de Vue que deseamos iniciar un nuevo proyecto, a partir de la plantilla webpack, y cuyo nombre será vue2-tutorial-contactos. Luego de ello, para completar la creación del proyecto, la herramienta interactiva preguntará al usuario la información necesaria para generarlo:


        En algunos casos, la herramienta mostrará los valores por defecto a un lado del dato requerido, en un tono más claro, y entre paréntesis. Tal es el caso del nombre del proyecto, que como puede notarse es el mismo que le enviamos como tercer parámetro al comando para generar el proyecto. Si deseamos utilizar el valor por defecto, solamente presionamos ENTER. Si no, digitamos el nuevo valor, y presionamos ENTER.

        Luego de ello nos solicita la descripción del proyecto. En este caso, ingresamos una pequeña sinopsis de nuestro proyecto de prueba:


        El siguiente dato solicitado es el autor del proyecto, el cual se obtiene de la configuración global de GIT:


        Seguidamente el asistente nos indica que elijamos el tipo de compilación a utilizar con Vue. En este ejemplo utilizaremos la recomendada, la cual es más fácil de utilizar, pero levemente más pesada (de acuerdo a la descripción, no he probado la segunda opción, jejeje):


        Luego debemos elegir si instalar o no el vue-router en nuestro proyecto, el cual se utiliza para navegar entre distintas partes de la aplicación. Si bien no es necesario poseer un componente de enrutamiento elaborado para este proyecto, ya que no tendremos una gran cantidad de "páginas", lo utilizaremos a modo de ejemplo, ya que puede ser de utilidad para proyectos de mayor envergadura. Para instalarlo ingresamos la letra Y, o bien presionamos ENTER solamente, ya que esta es la opción por defecto.


        Después se solicita indicar si se utilizará la herramienta ESLint para analizar el código fuente (linter). Si bien no es necesario, ya que Vetur lo hará dentro del Visual Studio Code, dejaremos que el asistente lo instale, para ver cómo se ejecuta y muestra esta herramienta al momento de correr el proyecto.


        Luego elegimos la configuración estándar de reglas de ESLint (he aquí una comparación de las configuraciones de lint):


        En el siguiente paso, se nos pide indicar si deseamos que el asistente prepare pruebas unitarias para el proyecto. Indicaremos que sí (Y), y seguidamente elegiremos a Karma y Mocha como herramientas para la creación y ejecución de las pruebas.


        Como penúltimo paso, se nos pregunta si deseamos que se preparen las pruebas de extremo a extremo (end-to-end) utilizando Nightwatch. Indicaremos que sí.


        Y finalmente, el asistente nos consulta si deseamos que se ejecute el comando npm install, una vez creado el proyecto, para instalar todas las librerías y componentes necesarios para poderlo ejecutar. Seleccionaremos que sí, utilizando la herramienta NPM:


        Una vez completados estos pasos, el asistente procede a crear el proyecto, e instalar los paquetes necesarios:


        Y nos indica cuando el proceso ha finalizado:


        Ejecución del proyecto de ejemplo

        Allí, en color mostaza, nos indica como podemos ejecutar el proyecto. Tal como dice allí, basta con ingresar a la carpeta vue2-tutorial-contactos, que es la que contiene el proyecto (nótese que el nombre de la carpeta es el mismo que indicamos al iniciar el asistente de vue-cli), y ejecutar el comando npm run dev. Con ello se procede a construir el proyecto.


        Una vez finalizada la construcción, se nos indica que se puede ver la aplicación en la URL: http://localhost:8080


        Al abrir la ruta en el navegador, vemos el resultado:


        Introducción a la estructura del proyecto

        Ahora que el proyecto ya esta listo, podemos abrir la carpeta que lo contiene utilizando Visual Studio Code, con la opción de menú File > Open Folder:


        En este punto las partes de la estructura del proyecto que más nos interesan son las siguientes:
        • src: contiene el código fuente de Vue del proyecto.
        • index.html: es la página de inicio de la aplicación.
        Una gran ventaja de que este proyecto haya sido generado con WebPack es que posee la característica de hot-reload, lo cual quiere decir que luego de modificar un archivo, este es recompilado, y la página web es refrescada automáticamente para ver los cambios. Para probar esto, podemos modificar el mensaje dentro archivo src/components/HelloWorld.vue, así:


        Al guardar el archivo, WebPack detecta el cambio, y recompila el archivo modificado, lo cual puede observarse en la terminal donde está corriendo la aplicación:


        Y una vez finalizada la compilación, la página es refrescada automáticamente en nuestro navegador (y si no es el caso, basta que la refresquemos nosotros mismos). Nótese el cambio en el texto del mensaje:


        Esto es todo en esta ocasión. Pueden encontrar el código fuente de esta parte del tutorial acá: https://github.com/guillegr123/vue2-tutorial-contactos/tree/tutorial-parte-02. Espero próximamente poder mostrar como crear nuestra lista inicial de contactos. Saludos.

        martes, 6 de marzo de 2018

        Baúl de los recuerdos: Gravity Well 2



        Saludos a todos. En esta ocasión quería compartirles acerca de un viejo juego que de casualidad recordé un día de estos, de la nada. O bueno, no tan de la nada: hablando con un compañero del trabajo, estaba recordando las cosas que solía hacer cuando al regresar de la escuela, y recordé que en 8o o 9o grado, luego de almorzar, jugaba un rato en la computadora (una Compaq Presario con Pentium 4 y Windows XP, que fué la segunda computadora que compraron mis papás, la cual todavía está guardada en mi cuarto). Uno de esos juegos era Gravity Well, un juego Shareware que venía incluido en un disco llamado The House of Games for Windows 95.


        Este disco venía incluido con la primera computadora que compraron mis papás, por allá por 1998 (hace casi 20 años, y creo que aún tengo el disco por allí), la cual era una clon que traía Windows 95. Este disco traía un montón de mini juegos en la modalidad Shareware, lo que quiere decir que eran más que todo demostraciones o juegos completos con limitaciones de tiempo. Muchos de ellos no los comprendía, pero entre los pocos que logré comprender estaba el juego tema de esta entrada.

        Gravity Well es un juego arcade y de estrategia, de combate espacial, desarrollado por Cactus Software Productions (Colorado, EE.UU.), en el año 1995. La descripción del juego dice:
        The age old conflict rages onward, spreading into another previously uncharted region of space. The race is on once again to establish strategic footholds and vital supply lines. Four separate races struggle for dominance in a continuing battle for the stars. Planet by planet, sector by sector, the galaxy is claimed by those who can take it.

        Traducido:
        El viejo conflicto se continúa y se extiende a otra región del espacio anteriormente desconocida. La carrera es una vez más para establecer puntos de apoyo estratégicos y líneas de suministro vitales. Cuatro razas separadas luchan por el dominio en una batalla continua por las estrellas. Planeta por planeta, sector por sector, la galaxia es reclamada por aquellos que pueden tomarla.

        Suena bastante épico, ¿verdad?. Esta sinopsis da una idea de qué se trata el juego, la cual extenderé a continuación con mis experiencias. Diría que Gravity Well es una especie de combinación entre el clásico Asteroides con Aterrizaje Lunar, en esteroides. En este juego formas parte del equipo azul, y conduces una nave de combate, la cual aparece estacionada en el "puerto espacial" que orbita tu planeta. Tu misión es explorar y conquistar otros planetas en el sector del espacio que estás asignado. Para ello, debes aterrizar en los planetas, para "marcarlos" como sitios de aterrizaje. Luego de ello, naves de carga son enviadas desde tu planeta hacia el nuevo, para completar su colonización. Sin embargo, el sector no está solo, ya que hay otras razas (roja, morada y amarilla), las cuales también lucharán por poder conquistar los planetas, e incluso podrían destruir toda tu presencia en el sector. Pierdes el juego si todas tus naves y colonias son destruidas.



        Para los estándares actuales, el juego parece bastante simple, pero examinándolo detenidamente, creo que es un bonito ejemplo de los programas de su época, por las siguientes características:
        • Poseía varios ejecutables, que dependían de la versión de Windows que se usara, y las características de la computadora: si tenía o no co-procesador de punto flotante, si la computadora poseía Win32 en la instalación de Windows, etc. En estos tiempos, al menos a un alto nivel, solo nos preocupamos en saber si el procesador es de 32 o 64 bits. Cabe mencionar que el ejecutable para Windows de 32 bits aun funciona en Windows 10, aunque no del todo bien, al menos en lo que pude probar yo.
        • Es un juego vectorial. Cada objeto se define por un conjunto de puntos, incluidos en un archivo llamado SYMBOLS.DAT, que no es mas que texto plano con un formato particular para listar los elementos y los puntos. Esto quiere decir que no sería muy difícil modificar la forma de los objetos en la pantalla.
        • Cada objeto en el juego se maneja de forma individual, y posee características distintas. El desarrollador afirma en sus notas haber probado hasta 300 objetos en una sesión de juego en la versión de Windows de 32 bits. Cabe mencionar también que la posición de los planetas se determina de forma aleatoria, y estos no son estáticos, sino que orbitan alrededor de alguna estrella.
        • Todos los planetas y estrellas poseen gravedad, por lo que tu nave es atraída hacia ellos. Las estrellas poseen mayor fuerza de gravedad que los planetas, por lo que su atracción es mayor. Controlando la propulsión de la nave, es posible orbitar los planetas, y aterrizar en ellos.
        • El juego posee manejo de colisiones. Tu nave es destruida si tocas una estrella, o te acercas demasiado rápido a un planeta. Si intentas aterrizar con un planeta en una posición incorrecta, tu nave es dañada. También, aunque puedes atravesar otras naves espaciales, tu nave sufre un porcentaje de daño al hacerlo. Por otra parte, tu disparas y tus enemigos también, así que los contactos de los proyectiles también son tomados en cuenta. Con un motor gráfico no ha de ser tan difícil manejar esto, pero codificarlo a mano, aunque sea en 2 dimensiones, no ha de ser una tarea tan sencilla.
        • El ratón es opcional, pero si se tenía uno, se permitía seleccionar los objetos en el sector, para ver qué estaba pasando cerca de ellos.
        • El juego soporta múltiples resoluciones, y parece ser que ajusta el tamaño de los objetos de acuerdo a la resolución.
        • Posee una especie de inteligencia artifical básica, ya que uno puede escoger el caracter de las razas contrincates, y esto determina la forma en que estos se comportan: agresivo, cobarde, tenaz, etc.
        • Todos los archivos en conjunto utilizan un espacio de solamente 273 Kb, siendo solamente el ejecutable 170.5 Kb. El resto de archivos incluyen los sonidos (en formato WAV), el archivo de objetos, el archivo leéme, y un archivo de ayuda de Windows.
        Estuve intentando correr el programa en Windows 10, en modo de compatibilidad con Windows 95, pero parece ser que el fondo negro no se pinta, sino solo los objetos. Solamente cuando se mueven estos objetos, se pinta de negro los píxeles donde antes estaban, produciéndose el siguiente efecto:



        Por otra parte, lo intenté correr también en Linux (una distro basada en Arch) utilizando Wine, pero corre demasiado rápido. Creo que se puede deber a que usa el procesador para dibujar la pantalla, basado en las notas y debido a que intenté reducir los frames por segundo con strangle, pero no obtuve ninguna reducción. Así que ni modo, tal vez pueda en otra ocasión.

        Sin embargo, es sorprendente que a pesar de tener más de 20 años, ¡aún corre! Aunque puede ser un poco corto, es bastante entretenido, y cada sesión de juego será diferente gracias a su AI y los elementos aleatorios. Lo recomiendo bastante.

        Si alguien sabe como correrlo agradecería mucho sus comentarios. Saludos, y hasta la proxima.
        Con la tecnología de Blogger.