django-fitlog / fitlog / models.py

from django.db import models
from django.contrib.auth.models import User

from fitlog.utils import addDateTimes
from fitlog.choices import WEIGHT_CHOICES, REP_CHOICES, GENDER_CHOICES
from fitlog.managers import (
    FitLogManager, CardioManager, WeightManager, BodyWeightLogManager)


class UserProfile(models.Model):

  # This is the only required field
    user = models.ForeignKey(User, unique=True)
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)

    def __unicode__(self):
        return u'%s' % self.user.username


class Team(models.Model):
    name = models.CharField(max_length=50)
    description = models.TextField(max_length=255, blank=True)


class FitLog(models.Model):
    member = models.ForeignKey(User)
    create_date = models.DateTimeField(auto_now_add=True)
    last_update = models.DateTimeField(auto_now=True)
    log_date = models.DateField()
    total_time = models.TimeField(blank=True, null=True)
    title = models.CharField(max_length=255)
    comments = models.TextField(max_length=5000, blank=True)

    objects = FitLogManager()

    def __init__(self, *args, **kwargs):
        super(FitLog, self).__init__(*args, **kwargs)
        self.__total_exercises = None
        self.__total_sets = None
        self.__total_reps = None
        self.__training_volume = None
        self.__cardio_min = None
        self.__cardio_distance = None
        self.__calculated = False

    def __calculate_totals(self):
        if not self.__calculated:
            if self.weightfitlogdetail_set:
                self.__total_exercises = self.weightfitlogdetail_set.count()
            else:
                self.__total_exercises = 0

            if self.weightfitlogdetail_set:
                wl = self.weightfitlogdetail_set.all()
                for w in wl:
                    wdl = w.weightlogset_set.all()
                    for wd in wdl:
                        if not self.__total_sets:
                            self.__total_sets = 0
                        if not self.__total_reps:
                            self.__total_reps = 0
                        if not self.__training_volume:
                            self.__training_volume = 0

                        self.__total_sets = self.__total_sets + 1
                        self.__total_reps = self.__total_reps + wd.reps
                        if wd.reps and wd.weight:
                            self.__training_volume = self.__training_volume + (
                                wd.reps * wd.weight)

            if self.cardiofitlogdetail_set:
                cl = self.cardiofitlogdetail_set.all()
                for c in cl:
                        if not self.__cardio_min:
                            self.__cardio_min = 0
                        if not self.__cardio_distance:
                            self.__cardio_distance = 0

                        self.__cardio_min = addDateTimes(self.__cardio_min,
                                                         c.total_time)
                        self.__cardio_distance = (self.__cardio_distance +
                                                  c.distance)

            self.__calculated = True

    @property
    def total_exercises(self):
        if not self.__total_exercises:
            self.__calculate_totals()
        return self.__total_exercises

    @property
    def total_sets(self):
        if not self.__total_sets:
            self.__calculate_totals()
        return self.__total_sets

    @property
    def total_reps(self):
        if not self.__total_reps:
            self.__calculate_totals()
        return self.__total_reps

    @property
    def training_volume(self):
        if not self.__training_volume:
            self.__calculate_totals()
        return self.__training_volume

    @property
    def cardio_min(self):
        if not self.__cardio_min:
            self.__calculate_totals()
        return self.__cardio_min

    @property
    def cardio_distance(self):
        if not self.__cardio_distance:
            self.__calculate_totals()
        return self.__cardio_distance


class FitnessType(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name


class MuscleGroup(models.Model):
    name = models.CharField(max_length=100)

    def __unicode__(self):
        return self.name


class ExerciseType(models.Model):
    fitness_type = models.ForeignKey(FitnessType)
    muscle_group = models.ForeignKey(MuscleGroup, blank=True, null=True)
    name = models.CharField(max_length=50)

    cardio_objects = CardioManager()
    weight_objects = WeightManager()

    def __unicode__(self):
        if self.muscle_group:
            name = "[%s]  %s" % (self.muscle_group.name, self.name)
        else:
            name = "%s " % (self.name)
        return name


class FitLogDetail(models.Model):
    fit_log = models.ForeignKey(FitLog)
    exercise_type = models.ForeignKey(ExerciseType)
    comments = models.CharField(max_length=500, blank=True)

    class Meta:
        abstract = True


class CardioFitLogDetail(FitLogDetail):
    total_time = models.TimeField(blank=True, null=True)
    distance = models.DecimalField(max_digits=5, decimal_places=1)


#TODO PERFORMANCE : Make this better..
class WeightFitLogDetail(FitLogDetail):
    __weights = None

    def __get_weightlogset(self):
        if not self.__weights:
            self.__weights = self.weightlogset_set.all()
        return self.__weights

    def get_weights(self):
        weights = self.__get_weightlogset()
        out = None
        for w in weights:
            if not out:
                out = "%s" % w.weight
            else:
                out = out + "/%s" % w.weight

        return out

    def get_reps(self):
        weights = self.__get_weightlogset()
        out = None
        for w in weights:
            if not out:
                out = "%s" % w.reps
            else:
                out = out + "/%s" % w.reps

        return out


class WeightLogSet(models.Model):
    weight_log_detail = models.ForeignKey(WeightFitLogDetail)
    sequence = models.SmallIntegerField()
    weight = models.SmallIntegerField(choices=WEIGHT_CHOICES)
    reps = models.SmallIntegerField(choices=REP_CHOICES)


class BodyWeightLog(models.Model):
    member = models.ForeignKey(User)
    weight = models.DecimalField(max_digits=5, decimal_places=1)
    weight_date = models.DateField()
    comments = models.TextField(max_length=5000, blank=True)

    objects = BodyWeightLogManager()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.