Archivo

Archivo para la categoría ‘programación’

Mi primer 10K: Joe Kleinerman 10K

Sábado, 7 de enero de 2012

Before the race
Mi primer 10K, no estuvo nada mal

Hoy corrí mi primer 10K; Decidí probar una estrategia dado que la distancia a batir es el doble de lo que yo estoy acostumbrado a correr; Comencé lento las 2 primeras millas, un poco más rápido las 2 siguiente y las 2 últimas con todo.

Central Park 6.2 mile loop
Recorrido alrededor de Central Park, 6.2 millas

Sin contar con una ida obligatoria al baño en la cual gaste por lo menos 40 segundos (el baño estaba ocupado) creo que salió bien :-)

Los resultados oficiales:

Last Name

First Name

Sex/
Age

Bib

Team

City

State

Country

Overall
Place
Gender
Place
Age
Place
Net
Time
Pace/
Mile
AG
Time
AG
Gender
Place

AG %

Nunez Zuleta Jose V M38 5735 0 DARIEN CT USA 2416 1701 316 0:55:05 08:54 0:52:51 1843 50.82
 Resultados oficiales

Esta es una de las carreras del 9+1 para tener una entrada garantizada el maratón de NYC, sólo me faltan 8 más :-)

java , , ,

¿Cuanto esfuerzo poner al correr? Usando un monitor de pulsaciones

Domingo, 25 de diciembre de 2011

Primero que todo, ¡Feliz navidad!. Hoy me dieron de regalo un monitor de pulsaciones (Polar Link, compatible con Nike GPS awatch), la idea es mantener mis niveles de esfuerzo constantes y en niveles seguros.

Así que hoy me decidí a probarlo con una carrera corta de sólo dos millas, ni tan rápido ni tan lento; La configuración del dispositivo fué trivial y aunque se sintió raro tener una cinta en el pecho durante los primeros 5 minutos luego la sensación se disipó y pude olvidarme por completo que el aparato estaba allí.

La teoría sobre cuales rangos son seguros la pueden encontrar en este enlace, pero si usted es un corcho como yo ya seguro tiene un script para hacer las conversiones:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
# Heart rate range calculator, for both aerobic and anaerobic ranges
# http://kodegeek.com/blog
# http://www.livestrong.com/article/179970-a-healthy-heart-rate-while-running/
def heartRate(age, anaerobic=False):
        maxHearthRate = 220 - age
        bound = []
        if not anaerobic:
                bound.append(0.50 * maxHearthRate)
                bound.append(0.85 * maxHearthRate)
 
        else:
                bound.append(0.80 * maxHearthRate)
                bound.append(0.90 * maxHearthRate)
        return bound
 
if __name__ == "__main__":
        import sys
        args = sys.argv[1:]
        if len(args) == 2:
                res = heartRate(int(args[0]), {'true': True, 'false': False}.get(args[1].lower()))
                print "%s,  %s " % (res[0], res[1])

Por ejemplo, para alguien de mi edad estos deberian ser los rangos aeróbicos y anaeróbicos:

1
2
3
4
5
6
 
Macintosh:python josevnz$ python com/kodegeek/fitness/heartrate.py 38 false
91.0,  154.7 
Macintosh:python josevnz$ python com/kodegeek/fitness/heartrate.py 38 true
145.6,  163.8 
Macintosh:python josevnz$

Según el monitor, en promedio mis pulsaciones promedio estuvieron en 165, solamente estuve un %38 del tiempo dentro de mi rango aeróbico. Muy alto, al menos que este leyendo algo mal. Ahora me sale hacer mi tarea :-)

kodegeek, python, vida sana

¿Como configurar Netbeans 7.10 beta y JavaFX 2.0 beta en OSX?

Sábado, 15 de octubre de 2011

Es un poco fastidioso, pero una vez que se bajen los binarios y siguiendo las instrucciones (no muy precisas de Oracle) terminé haciendo esto:

Netbeans 1.7.1 (beta) + JavaFX 2.0 (beta)

¡Ahora a jugar! :-)

java, javafx

Hackeando mis datos en NikeRunning.com

Miércoles, 12 de octubre de 2011


Tipos de terreno para todas mis carreras, desde NikeRunning, mostrado con JavaFX

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:

1
http://nikerunning.nike.com/nikeplus/v1/services/widget/get_public_run_list.jsp?userID=IDENTIFICADOR_DE_USUARIO

El archivo resultante está en formato XML.

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:

1
http://nikerunning.nike.com/nikeos/p/nikeplus/en_US/plus/#//runs/gps/IDENTIFICADOR_DE_USUARIO/299193444/

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í:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/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: BSD
import sys
from javafx.application import Application
from javafx.collections import FXCollections
from javafx.collections import ObservableList
from javafx.scene import Scene
from javafx.stage import Stage
from javafx.scene.chart import PieChart
from javafx.scene import Group
from com.kodegeek.fitness.nikerun.query import CannedQuery
from com.kodegeek.fitness.nikerun.public import 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
!/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
#
from httplib import HTTPConnection, HTTP_PORT
import sys
 
__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:
                        raise Exception("Error. Status = %s, reason = %s" % (response.status, response.reason))
                con.close()
                return data
 
if __name__ == "__main__":
        argv = sys.argv[1:]
        if len(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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/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
 
from xml.dom.minidom import parse, parseString
from xml.etree import ElementTree
import sys
 
class DataParser(object):
 
        def __init__(self, type='string'):
                self.type = type
 
        def __parseDomFile__(self, file):
                return parse(open(file, 'r'))
 
        def __parseDomString__(self, string):
                return parseString(string)
 
        def __parseXpathFile__(self, file):
                return ElementTree.parse(file)
 
        def __parseXpathString__(self, string):
                return ElementTree.fromstring(string)
 
        def __getDom__(self, source):
                if self.type == 'string':
                        return self.__parseDomString__(source)
                else:
                        return self.__parseDomFile__(source)
 
        def __getTree__(self, source):
                if self.type == 'string':
                        return self.__parseXpathString__(source)
                else:
                        return self.__parseXpathFile__(source)
 
class CannedQuery(DataParser):
 
        def __init__(self, type, source):
                super(CannedQuery, self).__init__(type)
                self.source = source
                self.terrainMap = { '0': 'Not defined', '1': 'Road', '2': 'Trail', '3': 'Treadmill', '4': 'Track' }
 
        def getTypesOfTerrain(self):
                tree = self.__getTree__(self.source)
                count = {}
                for elem in tree.findall(".//terrain"):
                        key = 'Never collected'
                        if elem.text in self.terrainMap:
                                key = self.terrainMap[elem.text]
                        if key in count:
                                count[key] += 1
                        else:
                                count[key] = 1
                return count
 
if __name__ == "__main__":
        argv = sys.argv[1:]
        if len(argv) > 0:
                dp = CannedQuery('file', argv[0])
                count = dp.getTypesOfTerrain()
                print "%s" % count

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 :-)

internet, java, javafx, kodegeek, vida sana

Jython + JavaFX: Comienzo duro

Domingo, 9 de octubre de 2011

Al fin Oracle liberó su versión final de JavFX en JavaOne 2011; También hay una versión beta para OSX la cual me baje de una vez.

Jugando con los ejemplos me dediqué a experimentar con el ejemplo de un gráfico de torta el cual se ve sencillo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.chart.PieChart;
import javafx.scene.Group;
 
public class PieChartSample extends Application {
 
    @Override public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Imported Fruits");
        stage.setWidth(500);
        stage.setHeight(500);
 
        ObservableList pieChartData =
                FXCollections.observableArrayList(
                new PieChart.Data("Grapefruit", 13),
                new PieChart.Data("Oranges", 25),
                new PieChart.Data("Plums", 10),
                new PieChart.Data("Pears", 22),
                new PieChart.Data("Apples", 30));
        final PieChart chart = new PieChart(pieChartData);
        chart.setTitle("Imported Fruits");
 
        ((Group) scene.getRoot()).getChildren().add(chart);
        stage.setScene(scene);
        stage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
}

Lo compilamos y corremos:

1
2
3
Macintosh:javafx josevnz$ export CLASSPATH=/Users/Shared/javafx-sdk2.0.2-beta//rt/lib/jfxrt.jar:.
Macintosh:javafx josevnz$ javac PieChartSample.java -d .
Macintosh:javafx josevnz$ java PieChartSample

JavaFX Pie chartJavaFX gráfico de torta en acción

Así que traté de convertir este sencillo código a Jython:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/usr/bin/env jython
import sys
from javafx.application import Application
from javafx.collections import FXCollections
from javafx.collections import ObservableList
from javafx.scene import Scene
from javafx.stage import Stage
from javafx.scene.chart import PieChart
from javafx.scene import Group
 
class PieChartSample(Application):
 
    def __init__(self):
        pass
 
    def 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:

1
public static void launch(String[] args);

and

1
public static void launch(Class< ? extends Application> appClass, String[] args);

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
public class Foo extends Application {
    @Override
    public void start(Stage stage) {
      // build the scene graph and show it
    }
 
    public static void 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
public class Foo extends Application {
  @Override
  public void start(Stage stage) {
    // build the scene graph and show it
  }
}
 
public class Launcher {
  public static void 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.

java, javafx, python

Es el tiempo de recuperación, idiota

Jueves, 29 de septiembre de 2011

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.

Mi implementación en Python a continuación:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/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/blog
import sys
 
class 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:
                                raise Exception("Invalid age value: %s" % age)
                        for bracket in [ 20, 30, 40, 40, 50, 70, 80 ]:
                                if dAge >= bracket and dAge < = (bracket + 9):
                                        return str(bracket)
                        # > 80 years
                        return 80
                except (Exception), exp:
                        raise Exception("Invalid age: %s" % age)
 
        def getDaysBetweenWorkouts(self, age, level):
                try:
                        bracket = self.getAgeBracket(age)
                        dBracket = self.__ages[bracket]
                        intensity = self.__fitnessLevel[level]
                        return self.__daysBetweenWorkouts[dBracket][intensity] * self.__adjustment[bracket]
                except (Exception), exp:
                        raise Exception("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]
                        return self.__recoveryDaysAfterRace[dBracket][intensity] * self.__adjustment[bracket]
                except (Exception), exp:
                        raise Exception("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 = 0
        if len(arg) == 2:
                days = recovery.getDaysBetweenWorkouts(arg[0], arg[1])
                print "Days: %2.2f, for age: '%s' and level: '%s'" % (days, arg[0], arg[1])
        elif len(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?

Bueno, hasta la próxima entrega.

–José

kodegeek, python, vida sana

2011 Komen Greater NYC Race for The Cure

Miércoles, 7 de septiembre de 2011

Bueno, ya dejando atrás la carrera del Yankee Stadium ahora me lanzo con quizas la última carrera de 5 kilómetros de este año para mi.

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.

java

¿Corriendo muy rápido al principio de una carrera? No necesariamente

Martes, 12 de julio de 2011

Franela Vino Tinto 2011 - Edición Copa America
En plena Copa America, y yo ahora corriendo luciendo los colores de la Vino Tinto.

En preparación para mi carrera en el Yankee Stadium, me conseguí un excelente articulo en el sitio web de RunnersWorld, el cual explica que tan rápido hay que ir en la primera milla para tener una ventaja más que decente, sin quemarse después en el resto de la carrera. Esto se aplica para carreras de 5 kilómetros, el código es muy fácil de seguir:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/env python
# author: josevnz@kodegeek.com
# http://kodegeek.com/blog
import re
import sys
 
'''
Formula taken from:
http://www.runnersworld.com/article/0,7120,s6-238-244--11404-2-1-2,00.html"To
figure your 6 percent faster first mile: First convert your best 5-K
time to all seconds by multiplying the minutes by 60 and adding the
seconds. Say, you've run 24:19. That would be 24 x 60, + 19 = 1459.
Now divide this total by 3.1 (miles in 5-K) to get your average mile
time in seconds (1459/3.1 = 470.6, or about 7:51 pace). Next multiply
this figure by .94 to get a figure that's 6 percent faster (470.6 x
.94 = 4
42.36). Now divide by 60 to return the figure to minutes:seconds
(442.36/60 = 7:22). So you should aim to run your first mile in 7:22.
Good l
uck!"
'''
def calc_time(time):
       if len(time) == 0:
           return None
       if len(time[0]) > 0:
               m = re.search('(\d+):(\d+)', time[0])
               min = m.group(1)
               sec = m.group(2)
               if len(min) > 0 and len(sec) > 0:
                       secs = (int(min) * 60.0) + int(sec)
                       secs /= 3.1
                       secs *= 0.94
                       mins = secs / 60.0
                       n = re.search('(\d+)\.(\d+)', str(mins))
                       realsecs = "0." + n.group(2)
                       realsecs = round(float(realsecs) * 60)
                       return str(int(mins)) + ":" + str(int(realsecs))
       return None
 
 
if __name__ == "__main__":
       secs = calc_time(sys.argv[1:])
       print "Pace for first mile in 5K: %s" % secs

Por ejemplo, si usted hizo 22:30 en su última carrera (Bueno, eso lo hice yo :-) ):

Macintosh:python josevnz$ ./fastmile5k.py 22:30
Pace for first mile in 5K: 6:49
Macintosh:python josevnz$

¿Qué piensa usted, correr rápido al principio o ir lento y explotar gradualmente?

programación, python, vida sana

Nueva carrera de 5 kilómetros, ¡esta vez en el Yankee Stadium!

Domingo, 12 de junio de 2011

Amigos y lectores del blog, este 7 de Agosto voy a correr la carrera de 5K en el Yankee Stadium en el estado de New York; Los fondos recolectados van a ser utilizados para estudios de cura contra el Cancer.

Yo estoy recaudando fondos como parte de la carrera, los invito a que donen cualquier cantidad ya que es para una buena causa.

Un abrazo y gracias de antemano,

–José

java , , , , , , ,

¿Como calcular cuantas calorias al día se deben consumir, usando Python?

Lunes, 30 de mayo de 2011

Está bien, es una excusa barata para usar Python para calcular una formula trivial :-) . Sin embargo la idea es útil:

  • Usted quiere saber cuantas calorías debe consumir al día para mantener un peso saludable
  • Sigue la proporción 40/ 30 / 30: %40 de proteínas, %30 de hidratos de carbono y %30 de grasas
  • Usted come 6 veces al día, para mantener su metabolismo activo

Por ejemplo, la salida del programa para una persona que pesa 196 libras:

1
2
3
4
5
Macintosh:python josevnz$ ./calories.py 
Please provide your weight in LB:
196
Daily calories for 196 lb: 2640. Grams of Protein: 44/264, Grams of Carbs: 33/198, Grams of Fat: 14/88
Macintosh:python josevnz$

programa que llama a la clase en Python:

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python
# Author: josevnz at kodegeek dot com
# http://kodegeek.com/blog
 
from sys import stdin
from com.kodegeek.fitness.nutrition import CalorieNeeds
 
if __name__ == "__main__":
        print "Please provide your weight in LB:"
        weight = int(stdin.readline())
        c = CalorieNeeds(weight)
        print "%s" % c

Y la clase en Python que hace el trabajo ‘pesado’:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/env python
class CalorieNeeds:
        """Simple class to determine the daily calorie intake. josevnz at kodegeek dot com"""
 
        def __init__(self, weight):
 
                self.weight = weight
 
                # Calculate daily calorie needs
                self.calorieIntake = (self.weight * 15) - 300
 
                # Calculate the 40/30/30 macronutriend breakdown
                # Proteins
                self.proteinsGramsDay = (self.calorieIntake * 0.40) / 4
                self.proteinsGramsPerMeal = self.proteinsGramsDay / 6
 
                # Carbs
                self.carbGramsDay = (self.calorieIntake * 0.30) / 4
                self.carbGramsPerMeal = self.carbGramsDay / 6
 
                # Fat
                self.fatGramsDay = (self.calorieIntake * 0.30) / 9
                self.fatGramsPerMeal = self.fatGramsDay / 6
 
        def __str__(self):
                return "Daily calories for %s lb: %d. Grams of Protein: %d/%d, Grams of Carbs: %d/%d, Grams of Fat: %d/%d" % (self.weight, self.calorieIntake, self.proteinsGramsPerMeal, self.proteinsGramsDay, self.carbGramsPerMeal, self.carbGramsDay, self.fatGramsPerMeal, self.fatGramsDay)
 
if __name__ == "__main__":
        """Self test code"""
        c = CalorieNeeds(158)
        print "%s" % c

Les dejo como ejercicio como convertir estos resultados a kilogramos, hoy tengo algo de pereza (el enlace para bajarse el código está aquí) :-)

–José

kodegeek, python, vida sana