la runeta se agita

Dec 01
Permalink

Geonames Hierarchy

In case you’re wondering how to get the hierarchy of a Geonames place, this is my recipe. As per Marc suggestion, I preprocessed the Geonames dump and fill a table with some handy columns and indexes.

You’ll get with something like this:

mysql> select * from places_preprocessed where name=’Almagro’\G
*************************** 1. row ***************************
id: 3436397
name: Almagro
alternames:
ansiname: Almagro
lat: -34.6
lon: -58.4166667
parent_ids: |3865483|3433955|3436397|
parent_names: |Argentine Republic|Distrito Federal|Almagro|
feature_code: PPLX
depth: 3

The following code is in Ruby, using Activerecord.

There’re 2 tables, “geonames” which holds the Geonames dump and “places_preprocessed” with the result data.

CREATE TABLE `geonames` (
`id` int(10) unsigned NOT NULL,
`name` varchar(200) NOT NULL default ”,
`ansiname` varchar(200) NOT NULL default ”,
`alternames` varchar(2000) NOT NULL default ”,
`latitude` double NOT NULL default ‘0’,
`longitude` double NOT NULL default ‘0’,
`feature_class` char(1) default NULL,
`feature_code` varchar(10) default NULL,
`country_code` char(2) default NULL,
`cc2` varchar(60) default NULL,
`admin1_code` varchar(20) default ”,
`admin2_code` varchar(80) default ”,
`admin3_code` varchar(20) default ”,
`admin4_code` varchar(20) default ”,
`population` int(11) default ‘0’,
`elevation` int(11) default ‘0’,
`gtopo30` int(11) default ‘0’,
`timezone` varchar(40) default NULL,
`modification_date` date default ‘0000-00-00’,
PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

CREATE TABLE `places_preprocessed` (
`id` int(10) unsigned NOT NULL,
`name` varchar(200) default NULL,
`alternames` varchar(255) default NULL,
`ansiname` varchar(200) default NULL,
`lat` double default NULL,
`lon` double default NULL,
`parent_ids` varchar(200) default NULL,
`parent_names` tinytext,
`feature_code` varchar(10) default NULL,
`depth` smallint(6) NOT NULL,
PRIMARY KEY  (`id`),
KEY `parent_ids` (`parent_ids`),
KEY `feature_code` (`feature_code`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

And now, the code:

class Geonames < ActiveRecord::Base
FEATURE_CLASS_HIERARCHY=[‘ADM1’, ‘ADM2’, ‘ADM3’, ‘ADM4’, ‘ADMD’, ‘LTER’, ‘PCL’, ‘PCLD’, ‘PCLF’, ‘PCLI’, ‘PCLI’, ‘PCLS’, ‘PRSH’, ‘TERR’, ‘ZN’, ‘ZNB’]
MAIN_HIERARCHY=[ ‘PCLI’,’ADM1’, ‘ADM2’, ‘ADM3’, ‘ADM4’,[‘PPLC’,’PPLA’,’PPLX’]]
def find_main_children
pos = MAIN_HIERARCHY.index(self.feature_code)
return [] if not pos
next_feature_codes = MAIN_HIERARCHY[pos + 1 .. -1]
puts “Children codes: #{next_feature_codes.inspect} (current fcode: #{self.feature_code})”
r = []
next_feature_codes.each { |next_feature_code|
if next_feature_code
puts “Finding children with code #{next_feature_code}”
sql = “country_code = ? and admin2_code = ? and admin3_code = ? and admin4_code = ? and feature_code in (?)”
param = [self.country_code, self.admin2_code,self.admin3_code,self.admin4_code,next_feature_code]      
if self.admin1_code and self.admin1_code != ‘00’
sql += ” and admin1_code = ? “
param « self.admin1_code
end
puts “** SQL: #{sql} p: #{param.inspect}”
r = Geonames.find(:all,:conditions => [sql, *param])
return r if not r.empty?
end
}
r
end
def find_children
next_feature_code = FEATURE_CLASS_HIERARCHY[FEATURE_CLASS_HIERARCHY.index(self.feature_code) + 1]
Geonames.find(:all,:conditions => [“country_code = ? and admin1_code = ? and admin2_code = ? and admin3_code = ? and admin4_code = ? and feature_code in (?)”,self.country_code, self.admin1_code,self.admin2_code,self.admin3_code,self.admin4_code,next_feature_code]) if next_feature_code
end
def parent
FEATURE_CLASS_HIERARCHY.reverse.each{ |feature_code|
break if feature_code == self.feature_code
place = Geonames.find(:first,:conditions => [“country_code = ? and admin1_code = ? and admin2_code = ? and admin3_code = ? and admin4_code = ? and feature_code = ? “,country_code, admin1_code, admin2_code, admin3_code, admin4_code, feature_code]);
return place if place
}
end    
end

And the code to preprocess:

class Place < ActiveRecord::Base
set_table_name :places_preprocessed;
has_many :properties
def self.preprocess
ActiveRecord::Base.connection.execute(“TRUNCATE TABLE `#{table_name}`”);
Geonames.find(:all, :conditions => “feature_code = ‘PCLI’ and feature_class = ‘A’ and admin1_code = ‘00’”).each{ |country|
Place.preprocess_place(country)
}
end
def self.preprocess_place(place, parent = nil, pad = ”)
puts pad + “Preprocess place: #{place.inspect}”
parent = parent || place.parent
puts  pad + ” * parent is: #{parent}”
if parent and parent.is_a?(Place)
parent_ids = parent.parent_ids
parent_names = parent.parent_names
depth = parent.depth
else
parent_ids = “|”
parent_names = “|”
depth = 0
end
preprocessed = Place.new
preprocessed.id = place.id
preprocessed.name = place.name;
preprocessed.feature_code = place.feature_code
preprocessed.lat = place.latitude
preprocessed.lon = place.longitude
preprocessed.parent_ids = parent_ids + place.id.to_s + “|”
preprocessed.parent_names = parent_names + preprocessed.name + “|”
preprocessed.alternames = place.alternames
preprocessed.ansiname = place.ansiname
preprocessed.depth = depth + 1
puts  pad + ” * presave #{preprocessed}”
preprocessed.save()
puts  pad + ” * processing children…  “
children = place.find_main_children
puts pad + ” * found #{children.length} children”
children.each{|child|
begin  
Place.find(child.id)
puts pad + ” * #{child.to_s} (#{child.id}) already processed!”
rescue
Place.preprocess_place(child, preprocessed, pad + ‘   ‘)
end
}
end
end

Usage, just run:

Place.preprocess()

Comments (View)
Nov 06
Permalink
Comments (View)
Oct 28
Permalink
However, I think most people just make the mistake that it should be simple to design simple things. In reality, the effort required to design something is inversely proportional to the simplicity of the result. As architectural styles go, REST is very simple.
Comments (View)
Sep 10
Permalink
Seinfeld - Serenity Now Montage (via eilgenfritz)
Comments (View)
Permalink
Fanny and Freddy podría haber sido el título de una comedia protagonizada por una simpática parejita de niños traviesos o un thriller de dos jóvenes asaltantes de bancos. Pero no. Fannie Mae y Freddie Mac son los nombres con los que se conoce hoy a las dos entidades de crédito que están haciendo temblar el sistema financiero mundial. El salvavidas de rescate que les lanzó el Tesoro de los Estados Unidos es de 200 mil millones de dólares. El monto de las hipotecas comprometidas asciende a más de 5 billones de dólares, algo así como treinta veces la deuda pública argentina, y casi la mitad de los 12 billones de dólares de los préstamos inmobiliarios de todo el sistema financiero estadounidense. ¿Cómo hicieron para llegar a tanto dos entidades cuyos nombres son simples apodos diminutivos?
Comments (View)
Sep 04
Permalink
Google also say they’re using a “multi-process design” which they say means “a bit more memory up front” but over time also “less memory bloat.” When web pages or plug-ins do use a lot of memory, you can spot them in Chrome’s task manager, “placing blame where blame belongs.”
[…]
By implementing this feature a browser is completely deflecting all memory or performance criticism off to individual site owners (“Yikes, my browser is using 300MB of memory! Actually it’s just youtube.com consuming 290MB of it, they should fix their web site!”). This is going to be a monumental shift in the responsibilities of web developers - and one that will serve the web better, as a whole.
Comments (View)
Aug 29
Permalink
Casi funciona&#8230;
For 11 days on the stand, Hans Reiser told Alameda County jurors to discount any guilty behavior he exhibited in the aftermath of his wife&#8217;s disappearance. After all, he said, he was a scientist, a misunderstood computer geek who stared at a computer screen for so long he hadn&#8217;t a clue of societal cues.
(via Hans Reiser Faces the Music Friday | Threat Level from Wired.com
)

Casi funciona…

For 11 days on the stand, Hans Reiser told Alameda County jurors to discount any guilty behavior he exhibited in the aftermath of his wife’s disappearance. After all, he said, he was a scientist, a misunderstood computer geek who stared at a computer screen for so long he hadn’t a clue of societal cues.

(via Hans Reiser Faces the Music Friday | Threat Level from Wired.com

)

Comments (View)
Aug 28
Permalink

Acentos y demas en Hpricot + UTF-8

Si usted esta, como yo, desesperado porque el Hpricot le devuelve signos de pregunta en vez de caracteres acentuados (aun cuando el doc es UTF-8), use esta asquerosidad:

require “htmlentities”
module Hpricot
class Elem
def inner_utext
coder = HTMLEntities.new
coder.decode(self.innerHTML)
end
end
end

Ahora puede hacer: doc.at(“#cosito”).inner_utext y le devuelve lo que usted andaba buscando. Algun dia, cuando el Hpricot funcione bien, cambia su inner_utext por “lo correcto”

Va a necesitar esto: HTML Entities for Ruby

Comments (View)
Aug 26
Permalink

Tips de Firebug para debuggear aplicaciones grandes

Antes que nada, usar siempre la ultima version en desarrollo de firebug (tiene mas bugs pero tambien mas features)

  1. Hasta el Firebug 2.0 debuggear JS grandes es lentisimo, partirlos en cachitos
  2. Cuando uno esta laburando con CSS y HTML y dandole poca bola al JS, lo mejor es desactivar los paneles de Net y Script; que segun mi experiencia es lo que hace lento al firebug
  3. Tener 2 firefox abiertos al mismo tiempo, uno con un perfil “normal” y otro con un perfil de “dev”. El de “dev”, borrarlo cada dos por tres y crearlo de nuevo. Por alguna razon el firefox se pone lento (?)
  4. El grupo de usuarios de firebug responde muy rapido
  5. Algo basico pero vital: cuando uno esta debuggeando step-by-step la consola cambia al contexto donde esta la linea que se esta ejecutando. Hay bastante interaccion entre los distintos paneles (Console, Net y Script) aunque por la interface no parezca.
Comments (View)
Aug 20
Permalink

A mi, este discurso de Steve Jobs me rompe las pelotas. Es como que es un tipo “buena onda” que te habla desde su corazon, que te dice “hace lo que sientas”. La parte oculta de esto es lo que sigue despues: “hace lo que sientas” (siempre que termines cambiando la tipografia de todas las computadoras del mundo).

Es como que nosotros lo escuchamos con mucha atencion y nos conmueve lo que dice, pero en realidad, lo que parece “genial” es que el hizo todo eso: y se hizo rico! y famoso! y es admirado por todo el mundo!

Yo podria decir lo mismo: “hace lo que tengas mas ganas”, pero claro, como yo no hice Pixar, a mi nadie me escucha. Tipico.

Comments (View)