1 from django.contrib.auth.models import User
2 from django.db import models
6 class Area(models.Model):
7 name = models.CharField(max_length=64)
8 notes = models.TextField(blank=True, null=True)
16 self.crags.order_by('name'),
17 self.clusters.order_by('name'),
21 class Crag(models.Model):
22 area = models.ForeignKey(
24 on_delete=models.CASCADE,
27 name = models.CharField(max_length=64)
28 notes = models.TextField(blank=True, null=True)
33 class Route(models.Model):
34 area = models.ForeignKey(
36 on_delete=models.CASCADE,
37 related_name='routes',
39 name = models.CharField(max_length=64)
40 mountain_project = models.URLField(blank=True, null=True)
41 notes = models.TextField(blank=True, null=True)
44 pitch_count = self.pitches.count()
50 return '{} {}'.format(self.name, self.difficulty_display)
52 return '{} {} ({} pitches)'.format(
54 self.difficulty_display,
62 for pitch in self.pitches.all():
63 diff = max(diff, pitch.difficulty)
68 def difficulty_display(self):
69 return RouteDifficulty(self.difficulty).label
71 class RouteDifficulty(models.IntegerChoices):
87 YDS_5_10a = 15, '5.10a'
88 YDS_5_10b = 16, '5.10b'
89 YDS_5_10c = 17, '5.10c'
90 YDS_5_10d = 18, '5.10d'
91 YDS_5_11a = 19, '5.11a'
92 YDS_5_11b = 20, '5.11b'
93 YDS_5_11c = 21, '5.11c'
94 YDS_5_11d = 22, '5.11d'
95 YDS_5_12a = 23, '5.12a'
96 YDS_5_12b = 24, '5.12b'
97 YDS_5_12c = 25, '5.12c'
98 YDS_5_12d = 26, '5.12d'
99 YDS_5_13a = 27, '5.13a'
100 YDS_5_13b = 28, '5.13b'
101 YDS_5_13c = 29, '5.13c'
102 YDS_5_13d = 30, '5.13d'
103 YDS_5_14a = 31, '5.14a'
104 YDS_5_14b = 32, '5.14b'
105 YDS_5_14c = 33, '5.14c'
106 YDS_5_14d = 34, '5.14d'
107 YDS_5_15a = 35, '5.15a'
108 YDS_5_15b = 36, '5.15b'
109 YDS_5_15c = 37, '5.15c'
110 YDS_5_15d = 38, '5.15d'
112 class Safety(models.IntegerChoices):
119 class Pitch(models.Model):
120 route = models.ForeignKey(
122 on_delete=models.CASCADE,
123 related_name='pitches',
125 name = models.CharField(max_length=64, blank=True, null=True)
126 difficulty = models.PositiveIntegerField(choices=RouteDifficulty.choices)
127 safety = models.IntegerField(choices=Safety.choices)
128 notes = models.TextField(blank=True, null=True)
131 verbose_name_plural = 'pitches'
135 return '{} ({})'.format(self.name, self.difficulty)
136 return 'Pitch ({})'.format(self.difficulty)
138 class Cluster(models.Model):
139 area = models.ForeignKey(
141 on_delete=models.CASCADE,
142 related_name='clusters',
144 name = models.CharField(max_length=64)
145 notes = models.TextField(blank=True, null=True)
150 class Boulder(models.Model):
151 cluster = models.ForeignKey(
153 on_delete=models.CASCADE,
154 related_name='boulders',
156 name = models.CharField(max_length=64)
157 notes = models.TextField(blank=True, null=True)
162 class BoulderDifficylty(models.IntegerChoices):
183 class Problem(models.Model):
184 boulder = models.ForeignKey(
186 on_delete=models.CASCADE,
187 related_name='problems',
189 name = models.CharField(max_length=64)
190 difficulty = models.IntegerField(choices=BoulderDifficylty.choices)
191 safety = models.IntegerField(choices=Safety.choices)
192 mountain_project = models.URLField(blank=True, null=True)
193 notes = models.TextField(blank=True, null=True)
196 return '{} ({})'.format(self.name, self.difficulty)
198 class RouteTodo(models.Model):
199 user = models.ForeignKey(User, on_delete=models.CASCADE)
200 route = models.ForeignKey(Route, on_delete=models.CASCADE)
202 class ProblemTodo(models.Model):
203 user = models.ForeignKey(User, on_delete=models.CASCADE)
204 problem = models.ForeignKey(Problem, on_delete=models.CASCADE)
206 class RouteTick(models.Model):
207 user = models.ForeignKey(User, on_delete=models.CASCADE)
208 route = models.ForeignKey(Route, on_delete=models.CASCADE)
209 timestamp = models.DateTimeField()
210 notes = models.TextField(blank=True, null=True)
212 class ProblemTick(models.Model):
213 user = models.ForeignKey(User, on_delete=models.CASCADE)
214 problem = models.ForeignKey(Problem, on_delete=models.CASCADE)
215 timestamp = models.DateTimeField()
216 notes = models.TextField(blank=True, null=True)