2008-02-25

Compilando LaTeX con rake

En el laburo estoy escribiendo un paper (es parte de las cosas que tengo que hacer como investigador en seguridad informática) y, como soy un geek que se precia, lo estoy escribiendo en LaTeX.

El temita es que las figuras que tiene el paper las hice en MS Visio y que quiero tener un script automático para generar el .dvi a partir del .tex, el .bib y los archivos de Visio. Pero LaTeX no acepta archivos de Visio como imágenes, solo .eps (encapsulated postscript) y Visio a lo sumo escupe .wmf. Así que instalé el wmf2eps y entonces tuve una idea, ¿por qué no generar todo usando rake y uso win32ole para hacer automation con el Visio?.

Este es el resultado (que anda) del rakefile que uso para generar el paper:


require 'rake/clean'
require 'win32ole'

VIS = FileList['*.vsd']
EPS = VIS.ext('eps')
MAIN = "paper.tex"
DVI = "paper.dvi"
BIB = "paper.bib"

CLEAN.include(FileList["*.wmf", "*.aux", "*.bbl", "*.blg", "*.log"] )
CLOBBER.include(FileList[DVI], VIS.ext("eps"))

def windows_name(file)
File.expand_path(file).gsub("/","\\").gsub(" ", "\\ ")
end

def visio()
begin
return WIN32OLE.connect("visio.application"), false
rescue WIN32OLERuntimeError # Visio is not running
return WIN32OLE.new("visio.application"), true
end
end

def open_doc(visio, filename)
begin
return visio.Documents(filename), false
rescue WIN32OLERuntimeError # file not open
return visio.Documents.open(filename), true
end
end

def latex
sh "latex", "-halt-on-error", MAIN do
|ok, res|
unless ok
puts "Error compiling LaTeX file (status=#{res.exitstatus})\n"
exit
end
end
end

def bibtex
sh "bibtex", "paper" do
|ok, res|
unless ok
puts "Error compiling bibtex file (status=#{res.exitstatus})\n"
exit
end
end
end

file DVI => EPS + [MAIN, BIB] do
latex
bibtex
latex
latex
end

rule '.wmf' => '.vsd' do
|t|
visio_filename = windows_name(t.source)
wmf_filename = windows_name(t.name)
visio, close_visio = visio()
document, close_document = open_doc(visio, visio_filename)
document.Pages(1).Export(wmf_filename)
document.Close if close_document
visio.Quit if close_visio
end

rule '.eps' => '.wmf' do
|t|
wmf_filename = windows_name(t.source)
dirname = windows_name( File.dirname(t.source) )
sh "wmf2eps\\wmf2eps -o #{dirname} #{wmf_filename}"
end

desc "Generates dvi for paper"
task :dvi => DVI

desc "Generates images for paper from Visio files"
task :images => EPS

desc "Generates images for paper from Visio files"
task :default => :images


Espero que les sirva esto, y que ruby se vaya acercando a la academia.

Happy hacking,
Aureliano.

2008-02-24

Mr Opener en rubyforge

Estoy muy contento de anunciar que el código de Mr Opener (anunciado en el post anterior) está disponible para todos los que lo quieran en rubyforge.

La página del proyecto es http://rubyforge.org/projects/mropener/.

Espero a futuro:

  • Hacer un gem con este programa
  • Hacer otro programita, que va a ser un clon del space invaders pero usando al Señor Destapador como personaje principal.
  • Seguir con más programas con el Señor Destapador como personaje principal.

Happy hacking,
Aureliano.

Mr Opener

Ultimamente estuve instalando Rubygame en mi PC.

Una vez que lo logré, puse manos a la obra. Así que me copé y en menos de una semana escribí un jueguito para mi sobrina. El mismo es una copia del Potato Guy, que viene con el KDE.

Como protagonista del juego puse al Señor Destapador. Al señor destapador hay que vestirlo, armarle la cara, y darle cosas para que tenga.

Acá les muestro un snapshot del programa andando.



Estoy tramitando un proyecto en rubyforge para hostear el proyecto y lo voy a licenciar con la GPL, ya que Rubygame es LGPL y no quiero tener quilombos de licencia al dope.

Les cuento que el código al final quedó bastante chiquito y fácil de leer, y que lo que más me costó fue editar las imágenes para que encajaran (más o menos) en el juego.

Hasta la próxima y happy hacking.

PD: Me olvidaba, si a alguno de ustedes les interesa tener el código fuente antes de que lo publique en ruyforge, no tienen más que pedirmelo.

2008-02-17

Rubygame en ubuntu, no hay 2 sin 3

Todavía hay más quilombos para hacer correr rubygame en kubuntu gutsy. La demo de sonido no anda y da este error:


$ ./demo_music.rb
ALSA lib pcm_dmix.c:864:(snd_pcm_dmix_open) unable to open slave
./demo_music.rb:19:in `open_audio': Error initializing SDL_mixer:
No available audio device (Rubygame::SDLError)
from ./demo_music.rb:73:in `join'
from ./demo_music.rb:73

Para arreglarlo hay tuve que desinstalar la biblioteca libpulse0, como sugieren en este post.

Happy hacking.

Rubygame en ubuntu, más soluciones

En el post anterior mostré como solucioné un problema que me impedía usar la biblioteca rubygame en mi kubuntu. Bueno, ese no es el único problema. Cuando traté de correr la demo de rubygame me daba otro error:


$ ./demo_rubygame.rb
./demo_rubygame.rb:28: SDL_gfx is not available. Bailing out. (RuntimeError)


Así que puse manos a la obra. El problema es que la versión de la biblioteca SDL_gfx que viene con ubuntu es vieja. En ubuntu gutsy viene la versión 1.2 y rubygame requiere la 2.0. Así que desinstalé la versión que viene con ubuntu, me bajé la última versión de acá y la instalé. La instalación es medio "tricky" porque la típica ./configure;make;make install no anda. Así que tuve que mirar el archivo INSTALL. Para ahorrarles el laburo de mirarlo ustedes, les cuento acá. Para instalarlo tienen que hacer:

$ ./autogen.sh
$ ./configure
$ make
$ sudo make install
$ sudo ldconfig
$ make distclean


Una vez que todo esto funcó, desinstalé y reinstalé el gem de rubygame y me anduvo la demo.

Bueno, espero que no haya más quilombos.

Happy hacking.

Rubygame en ubuntu

Estoy con ganas de probar rubygame porque tengo ganas de programar un poco en ruby (en el laburo me obligan a programar en python y php). Rubygame es la versión para ruby de pygame.

Pero me encontré con un problemita con el que quizás se encuentren ustedes también. Tengo kubuntu 7.10 (gutsy) y la instalación de ruby de ubuntu (al menos en esta versión) hace que el shared object de ruby tenga un nombre distinto del standard. Por eso la librería de rubygame no lo encuentra.

Este es un ejemplo del problema:


$ irb -rubygems -rrubygame
/usr/lib/ruby/gems/1.8/gems/rubygame-2.2.0-x86-linux/ext/rubygame/rubygame_core.so:
libruby18.so.1.8: cannot open shared object file: No such file or directory -
/usr/lib/ruby/gems/1.8/gems/rubygame-2.2.0-x86-linux/ext/rubygame/rubygame_core.so (LoadError)
from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
from /usr/lib/ruby/gems/1.8/gems/rubygame-2.2.0-x86-linux/lib/rubygame.rb:25
from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:32:in `gem_original_require'
from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:32:in `require'
from /usr/lib/ruby/1.8/irb/init.rb:252:in `load_modules'
from /usr/lib/ruby/1.8/irb/init.rb:250:in `each'
from /usr/lib/ruby/1.8/irb/init.rb:250:in `load_modules'
from /usr/lib/ruby/1.8/irb/init.rb:21:in `setup'
from /usr/lib/ruby/1.8/irb.rb:54:in `start'
from /usr/bin/irb:13


Para arreglarlo, hay que hacer un link más en /usr/lib así: $ sudo ln -s libruby1.8.so libruby18.so.1.8.

La pista de como emparchar mi sistema me lo dio este post en la lista de ruby.

Aparentemente, es un bugcito de rubygame, pero no estoy del todo seguro.

Bueno, hasta la próxima y happy hacking.

2008-02-13

Un hecho, dos noticias

Esto lo encontró Natalia, una gran amiga mía.

La noticia, agarraron a un represor de la última dictadura militar, que boleteó a 19 personas. Comparen por ustedes mismos y miren.
Esta es la versión de La Nación y esta la de Página 12.

La verdad, indignante.

2008-02-10

No vayan al Hostal Azul (Humahuaca)

Hola,
Les cuento porqué. La habitación que me dieron tenía un olor a cigarrillo insoportable, impregnado por todos lados. Se notaba que no lavaron bien las sábanas ni la colcha y no me cambiaron el colchón aunque se los pedí explícitamente. Así que en plena temporada alta tuve que salir en una gira desesperada por Humahuaca para conseguir otra habitación en otro hotel. Por suerte conseguí una sin ese olor asqueroso que tenía la del hotel. Otro motivo para no ir es que tardan 45 minutos (aproximadamente) en servir el desayuno (medido con reloj, promediado en los 3 desayunos que estuvimos ahí).

Repito. No vayan al Hostal Azul en Humahuaca, Jujuy, Argentina.

Igual vayan a Humahuaca que está buenísimo, y si pueden haganse una escapada a Iruya.

2008-01-04

Nuevo blog

José (AKA: Termo) presenta su nuevo blog. En su segundo artículo (el primero es un test del blog) habla sobre como calcular el page rank en python. Espero que les guste.

2007-12-30

Dual head en mi notebook

Estoy muy contento de como quedó la configuración de la pantalla de mi Inspiron 1520.

Después de un toque de googleo, encontré un post donde explican cómo configurar una notebook con placa Intel para que soporte 2 monitores (el de la notebook y otro más) en KUbuntu Gutsy. Así que seguí los pasos (que son bastante simples) y los retoqué un bati-toque (santas redundancias batman) para que se configure solo.

Primero agregué a la subsección "Screen"/"Display" del archivo la entrada:

virtual         2560    1024

La onda de esta entrada es que el virtual desktop alcance para los 2 monitores.

Después me agregué en $HOME/bin 2 scripts. Uno para activar el segundo monitor y configurarlo bien y otro para desactivarlo. El que activa y configura el segundo monitor (dual-head) es:
#!/usr/bin/env bash

xrandr --output VGA --auto
xrandr --output VGA --right-of LVDS


El que la apaga es:
#!/usr/bin/env bash

xrandr --output VGA --off


Por último, linkié en ~/.kde/Autostart el script dual-head, así se setea automágicamente la dualidad onda-monitor. Si el monitor no está enchufado, el script no hace nada, así que lo dejé así:
ln -s ../../bin/dual-head


Así que ahora tengo todo listo y cuando estoy en casa puedo usar mi otro monitor también.

2007-12-24

Papá Noel

Ayer a la noche hice de Papá Noel en el complejo de departamentos en el que vivo. Fue un quilombo de niñ@s y adult@s. Impresionante el efecto que genera el disfraz de Papá Noel en la gente. L@s chic@s se me quedaban mirando (se quedarían preguntándose, ¿es de verdad?). En el evento repartí bolsitas con regalitos tontos para l@s chic@s y recibí algunas cartitas. Entre las cartas que recibí está la de mi sobrina.


Y acá está una foto con ella (que nunca supo que Papá Noel era yo) y de fondo el batifondo (santas redundancias batman) del evento.

La verdad, lo disfruté mucho.

2007-12-17

PHP es KK. Un ejemplo práctico

Hoy mi amigo Ernesto Alvarez me mostró un pequeñísimo ejemplo de porqué PHP es una mierda. La semántica del lenguaje deja muuuucho que desear.

El programa:

<?php
echo count == 0;# . "\n";
?>


Muestra "1" en la salida por standard output.

En cambio si dejamos el enter comentado no muestra nada. Este es el código que no muestra nada:

<?php
echo count == 0 . "\n";
?>


Bueno, una cosa más para hacer leña del árbol caído.
Hasta la próxima, amigos.

Update: Escribí una segunda parte de esto en mi artículo Si php es KK, ¿por qué lo usan tanto?.

2007-11-28

51 x 10^9 (parte 2)

En mi mi último post, mostré un problema que usan en ITA para reclutar gente. Parece que anda mal porque el resultado que encuentra no coincide con el fin de un número, como dice en el enunciado. Pero como me quedé desvelado una noche haciendolo, les mandé un mail con mi solución. Mientras tanto aprovecho y les pregunto a ustedes.

¿Le ven algún quilombo al código de abajo?


#!/usr/bin/env ruby

class Result
attr_accessor :letters_advanced
attr_accessor :letters_missing
attr_accessor :sum
attr_accessor :number
attr_accessor :name

def initialize(letters_missing=0)
self.letters_missing = letters_missing
self.sum = 0
self.letters_advanced = 0
self.number = -1 # not set
end

def << (other_result)
self.letters_advanced += other_result.letters_advanced
self.sum += other_result.sum
self.letters_missing -= other_result.letters_advanced
self.number = other_result.number
self.name = other_result.name
end

def to_s
string = "name:#{name} - number:#{number} - " +
"letters_advanced:#{letters_advanced} - " +
"letters_missing:#{letters_missing} - sum:#{sum}"
string += " - letter:#{name[name.length-1+letters_missing,1]}" if letters_missing <= 0
end
end

class Block

attr_reader :value
attr_reader :name
attr_accessor :next_block
attr_reader :position # 0 for ones, 1 for thousands, 2 for millions

def initialize( name, number, position )
@name = name
@value = number * (1000 ** position)
@position = position
end

# Inserts a block somewhere after this block, hopefully close (if not, takes a long time)
def insert_block(new_block)
before = self
after = self.next_block
while( after != nil && new_block.name > after.name )
before = after
after = before.next_block
end
before.next_block = new_block
new_block.next_block = after
end

def advance(min_position, max_position)
current = self.next_block
while !current.nil? && !current.position.between?(min_position, max_position)
current = current.next_block
end
current
end

ONES = [ "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" ]
TEENS = ["ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen",
"seventeen", "eighteen", "nineteen" ]
ORIG_TENS = [ "twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety" ]

tens = Array.new
ONES.each { |n| tens << n }
TEENS.each { |n| tens << n }
ORIG_TENS.each do
|ten|
ONES.each do
|one|
tens << ten + one
end
end

TENS = tens

HUNDREDS = ONES.map do
|hundred|
root = hundred == "" ? "" : hundred + "hundred"
numbers = tens.map do
|ten|
root + ten
end
numbers
end.flatten

number = 0
NAMED_HUNDREDS = HUNDREDS.map do
|name|
value = { :number => number, :name => name }
number += 1
value
end.sort_by { |pair| pair[:name] }.reverse

last = nil
NAMED_HUNDREDS.each do
|pair|
new = Block.new(pair[:name], pair[:number], 0)
new.next_block = last
last = new
end

@last = last.next_block # Ignore zero

#Add higher level blocks (thousand and millions)
current = last
while( current != nil )
if current.position == 0 then
current.insert_block( Block.new(current.name + "thowsand", current.value, 1) )
current.insert_block( Block.new(current.name + "million", current.value, 2) )
end

current = current.next_block
end

def self.first( position=0 )
first = @last
while (first.position != position)
first = first.next
end
first
end
end

class Number

def initialize( pos2, pos1, pos0 )
@blocks = [pos0, pos1, pos2]
end

def name
@blocks.reverse.inject("") do
|acum, block|
acum += block ? block.name : ""
end
end

def value
@blocks.inject(0) do
|acum, block|
acum += block ? block.value : 0
end
end

def description
r = Result.new
r.letters_advanced = self.name.length
r.name = self.name
r.number = r.sum = self.value
r
end

def next_number(min_pos=0)
max_pos = min_pos + 1
while @blocks[max_pos].nil? && max_pos < 3
max_pos += 1
end
max_pos -= 1
new_block = @blocks[min_pos] ? @blocks[min_pos].advance(min_pos, max_pos) : Block.first(min_pos)
@blocks[min_pos] = nil
if (new_block) then
@blocks[new_block.position] = new_block
else #carry
self.next_number(min_pos + 1)
end
self
end

unit_letter_count = 0
unit_accumulated_values = 0
block = Block.first(0)
while( block )
unit_letter_count += block.name.length
unit_accumulated_values += block.value
block = block.advance(0,0)
end
UNIT_LETTER_COUNT = unit_letter_count
UNIT_ACCUMULATED_VALUES = unit_accumulated_values

def step(result)

if (@blocks[1] && !@blocks[0])
big_step_char_count = self.name.length * 1000 + UNIT_LETTER_COUNT
if big_step_char_count < result.letters_missing then
step_result = Result.new
step_result.letters_advanced = big_step_char_count
step_result.number = step_result.sum = self.value * 1000 + UNIT_ACCUMULATED_VALUES
result << step_result
self.next_number(1)
return
end
end
# Big step is not taken
result << self.description
self.next_number
end

def self.first
self.new( nil, nil, Block.first )
end

def self.result( letter_position)
result = Result.new(position)
number = Number.first
while( result.letters_missing > 0 )
result << number.description
number=number.next_number
end
result
end

end


position = ARGV[0].to_i
result = Result.new(position)
number = Number.first
count = 0
while( result.letters_missing > 0 )
number.step(result)

count += 1
if (count % 100000) == 0 then
puts "Partial result"
p result
end
end

puts "Final result"
puts result

2007-11-25

51 x 10^9

Como estuve con un poquito de tiempo libre me puse a programar un toque este sábado a la noche (sí que soy divertido :p). Y encontré un problemita intereseante en el blog de una .com. El problema es el mismo que proponen en ITA para tomarte como programador.

El mismo consiste en saber cuál es la letra número 51 x 10^9 (o sea 51000000000) de la secuencia de agarrar todos los números entre 1 y 1000000000 y transformarlos en letras, saber a que número pertenece y cuanto vale la suma de todos los números por los que pasaste para llegar a esa letra desde el principio. La solución del problema es un bardo, así que no lo hice todo, pero escribí un programa para obtener la letra en la posición x en la secuencia de números que va del 1 al 1000, a qué número pertenece y cuál fue la suma acumulada hasta ahí.

Acá les pongo a continuación el enunciado del problema:

"If the integers from 1 to 999,999,999 are written as words, sorted alphabetically, and concatenated, what is the 51 billionth letter?"

To be precise: if the integers from 1 to 999,999,999 are expressed in words (omitting spaces, 'and', and punctuation[1]), and sorted alphabetically so that the first six integers are

  • eight
  • eighteen
  • eighteenmillion
  • eighteenmillioneight
  • eighteenmillioneighteen
  • eighteenmillioneighteenthousand
and the last is
  • twothousandtwohundredtwo
then reading top to bottom, left to right, the 28th letter completes the spelling of the integer "eighteenmillion".

The 51 billionth letter also completes the spelling of an integer. Which one, and what is the sum of all the integers to that point?

[1] For example, 911,610,034 is written "ninehundredelevenmillionsixhundredtenthousandthirtyfour"; 500,000,000 is written "fivehundredmillion"; 1,709 is written "onethousandsevenhundrednine".

Y este es mi programa en ruby. Una generalización trivial para correrlo con los números que vayan desde 1 a 1000000000 requeriría (según estimo) unos 100GB de espacio libre en el disco rígido, varios días de tiempo de procesamiento para correr e implementar una rutina de external sorting. Pero me parece que los números tienen suficiente estructura como para cortar camino, así que si se me ocurre algo mejor lo postiaré por acá también.



#!/usr/bin/env ruby

class Result
attr_accessor :letters_advanced
attr_accessor :letters_missing
attr_accessor :sum
attr_accessor :number

def initialize(letters_missing=0)
self.letters_missing = letters_missing
self.sum = 0
self.letters_advanced = 0
self.number = -1 # not set
end

def << (other_result)
self.letters_advanced += other_result.letters_advanced
self.sum += other_result.sum
self.letters_missing -= other_result.letters_advanced
self.number = other_result.number
end
end

class Hundred

attr_reader :value
attr_reader :name
attr_reader :next_number

def initialize( name, value, next_number )
@name = name
@value = value
@next_number = next_number
end

def description
r = Result.new
r.letters_advanced = self.name.length
r.sum = self.value
r.number = self.value
r
end

ONES = [ "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" ]
TEENS = ["ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" ]
ORIG_TENS = [ "twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety" ]

tens = Array.new
ONES.each { |n| tens << n }
TEENS.each { |n| tens << n }
ORIG_TENS.each do
|ten|
ONES.each do
|one|
tens << ten + one
end
end

TENS = tens

HUNDREDS = ONES.map do
|hundred|
root = hundred == "" ? "" : hundred + "hundred"
numbers = tens.map do
|ten|
root + ten
end
numbers
end.flatten

number = 0
NAMED_HUNDREDS = HUNDREDS.map do
|name|
value = { :number => number, :name => name }
number += 1
value
end.sort_by { |pair| pair[:name] }.reverse

last = nil
NAMED_HUNDREDS.each do
|pair|
last = Hundred.new(pair[:name], pair[:number], last)
end

@last = last

def self.first
@last
end
end

position = ARGV[0].to_i
result = Result.new(position)
number = Hundred.first
while( result.letters_missing > 0 )
result << number.description
number=number.next_number
end

p result

2007-11-18

Viaje boliviano

Mi cuñada está de viaje (tipo mochilera) por Bolivia desde junio. Éstas son las consecuencias del viaje, tal como lo relata en un mail:

"cerca de alli esta el ojo del inca, que es una fuente de aguas termales segun dicen con grandes propiedades curativas.... y creo que es lo uqe estoy necesitando en este momento porque no paro de tener problemas de salud.... nada grave no te preocupes, pero la verda es que me siento unav ieja tomando antibioticos, poniendome pomadas n diversos lugares del cuerpo, tomando toda clase de hierbas y yendo de medico en medico, a ver si alguna vez alguno la pega..... por suerte la quemadura ya cicatizo, pero tendre una enorme mancha en la pierna por el resto de mis dias.... de cualquier manera estoy probando con aloe vera y mayonesa, a ver si se borra un poco, pero por ahora no veo mucho resultado....

despues esta el tema del quiste, que creo que te habia contado, que me salio hace unos meses en el gluteo y me esta molestando por demas, ahora estoy probando con un nuevo antibiotico y si no funciona tendre que ir a un especialista porque eso si me dijeron que no lo deje pasar....
y de la selva me traje algo que parece ser un excema, cosa que nadie supo explicarme que es, pero todavia ono encuentro cura y no solo me duele sno que tengo la piel que pareciera pudrirse, justo detras de la rodilla....
por si fuera poco tengo parasitos que me hacen descomponerme cada dos por tres.... ahora estoy probando con gotitas de ajenjo y bardana que me regalo un español, el problema es que deberia continuar el tratamiento pero no encuentro esas hierbas por aqui......"

¿Sobrevivirá para traerme el charango que le pedí?

2007-11-08

¿Qué estudio?

Estoy con ganas de estudiar algo el año que viene (y quizás algunos más, o no). Mis opciones son bastante amplias, así que quería preguntarles que les parecen, si se les ocurre alguna otra, si alguna les parece que no vale la pena (por ejemplo, porque lo estudiaron y no les parece que lo vale) o si hay alguna de éstas que sea la posta. Es claro que no puedo estudiar todo esto, así que tengo que elegir.

Estas son las opciones que se me ocurrieron (sin ningún orden particular) y algunos pros y contras:

  • Lenguaje chino (¿mandarín?)
    • Pros: 1/6 del mundo lo habla. Tiene una forma re conceptual de definir las ideas.
    • Cons: mucha gente lo estudia. ¿No me puedo comunicar en inglés? Aparentemente es re-dificil
  • Lenguaje coreano
    • Pros: menos gente lo estudia. La comunidad coreana argentina es bastante grande.
    • Cons: menos gente lo habla.
  • Matemática
    • Pros: es perenne.
    • Cons: descolgado del mundo. Carrera exigente y larga.
  • Física
    • Pros: el mejor ejemplo de modelado que hay.
    • Cons: Carrera exigente y larga. ¿Hay gente más pedante que los físicos?
  • Algo relacionado con el diseño gráfico
    • Pros: Una de mis falencias más evidentes es la falta de criterio estético.
    • Cons: Una de mis falencias más evidentes es la falta de criterio estético.
  • Doctorado en computación
    • Pros: Seguir avanzando en el mismo camino.
    • Cons: Los doctorados son algo demasiado intensivo y no tengo forma de aguarlo (en las carreras de grado cursaría menos materias y listo).
Bueno, eso es todo.
Escucho ideas, sugerencias y críticas.

2007-10-26

El voto geek

El voto geek está complicado en estas elecciones.

Por un lado están los pingüinos K, que en su plataforma tienen Linux con KDE.

Por otro lado está UNA, representante de una gran tradición, el acrónimo recursivo.

Por lo tanto, el voto geek estará fuertemente polarizado. ¿A quién apoyaremos en estas elecciones?

PD: Si ya sé, estoy rompiendo la veda. Si quieren denúncienme al COMFER.
PD2: El voto geek puede o no estar correlacionado con el voto del resto de la gente.

2007-10-24

El botellón del dispenser

Hace un tiempo que estuve pensando en cómo explicar cuál es el mejor momento para hacer un refactoring, y cómo explicar cuál es el momento para hacer el refactoring, y cómo explicar cómo explicar cuál es el momento para hacer el refactoring....
Bueno, ustedes captan la idea.
Y esta es la explicación que elaboré.
Hacer un refactoring es como cambiar el botellón del dispenser de agua de la oficina.
¿Por qué?

  • No vas a ganar más plata por cambiar el bidón.
  • Generalmente cambiar el bidón es un dolor de huevos.
  • Pero peor es no cambiarlo (y quedar sediento).

Bueno, ¿y cuándo conviene cambiar un bidón del dispenser?
Definitivamente no cuando todavía queda agua en el mismo.

Tampoco es una buena idea cambiarlo después de que deje de salir agua del dispenser, porque cuando quieras sacar agua caliente va a estar tibia y cuando quieras sacar agua fría va a estar tibia.

¿Entonces cuándo hay que cambiarlo?
Cuando se vació el bidón, pero queda agua en el tanque que está adentro del dispenser (y las cañerías). Entonces no desperdiciamos agua y el agua sale fría y caliente cuando lo queremos.

Hacer refactorings es algo parecido. Hacer un refactoring antes de tiempo es hacer "boiler-plate", y por lo tanto una pérdida de tiempo. Hacer un refactoring tarde (o no hacerlo) que suframos un diseño feo y que apenas lo hagamos tengamos que arreglar todas las cosas que se hicieron mal porque el diseño anterior no lo permitía de otra manera. En cambio, hacer el refactoring justo antes de necesitar esa flexibilidad en el código por primera vez, es como cambiar el botellón cuando queda agua dentro del dispenser pero no en el botellón.
¿Y cómo nos damos cuenta cuándo estamos por necesitar una flexibilidad en el diseño? La verdad es que soluciones mágicas no conozco (si alguien sabe alguna, por favor que avise). Pero en mi experiencia programar test-first ayuda mucho.

Eso es todo, y espero que hayan disfrutado de las ilustraciones,
Aureliano.

2007-09-17

El cambio recién empieza




¿Siguen las cirujías? ¿Cómo va a terminar? ¿Como Moria Casán? ¿Cómo Zulema Yoma? ¿Como Michael Jackson?

2007-09-10

Un poquitín de Opera

Ayer a la noche fui a ver "Iphigénie en Tauride", de Gluck, interpretada por mi querida Compañía de las Luces. Como siempre (y aún más desde que dejé de cantar ahí) hicieron un espectáculo espectacular (redundantemente). Y están de suerte. Todavía quedan 2 funciones más, así que vayan.

Las dos funciones que quedan son el próximo sábado 15 y domingo 16 de septiembre a las 19:20hs en el Museo Nacional de Arte Decorativo. El mismo está en Libertador y Pereyra Lucena. Las entradas salen solamente $30.

2007-09-05

PHP GRASP

En mi laburo, Core Security, acaban de relesear un proyecto open source (licencia: Apache 2) que sirve para detectar SQL injections en PHP 5.2. El proyecto se llama GRASP y lo que hicieron mis compañeros de laburo es que se puede taintear cada caracter de un string y cuando se hace la llamada a la base de datos chequea las marcas en el string del query y controla si hubo un SQL injection o no.

En la versión actual chequea injections en mysql.

Me parece que se podría hacer algo para Rails. Así que si insisten lo suficiente (¡suscribanse a la lista y pidanlo!) en una de esas me dejan hacerlo. ¡Pidanlo ahora!

El site de GRASP es: http://grasp.coresecurity.com.

2007-08-31

Bug en rubygems 0.9.4

Hoy me crucé con un bug en la versión 0.9.4 de rubygems que hace que no tome de la línea de comando el proxy http, lo que hacía que no ande desde el laburo. Este bug está reportado y, por lo que dice en el bug tracker ya está arreglado en el repositorio de svn.

Pero si no quieren esperar a un nuevo release, se arregla muy fácil.

Busquen el archivo config_file.rb y pongan el siguiente código dentro de la clase ConfigFile (arriba de donde dice private):


def []=(key,value)
@hash[key.to_s] = value
end


Enjoy!
Aureliano.

2007-08-29

2007-08-24

Pequeña alegría

Es bueno cuando el universo confirma algunas cosas, como que ruby es "1337".

Esto apareció hoy cuando miré mi gmail a la mañana:

2007-07-24

Una nación avanzada

Ayer a la noche caí que el partido de Lavagna tiene un acrónimo
recursivo. Siguiendo la tradición informática de "Joe's own editor",
"Sine is not emacs", "LAME Ain't an MP3 Encoder", "Wine Is Not an
Emulator" y "GNU's not UNIX", se viene "Una Nación Avanzada".

¿Lo habrán hecho apropósito?

¿Están buscando el voto nerd?

2007-07-07

Nitro

Como algunos de ustedes saben (y otros no), a mi me gusta Ruby como lenguaje de programación. Y, aparte, se me ocurrió (de nuevo) una idea para hacer una página web y llenarme de $$$$. Por supuesto que no les voy a contar la idea ;), porque no me gusta programar apurado.

Pero rails no me termina de gustar. Es medio fascista, como python. Tiene un montón de cosas que están buenas, como python, pero no me gusta que sea tan estructurado, como python. Tampoco me da hacerla en PHP (eso sí que es feo). Y como es algo que hago porque tengo ganas y con mis propios tiempos decidí probar algo nuevo. Así que me puse a revisar un framework web que viene creciendo hace rato, a la sombra de Rails.

El framework se llama nitro y en gems va por la versión 0.43 (o sea, tiene 43 releases, creo). Como hace 6 meses que no releasean nada, pero están laburando a full decidí agarrar la última versión del repositorio de desarrollo. Así que me instalé darcs e hice un "get" del repositorio. Después de un rato, encontrar un bug, reportarlo y que lo arreglen y con ayuda por IRC de uno de los tipos que lo desarrollan, hice andar el ejemplo que viene con nitro, un blog.

Por lo que estuve leyendo, el framework es más desestructurado que rails y te deja poner las cosas donde quieras y aparte el mapping relacional-objeto que tienen es copado (googleen "ruby og").

Les cuento que las gems de las que depende son: facets, xml-simple, RedCloth y uuidtools.

Bueno, por último les dejo algunos links:
* http://www.arnebrasseur.net/2007/07/01/the-daily-nitro/en/ (explica como "setupear" nitro para hacerlo funcar y de que gems depende, aunque les faltó incluir una dependencia, uuidtools)
* http://rubyforge.org/pipermail/nitro-general/2006-August/005832.html (en el medio del post explica cómo agarrar nitro del repositorio darcs en el que está la última versión "oficial").
* http://www.nitroproject.org/ (home page de nitro, todavía no está terminada).
* http://oxyliquit.de/ (site con tutoriales y preguntas y respuestas sobre nitro y og).
* http://blog.interlinked.org/tutorials/darcs.html (tutorial sobre como usar darcs).

Eso es todo amigos, me voy a hacer lo que todo geek que se precie hace un sábado a la noche, programar.

Aureliano.

2007-06-11

Charla de metaprogramación en Ruby

El viernes pasado di una charla de metaprogramación en Ruby en mi laburo. La misma duró algo así como una hora y media y me faltó mostrar algunas cosas (tenía que tardar una hora) y estuvo interesante (creo). Una hora y media a puro irb, sin slides y casi sin usar el pizarrón.

Acá pongo la planificación de la misma y algunos comentarios:

A continuación está la preparación de la charla:

Historia
Creado por Yukiro Matsumoto (AKA:Matz) en 1994 porque Perl no soportaba Kanji (encoding japonés). Se usó solo en Japón hasta que en el 2000 se publicó el libro: "Programming Ruby", primer libro de Ruby en inglés. Después lo agarró DHH e hizo Rails y se hizo famoso.

Comparaciones
Ruby tiene muchas de las cosas buenas de Perl, como soporte nativo con sintaxis propia para regex.
/\d+(\.\d+)?/ reconoce números (por ejemplo). Y como a Matz le gustaba Smalltalk, todo es un objeto.
También, como en Smalltalk, hay metaclases, las clases son objetos, todas las variables son referencias (no hay tipos primitivos) y se pueden pasar closures a los métodos.

Hands on
(las líneas que empiezan con >> las tipeo en el irb, las que empiezan con => son lo que escribe el irb solo, las que están en corchetes las pongo en un archivo)
En ruby podés hacer cuentas:

>> 1+1
=> 2

asignar a variables, usar strings:

>> var = "hola"
=> "hola"
>> var
=> "hola"

usar expresiones regulares para hacer cosas:

>> "5 mas 95 es 100".gsub( /\d+/, "numerito" )
=> "numerito mas numerito es numerito"

tambien hay una cosa que se llaman símbolos (que son como los símbolos de Lisp) y se escriben así:

>> :mi_simbolo

a muchos objectos (incluidos los simbolos) les puedo pedir que se muestren como strings:

>> :mi_simbolo.to_s
=> "mi_simbolo"

la diferencia entre los símbolos y los strings es que puede haber muchos strings con el
mismo texto pero solo un symbol con ese texto (object_id es un número único del objecto,
o sea que si dos objectos tienen el mismo número son el mismo objeto):

>> :mi_simbolo.object_id
=> 359538
>> :mi_simbolo.object_id
=> 359538

el object id es el mismo.

>> "mi_simbolo".object_id
=> 24163140
>> "mi_simbolo".object_id
=> 24160510

el object id es distinto.

También, como en Perl, hay interpolación de strings

>> "1 mas 1 es #{1+1}"
=> "1 mas 1 es 2"

Y como lo que devuelve es un string posta:

>> "1 mas 1 es #{1+1}".gsub( /\d+/, "numerito" )
=> "numerito mas numerito es numerito"

podés aplicarle todas las operaciones de string.

Arrays:

>> [1,2,3]
=> [1, 2, 3]

Hashes:

>> h = { :a => "aa", :b => "bb" }
=> {:b=>"bb", :a=>"aa"}
>> h[:a]
=> "aa"

Bueno ahora vamos a definir una clase. Edito en el gvim:

[
class A
def initialize( param )
puts "Inicializando A con #{param}"
@inst_var = param
end

def hace_algo( param )
"#{@inst_var} #{param}"
end
end
]

mostrar que no tengo que pasar self como en python
y uso la clase en el irb (después de cargarla):

>> a = A.new( "toto" )
Inicializando A con toto
=> #

esto guarda "toto" en la variable de instancia

>> a.hace_algo( "parametro" )
=> "toto parametro"

y acá lo muestra.

La herencia es herencia simple igual a otros lenguajes, así que no la muestro.

Otra cosa medianamente distintiva de Ruby es el uso de módulos como mixin:
Mostrar todos los métodos de instancia que tienen "algo" en su nombre:

>> A.instance_methods.select { |m| m.include? "algo" }
=> ["hace_algo"]

escribo en un archivo:

[
module M
def otro_algo( param )
"otro " + hace_algo( param )
end
end
]

lo cargo y después:

>> class A; include M; end
=> A

eso pone los métodos definidos en M en la clase A

>> A.instance_methods.select { |m| m.include? "algo" }
=> ["hace_algo", "otro_algo"]

Esto inclusive modifica a los métodos de las instancias vivas:

>> a.methods.select { |m| m.include? "algo" }
=> ["hace_algo", "otro_algo"]

Y los ejecuto para mostrar como llamar desde el módulo a la clase:

>> a.otro_algo( "aaaaaaaaaaa" )
=> "otro inicial aaaaaaaaaaa"

Como acaban de ver cuando hice el include, las clases de ruby son abiertas. Alguien se acuerda de VB? Algo que siempre me gustó es que en vez de escribir "self" o "this" usamos "me".

Abro un archivo y escribo:

[
class Object
def me
self
end
end
]

Lo cargo (load ....) y lo uso:

>> me
=> main
>> me.class
=> Object

También lo puedo usar dentro de otras clases:

>> class A; def klass; me.class; end; end
=> nil
>> a.klass
=> A

Otro feature interesante es el de los bloques de código (AKA: closures)
Ya vimos un ejemplo del uso cuando miramos los nombres de los métodos definidos en A y a.
Mirando un toque más en detalle:

>> [1,2,3,4,5].each { |n| puts "Numero #{n}" }
Numero 1
Numero 2
Numero 3
Numero 4
Numero 5
=> [1, 2, 3, 4, 5]

También puedo hacer mis propios métodos que reciban bloques de código, recordando que las clases son abiertas, modifico Integer para iterar. (Acá nos desviamos un toque de la planificación y mostramos también como usar parámetros del método definido dentro del closure. Dejo la planificación original):

>> class Integer; def veces( &block ); (1..self).each { |n| block[n] }; me; end; end
=> nil
>> 3.veces{ |n| puts n }
1
2
3
=> 3

Los métodos se pueden definir en clases y en objetos, por ejemplo:

>> b = [1,2,3,4,5,6]
=> [1, 2, 3, 4, 5, 6]
>> def b.sarasa(toto); "sarasa #{toto}";end
=> nil
>> b.sarasa
ArgumentError: wrong number of arguments (0 for 1)
from (irb):71:in `sarasa'
from (irb):71
from :0

(ups, me olvidé de pasarle el parámetro).

>> b.sarasa( "aaaaaaaaaaaa" )
=> "sarasa aaaaaaaaaaaa"

En ruby puedo definir properties "tipo Delphi" (o C#). Para esto, hay varios métodos
definidos en la clase Module. Acá muestro uno:

>> class A; attr_accessor :sarasa; end
=> nil
>> a.sarasa = "SARASASASA"
=> "SARASASASA"
>> a.sarasa
=> "SARASASASA"

Ahora bien, attr_accessor es un método del lenguaje (no una palabra reservada) así que voy
a implementarlo de nuevo.

[
class Module
def my_attr_accessor( symbol )
instance_var = "@#{symbol}"
define_method( symbol ) { instance_variable_get instance_var }
define_method( symbol.to_s + "=" ) { |value|
instance_variable_set instance_var, value }
end
end
]


Hago load y lo uso:

>> class A; my_attr_accessor :toto; end
=> #
>> a.toto = 5
=> 5
>> a.toto
=> 5

Salvo por cuestiones de performance my_attr_accessor (y que le falta funcionalidad) es equivalente
al original. Toda la funcionalidad se puede implementar, pero tardaría más y no tengo tiempo ni ganas.

También se pueden hacer métodos de clase que son solo para una clase específica, usando la metaclase.

>> class A; def self.klass_method; "klass_method";end;end
=> nil
>> class A; klass_method; end
=> "klass_method"
>> class B; klass_method; end
NameError: undefined local variable or method `klass_method' for B:Class
from (irb):75
from :0

Notar que lo que hice es definir un método para una sola instancia de la clase Class.

>> class C < A; klass_method; end
=> "klass_method"

También vale para las clases que heredan de la misma. Esto es lo que hacen en Rails para poder hacer:

class Entity < ActiveRecord::Base
has_many :other_entity
end

Como en Smalltalk, se puede hacer override de method_missing para hacer proxies dinámicos y esas cosas (en la charla tuve que saltear esta parte porque venía atrasado de tiempo, así que se perdieron mi DSL de diálogos de pelis porno):

[
class A
def method_missing( method_id, *args, &block )
action = "action_#{method_id}"
(respond_to? action) ? send(action) : super( method_id,*args, &block )
end

def action_a
puts "AAAAAAhhhh"
end

def action_o
puts "OOooohhhh"
end
end
]

Y lo uso:

>> load "bdlv.rb"
=> true
>> a.a
AAAAAAhhhh
=> nil
>> a.o
OOooohhhh
=> nil
>> a.metodo_que_no_existe
NoMethodError: undefined method `metodo_que_no_existe' for #
from ./bdlv.rb:17:in `method_missing'
from (irb):107
from :0


Por último, mostré markaby:

>> require 'markaby'
=> true
>> mab = Markaby::Builder.new
=> #<Markaby::Builder:0x2ef2160 @auto_validation=true, @assigns={}, @output_meta
_tag=true, @builder=<inspect/>, @indent=0, @streams=[["<inspect", "/", ">"]], @h
elpers=nil, @tagset=Markaby::XHTMLTransitional, @output_xml_instruction=true, @o
utput_helpers=true, @elements={}>

>> mab.html do
?> head { title "Core se la banca" }
>> body do
?> h1 "Productos de Core"
>> ul do
?> li "Sarasa $500000000"
>> li "Sarasa2 $100000000"
>> li "Consulting priceless"
>> end
>> end
>> end
=> "<html><head><meta content=\"text/html; charset=utf-8\" http-equiv=\"Content-
Type\"/><title>Core se la banca</title></head><body><h1>Productos de Core</h1><u
l><li>Sarasa $500000000</li><li>Sarasa2 $100000000\n</li><li>Consulti
ng priceless</li></ul></body></html>"

Notar que es código ruby! Por ejemplo, puedo iterar:

>> mab = Markaby::Builder.new
=> #<Markaby::Builder:0x2ecec9c @auto_validation=true, @assigns={}, @output_meta
_tag=true, @builder=<inspect/>, @indent=0, @streams=[["<inspect", "/", ">"]], @h
elpers=nil, @tagset=Markaby::XHTMLTransitional, @output_xml_instruction=true, @o
utput_helpers=true, @elements={}>
>> mab.html {
?> body {
?> ul {
?> [ "Sarasa $500000", "Sarasa2 $100000", "Consulting priceless" ].each do
?> |item| li item
>> end
>> }
>> }
>> }
=> "<html><body><ul><li>Sarasa $500000</li><li>Sarasa2 $100000</li><li>Co
nsulting priceless</li></ul></body></html>"


Por supuesto, este html es básico pero esto es CÓDIGO. Por ejemplo, haciendo un form:

>> mab.html { body { form( :target => "http://sarasa" ) { input( :type => :submit ) } } }
=> "<html><body><form target="http://sarasa"><input type="submit"/></form></body></html>"


También mostré como yapa el ejemplo del tutorial de rake.

Y me faltó el ejemplo de como manipular Excel, pero lo dejo acá:

require 'win32ole'
# -4100 is the value for the Excel constant xl3DColumn.
ChartTypeVal = -4100;

# Creates OLE object to Excel
excel = WIN32OLE.new("excel.application")

# Create and rotate the chart

excel['Visible'] = TRUE;
workbook = excel.Workbooks.Add();
excel.Range("a1")['Value'] = 3;
excel.Range("a2")['Value'] = 2;
excel.Range("a3")['Value'] = 1;
excel.Range("a1:a3").Select();
excelchart = workbook.Charts.Add();
excelchart['Type'] = ChartTypeVal;

30.step(180, 10) do |rot|
excelchart['Rotation'] = rot
end

excelchart2 = workbook.Charts.Add();
excelchart3 = workbook.Charts.Add();

charts = workbook.Charts
charts.each { |i| puts i }

excel.ActiveWorkbook.Close(0);
excel.Quit();

2007-04-17

Mirando el largo plazo

Encontré este comentario en slashdot que me pareció buenísimo, así que quería compartirlo. Lo que leerán a continuación es mi traducción del mismo.


Las características que nuestra sociedad capitalista premia (la excelencia en algunos campos da una gran riqueza y la competencia en ciertas habilidades en el trato interpersonal son más importantes que la competencia en cuestiones técnicas, etc.) son, aparentemente, lo que queremos como sociedad. Si la paga es mejor, la oferta debería incrementar. Sin embargo, las cosas que están correlacionadas con una mayor tasa de nacimientos son: religión (más => más hijos), región del país, etc. Características que están negativamente correlacionadas son educación (una mayor educación, especialmente para las mujeres, reduce la natalidad), ingreso, etc.

Aún más interesante es el nivel de diversidad genética. Los más despreciados por la gente que destaca los valores "familiares" (madre soltera con muchos hijos de diferentes padres) son los que generan más diversidad genética. Caballeros como K-Fed producen múltiple descendencia con múltiples mujeres, asegurando la diversidad genética de su prole.

Esto es interesante porque después de varias generaciones con decreciente religiosidad, creciente educación y gente sana viviendo más, parece que estas mismas fuerzas biológicas están achicando estas características. Hace unos años salió un divertido editorial sugiriendo que Roe vs. Wade destruyó el partido demócrata (N. de A.: de EEUU) no porque los abortos fueran impopulares sino por todo lo contrario. Debido a la alta correlación de la opinión política de la gente con la de sus padres, y la correlación entre ser demócrata con abortar (es 2 o 3 veces más probable tener un aborto si la mujer es demócrata que si es republicana), hacen que 18 años después de Roe vs. Wade haya una reducción en el pool genétcio de los demócratas.

También, las mayores tasas de natalidad de los fundamentalistas de todas las religiones está causando una lenta regresión de las reformas y cambios de la "post-iluminación" en las comunidades religiosas. Las "iglesias protestantes tradicionales" están perdiendo gente, los católicos se mantienen, pero el crecimiento es en Sudamérica y Africa (N. de A.: espero que no tenga razón) mientras que su presencia en Europa se achica y los católicos americanos son porcentualmente cada vez más latinos, en el judaísmo está creciendo su ala ortodoxa (desde el 8% hace 20 años hasta el 15% ahora) que se está tirando a la derecha y las tasas de crecimiento de los musulmanes están ganándoles a todo lo demás.

Basicamente, nuestra cultura secular ateísta encontró tal grado de autoindulgencia y libertad que puede llegar a achicarse a si misma. La izquierda norteamericana constantemente acusa a Bush pero los cambios culturales en EEUU muestran que la demografía, y no la demagogia, es lo que causa este empuej político reaccionario.

Es sumamente interesante, pero yo lo encuentro en más alto grado de ironía (N. de A.: yo también), que las alas "bíblicas" "anti-evolucionarias" de todas las religiones, que eran marginales hace una generación, de golpe están ganando, mientras que las seculares, culturalmente basadas en la ciencia y la razón, están en retirada. Y la razón es que la gente "anti-evolucionaria" está exparciendo su material genético y haciendo crías para hacer avanzar su agenda, y la gente pro-ciencia pro-evolución está acotando su material genético con familias de 0 a 2 hijos.

De hecho, más molesto es que los hombres que se manejan de las forma socialmente más irresponsable -- engaños permanentes, divorcio, etc., generalmente son padres de muchos más niños que aquellos que "juegan respetando las reglas". Así que si el material genético influencia el comportamiento, vamos a encontrar que cada generación es un poquito más adúltera.....

Si está tendencia continúa, que por supuesto no va a pasar, las cosas se vana ir para el otro lado, pero ironicamente en 4 o 5 generaciones, vamos a tener una población general no-blanca, muy religiosa que va a la iglesia/sinagoga/mesquita regularmente mientras tienen relaciones adúlteras durante la semana.

:) Pero seriamente, ¿piensan que la derecha religiosa es mala ahora? En 50 o 60 años, si siguen duplicando en su tasa de natalidad al EEUU secular... van a ser la mayoría.

Divertidas observaciones demográficas amateurs...
Alex



A mi me asusta que no veo ningún motivo para pensar que esto no pueda ser así. Como la gente que me conoce sabe, me preocupa mucho más el crecimiento demográfico de los religiosos que de los adúlteros. ¿Estamos por entrar en otra Edad Media? ¿Nos salvarán los adúlteros? ¿Cómo evitarían este futuro?

2007-03-12

Experiencias con GMail

Hace unas semanas que estoy usando GMail como mi mail de cabecera. Este es el balance que hago del mismo.

Cosas buenas:

  • Siempre anduvo y rápido
  • Tags (AKA: labels)
  • Las conversations (están buenísimas para dar contexto a los mails).
  • Me gusta usar el search para los mails (de hecho ya lo hacía de antes).
Cosas malas:
  • No puedo abrir tabs en el Firefox con los mails (clickear un mail con el botón del medio del mouse no sirve para nada).
  • No hay API para manejar GMail.
  • La versión no-ajaxificada está incompleta y no se pueden agregar filtros ni tags nuevos.
En particular, los últimos 2 puntos hicieron imposible hacer un programita para traer los mails que tengo en Yahoo y ponerles etiquetas para matchear con las carpetas en las que tengo los mails clasificados allá. De hecho, con la rubygem que usaría para acceder a GMail (gmailer) no me anduvo crear tags nuevos (al menos cuando la probé desde el irb). Y, la verdad, no veo como hacer screen scrapping de la versión con AJAX de GMail.

Ya sé que puedo importar los mails por POP3, pero cuando tenés como 5000 mails, es mejor mantener la clasificación de los mismos. Igualmente, probar el traspaso de mails de Yahoo a GMail (que quedó abortado) sirvió para que aprenda a mandar mails con attachments y acentos en ruby via SMTP.

2007-03-09

Auto retrato technicolor


Solo lápices de colores. Nada de edición por computadora.

Auto retrato

Resultado del curso de dibujo

El martes pasado terminé el curso de dibujo que hice en la Academia Da Vinci. Tuve la suerte de tener unos compañeros copados y muy talentosos y un muy buen profesor. Ahí aprendí que es una paleta, algunos efectos ópticos que se generan con los colores (por ejemplo, en una imagen parece que los colores cálidos, como el rojo, están más adelante que los colores fríos, como el azul). Como centrar un dibujo, y varios etcéteras, todos muy interesantes.

Pero lo más importante es que estoy empezando (muy de a poco) a ver algunas cosas de otra manera. Empecé a ver como se combinan los colores, que paleta usaría para pintar las cosas, cuando algo está sin equilibrio, etcétera. Igual este es el primer paso de una maratón, así que no esperen que me vuelva en un artista plástico en 5".

Por último les muestro el resultado práctico del curso:

2007-03-07

Compositor de colores

Para los insensibles del color, como yo, les comento de una página web que está re-buena. En http://www.colorsontheweb.com/ tiene una compositor de colores. Le das el color base y te arma las paletas (monocromático, complementario, tríadas, etc.).

¡Una masa!

Encontré esta página mirando esta entrada de blog: http://www.glanzani.com.ar/?p=132

Enjoy!
Aureliano.

2007-03-05

Business card

Aprovecho el blog para hacerles una consulta,
Estoy considerando hacerme a mano las tarjetas para repartir en eventos. Mi idea es hacerlas en rojo, azul y amarillo con lápices aquarelables. Me pareció que le darían una onda más "tierna" y que se destacarían del resto. Pero no sé si quedarían mal. Así que escucho sus opiniones.

Así que las opciones que se me ocurren son:
1) Es la mejor idea que haya escuchado, voy a hacerlo yo también.
2) Puede ser que esté bueno.
3) Me parece medio tonto.
4) Das una imagen poco profesional.
5) Yo no contrataría a alguien que hace sus tarjetas así ni por casualidad.
6) Va a parecer que torturás una familia de niños tailandeses para hacer hacer tus tarjetas (y eso sólo está bien para las zapatillas).

Los escucho atentamente,
Aureliano.

2007-03-04

Me pasé a GMail

Les cuento que mi nueva dirección de correo es aurelianocalvo at gmail.com. La dirección de Yahoo está forwardeada a la nueva, así que por el momento si me mandan mails a Yahoo los seguiré viendo (aunque con una pequeña demora).

El motivo del pase es que Yahoo! estuvo inestable como 3 días seguidos y no podía acceder a mi mail. Ahora me voy a tener que adaptar a usar labels en vez de folders (en ppio no parece malo).

Éxitos,
Aureliano.

2007-02-19

Jugando con greasemonkey

Estuve probando un plugin re-groso para Firefox que se llama greasemonkey. El mismo permite ejecutar JavaScript arbitrario después de que se cargue cada página.

Usandolo, hice un pequeño script para sacar la molesta propaganda que ponen en el nuevo Yahoo Mail Beta. El script tiene 10 líneas y lo puse acá. Pero para que no tengan que cliquear, se los posteo acá mismo.


// ==UserScript==
// @name Yahoo Beta Ads Blocker
// @namespace http://mywebsite.com/myscripts
// @description Yahoo Beta Ads Blocker
// @include *.mail.yahoo.com
// ==/UserScript==

function $(id) {
return document.getElementById(id);
}

function remove(id) {
var elem = $(id)
if (elem) {
elem.parentNode.removeChild(elem)
}
}

window.addEventListener(
'load',
function() {
remove('largePane')
remove('emptyFolderFrame')
remove('nwPane')
remove('swPane')
},
true
);


Enjoy!
Aureliano.

Si quieren ver más detalles sobre el greasemonkey vayan a http://greasemonkey.mozdev.org/

2007-02-16

Los lenguajes de la web

Para programar páginas web hay que aprender unas cuantas cosas. En particular es llamativa la cantidad de lenguajes que hay que aprender:

  1. HTML
  2. JavaScript
  3. CSS
  4. XML
  5. XPath
  6. CSS selectors
  7. Javascript
  8. Lenguaje y bibliotecas server side de tu preferencia (Ruby on Rails, PHP, Perl, Java, JSP, EJBs, ASP.NET, etc)
  9. SQL?
Sin embargo, la mayoría de estas cosas son carga cognitiva al dope. Es mi opinión que el desarrollo web se simplificaría bastante ordenando este quilombo.

En primer lugar, en vez de usar HTML, se podría usar una biblioteca en JavaScript para generarlo (algo como markaby pero hecho en JavaScript). Esto haría que sea más fácil generar dinamismo en el cliente.

Los CSSs deberían ser una biblioteca que encaja con la biblioteca anterior. Si quieren separar los datos para que los maneje un diseñador, podría perfectamente usarse JSON.

El XML es 100% reemplazable por JSON (que, es más lindo para escribir datos y todo). JSON (y javascript) es lo que usan varias bibliotecas de AJAX (ATLAS, prototype) para comunicar cambios en la página.

XPath puede llegar a ser algo práctico, pero solamente para navegar por árboles de objectos (no XML). Quizás una biblioteca para buscar cosas en JSON con sintáxis parecida estaría buena.

Los CSS selectors son una creación abominable. No aportan nada al XPATH, pero como están en los archivos de estilo, no queda otra que usarlos.

Con respecto al server, estoy esperando que alguien haga JavaScript on Rails (la capacidad de metaprogramación está ahí) y lo enchufe con algún intérprete de Javascript. "¿Harías Rails en el cliente?", se preguntarán. Nop. La idea es usar el mismo lenguaje en el cliente y en el server. Netscape lo intentó hace un tiempo pero se le acabo la plata. El mundo sería mejor si Sun hubiera apoyado esto en vez de impulsar Java a diestra y siniestra. Tener el mismo lenguaje en cliente y server permitiría hacer algunas cosas que ahora no se puede, como compartir el código de validación formato de los datos entre cliente y server sin repetir nada.

Y, por último, SQL es lo que intentamos sacarnos desde hace años de encima. Cada ORM (Hibernate, ActiveRecord) que hay es un intento fallido para escaparle.

¿Y por qué no lo ven así? Lo que hay que darse cuenta es que programar una página web dinámica es un ejercicio de metaprogramación. Un escribe un programa (que está en el server) que cuando se ejecuta genera un programa que se transmite al cliente (HTML + Javascript + CSS, etc) que cuando se ejecuta se renderea y muestra la página. Cuando se hace AJAX, en realidad hacés un hot fix en un sistema productivo. El resultado de una llamada AJAX son instrucciones de como cambiar el programa que está corriendo.

Pensado de esta manera, es razonable ver que conviene unir lenguajes en uno solo. JavaScript, a pesar de no ser mi lenguaje favorito (que es Ruby), para mi tiene todas las de ganar.

Tiene:
  • Soporte en el cliente.
  • Es conocido por los desarrolladores de páginas web.
  • Es razonablemente metaprogramable.
Para mi, el mayor problema es que para pasar cachos de código hay que escribir demasiado. Un bloque de código, pasado a una función, se ve así:
foo( c, function(a, b) { return a+b })


En cambio, el mismo código en Ruby es:
foo(c) { |a,b| a+b }


De todas maneras, JavaScript ya está por todos lados y es razonablemente bueno. Lo más importante es que tiene soporte en el cliente, que es la parte más dificil de cambiar en una página web. Si no me creen, traten de hacer páginas que anden solamente en FireFox y diganles a sus usuarios que se lo instalen.

Por último, quería agradecerle a frinfrunfranfrun haberse bancado chatear conmigo de este tema, lo que hizo que me caiga la ficha sobre que escribir.

Éxitos,
Aureliano.

2007-02-15

Si no puedes con ellos, úneteles

En una nota anterior, dije que había demasiados egresados de la Escuela da Vinci. Bueno, mañana empiezo un curso de dibujo allí mismo.

Espero poder contrarrestar mi falta de sensibilidad estética, y poder hacer programas (y/o páginas web) que no sean muy fe@s, sin ayuda de un diseñador. Sip, sólo no muy fe@s, hacer cosas lindas es realmente difícil y se los dejo a ellos.

Aureliano.

2007-02-14

Xara Extreme

Hoy estuve probando el editor vectorial de imágenes para Linux Xara (está en http://www.xaraxtreme.org/). Y me gustó. Está por la versión 0.7 y es un port de un programa de Windows. Aunque tiene algunos bugs, ya está usable y ¡estuve haciendo un dibujo!.

Les presento al "Señor Destapador":


¿Sugieren algún otro programa para reemplazar al Illustrator en Linux?

Aureliano.

PD: pueden usar esa imagen como quieran mientras me atribuyan la creación de la misma.

2007-02-13

Se termina kinesio

Si dios, la patria y los santos evangelios están conmigo; me quedan solamente 9 sesiones de kinesiología para la rodilla. Pero todavía no terminé :-(. Ahora me toca ir a un gimnasio a hacer pesas. Pesas y natación.

Tengo por lo menos 45 días de pesas. Aparentemente, todavía no tengo suficiente fuerza en el cuádriceps para que me den el alta. Se supone que puedo volver a las canchas (de paddle) en 2 meses, si no hay inconvenientes.

Éxitos,
Aureliano.

2007-02-05

Filtrado en el MSN

Están filtrando el envío de algunos URLs en MSN.

Acabo de confirmar que el URL http://www.scribemedia.org/2006/07/09/dhh/ ¡genera que la conexión del MSN se cierre! Parece que decidieron que Rails es competencia y lo empezaron a boicotear.

La verdad es que no me arrepiento en lo más mínimo de haber instalado KUbuntu en casa.

Saquen sus propias conclusiones,
Aureliano.

Update: en realidad parece que no dejan pasar mensajes que contengan el string ".scr" para evitar virus! ¡Qué patético!

2007-02-01

Maldito flash

Anteayer a la noche fuimos con Agustina a cenar a la casa de un amigo. Como nos tocó llevar el postre, hacía calor, Agus estuvo ocupada con un proyecto laboral, y yo tenía rehabilitación (de la rodilla, ¡malpensados!), decidimos comprar helado.
Entonces nos pusimos a buscar las heladerías en Google. Googleamos "sucursales Freddo" y nada. Googleamos "sucursales Persicco" y nada. Googleamos "sucursales Munchis" y nada.
¡Que raro! ¿Cómo puede ser?
¿No tendrán página web?
El problema es que hay demasiados egresados de la Escuela Da Vinci por ahí haciendo páginas web. Y hacen todo en Flash. Por lo tanto no podés linkear adentro de la página. Y aparte google no los indexa.

¡Basta de páginas web hechas en flash!

¡Quiero un google que ande!

¡Quiero mi helado!


Skip intro,
Aureliano.

2007-01-30

Carpetas _svn y radrails

La versión 1.0.3 de subclipse no se banca carpetas administrativas de svn con _svn. Pero la versión 1.0.4 sí. El problema es que RadRails (que es la customización de eclipse para programar sitios web con rails) viene con la versión 1.0.3.

Así que intenté hacer Help -> Update RadRails. Pero me dio un mensaje de error: RadRails (0.7.2) requires plug-in "org.eclipse.core.runtime (2.1.0)", or later version.

Buscando en la net no encontré ninguna solución fácil a este problema, así que me mandé a mirar como está armado RadRails y toqué un descriptor de eclipse para que no me de más ese error. Eclipse está compuesto por "features" que tienen "plugins". Y la configuración de RadRails exige en un feature que sea mejor o igual que otro, como indica el error.

Navegando un toque por los descriptores de las features encontré un candidato. En la línea 234 del archivo RadRails\feature\org.radrails.feature_0.7.2\feature.xml dice:

<import plugin="org.eclipse.core.runtime" version="2.1.0" match="greaterOrEqual">

Lo cambié a <import plugin="org.eclipse.core.runtime"> y Help -> Update RadRails empezó a funcar. Hice update, instalé subclipse 1.0.4 y listo el pollo.

Bueno, ahora tengo soporte para svn en RadRails 0.7.2 en Windows :D.

2007-01-21

Usos de la comida en el lunfardo para describir gente

Update: Gracias a Mariano, Diego, Anónimo y Florencia por sus aportes.

Estabamos charlando con mi mujer y encontramos que un montón de comida se usa en el lunfardo porteño para describir gente. He aquí algunas de ellas:

  • Banana: Piola, pero en forma despectiva. Uso: "Te pensás que sos re-banana por hacer esa boludez, ¿no?"
  • Papa frita: Tonto. Uso: "Sos un papa frita, ¿cómo vas a dejar el auto sin cerrar?".
  • Nabo: Tonto. Uso: "Flor de nabo resultaste vos, eh!"
  • Dulce: Tierno. Uso: "Mirá que dulce que es mi novio, me trajo flores"
  • Bombón: Linda. Uso: "Tu hermanita está hecha un bombón"
  • Maestra ciruela: Que explica cosas sin que le pidas. Uso: "Tu tía es una maestra ciruela"
  • Flan: Flojo. Uso: "Sos un flan".
  • Zanahoria: Tonto. Uso: "Flor de zanahoria resultaste"
  • Perejil: Gil. Uso: "Al final se la daba de re-banana y resultó un perejil"
  • Panqueque: que se da vuelta facilmente. Uso: "José se dio vuelta como un panqueque y nos cagó"
  • Ñoqui: que no labura pero va a cobrar. Uso: "Todos se quejan de los ñoquis pero quieren ser uno de ellos"
  • Salame: tonto. Uso: "Sos un salame"
  • Salamín: tonto (pero en forma cariñosa). Uso: "Salamín, el control remoto usa 2 pilas, no una".
  • Queso: que no juega bien al fútbol. Uso: "Aureliano es un queso"
  • Zapallo: Tonto. "Sos un zapallo"
  • Caramelito: Dulce, linda. "Tu hermana es un caramelito"
  • Radicheta: que pertenece a la Unión Cívica Radical. Uso: "Los radichetas ya no existen"
  • Pavo: Tonto. Uso: "Tu hermano es un pavo"
  • Vaca: gorda. Uso: "Susana es una vaca"
  • Pescado: tonto. Uso: "Sos un pescado"
  • Gallina: cagón. Uso: "Arrugaste, gallina". Hincha de River. Uso: "Los gallinas son todos gallinas".
  • Lechón: gordo. Uso: "Estás hecho un lechón"
  • Cerdo: gordo. Uso: "Estás hecho un gordo". Asqueroso. Uso: "Sos un cerdo"
  • Puerco: asqueroso. Uso: "Sos un puerco".
  • Torta: lesbiana. Uso: "Tu hermana es una torta"
  • Tortilla: lesbiana. Uso: "Tu hermana es una tortilla"
  • Vinagre: amargo/a, caraculico/a, malcogida. Uso: "La señorita Adriana es un vinagre"
  • Pancho: perezoso / tonto. Uso: "Dale, venite.. no seas pancho (perezoso) / Dale pancho, no ves que estás tirando todo al piso?!"
  • Chorizo: ladron. Uso: "Es un chorizo"
  • Limon: limado / quemado. Uso: "Dale limón! Rescatate!"
  • Manteca: flojo. Uso: "Eehh.. sos un mantequita al final vos, eh?"
  • Churro: pintón / fachero. Uso: "Es un churro bárbaro". porro. Uso: "Ese churro se fumó un churro y quedó de la cabeza"
  • Durazno: Duro / Que le cuesta razonar, aprender, etc. Uso: "Uff.. A este boludo le tengo que dedicar mas tiempo para enseñarle porque es medio durazno".
  • Bagre: Fea. Uso: "Esa mina es un bagre"
  • Papa: Jefe de la Iglesia Católica. Uso: "El Papa tiene cara de malo".
  • Batata: Que anda muy despacio. Uso: "Tu auto es una batata".
  • Tomate, del: loco. Uso: "Ahora sí quedo claro que Aureliano está del tomate".
  • Choclo: persona que tiene acne Uso, "que bagre mas feo es un choclo"
¿Se les ocurre algo más?

2006-10-29

Génesis de los requerimientos


En el primer día


El cliente separa lo que quiere de lo que no quiere, explicando sus requerimientos de negocio, y ve que son buenos.

En el segundo día


El cliente (con ayuda de un analista, probablemente) explicita en forma de "Epics" sus requerimientos. Un "epic" es un título para un montonazo de laburo (por ejemplo: "Quiero mostrar información de todos los países del mundo"). Los "epics" serán lo que respiremos y tomemos el resto de nuestra jornada.

En el tercer día


Separamos los "epics" en "user stories". Una "user story" es algo que se puede hacer en 2 días o menos y que tiene un título de la forma "Como [rol] quiero [feature] para [razón de negocio]". Navegaremos y caminaremos por los user stories hasta llegar al final, empezando por la reunión de planificación del sprint.

En el cuarto día


Durante la reunión de planificación establecemos que cosas hay que hacer para decir que implementamos una user story y lo anotamos en la tarjetita correspondiente. Éstas son las estrellas que guiarán nuestro camino.

En el quinto día


Armamos los tests automáticos de aceptación, tomando como base los criterios de aceptación definidos ayer.

En el sexto día


Hacemos andar a los tests (uno a uno), implementando las funciones requeridas.

En el séptimo día


Descansamos.

Nota: Tanto en la biblia como acá, los días son separados así por razones didácticas. En la práctica, tanto dios como nosotros, hacemos un poquito de cada día todos los días.

2006-10-16

¿Aló?

Hola a todos,
quería saber quienes están leyendo el blog. Así que me gustaría que cuando lean este post, contesten y cuenten quienes son. Este pedido es para la gente que conozco y para la que no. También me gustaría que me cuenten que les gustó y que no del blog, si tienen ganas, y también algo de ustedes (esto último sobre todo si aparece alguien con quién no tengamos el gusto de conocernos).

Hasta la próxima,
Aureliano.

2006-10-15

Haciendo que internet arranque solo

Hoy configuré mi KUbuntu para que se conecte a internet al bootear via pppoe. Para eso tuve que deshabilitarle algunas cosas ya que antes se conectaba pero no resolvía bien el DNS (!).
Les cuento que hice:
Borre los links de nombre S14ppp de todos los directorios /etc/rc?.d
Edité el archivo /etc/network/interfaces y le saqué que levante automáticamente la interface de red que se levanta por pppoe. Para eso borré la línea auto dsl-provider.
En /etc/init.d creé el script ppp_aure (estoy creativo eh!) con el siguiente código:

#!/bin/sh -e
#
# /etc/init.d/ppp: start or stop PPP link.
#
# This configuration method is deprecated, please use /etc/network/interfaces.
. /lib/lsb/init-functions


case "$1" in
start)
log_begin_msg "Starting up PPP link..."
/usr/bin/pon dsl-provider
log_end_msg $?
;;
stop)
log_begin_msg "Shutting down PPP link..."
/usr/bin/poff
log_end_msg $?
;;
restart|force-reload)
log_begin_msg "Restarting PPP link..."
/usr/bin/poff
/usr/bin/pon dsl-provider
log_end_msg $?
;;
*)
log_success_msg "Usage: /etc/init.d/ppp {start|stop|restart|force-reload}"
exit 1
;;
esac

exit 0

Y por último linkié en /etc/rc2.d: sudo ln -s ../init.d/ppp_aure S97ppp_aure

Ahora no necesito arrancar internet a mano y soy feliz.

2006-10-06

Linux genuine advantage

Esta semana me puse a instalar Linux después de unos años de no hacerlo, ya que parece que ahora sí está usable al punto en el que mi mujer podría usarlo. Les cuento como fue todo esto.

Pedí por correo los CDs de instalación de KUbuntu, que se tomaron su tiempo pero vinieron y son gratis (sip, podría haber grabado un CD, pero me dio vagancia enchufar la grabadora de CDs). Después de tenerlos un par de semanas añejándose, decidí instalarlo.

Puse el CD en la compactera y anduvo bárbaro. Inclusive hasta me tomó una llave USB que le enchufé. Lo que sí fue medio pedorro fue el tema de la conexión ADSL.

La conexión de ADSL que tengo ahora anda por USB (ya que mi PC no tiene placa de red) y cuando bootié con el CD no se conectó a internet, lo cual es entendible porque no puse el usuario y password de la conexión. Lo que fue más complicado es ver como (|mierda|carajo|diantres) hacer para conectarlo y darle el usuario y password. En los menúes no estaba como conectarme a internet por ningún lado. Como estaba más perdido que monja con 2 porongas, lo llamé a un amigo linuxero para que me de soporte técnico.

Ernesto es un especialista, labura de administrador de red y hace años que usa Linux en su casa y el laburo y tiene andando la conexión por ADSL en linux también. Si quieren contratar un administrador de red, lo sugiero (y no solo porque sea mi amigo).

Así que con Ernesto al TE, empezó el troubble shooting. Después de media hora de trouble shooting, corriendo lsmod, ifconfig y ls /proc/bus/usb/devices llegamos a la conclusión que el modem ADSL lo detectó y solo faltaba configurar el pppoe. Pero en el menú gráfico de Kubuntu no hay nada para configurar el pppoe :(. Por suerte yo había estado buscando cosas en Internet sobre como conectarme con el modem y había instrucciones para otro modem que decían que para configurar pppoe en ubuntu hay que ejecutar pppoeconf. Lo ejecuté y anduvo, así que me decidí a instalar Kubuntu en el rígido.

Instalé KUbuntu y anduvo. Le hice una cuenta a mi mujer y anduvo. Instalé ruby, y los paquetes de apt-get para ruby son un asco. En vez de poner "apt-get install ruby" hay que poner "apt-get install ruby1.8 irb1.8 ri1.8 rubylib1.8 .....". Aparte están fuera del repo oficial de Ubuntu, por lo que hay que activar el repositorio "universe". Igualmente, después de 3 instalaciones (que incluyeron compilar ruby desde el tar.gz y borrarlo porque no encontraba zlib), logré tener irb, ri y gems, así que decidí que había terminado.

También instalé el kpilot y enchufé la Palm (una Zire 21), que la detectó al toque, pero me hizo mierda la base de datos:

  • Me borró todas las actividades con fechas (!)
  • Me hizo mierda todos los acentos y eñes de los contactos.
Y encima, cuando sincronicé en Windows de nuevo, me pasó la base de datos hecha mierda a Windows, o sea, la cagué.

Aunque logré configurar el teclado para que anden los acentos y las eñes, no pude lograr que aparezcan los signos de pregunta y admiración del principio de las oraciones, o sea "?" y "!" pero dados vuelta. Si alguien sabe, por favor que me diga.

Y por último, todavía no logré que internet se conecte solo, pero me le animo al init.d, así que es solo cuestión de tiempo. Aparte en Windows no se conecta solo tampoco, así que está parejo.

Bueno, resumiendo, instalando Linux logré:
  1. Irritar a mi mujer, que se queja que le doy más bola a la compu que a ella.
  2. Cagar la base de datos de la Palm
  3. Estar hablando una hora x TE con un amigo con el que no hablaba hace rato (esto estuvo bueno).
Pero voy a seguir intentando con Linux, porque entre el DRM, los virus y el Windows Genuine Advantage me están dando escalofríos. No quiero seguir regalando mi externalidad de red.

2006-09-25

Un tropezón no es

Caída. Así podría resumirse un movimiento que hice el viernes a la noche. Estaba la flia de mi mujer en casa porque fue el cumpleaños de mi suegra y como ella vive en un 1er. piso x escalera, yo no podía ir para allá. Cenamos, tomé un poquito de vino (no mucho, pero soy un blandito) y después quise mostrar habilidades con las muletas.

¡ERROR!

Después de pivotear una vez sobre cada muleta (no es tan difícil como suena), me olvidé que Amón (mi gato) estaba en el medio del living. Entonces, para no pisarlo, lo salte, pero quedé para caer con la pierna derecha, la operada. Pisé con la pierna derecha, no pude sostenerme y seguí de largo. Según los testigos presenciales, la pierna se puso a 90 grados, pero por suerte no se fue para el costado. Seguí hasta que las rodillas y mis brazos tocaron el piso y me dolió un poco. Pero no tanto porque había tomado un analgésico bastante fuerte 2 horas antes.
Hoy lunes fui a ver a un traumatólogo (no al mío porque está en un congreso) y lo que me dijo es que lo más probable es que no me haya pasado nada, pero que no se puede hacer una resonancia para chequear porque como me operaron recién no sale nada (bah, sale de todo y no es posible distinguir la carnicería que me hicieron de una posible nueva lesión). Igualmente, vengo evolucionando bien, así que lo más probable es que solo haya sido un susto

2006-09-24

Clases de CS del MIT

Con esto de que estoy con la pata rota, tuve tiempo para surfear la net un toque más. Y volví a ver el libro "Structure and Interpretations of Computer Programs". El libro es heavy metal y está buenísimo. También encontré los videos de las clases. Aunque son medio ochentosos, están bárbaros. No se dejen engañar por la cara de boludo del profesor. Mi sugerencia es que se bajen los videos y miren el libro acordemente.
Les paso los links:

También estoy poniendo los links interesantes sobre el tema en del.icio.us.
Es increíble que lo que enseñan ahí sea introductorio.

Enjoy!

2006-09-22

El postoperatorio

Como les conté anteriormente, me rompí los ligamentos y me operaron para poner 2 tendones que me sobraban en su lugar. Después de la operación, estas son las cosas que fueron aconteciendo:

  • Miércoles 13/9
    • Volví a casa
    • Almorcé y cené sentado a la mesa
  • Jueves 14/9
    • Me senté adelante de la compu por primera vez
  • Viernes 15/9
    • Hablé x TE por primera vez
  • Sábado 16/9
    • Me saqué la férula para dormir
  • Domingo 17/9
    • Escribí las entradas en el blog
    • Vinieron mis viejos a casa
  • Lunes 18/9
    • Fui a ver al médico, que dijo que está todo bien
    • Empecé a hacer ejercicios de rehabilitación
    • Empecé a laburar de nuevo (en casa)
  • Martes 19/9
    • Me saqué la férula para andar con muletas dentro de casa
    • Fui a pasear por el parque del edificio
  • Miércoles 20/9
    • Me bañé
    • Empecé a tomar analgésicos una vez por día
  • Jueves 21/9
    • Se me infló el pie.
    • Decidí no estar sentado o parado mucho tiempo seguido
Bueno, después les sigo contando. Me voy a descansar la pierna. Aureliano.

2006-09-17

Reconstrucción de ligamentos (parte 2)

Resumen del capítulo anterior



  • El ligamento cruzado anterior no se rompe a medias

  • Los anestesistas entran sin avisar a las habitaciones

  • A los camilleros les gusta pasearte en camilla por las clínicas

  • En el largo plazo, la cantidad de líquido que entra al cuerpo es la misma que la que sale


Cuando me levanto temprano a la mañana


Tomo unos mates y riego las plantas :P.
Después de echarme cloros cada hora y media, a las 7:00 AM decidí que estaba despierto y no me volví a dormir. Agustina se despertó al ratito, no recordando que la desperté cada 2 x 3 para mear (por suerte para los 2). Estaba:

  • Hambriento

  • Enchufado al suero a través de mi mano derecha

  • Con un coso enchufado a la rodilla para que salga sangre

  • Con las sábanas ensangrentadas

  • Con un piquete en el nervio femoral de la pierna derecha


Entonces prendimos la tele y nos pusimos a esperar el desayuno. El desayuno no apareció como por una hora :(. Tampoco apareció el médico, que me había dicho que iba a venir a las 8 AM para ver si me podía ir a la mañana o no. Alrededor de las 9 Agustina fue a reclamar por los desayunos (a ella le empezó a agarrar hambre también) y me trajeron el mío y le dieron un ticket para que tome el suyo en la confitería de la clínica. El desayuno fue el típico desayuno choto de hospital, o sea, lo que pensé que iba a ser. Un té con leche y unas galletitas de H20 con mermelada.

Pobre monjita


En la espera entró a la habitación una monja (!?). La monja, no sé porqué, vino a ver si estabamos bien y si no queríamos abortar (adivinen cuál de las 2). La verdad es que no la traté muy mal, pero tampoco le di mucha pelota. Cuando se dio cuenta que el crucifijo no estaba más en la pared huyó despavorida. Me parece que la abstinencia no le hace bien y se comporta de forma errática.

Esperando al dotor


A eso de las 10 nos empezamos a preocupar por el médico, así que Agus fue a buscar un TE para llamarlo (¿debería tener un celular?). Cuando logró comunicarse, el médico entró por la puerta de mi habitación (la 131). Sin un orden específico, llegó, me preguntó como estaba, me desenchufó del coso que drena la rodilla, firmó el alta, explicó como tenía que poner la rodilla en casa (levantada y derecha), me dijo que lo tengo que ir a ver el lunes (o sea mañana) y se fue.

La despedida


Como teníamos el alta, Agustina llamó a mi viejo para que nos venga a buscar. Mi viejo vino a los 15' e iniciamos los trámites para el alta. Me desenchufaron del suero y llamaron a un enfermero para que me paseen por toda la clínica, pero en silla de ruedas. El enfermero me llevó hasta el estacionamiento, mi viejo fue a buscar el Twingo y lo metió adentro del estacionamiento. El crucifijo de la habitación siguió adentro de un cajón de la misma.

Subiendo al auto


(Música de misión imposible)
"Suba a un auto de 2 puertas después de una cirujía reconstructiva en la rodilla"

Primero intenté sentarme en el asiento de adelante, pero no entré :(. Mi pierna derecha, estirada, no entraba en el espacio para las piernas. Así que me tuve que sentar atrás. Haciendo fuerza con mis brazos, mientras me tenían las piernas, fui escalando el asiento de atrás y deslizandome por él. Después de una leve taquicardia, logré sentarme, y por suerte así si entré (cagando). Y nos dirigimos a casa.

Bajando del auto


(Música de misión imposible, más fuerte)
Llegamos a casa, por primera vez tengo que usar las muletas (las usé antes, pero ahora es en serio). Entramos al edificio y vamos al estacionamiento subterráneo. Y empiezo a bajar del auto. So far, so good. Bajé del auto casi sin ayuda y me dirijo a la puerta del estacionamiento, que comunica con los ascensores.
¡Hay un escalón! No es muy grande, pero es un escalón al fin. Y la puerta es chiquita. ¿Cómo mierda paso con las muletas por ahí?

Miro a mi enemigo y lo enfrento. Conmigo está mi fiel esposa, mi viejo fue a poner el auto en otro lado. Estamos solos, desamparados ante un enemigo omnipotente, perenne, imponente. Después de meditarlo, decido enfrentar mi destino. Me posiciono de costado al lado del escalón, con el pie derecho junto al mismo. Error. Esa pierna está dormida e inmobilizada. Intento pasarla por arriba del escalón. Error. Esa pierna está dormida e inmobilizada. Giro 180 grados y encaro con la otra pierna. Pulsaciones: 180. Me apoyo en las muletas y subo al escalón con la pierna izquierda. ¡Gané! Ahora bajo el escalón (está solo para que no pase agua entre el pasillo y el estacionamiento. Hago los 6 metros hasta el ascensor y subo (ya volvió mi viejo). El camino incluye una barranca en subida (¡por suerte no hay escalones!). Llego al piso 10, y voy derecho a la cama. Sudado, con taquicardia, cansado, pero feliz. Ya estoy de vuelta en casa.

Colorín colorado


Así que estoy en casa desde el miércoles, inmobilizado. Agustina se está portando como una reina conmigo y me mima mucho. Estoy tomando analgésicos cada 12 horas así que salvo algunas puntaditas no me duele nada. El jueves se empezó a ir el bloqueo del femoral, pero no me dolió. A veces me molesta cuando estoy levantado mucho tiempo, así que tengo que ir con calma. Mañana voy al médico y vuelvo a programar, aunque con calma, no creo que sea bueno que esté mucho tiempo delante de la compu (como ahora :( ).

Conclusiones


Podría ser mucho peor todo esto.

Reconstrucción de ligamentos

El martes de la semana pasada me operaron de ligamentos. Esto me pone a la altura de los grandes deportistas del mundo :-). Les cuento día a día como fue la operaración y como viene el post-operatorio.

Antes de la operación


Me vieron ¡5! traumatólogos distintos entre Bariloche y Buenos Aires. Como tengo articulaciones laxas, el primer día no quedaba claro si tenía el ligamento cruzado anterior de la pierna derecha roto o no. Pero entre la espera y la resonancia magnética, fueron lapidarios. La resonancia magnética decía que estaba todo bien salvo por un detallecito:
Disrupción parcial del ligamento cruzado anterior

La parte de "parcial" me dio esperanza, pero los últimos 2 traumatólogos fueron lapidarios. "No hay rotura parcial del ligamento cruzado anterior, está roto o no", dijeron.
Y me dijeron que lo mejor que podía hacer es operarme, así que me fui preparando para ser carneado. También hice todos los exámenes prequirúrjicos correspondientes.
OSDE cubrió todo salvo las muletas y la férula. Por si no saben que es una férula, la RAE dice que una férula es una "Tablilla flexible y resistente que se emplea en el tratamiento de las fracturas.". Por suerte, uno de mis jefes ya se operó de ligamentos hace como 5 años y tiene todos los implementos ¡y me los prestó! (grande Guido).
Como no voy a poder moverme por como 2 o 3 semanas a partir del momento de la operación, también traje la compu del laburo a casa (el Visual Studio 2005 no anda ni por puta en la carcacha que tengo acá). Así que voy a estar productivo antes de poder caminar de nuevo. Mejor así, sino me pegaría un embole bárbaro.

El día de la operación


El lunes a la tarde fui a ver al cirujano que me dio todas las instrucciones pre-operación:

  • "Te operamos a las 19:30 en la clínica San Camilo, tenés que internarte a las 18hs."

  • "Afeitate la pierna, 15 cm para arriba y 15cm para abajo de la rodilla."

  • "Tenés que estar en ayunas de sólidos desde las 12hs."

  • "Tenés que estar en ayunas de líquidos desde las 14hs."


Como soy un niño responsable, hice todo esto (la verdad, me dio un poco de hambre, pero que puedo hacer). Así que llegamos con mi mujer a la clínica a las 18hs y me interné, habiendo hecho todos los deberes.
Cuando entramos a la habitación la enfermera me indicó que para la hora de la operación tenía que estar vestido con una especie de camisón para operarme. El coso ese es igual al que me hicieron poner cuando me operaron de apendicitis, así que todas las personas a las que hayan operado sabén de lo que estoy escribiendo.
Alrededor de las 18:45hs apareció en la habitación un señor vestido de traje, muy confianzudo, que empezó a revisarme sin decir nada. Como parecía que sabía lo que estaba haciendo, y estaba mi mujer controlando todo, estuvo como 5 minutos revisandome antes que le pregunte: "¿Y vos quién sos?". Ahí me dijo que era el anestesista (cosa que después confirmé, porque estaba en el quirófano, distrazado con el mameluco correspondiente). Bueno, el chabón chequeó y estaba todo en orden.
Alrededor de las 19:10 vino una enfermera a chequear mis "signos vitales". O sea, a tomarme la presión y el pulso. Todo en orden, 12-6 de presión y ni idea del pulso (seguramente bajo, ya que estaba acostado hacía un rato).

La operación


Aunque yo todavía podía caminar bien (bah, no tan bien, pero tampoco es que estuviera como ahora), vino un enfermero a buscarme con una camilla. Esto es parte del show, la verdad es que no hacía falta pasearme en camilla por todo el hospital. Mi habitación estaba en el primer piso y el quirófano en el cuarto, así que anduve en ascensor y todo.
Llegué al quirófano y estaba el chabón del traje, pero ahora vestido de médico o algo así (el disfráz típico de quirófano). Ahí me enchufaron el suero, por donde me darán la anestesia.

El bloqueo femoral


Como parte de la anestesia me hicieron un "bloqueo femoral". El procedimiento consiste en meterte un cable en la pierna (justito al lado de la ingle) y electrocutarte el nervio así movés la pierna y saben dónde queda; y después inyectarte andá a saber qué, que hace que ese nervio no ande por un par de días. Según el cirujano, ese bloqueo femoral es lo que hace que al día siguiente no esté llorando del dolor. Como yo le temo mucho más al dolor que a la muerte, por supuesto que estuve contento que hagan esto.
Ah!, no les conté. Como soy un cagón, elegí que me hicieran anestesia general en vez de la peridural, así que de la operación no les voy a poder contar nada.

Después de la operación


Me desperté y estaba en el quirófano, ahí me dijeron que estaba todo bien y que la operación fue un éxito (lo que más me puso contento es que no se les murió el paciente). Me recordaron que iba a tener unos chuchos de frío y me mandaron para la habitación.
Hice de nuevo el recorrido en camilla, pero esta vez sí lo necesitaba. Llegué y estaban mi mujer, mis viejos y Cristo. Me acostaron en la cama y, en cuanto lo vi, hice sacar al crucufijo de mi vista. Ahora supongo que estará en algún cajón de la habitación de la clínica.
En la rodilla tenía enchufada una manguera por donde salía sangre y en la mano otra por donde entraban suero fisiológico, antibióticos, analgésicos y compensador gástrico. Así que la salida y entrada de líquidos estaba compensada (por el momento).
Me empezaron a dar chuchos de frío (duraron unos 20', tal como me habían avisado) y emepcé a recuperarme de la operación. Todavía me quedaba una hora para poder comer algo y la cocina ya estaba cerrada, así que mi viejo fue a comprarme 2 yogures. Todavía no los podía comer, pero ya tenía hambre (no comía desde las 12 y eran las 12). Al ratito mis viejos se fueron.

La primera noche


Alrededor de la una, me tomé un tesito y el yogur bebible, mirando la tele. Por suerte encontramos un poquito de una peli erótica, así que me pude relajar un toque (la verdad, después de hacer zapping un rato, no me arrepiento de no tener tele en casa). También me agarraron ganas de mi primer meo nocturno. Como no me podía ni mover, me trajeron un papagayo (es como una botella con un lado medio plano) para que me eche ahí el meo. Salió como un litro de meo oscuro, oscuro y con mucho olor a medicamento.
A las 2 AM a mi mujer le dio sueño y exigió irse a dormir. Yo no tenía nada de sueño pero no me quedó otra.
Como estaba enchufado al suero, cada hora y media me agarraban unas ganas bárbaras de echarme un cloro, así que esa noche desperté como 4 veces a Agustina para que me alcanzara el papagayo y mear. ¡Mi mujer es una santa!

(Continuará......)

Update: Conté el final de mi recuperación en Reconstrucción del ligamento cruzado anterior de la rodilla derecha - Epílogo