10 de July de 2019

Jose Manuel

Sword Art Online (I)

Yo no lo sabía pero en Japón Sword Art Online es tan famosa como aquí Star Wars (y un buen sustituto ahora que Disney la ha terminado de destrozar).

Han hecho y siguen haciendo novelas ligeras, mangas, videojuegos, animes y películas.

Te cuento lo que he visto interesante.

¿De que va?

Sword Art Online es un VRMMORPG ( Virtual Reality Massively Multiplayer Online Role-Playing Game ), es decir, como el World of Warcraft pero con un casco de realidad virtual.

Lo guay que tiene ese casco es que una vez puesto intercepta todas las señales que entran y salen de tu cerebro de forma que dejas de sentir y poder mover tu cuerpo para solo sentir y mover tu avatar. Lo que se llama inmersión total (Full Dive).

nervegear

Para conseguir penetrar en el cerebro usa microondas, como las de calentar la leche, pero de baja intensidad.

El día en que se lanza el juego 10000 personas se conectan y empiezan a jugar. En este tipo de juegos los recursos son limitados así que el que antes entra tiene más facilidades para hacerse con objetos únicos, subir de nivel y acabarse el juego en primer lugar.

Pasadas unas horas los jugadores quieren desconectarse para hacer cosas como tomarse una pizza, estudiar para un examen, ... pero el botón de desconectar ha desaparecido del menú.

logout

Tras el desconcierto inicial todos los jugadores son forzosamente teletransportados a la plaza central del primer piso y el creador del juego, que es un bromista de la leche, les comunica que puede matarles cuando le venga en gana friéndoles el cerebro con las microondas que usa el casco.

logout

Las reglas son las siguientes:

  • si alguien te intenta quitar el casco mueres
  • si mueres en el juego mueres de verdad
  • si quieres volver al mundo real acábate el juego llegando hasta el piso 100 y cargándote a todos los jefes de todas las plantas
  • no existe comunicación con el mundo real para hacer la experiencia más "inmersiva"
  • en el mundo real conocen estas mismas reglas

Se quedaría solo en una broma pesada si fuera un juego corto, pero es que en la prueba beta solo consiguieron llegar hasta el décimo piso después de unos meses.

youaredeath

El protagonista es Kirito, un beta tester del juego, que se ve atrapado junto a otros miles de personas en ese metaverso. En ese juego mortal conoce a un montón de gente con quienes vive muchos meses.

people

No pretende ser una historia alegre para niños así que prepárate para ver morir a niños y preadolescentes, romances, dramas, historias de superación, ... e incluso sexo censurado en el capítulo 16.5 de las novelas ligeras.

Y esta es la intro de la serie, canción cortesía de LiSa:

¿Y porqué es especial?

Todos los jugadores se ven obligados a vivir en ese metaverso durante muuuuucho tiempo y para muchos acaba convirtiéndose en su mundo real. Es muy interesante ver los sentimientos y la forma de afrontar la situación de todas las personas, desde la heroicidad de los protagonistas a la cobardía de los suicidas pasando por la maldad de los asesinos. De alguna forma todos nos veremos reflejados en algún personaje de la serie y entenderemos realmente que significa el concepto de metaverso.

people

Velocidad

La serie va a la esencia de lo que quiere contar. No es un Dragon Ball ni nada por el estilo.

En los primeros 14 capítulos se cuenta la historia de lo que pasa en los primeros 75 pisos.

Fíjate lo que acabo de escribir: 75 pisos en 14 capítulos. Pasan muchíiiiiiiisimas cosas en cada capítulo de 20 minutos así que es imposible aburrirse.

Cultura general

Solo es necesario que te veas los primeros 14 capitulos para comprender el fenomeno y solo necesitas ver los dos primeros, de 20 minutos cada uno, para saber si te va a gustar o no.

Además, a partir de ese capítulo 14 salen todos los videojuegos de la saga así que si o si necesitas llegar hasta ahí si vas a jugar los juegos.

No te dejes liar por lo que te cuento a continuación y haz lo que pone en los dos párrafos de arriba. ;-)

A saltos

La sensación que se te queda cuando ves el anime, manga o novelas ligeras es que se pegan unos saltos muy grandes quedándote con la sensación de no saber de donde salen los personajes o como se ha llegado hasta ahí.

sao_light_novels

Esto ocurre porque el autor, Reki Kawahara, presentó la novela a un concurso que limitaba el tamaño de la misma y tu estás viendo esa versión.

Pero entre los capítulos pasan muchas cosas que están en las novelas ligeras de Sword Art Online Progressive donde se cuentan las cosas más en detalle:

sao_progressive

No en la reunión para enfrentarse al primer jefe

Kirito es un luchador solitario. Cuando se cruza con alguien en alguna mazmorra y le ve mal intenta ayudarle pero no interviene salvo que vea las cosas mal.

Un día en una mazmorra ve a un jugador encapuchado que tiene algo especial. Se nota que es novato porque hace tonterías de novato, pero cuando lucha lo hace con un nivel de definición PERFECTO nunca visto antes para él así que le pica la curiosidad y cuando el jugador acaba con los monstruos a su alrededor y se sienta apoyado en una pared a descansar, Kirito se le acerca para hablar con él.

asuna_encapuchada

Cuando el otro le contesta se lleva una sorpresa al ver que es un jugador de un tipo muy extraño en Aincrad porque no es un jugador sino ¡una jugadora!

Kirito ve en ella a una persona que si formara parte de un raid podría ser muy relevante, ayudar a muchas personas y ser clave para liberarlos a todos de ese juego mortal.

Esa jugadora es lo que se suele llamar la empollona de la clase: metódica, perfeccionista, tenaz, ...

A ella no le gustan los videojuegos y tenía un examen la semana pasada al que no ha podido asistir. El casco de realidad virtual es de su hermano pero el día del estreno del juego él estaba de viaje así que ella se decidió a probarlo y se vio encerrada ahí. Fue el mayor error de su vida.

Ella estaba decidida a suicidarse luchando hasta morir en esa mazmorra pero Kirito la salvó. Su visión del mundo cambió mientras se daba una ducha de polígonos azules en la habitación de Kirito y los sentía como si fueran agua en su cuerpo virtual.

Kirito no conoce a Asuna en la reunión para acabar con el jefe del primer piso tal como parece en el Anime. ¿Y como se yo todo esto?

Complemento casi necesario

Para enterarte bien de la historia y entender de donde salen personajes como Asuna, Argo la rata, Agil, ... tienes que leerte los hechos que ocurren entre el primer y el segundo capítulo.

En las 112 primeras páginas del primer volumen de Sword Art Online Progressive está todo lo que necesitas saber.

sao_volumen_1

Lo tienes traducido solo por molestar aquí.

En las siguientes 200 páginas hay cosas que no necesitas saber pero querrás saber.

El resto de volúmenes están muy bien pero no son necesarios para comprender la historia principal aunque encierran cosas como el origen de Aincrad contado por la elfa oscura Kizmel.

kizmel

Te puedes bajar todo traducido de un grupo que lo hace solo por molestar y al que le debo un montón de horas de entretenimiento. ;-)

En concierto

Si ya has visto la serie, cuando escuches este concierto no podrás evitar que se te erize la piel. Toda la banda sonora cantada por profesionales y muy bien ambientada:

Tiene una de las mejores bandas sonoras que he escuchado. Y cada vez que lo hago encuentro un matiz nuevo.

Ahora mismo se me esta erizando el bello.

Gracias Yuki

Entregas

Como he dicho, en aquel alejado rincón del planeta, Sword Art Online ha tenido y sigue teniendo un gran impacto desde que empezó en el 2009:

También se está planificando crear una especie de NerveGear, pero sin sorpresa, y otro juego llamado "Sword Art Online - The Beginning -":

Me he visto todas las temporadas de anime, jugado a los dos primeros juegos y estoy con el tercero.

Mundos

Pero esta serie es muy ambiciosa y entre sus animes, novelas y juegos, cubre desde los mundos de espadas:

sao+alo

hasta los mundos de armas en Phantom Bullet y Alternative:

phantom_bullet

Y nos da una visión sobre como sería vivir en ellos de verdad usando muy bien el concepto de metarverso.

También cubren la realidad aumentada en Ordinal Scale:

ordinal_scale

Y cultivar Inteligencia Artificial dentro de un metaverso en Alicization.

sao+alo

Todo dentro de Metaversos accesibles solo por Realidad Virtual. Si te gustan todos estos temas, no debes perderte esta serie.

Bye bye Star Wars

Desde que Star Wars pasó a ser de Disney y pusieron a anidar a un Porg en el Halcón milenario estoy buscando otra saga que esté a la altura y esta lo está para mi.

He cambiado un mundo de fantasía en el que existe una fuerza midicloriana que lo une todo y pretende ser realista pero nunca podrá serlo, por otro fantástico, que pretende ser fantástico y cuyos únicos poderes se basan en tu trabajo, insistencia y a veces en predecir las líneas de predicción.

Como es un universo VR con trabajo y esfuerzo si podremos hacerlo, aunque yo no lo veré.

Coste

Aunque nadie dijo que fuera a ser barato. :-D

Enlaces interesantes

Un poco de música para amenizar el trabajo

Una hora de música épica que encontrarás en Sword Art Online:

10 de July de 2019 a las 14:33

05 de April de 2019

Jose Manuel

AWS S3 ¿on-premise?

minio ha sido, junto a un bug de la máquina de vending que me permite sacar dos bollitos por el precio de uno, mi descubrimiento más grande de esta semana.
Permite tener un servicio compatible con AWS S3 en tu cluster de Kubernetes. Esto podrá parecer innecesario si trabajas en cloud pública, donde ese servicio ya existe, pero en entornos on-premise es una necesidad muy real.

¿Porqué AWS S3 on-premise?

Cuando hablamos de servicios cloud no solo hablamos de disponibilidad, replicación, gigas, y con casinos, y ....... .

Para el desarrollador de un equipo agile lo importante es tener un api para poder trabajar. Y si además es un api "estandarizada" pues mucho mejor porque nos permite desarrollar nuestras aplicaciones de forma que son independientes del entorno sobre el que corren.

Por desgracia en los clientes que suelo frecuentar hay una cierta alergia a todo lo que sea externalizar servicios por lo que AWS S3 les provoca urticaria pero minio encaja como un guante.

Despliegue en OpenShift

Usamos los objetos de karrier.io un poco modificados e incrustados en una plantilla que puedes encontrar en este repositorio.

Ejecuta:

oc new-app -f minio-template.yaml

Y ya está. ¿A que pensabas que iba a ser más difícil? ;-)

openshift

Recuerda apuntar la "Access Key" y la "Secret Key".

Venga, te pongo la salida del comando para que parezca más difícil:

jmferrerm@serenity:~/blog/AWSS3on-premise$ oc new-app -f minio-template.yaml -p MINIO_ACCESS_KEY=holaaaaaaa -p MINIO_SECRET_KEY=adiooooooos
--> Deploying template "jmferrer-minio-template/minio" for "minio-template.yaml" to project jmferrer-minio-template

     min.io
     ---------
     A min.io service.  For more information about using this template, including OpenShift considerations, see https://github.com/elmanytas/minio-openshift/blob/master/README.md.

     WARNING: This template needs a default storage class with space enough.

     The following service(s) have been created in your project: minio.

     For more information about using this template, including OpenShift considerations, see https://github.com/elmanytas/minio-openshift/blob/master/README.md.

     * With parameters:
        * Name=minio
        * Memory Limit=512Mi
        * Application Hostname=
        * Access Key=holaaaaaaa
        * Secret Key=adiooooooos

--> Creating resources ...
    secret "minio-keys" created
    service "minio" created
    route "minio" created
    statefulset "minio" created
--> Success
    Access your application via route 'minio-jmferrer-minio-template.osapps.elmanytas.es'
    Run 'oc status' to view your app.
jmferrerm@serenity:~/ownCloud/blog/AWSS3on-premise$

Uso con la cli de aws

Hacemos un uso normal cambiando el endpoint url tal como pone aquí:

jmferrerm@serenity:~$ aws --endpoint-url=http://minio-jmferrer-minio-template.osapps.elmanytas.es s3 ls
jmferrerm@serenity:~$ aws --endpoint-url=http://minio-jmferrer-minio-template.osapps.elmanytas.es s3 mb s3://swordartonline
make_bucket: swordartonline
jmferrerm@serenity:~$ aws --endpoint-url=http://minio-jmferrer-minio-template.osapps.elmanytas.es s3 cp /tmp/YukiKajiuraSAOLive.mp4  s3://swordartonline
upload: ../../tmp/YukiKajiuraSAOLive.mp4 to s3://swordartonline/YukiKajiuraSAOLive.mp4
jmferrerm@serenity:~$ aws --endpoint-url=http://minio-jmferrer-minio-template.osapps.elmanytas.es s3 ls s3://swordartonline
2019-04-04 20:04:27  237535530 YukiKajiuraSAOLive.mp4
jmferrerm@serenity:~$

GUI

El GUIaburros es simple y escueto.

login

Tanto que no necesita mayor explicación:

interfaz

Happy object storing!!

Un poco de música épica para amenizar tu fin de semana

Conciertazo en vivo de Yuki Kajiura 梶浦由記 at 「Sword Art Online event “Sing all Overtures”」:

05 de April de 2019 a las 20:51

26 de March de 2019

Jose Manuel

Crea tu portal con Antora

A la hora de crear un portal siempre nos encontramos con los mismos problemas: la gestión de permisos, la "caducidad" de la plataforma, el formato de la documentación, la gestión manual de la documentación, uniformidad de los estilos en todos los portales, transformación entre diferentes formatos, ...

Antora es un generador de portales a partir de AsciiDoc, lo cual se suma a la facilidad que tiene para transformarse en varios formatos como epub, pdf o html.

Tendencias

Desde hace unos años podemos ver como diferentes empresas desarrollan su documentación usando un lenguaje de marcado organizado en repositorios:

Soporte

Existen plugins de AsciiDoc para los CMS más populares como pueden ser Wordpress o Drupal. Y lo mismo con Markdown.

También tenemos plugins para los principales IDEs que permiten ver en tiempo real el resultado de tu trabajo:

Github Atom Microsoft Visual Studio Code
Atom Code

Y por supuesto, tal como has podido ver pinchando en los enlaces de tendencias, están soportados de caja en cualquier servicio de git que ofrezca una mínima funcionalidad como Github o Gitlab.

Sintaxis de lenguajes de marcado

Hay unos que se caracterizan por ser más fáciles y otros más difíciles pero con más funcionalidad.

Por ejemplo, para poner énfasis en algo tenemos lo siguiente:

Markdown AsciiDoc DocBook
texto en **negrita** texto en *negrita*

texto en <emphasis>negrita</emphasis>

Resumir toda una sintaxis en tres líneas es muy difícil pero esto nos da una idea de que Markdown y AsciiDoc pueden llegar a parecerse en cuanto a simplicidad mientras DocBook, al usar xml, puede ser más tedioso.

La tendencia ha sido simplificar todo lo posible la edición manteniendo toda la funcionalidad necesaria y por eso lo más usado suele ser Markdown o AsciiDoc. Por supuesto que existen otros formatos como Doxygen, que son perfectamente válidos, pero parece que el mercado tiende a Markdown o AsciiDoc dependiendo del uso.

¿Markdown o AsciiDoc?

Si queremos un documento que al mostrarse por la web tenga enlaces a otros documentos pero al generarse el PDF se incrusten, deberemos poner en AsciiDoc:

ifdef::env-gitlab,env-github,env-browser[]
Secciones:

* link:./arquitectura/arquitectura.adoc[Arquitectura]
* link:./infraestructura/infraestructura.adoc[Infraestructura]

endif::[]

ifdef::ebook-format-kf8,backend-pdf[]

include::./arquitectura/arquitectura.adoc[]
include::./infraestructura/infraestructura.adoc[]

endif::[]

Si quieres hacerlo en Markdown, no podrás.

AsciiDoc tiene bastantes funcionalidades que Markdown no tiene y su uso es casi igual de fácil.

En Markdown ha habido intentos de incluir funcionalidad que en AsciiDoc viene de caja pero han desembocado en distintas implementaciones que pueden funcionar o no dependiendo del servicio que utilices.
Por ejemplo, la implementación de Gitlab es distinta a la de Github, lo que supone un problema en cuanto a portabilidad.

Renderizando, ando

Vamos a renderizar este documento a diferentes formatos a partir de este archivo, como son:

Para renderizar un documento hemos usamos la imagen docker-asciidoctor que la organización mantiene en dockerhub.

Creando un portal

Podría subir los html estáticos a un servidor y ya tendría mi portal, pero existen frameworks que permiten generar portales fácilmente tomando como fuentes uno o varios repositorios.

En la wikipedia nos encontramos con tres frameworks cuyas pruebas me han hecho llegar a las siguientes conclusiones:

Antora

Antora permite la creación de un portal a partir de un playbook en formato yaml donde se definen todos los repositorios que lo forman.

De esta forma podemos tener diferentes repositorios para sistemas, seguridad, desarrollo, …​ y Antora se encargará de juntarlos todos en un solo portal al que aplicará los mismos estilos. Cada uno de esos repositorios es un "componente" del portal para Antora.

En cada repositorio (componente) necesitamos crear un archivo llamado antora.yml donde definiremos las secciones que formarán este componente. Cada una de esas secciones es un "módulo" para Antora.

Si el repositorio tiene varias ramas nos puede crear una versión del componente por cada una de ellas.

Un ejemplo de Antora

Por suerte la documentación oficial es realmente clara en este aspecto pero voy a intentar simplificarla más.

Clona el siguiente repositorio:

git clone https://gitlab.com/antora/demo/demo-site

Dentro del repositorio verás el playbook site.yml con este contenido:

site:
  title: Antora Demo Site
  # the 404 page and sitemap files only get generated when the url property is set
  url: https://example.org/docs
  start_page: component-b::index.adoc
content:
  sources:
  - url: https://gitlab.com/antora/demo/demo-component-a.git
    branches: master
  - url: https://gitlab.com/antora/demo/demo-component-b.git
    branches: [v2.0, v1.0]
    start_path: docs
ui:
  bundle:
    url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/master/raw/build/ui-bundle.zip?job=bundle-stable
    snapshot: true

Este archivo indica a antora que la raíz del portal (site.start_page) será el archivo index.adoc del componente b.

Además irá a los dos content.sources y generará sus html con la versión master para el primero mientras para el segundo generará las versiones v2.0 y v1.0 partiendo del directorio docs.

Ejecuta esto para generar los estáticos:

docker run -u $UID --privileged -v `pwd`:/antora --rm -t antora/antora site.yml

Tu portal ahora se encuentran en build/site/index.html

Cambios para construir un portal

Imagina que tienes un archivo en AsciiDoc llamado antora.adoc en un repositorio y quieres cambiar su estructura para tener un portal. Todo el contenido está en la rama master de un único repositorio ubicado en https://github.com/elmanytas/antora-examples:

A partir de este momento puedes trabajar tal como lo hacías antes escribiendo en modules/ROOT/pages/ y dejando las imágenes en modules/ROOT/assets/images/. Todo lo que escribas aparecerá en tu portal ejecutando:

docker run -u $UID --privileged -v `pwd`:/antora --rm -t antora/antora site.yml

26 de March de 2019 a las 23:33

23 de March de 2019

Jose Manuel

Kubernetes a través de Terraform

En esta ocasión vamos a probar como de bueno o malo es el provider de Terraform para Kubernetes.

Por si no lo conoces, Terraform es el "anillo único" que permite gestionar como código todas las infraestructuras que se te pongan por delante (y para las que haya un provider). Una ventaja de Terraform es que si eliminas un objeto de tu código, también se elimina en tu infraestructura, lo que no pasa con Cloudformation de AWS o Heat de OpenStack.

Buscando el Ingress

Con un rápido vistazo a la página del provider de Terraform para Kubernetes echamos en falta algo tan normal como el objeto Ingress y tampoco podemos crear objetos custom. Si además conoces OpenShift verás que faltan DeploymentConfig y Route.

Pero vamos a ver porqué no están los Ingress. Lo primero que pensé es que a lo mejor era un custom que no formaba parte del core de Kubernetes y por eso no estaba agregado así que me fui al código del provider de Kubernetes.
Vi que importaba un tal k8s.io/api/apps/v1 y me fui a buscarlo a github donde vi que el Ingress está implementado en el core directamente ¡desde hace 2 años!

Conclusión: en Terraform faltan cosas que no te esperas que falten, como Ingress aunque parece que algo se está moviendo, y OpenShift viene con muchos objetos que ni se pueden gestionar desde Terraform ni creo que se vayan a poder gestionar a corto plazo aunque algo se está moviendo también.

Caso OpenShift

Si estamos dispuestos a usar Deployments en OpenShift y gestionar las rutas a mano, entonces este provider si nos puede valer.

Con OpenShift he probado esto:

provider "kubernetes" {
  host = "https://openshift.serenity.es:9443"
}

resource "kubernetes_config_map" "example" {
  metadata {
    name = "my-config"
    namespace = "terraform"
  }

  data {
    api_host = "myhost:443"
    db_host  = "dbhost:5432"
  }
}

Y me ha creado el configmap:

jmferrerm@serenity:~/gitops/openshift$ oc get cm
NAME        DATA      AGE
my-config   2         6s

Luego he probado a borrarlo del fichero y lo ha borrado de OpenShift así que en principio hace lo que dice que hace:

jmferrerm@serenity:~/gitops/openshift$ terraform apply
kubernetes_config_map.example: Refreshing state... (ID: terraform/my-config)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - kubernetes_config_map.example


Plan: 0 to add, 0 to change, 1 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

kubernetes_config_map.example: Destroying... (ID: terraform/my-config)
kubernetes_config_map.example: Destruction complete after 0s

Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
jmferrerm@serenity:~/gitops/openshift$ oc get cm
No resources found.

¿Lo uso o no lo uso?

Esto es algo que te toca a ti valorar ... pero si quieres mi opinión, para Kubernetes es un SI rotundo gestionando con un "kubectl apply" los ingress, que raramente van a cambiar, y esperando a que finalmente se cree esa función.

En OpenShift tenemos que estar dispuestos a usar Deployments en vez de DeploymentConfigs y eso en la mayoría de ocasiones suele ser un problema ya que al crear una aplicación, OpenShift utiliza DeploymentConfigs.
En OpenShift el criterio es ... ¿Quiero usar GitOps o los procedimientos que me ofrece RedHat para la gestión de Kubernetes?

Yo llevo apostando por GitOps desde antes que alguien le diera nombre.

23 de March de 2019 a las 07:20

10 de March de 2019

Jose Manuel

Currículum

Jose Manuel Ferrer Mosteiro

Skills

  • Administrador Unix con experiencia en múltiples distribuciones de GNU/Linux (RHEL, Ubuntu, CentOS, Debian) y Windows.
  • Conocimientos de IaaS / PaaS públicos con AWS y GCE .
  • Conocimientos muy profundos de IaaS / PaaS privados con OpenStack, Kubernetes y OpenShift así como de Docker y KVM.
  • Gestión de la configuración y automatización (Puppet, Ansible, OpenStack Heat).
  • Programación con Python, Ruby, Bash y Perl.
  • Sistemas de control de versiones git y svn.
  • Experiencia con despliegue y gestión de sistemas distribuidos (ElasticSearch, MongoDB, Logstash, ActiveMQ, RabbitMQ)
  • Habilidades en entornos de realidad virtual (OpenSim, High Fidelity).

Charlas

Experiencia

Septiembre 2014 - ahora: Paradigma Digital

  • Despliegue, gestión y uso de Kubernetes, OpenShift y OpenStack.
  • Automatización y gestión de la configuración con Ansible y Puppet.
  • Despliegue, gestión y uso de jobs y pipelines en Jenkins.
  • Docker
  • Codificación en Python y bash
  • Git
  • Gestión de RHEL, Debian, CentOS y Ubuntu.
  • Despliegue y gestión de ElasticSearch, Logstash y Kibana dentro y fuera de OpenShift.
  • Despliegue y gestión de MongoDB y Redis.
  • Despliegue y gestión de RabbitMQ y ActiveMQ.

10 de March de 2019 a las 06:45

03 de March de 2019

Jose Manuel

Retrogaming IV: Las maquinitas

Las maquinitas

Toda una reliquia de nuestra niñez. Nos pasamos horas frente a una pantalla de cristal líquido escuchando un pitido tras otro con nuestra Game & Watch preferida.

Pues puedes volver a hacerlo y a tus hijos les encantarán estos juegos.

El problema

No todas las maquinitas se ven igual en todos los emuladores y el catálogo de juegos disponibles es muy limitado así que para muchos juegos no nos quedará otra que comprar las máquinas originales.

Y no estoy hablando de juegos extraños. El Donkey Kong II, uno de los grandes referentes de este género, solo se puede jugar bien con la maquinita original.

Y aquí llega el auténtico problema: salvo que tengas 6000€ sueltos en el bolsillo y unos meses libres para buscar, ir y venir, no podrás comprarlas todas. El precio de cada maquinita en el mercado de segunda mano oscila entre los 50€ y los 500€ dependiendo de distintos factores en los que no voy a entrar.

Si, la maquinita que tienes tirada en el trastero vale más que los pendientes de oro que le regalaste a tu chica. :-D

Formatos de pantalla

Las maquinitas se hicieron en un momento en que primero se pensaba el juego y luego el hardware. Eso hizo que hubiera maquinitas de una sola pantalla en horizontal, una pantalla en vertical, dos pantallas en horizontal dispuestas en vertical o dos pantallas en horizontal dispuestas en horizontal. Lo único que falta es en diagonal. ;-)

Como te podrás imaginar, en un mundo que ha evolucionado hacia el formato panorámico con una sola pantalla, emular estas consolas puede resultar un problema así que veremos cada caso por separado tomando como referencia los siguientes juegos que todos conocemos:

  • Donkey Kong Junior
  • Donkey Kong
  • Mario Bros

Donkey Kong Jr.

Este parece de los fáciles: pantalla panorámica, cruceta y un botón. Pero si buscamos su ROM no la encontraremos así que ya no es tan fácil.

Pero estamos buscando mal: en el año 2007 Nintendo sacó la Game & Watch Gallery 3 y uno de los juegos que tenia era precisamente el Donkey Kong Jr. Asi que el problema ahora es emular una GameBoy Advance y ¡eso es muy fácil!
Aqui lo tenemos:

Con otros juegos, como el Donkey Kong Circus, emularemos la consola usando el core Handhelds Electronic de RetroArch con este resultado:

Mas adelante entraremos más en detalle, pero ahora quédate con que de una forma mas o menos retorcida si se puede jugar bien a casi todos los que tengan formato panorámico, siempre que la rom este disponible.

Donkey Kong

Dos pantallas en horizontal dispuestas en vertical.

En una sola pantalla panorámica ... poderse se puede pero el resultado es un churro con el core Handhelds Electronic de retroarch por culpa del hardware:

En este caso la pantalla cuanto más alta mejor así que si hay que elegir yo me quedaria con la PSVita.

Si has leído mi artículo anterior pensarás: "pues pon la psvita en vertical usando el joystick derecho para las flechas y el botón para saltar". ¡Eres un blasfemo! ¡A un niño no se le enseña a jugar a una maquinita con un joystick! ;-)

La buena noticia es que en el 2006 Nintendo hizo la Game & Watch Collection 1 para Nintendo DS donde incluyó entre otros el Donkey Kong y asi es como se ve en una Nintendo 3ds y una dsi:

Doy fe de que la sensación es casi exactamente igual a la de la máquina original.

Mario Bros.

Dos pantallas en horizontal dispuestas en horizontal.

Si el panorama del formato vertical estaba mal este no está mucho mejor. En este formato la PSVita gana por la proporción y tamaño de la pantalla. Incluso haciendo zoom el resultado sigue sin ser óptimo, aunque si mejor que el que viene en la Game & Watch Gallery 3 tal como se puede ver aquí:

He probado a jugar con la PSVita al Mario Bros habiendo obtenido los 800 y pico puntos que obtengo con la maquinita original y tengo que decir que me quedo con Retroarch antes que con el de la Game & Watch Gallery 3. La emulación tiene algunos fallos que ocurren cuando tardas demasiado en recoger un paquete pero por lo demás está perfecta.

Para el Mario Bros existe un Homebrew de Nintendo DS muy bien logrado en el que se usa la cruceta para los dos personajes del que hablaré en la sección de Homebrews.

Listado de todos los juegos

Si te interesa de verdad este tema en este artículo de la wikipedia tienes TODO.

Nintendo ¡no mató los Game & Watch al evolucionar las consolas! Con una pequeña búsqueda podemos encontrar varios títulos disponibles para DS y 3DS.

Además, mediante emulación utilizando retroarch y bajándonos las roms de varias maquinitas desde MADrigal podemos conseguir unos cuantos títulos.

En el wiki de emulation.miraheze.org tenemos información más extendida.

Tienes enlaces para bajarte varios juegos y homebrews en este blog.

Virtual Console para Nintendo 3ds

Nintendo publicó varios juegos de Game & Watch para GameBoy, GameBoy Color y GameBoy Advance que se ven bastante bien en la 3ds y su UX nos acerca bastante a la real. Además, podemos comprar todos los juegos de GameBoy que están en el catálogo. Un punto para Nintendo.
Por supuesto también funcionan con los cores que vienen en Retroarch. En el post de GameBoy explicaré como.

Pegas:

  • Con los juegos de dos pantallas para GameBoy Nintendo optó por poner la pantalla superior más pequeña y la inferior más grande. Tampoco es que se pueda hacer mucho mejor pero el resultado es bastante cutre. Los juegos de dos pantallas hay que jugarlos con dos pantallas.
  • Al ser juegos de GameBoy emulados, heredan la resolución de pantalla de esta máquina que resulta claramente insuficiente para los juegos de Game & Watch.

  • Una pega más es que no se ven las sombras tan características de este tipo de pantallas LCD. No les hubiera costado nada emularlas.
  • Empezamos con los que ahora Nintendo ofrece como Virtual Console:

    Game & Watch Collection para Nintendo DS

    Allá por el 2006 Nintendo sacó dos juegos que emulaban Game & Watch para Nintendo DS aprovechándose bien de las dos pantallas.

    Sin duda, si lo que quieres es revivir estos clásicos de dos pantallas y no tienes la maquinita original, necesitas el Game & Watch Collection 1. Se hace una emulación casi perfecta utilizando las dos pantallas y la disposición de los controles recuerda mucho más a los originales.

    Si me dan a elegir mejor en la DS que en la 3DS porque la DS tiene las dos pantallas iguales y la resolución encaja mucho mejor.

    Homebrews

    La mala noticia es que Nintendo solo saco esos tres juegos de dos pantallas dejando de lado otros grandes como el Donkey Kong II.

    Donkey Kong II

    Existe un Homebrew del Donkey Kong II para Nintendo DS hecho por Martin Kool pero no tiene bien resuelto el tema de las colisiones así que no es muy jugable. En el apartado estético roza la perfeccion. Con la Y y con la X se activan las sombras y las colisiones.

    Mario Bros

    Para el Mario Bros existe un Homebrew para Nintendo DS muy bien logrado en el que se usa la cruceta para Mario y Luigi.

    Poniendo otra cruceta en la parte izquierda de la pantalla superior creo que se podria conseguir casi la misma sensacion que en la consola original.
    Habría que usar una DS Lite y mover la antena al lado derecho de la pantalla o en el caso de la DSi quitar la antena tal como se ve en esta foto de la pantalla desmontada:

    Donkey Kong Jr.

    Existe un homebrew interesante para el Donkey Kong Jr. en github cortesía de PaulGoes: https://github.com/PaulGoes/DS-Donkey-Kong-Jr/

    Pokemon Mini

    Un comercial pensó ... ¿Y si aprovechando el poder de la marca Pokemon hacemos una videoconsola que no tenga nada que ver con Pokemon para conseguir ventas millonarias? Y así nació ¡Pokemon Mini! pero les salió mal y cerraron el chiringuito poco después de abrirlo.

    Me recuerda a lo de, "visto el éxito de Java, ¡llamémoslo JavaScript!". :-D
    Vamos, que no tienen nada que ver pero aprovechando el nombre de Pokemon sacaron esta consola donde podemos encontrar juegos de todo tipo con la temática de Pokemon. Por ejemplo, cada vez que haces 4 líneas del tirón con el Tetris, aparece una pokeball en la pantalla y capturas un Pokémon.
    Esta es extremadamente difícil de conseguir pudiendo llegar fácilmente en el mercado de segunda mano a los $500.

    También existe un emulador para el Pokemon Mini así que si a tu hijo le gustan los Pokemon y quieres que aprenda a jugar al tetris esta puede ser una buena opción.

    Existen emuladores para Nintendo DS y PSP así que funciona sobre 3ds y PSVita sin problemas. Me vuelvo a quedar con la 3ds por tema de tamaño de pantalla.

    Hay un port nativo para 3ds.

    La mejor

    La Nintendo DS es la mejor máquina para jugar a los juegos Game&Watch que existen disponibles para ella. La segunda opción es la 3DS y la peor es la PSVita/PSP tal como le pasaría a cualquier consola con una sola pantalla.

    Nintendo, por favor

    Señores de Nintendo, fabriquen estas maquinas por 2 euros en China y las compraremos por 15. ¡Solo tenéis que poner las manos para recoger el dinero!

    03 de March de 2019 a las 08:38

    25 de January de 2019

    Jose Manuel

    MySQL no es perfecto

    Primer problema de MySQL en los 12 años de vida de este blog:
    MariaDB [drupal7]> select * from semaphore;
    ERROR 144 (HY000): Table './drupal7/semaphore' is marked as crashed and last (automatic?) repair failed
    MariaDB [drupal7]> repair table semaphore;
    +-------------------+--------+----------+----------------------------------------+
    | Table             | Op     | Msg_type | Msg_text                               |
    +-------------------+--------+----------+----------------------------------------+
    | drupal7.semaphore | repair | warning  | Number of rows changed from -2032 to 0 |
    | drupal7.semaphore | repair | status   | OK                                     |
    +-------------------+--------+----------+----------------------------------------+
    2 rows in set (0.00 sec)
    
    MariaDB [drupal7]>
    
    Hasta hoy yo estaba convencido de que era irrompible.

    25 de January de 2019 a las 10:57

    25 de July de 2018

    Jose Manuel

    Retrogaming III: Los emuladores

    Seguro que ya lo cononoces el agregador de emuladores con más tirón del momento: Libretro o Retroarch. Pero lo que no conoces son algunos trusquis mal documentados que te permiten jugar bien y que te voy a contar aquí.

    En este post haré una pequeña introducción a retroarch, instalación y lanzamiento de alguna rom que se vea mal.

    Por si no lo conoces ...

    ... libretro es un lanzador de emuladores, que él denomina cores. Existen cores para Arcade, maquinitas, Gameboy, PlayStation, ... y todos ellos vienen instalados o son fácilmente descargables con Retroarch, que es otro proyecto que utiliza el api de libretro para hacer el frontend.

    Su diseño modular en interfaz y cores nos permite poder instalar solo lo que necesitamos permitiéndonos utilizar hardware a medida. Actualmente el 90% de las soluciones de emulación funcionan con Retroarch.

    Hace no mucho tiempo ...

    ... en nuestro planeta, si querías usar un juego primero tenías que elegir un emulador que pudiera emularla de entre todos los existentes, luego conocer los parámetros con los que lanzar el emulador y muchas veces el juego fallaba sin saber porqué.

    Con retroarch tenemos un solo instalador para todos los emuladores existentes, una sola interfaz para lanzar los juegos y un procedimiento de instalación fácil y rápido.

    Instalación

    Primero ve a la y mira si tu consola está entre ellas. Si no aparece ahí puedes probar suerte directamente en la página de descargas.

    Te recuerdo que en esta serie de posts no hablamos de PCs sino de PSP, PSVita, NDS y 3DS.

    En esta parte doy por supuesto que tu consola ya está desbloqueada y conoces de forma básica su manejo. Si no lo está y no sabes como hacerlo te tendrás que esperar a que lo cuente en algún post de esta serie para que lo explique un poco así que ten paciencia y mientras tanto ¡no actualices el sistema de la consola!

    Instalación en PSVita

    Tenemos dos opciones de instalación: vía homebrew browser y vía descarga de la aplicación.

    La instalación usando el Homebrew Browser dejó de funcionar en algún momento porque ahora es necesaria una copia manual de archivos después de instalar el paquete vpk y el Homebrew Browser solo instala paquetes.

    En la página de descargas vemos dos archivos y nos tenemos que bajar los dos. Instalamos el vpk utilizando VitaShell.

    Copiamos el contenido de Retroarch_data.7z en ux0:data/ para lo cual no recomiendo utilizar el servidor de ftp que viene con VitaShell porque aunque solo son 28mb, son miles de archivos que transmitidos por ftp pueden tardar horas en copiarse.

    Y ya lo tenemos:

    Instalación en PSP

    Nos vamos a la página de descargas y nos bajamos el archivo para nuestra consola ... pero vemos que ocupa muy poco espacio, solo 4 megas y pico.

    Esto se debe a que tiene muy poquitos cores y algunos de los que faltan son muy importantes, como el de MAME, pero eso ya lo hablaremos más adelante.

    Para instalarlo copiamos el contenido del 7z al directorio PSP/GAME/RetroArch de la tarjeta y ya está instalado.

    Instalación en Nintendo New 3ds

    Como ya sabrás podemos utilizar homebrews en formato cia o 3dsx. Los .cia son instalables de 3ds que aparecerán en el menú con el resto de los juegos mientras los .3dsx son archivos que copiamos en el directorio sdmc:/3ds/ y que se podrán abrir usando "The homebrew launcher".

    Si elegimos el formato 3dsx solo tenemos que copiar el contenido del archivo en la raíz de nuestra MicroSD o en sdmc:/3ds/ en caso de usar el servicio de FTP, cosa que no recomiendo porque nos podemos tirar horas para copiar todo.

    Si elegiste la distribución 3dsx ¡ya está instalado! peeeeero me ha dado problemas que lo han hecho inusable asi que no lo recomiendo.

    Si elegiste la distribución cia debes instalar todos los cia usando el FBI de la forma habitual.

    En el caso de Nintendo, el resultado es un poco más sucio porque una vez instalado todo tendrás un icono por cada uno de los cores en el menú:

    Se suponía que Retroarch te ocultaba la existencia de los cores pero este te los muestra todos en el menú principal. Yo los he puesto muy a la derecha para diferenciarlos del resto de programas.

    Instalación en Nintendo DSi

    La Nintendo DSi no está soportada por retroarch pero tiene emuladores por separado que ya veremos más adelante. No la subestimes por no poder usar Retroarch, aunque ya te adelanto que no es la mejor opcion.

    Primeros pasos

    La guía oficial es bastante explicativa.

    Configuración de retroarch

    Probablemente nunca tengas necesidad de tocar la configuración pero por si acaso en el repo de retroarch puedes encontrar lo necesario para saber donde tocar.

    El fichero de configuración se encuentra en ux0:/data/retroarch/retroarch.cfg en el caso de la psvita o en sdmx:retroarch/retroarch.cfg en el caso de la 3ds.

    En este archivo se guarda la configuración de retroarch y de los cores de retroarch a nivel general. Si ves que TODOS los juegos de GameBoy funcionan mejor con una configuración aquí es donde debes tocar.

    Convenciones

    Es muy importante conocer el nombre de los botones para poder entender cualquier guía así que memoriza estos nombres:

    En las máquinas que solo tienen dos botones, como la GameBoy, los botones son el A y el B.

    Funciones que debes habilitar

    Antes de empezar a jugar debes tener activada la función que te permite congelar la partida y guardar el estado del emulador o realizar configuraciones específicas para ese juego.

    Se configura en "Configuración | Input | Menu Toggle Gamepad Combo" con las teclas del pad derecha e izquierda.

    En la PSVita se activa con L + R + Select + Start. Si tienes la 1000 te costará cogerle el trusqui a pulsar Select y Start a la vez pero yo ya lo hago sin problemas.

    En la New 3ds yo he elegido L + R + Y + Down pero pulsando sobre la parte inferior de la pantalla táctil también sale.

    Configuración avanzada

    Esto no te va a hacer falta, pero por si te hace falta te pongo un par de casos de juegos cuya configuración he tenido que cambiar para que se vean bien.

    Rotación de la pantalla y remapeo de teclas

    Vamos con el pacman de Arcade donde al arrancar vemos que ¡está del revés!

    Con el juego arrancado pulsamos el Menu Toggle Gamepad Combo y en la configuración elegimos la opción "Overrides":

    Y guardamos las opciones para ese juego:

    Esto nos creará un archivo de configuración para ese juego en la ruta_de_datos_retroarch/config/nombre_del_emulador/nombre_de_la_rom.cfg .

    Configuramos las opciones:

    video_rotation = 2
    video_allow_rotate = true
    


    y este será el resultado en el que rotamos 180 grados la pantalla:

    Pero este juego esta pensado para una pantalla mas vertical asi que necesitamos cambiar la rotacion y el mapeo de teclas.
    Rotamos la pantalla con esta configuracion:

    video_rotation = 3
    video_allow_rotate = true
    

    Y para el mapeo de teclas, mientras estamos en el juego salimos al menu con el Menu Toggle Gamepad Combo, vamos a "Controls" y cambiamos el mapeo de teclado para que:
    • arriba -> izquierda
    • abajo -> derecha
    • izquierda -> abajo
    • derecha -> arriba

    Luego guardamos los cambios, salimos, entramos y aqui esta:

    Proporción de la pantalla

    Pongamos por caso que arrancamos el Mario Bros y nos sale este churro:

    Pero esperamos esta proporción:

    Le damos a la combinación de teclas de arriba (Menu Toggle Gamepad Combo), elegimos la opción de sobreescribir las opciones para este juego y eso nos creará un archivo donde podemos personalizarlas, en el caso de la psvita, en ux0:data/retroarch/config/Game & Watch/Mario Bros. (Nintendo, Multi Screen).cfg.

    Sabiendo que la pantalla de la psvita es de 960x544 configuramos estas opciones:

    custom_viewport_width = 960
    custom_viewport_height = 544
    


    y el resultado es el siguiente:

    Si queremos hacer zoom sobre una zona del juego no tenemos más que decirle que nuestra pantalla es más grande de lo que realmente es y que empiece a pintar en el vacío:

    custom_viewport_width = 1200
    custom_viewport_heigh = 680
    custom_viewport_x = -115
    custom_viewport_y = -100
    


    Este es el resultado:

    Conclusiones

    Con Retroarch podrás tener todos los emuladores que quieras y aunque nunca vayas a tocar la configuración, puedes hacerlo para adaptarla a cualquier máquina existente en el mercado y poder enseñarle a tus hijos lo que eran juegos de verdad en una consola portátil:

    25 de July de 2018 a las 15:11

    Retrogaming (II)

    Cuando buscamos recordar juegos antiguos y no tenemos restricciones nos vale cualquier portátil viejo pero si queremos una máquina que nos quepa en el bolsillo empiezan los problemas.

    En esta y sucesivas entradas veremos una comparativa entre distintas consolas portátiles y como les pegan los distintos emuladores que existen entre los que nos encontramos:

    To retro or not to retro?

    La definición de retro es bastante subjetiva. Para alguien mayor puede que solo los juegos de Arcade sean retro pero para mis hijos lo es todo lo que tiene más de 10 años.

    Para mi algo retro es algo que no puedes comprar nuevo en una tienda aunque tengas dinero infinito. Por ejemplo, una Nintendo GameBoy. En el caso del software el panorama se complica bastante porque hay juegos que tienen 20 años y se siguen vendiendo para consolas modernas, como por ejemplo SEGA Genesis Classics para PS4 o SEGA 3d Classics Collection para Nintendo 3DS.

    También tenemos en la tienda The Legend of Zelda: Ocarina of Time 3D que es exactamente el mismo juego que se hizo para Nintendo 64.

    Es bastante habitual que los fabricantes de consolas modernas sigan haciendo reediciones de juegos viejos por lo que a lo mejor ya tienes el trozo de retroconsola que necesitas y no lo sabías.

    ¡Podemos jugar legalmente al Sonic si nos compramos una Nintendo 3DS! Si es así ¿Es moralmente correcto bajárselo de emuparadise, portalroms, romsmania, loveroms, ... y jugarlo? ¿No es más cómodo y seguro pagar los 20$ que valen los 9 juegos?

    ¿Y en el coche?

    ¡Podemos comprar el Golden Axe para PS4! Pero ¿como hago para enseñárselo a mis hijos en el coche de viaje o en la sala de espera del médico?

    ¿Como hago para que mis hijos sepan para que sirve un pollo de goma con una polea en el medio en una consola portátil?

    ¿Que es ser portátil?

    Para mi una consola portátil es aquella que te cabe en el bolsillo tal y como lo hace un móvil:

    • Por ejemplo la Nintendo DSi es una consola portátil.
    • La PSVita cabe en el bolsillo por un pelo pero también se pueden considerar portátil.
    • La Nintendo Switch NO es una consola portátil a pesar de no necesitar estar enchufada para funcionar. Es una consola estupenda y para algunos casos la mejor que existe pero no cabe en el bolsillo así que no esperes verla mencionar en esta serie.

    ¿Que nos sirve para jugar?

    Para mi es esencial la parte ergonómica de la consola y eso hace que un móvil con pantalla táctil me parezca una opción horrible. Si quieres destrozar un juego úsalo en tu móvil.

    Es necesario que al menos disponga de cruceta y 4 botones ya que son los que usan los juegos antiguos y es deseable que permita jugar a juegos más modernos.

    ¿Porqué con emuladores?

    En mi caso es crucial que todos los juegos funcionen sobre un emulador ya que nos permite guardar una instantánea de la partida para seguir a partir de ahí si nos matan.

    En los juegos de mi época cuando te mataban tenías que empezar desde el principio y eso es algo que cuando vas justo de tiempo no te puedes permitir.

    Consolas a comparar con los emuladores

    Voy a comparar las siguientes consolas:

    Se quedan fuera de la comparativa la GPD XD, Retromini, raspiboy, ... que tienen muy buena pinta pero hasta la fecha no he tenido contacto con ellas así que no puedo opinar para bien ni para mal.

    Puede que los resultados te sorprendan ya que no hay ninguna perfecta para todo aunque ya te adelanto que yo me decanto por la PSVita ya que cubre más casos de uso que el resto.

    Temas legales

    No queda del todo claro si utilizar emuladores bajándonos las roms es legal o no y tampoco queda claro si desbloquear una consola es legal o no.

    Desbloquear una consola consiste en ejecutar programas con los que en un principio el fabricante no contaba como por ejemplo una calculadora. Si bien es cierto que eso te permite utilizar backup de juegos y por lo tanto ser un pirata, tener una consola desbloqueada, siempre que sea para uso personal y no haya ánimo de lucro, no está perseguido.

    En caso de serlo habría que empezar por declarar ilegal el sistema operativo que más se utiliza para jugar a juegos piratas, piratearlos o se usó para entrenar a los pilotos que estrellaron los aviones contra las torres gemelas: Microsoft Windows.

    25 de July de 2018 a las 05:08

    08 de July de 2018

    Jose Manuel

    Retrogaming (I)

    En esta serie de post os voy a mostrar mis experiencias con casi toda la historia de los videojuegos desde las Game&Watch hasta la PSVita pasando por la PlayStation sin dejar de lado a Nintendo.

    Al final explicaré como conseguir las consolas necesarias, liberación de las mismas y todo lo que necesitas saber para sacarles todo el partido. Y por supuesto cual me parece la mejor para usarla de retroconsola.

    Limitaciones

    Solo una limitacion: debe poder jugarse en una consola portátil bien a traves de emulación o bien liberándola porque mi cantidad de tiempo para sentarse a jugar es extremadamente limitada pero si puedo hacerlo esperando al autobús.

    Muchos padres sabréis de lo que estoy hablando. Es lo que ocurre cuando pasas de tener poco dinero pero si tienes tiempo a tener poco tiempo pero si dinero.

    ¿Porqué?

    Tras leer Ready Player One quise:

    • entender que es lo que hace realmente bueno un juego: ¿Porqué antes nos pasabamos horas delante de una pantalla con gráficos pixelados mientras ahora tenemos en el store de nuestro móvil miles de juegos que desinstalamos al minuto? ¿Que es lo que hace realmente bueno a un juego?
    • vivir parte de la historia de los videojuegos que me había perdido: cuando mis compañeros hablan de ciertos juegos antiguos y no los conozco me siento como si hablaran de Optimus Prime y no supiera quien es.
    • enseñarle a mis hijos como se jugaba antes: los niños van a tener sobredosis de gráficos y efectos especiales pero a lo mejor esa no es la esencia que hace un juego bueno. Ahora nos tragamos cualquier cosa que pongan en el cine con buenos efectos especiales. ¿Es realmente lo mejor para ellos o tienen que aprender a valorar algo más?

    Un buen juego

    Para valorar la sensación que ofrece un juego yo tomo en cuenta los siguientes factores por orden de importancia:

    • jugabilidad
    • ergonomía
    • historia
    • estética
    • juega con amigos

    Jugabilidad

    Nos podemos pasar horas jugando al Candy Crush o al Tetris. Son juegos sencillos y que cualquier estudiante de informática puede programar despues del primer año de carrera.

    Son pura jugabilidad.

    Ergonomía

    Volviendo al Candy Crush y al Tetris, fíjate que antes triunfaba era el Tetris y ahora el Candy Crush. ¿Porqué?

    El Candy Crush parece estar diseñado para jugar en móviles y todos tenemos un móvil. Se puede jugar solo con un solo dedo.

    Para jugar al Tetris sin frustrarte necesitas botones para desplazamiento y giros. Si le das el Tetris a tu hijo en el móvil te va a durar un par de minutos. Dale el mismo juego en una GameBoy y le tendras enganchado horas.
    Yo y mi hijo podemos dar fe de ello.

    Los que dicen que con un teléfono móvil las videoconsolas no tienen sentido sencillamente no tienen ni idea de lo que están hablando. Intenta jugar sin dos Joysticks al Geometry Wars.

    Estética

    En el store de tu móvil tienes un monton de candy crushes pero en el apartado estético (explosiones, sonidos, desplazamientos, ...) el equipo de desarrollo ha hecho un gran trabajo. Ese factor es el diferencial en muchos juegos que pasan de ser "uno más" a ser auténticos éxitos.

    Historia

    Ya existían juegos parecidos a los Angry Birds. Una de las claves de su éxito ha sido la historia de los cerdos malos que se quieren comer los huevos. ¿Quien no va a querer ayudarles?

    Muchas veces he oído decir que es un juego sencillo que podía haber hecho cualquiera. Tu mismo podrías haber hecho el Apple Flinger.

    Si todavía no entiendes la diferencia juega un rato al Angry Birds y otro al Apple Flinger. Luego sigue leyendo.

    Juega con amigos

    Por ultimo, la posibilidad de jugar online compitiendo con tus amigos o con otros clanes es otro factor que hay que tomar en cuenta.

    Para mi es totalmente prescindible pero hay que reconocer que muchos juegos no tendrian el éxito que tienen si no fueran online, por ejemplo el World of Warcraft.

    AdjuntoTamaño
    Image icon Imagen de portada.3.81 MB
    Image icon Portada reducida175.44 KB

    08 de July de 2018 a las 07:02

    10 de March de 2018

    Jose Manuel

    Juego, Metaverso y Realidad Virtual (y III)

    VRMMOM

    Virtual Reality Masive Multiplayer Online Metaverse .

    Características deseables en un VRMMOM

    Un software para construir un VRMMOM debería:
    • permitir compartir y crear contenido
    • ser Sofware Libre para poder:
      • modificar y redistribuir las modificaciones
      • desplegar tantas copias de la plataforma como queramos
      • poder elegir si desplegar en infraestructura pública o privada
    • tener carácter distribuido:
      • legislación distribuida
      • tolerancia a fallos
    • ser infinitamente escalable
    • usar protocolos abiertos para ser interoperable
    • ...

    ¡Como internet!

    Un poco de historia

    El software sobre el que voy a hablar en los siguientes posts lleva gestándose unos 20 años y hay una persona que nos va a servir de hilo conductor. No es una idea peregrina que se le acaba de ocurrir a alguien.

    Todo empieza así: un adolescente sueña con una realidad virtual que no tenga las mismas limitaciones que tiene nuestro mundo material … pero es solo un adolescente. Su nombre es Philip Rosedale.

    Su trayectoria resumida en unas pocas líneas:

    • Con 17 años crea su propia compañía para vender sistemas de bases de datos y comienza a estudiar física, acabando la carrera años más tarde.
    • Con 26 años (1994) Rosedale empieza a aterrizar el sueño de crear mundos virtuales usando Internet.
    • Con 27 años (1995) crea FreeVue destinado a la reproducción de vídeos en streaming.
    • Con 28 años (1996) FreeVue se integra en RealNetworks y pasa a llamarse RealPlayer. Es nombrado CTO y Vicepresidente de la empresa.
    • Con 29 años (1997) Rosedale, ya con dinero en el bolsillo, deja RealNetworks.
    • Con 31 años (1999) se lanza a por su sueño:
      • funda Linden Lab dedicado a la creación de hardware háptico para su uso dentro de entornos de Realidad Virtual
      • pero lo abandona por un problema de patentes de hardware
    • Con 33 años (2001) de Philip renombran su metaverso de pruebas "Linden World" y lo llaman "Second Life".
    • Con 34 años (2002) de Philip Rosedale se saca la primera beta de SecondLife con 16 regiones.
    • Con 35 años (2003) de Philip se introduce la moneda, teletransportes, ... y se evoluciona el producto.
    • Con 38 años (2006) de Philip Linden Labs recibe un premio a la innovación y uno de sus primeros usuarios pasa a ser millonario gracias a SecondLife.
    • Con 39 años (2007) de Philip Linden Labs hace Open Source el cliente. La comunidad deduce a partir de él las especificaciones del protocolo y crea OpenSimulator.
      A partir de OpenSimulator nacen otras compañías y organizaciones donde el protocolo que usa Second Life pasará a ser el más extendido en internet para la creación de mundos virtuales interconectados ... pero centrémonos en Philip.
    • Con 40 años (2008) Philip anuncia su dimisión como CEO y pasa a ser Director de la empresa.
    • Con 41 años (2009) Philip ve que las cosas no van bien y deja la empresa que el mismo fundó.

    Una trayectoria bastante movida. Lo que pasó a continuación fue la gran caída de interés sobre este mercado al aparecer alternativas que encajaban mejor con las necesidades de los usuarios y el tema dejó de salir en los telediarios.

    El interés sigue ahí

    Sin embargo en el 2011 se publica "Ready Player One" claramente inspirado en Second Life resultando un éxito rotundo en ventas que ha llegado hasta nuestros días y del que Steven Spielberg ha sacado una película que ¡se estrena en solo 20 días!

    En realidad el interés siempre ha estado ahí pero la tecnología hardware nunca ha estado a la altura.

    La historia continúa

    Desde el 2009 hasta ahora han seguido pasando cosas y para mi la más relevante desde el punto de vista de software es que:

    • con 45 años (2013) y 4 hijos Rosedale comienza un nuevo proyecto:

    caché

    ¡High Fidelity cumple!

    High Fidelity cumple todas las características que debería cumplir un VRMMOM:

    • es software Libre
    • personalizable hasta el extremo
    • infinitamente escalable
    • distribuido

    En High Fidelity se solucionan los problemas de los que adolecen anteriores tecnologías, se incorporan los últimos avances en hardware háptico y de realidad virtual así como los últimos avances en tecnologías distribuidas como blockchain.

    En los próximos posts veremos donde encaja cada pieza en High Fidelity.

    ¡El futuro está llegando!

    ¿Te imaginas hacer teletrabajo de verdad? ¿o quedar con tus amigos sin moverte del sofá viéndoles sonreir y hacer bromas?
    ¡No queda mucho para eso!

    ¡Emociónate!

    caché

    10 de March de 2018 a las 07:50

    31 de January de 2018

    Jose Manuel

    Juego, Metaverso y Realidad Virtual (II)

    En la década de los 2000 hubo una explosión en el interés por estos campos que llevó a empresas como Linden Lab a tener gran relevancia a nivel mundial pero rondando el año 2008 el mercado se desplomó sobreviviendo los mejor posicionados.

    Han pasado 10 años y mientras tanto para muchos ha pasado desapercibido que ese desplome del mercado en realidad nunca ha existido sino que el mercado se ha diversificado.

    Esto es lo que hay

    En el caso de los metaversos Linden Labs se ha traducido en una caída de usuarios a unos 40000 diarios en Second Life, que ya los quisieran muchas empresas, a los que da servicio una empresa con más de 200 empleados. A esos usuarios hay que sumar el resto de usuarios de los más de 100 de grids basados en Opensim y otros grids basados en otras tecnologías que actualmente está creciendo de forma moderada.

    También ha habido un desplazamiento de los usuarios que buscaban jugar hacia juegos masivos en línea como World of Warcraft.

    Los usuarios que querían experiencias de realidad virtual han encontrado un hueco en visitas virtuales a otros lugares utilizando tecnologías como Google VR.

    Los usuarios para los que la comunicación simple con texto e imágenes desde cualquier dispositivo era suficiente (la mayoría) se han desplazado a las grandes redes sociales.

    Algo está pasando

    Pero ahora se están dando varios factores de forma simultánea:

    ¿Puede estar preparándose otro boom?

    31 de January de 2018 a las 06:24

    20 de January de 2018

    Jose Manuel

    Juego, Metaverso y Realidad Virtual (I)

    A cualquier persona que tenga ojos en la cara le ha tenido que llamar la atención la relevancia que poco a poco está ganando el mercado de la muchas veces mal llamada Realidad Virtual.

    Las cosas claras

    Como cada vez que comienza una nueva moda el sector comercial va a empezar a usar el término Realidad Virtual para vender su producto, aunque no tenga nada que ver con eso. Ha pasado con términos como cloud, dron, linux o robot y seguirá pasando en el futuro.

    Muchas veces confundimos o vemos en la misma frase los términos juego, realidad virtual y metaverso que, aunque puedan relacionarse, se refieren a cosas distintas.

    Un juego ...

    ... se define como la actividad que realiza uno o más jugadores, empleando su imaginación o herramientas para crear una situación con un *número determinado de reglas*, con el fin de proporcionar entretenimiento o diversión (en wikipedia).


    La realidad virtual ...

    ... es un *entorno de escenas u objetos de apariencia real* (en wikipedia).

    Los metaversos ...

    ... son *entornos donde los humanos interactúan* social y económicamente como iconos, a través de un soporte lógico en un ciberespacio, el que actúa como una metáfora del mundo real, pero sin las limitaciones físicas o económicas allí impuestas (en wikipedia).

    41 ejemplos metaversos en el 2008 (caché):

    Algunas diferencias

    Utilidad y objetivos

    En un juego existen unos objetivos marcados por el propio juego. Tu personaje dentro del juego sirve para algo porque tiene unos objetivos.

    Sin embargo en un metaverso abierto la pregunta no es ¿para qué sirve el entorno? sino ¿para qué sirves tú? Los creadores del metaverso no ponen los objetivos sino que los ponen sus usuarios.

    En el término Realidad Virtual la existencia de objetivos es irrelevante.

    Interacción con el entorno

    En un juego el usuario interacciona modificándolo a medida que avanza.

    En un metaverso el usuario también interacciona pudiendo crear o eliminar objetos.

    En un entorno de Realidad Virtual no es necesaria la interacción del usuario pudiendo limitarse a mirar a su alrededor haciendo una "visita virtual".

    Interacción con otros usuarios

    En un juego no es necesaria la interacción con otros jugadores. Eres solo tú, la máquina y la empresa que explotará tus datos si te has bajado el juego gratis dándole permiso para usar tu GPS, ver tus contactos, fotos, hacer llamadas y enviar SMS. ;-)

    En un metaverso el usuario necesariamente ha de estar conectado a una red a la que también están conectados otros usuarios.

    En un entorno de Realidad Virtual no es necesaria la interacción con otras personas.

    Inmersión sensorial en el entorno

    En un juego no es necesaria la inmersión sensorial. Se puede jugar mientras se mantiene una conversación con otra persona en el mundo real.

    En un metaverso tampoco es necesaria la inmersión sensorial. Se puede interaccionar sin desconectarse del mundo real.

    En un entorno de Realidad Virtual SI es necesaria la inmersión ya que se bloquean tus sentidos a las sensaciones del mundo real.

    Tiempo real

    En un juego no es necesaria una respuesta inmediata. Un juego se puede poner en pausa.

    En un metaverso el tiempo corre para todos por igual ya que es un entorno interconectado. Las cosas ocurren aunque nadie las vea.

    En un entorno de Realidad Virtual podemos descansar y volver en otro momento sin que nada haya cambiado.

    Problemas de rendimiento imprevisible

    Un juego es un entorno controlado en el que se puede tener una cierta certeza de su fluidez dado que podemos conseguir que los objetos y texturas entren en la memoria de la tarjeta de vídeo.

    En un metaverso tanto el número de avatares como el número de objetos y texturas diferentes que pueden existir en un mismo lugar son desconocidos por lo que nos enfrentamos a graves problemas de rendimiento.

    El entorno de Realidad Virtual es un entorno controlado.

    Persistencia

    Un juego puede volver a ser jugado tantas veces como se quiera sin tener en cuenta como fue el resultado anterior.

    En un metaverso el estado debe ser actualizado y persistido de forma indefinida para que tenga sentido.

    En un entorno de realidad virtual puede no ser necesario almacenar el estado.

    En resumen

    Juego Metaverso Realidad Virtual
    Utilidad y objetivos *
    Interacción con el entorno * *
    Interacción con otros usuarios *
    Inmersión sensorial *
    Tiempo real * *
    Problemas de rendimiento imprevisibles *

    Juego + Metaverso + Realidad Virtual = High Fidelity

    (caché)

    Is not a game!

    En otros posts explicaré detalles sobre esta plataforma.

    20 de January de 2018 a las 07:49

    31 de December de 2017

    david::

    As the world shows you their teeth and people hate you in slow motion, you look at her sleeping...

    As the world shows you their teeth and people hate you in slow motion, you look at her sleeping happily in your arms. Who knows what she is dreaming of right now. Supermassive red giants collapsing for millions of years so she can be here with you.

    How lucky is that.

    31 de December de 2017 a las 19:22

    24 de October de 2017

    Jose Manuel

    Sincronizar dos repositorios de git

    Sincronizar dos repositorios con todas sus ramas es fácil pero encontrarlo en Google es realmente difícil.

    Nosotros lo usamos en jobs de Jenkins para sincronizar los repositorios de nuestro gitlab con los del servidor de turno de git del cliente.

    Pasos:

    1. Crear un repositorio
    2. Agregar remote 1
    3. Agregar remote 2
    4. Bajar remote 1
    5. Bajar remote 2
    6. Subir remote 1
    7. Subir remote 2
    8. Subir remote 1

    Y en código

    git init repositorio
    git remote add origin https://git.server1.com/usuario/repositorio.git
    git remote add upstream https://git.server2.com/usuario/repositorio.git
    git fetch -a origin
    git fetch -a upstream
    git push upstream "refs/remotes/origin/*:refs/heads/*"
    git push origin "refs/remotes/origin/*:refs/heads/*"
    

    solución de conflictos

    Si da algún conflicto del tipo:

     ! [rejected]        origin/develop -> develop (non-fast-forward)
    error: failed to push some refs to 'https://git.server1.com/usuario/repositorio.git'
    consejo: Updates were rejected because a pushed branch tip is behind its remote
    consejo: counterpart. Check out this branch and integrate the remote changes
    consejo: (e.g. 'git pull ...') before pushing again.
    consejo: See the 'Note about fast-forwards' in 'git push --help' for details.
    

    Vas al repositorio que tu sepas más desactualizado, eliminas la rama que tenga el contenido más viejo y le das a actualizar o haces un merge manual y o bien reduces el tiempo de sincronización entre repositorios o bien usas solo uno de los dos.

    En mi caso el job de Jenkins se ejecuta cada minuto y no estamos teniendo conflictos.

    AdjuntoTamaño
    Image icon git_logo.png4.2 KB

    24 de October de 2017 a las 11:08

    10 de February de 2017

    david::

    T3chfest 2017

    https://drive.google.com/file/d/0B7W0kQVbSVoAbkdvaXVXNXdFUlU/view

    10 de February de 2017 a las 07:47

    14 de November de 2016

    david::

    Slides of my next talk at GUL UC3M

    14 de November de 2016 a las 17:15

    27 de June de 2016

    Jose Manuel

    Conectando dos puntos a 8 km de distancia

    Normalmente escribo para explicar cosas difíciles pero esta vez escribo para explicar algo extremadamente sencillo: tirar un "cable de red" entre dos puntos a 8 km de distancia a un coste irrisorio.

    Nunca había confiado en la tecnología wireless y como además necesitas hacer una inversión en un equipamiento que no sabes si va a funcionar, nunca me había atrevido antes. Pero como este verano tenía un poco de tiempo he pensado que si otros se lo gastan en copas yo me lo puedo gastar en formación jugando a la antena rusa.

    El resultado ha sido conseguir unir dos casas con visión directa en unas pocas horas con un "cable wireless".

    Lo que queremos

    Vamos a hacer que las dos casitas se vean como si estuvieran en la misma red. La casita de la derecha tendrá acceso a internet a través de la casita de la izquierda:

    Fundamentos de andar por casa

    Salvo que hayas estado viviendo en otro planeta los últimos 5 años, estarás familiarizado con la típica red wifi casera con un portátil (Station) conectado a un punto de acceso (Access Point) utilizando cifrado WPA2 Personal. Pues pon el punto de acceso (AP) en el foco de una antena parabólica, haz lo mismo con el portátil (Station) y aléjalos 1 kilómetro. Verás con sorpresa que sigue habiendo comunicación entre los dos.

    Además necesitaríamos un protocolo que retransmitiera entre antenas paquetes como los que se usan para el DHCP. Como si las antenas fueran dos switches conectados por un cable "wireless". Pues el protocolo existe y se llama WDS.

    Material que he usado

    Dos antenas parabólicas que incluyan la electrónica de red necesaria para hacer de Access Point y Station. Deben poder configurarse en modo bridge y soportar WDS. Mejor si funcionan a 5GHz por la sobreutilización de los 2.4GHz . Las Ubiquiti PowerBeam M5 cumplen esas características.

    También necesitaremos dos cables de red para unir el transformador con la antena ya que utiliza PoE (Power Over Ethernet) donde que se usan 2 pares para la red y otros dos pares para la alimentación.

    Montaje

    Lo primero, monta las antenas tal como pone en las instrucciones. La primera la monté yo y la segunda la montó mi hijo de 6 años así que no debe ser muy difícil.

    Ahora, por cada antena, conecta un cable de red a la antena y el otro extremo donde pone PoE. Si enchufas el transformador se deberían encender las lucecitas de la antena.

    Pon las antenas una frente a la otra a una cierta distancia. Puedes usar dos sillas, una en cada rincón de la habitación.

    Configuración

    Para la configuración he utilizado este enlace de ubiquity que describo a continuación.

    Para las dos antenas

    Entre el conector del transformador donde pone LAN y tu portátil conectas otro cable. Cuidado porque si te equivocas y conectas el portátil a donde pone PoE pasarán 24 voltios por la tarjeta de red, lo que hará que te empiece a oler a quemado y te quedes sin él.

    Ahora accede a la antena como diga el manual (probablemente poniendo una dirección IP en un navegador) y configura una IP libre del rango que vayas a usar. En el caso del ejemplo será la 192.168.1.2 para una antena y la 192.168.1.3 para la otra.

    Access Point

    Elige una de las antenas como Access Point y configúrala de esta forma:

    La configuración del "cable wireless" se hace en "Basic Wireless Settings" donde tendremos que poner:

    • Wireless Mode: Access Point
    • WDS: Activado
    • SSID: El SSID de la red wifi entre las dos antenas.

    Seguramente querremos cifrar la información que pasa por el "cable wireless" así que podemos configurar WPA2 Personal en "Wireless Security" tal como se ve en la imagen.

    Station

    La otra antena se configura en modo Station (como si fuera el portátil que se conecta al punto de acceso) de esta forma:

    Pruebas de conectividad

    Si lo has hecho todo bien, estando conectado a una antena deberías poder hacer ping a la otra. Si esto funciona ya está tirado el cable entre las dos antenas y solo queda "estirarlo".

    Orientar las antenas

    La orientación de las antenas es un tema bastante delicado porque con una pequeña desviación el invento no funcionará, pero gracias a los móviles que tenemos ahora se puede hacer de una forma bastante sencilla y precisa.

    Es extremadamente recomendable que haya dos personas, una en cada antena por si hay que reorientar. Yo lo hice solo y me funcionó a la primera pero reconozco que tuve mucha suerte.

    Pon la antena en el poste de forma que no se caiga pero permita ser movida para orientarla correctamente.

    Orientación horizontal.

    Necesitas un programa tipo OsmAnd donde marcarás como destino el lugar donde vaya a ubicarse la otra antena. Vuelve a la ubicación actual y te saldrá una flechita que te indicará hacia donde orientar la antena.

    Bloquea la rotación de la pantalla para que se quede siempre en vertical.

    Pon el móvil dentro de la parabólica, justo en el centro y tocándola como si fuera el pincho de la antena (Antenna Feed). Orienta la antena hacia donde indica la flecha.

    Orientación vertical.

    A ojo la hice yo y me funcionó bien. ;-)

    Pero si quieres hacerlo bien activa las curvas de nivel en el móvil, mira a que altura están los dos puntos que quieres unir y la distancia en línea recta. Restando las dos alturas vemos la diferencia de alturas, que es lo que nos interesa. Haz un eje de coordenadas y pon un puntito donde X será la distancia que separa los dos puntos e Y será la diferencia entre las dos alturas.

    Para averiguar el ángulo solo tienes que pasar esas coordenadas rectangulares a coordenadas polares (θ = atan( y / x )).

    Lo más importante es que si inclinas una antena 1 grado hacia arriba, inclines la otra 1 grado hacia abajo. Lo que subas en un extremo lo tienes que bajar en el otro si quieres que el invento funcione.

    Comprobación de la fuerza de la señal

    A la hora de orienar la antena podemos usar el programa que viene en la consola de gestión de la antena que nos dará una idea de la fuerza de la señal.

    La hora de la verdad

    Desde un extremo haz ping al otro y si funciona. ¡ya tienes el cable tirado!

    27 de June de 2016 a las 07:00

    08 de June de 2016

    david::

    Photo



    08 de June de 2016 a las 15:12

    25 de March de 2016

    david::

    On telegram and dependencies

    I’ve just committed two small, but quite interesting, changes to zoe-startup-kit.

    First, I’ve deprecated the tg bot in favour of rmed’s tgbot. It’s built on pyTelegramBotAPI, and works out of the box. Create your tg bot, paste the API key in etc/tgbot.conf and you’re done.

    Regarding python dependencies, zam made me think. Not only it install the desired agent, it also installs its dependencies in agents/xx/lib. It can, and should, be added to the launch script. Paste your code, paste your dependencies in a file, you’re done.

    Here you can find the tgbot agent. Notice the “pip-requirements.txt” file. Now, when it is first launched, its dependencies will be downloaded and added to sys.path automatically. Lovely.

    25 de March de 2016 a las 09:37

    10 de February de 2016

    david::

    Slides of my next #t3chfest 2016 talk

    10 de February de 2016 a las 23:58

    28 de September de 2015

    Jose Manuel

    Flash: ese virus de Linux

    En esta noche de insomnio he encendido el ordenador para aprovechar el tiempo y al arrancar el navegador el monitor de red registraba un tráfico de red de unos pocos kb/s cuando yo todavía no había abierto una página así que he hecho un "iftop -B -i wlan0" y me he encontrado una sorpresa.

    La sorpresa

    ¡Tráfico desde y hacia la IP 66.117.29.11!

    Investigando

    Me conecto al puerto 80 y me devuelve un bonito "The requested URL "/test" was not found on this server. That's all we know.". Hago un escaneo de puertos y tiene abierto también el 443. Misma respuesta.

    Apago el navegador, desactivo el plugin de flash y deja de haber tráfico. Ups, olvidé hacer un tcpdump para ver a que endpoint llegaba el tráfico.

    Buscando en internet

    He buscado la IP y parece que es de Adobe pero en virustotal pone que se resuelven dominios tan exóticos como nationalbankofcanada.tt.omtrdc.net y doy fe de que es así.

    Mirando en abine veo que el dominio es de una empresa que se dedica a vender datos de usuario.

    Conclusión

    Supongo que el plugin estaría actualizando mis datos en su base de datos de usuarios.

    No se en que momento el plugin de flash paso de ser algo serio a un virus pero no me extraña que haya bastantes empresas que lo rechacen frontalmente y que no funcione en algunos navegadores.

    Y así es como mi relación con el plugin de flash terminó un 28 de Septiembre de 2015 a las 6 de la mañana.

    28 de September de 2015 a las 05:00

    12 de February de 2015

    david::

    Slides of my next #t3chfest talk

    12 de February de 2015 a las 20:14

    Jose Manuel

    Redis Sentinel (parte 1)

    Redis es un gestor de bases de datos nosql clave-valor que por si mismo no funciona en alta disponibilidad. Para conseguir la alta disponibilidad se utiliza sentinel que ya viene con redis desde la versión 2.8.

    En este artículo indico como conseguir un redis en HA y como usarlo desde python ahorrándote unas horas de aprendizaje.

    Si no tienes conocimientos básicos de clustering tendrás que hacer un acto de fe cuando diga ciertas cosas como que necesitamos al menos tres servidores. No voy a explicarlo en este artículo.

    Como funciona

    Sistemas

    Redis se puede configurar en un conjunto de réplica con un primario y múltiples secundarios. El problema es que no tenemos failover, es decir, si se cae el redis primario todo el sistema deja de funcionar.

    Para solucionar el problema, en vez de dotar de failover al propio redis, se ha creado otro componente llamado sentinel que monitoriza a los redis y es capaz de reconfigurar el replicaset para volver a otro estado estable y avisar a los clientes en caso de caída de un nodo de la réplica.p>

    Salvando las distancias, es como si en mongodb tuviéramos 3 nodos árbitros y tres nodos de datos sin capacidad de votación. 6 procesos en total.

    Desarrollo

    Cuando te ofrecen un redis con un primario para hacer las escrituras y un secundario para lecturas asíncronas que seguramente pasarás de usar por si tiene datos desfasados, si se cae el primario tu programa dejará de funcionar.

    Para solucionar ese problema, en vez de acceder directamente al redis, accederemos a sentinel que nos dirá cual es el nodo primario de redis y una vez tengamos esa información ya podremos acceder al redis primario.

    Es solo agregar una línea más de código.

    Despliegue

    Necesitas tres servidores que llamaremos redis-01, redis-02 y redis-03.

    Por si no quieres montarlos te los puedes bajar de los tres enlaces anteriores. Son contenedores lxc comprimidos así que para usarlos instala lxc con un

    sudo apt-get install lxc
    los descomprimes en /var/lib/lxc/ y los arrancas con
    sudo lxc-start -n redis-01 -d
    sudo lxc-start -n redis-02 -d
    sudo lxc-start -n redis-03 -d
    
    Puedes conectarte con root/root a las direcciones 10.0.3.201, 10.0.3.202 y 10.0.3.203.

    Replica set

    Tras instalar redis, nos aseguramos de que en /etc/redis.conf escuche en todas las interfaces comentando la línea:

    bind_ip=127.0.0.1

    Elegimos uno de los tres como primario y configuramos el resto como esclavos con un:

    redis-cli
    slaveof 10.0.3.201 6379

    Tras hacerlo en los dos esclavos ejecutamos info en el maestro para comprobar que están replicando adecuadamente:

    redis-cli
    info

    Sentinel

    Viene junto con redis a partir de la versión 2.8 así que ya lo tendrás instalado sin saberlo.

    Lo único que hay decirle a los sentinel es la ip y puerto del primario en la replica set. Con eso sacará cuales son los demás nodos del replica set y los demás sentinel que se hayan conectado a ese maestro.

    En /etc/redis/redis-sentinel.conf de todos cambia esta línea

    sentinel monitor mymaster 127.0.0.1 6379 2
    Por esta otra
    sentinel monitor mymaster 10.0.3.201 6379 2
    Y ejecutar
    redis-sentinel /etc/redis/redis-sentinel.conf
    en los tres servidores.

    12 de February de 2015 a las 18:24

    09 de November de 2014

    david::

    Slides of my next tech FP talk at GUL UC3M

    09 de November de 2014 a las 13:31

    02 de November de 2014

    david::

    Introducing zoe.state

    Suppose that you arrive home and Zoe asks you if you want to hear some music. You answer “yes” and she triggers a playlist. This is really easy to do:

    1. Create an agent that detects your presence at home (pinging your phone is enough) and asks you if you want to hear some music
    2. Create a command “yes” that, when invoked, plays your favourite spotify playlist.

    Ok that was easy, let’s try something a little bit more difficult. Suppose you hate your neighbour and you are pretty sure that, eventually, you will want him killed. In fact it is not much harder:

    1. Create an agent that detects your anger (pretty easy) and asks you if you are angry because of your neighbour.
    2. Create a command “yes” that, when invoked, kills your neighbour. 

    Now, you see the problem, you arrive at home, you are so happy because you got a raise, and Zoe asks you if you want to hear some music. You answer yes. 

    Your favourite music starts playing and your neighbour dies. 

    This happens because fuzzy commands are not exclusive. This means that you can have two different scripts that are activated with the command “yes”. Zoe can’t tell wether you are answering the music question or wether you are deciding on your neighbour fatal destiny. 

    Correlating the “yes” command with your presence or anger would not be an optimal solution, because they are not exclusive: you can arrive at home angry and answer “yes” to the music question, and the killing bot would decide it’s a green light for him.

    The solution here is simple: do not create a command that kills people with a single “yes”. Make it triggered with something like “yes, kill my neighbour”.

    In any case, this example shows the underlying problem of managing state. Zoe is mostly a stateless machine (well, it depends on your agents). So, it would be great to have her some sense on your state. 

    The following picture shows some code I’m working on:

    image

    1. When zoe detects my presence, sends a “hello” message to this agent
    2. This agent offers me to hear some music and stores two commands, “yes /please” and “no /thanks”. Those commands are nothing but messages, in this case to the same agent.
    3. When I send her a “yes” or “no”, zoe sends the correct message to this agent.

    Pretty easy, isn’t it? There are two main advantages of this:

    1. Inherent to this design, you can implement full workflows with this. 
    2. Now, what would happen if two different agents are triggered at the same time, one of them asking about music and the other asking about killing your neighbour, you answer will be sent only to the agent that asked last.

    Now you can write at last your killer app.

    02 de November de 2014 a las 18:34

    25 de October de 2014

    david::

    Exact match in Zoe commands

    We have just added exact match commands in Zoe. This lets you match the input command against a regexp.

    When your command script is queried with –get, just return the regexp quoted in “/” and no \n at the end. That is, 

    echo -n “/your regexp here/”

    When the user asks for something that matches the regexp, your script will be invoked with the following options:

    If you are a sysadmin or a more-than-a-newby UNIX user, you will feel so comfortable with this. Have a taste of this exact match support in https://github.com/voiser/zoe-startup-kit/blob/master/cmdproc/regexp.sh

    25 de October de 2014 a las 10:10

    07 de September de 2014

    Jose Manuel

    Ubuntu 14.04 con el escritorio clásico

    Aburrido estarás ya de sitios en los que dicen que Ubuntu es la solución al hambre en el mundo. No lo es pero en este momento me parece la mejor distribución que hay para cualquier uso muy por encima del resto.

    Una de las cosas que me enerva hasta el punto de haberme pasado a KDE durante una temporada es Unity o el nuevo Gnome que viene en Ubuntu Gnome así que vamos a ver cómo cargárnoslos para poner un Gnome normal al que le funcione todo incluidos los efectos de escritorio.

    ¡32 bits por favor!

    Como cada dos años he vuelto a cometer el mismo error: instalar Ubuntu de 64 bits. Este año el escarmiento ha venido por haber intentado asistir a un webinar con webex y no poder hacerlo porque el javaleches que utilizaba sólo funcionaba bien con 32 bits.

    Con esto no digo que la de 64 bits vaya mal pero siempre hay alguna aplicación privativa que no te va a funcionar y necesitas que funcione.

    Es increíble que a estas alturas sigamos así pero "esto es lo que hay y nosotros no hemos sido". Advertido quedas.

    Ubuntu != Ubuntu Gnome

    Después de hacer todo lo que pongo abajo no quedará el mismo escritorio con uno que con otro empezando por el gestor de archivos que es distinto en uno o en otro, o la posibilidad de usar una segunda fila de escritorios que con Ubuntu Gnome se vuelve más engorrosa.

    Si todavía no has elegido mejor instala Ubuntu con Unity que tras los cambios te resultará más familiar.

    Instalando gnome sin efectos

    Instalamos los paquetes necesarios:

    sudo apt-get install gnome-session-flashback

    Cerramos y abrimos la sesión con Gnome Flashback (Metacity).

    Activando los efectos: empiezan los problemas

    Como te podrás imaginar para lo de arriba no me molesto en escribir una entrada. Los problemas vienen a partir de ahora cuando activamos los efectos porque deja de funcionar el Alt-Tab y no podemos elegir el número de escritorios.

    Activar drivers privativos

    Necesitamos que la tarjeta de vídeo funcione bien así que vamos a controladores adicionales:

    E instalamos los que nos toquen. En mi caso los de nvidia.

    Cuando acabes reinicia y arranca con Gnome Flashback (Compiz).

    Instalando gnome con efectos

    Primero instala los paquetes necesarios:

    sudo apt-get install compiz-plugins compiz-plugins-default compizconfig-settings-manager

    Arrancando CompizConfig Settings Manager

    Nos interesa el el Compiz Config Settings Manager así que ve a "Herramientas del sistema|Preferencias|CompizConfig Settings Manager"

    Configurando varios escritorios

    Pincha en "Opciones Generales":

    Ve a la pestaña de la derecha que pone "Tamaño de Escritorio". No se ve así que tienes que darle a la flecha de la derecha hasta que aparezca:

    En este punto puedes elegir el número de escritorios y su disposición en altura y longitud. Si has instalado Ubuntu Gnome sólo podrás moverte con Ctrl-Alt-Cursor de forma horizontal. Supongo que para moverte de forma vertical tendrás que configurar algo en algún sitio que no me he molestado en mirar.

    Configurando Alt-Tab para cambiar entre ventanas

    Vamos a "Gestión de ventanas|Cambiador de Aplicaciones" y lo activamos:

    En este punto ya funcionará el Alt-Tab pero se verá un poco feo así que vamos a ir a su configuración pinchando en su icono y desactivamos el check de "Icono".

    cerrar,minimizar,maximizar:menu

    Desde mi punto de vista los botones del marco de la ventana deberían estar a la izquierda en ese orden pero hay gente que los quiere más a lo Windows.

    Si has instalado Ubuntu Gnome los tienes a lo Windows y si es Ubuntu los tendrás a la izquierda.

    Para cambiarlos ejecuta dconf en cualquier terminal y ve a la clave "org|gnome|desktop|wm|preferences|button-layout" o dale a buscar button-layout y te saldrá directamente la clave que buscamos.

    Resultado de :close,minimize,maximize:menu":

    Resultado de minimize,maximize,close:":

    El álbum de hoy

    Nomoredolls - Nomoredolls (caché), un poco de rock para empezar la mañana:

    07 de September de 2014 a las 15:37

    28 de July de 2014

    Jose Manuel

    Introducción a ELK (Elasticsearch, Logstash y Kibana) (parte 3)

    En todas las aplicaciones que he conocido el cuello de botella siempre ha estado en el mismo sitio: el almacenamiento.

    Puedes poner 20 frontales web y 20 servidores de aplicación pero en la capa de persistencia tiene que haber un almacenamiento compartido que puede provocar verdaderos quebraderos de cabeza y muchas noches de insomnio al sysadmin de turno.

    Para entender la problemática vamos a ver que tiempos manejamos en un entorno típico con mysql y cómo escalamos con Elasticsearch. En los siguientes artículos de SQL vs NoSQL entraré más en el detalle. En este artículo sólo quiero que se entienda la problemática y cómo se podría "resolver" con Elasticsearch.

    Más rápido por favor

    Imaginémonos que usamos mysql en mi portátil manejando unos tiempos de 0.01 segundos por inserción:

    mysql> create table `tabla` (`id` varchar(5) NOT NULL, `data` varchar(5), primary key(`id`));
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> insert into `tabla` values ("1","2");
    Query OK, 1 row affected (0.01 sec)
    
    mysql> insert into `tabla` values ("2","2");
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into `tabla` values ("3","2");
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into `tabla` values ("4","2");
    Query OK, 1 row affected (0.02 sec)
    
    mysql> 
    

    Eso nos da una capacidad máxima de 100 inserciones por segundo que podrá parecer mucho pero ahora imagínate 10 servidores enviando líneas de log a razón de 10 por segundo de forma simultánea y verás como no te parece tanto.

    Con elasticsearch dentro de una máquina virtual con discos de portátil estoy sacando unas 300 inserciones por segundo. Está mejor pero también tenemos un techo.

    Soluciones SQL

    Usar el típico entorno de replicación de mysql no soluciona el problema porque tenemos más escrituras que lecturas. En todo caso lo empeoraría porque la base de datos estaría más tiempo ocupada enviando datos a sus réplicas.

    También podríamos tener varios servidores de mysql e ir enviando las líneas de log en roundrobin pero eso obligaría al software que va a explotar esos datos a hacer una gestión extra.

    Además, al utilizar SQL, el software que va a insertar y explotar esos datos está obligado a cambiar el esquema de la base de datos cada vez que haya un cambio de un campo en un archivo de log.

    Solución Elasticsearch

    Elasticsearch es un gestor de bases de datos NoSQL que para el caso que nos ocupa tiene tres ventajas:

    • Todos son maestros: En un grupo de replica (replica set) puedes insertar datos en cualquier servidor que ellos se las apañarán para replicarlos en los demás.
    • Inserción asíncrona: Se envían los datos a la base de datos y el servidor te da el OK antes de hacer la inserción real en la base de datos y replicarlo al resto. Esto reduce muuuuucho los tiempos de inserción aunque crea otros problemas de latencia que en este dominio nos dan exactamente igual.
    • Sin esquema: en una misma "tabla" puedes insertar "filas" con diferentes esquemas lo que posibilita poder insertar líneas de log desde diferentes orígenes. Pongo tabla y filas entre comillas porque ni las tablas se llaman tablas ni las filas se llaman filas, pero ya lo veremos en un artículo posterior.

    Solución escalable

    "Solucionando" cuellos de botella

    En esta solución utilizaremos un servidor de redis que es otro gestor NoSQL (¡sorpresa!) utilizado como catalizador para que el logstash que almacena los datos en elasticsearch no explote. Se usará como un gestor de colas donde los agentes irán metiendo líneas de log desde los servidores y logstash las irá recogiendo para insertarlas en la base de datos.

    De esta forma conseguimos:

    • Paliar el problema con el cuello de botella en la base de datos.
    • Monitorizar cuando nos vamos quedando sin capacidad mirando la longitud de la cola en redis. Por ejemplo haciendo un plugin de Zabbix que mire el tamaño de la cola de redis y nos devuelva un número que luego se podrá representar en una gráfica. Si el número supera un umbral. ¡alerta, necesitamos más capacidad!

    Visto en código suponiendo que tomamos los datos de un apache en el agente fíjate en el output:

    input {
      file {
        type => "auth"
        path => "/var/log/auth.log"
      }
    }
    filter {
      # This is a standard syslog line like this:
      # Mar  9 17:17:02 path-precise CRON[25638]: pam_unix(cron:session): session closed for user root
      if [type]=="auth" {
        # Look for patterns in /opt/logstash/patterns/grok-patterns
        grok {
          match => [ "message", "%{SYSLOGLINE}" ]
        }
        # Set timestamp: http://logstash.net/docs/1.4.1/filters/date#match
        date {
          match => [ "timestamp", "MMM dd HH:mm:ss",
                                  "MMM  d HH:mm:ss",
                                  "ISO8601" ]
        }
      }
    }
    output {
      redis {
        host => "localhost"
      }
    }
    
    Y en el servidor de logstash fíjate en input:
    input {
      redis {
        host => "localhost"
      }
    }
    output {
      elasticsearch_http {
        host => "127.0.0.1"
      }
    }
    

    Podríamos tener múltiples agentes disparando al mismo redis y de ahí viene la solución oficial:

    Hay que tener cuidado con redis porque para ganar velocidad almacena en memoria los datos así que en caso de dejar de funcionar el logstash o el elasticsearch durante un período de tiempo prolongado te puedes encontrar con un redis que ocupa en memoria 4GB. Si, también me ha pasado, ... hace una semana (nota mental: volver a poner 4GB de memoria al servidor de logstash ;-) ).

    Escalando horizontalmente

    La alarma que tenemos para la longitud de la cola de redis se dispara y en el kibana vemos datos de lo que pasó hace una hora. El problema puede estar en Logstash o en Elasticsearch así que vamos a crear otra máquina virtual con la pila completa de Redis, Logstash, Elasticsearch en cluster con el otro y un Kibana.

    ¡Cuidado! Para escalar realmente necesitaríamos tocar conceptos como el sharding que se tocarán en un artículo posterior. Aquí vamos a crear un conjunto de réplica entre dos servidores de Elasticsearch.

    ¿Has replicado ya el entorno anterior? ¿Y a qué estás esperando? Cuando tengas los dos servidores de Elasticsearch levantados en la misma red verás con sorpresa que ¡Ya están en el conjunto de réplica! Abre los kibanas de ambas instancias y verás como ves los mismos datos.

    Este fue el detonante que me impulsó a meterme en el mundo NoSQL. Yo que vengo de un mundo de almacenamientos compartidos, clusters RedHat, IPs flotantes, réplicas que no se recuperan automáticamente en caso de caída de un maestro ... y va este y se configura sólo con un doble click sin pedirle permiso al sistema operativo.

    Configuración de Elasticsearch

    Su configuración por defecto está escuchando a que alguien dentro del cluster "elasticsearch" se anuncie por multicast. Cuando eso ocurre los dos servidores se sincronizan y a partir de ahí los datos que insertas en un servidor están disponibles en el otro un segundo más tarde.

    La configuración más relevante que puedes encontrar en /etc/elasticsearch/elasticsearch.yml y que permite este comportamiento es la siguiente:

    cluster.name: elasticsearch
    discovery.zen.ping.multicast.enabled: true
    

    Con un rápido vistazo en el archivo de configuración podrás ver entre otras cosas que también puedes utilizar unicast para la configuración entre los nodos en caso de que estés usando una red que no permita usar multicast o servidores en la nube como por ejemplo dos instancias de Amazon EC2.

    Plugin para ver el estado del cluster en un navegador

    Con el plugin elasticsearch-head podemos ver el estado del cluster y gestionarlo desde un navegador.

    Solución a problemas que te acabarán ocurriendo

    Antes de nada ten presente que logstash crea una "base de datos", que en elasticsearch se llama indice, cada día. Supongo que hace esto para que el indice de logs no crezca hasta el infinito haciéndose inmanejable. Puedes ver los que ha ido creando en /var/lib/elasticsearch/elasticsearch/nodes/0/indices/.

    Too many open files

    Te pasará más o menos en el momento en que todo el mundo se haya acostumbrado a usar el kibana y se haya convertido en una aplicación crítica para la empresa pero no tengas sufiente experiencia para solucionar el problema rápidamente. Como será algo con lo que no contabas probablemente tampoco tengas tiempo para solucionarlo. Eso fue lo que me pasó a mi.

    La causa del problema es que cada vez que logstash crea un índice en elasticsearch éste crea y mantiene abiertos un porrón de archivos. En mi caso para el índice logstash-2014.07.08 tiene abiertos 62 archivos:

    root@path-precise:/etc/elasticsearch# lsof | grep /var/lib/elasticsearch/elasticsearch/nodes/0/indices/logstash-2014.06.26 | wc
         62     558   10582
    root@path-precise:/etc/elasticsearch# 
    

    Como además la configuración por defecto de elasticsearch crea tres shards el número de archivos abiertos se triplica. No voy a explicar esta afirmación. Veremos que es un shard en un artículo posterior.

    Llegar al límite de 1024 archivos, se llega bastante rápido así que deberás realizar estas tres cosas en el servidor:

    • Reducir el número de shards a 1: Si tu elasticsearch va sobrado de capacidad en el archivo de configuración de elasticsearch /etc/elasticsearch/elasticsearch.yml, sección Index, deja la siguiente configuración:
      index.number_of_shards: 1
      index.number_of_replicas: 0
      
    • Desactivar o eliminar los indices que no utilices: esto hará que la información de los mismos no esté accesible pero tampoco se abran los archivos que componen el indice:
      • Desactivar un indice:
        curl -XPOST 'localhost:9200/logstash-2014.06.26/_close'
      • Eliminar un indice:
        curl -XDELETE 'http://localhost:9200/logstash-2014.06.26/
    • Aumentar el límite de archivos abiertos en el /etc/security/limits.conf: se puede aumentar agregando las líneas:
      logstash  hard  nofile 32000
      logstash  soft  nofile 32000

    Se me ha llenado el disco y ahora elasticsearch no arranca

    No digo que me haya pasado, porque si me hubiera pasado significaría que no tenía bien monitorizada la máquina y que no me habría dado cuenta cuando ocurrió, pero en el hipotético caso de que me hubiera pasado, que no digo que me haya pasado, lo que hay que hacer es arreglar o borrar unos archivos de datos que se han corrompido.

    Elasticsearch, antes de insertar datos de verdad, los guarda en unos archivos de texto que usa como si fuera un buffer. El problema es que al estar el disco lleno esos archivos de texto se corrompen así que cuando Elasticsearch va a leerlos para indexar esos datos no puede hacerlo y se pega un tortazo.

    Una vez liberado el disco, el archivo que tienes que arreglar o borrar con la consecuente pérdida de datos está en el directorio translog del indice que de problemas. El log del elasticsearch te dirá cual está fallando. Por ejemplo, si te dice que el shard 0 del indice test está fallando vas a /var/lib/elasticsearch/elasticsearch/nodes/0/indices/test/0/translog y dentro verás que hay dos archivos, un translog-1405060275771 y otro translog-1405060275771.recovering. El que tienes que arreglar o borrar es el que se apellida .recovering .

    El álbum de hoy

    Shedneryan debe ser la obra que más he escuchado de Jamendo (caché). Ideal para trabajar:

    Espero que este artículo te haya servido de ayuda.

    28 de July de 2014 a las 05:53

    06 de July de 2014

    Jose Manuel

    ManiaDrive

    Maniadrive es un juego de coches de los que jugábamos cuando éramos pequeños. Me vino a la cabeza porque ahora tengo un hijo pequeño así que lo he sacado del cajón y empaquetado para vosotros.

    Se trata de un clon del conocido trackmania pero con licencia libre.

    Descripción

    Incluye un montón de pistas así que se puede jugar en modo historia.

    También puedes usar el modo multijugador por internet o crear tus propias pistas con el editor que viene integrado. Hice esta pista para que el niño aprendiera a usar su primer juego de coches:


    Si quieres usarla descarga el archivo en ~/.mania_drive/data y cárgala desde el editor.

    Paquete para Ubuntu

    He hecho un paquete a partir de los binarios que se pueden bajar desde sourceforge que configura el sonido a través de alsa-oss y añade las entradas "ManiaDrive" y "ManiaDrive track editor" en el apartado de juegos:

    Algunas imágenes del juego

    Espero que os guste:

    06 de July de 2014 a las 15:35

    26 de June de 2014

    Jose Manuel

    Introducción a ELK (Elasticsearch, Logstash y Kibana) (parte 2)

    Vamos a hacer algo útil con los datos que tenemos sin modificar mucho el ejemplo anterior. La salida, en vez de ir a un correo vamos a meterla en Elasticsearch para luego poder hacer consultas con Kibana.

    Hay multitud de tutoriales en internet así que no me voy a extender mucho en el cómo hacerlo sino en qué cosas puede hacer que funcione mejor en base a mi experiencia en los casi dos años que llevo usándolo.

    ¿Cómo funciona?

    El esquema será el que ilustra la imagen de la portada donde se ve el flujo de los datos.
    Esta imagen no refleja el cómo los datos viajan de un lado al otro y eso es lo que realmente hace falta entender así que ahí va la misma imagen ligeramente retocada:

    Como ves hay dos almacenes (log y elasticsearch) en los que están los datos que nos interesan y dos piezas de software (logstash y kibana) que hacen transformaciones con ellos y los mueven o los muestran como nosotros queremos.

    Logstash

    Si has seguido las instrucciones del artículo anterior ya lo tienes instalado.

    Para acceder a los logs que necesitamos es necesario que se ejecute como root así que ve a /etc/default/logstash y pon LS_USER=root.

    Dado que va a leer de los logs en este caso (aunque podría leer desde otro sitio) y escribir en elasticsearch necesitamos saber cómo son los logs de los que vamos a leer y cómo meter los datos en elasticsearch.

    read

    La primera parte es la más peliaguda porque cada aplicación tiene un log distinto pero hay un par de cosas que tendremos que tener en cuenta siempre:

    • Formato de la hora que usa la aplicación para escribir en el log
    • Datos que podemos querer consultar del log
    timestamp

    Me viene a la cabeza el log de squid donde la hora viene en el primer campo en segundos desde 01/Ene/1970 (fecha epoch) hasta la del apache donde viene en formato legible en el cuarto campo pasando por las de diversas aplicaciones que guardan el día y la hora en dos campos distintos separados por un pipe "|".

    Si queremos hacer una consulta del estilo "¿qué paso esta noche a las 3 de la madrugada?" necesitamos que logstash sea capaz de entender todos esos formatos de hora para poder insertarlos en la base de datos con el mismo timestamp.

    fields

    Pongamos por caso que tenemos el log de apache siguiente:

    127.0.0.1 - - [20/Jul/2013:08:16:58 +0200] "POST /my/machines HTTP/1.1" 404 443 "-" "-"

    Si utilizamos como separador de campo los espacios veremos que nos meterá la fecha en dos campos y eso no es lo que queremos. Tampoco podemos separar campos utilizando comillas porque no todos los campos tienen comillas así que hay que gestionar esto de una forma más inteligente.

    write

    En este caso concreto es bien fácil, ya que existe el output elasticsearch al que le indicamos donde está la base de datos y el resto lo gestiona él.

    Hay dos cosas a tener en cuenta:

    • Utilizar el plugin de elasticsearch con protocol => "http" para utilizar el API Rest de la base de datos. De esta forma ante una actualización de logstash o la base de datos, es menos probable que se rompa la aplicación.
    • logstash crea una base de datos diaria y realiza muchos accesos a disco lo cual, tras meses de uso, puede desembocar en problemas para el sistema operativo que se tratarán en la sección de elasticsearch.

    Ejemplo completo: SpyYourFriend

    Queremos poder responder a la siguiente pregunta: ¿cuando se eliminó el directorio /var/www/kibana del servidor y quien lo hizo?

    Vamos a utilizar como fuente de datos el .bash_history y el /var/log/auth.log.

    Pasos:

    • Configurar la bash para que agregue líneas en el history cada vez que se pulsa el enter y que ponga la fecha de cada comando en el log.
    • Configurar logstash para extraer los campos de cada log e insertar la información en la base de datos.
    Configurar la bash

    No me extiendo mucho. Simplemente agrega esto al .bashrc de root:

    export HISTTIMEFORMAT="%F %T "
    export PROMPT_COMMAND='history -a'
    

    Con esto dejaremos el timestamp de cada comando en /root/.bash_history y forzaremos a escribir en el history cada vez que tecleamos un comando en vez de al hacer logout.

    Configurar logstash para extraer datos de /var/log/auth.log

    Vamos a introducir la variable type que utilizaremos para "etiquetar" un flujo y poderle dar un trato diferencial a lo largo del archivo de configuración de logstash. A tener en cuenta:

    • Entrada: líneas del archivo en "/var/log/auth.log"
    • Proceso: extraer campos y configurar timestamp.
    • Salida: enviar todo a elasticsearch.
    input {
      file {
        type => "auth"
        path => "/var/log/auth.log"
      }
    }
    filter {
      # This is a standard syslog line like this:
      # Mar  9 17:17:02 path-precise CRON[25638]: pam_unix(cron:session): session closed for user root
      if [type]=="auth" {
        # Look for patterns in /opt/logstash/patterns/grok-patterns
        grok {
          match => [ "message", "%{SYSLOGLINE}" ]
        }
        # Set timestamp: http://logstash.net/docs/1.4.1/filters/date#match
        date {
          match => [ "timestamp", "MMM dd HH:mm:ss",
                                  "MMM  d HH:mm:ss",
                                  "ISO8601" ]
        }
      }
    }
    output {
      elasticsearch {
        protocol => "http"
        host => "localhost"
      }
    }
    

    Este es el ejemplo más sencillo que puede haber pero se puede complicar bastante. Pasemos al ejemplo siguiente.

    Configurar logstash para extraer datos del history

    El archivo de history tiene una pinta como esta:

    root@yinyan-precise:~# tail .bash_history 
    #1403070049
    history
    #1403070054
    ls
    #1403070056
    history
    #1403070062
    cd
    #1403070066
    more .bash_history 
    root@yinyan-precise:~#

    donde como se puede observar el timestamp está escrito en formato epoch precedido por un "#" y además el comando está en la siguiente línea. Esto último seguro que te recuerda al catalina.out del tomcat donde cada "línea" de log está compuesta de múltiples líneas.

    • Entrada: /root/.bash_history
    • Proceso:
      1. Juntamos las dos líneas en una sola eliminando '\n' y '#'
      2. Extraemos el campo de la fecha y el de la línea de comandos
      3. Utilizamos la fecha en formato epoch para poner valor al timestamp
      4. Agregamos un campo con la línea en formato más legible
    • Salida: Elasticsearch

    Agárrate que vienen curvas:

    input {
      file {
        type => "bash_history"
        path => "/root/.bash_history"
      }
    }
    filter {
      if [type]=="bash_history" {
        # Poner las dos líneas como una sola en el campo message
        multiline {
          pattern => "^#"
          what => "next"
        }
        # Cambiar fecha del principio
        # Vamos a separar los campos eliminando el retorno de carro y el comentario
        mutate {
          add_field => ["temp_message", "%{message}"]
        }
        mutate {
          gsub => [
            "temp_message", "\n", " ",
            "temp_message", "^#", ""
          ]
        }
        grok {
          match => [ "temp_message", "%{WORD:unix_date} %{GREEDYDATA:command_line}"]
        }
        mutate {
          remove_field => ["temp_message"]
        }
        # Copio el contenido del timestamp a otra variable para conservar el momento
        # en que el mensaje llegó al servidor de logstash
        mutate {
          add_field => [ "input_timestamp", "%{@timestamp}" ]
        }
        # Sobreescribo el timestamp con la fecha que pone en el archivo de log
        date {
          match => [ "unix_date", "UNIX"]
        }
        mutate {
          remove_field => ["unix_date"]
        }
        # Agrego un campo con la línea en formato legible
        mutate {
          add_field => [ "human_readable_message", "%{@timestamp} %{command_line}" ]
        }
      }
    }
    output {
      elasticsearch {
        protocol => "http"
        host => "localhost"
      }
    }
    
    Toda la configuración junta
    input {
      file {
        type => "auth"
        path => "/var/log/auth.log"
      }
      file {
        type => "bash_history"
        path => "/root/.bash_history"
      }
    }
    filter {
      # This is a standard syslog line like this:
      # Mar  9 17:17:02 path-precise CRON[25638]: pam_unix(cron:session): session closed for user root
      if [type]=="auth" {
        # Look for patterns in /opt/logstash/patterns/grok-patterns
        grok {
          match => [ "message", "%{SYSLOGLINE}" ]
        }
        # Set timestamp: http://logstash.net/docs/1.4.1/filters/date#match
        date {
          match => [ "timestamp", "MMM dd HH:mm:ss",
                                  "MMM  d HH:mm:ss",
                                  "ISO8601" ]
        }
      }
      if [type]=="bash_history" {
        # Example: "#1403708872\n tar -zxvf kibana-3.1.0.tar.gz "
        # This is a multiline log. Set message var with both lines.
        multiline {
          pattern => "^#"
          what => "next"
        }
        # Split fields. First field unix_date until first space. Second field command line after first space.
        # Use aux var temp_message.
        mutate {
          add_field => ["temp_message", "%{message}"]
        }
        # temp_message=="#1403708872\n tar -zxvf kibana-3.1.0.tar.gz "
        # Remove \n and #
        mutate {
          gsub => [
            "temp_message", "\n", " ",
            "temp_message", "^#", ""
          ]
        }
        # temp_message=="1403708872 tar -zxvf kibana-3.1.0.tar.gz "
        # Set unix_date and command_line
        grok {
          match => [ "temp_message", "%{WORD:unix_date} %{GREEDYDATA:command_line}"]
        }
        mutate {
          remove_field => ["temp_message"]
        }
        # unix_date=="1403708872"
        # command_line=="tar -zxvf kibana-3.1.0.tar.gz "
        # Set input_timestamp to the timestamp when the log line is processed by logstash
        mutate {
          add_field => [ "input_timestamp", "%{@timestamp}" ]
        }
        # Set timestamp and remove temporal var unix_date
        date {
          match => [ "unix_date", "UNIX"]
        }
        mutate {
          remove_field => ["unix_date"]
        }
        # Add a field with the log line in human readable format
        mutate {
          add_field => [ "human_readable_message", "%{@timestamp} %{command_line}" ]
        }
      }
    }
    output {
      elasticsearch {
        protocol => "http"
        host => "localhost"
      }
    }
    

    Elasticsearch

    Su instalación consiste en bajarse el paquete de aquí e instalarlo.

    En el siguiente post haré un monográfico de elasticsearch. De momento sólo diré que para enviar la información a la base de datos hay que poner esto en el output:

    output {
      elasticsearch {
        protocol => "http"
        host => "localhost"
      }
    }
    

    Kibana

    Yo lo defino como un visualizador gráfico de consultas lucene que sirve para hacer búsquedas que no sabes que vas a hacer hasta que las haces.

    Esto te da una enorme flexibilidad pero no te permitirá hacer unos buenos informes. El tema de los informes se tratará más adelante en el siguiente post.

    Instalación y ejecución

    En versiones anteriores Kibana era una aplicación Ruby que funcionaba sobre Sinatra en el servidor. Ahora es una aplicación que se ejecuta enteramente en el navegador, lo que significa que desde tu navegador hará falta acceso a la base de datos (se puede restringir).

    Bájate el kibana de aquí, lo descomprimes en /var/www/ y en config.js escribe la url que vas a poner en el navegador para acceder a tu servidor de elastisearch.

    SpyMyFriend en funcionamiento

    Si abrimos en el navegador la url donde hemos descomprimido el kibana y pinchamos en "here" veremos como tanto las líneas del auth que nos indican el momento y el origen de la conexión por ssh al servidor como los comandos que se han ido ejecutando han sido correctamente indexados.

    Hacer búsquedas es bastante sencillo ya que se usa la sintaxis de lucene así que no hay que saber acerca de cómo funciona la base de datos que hay detrás. Si queremos buscar cuando se ejecutó un rm basta con poner "rm" y lo buscará.

    Si pulsamos en el evento nos saldrá una descripción de los campos con sus valores, lo que nos dará una idea para hacer más búsquedas:


    Ahí vemos que la búsqueda "correcta" hubiera sido command_line:"*rm*"

    Ahora vamos a poner en verde las líneas del auth.log, en amarillo las del bash_history y en rojo la línea donde se ha borrado el kibana.

    Sigue habiendo mucho ruido. De las líneas del auth.log nos interesan las que nos indican una conexión por ssh:


    Al parecer tras hacer el estropicio quien sea se dejó la sesión abierta porque tras hacerlo no hay actividad en el auth.log de cierre de sesión ssh.

    Encontramos actividad de ssh en el auth a las 17:06 y que luego se han tecleado una serie de comandos. Ampliamos la parte que nos interesa:

    Ahora vamos a los eventos y vemos que alguien se conectó desde 127.0.0.1 y seguidamente estuvo trasteando con la instalación de kibana pero que luego la dejó bien. ¡Oh sorpresa! ¡He sido yo mismo!

    Anotaciones

    Este ejemplo, sobre todo la parte del bash_history, es bastante complicado pero si lo has entendido y lo has repetido en tu computadora te puedes considerar un usuario con experiencia de logstash y kibana.

    Existen otras alternativas a logstash como por ejemplo fluentd que también es bastante popular. Entiendo que una vez entiendas cómo funciona logstash podrás hacer extensible ese conocimiento al resto de alternativas tanto libres como privativas.

    Elasticsearch es un mundo en si mismo así que lo dejo para el siguiente post en el que intentaré hacer un "mapeo" entre SQL y NoSQL (mongodb y elasticsearch) ya que si nunca has usado una base de datos NoSQL pero eres un experto en SQL siento decirte que de NoSQL no tienes ni idea. Cambia tanto la filosofía a nivel de sistemas como a nivel de desarrollo.

    Espero que este post os ayude.

    26 de June de 2014 a las 07:23

    08 de June de 2014

    Jose Manuel

    Introducción a ELK (Elasticsearch, Logstash y Kibana) (parte 1)

    Se trata de un gestor de logs, o eso es al menos lo que nos venden.

    En realidad yo lo veo como algo mucho más genérico: una navaja suiza para gestión de datos que permite su transporte entre máquinas, procesamiento y consulta en tiempo real.

    En este artículo escribiré sobre logstash para en artículos posteriores hablar de su integración con Elasticsearch y Kibana.

    Cuando conozcas la potencia de ELK no sabrás como has sido capaz de vivir sin él hasta ahora.

    Ventajas aplicadas a archivos de log

    Con logstash no necesitas hacer una recolección de logs porque ya te la hace él, y tampoco necesitas hacer un tratamiento de los datos porque se le puede decir que te lo haga él o programarle una rutina que te actualice lo que sea en tiempo real. De esta forma en cualquier momento puedes saber lo que está pasando en tus sistemas y aplicaciones.

    Se puede usar tanto para procesar logs de apache como para procesar logs de aplicaciones internas o bases de datos por lo que puedes generar informes útiles tanto para la dirección como para ti o el equipo de desarrolladores. Por ejemplo, tal como viene "de fábrica" se le puede pedir un diagrama de barras con el número de peticiones que ha hecho un cliente a tu API agrupadas cada 5 minutos.

    Ahora imagínate que tienes un montón de instancias en Amazon que están constantemente creándose y destruyéndose en función de la carga pero quieres saber qué está pasando con ellas: cuando las creas configuras un logstash en ellas para que envíe los datos que te interesan a tu servidor de logs y problema solucionado. El accesorio perfecto para la descentralización de sistemas.

    Cómo funciona: el sistema de plugins/

    Pues como todos los programas: recibe unas entradas, las procesa y crea unas salidas. Sólo que es en sentido literal. Para ilustrarlo mira este dibujo:

    En él puedes ver lo que es logstash y en los plugins en los que que tienes que pensar cuando vas a diseñar un sistema con él: entradas, codecs/filtros y salidas.

    Una entrada es un plugin que utiliza logstash para extraer datos de algún sitio y pasársela al plugin de codec/filtro que devuelve otros datos y por último pasársela al plugin de salida.

    Intencionalmente he juntado los codecs y los filtros en el mismo saco porque aunque esto es incorrecto, me parece más didáctico. Más adelante lo aclararé.

    A estas alturas te habrás dado cuenta, y sino te lo digo yo, que lo realmente importante no es logstash sino sus plugins. En logstash todo gira alrededor de los plugins. Te puedes encontrar un listado abajo en la página de documentación.

    Instalación básica

    En este post me centraré más en mostrar cómo funciona logstash, no cómo se instala en producción así que ve a la página de http://logstash.net/docs/1.4.1/repositories, agrega el repositorio y ejecuta apt-get install logstash logstash-contrib. También hay paquetes para CentOS.

    Si no usas Debian ni CentOS puedes ir a http://logstash.net, pinchar en el botón gordo que pone "Download" y deja el archivo en algún sitio. Necesitarás java así que instálalo con un apt-get install default-jdk.

    Ejemplo de uso

    Vamos a suponer que en tu site hay una nueva página llamada /my/machines.html y quieres saber si la visita alguien así que haremos que cuando aparezca una entrada con ese texto en tu archivo de log, te llegue un mensaje al correo avisándote.

    Instala un apache en tu PC con un apt-get install apache2.

    Vamos a la página de documentación donde están los plugins disponibles y elegimos los que nos interesan:

    • plugin de entrada: file
    • plugin para filtro: grep
    • plugin de salida: email

    Pinchando en el plugin de entrada file podemos ver que para procesar los archivos de log que están en /var/log/apache2/*log debemos decirle algo como:

    input {
      file {
        path = ["/var/log/apache2/*log"]
      }
    }
    

    Pinchando en el plugin para filtro grep y teniendo en cuenta que una línea de log sería algo así:

    127.0.0.1 - - [20/Jul/2013:08:16:58 +0200] "POST /my/machines.html HTTP/1.1" 404 443 "-" "-"
    

    Tendríamos que configurarlo de esta forma:

    filter {
      grep {
        match = {"message", "/my/machines.html"}
      }
    }
    

    Y por último, pinchando en el plugin de salida email y suponiendo que utilizaremos una cuenta de correo de un proveedor externo para enviar los correos tenemos que poner como plugin de salida:

    output {
      email {
        subject => "Nueva visita"
        to => "direccion@gmail.com"
        from => "direccion@gmail.com"
        body => "%{message}"
        via => "smtp"
        options => [
          "smtpIporHost", "smtp.gmail.com",
          "port", "587",
          "enable_ssl", "true",
          "authenticationType", "plain",
          "userName", "cuentaDeEnvio",
          "password", "contrasenyaDeCuentaDeEnvio",
          "starttls", "true"
        ]
      }
    }
    

    Cada vez que ejecutemos esto:
    wget http://localhost/my/machines.html
    nos aparecerá en nuestro archivo de log el acceso a esa página, logstash lo verá y nos enviará un e-mail advirtiéndolo.

    Este ejemplo no es muy útil porque nadie quiere que le inunden el correo con líneas de log pero nos da una idea de lo que se puede hacer con los filtros y plugins.

    En marcha

    Si has seguido los pasos de arriba ya tienes instalado todo lo que necesitas así que vamos a ponerlo todo junto.

    Crea un archivo llamado /etc/logstash/conf.d/logstash.conf con el contenido:

    input {
      file {
        path => ["/var/log/apache2/*log"]
      }
    }
    filter {
      grep {
        match => {"message" => "/my/machines.html"}
      }
    }
    output {
      stdout {}
      email {
        subject => "Nueva visita"
        to => "direccion@gmail.com"
        from => "direccion@gmail.com"
        body => "%{message}"
        via => "smtp"
        options => [
          "smtpIporHost", "smtp.gmail.com",
          "port", "587",
          "enable_ssl", "true",
          "authenticationType", "plain",
          "userName", "cuentaDeEnvio",
          "password", "contrasenyaDeCuentaDeEnvio",
          "starttls", "true"
        ]
      }
    }
    

    Advertencias en producción

    Esto es sólo un ejemplo muy didáctico para ver cómo funciona el sistema de plugins en Logstash: entrada, procesado y salida. Así que me he permitido introducir un par de incorrecciones.

    El filtro grep no se usa

    La forma correcta sería con el input que he descrito, sin filter y metiendo dentro del output una condición para que se envíe el e-mail cuando la línea la cumpla. Más adelante lo aclararé.

    Cuando encuentra un error muchas veces Logstash se para

    En el ejemplo utilizamos como salida el smtp de gmail y esto es una mala idea porque en caso de estar inaccesible mientras Logstash intenta enviar un e-mail, nos devolverá un error y se parará. Si mientras nos damos cuenta de que está parado se rotan los logs habremos "perdido" todo el procesamiento de esa información que está entre la parada y el momento de rotar los logs.

    Con esto quiero decir que es siempre mejor tener un relay de correo en local configurado para reenviar los correos al relay de tu red o a tu proveedor externo.

    08 de June de 2014 a las 07:53

    06 de May de 2014

    david::

    Zoe controlling my TV (thanks to this)



    Zoe controlling my TV (thanks to this)

    06 de May de 2014 a las 10:59

    03 de May de 2014

    Jose Manuel

    Google Code Jam 2014 ... con obstáculos - Round 1A, 1B y fin

    El comentario de anonimo en mi post anterior me ha descubierto una cosa que no conocía: la Programación Competitiva. Yo pensaba que esto era un invento de Google pero resulta que ya estaba inventado. Un gran aporte. Muchas gracias.

    Le he estado dando bastantes vueltas y he decidido mantener mi mente "virgen" porque lo que me interesa es saber hasta donde puedo llegar con mis limitaciones actuales, no preparame para ganar un concurso. El año que viene ya veremos si opino lo mismo.

    Round 1A

    Gracias a un "papá miedo" tuve la "suerte" de despertarme a las 3 de la mañana así que aproveché para ver los tres problemas y hacerme una idea de la dificultad. Vi asequibles tanto el "Problem A. Charging Chaos" como el "Problem B. Full Binary Tree" pero el "Problem C. Proper Shuffle" era más difícil.

    Al día siguiente vi que el corte estaba en hacer los dos primeros problemas sin cometer equivocaciones así que tomé nota para la siguiente.

    Round 1B

    Tras haber solicitado el correspondiente permiso marital para poder pasar la tarde frente al ordenador empiezo por el primer problema.

    Problem A. The Repeater

    Lo que nos piden

    En el primer problema nos piden cual es el número mínimo de pasos necesarios para igualar varias cadenas de texto cadenas de texto siguiendo dos reglas:

    • Si hay dos caracteres consecutivos iguales se puede eliminar uno de los dos.
    • Si hay un caracter se puede duplicar.

    Por ejemplo, si tenemos la cadena "aaabcc" y queremos llegar a "abbbcc" tenemos que pasar por "aabcc", "abcc" y "abbcc". ¿Fácil no?

    Aquí tenemos unos ejemplos del concurso:

    • Caso 1: Cadenas:
      • mmaw
      • maw
      Solución: Case #1: 1
    • Caso 2: Cadenas:
      • gcj
      • cj
      Solución: Case #2: Fegla Won
    • Caso 3: Cadenas:
      • aaabbb
      • ab
      • aabb
      Solución: Case #3: 4
    • Caso 4: Cadenas:
      • abc
      • abc
      Solución: Case #4: 0
    • Caso 5: Cadenas:
      • aabc
      • abbc
      • abcc
      Solución: Case #5: 3

    La solución

    La solución consiste en primero comprobar si el problema tiene solución y en caso de tenerla averiguar cuantos pasos son necesarios para llegar desde una cadena a la otra. Si has hecho este problema probablemente esto te sonará un poco raro pero me explicaré más adelante.

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import sys
    import time
     
    def getValue(inputFile,dataType="string"):
      line=""
      value=0
      while len(line) 1:
        line=inputFile.readline()
     
      if dataType=="string":
        value=line.split()[0]
      elif dataType=="integer":
        value=int(line.split()[0])
      elif dataType=="float":
        value=float(line.split()[0])
     
      return value
     
    def reducedCase(case):
      char=""
      reduced=""
    
      i=0
      while i len(case):
        if not(char==case[i]):
          char=case[i]
          reduced=reduced+char
        i=i+1
    
      return reduced
    
    def testPossible(cases):
      # For each case test if removing duplicates make them the same
      reduced=reducedCase(cases[0][0])
      possible=1
      i=1
      while i len(cases) and possible==1:
        if not(reduced==reducedCase(cases[i][0])):
          possible=0
        i=i+1
      return possible
    
    def convert(case1, case2):
      # Try to find the number of steps to translate case1 to case2
      steps=0
    
      diff=0
      i=0
      j=0
      char=case1[0]
      while i len(case1) and j len(case2):
        found=0
        while i len(case1) and found==0:
          if char==case1[i]:
            i=i+1
          else: 
            found=1
        found=0
        while j len(case2) and found==0:
          if char==case2[j]:
            j=j+1
          else:
            found=1
        steps=steps+abs(i-j-diff)
        diff=abs(i-j)
    
        if i len(case1):
          char=case1[i]
      return steps
       
    ### solve it! ###
    def solveIt(cases):
      res=1
    
      # Reducir duplicados en todos y comprobar que sale la misma cadena para ver si
      # es posible resolverlo
      possible=testPossible(cases)
      if possible==1:
        i=1
        while i len(cases):
          #Elegir uno como plantilla e igualar el resto.
          steps=convert(cases[0][0],cases[i][0])
          cases[i][1]=steps
          i=i+1
    
        res=0
        for case in cases:
          if case[1]>res:
            res=case[1]
      else:
        res=-1
     
      return res
     
    if __name__=='__main__':
      # Open input and output files
      inputFile=open(sys.argv[1],'r')
      outputFile=open(sys.argv[2],'w')
     
      # Get number of cases
      NoC=int(getValue(inputFile))
      # for each case
      for i in range(NoC):
        # get case data
        inputs=getValue(inputFile,"integer")
        cases=[]
        while inputs>0:
          case=getValue(inputFile,"string")
          cases.append([case,-1])
          inputs=inputs-1
        # solve problem
        res=solveIt(cases)
     
        # write data
        if res==-1:
          outputFile.write("Case #"+str(i+1)+": Fegla Won\n")
          print "Case #"+str(i+1)+": Fegla Won"
        else:
          outputFile.write("Case #"+str(i+1)+": "+str(res)+"\n")
          print "Case #"+str(i+1)+": "+str(res)
     
      # Close input and output files
      inputFile.close()
      outputFile.close()
    

    Resultados

    En el ejemplo que viene la entrada es:

    5
    2
    mmaw
    maw
    2
    gcj
    cj
    3
    aaabbb
    ab
    aabb
    2
    abc
    abc
    3
    aabc
    abbc
    abcc
    

    Y la salida correcta es:

    Case #1: 1
    Case #2: Fegla Won
    Case #3: 4
    Case #4: 0
    Case #5: 3

    Sin embargo a mi me sale mal el último resultado y me empiezo a poner nervioso:

    Case #1: 1
    Case #2: Fegla Won
    Case #3: 4
    Case #4: 0
    Case #5: 2
    

    19:45

    "La cagamos Luis"

    ... dijo Carlos Sainz cuando se enteró de que su motor llevaba estando defectuoso desde la salida.

    Resuelvo el problema que he descrito pero no el que me piden y a estas horas ya no me da tiempo a rectificar.

    Para resolver el problema hay que tener en cuenta todas las cadenas simultáneamente y yo las he tenido en cuenta de una en una

    En el último caso yo obtengo como resultado 2 porque aabc->abc->abbc y aabc->abc->abcc . Así que como mucho necesito dos pasos pero lo que en realidad hay que hacer entiendo es pasar a la vez todas las cadenas a una sóla de esta forma:

    ["aabc","abbc"]->["abc","abbc"]->["abc","abc"]->["abcc","abcc"]
    Y de ahí salen los tres pasos.

    No tengo tiempo para volver a rediseñar el programa así que se acabó esta ronda para mí.

    ¿Round 1C?

    "En habiendo agotado" todos los permisos maritales que tenía para el Google Code Jam, me tengo que retirar de esta convocatoria así que ya veremos el año que viene si aprendo a leer.

    Creo que me tendré que conformar con presentarme al Tuenti Challenge 4 y acabar mi curso de mongodb para desarrolladores y mi curso de mongodb para administradores avanzados.

    03 de May de 2014 a las 18:41

    23 de April de 2014

    david::

    I'll make my own Zoe. With blackjack. And hookers.

    I’m working in a reduced distribution of Zoe with the basic components, so you can build your own assistant with the basic services running out of the box. So you don’t have to clone our installation and trim all the services you don’t care about.

    It includes the basic agents (natural, broadcast, users, log, relay), some natural language commands, the communication agents (mail, jabber, twitter) and some example agents.

    In order to make it easier to add new agents, the server has been updated to feature dynamic agent registration, which means that instead of registering your agent in a configuration file, you can send a message to the server with the agent parameters (name, host, port and optionally a list of topics it listens to). This message is automatically generated by the Python library zoe.deco, which I think is the best option to start writing agents.

    By the way, the server’s source code has been updated to make use of Akka instead of scala.actor, and to have a cleaner and more functional style. I’m still a complete newbie at FP so I beg you to forgive me if the code does not reach the pure functional meta-existentialist beauty standards :P

    As soon as it is tested in Linux and OS X I’ll drop the code to a new Github repo.

    23 de April de 2014 a las 19:50

    13 de April de 2014

    Jose Manuel

    Google Code Jam 2014 ... con obstáculos - Qualification Round

    Preparando el concurso

    Dado que la entrada y salida de datos es siempre exactamente igual he hecho una plantilla que usaré en todos los retos:

    #!/usr/bin/python
    # -*- coding: utf-8 -*- 
    import sys
    import time
    
    def getValue(inputFile,dataType="string"):
      line=""
      value=0
      while len(line) 1:
        line=inputFile.readline()
    
      if dataType=="string":
        value=line.split()[0]
      elif dataType=="integer":
        value=int(line.split()[0])
      elif dataType=="float":
        value=float(line.split()[0])
    
      return value
    
    def getList(inputFile,dataType="string",separator="space"):
      # dataType could be string, integer and float
      # separator can be space or none
      list=[]
      
      line=""
      while len(line) 1:
        line=inputFile.readline()
    
        if  separator=="space":
          list=line.split()
        elif separator=="none":
          line=line.rstrip('\n')
          for i in range(len(line)):
            list.append(line[i])
    
    
      #if dataType=="string": ... already a string
      if dataType=="integer":
        i=0
        while (i len(list)):
          list[i]=int(list[i])
          i=i+1
      elif dataType=="float":
        i=0
        while (i len(list)):
          list[i]=float(list[i])
          i=i+1
      return list
    
    def getBoard(inputFile,dimX,dimY,dataType="string",separator="none"):
      line=""
      board=[]
     
      for y in range(dimY):
          board.append(getList(inputFile,dataType,separator))
     
      return board
    
    def printBoard(board,array="0"):
      #print board
      for i in range(len(board)):
        for j in range(len(board[i])):
          if array=="1":
            sys.stdout.write("[\""+str(board[i][j])+"\"]")
          else:
            sys.stdout.write(str(board[i][j]))
            
        print ""
      
    ### solve it! ###
    def solveIt(inputs, values,board):
    #  time.sleep(1)
    #  print ""
    #  print inputs
    #  print values
    #  print board
    
      res=[]
      i=0
      j=1
    
      res.append(i)
      res.append(j)
    
      return res
    
    if __name__=='__main__':
      # Open input and output files
      inputFile=open(sys.argv[1],'r')
      outputFile=open(sys.argv[2],'w')
    
      # Get number of cases
      NoC=int(getValue(inputFile))
    
      # for each case
      for i in range(NoC):
        # get case data
        inputs=getValue(inputFile,"integer")
        values=getList(inputFile,"integer")
        board=getBoard(inputFile,"integer")
        # solve problem
        res=solveIt(inputs, values, board)
    
        # write data    
        outputFile.write("Case #"+str(i+1)+": "+str(res[0]+1)+" "+str(res[1]+1)+"\n")
    #    print "Case #"+str(i+1)+": "+str(res[0]+1)+" "+str(res[1]+1)
    
      # Close input and output files
      inputFile.close()
      outputFile.close()
    

    Y pensarás ¿no puedes hacer eso el día del concurso? Pues no porque tengo los minutos contados. 10 minutos pueden suponer la diferencia entre que de tiempo a resolver un problema o no.

    Insomnio provocado

    4:00

    Aprovecho una subida de fiebre del niño para despertarme del todo y valorar la dificultad de los problemas.

    Esta vez me voy directo al "Contest scoreboard" donde veo que los mejores tardan 15 minutos en resolver el primero, otros 15 el segundo y alrededor de una hora el tercero y el cuarto así que supongo que los fáciles son el primero y el segundo.

    Tras leer el primero, parece más una broma que un problema. El segundo también parece fácil pero necesita de una lectura más profunda del problema y con menos sueño.

    Mañana será otro día. Bueno, hoy dentro de un rato será otro día.

    Problem A. Magic Trick

    7:30

    Este problema es facilísimo. Nos dan dos arrays distintos en los que los números cambian de posición y nos piden que busquemos los números de una fila del primer array en otra fila del segundo array.

    • Si se encuentran 2 -> Case #x: Bad magician!
    • Si no se encuentran -> Volunteer cheated!
    • Si se encuentra 1 -> Case #x: x
    8:40

    Tras un "tengo pis" y un "dale el antibiótico al niño" la solución, utilizando la plantilla como librería es la siguiente contenida en la función solveIt:

    #!/usr/bin/python
    # -*- coding: utf-8 -*- 
    import time
    import sys 
    import gcjtemplate
    
    ### solve it! ###
    def solveIt(row1,board1,row2,board2):
      res=[]
      for i in board2[row2-1]:
        if i in board1[row1-1]:
          res.append(i)
    
      return res
    
    if __name__=='__main__':
      # Open input and output files
      inputFile=open(sys.argv[1],'r')
      outputFile=open(sys.argv[2],'w')
    
      # Get number of cases
      NoC=int(gcjtemplate.getValue(inputFile))
    
      # for each case
      for i in range(NoC):
        # get case data
        row1=gcjtemplate.getValue(inputFile,"integer")
        board1=gcjtemplate.getBoard(inputFile,4,4,"integer","space")
        row2=gcjtemplate.getValue(inputFile,"integer")
        board2=gcjtemplate.getBoard(inputFile,4,4,"integer","space")
        # solve problem
        res=solveIt(row1, board1, row2, board2)
    
        # write data    
        if len(res)==0:
          outputFile.write("Case #"+str(i+1)+": Volunteer cheated!\n")
          print ("Case #"+str(i+1)+": Volunteer cheated!")
        elif len(res)==1:
          outputFile.write("Case #"+str(i+1)+": "+str(res[0])+"\n")
          print ("Case #"+str(i+1)+": "+str(res[0]))
        elif len(res)>1:
          outputFile.write("Case #"+str(i+1)+": Bad magician!\n")
          print ("Case #"+str(i+1)+": Bad magician!")
        else:
          time.sleep(5)
          print "HELP, HELP!"
    
      # Close input and output files
      inputFile.close()
      outputFile.close()
    

    Problem B. Cookie Clicker Alpha

    8:45

    En este problema la dificultad está más en comprenderlo que en resolverlo.

    Tu objetivo es llegar a tener un número de galletas en el menor tiempo posible. Empiezas con una fábrica de galletas y que te ha costado x galletas. Cuando llegas a esas x galletas puedes elegir entre comprar una fábrica para doblar la capacidad de producción o seguir produciendo como hasta ahora.

    Se trata de elegir la mejor estrategia para decir cual es el menor número de segundos que se tarda en llegar a conseguir el número de galletas que queremos.

    Hay que tener en cuenta que nos dan unos límites que, aunque en python nos dan igual, en otros lenguajes nos vienen bien para elegir el tipo de datos.

    9:09

    Se levanta la tropa, les llevo al parque, reunión familiar, comilona, ...

    23:43

    Estoy a 1:15 de decidir si paso a la siguiente fase o no. En teoría es factible pero no me gusta ir tan corto de tiempo.

    00:35

    El que nos den 8 minutos para entregar el resultado de nuestro programa en vez de los 4 habituales es un indicador de que puede ser bastante costoso en términos computacionales.

    Este problema es de naturaleza recursiva ya que para decidir entre comprar o no comprar otra fábrica de galletas hay que saber qué es lo que pasaría si no se comprara otra o qué pasaría si se comprara otra, en cuyo caso habría que volver a saber qué es lo que pasaría si no se comprara otra o qué pasaría si se comprara otra, ... hasta que viéramos que deja de salir a cuenta comprar otra fábrica.

    Sin embargo el problema se puede enfocar desde un punto de vista más lineal si pensamos en qué vamos a basar la decisión final: si con la capacidad de producción que tengo ahora tardo menos en producir las galletas que aumentando la producción en una fábrica más es que no debo comprar más fábricas.

    Ignorando el resto de la plantilla que he puesto arriba del todo, la solución es la siguiente:

    ### solve it! ###
    def solveIt(c,f,x):
      res=0.0
    
      speed=2
      cookies=0.0
      spentSeconds=0
    
      finish=0
      while finish==0:
        withoutMoreFarms=x/speed
    
        secondsToBuyFarm=c/speed
        newSpeed=speed+f
        withOneMoreFarm=secondsToBuyFarm+x/newSpeed
    
        if withOneMoreFarm withoutMoreFarms:
          spentSeconds=spentSeconds+secondsToBuyFarm
          speed=newSpeed
        else:
          spentSeconds=spentSeconds+withoutMoreFarms
          finish=1
        
    #    print "spentSeconds: "+str(spentSeconds)
    
      res=spentSeconds
      return res
    
    if __name__=='__main__':
      # Open input and output files
      inputFile=open(sys.argv[1],'r')
      outputFile=open(sys.argv[2],'w')
    
      # Get number of cases
      NoC=int(getValue(inputFile))
    
      # for each case
      for i in range(NoC):
        # get case data
        c,f,x=getList(inputFile,"float")
        # solve problem
        res=solveIt(c,f,x)
    
        # write data    
        outputFile.write("Case #"+str(i+1)+": "+str(round(res,7))+"\n")
        #print "Case #"+str(i+1)+": "+str(round(res,7))
    
      # Close input and output files
      inputFile.close()
      outputFile.close()
    

    Una vez enviada la respuesta al Large Set te indican que:
    You have already tried this input set. (Judged at the end of the contest.)
    Así que no hay forma de saber si ya tengo los 25 puntos que necesito o no.

    ¿Mas?

    1:00

    Pues va a ser que a estas horas lo que me apetece es dormir. Mañana publicaré este post y el resultado del concurso.

    9:20

    ¡He pasado!

    Lo que no entiendo muy bien es cómo puede haber gente que lo haya hecho peor todavía que yo y haber pasado también, pero ahí están los resultados.

    Para la próxima a mirar la librería multiprocessing que me hará falta para utilizar todos los cores de mi máquina.

    13 de April de 2014 a las 07:35

    17 de December de 2013

    Ana

    Voy a comprar pasta de dientes sin flúor

    Me he quedado flipando, pero resulta que el flúor es tóxico y provoca caries O_o

    Lo usaban los alemanes en la II Guerra Mundial para controlar a la población O_O
    Y España fluorando el agua.

    Dos extractillos y enlace a la noticia, por si queréis echarle un vistazo (y si alguien sabe algo sobre si es verdad o mentira, que lo diga, porfa).

    http://r-evolucion.es/2013/09/03/espana-fomenta-la-fluoracion-del-agua-y-el-mundo-la-prohibe/

    "se comprobó que la fluoración causó ligeros daños a una parte específica del cerebro, haciendo más difícil para la persona afectada defendiera su libertad y causando que la persona llegue a ser más dócil a la autoridad. El flúor sigue siendo una de las más fuertes substancias anti-psicóticas conocidas, y está contenida en un 25% de los mayores tranquilizantes"

    "Durante la década de los años ´90, la investigación realizada por la toxicóloga Dra. Phillis Mullenix de Harvard demostró que el flúor en el agua puede llevar a un menor coeficiente intelectual, y los síntomas producidos en ratas se parecían fuertemente al déficit de atención e hiperactividad (SDAH)"

    17 de December de 2013 a las 14:25

    15 de August de 2013

    Ana

    ¡Software libre en la uni! II

    No sé qué os parecerá a vosotros, pero a mí me ha sorprendido:

    http://www.uc3m.es/portal/page/portal/cultura_y_deporte/espacio_abierto/cursos/sw_libre

    Taller de Diseño Gráfico con Software Libre

    Desde luego es una buena opción para aprender, para enseñar y para manejarse después, aunque algunas personas crean que el software privativo tiene que ser mejor "porque si no no habría gente que paga por él".

    Me parece una buena iniciativa. Aunque a lo mejor hace competencia a los cursos del GUL :p

    15 de August de 2013 a las 21:38

    11 de October de 2012

    Fernando Cerezal

    Elecciones a delegados en la universidad

    Llegan este año las elecciones a delegados. Parece que nos han escuchado de años anteriores y ahora aparece un anuncio en aula global y se mandan correos sobre el tema.

    Este año vuelvo a presentarme, al igual que los dos anteriores. Este año hemos conseguido que se cambien algunos profesores, y se han dado toques de atención a algunos departamentos. Poco a poco, vamos consiguiendo que las cosas cambien. Aún hay muchas cosas en las que trabajar, y es necesario poder expresar de una forma responsable y sin miedo los problemas que existen, tanto directamente a los profesores como a las instancias superiores que sean necesarias. Si bien parece que los alumnos estamos en desventaja, saber con quien hablar puede dejar en clara desventaja a quien no sigue las normas de la universidad. Y algunos ya sabéis de mis más y mis menos con algunos profesores, y que en la mayoría de las ocasiones han tenido que ceder: De las entregas de boletines de ejercicios por sorpresa en clase a cambiar la forma de evaluación durante el curso. Al final han tenido que acogerse a lar normas.

    Aunque tuve una etapa anterior en la delegación, sobre el 2007, muchas cosas han cambiado en esta nueva etapa. Hemos tenido que pegarnos con los problemas en la implantación de las últimas fases de los grados, y con la implantación del plan 2011 de las ingenierías TIC (a.k.a. plan ABET). Conocer los problemas que aparecen en cada momento es vital para solucionarlos cuanto antes.

    Ser estos dos últimos años subdelegado de curso y de titulación, y el último año miembro del Claustro, me han permitido conocer trabajar con mucha gente. Para empezar habría que agradecer a Paco Valera su dedicación como subdirector de la titulación en los últimos años con los problemas de los nuevos planes de estudio, y cuya puerta siempre estaba abierta para hablar de cualquier problema, o dar a un toque a los profesores que fuese necesario.  Si bien apenas acaba de empezar el curso, la misma sensación tengo con el nuevo subdirector, Mario Muñoz, con quien ya he tratado algunos problemas.

    Aunque vuelvo a presentarme, salga quien salga sabe que puede contar con mi ayuda para lo que necesite.

    11 de October de 2012 a las 13:43

    30 de September de 2012

    Fernando Cerezal

    REAMDE, como soltarle una pullita a Google

    Hace poco que he empezado a leer "REAMDE", el último libro de Neal Stephenson. En él habla de un personaje que ha creado un videojuego cuyas primeras imágenes al cargar son como las de Google Earth, pero que el personaje no tienen ningún remordimiento porque los que los que hicieron Google Earth copiaron esa idea de un libro.


    30 de September de 2012 a las 16:37

    27 de May de 2010

    Fernando J. Pereda

    iostreams are VERY thread-unsafe on Mac OS X

    This was both surprising and disgusting. Our in-house data acquisition software needs to convert lots of floats to ascii so that they can ve viewed in real time. This is very easy to do with a stringify-like function like the one found in paludis/paludis/util/stringify.hh.

    stringify looks trivial, there’s no shared state nor there is any static data, so I thought that I could call stringify from several threads at the same time. I don’t think there’s any guarantee about thread safety of ostringstream’s operator<< but it looked like a safe assumption. Well, incorrect.

    operator<< calls vsnprintf, which should be thread-safe by itself. However, OSX's vsnprintf ultimately calls localeconv_l, which is not thread-safe. And, you end up with something like this:

    #0 0x96f734a9 in malloc_error_break ()
    #1 0x96f6e497 in szone_error ()
    #2 0x96e98503 in szone_free ()
    #3 0x96e9836d in free ()
    #4 0x96e97f24 in localeconv_l ()
    #5 0x96e93335 in __vfprintf ()
    #6 0x96ecb9b5 in vsnprintf ()
    #7 0x0144615e in std::__convert_from_v ()
    #8 0x01437d2a in std::num_put<char, std::ostreambuf_iterator<char, std::char_traits > >::_M_insert_float ()
    #9 0x0143803d in std::num_put<char, std::ostreambuf_iterator<char, std::char_traits > >::do_put ()
    #10 0x0144ab6a in std::ostream::_M_insert ()
    #11 0x0000fb25 in std::basic_ostringstream<char, std::char_traits, std::allocator >::str () at sstream:217
    ...

    Which means there’s no way of converting stuff to human readable in a thread-safe manner. I’m not sure whether I’m missing something or not… but this looks very fishy. I ended up adding a stupid big mutex around my stringify calls, but that looks more like a workaround that a final solution to the problem. Plus, this doesn’t protect ANY other uses of iostream’s operator<< such as loggers.

    Ok… looks like that wasn’t a very accurate diagnostic. This is going to be more annoying than I thought.

    — ferdy


    Tagged: C, osx, programming, threads

    27 de May de 2010 a las 08:33

    01 de May de 2010

    Fernando J. Pereda

    Finally, a real AMSV (Autonomous Marine Surface Vehicle)

    After lots of work from different people, it finally is a real AMSV. Nothing too fancy yet (just a mere PD controller for speed and heading). It is, nonetheless, a very interesting platform for future research.

    With semi-strong current and some wind it managed to follow a very nice path across some waypoints:

    The trajectory between p2 and the shore was done manually using a joystick. Interestingly enough, that path is less nice than those done by the autonomous control.

    I hope to be able to post more niceties soon.

    — ferdy

    01 de May de 2010 a las 15:15

    17 de December de 2009

    Roberto Muñoz

    Poliamor

    «Como digo, soy un hombre. Me gustan las mujeres. A veces esa atracción está incluso fuera de mi control. Puedo controlar mis actos, aunque no lo que siento. Miro a las chicas por la calle, y a algunas las encuentro realmente atractivas. No sentiré especial devoción por Sorolla o Velázquez, pero es que no todas las obras de arte se encuentran en los museos. A veces me salto a los intermediarios y voy directamente a la exposición de Dios.»
    -- Javier Malonda (aunque bien se puede atribuir a cualquier hombre heterosexual)

    Al final de la entrada de donde he extraído lo anterior se da el enlace de la Wikipedia del Poliamor. Después de leerlo veo que un poliamoroso famoso es Eric S. Raymond. Que la wikipedia lo define como:
    «Raymond es un neopagano, un confeso anarcocapitalista, y un defensor del derecho a poseer y utilizar armas de fuego. Tiene un gran interés en la ciencia ficción. Es músico amateur y cinturón negro de taekwondo. Además sufre una leve parálisis cerebral congénita.»
    A eso añádele poliamoroso. El amigo «dospistolas» no se aburre, y es más listo que el hambre, como se suele decir.

    17 de December de 2009 a las 18:58

    02 de November de 2009

    Roberto Muñoz

    TTS 2.0

    He publicado la versión 2.0 de TTS (TalkToSerial) que tiene las siguientes mejoras:


    Para más info visitad el Wiki. Y si se quiere descargar, aquí está el código fuente.

    02 de November de 2009 a las 19:59

    29 de May de 2009

    Fernando J. Pereda

    MSDNAA, clever?

    So MSDNAA lets university students get some Microsoft products for free for educational purposes. That’s all fine and dandy except that you can’t directly download stuff, you have to do it using a shitty download manager.

    It is hilarious that you have to run a Windows executable to download a copy of Windows XP.

    Chicken and egg?… Yeah, that’s clever.

    One point for you Suckrosoft.


    Tagged: enterprisey, idiots, rant, suckrosoft

    29 de May de 2009 a las 09:02

    10 de May de 2009

    Fernando J. Pereda

    OpenSceneGraph

    For SpaceFish I wanted a quick way to load a 3D model and be able to rotate it easily. This, along with an artificial horizon is a nice way to see the attitude of the plane while it is far to see it. It is also quite good to replay recorded data during experiments to study it further in the lab.

    Since I haven’t really done anything in OpenGL beyond stupid examples and helloworld-like programs and given that I don’t have much time to devote to this task I decided to use an existing framework. Among Irrlicht, OpenSceneGraph and Ogre. I decided to give OpenSceneGraph a try, for no particular reason.

    Unfortunately, it took a while to get it working under OSX… it needs something like this. I use MacPorts for this kind of stuff under OSX:

    fixOpenSceneGraph()
    {
    	local lib_dir=/opt/local/lib
    	pushd ${lib_dir} > /dev/null
    	echo pushd ${lib_dir}
    	for i in libosg*.dylib* libOpenThreads*.dylib* ; do
    		echo install_name_tool -id ${lib_dir}/${i} ${i}
    		otool -L ${i} | sed -e 1d | while read f ; do
    			if [[ ${f} =~ ^libosg ]] || [[ ${f} =~ ^libOpenThreads ]] ; then
    				l=${f%% *}
    				echo install_name_tool -change ${l} ${lib_dir}/${l} ${i}
    			fi
    		done
    	done
    	popd > /dev/null
    	echo popd
    	port contents OpenSceneGraph |
    		sed -n -e '/^[[:space:]]*\/opt\/local\/bin\//p' -e '/\.so/p' |
    		while read f ; do
    		otool -L ${f} | sed -e 1d | while read d ; do
    			if [[ ${d} =~ ^libosg ]] || [[ ${d} =~ ^libOpenThreads ]] ; then
    				l=${d%% *}
    				echo install_name_tool -change ${l} ${lib_dir}/${l} ${f}
    			fi
    		done
    	done
    }

    It wasn’t fun to figure that out (thank you CMake)…

    Anyway, I think I’ll stick to OpenSceneGraph until it annoys me enough. For now, I managed to do what I wanted in less than 2 hours, which is pretty good when you have a stupidly tight schedule.

    — ferdy


    Tagged: cmake-sucks-goat-balls, cpp, openscenegraph, osx, spacefish

    10 de May de 2009 a las 22:18

    27 de April de 2009

    Fernando J. Pereda

    Small C trivia

    This is somehow surprising the first time you see it and it is interesting to remind it to people from time to time. The question is easy, does this program always return 0? That is, are those summations the same?

    If there’s a case when it doesn’t, provide a sample input and explain why it happens.

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[])
    {
    	float f[argc - 1];
    	for (int i = 1; i < argc; i++)
    		f[i - 1] = atof(argv[i]);
    	float r1 = 0;
    	for (int i = 0; i < argc - 1; i++)
    		r1 += f[i];
    	float r2 = 0;
    	for (int i = argc - 2; i >= 0; i--)
    		r2 += f[i];
    	return r1 != r2;
    }

    As usual, I’ll post the solution in a couple of days or when someone gets it right (which is always the case :))

    — fpereda

    Update: correct typo spotted by Snaury.


    Tagged: C, CS, programming, trivia

    27 de April de 2009 a las 09:21

    21 de March de 2009

    Fernando J. Pereda

    The Burning Ship fractal

    I finally sat down and wrote support for drawing the Burning Ship Fractal into gmandel. It only took a couple of minutes, but I haven’t really had spare time lately.

    Some parts of the fractal are quite interesting and different from other fractals derived from the Mandelbrot set. Here are some pictures using gmandel:

    burningship1 burningship2 burningship3

    — fpereda


    Tagged: burningship, chaos, fractal, gmandel

    21 de March de 2009 a las 19:11

    15 de March de 2009

    Fernando J. Pereda

    Bye-Bye Gentoo

    My retirement from Gentoo is complete now.

    Good luck to everybody. I hope some people understand the real needs of Gentoo and where it should go. Even if I’m not planning to come back to Gentoo (either as a user or as a developer), I certainly hope the best for it.

    Cheers.

    — ferdy


    Tagged: gentoo

    15 de March de 2009 a las 17:23

    16 de February de 2009

    Fede Mon

    esta tarde a la expo de Star Wars en Madrid, quien se viene?

    16 de February de 2009 a las 12:03

    13 de February de 2009

    Fede Mon

    me encanta: la camiseta con el piechart de la procastinación: http://ping.fm/caI56

    13 de February de 2009 a las 00:54

    10 de February de 2009

    Fernando J. Pereda

    Selected!

    So this led to this

    ’nuff said!

    Mood: Extremelly happy.

    — ferdy


    Tagged: esa, estec, happy, research, spacefish

    10 de February de 2009 a las 18:11

    02 de February de 2009

    Fernando J. Pereda

    More reading

    I finished reading Anathem a while ago, and I really do recommend it. It was weird at first, but really nice in the end. It finished a bit fast, I’d say it needs another hundred pages to tie some of the stuff.

    Also, Ricardo Cervera (you don’t have an url these days, you do?) sent me Introduction to Algorithms which I’ve been skimming through. Really nice book, of course. — Thanks.

    As part of one of the research projects I’m involved, I just started reading/studying Aircraft control and simulation. Fortunately, it is not hurting as much as I expected. Though it is not for the faint of heart.

    — ferdy


    Tagged: book, reading, thanks

    02 de February de 2009 a las 12:05

    ESTEC and EeePC’s first big test

    This year I joined a couple of research projects at the Computer Architecture and Automatics Department of UCM. Since I’m still finishing my Computer Science degree I can’t spend as much time as I’d liked on the projects I’m taking part. I’m mostly doing softwar and learning quite a bit of electronics and such.

    Tomorrow morning I’m heading ESA’s ESTEC to attend the first workshop of this year’s RexusBexus campaign. We’ll be there until friday. We’ve worked quite hard and are hoping to get selected for the next phase. Even if we are continuing our research even if we don’t get accepted, it is a great opportunity to test the thing.

    Given that I really hate checking luggage at airports I was planning to travel as light as possible. Not needing lots of computing power the Eee came as the best candidate to carry around. I haven’t really done much with it than using it to go to University and back home so this is going to be its firs big test. I get to see whether this netbook thing really works for me, though I think it will.

    We’ll see how it works…

    — ferdy


    Tagged: asus, eee pc, eeepc, esa, estec, netbook, ucm

    02 de February de 2009 a las 09:07

    25 de November de 2008

    Fede Mon

    Undervolting

    Anoche me divertí mucho. Me acosté como a las 3:30.

    Andaba buceando intentando investigar por qué Xorg me consume más CPU últimamente, y no lo encontré, pero casi sin querer me encontré con un tipo que había hecho undervolting en su macbook.

    Básicamente se trata de disminuir el voltaje suministrado a la CPU hasta el límite en el que ésta siga funcionando correctamente.

    De esta manera dura más la batería, se calienta menos el procesador, se encienden menos los ventiladores... son todo ventajas. Mi batería ha empezado a durarme una hora más!!

    Para usarlo en linux, tenemos que usar linux-phc: https://www.dedigentoo.org/trac/linux-phc/

    En los foros de ubuntu [[http://ubuntuforums.org/showthread.php?t=786402] se pueden conseguir los módulos compilados, así como un howto para descubrir tu configuración (los voltajes mínimos para tu procesador).

    Lo malo es que el script que hay en el foro es para procesadores con un solo core, de manera que si tienes un dual core, hay que retocarlo para que ponga la misma frecuencia en ambos cores, y les baje el voltaje a los dos, asimismo hay que lanzar otro burnMMX que se coma la otra CPU, ya que el script sólo lanza uno.

    Para que funcione con dos procesadores:

    Creamos una variable nueva para la segunda CPU:
    cpufreq1=/sys/devices/system/cpu/cpu1/cpufreq

    y buscamos "$cpufreq", añadiendo una linea extra pero con "$cpufreq1", por ejemplo:

    printf "ondemand" | sudo tee $cpufreq/scaling_governor > /dev/null
    printf "ondemand" | sudo tee $cpufreq1/scaling_governor > /dev/null

    Eso sí, en otra terminal hay que lanzar otro burnMMX para que se funda el segundo procesador.

    Sin duda, averiguar tu configuración es lo más divertido del tema, consiste en, para cada frecuencia del procesador, ir bajando el voltaje hasta que la salida de las puertas deje de ser estable, lo que conlleva un reboot instantáneo.

    Bueno, happy undervolting, y hasta el año que viene!

    25 de November de 2008 a las 09:26

    07 de September de 2007

    Fede Mon

    Y luego decimos que los yankies son tontos

    Yo pensaba que hacían entrevistas a la gente antes de dejarla ir a estos programas.

    ¿Qué es lo que gira alrededor de la Tierra?


    Vía: Gran Angular

    07 de September de 2007 a las 11:10

    Una patada en el culo a la política

    Ya sé a quién voy a votar en las próximas elecciones:

    Eva Hache se presenta a presidenta.

    Al menos éstos no se meten al gobierno para sacar tajada, y seguro que a la hora de tomar decisiones estarán más cerca del pueblo que cualquier otro partido político.

    07 de September de 2007 a las 10:43

    05 de September de 2007

    Fede Mon

    Comics

    Sí, ya sé que es una mierda de post después de tanto tiempo sin postear, pero es que termino antes que enseñándooslo uno por uno:

    No son Bilo y Nano, ni Raulito el Friki, es diferente, pero es genial.

    Es Alberto Montt

    Para muestra, un botón:

    05 de September de 2007 a las 02:57

    16 de May de 2007

    Fede Mon

    I am C

    You are C. You do what you're told, even if you know the result will be bad.
    Which Programming Language are You?

    16 de May de 2007 a las 01:06

    17 de April de 2007

    Fede Mon

    Taller en la UAM: Reciclaje de ordenadores (LTSP para entendidos)

    Mi hermanito Sergio Tena me ha invitado a participar en la Semana Verde que está organizando en la UAM (él estudia Medio Ambiente) y me ha ofrecido dar una taller de cómo reutilizar ordenadores viejos.

    Así que me estoy preparando para hacer una demo de todo el poder del Linux Terminal Server Project. El LTSP, para los que no les suene, es un proyecto para conectar ordenadores poco potentes como clientes de uno bien potente. Esto hace posible, por ejemplo, montar un aula de informática en un colegio con un ordenador nuevo y 20 viejos, más el coste de instalar linux sólo en el potente.

    Eso sí, para asistir al taller hay que pasarse por el despacho de Ecocampus a apuntarse, y no existe la posibilidad de apuntarse vía web, así que es de esperar que se apunten pocos geeks. Dependiendo del porcentaje de geeks, me meteré más adentro (cómo ponerse uno y cómo funciona exactamente) , o más general, así que ya sabéis, os invito a todos a que asistáis, la intención es que todos aprendamos algo.

    17 de April de 2007 a las 03:08