Workout With Friends
Stay fit with a little motivation
 All Classes Namespaces Files Functions Variables Properties
utils.py
Go to the documentation of this file.
1 ##
2 #
3 # Miscellaneous helper functions.
4 #
5 
6 import csv
7 import inspect
8 import math
9 import times
10 from datetime import date, datetime
11 
12 
13 TIMESTAMP = 'timestamp_epoch'
14 DISTANCE = 'DISTANCE'
15 HEARTRATE = 'HEARTRATE'
16 CALORIEBURN = 'CALORIEBURN'
17 
18 
19 ##
20 #
21 # Parse and extract the needed data from the csv of the workout report.
22 #
23 def parse_workout_report(workout_report):
24  csv_reader = csv.reader(workout_report)
25  csv_header = None
26  samples = {}
27  try:
28  while not csv_header:
29  csv_header = csv_reader.next()
30  except:
31  return samples
32  for row in csv_reader:
33  try:
34  samples.setdefault('timestamp', []).append(float(row[csv_header.index(TIMESTAMP)]))
35  samples.setdefault('distance', []).append(float(row[csv_header.index(DISTANCE)]))
36  samples.setdefault('heart_rate', []).append(float(row[csv_header.index(HEARTRATE)]))
37  samples.setdefault('calories_burned', []).append(float(row[csv_header.index(CALORIEBURN)]))
38  except:
39  pass
40  if samples['timestamp']:
41  # Downshift timestamps
42  leading_timestamp = samples['timestamp'][0]
43  samples['timestamp'] = map(lambda x: x - leading_timestamp, samples['timestamp'])
44  return samples
45 
46 
47 ##
48 #
49 # Calculate the wilkes coefficient for this user.
50 #
51 # @param weight The users weight (kg).
52 #
53 def calculate_wilks_coefficient(weight, gender):
54  x = weight
55  if gender == 'M':
56  a = -216.0475144
57  b = 16.2606339
58  c = -0.002388645
59  d = -0.00113732
60  e = 7.01863e-06
61  f = -1.291e-08
62  else:
63  a = 594.31747775582
64  b = -27.23842536447
65  c = 0.82112226871
66  d = -0.00930733913
67  e = 0.00004731582
68  f = -0.00000009054
69  return 500.0 / (a + b * x + c * x**2 + d * x**3 + e * x**4 + f * x**5)
70 
71 
72 ##
73 #
74 # Calculate the estimated one rep max.
75 #
76 # @param weight How much weight the user lifted.
77 # @param repetitions How many times the user lifted the weight.
78 #
79 def calculate_one_rep_max(weight, repetitions):
80  w = weight
81  r = repetitions
82  return (100.0 * w) / (48.8 + 53.8 * math.exp(-0.075 * r))
83 
84 
85 ##
86 #
87 # Calculate a persons body mass index, given weight (kg) and height (m).
88 #
89 def calculate_bmi(weight, height):
90  try:
91  return round(weight / (height ** 2), 1)
92  except:
93  return False
94 
95 
96 ##
97 #
98 # Calculate the difference in years between the start date and today.
99 #
100 def years_ago(start_dt):
101  today = date.today()
102  if isinstance(start_dt, datetime):
103  start_dt = start_dt.date()
104  try:
105  dt = start_dt.replace(year=today.year)
106  except ValueError:
107  # Start date is February 29 and the current year is not a leap year
108  dt = start_dt.replace(year=today.year, day=start_dt.day-1)
109  if dt > today:
110  return today.year - start_dt.year - 1
111  else:
112  return today.year - start_dt.year
113 
114 
115 ##
116 #
117 # Get all classes residing in a given module which subclass a given base class.
118 #
119 # @param with_base Whether to include the base class also
120 #
121 def get_subclasses(module, base, with_base=False):
122  subclasses = []
123  for name, cls in inspect.getmembers(module):
124  if inspect.isclass(cls) and issubclass(cls, base):
125  if not with_base and cls is base:
126  continue
127  subclasses.append(cls)
128  return subclasses
129 
130 
131 ##
132 #
133 # Split a comma separated list by both newlines and commas.
134 #
135 def split_cslist(cslist):
136  items = []
137  for line in cslist.splitlines():
138  for item in line.split(','):
139  item.strip() and items.append(item.strip())
140  return items
141 
142 
144  return datetime.utcnow()
145 
146 
147 ##
148 #
149 # Convert a datetime from system timezone to the given timezone.
150 #
151 def to_user_timezone(dt, timezone):
152  from wowf.config import settings
153  timezone = timezone or settings.timezone
154  return times.to_local(dt, timezone)
155 
156 
157 ##
158 #
159 # Convert a datetime from the given timezone to system timezone.
160 #
161 def to_system_timezone(dt, timezone):
162  from wowf.config import settings
163  timezone = timezone or settings.timezone
164  return times.to_universal(dt, timezone)
165 
166 
167 ##
168 #
169 # Get the days, hours, and minutes from a timedelta object.
170 #
172  days, hours, minutes = td.days, td.seconds // 3600, (td.seconds // 60) % 60
173  return Storage(days=days, hours=hours, minutes=minutes)
174 
175 
176 ##
177 #
178 # Return a dictionary of settings all containing the same key prefix, with the
179 # prefix removed from the keys.
180 #
181 def settings_from_prefix(settings, prefix):
182  data = {}
183  for key in settings:
184  if key.startswith(prefix):
185  data[key.replace(prefix, '')] = settings[key]
186  return data
187 
188 
189 ##
190 #
191 # Generic container class.
192 #
193 class Storage(dict):
194 
195  def __getattr__(self, key):
196  try:
197  return self[key]
198  except KeyError as e:
199  raise AttributeError(e)
200 
201  def __setattr__(self, key, value):
202  self[key] = value
203 
204  def __delattr__(self, key):
205  try:
206  del self[key]
207  except KeyError as e:
208  raise AttributeError(e)
209