Add weight record modeling
[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     notes = models.TextField(blank=True, null=True)
74
75     def __str__(self):
76         return self.name
77
78 ROUTE_DIFFICULTY_CHOICES = (
79     ('5.0', '5.0'),
80     ('5.1', '5.1'),
81     ('5.2', '5.2'),
82     ('5.3', '5.3'),
83     ('5.4', '5.4'),
84     ('5.5', '5.5'),
85     ('5.6', '5.6'),
86     ('5.6+', '5.6+'),
87     ('5.7', '5.7'),
88     ('5.7+', '5.7+'),
89     ('5.8', '5.8'),
90     ('5.8+', '5.8+'),
91     ('5.9-', '5.9-'),
92     ('5.9', '5.9'),
93     ('5.9+', '5.9+'),
94     ('5.10a', '5.10a'),
95     ('5.10b', '5.10b'),
96     ('5.10c', '5.10c'),
97     ('5.10d', '5.10d'),
98     ('5.11a', '5.11a'),
99     ('5.11b', '5.11b'),
100     ('5.11c', '5.11c'),
101     ('5.11d', '5.11d'),
102     ('5.12a', '5.12a'),
103     ('5.12b', '5.12b'),
104     ('5.12c', '5.12c'),
105     ('5.12d', '5.12d'),
106     ('5.13a', '5.13a'),
107     ('5.13b', '5.13b'),
108     ('5.13c', '5.13c'),
109     ('5.13d', '5.13d'),
110     ('5.14a', '5.14a'),
111     ('5.14b', '5.14b'),
112     ('5.14c', '5.14c'),
113     ('5.14d', '5.14d'),
114     ('5.15a', '5.15a'),
115     ('5.15b', '5.15b'),
116     ('5.15c', '5.15c'),
117     ('5.15d', '5.15d'),
118 )
119
120 SAFETY_CHOICES = (
121     ('G', 'G'),
122     ('PG', 'PG'),
123     ('PG13', 'PG13'),
124     ('R', 'R'),
125     ('X', 'X'),
126 )
127
128 class Pitch(models.Model):
129     route = models.ForeignKey(
130         Route,
131         on_delete=models.CASCADE,
132         related_name='pitches',
133     )
134     name = models.CharField(max_length=64, null=True)
135     difficulty = models.CharField(max_length=5, choices=ROUTE_DIFFICULTY_CHOICES)
136     safety = models.CharField(max_length=4, choices=SAFETY_CHOICES)
137     notes = models.TextField(blank=True, null=True)
138
139     def __str__(self):
140         if self.name:
141             return '{} ({})'.format(self.name, self.difficulty)
142         return 'Pitch ({})'.format(self.difficulty)
143
144 class Cluster(models.Model):
145     area = models.ForeignKey(
146         Area,
147         on_delete=models.CASCADE,
148         related_name='clusters',
149     )
150     name = models.CharField(max_length=64)
151     notes = models.TextField(blank=True, null=True)
152
153     def __str__(self):
154         return self.name
155
156 class Boulder(models.Model):
157     cluster = models.ForeignKey(
158         Cluster,
159         on_delete=models.CASCADE,
160         related_name='boulders',
161     )
162     name = models.CharField(max_length=64)
163     notes = models.TextField(blank=True, null=True)
164
165     def __str__(self):
166         return self.name
167
168 BOULDER_DIFFICULTY_CHOICES = (
169     ('V0', 'V0'),
170     ('V1', 'V1'),
171     ('V2', 'V2'),
172     ('V3', 'V3'),
173     ('V4', 'V4'),
174     ('V5', 'V5'),
175     ('V6', 'V6'),
176     ('V7', 'V7'),
177     ('V8', 'V8'),
178     ('V9', 'V9'),
179     ('V10', 'V10'),
180     ('V11', 'V11'),
181     ('V12', 'V12'),
182     ('V13', 'V13'),
183     ('V14', 'V14'),
184     ('V15', 'V15'),
185     ('V16', 'V16'),
186     ('V17', 'V17'),
187 )
188
189 class Problem(models.Model):
190     boulder = models.ForeignKey(
191         Boulder,
192         on_delete=models.CASCADE,
193         related_name='problems',
194     )
195     name = models.CharField(max_length=64)
196     difficulty = models.CharField(max_length=3, choices=BOULDER_DIFFICULTY_CHOICES)
197     safety = models.CharField(max_length=4, choices=SAFETY_CHOICES)
198     notes = models.TextField(blank=True, null=True)
199
200     def __str__(self):
201         return '{} ({})'.format(self.name, self.difficulty)
202
203 class RouteTodo(models.Model):
204     user = models.ForeignKey(User, on_delete=models.CASCADE)
205     route = models.ForeignKey(Route, on_delete=models.CASCADE)
206
207 class ProblemTodo(models.Model):
208     user = models.ForeignKey(User, on_delete=models.CASCADE)
209     problem = models.ForeignKey(Problem, on_delete=models.CASCADE)
210
211 class RouteTick(models.Model):
212     user = models.ForeignKey(User, on_delete=models.CASCADE)
213     route = models.ForeignKey(Route, on_delete=models.CASCADE)
214     timestamp = models.DateTimeField()
215     notes = models.TextField(blank=True, null=True)
216
217 class ProblemTick(models.Model):
218     user = models.ForeignKey(User, on_delete=models.CASCADE)
219     problem = models.ForeignKey(Problem, on_delete=models.CASCADE)
220     timestamp = models.DateTimeField()
221     notes = models.TextField(blank=True, null=True)