Desde que comencé a correr en 1ero de Mayo de este año hasta la fecha he recorrido 200 millas o 312.8688 kilómetros. Para darles una idea de cuanto es eso:
La distancia entre las ciudades de Mérida y Trujillo es de 203 kilómetros
La distancia entre las ciudades de Mérida y San Antonio es de 298 kilómetros
La distancia entre las ciudades de Caracas y Puerto La Cruz es de 320 kilómetros
La distancia entre Darien, CT y Manhattan, New York (Central Park) es de 38 millas (llevo aproximadamente 5 viajes a pié)
Rompí la marca de las 200 millas con una carrera con velocidad 8’20 millas / mi minuto, antes de hacer ejercicio de resistencia. Mañana me toca una carrera un poco más larga (y lenta) de 6 millas, estoy intentando mis primeros 10K
Y ya paré de contar. Actualizaré el blog con una entrada como esta cuando llegue a 500 millas.
Great Grete Waitz Inspiration, Hero, Champion–The Woman Who Transformed Running, el libro presentado por Runner’s World, es una recolección de historias cortas sobre esta atleta. Su participación casi accidental en el maratón de Nueva York y como lo ganó por 9 veces seguidas, además de establecer marcas mundiales y mostrar a las mujeres como una fuerza a ser reconocida en el mundo de las carreras de distancia es algo que no tiene nombre.
Grete Waitz murió este año, después de combatir Cáncer. Este año hemos perdido a grandes figuras y Grete es una de ellas, le recomiendo este libro para que aprenda un poco sobre verdadera dedicación que sólo una atleta de este calibre pudo ofrecer.
Desde que comencé a correr he utilizado a NikeRunning.com de una u otra manera; Primero comencé con mi Itouch y ahora lo utilizó con el NikeWatch.
Sin embargo, el sitio de Nike es un poco fastidioso; El sitio web está escrito en Flash (lo cual lo hace pesado), tiene gráficos limitados pero lo mas inconveniente es que mis datos están cautivos en el sitio web. Según ellos ya llevan tiempo trabajando en una migración que eliminará Flash:
Hello Everyone,
Thank you all for your feedback.
To let everyone know, we are in the process of revamping our website. We are in transition to move away from flash to HTML. The goal is to be faster and more efficient.
We thank you for your patience as we update our sites. There is not an estimated time of when the transition will be fixed, but I can assure you that I’ve seen parts of the site and it’s looks and feels amazing.
Stay tuned!
Buscando un poco en Google me conseguí conque se puede obtener toda la información de las carreras (siempre y cuando estas esten marcadas como públicas) usando el siguiente URL:
Pero, ¿y de donde obtenemos el identificador del usuario? Es sencillo, simplemente vaya a nikerunning.nike.com y una vez que entre con su usuario y clave al sitio web haga click sobre una de sus corridas. El URL resultante se verá como esto:
En donde IDENTIFICADOR_DE_USUARIO es el número mágico que queremos usar.
Se me ocurrió por ejemplo escribir un pequeño programa en Jython y JavaFX el cual muestra la distribución de tipos de terreno encontrados mientras corrí:
#!/usr/bin/env jython# Author: Jose Vicente Nunez Zuleta, josevnz@kodegeek.com# This script parses the user run data and creates a simple distribtion by terrain types# See: http://nikerunning.nike.com/nikeos/p/nikeplus/en_EMEA/plus/#//dashboard/# Nike and Nikeplus/Nike+ are trademarks owned by Nike.# License: BSDimportsysfrom javafx.applicationimport Application
from javafx.collectionsimport FXCollections
from javafx.collectionsimport ObservableList
from javafx.sceneimport Scene
from javafx.stageimport Stage
from javafx.scene.chartimport PieChart
from javafx.sceneimport Group
from com.kodegeek.fitness.nikerun.queryimport CannedQuery
from com.kodegeek.fitness.nikerun.publicimport PlusPublicService
class TerrainTypesChart(Application):
def __getData__(self):
args = self.getParameters().getRaw()
pServ = PlusPublicService(args[0])
data = pServ.getUserData()
dp = CannedQuery('string', data)return dp.getTypesOfTerrain()def start(self, stage):
scene = Scene(Group())
stage.setTitle("Terrain types found in all races")
stage.setWidth(500)
stage.setHeight(500)
count = self.__getData__()
data = [PieChart.Data(key, value)for(key, value)in count.iteritems()]
pieChartData = FXCollections.observableArrayList(data)
chart = PieChart(pieChartData)
chart.setTitle("Terrain types found")
scene.getRoot().getChildren().add(chart)
stage.setScene(scene)
stage.show()if __name__ == "__main__":
Application.launch(TerrainTypesChart().class, sys.argv[1:])
La clase ‘PlusPublicService’ no es más que un simple cliente GET el cual se baja los datos del sitio de Nike:
!/usr/bin/env jython
## Author: Jose Vicente Nunez Zuleta, josevnz@kodegeek.com# See: http://nikerunning.nike.com/nikeos/p/nikeplus/en_EMEA/plus/#//dashboard/# Nike and Nikeplus/Nike+ are trademarks owned by Nike.# License: BSD#fromhttplibimport HTTPConnection, HTTP_PORT
importsys
__URL__ = 'nikerunning.nike.com'
__SERVICE__ = '/nikeplus/v1/services/widget/get_public_run_list.jsp?userID='class PlusPublicService:
def__init__(self, userId, port = HTTP_PORT):
self.service = __SERVICE__ + userId
self.userId = userId
self.port = port
def getUserData(self, debug=0):
data = None
con = HTTPConnection(__URL__, self.port)
con.set_debuglevel(debug)
con.request('GET', self.service)
response = con.getresponse()if response.status == 200:
data = response.read()else:
raiseException("Error. Status = %s, reason = %s"%(response.status, response.reason))
con.close()return data
if __name__ == "__main__":
argv = sys.argv[1:]iflen(argv)>0:
pServ = PlusPublicService(argv[0])print"%s"% pServ.getUserData(8)else:
print"NikeRunning user id is required!"sys.exit(192)
Y para procesar mis datos utilizo un poco de XPATH en la clase ‘CannedQuery’ la cual tiene un método el cual se encarga de crear la distribución para los distintos tipos de terreno:
Pienso abrir un proyecto con todas estas clases de Python (Jython) en unos pocos días. Quiero agregarle un par de cosas más antes de soltarlas al aire libre
#!/usr/bin/env jythonimportsysfrom javafx.applicationimport Application
from javafx.collectionsimport FXCollections
from javafx.collectionsimport ObservableList
from javafx.sceneimport Scene
from javafx.stageimport Stage
from javafx.scene.chartimport PieChart
from javafx.sceneimport Group
class PieChartSample(Application):
def__init__(self):
passdef start(self, stage):
scene = Scene(Group())
stage.setTitle("Imported Fruits")
stage.setWidth(500)
stage.setHeight(500)
pieChartData = FXCollections.observableArrayList(
PieChart.Data("Grapefruit", 13),
PieChart.Data("Oranges", 25),
PieChart.Data("Plums", 10),
PieChart.Data("Pears", 22),
PieChart.Data("Apples", 30))
chart = PieChart(pieChartData)
chart.setTitle("Imported Fruits")
scene.getRoot().getChildren().add(chart)
stage.setScene(scene)
stage.show()if __name__ == "__main__":
PieChartSample().launch(sys.argv[1:])
Pero al correrlo me se queja que no estoy extendiendo bien la clase ‘Aplication’ y por eso falla:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Macintosh:javafx josevnz$ ./piechart.py
*sys-package-mgr*: can't create package cache dir, '/Users/Shared/jython2.5.2/cachedir/packages'
Traceback (most recent call last):
File "./piechart.py", line 36, in <module>
PieChartSample().launch(sys.argv[1:])
at javafx.application.Application.launch(Application.java:186)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
java.lang.RuntimeException: java.lang.RuntimeException: Error: class sun.reflect.NativeMethodAccessorImpl is not a subclass of javafx.application.Application
</module>
No tengo ni idea en donde esta el error, ¿alguno de ustedes tiene una pista? De verdad me muero de ganas por usar JavaFX con Jython, ya otros han tenido éxito similar con JRuby y Groovy.
Amanecerá y veremos.
Actualización: De la lista de Jython me llegaron muchas sugerencias, al final Weiqi Gao encontró cual era el verdadero problema y esta es la solución:
1
2
3
# The key to happiness in JavaFX + Jython is this:if __name__ =="__main__":
Application.launch(PieChartSample().class, sys.argv[1:])
La explicación detallada a continuación:
The trick is with the last line of code that launches the application, which is accomplished with the javafx.application.Application.launch() method. There are two overloaded versions of this method:
The first version must be called from a method in a class that extends Application, which is not the case in the above python code. So we have to use the second version.
The idiom for using the first version of launch() in Java is the following:
1
2
3
4
5
6
7
8
9
10
publicclass Foo extends Application {
@Override
publicvoid start(Stage stage){// build the scene graph and show it}publicstaticvoid main(String[] args){
Application.launch(args);}}
The idiom for using the second version of launch() in Java is the following:
1
2
3
4
5
6
7
8
9
10
11
12
publicclass Foo extends Application {
@Override
publicvoid start(Stage stage){// build the scene graph and show it}}publicclass Launcher {publicstaticvoid main(String[] args){
Application.launch(Foo.class, args);}}
There is an inefficiency in my python code in that I instantiated PieChartSample once only to get its class. I think there is a better way of doing it but can’t think of how at the moment.
En una de esas cosas del destino conseguí un parque con una pista de asfalto a no más de 2 millas de mi casa; El parque abre de 5:30 de la mañana hasta las 10:00 de la noche y aunque no se compara con Central Park con sus subidas y bajadas esta bien cuidado y tiene un lazo de casi una milla, ideal para correr.
Hoy manejé hasta allá a las 5:30 AM y después de quitarme la ropa que no necesitaba para correr comencé a darle vueltas al circuito; En un principio el frio de otoño me carcomía todo el cuerpo mientras un hilo nada modesto de mocos me corría por la nariz. Lo otro es que el recorrido no me era familiar, así que tenia que ir con cuidado especialmente en los pedazos que estaban totalmente a oscuras (se puede correr sin ver muy bien con poca luz, se sorprenderían de ver como se acostumbran los ojos).
Pero el cuerpo se adaptó rápido; El frio en las manos y cuerpo cedió a la euforia de correr para ir acelerando el paso hasta alcanzar la velocidad requerida.
Lo mejor es que el parque era prácticamente mio; Sólo unas pocas personas con linternas paseando sus perros pero nadie corriendo, nadie más rápido que yo.
Mi ego se inflama y poco a poco le pierdo respeto a las curvas y huecos del parque, ahora estoy corriendo. Ya no hay mocos en la nariz sino sudor por todo el cuerpo. No estoy llevando cuenta del tiempo ni las millas, sólo disfruto el sonido del agua que choca contra la orilla (el parque queda cerca del mar), mientras veo que ya hay más gente en el parque y ahora si, algunos corredores.
El reloj me recuerda que mis 5 kilómetros ya están listos; Mis manos me recuerdan que me ponga guantes la próxima vez, porque seguro va a haber una próxima vez.
Ah si, y una lampara para ver el camino mejor en la oscuridad
Normalmente no leo biografías de nadie; No me malentiendan, la historia de individuos que resaltan por haber hecho cosas extraordinarias es algo que debería motivarnos a ser mejores a todos.
Este libro es especial dado lo inusual de su personaje; Imagínese que usted es un corredor / atleta que se hizo desde cero, comenzando primero a pujar para poder correr hasta lograr conquistar varias metas: El maratón ING de New York (el más famoso del mundo), el de ChicagoBoston (con su fama de invitar sólo a los más rápidos) y luego el triatlón Iron Man (si nadar, montar bicicleta y correr por varias millas no lo intimidan entonces usted seguro no es normal).
Todo va muy bien hasta un fatídico día en el cual en vez de entrenar con sus amigos es atropellado por un autobús el cual casi lo deja muerto, todo gracias a un paro de transporte en la gran manzana y a un conductor descuidado.
Pero Matt no se rindió. Peleó por recuperarse y al final logró volver a correr el maratón de New York y no sólo eso, logró hacer otro Iron Man.
Su lucha no fué fácil, ya que le dieron sólo %5 de posibilidades de éxito; Leer sus dudas y dolor físico es angustiante pero lo que realmente lo que cautiva de este libro es que aún con sus dudas el pudo salir a adelante y cambiar su suerte.
Mucha gente se ríe cuando les digo que me levanto a las 4:00 de la mañana 3 veces a la semana para entrenar en el gimnasio. Yo les digo que eso no es nada, no es un esfuerzo de verdad. Si no lean la historia de Matt Long para que vean que si se puede; Si eso no los inspira a ser mejores entonces no se que pueda
O algo así es como dice el articulo que apareció en la revista del mes de Octubre del 2011 ‘Running Times’, del atleta y escritor Peter Magil;. Allí el nos muestra como calcular cuanto descansar después de un entrenamiento usando las tablas creadas por el científico Tom Schwarts.
#!/usr/bin/env python# Calculate days of recovery after a race. Based on the article appeared on the Running times magazine # "It's the Recovery Stupid" by Pete Magill, using Tom Schwartz tables# author: josevnz@kodegeek.com# http://kodegeek.com/blogimportsysclass Recovery:
def__init__(self):
self.__ages = {'20':0, '30':1, '40':2, '50':3, '60':4, '70':5, '80':6}self.__fitnessLevel = {'LOW':0, 'MEDIUM':1, 'HIGH':2}self.__daysBetweenWorkouts = [[4.0, 3.0, 2.5],
[5.0, 4.0, 3.0],
[6.0, 4.5, 3.5],
[7.0, 5.0, 4.0],
[7.5, 6.0, 4.5],
[8.0, 6.5, 5.0],
[9.0, 7.0, 5.5]]self.__races = {'5K':0, '8K':1, '10K':2, '15K':3, '1/2 Mar':4, 'Mar':5}self.__intensityWorkout = {'EASY':0, 'MEDIUM':1, 'HARD':2}self.__recoveryDaysAfterRace = [[2, 3, 5],
[3, 5, 8],
[3.5, 6, 9],
[4, 7, 11],
[5.5, 9, 14],
[9, 17, 26]]self.__adjustment = {'20':1.0, '30':1.1, '40':1.2 , '50':1.3, '60':1.4, '70':1.5, '80':1.6}def getAgeBracket(self, age):
try:
dAge = int(age)if dAge <0:
raiseException("Invalid age value: %s"% age)for bracket in[20, 30, 40, 40, 50, 70, 80]:
if dAge >= bracket and dAge < = (bracket + 9):
returnstr(bracket)# > 80 yearsreturn80except(Exception), exp:
raiseException("Invalid age: %s"% age)def getDaysBetweenWorkouts(self, age, level):
try:
bracket = self.getAgeBracket(age)
dBracket = self.__ages[bracket]
intensity = self.__fitnessLevel[level]returnself.__daysBetweenWorkouts[dBracket][intensity]*self.__adjustment[bracket]except(Exception), exp:
raiseException("Invalid age or level: age=%s, level=%s"%(age, level))def getDaysAfterRace(self, age, race, level):
try:
bracket = self.getAgeBracket(age)
dBracket = self.__races[race]
intensity = self.__intensityWorkout[level]returnself.__recoveryDaysAfterRace[dBracket][intensity]*self.__adjustment[bracket]except(Exception), exp:
raiseException("Invalid age race type or level: age=%s, race=%s, level=%s"%(age, race, level))if __name__ == "__main__":
recovery = Recovery()
arg = sys.argv[1:]
days = 0iflen(arg) == 2:
days = recovery.getDaysBetweenWorkouts(arg[0], arg[1])print"Days: %2.2f, for age: '%s' and level: '%s'"%(days, arg[0], arg[1])eliflen(arg) == 3:
days = recovery.getDaysAfterRace(arg[0], arg[1], arg[2])print"Days: %2.2f, for age: '%s' and level: '%s', race=%s"%(days, arg[0], arg[2], arg[1])else:
sys.exit(192)# "com/kodegeek/fitness/recoveryrun.py" 76L, 2539C written
Así que por ejemplo, si corremos una carrera de 5K con todo y tenemos 35 años de edad:
1
2
3
Macintosh:python josevnz$ ./com/kodegeek/fitness/recoveryrun.py 35 5K HARD
Days: 5.50, for age: '35' and level: 'HARD', race=5K
Macintosh:python josevnz$
¿Y si no es una carrera, pero un entrenamiento fuerte y soy medianamente resistente?
1
2
3
Macintosh:python josevnz$ ./com/kodegeek/fitness/recoveryrun.py 35 MEDIUM
Days: 4.40, for age: '35' and level: 'MEDIUM'
Macintosh:python josevnz$
Por cierto, hoy es mi día de descanso entre entrenamientos. Así que es hora de ejercitar el lado Geek un poquito. Estoy pensando en abrir un nuevo proyecto de código abierto para ir dejando estos pedazos de código relacionados con correr y ejercicios de resistencia. ¿Les suena buena idea?
Después de ir al doctor y comenzar a recuperarme, decidí hacer esta carrera; La idea es celebrar el esfuerzo de las mujeres y hombres que han sobrevivido a un cáncer de seno, a la vez que se recaudan fondos para pelear contra esta variedad de la enfermedad.
Ya mi amigo Hengel (otro corredor Venezolano amigo mio) se habia inscrito, así que yo no tenia ninguna excusa para no correr. Además, después de eso el plan era hacer un almuerzo al aire libre en Central Park, al comienzo de Otoño cuando aún no es muy frío.
Nunca puedo dormir antes de una carrera; Esta no fué la excepción y después de comer mi desayuno (una buena mezcla de proteína y carbohidratos lentos) escribí lo siguiente en Facebook y Google+:
Race for the cure schedule so far:
- 5:00 AM: Breakfast and prepare race items
- 6:30 AM: Wake up Veronica and Sebastian
- Registration will open at 7:00 Am at 71 Street West in Central park. We will be there around 8:30 AM, no rush (I already got by BIB# 16539. How many people is in there?)
- 9:20 AM: Race starts for elite female runners and survivors only (yeah, males like me will have to suck it until 9:25 AM).
- 10:30 Runners award ceremony begins in Bandshell. Based on my previous two races I should not take more than 30 minutes to complete this one.
This year I’ll record some video (wait for the Flickr invite) and some photos as things develop. This race doesn’t have an official time, so unless I win (JAJAJA) I will have no way to know on which position I finish (so my new GPS time will have to be enough for my poor ego).
I’ll keep you guys posted!
Hengel Zambrano: I’ll call you to see where are we meeting before the race.
–José
Nada sabia yo que esta carrera iba a tener sorpresas preparadas.
Antes de la carrera
Llegamos a las 8:40 A.M. a Central Park, calle 71 oeste; Una ves entrados allí recordamos que había que estar a esa altura en el lado Este.
Había que atravesar un pedazo completo del parque para llegar allí.
¿Qué tan lejos puede ser? No es lo lejos sino lo complicado cuando tu hijo de 4 años está disfrutando del parque, jugando con los perros, recogiendo hojas; Después de hacer una parada obligatoria en el baño (más nervios que otra cosa) y de tomarnos un café caminamos a la salida.
Allí la realidad se encargo de recordarme lo descuidado que había sido, la salida de los corredores acababa de comenzar a las 9:20 A.M. y la mia era la siguiente en 5 minutos.
El problema era pasarle por encima a las 500 personas que tenia por delante de mi para llegar a la salida de la carrera, nunca habia visto tanta gente (vestida de rosado) en mi vida.
Comencé a trotar hacia la salida, luego a correr para luego detenerme abruptamente porque no se podía avanzar. Luego entro el pánico cuando el anunciador dijo lo siguiente:
Siento una lastima por los corredores que no salieron a tiempo ya que ahora ahora van a tener que lanzarse entre los que sólo vienen a caminar los 5 kilómetros
Coño, ¡Coño!, ¡están hablando de mi!.
Mi carrera anterior en el Yankee Stadium había sido un desastre y ahora esta estaba a punto de ser algo peor. Sin tiempo oficial y comenzando tarde con obstáculos, mi tiempo prometía ser el peor de todos.
Sin exagerar, me paralice por 5 segundos pensando que hacer después…
Mis piernas decidieron por mí; Comencé a correr lo más rápido que podía, empujando a quienes estaban adelante, rozándome de manera incomoda mientras trataba de buscar un espacio por donde pasar, pidiendo disculpas entre empujón y empujón mientras le rogaba a Dios que no me volaran la cara de un merecido golpe por no haber estado donde tenía que haber estado 10 minutos atrás.
Cuando ya llevaba apenas 0.80 millas (ni siquiera una milla) ya estaba jadeando del cansancio y mis cuádriceps me pedían a gritos que parara el abuso de correr – parar de golpe – correr. Estaba empapado de sudor y aún tenia un mar de gente por delante (viendo el gráfico en NikePlus se puede ver me mi ritmo era de 4:40 minutos por milla a la milla 0:84, muy rápido).
No estaba viendo el recorrido sino a quien tenia al frente, buscando huecos para poder pasar.
¿Como me las había arreglado para dañar mi carrera de ese modo?
La pelea sólo se hace peleando
No me detuve a descansar ni un momento; Ya sabía que la carrera iba a ser difícil por lo tarde de mi salida y la cantidad de gente en el recorrido tan estrecho, así que sólo me concentré en seguir pujando.
Después de la primera milla y media me dí cuenta que tenia que estabilizar el ritmo, de lo contrario no iba a llegar a la meta en buen estado; Mirando alrededor me conseguí con un muchachito de 25 años (o algo así) que tenia buen ritmo y pasaba a la gente cuando tenia una oportunidad.
Esa era nueva meta, pegarmele atrás y seguirlo. El me iba a abrir el paso por la siguiente milla o más.
El plan funcionó ya que cuando ibamos por la milla 2.60 me sentía con más energía que al principio y aún seguía pasando gente por delante; Cuando llegamos a la milla 2.80 llegó el momento de desprenderme e iniciar la carrera con todo.
Mira de nuevo mi reloj y me dí cuenta que mi tiempo no era fatal, por lo que aprete el pedal y corrí con todo, tan rápido que pase a muchos corredores que ya estaban en pleno ‘surge’. Cuando llegué a la meta, lo hice volando y estrellandome contra los corredores que ya habían bajado la velocidad al cruzar la meta antes que yo.
Mi tiempo ‘no oficial’: 25:20, Mejor que en el Yankee Stadium pero peor que la carrera de Yai.
La carrera fué interesante; En particular celebro el coraje de quienes nunca se rindieron cuando la enfermedad los atacó y lograron salir adelante.
Lo único negativo: Para mi fué decepcionante el hecho de que no se midan los tiempos oficiales, aunque los organizadores de la carrera son MUY claros diciendo que es una carrera por diversión no competitiva, no creo que tomar los tiempos afecte el espíritu de camaradería que caracterizo al evento.
De cualquier forma la pasé genial, en especial con la comida al aire libre con Verónica y Sebastian. Esta es una excelente excusa para hacer más carreras
¿Queda alguna carrera interesante para el 2011? Hay un par que me llaman la atención, queda ver como me va adaptándome a correr en el frio de Noviembre / Diciembre.
NOTA: Hay fotos que me faltan por subir, en especial las del día de la carrera. Cuando salgan las pongo en este artículo.
El recorrido está aquí, es una carrera sin tiempo oficial y por diversión. La idea es colaborar contra el cáncer de seno.
Me estoy recuperando aún de la lesión de la carrera anterior. Sin embargo las medicinas y el calzado han hecho una gran diferencia. No creo que mejore los tiempos (poco tiempo para entrenar, más recuperación), pero al menos espero mantener lo que hice la última carrera.
Comentarios recientes