Workout With Friends Stay fit with a little motivation

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Properties
challenge.py
Go to the documentation of this file.
1 from __future__ import unicode_literals
2 from sqlalchemy.ext.declarative import declared_attr
3 from sqlalchemy.orm import backref, relationship
4 from sqlalchemy.schema import Column, ForeignKey
5 from sqlalchemy.types import DateTime, Integer, Numeric, SmallInteger
6 from wowf.lib.utils import current_timestamp
7 from wowf.models.lookup_tables import ChallengeType
8 from wowf.models.meta import Base
9 from wowf.models.pivot_tables import UserChallenge
10
11
12 ##
13 #
14 # Base class for ALL challenges.
15 #
16 class Challenge(Base):
17
18 __tablename__ = 'challenges'
19 __mapper_args__ = {'polymorphic_on': 'challenge_type_id', 'with_polymorphic': '*'}
20 id = Column(Integer(unsigned=True), primary_key=True)
21 user_id = Column(Integer(unsigned=True), ForeignKey('users.id'), nullable=False)
22 challenge_type_id = Column(
23 Integer(unsigned=True), ForeignKey('challenge_types.id', ondelete='cascade'),
24 nullable=False)
25 created_at = Column(DateTime, nullable=False, default=current_timestamp)
26
27 _creator = relationship('User', lazy='joined')
28 competitors = relationship(
29 'User', backref=backref('challenges', lazy='dynamic'),
30 secondary='users_challenges', lazy='dynamic')
31
32 def _get_creator(self):
33 return self._creator
34
35 ##
36 #
37 # Set the creator, and accept the challenge for him.
38 #
39 def _set_creator(self, creator):
40 self._creator = creator
41 pivot = UserChallenge.create(creator, self)
42 pivot.accept()
43
44 creator = property(_get_creator, _set_creator)
45
46 ##
47 #
48 # Add the user to the list of competitors.
49 #
50 def add_competitor(self, user):
51 if user not in self.competitors:
52 self.competitors.append(user)
53
54 ##
55 #
56 # Remove the user from the list of competitors.
57 #
58 def remove_competitor(self, user):
59 if user in self.competitors:
60 self.competitors.remove(user)
61
62 ##
63 #
64 # Check if the challenge requires the use of a heart rate device.
65 #
66 def is_device_challenge(self):
67 return isinstance(self, DeviceChallenge)
68
69 ##
70 #
71 # Check if the challenge is a weight lifting challenge.
72 #
73 def is_weight_challenge(self):
74 return isinstance(self, WeightChallenge)
75
76 ##
77 #
78 # Check if the challenge is a speed challenge.
79 #
80 def is_speed_challenge(self):
81 return isinstance(self, SpeedChallenge)
82
83 ##
84 #
85 # Check if the challenge is an endurance challenge.
86 #
87 def is_endurance_challenge(self):
88 return isinstance(self, EnduranceChallenge)
89
90 ##
91 #
92 # Check if the challenge is a bench press challenge.
93 #
94 def is_bench_press_challenge(self):
95 return isinstance(self, BenchPressChallenge)
96
97 ##
98 #
99 # Check if the challenge is a squat challenge.
100 #
101 def is_squat_challenge(self):
102 return isinstance(self, SquatChallenge)
103
104 ##
105 #
106 # Check if both competitors have uploaded a workout.
107 #
108 def is_completed(self):
109 return self.workouts.count() == 2
110
111 ##
112 #
113 # Check if given user is the winner of the challenge.
114 #
115 def user_is_winner(self, user):
116 if self.is_completed():
117 winning_workout = self.workouts.order_by(Workout.points.desc()).first()
118 return user is winning_workout.user
119
120 ##
121 #
122 # Used for SQLAlchemys joined table inheritance (polymorphism).
123 #
124 class _Challenge(object):
125
126 @declared_attr
127 def id(cls):
128 return Column(
129 Integer(unsigned=True), ForeignKey('challenges.id', ondelete='cascade'),
130 primary_key=True)
131
132
133 ##
134 #
135 # Base class for all challenges which require the use of a heart rate device.
136 #
137 class DeviceChallenge(_Challenge):
138 pass
139
140
141 ##
142 #
143 # Base class for all weight related challenges.
144 #
145 class WeightChallenge(_Challenge):
146
147 percentage = Column(Numeric(3, 2), nullable=False, doc='percentage of body weight')
148
149 @classmethod
150 def create(cls, creator, percentage):
151 return super(WeightChallenge, cls).create(creator=creator, percentage=percentage)
152
153 ##
154 #
155 # How much weight this user needs to lift for this competition.
156 #
157 def calculate_user_weight(self, user):
158 return round(self.percentage * user.weight, 2)
159
160
161 class SpeedChallenge(DeviceChallenge, Challenge):
162
163 __tablename__ = 'speed_challenges'
164 __mapper_args__ = {'polymorphic_identity': ChallengeType.lookup_data.index('speed') + 1}
165 distance = Column(SmallInteger(unsigned=True), nullable=False, doc='distance in meters')
166
167 @property
168 def description(self):
169 return 'Sprint %d meters as fast as you can. The person with the fastest time wins.' % (
170 self.distance)
171
172 def __unicode__(self):
173 return '%d meter speed challenge' % self.distance
174
175 @classmethod
176 def create(cls, creator, distance):
177 return super(SpeedChallenge, cls).create(creator=creator, distance=distance)
178
179
180 class EnduranceChallenge(DeviceChallenge, Challenge):
181
182 __tablename__ = 'endurance_challenges'
183 __mapper_args__ = {'polymorphic_identity': ChallengeType.lookup_data.index('endurance') + 1}
184 duration = Column(SmallInteger(unsigned=True), nullable=False, doc='duration in minutes')
185
186 @property
187 def description(self):
188 return 'Run as hard as you can for %d minutes. The person with the highest vitals wins.' % (
189 self.duration)
190
191 def __unicode__(self):
192 return '%d minute endurance challenge' % self.duration
193
194 @classmethod
195 def create(cls, creator, duration):
196 return super(EnduranceChallenge, cls).create(creator=creator, duration=duration)
197
198
199 class BenchPressChallenge(WeightChallenge, Challenge):
200
201 __tablename__ = 'bench_press_challenges'
202 __mapper_args__ = {'polymorphic_identity': ChallengeType.lookup_data.index('bench_press') + 1}
203
204 @property
205 def description(self):
206 return 'Bench press %d%% of your body weight for as many repetitions as you can. The person with the most repetitions wins.' % (
207 self.percentage * 100)
208
209 def __unicode__(self):
210 return '%d%% bench press challenge' % (self.percentage * 100)
211
212
213 class SquatChallenge(WeightChallenge, Challenge):
214
215 __tablename__ = 'squat_challenges'
216 __mapper_args__ = {'polymorphic_identity': ChallengeType.lookup_data.index('squat') + 1}
217
218 @property
219 def description(self):
220 return 'Squat %d%% of your body weight for as many repetitions as you can. The person with the most repetitions wins.' % (
221 self.percentage * 100)
222
223 def __unicode__(self):
224 return '%d%% squat challenge' % (self.percentage * 100)
225
226
227 from wowf.models.workout import Workout
228