lunes, 30 de marzo de 2020

SQL-Experiments: experimentando queries alternativas en SQL

Como ya sabréis, el lenguaje SQL permite procesar los datos contenidos en una BDD ya sea a la hora de consultarlos, insertarlos, borrarlos, o actualizarlos.
Si queremos hacer con ellos operaciones más complejas, lo habitual es, una vez obtenidos en SQL procesarlos en Java, PHP,...
Pero... ¿hasta que punto podemos ejecutar algoritmos dentro de la propia query SQL?
Recientemente he creado un nuevo respositorio en mi Github donde subir algunos experimentos.

Para inaugurar el repositorio, he subido una query recursiva que permite ejecutar el algoritmo dinámico de Longest common subsequence problem que tambien podeis encontrar en HackerRank bajo el nombre de Commond Child. La query final para SQLite me quedó así de bonica:

WITH
INPUTS(I1,I2) AS (
 SELECT 'HARRY','SALLY'
 UNION ALL SELECT 'AA','BB'
 UNION ALL SELECT 'SHINCHAN','NOHARAAA'
 UNION ALL SELECT 'ABCDEF','FBDAMN'
),
RESULTS(I1,I2,X,Y,A) AS (
 SELECT I1,I2,0,1,'0000'
 FROM INPUTS UNION ALL
 SELECT I1,I2,
  CASE WHEN X=LENGTH(I1) THEN 0 ELSE X+1 END,
  CASE WHEN X=LENGTH(I1) THEN Y+1 ELSE Y END,
  CASE WHEN X=LENGTH(I1) THEN '0000' ELSE
  SUBSTR('0000'||(
   CASE WHEN SUBSTR(I1,X+1,1) = SUBSTR(I2,Y,1)
   THEN 1 + CAST(SUBSTR(A,1+4*(LENGTH(I1)+1),4) AS INTEGER)
   ELSE MAX(CAST(SUBSTR(A,1+4*LENGTH(I1),4) AS INTEGER),CAST(SUBSTR(A,1,4) AS INTEGER)) END
  ),-4,4) END || A
 FROM RESULTS
 WHERE NOT (X=LENGTH(I1) AND Y=LENGTH(I2))
),
FRESULTS(I1,I2,R) AS (
 SELECT I1,I2,CAST(SUBSTR(A,1,4) AS INTEGER) FROM RESULTS WHERE X=LENGTH(I1) AND Y=LENGTH(I2)
)
SELECT * FROM FRESULTS;
Sí os perdeis, tambien teneis otra query más simple que os permite generar un triangulo de pascal como en otro problema de HackerRank. La query es así de bonica:

WITH P(N,ROW,IT,REM) AS (
SELECT '1',1,1,''
UNION ALL
SELECT CASE WHEN REM='' THEN '1' ELSE N||' '|| --FIRST VALUE ALWAYS 1
 CASE WHEN instr(REM, ' ')=0 THEN REM  --IF REM ONLY HAS A NUMBER(1) CONCAT N THIS VALUE
 ELSE substr(REM, 1, instr(REM, ' ')-1) + --ELSE CONCAT SUM OF FIRST 2 NUMBERS OF REM
  CASE WHEN instr(substr(REM, instr(REM, ' ')+1),' ')=0 THEN substr(REM, instr(REM, ' ')+1) ELSE
  substr( substr(REM, instr(REM, ' ')+1),1,instr( substr(REM, instr(REM, ' ')+1),' ')-1) END
 END
END,
CASE WHEN REM='' THEN ROW+1 ELSE ROW END,
CASE WHEN REM='' THEN 1 ELSE IT+1 END,
CASE WHEN REM='' THEN N WHEN instr(REM, ' ')=0 THEN '' ELSE substr(REM, instr(REM, ' ')+1) END --POP FIRST NUMBER FROM REM / SET IT TO PREVIOUS N
FROM P
WHERE ROW<=15
)
SELECT N FROM P WHERE ROW=IT;

Y el resultado de ejecutarla es así de bonico:

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 1
1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1
1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1
Os recomiendo ver los enlaces de los problemas y del repositorio donde se explica como están implementados. Ahora sí, esto es importante followers:
¡Sugeridme más experimentos SQL en los comentarios! ;)

domingo, 29 de marzo de 2020

Remote-Clipboard: Compartiendo portapapeles entre varios ordenadores.

Proyecto Github aquí.
Hay mucha gente que trabaja con más de un ordenador a la vez, con maquinas virtuales, etc... Y uno de los problemas a los que se enfrentan es a copiar y pegar entre distintos equipos. Cada uno tiene un portapapeles distinto, y si haces CTRL+C en un ordenador, y CTRL+Z en el otro no obtendrás ese contenido... Hasta ahora.
Con mi nuevo proyecto Java, podéis compartir a través de un servidor el contenido de vuestro portapapeles cada vez que copiais o haceis CTRL+C y actualizar en tiempo real el portapapeles de todos los equipos conectados al servidor (Se envía cifrado con AES del bueno).
¿Dudas? ¿comentarios? Veo que no XD

martes, 17 de marzo de 2020

Obteniendo la colisión de videojuegos en PSX

Proyecto de Github aquí.

Recientemente me enfrenté al proyecto de reversing más complejo que he hecho hasta la fecha, pero antes de nada os pongo un poco en contexto:

Hace ya tiempo apareció en Youtube un canal llamado "GameHut", el cual trata sobre como se desarrollaban los videojuegos antiguamente, en especial en la epoca de la SEGA Saturn/Megadrive. El dueño del canal podría ser cualquier ex-programador de esa epoca... Pero no,  sorprendentemente se trata de Jon Burton, fundador y antiguo jefe de la compañía de videojuegos Travellers Tales.
Os animo a visitar su canal de Youtube ya que es muy interesante.
Curiosamente incluso llegó a ver mi video sobre la tech-demo de TT oculta que encontré, la cual según contestó en Twitter fue desarrollada por él mismo.
Bueno, la cuestion es que yo ya conocía algunos juegos de Travellers Tales, incluyendo los de PSX que estan basados sobre todo en peliculas de Pixar, y estando familiarizado con ellos, me dió la impresión de que compartian el mismo motor de alguna manera, y había algo que siempre había tenido curiosidad, y es... ¿Se puede obtener la colisión de estos juegos de alguna forma para hacerla visible?
Pues me llevó varios días de buscar estructuras de datos en la RAM del emulador relacionadas con la colisión, mucho ensamblador MIPS (Incluso llegué a mirar por encima el funcionamiento del coprocesador de la PSX) y bueno, aunque muchas veces mirar los datos de la RAM y cambiarlos arbitrariamente te da muchas pistas, el hecho de mirar lo que hacían las rutinas de ensamblador que accedían a esas direcciones me ayudó mucho.
Pues al final lo conseguí hacer, y efectivamente el motor de colisión es prácticamente el mismo en todos los juegos de TT, con algunos pequeños cambios entre alguno de ellos, por ejemplo: en TS2 y BLSC el motor es exactamente idéntico, y al contrario que en los juegos previos, los poligonos de colisión pueden ser o bien triangulos o bien cuadrilaterios (en los anteriores solo podían ser triangulos).

Travellers Tales Collision Viewer es una aplicacion Web (Javascript) que lee SaveStates del emulador PSXE y muestra los polígonos y objetos de colisión del nivel cargado en el momento de realizar el SaveState. Tiene soporte para todos los juegos de PSX desarrollados por Travellers Tales. Se muestra no solo la colisión del nivel final, sino también la de los polígonos de prueba que se usarían durante el desarrollo y testing del videojuego ¿A que me ha quedado bonico?



Polígonos de colisión de prueba de distintos tipos, situados fuera de los limites de uno de los niveles de TS2



lunes, 16 de marzo de 2020

El rincon oscuro de Technology-Hellín: Proyectos abandonados

No todos los proyectos que hago acaban haciéndose realidad, la primera vez que pasó fue hace ya 6 años cuando estaba aprendiendo a programar (que tiempos aquellos...) la causa principal fue falta de formación. ¡Casi parece un chiste hoy en día! Que joven que era entonces y que viejo que estoy ahora :P
A día de hoy los motivos por los que puedo cancelar un proyecto son o bien falta de tiempo (tengo mucho menos tiempo libre que antes) o simplemente que tras analizarlo, no encaja. Os dejo los 2 proyectos cancelados más relevantes actualmente:

JMusic
¿Recordais la APP para Android que hice para escuchar y descargar música que se encontraba en Youtube? Finalmente fue abandonada. ¿O eso creiais?

El logotipo del nuevo JMusic

JMusic necesitaba una actualización importante para darle impulso, y eso me hizo replantearla como... Una app de música en la nube privada. ¿Que quiero decir con eso? Sería una aplicación web accesible tanto en PC, IOS, Android,... habría una biblioteca de canciones, y radios online, organizadas por categorías, sincronizada siempre en todo momento en todos los dispositivos. Ademas tendría otras cosas molonas como un portapapeles, y una lista de enlaces compartida, todo sincronizado y almacenado en la nube. La falta de tiempo y los filtros de Instagram le hicieron mucho daño a la pobre:

  • El desarrollo comenzó en Julio de 2019 una mañana de la semana que estuve de vacaciones en Benicassim (la playica). Ya tenía la idea pensada y estaba inspirado, asi que decidí empezar con el layout. Ya la continuaría durante mi tercera semana de vacaciones en Hellín
  • El desarrollo continuó a la vuelta de mis segunda semana de vacaciones, en Asturias, concretamente desde el asiento trasero del coche (el viaje era largo y estaba aburrido) empecé a meterle JavaScript y mas cosicas. Al final de ese mismo día descubrí que me habían aceptado dentro de la beta de SparkAR para crear filtros de Instagram. Era una oportunidad muy importante para mi, para destacar y dar a conocer mis creaciones. JMusic podía esperar, y se quedó en el olvido.
  • Navidades 2019-2020: habían pasado 6 meses, JMusic, mi proyecto en el cual seguía pensando muchas veces, seguía en un estado de desarrollo... Ya os podeis imaginar. Durante todas las vacaciones solo le dediqué 2 mañanas a continuarlo un poco.

¡Y ya esta! Es una APP privada (En principio la estoy haciendo para mi mismo, dudo que nadie quiera probarla) y por lo tanto siempre acabo dándole prioridad a cualquier otra cosa. Eso la esta condenando. Mi intención es que acabe saliendo a la luz algún día, aunque es mi proyecto que lleva más tiempo a mitad de desarrollo.


Flappy Adventure 3 (FA3)

No es un secreto que desde niño siempre quise crear mi propio videojuego 3D. Lo conseguí con FA2 en menos de una semana sin ninguna experiencia previa en diseño de videojuegos 3D. Un año después, tras ser portado a Realidad Virtual (VR), lo tenía claro: con más tiempo, y con la experiencia obtenida, podría hacer un videojuego muy decente, con montones de objetos dinamicos y su propio editor. Empecé con la tormenta de ideas para la 3ª entrega de la saga FA:
  • Seguiría usando la librería Three.js pero esta vez crearía un Flappy Engine desde 0, en el que por una parte crease el modelo de SketchUp (Esta vez los objetos del modelo tendrían propiedades como distancia de dibujado,colisión, apariencia metalizada,..) y por otra parte los objetos dinámicos del nivel se cargarían aparte en un JSON que tambien contendría propiedades como el spawnpoint. Estos objetos tendrían su propio modelo SketchUp y su .js con su código propio, el cual aceptaría parámetros. Habrían muchos mas objetos dinámicos que en FA2, y algunos se crearía para un único nivel en concreto.
  • Para añadir los objetos dinamicos en los niveles junto a sus propiedades (parámetros, como por ejemplo color, velocidad,...), así como para comprobar el rendimiento, número de poligonos, y la correcta visualización (Los objetos tendrían una distancia de dibujado para mejorar el rendimiento y FPS respecto a FA2, donde siempre estaban cargados todos los elementos del nivel) se dispondría de un editor, donde uno se pudiera mover libremente, insertar objetos, colocarlos, y modificar sus propiedades. Estos cambios se podrían comprobar inmediatamente llamando al HTML del juego con el JSON generado como parametro de la URL.
  • En esta entrega se transportaría al jugador a una historia, igual que se hizo en la primera entrega de FA en la que flappy fue en busca de su pareja que finalmente resultó haber sido secuestrada por los Angry Birds. En este caso la historia sería mucho más profunda, con muchos niveles, dialogos,... Terminar cada nivel sería parecido a cuando terminas de ver el capitulo de una serie, que quieres ver como sigue. Se contempló la idea de poder manejar tanto a Flappy como a su pareja (rosa) con distintos poderes cada uno.
  • La jugabilidad sería parecida a la de FA2, es decir, se dispondría de un numero limitado de saltos en el aire y habría que intentar no chocar contra las paredes. 
  • Para FA3 habría pensado utilizar cel shading, que traducido al cristiano significa que la apariencia del videojuego sería como de dibujos animados. Este tipo de renderizado es poco frecuente, y habría llamado la atención. Se ha usado en juegos como Jet Set Radio.
  • El juego habría sido en 3ª persona, puesto que haría mas fácil visualizar la posición de Flappy, y recibí muchos comentarios en FA2 de que "si estaba jugando al Minecraft" solo por el hecho de ser un juego en primera persona.
Lamentablemente, aun anotando todas estas ideas (y otras relacionadas con el código), cancelé el proyecto sin ni siquiera haberlo empezado a desarrollar. Los motivos fueron:
  • Ya existen gran cantidad de juegos Indie con un gran nivel.  La recepción del juego muy probablemente sería nula. Sería hacer el juego para mi solo.
  • El hecho de hacer un motor de 0, me llevaría mucho tiempo existiendo ya herramientas como Unity.
  • Apenas tengo tiempo libre ahora con el trabajo, y por lo menos la mitad de ese tiempo prefiero pasarlo AFK.