Add Mountain Project URLs
[climbing.kerkeslager.com] / src / climbing / models.py
1 from django.contrib.auth.models import User
2 from django.db import models
3
4 class Area(models.Model):
5     name = models.CharField(max_length=64)
6     notes = models.TextField(blank=True, null=True)
7
8     def __str__(self):
9         return self.name
10
11     @property
12     def sub_areas(self):
13         crags = iter(self.crags.order_by('name'))
14         clusters = iter(self.clusters.order_by('name'))
15
16         try:
17             crag = next(crags)
18         except StopIteration:
19             crag = None
20
21         try:
22             cluster = next(clusters)
23         except StopIteration:
24             cluster = None
25
26         while crag and cluster:
27             if crag.name < cluster.name:
28                 yield crag
29                 try:
30                     crag = next(crags)
31                 except:
32                     crag = None
33             else:
34                 yield cluster
35                 try:
36                     cluster = next(clusters)
37                 except:
38                     cluster = None
39
40         while crag:
41             yield crag
42             try:
43                 crag = next(crags)
44             except:
45                 crag = None
46
47         while cluster:
48             yield cluster
49             try:
50                 cluster = next(clusters)
51             except:
52                 cluster = None
53
54 class Crag(models.Model):
55     area = models.ForeignKey(
56         Area,
57         on_delete=models.CASCADE,
58         related_name='crags',
59     )
60     name = models.CharField(max_length=64)
61     notes = models.TextField(blank=True, null=True)
62
63     def __str__(self):
64         return self.name
65
66 class Route(models.Model):
67     area = models.ForeignKey(
68         Crag,
69         on_delete=models.CASCADE,
70         related_name='routes',
71     )
72     name = models.CharField(max_length=64)
73     mountain_project = models.URLField(blank=True, null=True)
74     notes = models.TextField(blank=True, null=True)
75
76     def __str__(self):
77         return self.name
78
79 ROUTE_DIFFICULTY_CHOICES = (
80     ('5.0', '5.0'),
81     ('5.1', '5.1'),
82     ('5.2', '5.2'),
83     ('5.3', '5.3'),
84     ('5.4', '5.4'),
85     ('5.5', '5.5'),
86     ('5.6', '5.6'),
87     ('5.6+', '5.6+'),
88     ('5.7', '5.7'),
89     ('5.7+', '5.7+'),
90     ('5.8', '5.8'),
91     ('5.8+', '5.8+'),
92     ('5.9-', '5.9-'),
93     ('5.9', '5.9'),
94     ('5.9+', '5.9+'),
95     ('5.10a', '5.10a'),
96     ('5.10b', '5.10b'),
97     ('5.10c', '5.10c'),
98     ('5.10d', '5.10d'),
99     ('5.11a', '5.11a'),
100     ('5.11b', '5.11b'),
101     ('5.11c', '5.11c'),
102     ('5.11d', '5.11d'),
103     ('5.12a', '5.12a'),
104     ('5.12b', '5.12b'),
105     ('5.12c', '5.12c'),
106     ('5.12d', '5.12d'),
107     ('5.13a', '5.13a'),
108     ('5.13b', '5.13b'),
109     ('5.13c', '5.13c'),
110     ('5.13d', '5.13d'),
111     ('5.14a', '5.14a'),
112     ('5.14b', '5.14b'),
113     ('5.14c', '5.14c'),
114     ('5.14d', '5.14d'),
115     ('5.15a', '5.15a'),
116     ('5.15b', '5.15b'),
117     ('5.15c', '5.15c'),
118     ('5.15d', '5.15d'),
119 )
120
121 SAFETY_CHOICES = (
122     ('G', 'G'),
123     ('PG', 'PG'),
124     ('PG13', 'PG13'),
125     ('R', 'R'),
126     ('X', 'X'),
127 )
128
129 class Pitch(models.Model):
130     route = models.ForeignKey(
131         Route,
132         on_delete=models.CASCADE,
133         related_name='pitches',
134     )
135     name = models.CharField(max_length=64, null=True)
136     difficulty = models.CharField(max_length=5, choices=ROUTE_DIFFICULTY_CHOICES)
137     safety = models.CharField(max_length=4, choices=SAFETY_CHOICES)
138     notes = models.TextField(blank=True, null=True)
139
140     def __str__(self):
141         if self.name:
142             return '{} ({})'.format(self.name, self.difficulty)
143         return 'Pitch ({})'.format(self.difficulty)
144
145 class Cluster(models.Model):
146     area = models.ForeignKey(
147         Area,
148         on_delete=models.CASCADE,
149         related_name='clusters',
150     )
151     name = models.CharField(max_length=64)
152     notes = models.TextField(blank=True, null=True)
153
154     def __str__(self):
155         return self.name
156
157 class Boulder(models.Model):
158     cluster = models.ForeignKey(
159         Cluster,
160         on_delete=models.CASCADE,
161         related_name='boulders',
162     )
163     name = models.CharField(max_length=64)
164     notes = models.TextField(blank=True, null=True)
165
166     def __str__(self):
167         return self.name
168
169 BOULDER_DIFFICULTY_CHOICES = (
170     ('V0', 'V0'),
171     ('V1', 'V1'),
172     ('V2', 'V2'),
173     ('V3', 'V3'),
174     ('V4', 'V4'),
175     ('V5', 'V5'),
176     ('V6', 'V6'),
177     ('V7', 'V7'),
178     ('V8', 'V8'),
179     ('V9', 'V9'),
180     ('V10', 'V10'),
181     ('V11', 'V11'),
182     ('V12', 'V12'),
183     ('V13', 'V13'),
184     ('V14', 'V14'),
185     ('V15', 'V15'),
186     ('V16', 'V16'),
187     ('V17', 'V17'),
188 )
189
190 class Problem(models.Model):
191     boulder = models.ForeignKey(
192         Boulder,
193         on_delete=models.CASCADE,
194         related_name='problems',
195     )
196     name = models.CharField(max_length=64)
197     difficulty = models.CharField(max_length=3, choices=BOULDER_DIFFICULTY_CHOICES)
198     safety = models.CharField(max_length=4, choices=SAFETY_CHOICES)
199     mountain_project = models.URLField(blank=True, null=True)
200     notes = models.TextField(blank=True, null=True)
201
202     def __str__(self):
203         return '{} ({})'.format(self.name, self.difficulty)
204
205 class RouteTodo(models.Model):
206     user = models.ForeignKey(User, on_delete=models.CASCADE)
207     route = models.ForeignKey(Route, on_delete=models.CASCADE)
208
209 class ProblemTodo(models.Model):
210     user = models.ForeignKey(User, on_delete=models.CASCADE)
211     problem = models.ForeignKey(Problem, on_delete=models.CASCADE)
212
213 class RouteTick(models.Model):
214     user = models.ForeignKey(User, on_delete=models.CASCADE)
215     route = models.ForeignKey(Route, on_delete=models.CASCADE)
216     timestamp = models.DateTimeField()
217     notes = models.TextField(blank=True, null=True)
218
219 class ProblemTick(models.Model):
220     user = models.ForeignKey(User, on_delete=models.CASCADE)
221     problem = models.ForeignKey(Problem, on_delete=models.CASCADE)
222     timestamp = models.DateTimeField()
223     notes = models.TextField(blank=True, null=True)