Example #1
0
class WorkoutSession(models.Model):
    """
    Model for a workout session
    """

    # Note: values hardcoded in manager.helpers.WorkoutCalendar
    IMPRESSION_BAD = '1'
    IMPRESSION_NEUTRAL = '2'
    IMPRESSION_GOOD = '3'

    IMPRESSION = (
        (IMPRESSION_BAD, _("Bad")),
        (IMPRESSION_NEUTRAL, _('Neutral')),
        (IMPRESSION_GOOD, _('Good')),
    )

    user = models.ForeignKey(
        User,
        verbose_name=_('User'),
        on_delete=models.CASCADE,
    )
    """
    The user the workout session belongs to

    See note in weight.models.WeightEntry about why this is not editable=False
    """

    workout = models.ForeignKey(
        Workout,
        verbose_name=_('Workout'),
        on_delete=models.CASCADE,
    )
    """
    The workout the session belongs to
    """

    date = Html5DateField(verbose_name=_('Date'))
    """
    The date the workout session was performed
    """

    notes = models.TextField(
        verbose_name=_('Notes'),
        null=True,
        blank=True,
        help_text=_('Any notes you might want to save about this workout '
                    'session.')
    )
    """
    User notes about the workout
    """

    impression = models.CharField(
        verbose_name=_('General impression'),
        max_length=2,
        choices=IMPRESSION,
        default=IMPRESSION_NEUTRAL,
        help_text=_(
            'Your impression about this workout session. '
            'Did you exercise as well as you could?'
        )
    )
    """
    The user's general impression of workout
    """

    time_start = models.TimeField(verbose_name=_('Start time'), blank=True, null=True)
    """
    Time the workout session started
    """

    time_end = models.TimeField(verbose_name=_('Finish time'), blank=True, null=True)
    """
    Time the workout session ended
    """

    def __str__(self):
        """
        Return a more human-readable representation
        """
        return "{0} - {1}".format(self.workout, self.date)

    class Meta:
        """
        Set other properties
        """
        ordering = [
            "date",
        ]
        unique_together = ("date", "user")

    def clean(self):
        """
        Perform some additional validations
        """

        if (not self.time_end and self.time_start) or (self.time_end and not self.time_start):
            raise ValidationError(_("If you enter a time, you must enter both start and end time."))

        if self.time_end and self.time_start and self.time_start > self.time_end:
            raise ValidationError(_("The start time cannot be after the end time."))

    def get_owner_object(self):
        """
        Returns the object that has owner information
        """
        return self

    def save(self, *args, **kwargs):
        """
        Reset cache
        """
        reset_workout_log(self.user_id, self.date.year, self.date.month)
        super(WorkoutSession, self).save(*args, **kwargs)

    def delete(self, *args, **kwargs):
        """
        Reset cache
        """
        reset_workout_log(self.user_id, self.date.year, self.date.month)
        super(WorkoutSession, self).delete(*args, **kwargs)
Example #2
0
class WorkoutLog(models.Model):
    """
    A log entry for an exercise
    """

    user = models.ForeignKey(User,
                             verbose_name=_('User'),
                             editable=False,
                             on_delete=models.CASCADE)
    exercise = models.ForeignKey(Exercise,
                                 verbose_name=_('Exercise'),
                                 on_delete=models.CASCADE)
    workout = models.ForeignKey(Workout,
                                verbose_name=_('Workout'),
                                on_delete=models.CASCADE)

    repetition_unit = models.ForeignKey(RepetitionUnit,
                                        verbose_name=_('Unit'),
                                        default=1,
                                        on_delete=models.CASCADE)
    """
    The unit of the log. This can be e.g. a repetition, a minute, etc.
    """

    reps = models.IntegerField(verbose_name=_('Repetitions'),
                               validators=[MinValueValidator(0)])
    """
    Amount of repetitions, minutes, etc.

    Note that since adding the unit field, the name is no longer correct, but is
    kept for compatibility reasons (specially for the REST API).
    """

    weight = models.DecimalField(decimal_places=2,
                                 max_digits=5,
                                 verbose_name=_('Weight'),
                                 validators=[MinValueValidator(0)])

    weight_unit = models.ForeignKey(WeightUnit,
                                    verbose_name=_('Unit'),
                                    default=1,
                                    on_delete=models.CASCADE)
    """
    The weight unit of the log. This can be e.g. kg, lb, km/h, etc.
    """

    date = Html5DateField(verbose_name=_('Date'))

    rir = models.DecimalField(verbose_name=_('RiR'),
                              decimal_places=1,
                              max_digits=3,
                              blank=True,
                              null=True,
                              choices=RIR_OPTIONS)
    """
    Reps in reserve, RiR. The amount of reps that could realistically still be
    done in the set.
    """

    # Metaclass to set some other properties
    class Meta:
        ordering = ["date", "reps"]

    def __str__(self):
        """
        Return a more human-readable representation
        """
        return "Log entry: {0} - {1} kg on {2}".format(self.reps,
                                                       self.weight,
                                                       self.date)

    def get_owner_object(self):
        """
        Returns the object that has owner information
        """
        return self

    def get_workout_session(self, date=None):
        """
        Returns the corresponding workout session

        :return the WorkoutSession object or None if nothing was found
        """
        if not date:
            date = self.date

        try:
            return WorkoutSession.objects.filter(user=self.user).get(date=date)
        except WorkoutSession.DoesNotExist:
            return None

    def save(self, *args, **kwargs):
        """
        Reset cache
        """
        reset_workout_log(self.user_id, self.date.year, self.date.month, self.date.day)

        # If the user selected "Until Failure", do only 1 "repetition",
        # everythin else doesn't make sense.
        if self.repetition_unit == 2:
            self.reps = 1
        super(WorkoutLog, self).save(*args, **kwargs)

    def delete(self, *args, **kwargs):
        """
        Reset cache
        """
        reset_workout_log(self.user_id, self.date.year, self.date.month, self.date.day)
        super(WorkoutLog, self).delete(*args, **kwargs)
Example #3
0
class WorkoutLog(models.Model):
    '''
    A log entry for an exercise
    '''

    user = models.ForeignKey(User, verbose_name=_('User'), editable=False)
    exercise = models.ForeignKey(Exercise, verbose_name=_('Exercise'))
    workout = models.ForeignKey(Workout, verbose_name=_('Workout'))

    reps = models.IntegerField(verbose_name=_('Repetitions'),
                               validators=[MinValueValidator(0)])

    weight = models.DecimalField(decimal_places=2,
                                 max_digits=5,
                                 verbose_name=_('Weight'),
                                 validators=[MinValueValidator(0)])
    date = Html5DateField(verbose_name=_('Date'))

    # Metaclass to set some other properties
    class Meta:
        ordering = ["date", "reps"]

    def __str__(self):
        '''
        Return a more human-readable representation
        '''
        return u"Log entry: {0} - {1} kg on {2}".format(
            self.reps, self.weight, self.date)

    def get_owner_object(self):
        '''
        Returns the object that has owner information
        '''
        return self

    def get_workout_session(self, date=None):
        '''
        Returns the corresponding workout session

        :return the WorkoutSession object or None if nothing was found
        '''
        if not date:
            date = self.date

        try:
            return WorkoutSession.objects.filter(user=self.user).get(date=date)
        except WorkoutSession.DoesNotExist:
            return None

    def save(self, *args, **kwargs):
        '''
        Reset cache
        '''
        reset_workout_log(self.user_id, self.date.year, self.date.month,
                          self.date.day)
        super(WorkoutLog, self).save(*args, **kwargs)

    def delete(self, *args, **kwargs):
        '''
        Reset cache
        '''
        reset_workout_log(self.user_id, self.date.year, self.date.month,
                          self.date.day)
        super(WorkoutLog, self).delete(*args, **kwargs)
Example #4
0
class Schedule(models.Model):
    """
    Model for a workout schedule.

    A schedule is a collection of workous that are done for a certain time.
    E.g. workouts A, B, C, A, B, C, and so on.
    """

    objects = ScheduleManager()
    """Custom manager"""

    user = models.ForeignKey(User,
                             verbose_name=_('User'),
                             editable=False,
                             on_delete=models.CASCADE)
    """
    The user this schedule belongs to. This could be accessed through a step
    that points to a workout, that points to a user, but this is more straight
    forward and performant
    """

    name = models.CharField(verbose_name=_('Name'),
                            max_length=100,
                            help_text=_("Name or short description of the schedule. "
                                        "For example 'Program XYZ'."))
    """Name or short description of the schedule."""

    start_date = Html5DateField(verbose_name=_('Start date'),
                                default=datetime.date.today)
    """The start date of this schedule"""

    is_active = models.BooleanField(verbose_name=_('Schedule active'),
                                    default=True,
                                    help_text=_("Tick the box if you want to mark this schedule "
                                                "as your active one (will be shown e.g. on your "
                                                "dashboard). All other schedules will then be "
                                                "marked as inactive"))
    """A flag indicating whether the schedule is active (needed for dashboard)"""

    is_loop = models.BooleanField(verbose_name=_('Is a loop'),
                                  default=False,
                                  help_text=_("Tick the box if you want to repeat the schedules "
                                              "in a loop (i.e. A, B, C, A, B, C, and so on)"))
    """A flag indicating whether the schedule should act as a loop"""

    def __str__(self):
        """
        Return a more human-readable representation
        """
        return self.name

    def get_absolute_url(self):
        return reverse('manager:schedule:view', kwargs={'pk': self.id})

    def get_owner_object(self):
        """
        Returns the object that has owner information
        """
        return self

    def save(self, *args, **kwargs):
        """
        Only one schedule can be marked as active at a time
        """
        if self.is_active:
            Schedule.objects.filter(user=self.user).update(is_active=False)
            self.is_active = True

        super(Schedule, self).save(*args, **kwargs)

    def get_current_scheduled_workout(self):
        """
        Returns the currently active schedule step for a user
        """
        steps = self.schedulestep_set.all()
        start_date = self.start_date
        found = False
        if not steps:
            return False
        while not found:
            for step in steps:
                current_limit = start_date + datetime.timedelta(weeks=step.duration)
                if current_limit >= datetime.date.today():
                    found = True
                    return step
                start_date = current_limit

            # If it's not a loop, there's no workout that matches, return
            if not self.is_loop:
                return False

    def get_end_date(self):
        """
        Calculates the date when the schedule is over or None is the schedule
        is a loop.
        """
        if self.is_loop:
            return None

        end_date = self.start_date
        for step in self.schedulestep_set.all():
            end_date = end_date + datetime.timedelta(weeks=step.duration)
        return end_date
Example #5
0
class WorkoutSession(models.Model):
    '''
    Model for a workout session
    '''

    IMPRESSION_BAD = '1'
    IMPRESSION_NEUTRAL = '2'
    IMPRESSION_GOOD = '3'

    IMPRESSION = (
        (IMPRESSION_BAD, _("Bad")),
        (IMPRESSION_NEUTRAL, _('Neutral')),
        (IMPRESSION_GOOD, _('Good')),
    )

    user = models.ForeignKey(User, verbose_name=_('User'))
    '''
    The user the workout session belongs to

    See note in weight.models.WeightEntry about why this is not editable=False
    '''

    workout = models.ForeignKey(Workout, verbose_name=_('Workout'))
    '''
    The workout the session belongs to
    '''

    date = Html5DateField(verbose_name=_('Date'))
    '''
    The date the workout session was performed
    '''

    notes = models.TextField(
        verbose_name=_('Notes'),
        null=True,
        blank=True,
        help_text=_('Any notes you might want to save about this workout '
                    'session.'))
    '''
    User notes about the workout
    '''

    impression = models.CharField(
        verbose_name=_('General impression'),
        max_length=2,
        choices=IMPRESSION,
        default=IMPRESSION_NEUTRAL,
        help_text=_('Your impression about this workout session. '
                    'Did you exercise as well as you could?'))
    '''
    The user's general impression of workout
    '''

    time_start = models.TimeField(verbose_name=_('Start time'),
                                  blank=True,
                                  null=True)
    '''
    Time the workout session started
    '''

    time_end = models.TimeField(verbose_name=_('Finish time'),
                                blank=True,
                                null=True)
    '''
    Time the workout session ended
    '''
    def __unicode__(self):
        '''
        Return a more human-readable representation
        '''
        return u"{0} - {1}".format(self.workout, self.date)

    class Meta:
        '''
        Set other properties
        '''
        ordering = [
            "date",
        ]
        unique_together = ("date", "user")

    def clean(self):
        '''
        Perform some additional validations
        '''

        if (not self.time_end
                and self.time_start) or (self.time_end
                                         and not self.time_start):
            raise ValidationError(
                _("If you enter a time, you must enter both start and end time."
                  ))

        if self.time_end and self.time_start and self.time_start > self.time_end:
            raise ValidationError(
                _("The start time cannot be after the end time."))

    def get_owner_object(self):
        '''
        Returns the object that has owner information
        '''
        return self