Shift over rest of choices to IntegerChoices
[climbing.kerkeslager.com] / src / climbing / models.py
index 71a8362..69bbc9f 100644 (file)
@@ -1,3 +1,216 @@
+from django.contrib.auth.models import User
 from django.db import models
 
-# Create your models here.
+from core import utils
+
+class Area(models.Model):
+    name = models.CharField(max_length=64)
+    notes = models.TextField(blank=True, null=True)
+
+    def __str__(self):
+        return self.name
+
+    @property
+    def sub_areas(self):
+        return utils.merge(
+            self.crags.order_by('name'),
+            self.clusters.order_by('name'),
+            'name',
+        )
+
+class Crag(models.Model):
+    area = models.ForeignKey(
+        Area,
+        on_delete=models.CASCADE,
+        related_name='crags',
+    )
+    name = models.CharField(max_length=64)
+    notes = models.TextField(blank=True, null=True)
+
+    def __str__(self):
+        return self.name
+
+class Route(models.Model):
+    area = models.ForeignKey(
+        Crag,
+        on_delete=models.CASCADE,
+        related_name='routes',
+    )
+    name = models.CharField(max_length=64)
+    mountain_project = models.URLField(blank=True, null=True)
+    notes = models.TextField(blank=True, null=True)
+
+    def __str__(self):
+        pitch_count = self.pitches.count()
+
+        if pitch_count == 0:
+            return self.name
+
+        if pitch_count == 1:
+            return '{} {}'.format(self.name, self.difficulty_display)
+
+        return '{} {} ({} pitches)'.format(
+            self.name,
+            self.difficulty_display,
+            pitch_count,
+        )
+
+    @property
+    def difficulty(self):
+        diff = -1
+
+        for pitch in self.pitches.all():
+            diff = max(diff, pitch.difficulty)
+
+        return diff
+
+    @property
+    def difficulty_display(self):
+        return RouteDifficulty(self.difficulty).label
+
+class RouteDifficulty(models.IntegerChoices):
+    YDS_5_0 = 0, '5.0'
+    YDS_5_1 = 1, '5.1'
+    YDS_5_2 = 2, '5.2'
+    YDS_5_3 = 3, '5.3'
+    YDS_5_4 = 4, '5.4'
+    YDS_5_5 = 5, '5.5'
+    YDS_5_6 = 6, '5.6'
+    YDS_5_6p = 7, '5.6+'
+    YDS_5_7 = 8, '5.7'
+    YDS_5_7p = 9, '5.7+'
+    YDS_5_8 = 10, '5.8'
+    YDS_5_8p = 11, '5.8+'
+    YDS_5_9m = 12, '5.9-'
+    YDS_5_9 = 13, '5.9'
+    YDS_5_9p = 14, '5.9+'
+    YDS_5_10a = 15, '5.10a'
+    YDS_5_10b = 16, '5.10b'
+    YDS_5_10c = 17, '5.10c'
+    YDS_5_10d = 18, '5.10d'
+    YDS_5_11a = 19, '5.11a'
+    YDS_5_11b = 20, '5.11b'
+    YDS_5_11c = 21, '5.11c'
+    YDS_5_11d = 22, '5.11d'
+    YDS_5_12a = 23, '5.12a'
+    YDS_5_12b = 24, '5.12b'
+    YDS_5_12c = 25, '5.12c'
+    YDS_5_12d = 26, '5.12d'
+    YDS_5_13a = 27, '5.13a'
+    YDS_5_13b = 28, '5.13b'
+    YDS_5_13c = 29, '5.13c'
+    YDS_5_13d = 30, '5.13d'
+    YDS_5_14a = 31, '5.14a'
+    YDS_5_14b = 32, '5.14b'
+    YDS_5_14c = 33, '5.14c'
+    YDS_5_14d = 34, '5.14d'
+    YDS_5_15a = 35, '5.15a'
+    YDS_5_15b = 36, '5.15b'
+    YDS_5_15c = 37, '5.15c'
+    YDS_5_15d = 38, '5.15d'
+
+class Safety(models.IntegerChoices):
+    G = 0, 'G'
+    PG = 1, 'PG'
+    PG13 = 2, 'PG13'
+    R = 3, 'R'
+    X = 4, 'X'
+
+class Pitch(models.Model):
+    route = models.ForeignKey(
+        Route,
+        on_delete=models.CASCADE,
+        related_name='pitches',
+    )
+    name = models.CharField(max_length=64, blank=True, null=True)
+    difficulty = models.PositiveIntegerField(choices=RouteDifficulty.choices)
+    safety = models.IntegerField(choices=Safety.choices)
+    notes = models.TextField(blank=True, null=True)
+
+    class Meta:
+        verbose_name_plural = 'pitches'
+
+    def __str__(self):
+        if self.name:
+            return '{} ({})'.format(self.name, self.difficulty)
+        return 'Pitch ({})'.format(self.difficulty)
+
+class Cluster(models.Model):
+    area = models.ForeignKey(
+        Area,
+        on_delete=models.CASCADE,
+        related_name='clusters',
+    )
+    name = models.CharField(max_length=64)
+    notes = models.TextField(blank=True, null=True)
+
+    def __str__(self):
+        return self.name
+
+class Boulder(models.Model):
+    cluster = models.ForeignKey(
+        Cluster,
+        on_delete=models.CASCADE,
+        related_name='boulders',
+    )
+    name = models.CharField(max_length=64)
+    notes = models.TextField(blank=True, null=True)
+
+    def __str__(self):
+        return self.name
+
+class BoulderDifficylty(models.IntegerChoices):
+    V0 = 0, 'V0'
+    V1 = 1, 'V1'
+    V2 = 2, 'V2'
+    V3 = 3, 'V3'
+    V4 = 4, 'V4'
+    V5 = 5, 'V5'
+    V6 = 6, 'V6'
+    V7 = 7, 'V7'
+    V8 = 8, 'V8'
+    V9 = 9, 'V9'
+    V10 = 10, 'V10'
+    V11 = 11, 'V11'
+    V12 = 12, 'V12'
+    V13 = 13, 'V13'
+    V14 = 14, 'V14'
+    V15 = 15, 'V15'
+    V16 = 16, 'V16'
+    V17 = 17, 'V17'
+
+
+class Problem(models.Model):
+    boulder = models.ForeignKey(
+        Boulder,
+        on_delete=models.CASCADE,
+        related_name='problems',
+    )
+    name = models.CharField(max_length=64)
+    difficulty = models.IntegerField(choices=BoulderDifficylty.choices)
+    safety = models.IntegerField(choices=Safety.choices)
+    mountain_project = models.URLField(blank=True, null=True)
+    notes = models.TextField(blank=True, null=True)
+
+    def __str__(self):
+        return '{} ({})'.format(self.name, self.difficulty)
+
+class RouteTodo(models.Model):
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    route = models.ForeignKey(Route, on_delete=models.CASCADE)
+
+class ProblemTodo(models.Model):
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    problem = models.ForeignKey(Problem, on_delete=models.CASCADE)
+
+class RouteTick(models.Model):
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    route = models.ForeignKey(Route, on_delete=models.CASCADE)
+    timestamp = models.DateTimeField()
+    notes = models.TextField(blank=True, null=True)
+
+class ProblemTick(models.Model):
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    problem = models.ForeignKey(Problem, on_delete=models.CASCADE)
+    timestamp = models.DateTimeField()
+    notes = models.TextField(blank=True, null=True)