diff --git a/core/models/caves.py b/core/models/caves.py index 3067520..a71eadf 100644 --- a/core/models/caves.py +++ b/core/models/caves.py @@ -468,7 +468,7 @@ class QM(TroggleModel): """ cave = models.ForeignKey(Cave, related_name='QMs',blank=True, null=True,on_delete=models.SET_NULL ) block = models.ForeignKey('SurvexBlock', null=True,on_delete=models.SET_NULL) # only for QMs from survex files - blockname=models.TextField(blank=True,null=True) # NB truncated copy of survexblock name + blockname=models.TextField(blank=True,null=True) # NB truncated copy of survexblock name with last char added expoyear = models.CharField(max_length=4,blank=True, null=True) # could change to datetime if logbooks similarly chnaged found_by = models.ForeignKey(LogbookEntry, related_name='QMs_found',blank=True, null=True,on_delete=models.SET_NULL ) ticked = models.BooleanField(default=False) # for ticked QMs not attached to a logbook entry, should imply completion_description has text @@ -480,7 +480,7 @@ class QM(TroggleModel): ('C', 'C: Tight unpromising lead'), ('D', 'D: Dig'), ('X', 'X: Unclimbable aven') - ) # also seen "?" in imported data - see urls.py + ) # also seen "?" and "V" in imported data - see urls.py grade = models.CharField(max_length=1, choices=GRADE_CHOICES) location_description = models.TextField(blank=True) nearest_station_description = models.CharField(max_length=400,blank=True, null=True) @@ -503,11 +503,10 @@ class QM(TroggleModel): else: expoyearstr = str(self.cave.slug())[5:9] if self.blockname: - blocknamestr = str(self.blockname) + blocknamestr = "-" + str(self.blockname) else: blocknamestr = "" - #return f'{self.cave.slug()[5:]}-{self.expoyear}-{self.blockname}{self.number}{self.grade}' - return f'{cavestr}-{expoyearstr}-{self.number}{self.grade}-{blocknamestr}' + return f'{cavestr}-{expoyearstr}-{self.number}{self.grade}{blocknamestr}' def get_completion_url(self): '''assumes html file named is in same folder as cave description file @@ -526,7 +525,7 @@ class QM(TroggleModel): return qmslug def get_absolute_url(self): - #return settings.URL_ROOT + '/cave/' + self.found_by.cave.kataster_number + '/' + str(self.found_by.date.year) + '-' + '%02d' %self.number + # This reverse resolution stuff is pure magic. Just change the regex in urls.py and everything changes to suit. Whacky. return urljoin(settings.URL_ROOT, reverse('qm',kwargs={'cave_id':self.cave.slug(),'year':self.expoyear, 'blockname':self.blockname,'qm_id':self.number,'grade':self.grade})) def get_next_by_id(self): @@ -535,9 +534,6 @@ class QM(TroggleModel): def get_previous_by_id(self): return QM.objects.get(id=self.id-1) - # def wiki_link(self): - # return "%s%s%s" % ('[[QM:',self.code(),']]') - class PersonTrip(TroggleModel): """Single Person going on a trip, which may or may not be written up. It accounts for different T/U for people in same logbook entry. diff --git a/parsers/survex.py b/parsers/survex.py index 876263c..0656c57 100644 --- a/parsers/survex.py +++ b/parsers/survex.py @@ -119,9 +119,10 @@ class LoadingSurvex(): instruments = "(waiting_patiently|slacker|Useless|nagging|unknown|Inst|instrument|rig|rigger|rigging|helper|something| compass|comp|clino|Notes|sketch|book|Tape|Dog|Pics|photo|drawing|Helper|GPS|Disto|Distox|Distox2|topodroid|point|Consultant|nail|polish|nail_polish_bitch|nail_polish_monkey|varnish|nail_polish|nail_varnish|bitch|monkey|PowerDrill|drill)" rx_teammem = re.compile(r"(?i)"+instruments+"?(?:es|s)?\s+(.*)"+instruments+"?(?:es|s)?$") rx_person = re.compile(r"(?i) and | / |, | & | \+ |^both$|^none$") - rx_qm = re.compile(r'(?i)^\s*QM(\d+)\s+?([a-dA-DxX])\s+([\w\-]+)\.(\d+)\s+(([\w\-]+)\.(\d+)|\-)\s+(.+)$') + rx_qm = re.compile(r'(?i)^\s*QM(\d+)\s+?([a-dA-DxX])\s+([\w\-\_]+)\.([\w\.\-]+)\s+(([\w\-]+)\.([\w\.\-]+)|\-)\s+(.+)$') # does not recognise non numeric suffix survey point ids rx_qm0 = re.compile(r'(?i)^\s*QM(\d+)\s+(.+)$') + rx_qm_tick = re.compile(r'(?i)^\s*QM(\d+)\s+TICK\s([\d\-]+)\s(.*)$') # remember there is also QM_PATTERN used in views.other and set in settings.py rx_tapelng = re.compile(r'(?i).*(tape|length).*$') @@ -510,6 +511,23 @@ class LoadingSurvex(): print((self.insp+message)) DataIssue.objects.create(parser='survex', message=message, url=url) + def TickSurvexQM(self, survexblock, qmtick): + # Now we need to find the correct QM object. It will be in the same block and have the same number. + + try: + qm = QM.objects.filter(block=survexblock, number=int(qmtick.group(1))) + except: + #raise + message = f' ! QM TICK find FAIL QM{qmtick.group(1)} date:"{qmtick.group(2)}" qmlist:"{qm}" in "{survexblock.survexfile.path}" + comment:"{qmtick.group(3)}" ' + print(message) + DataIssue.objects.create(parser='survex', message=message, url=f'/survexfile/{survexblock.survexfile.path}.svx') + if len(qm)>1: + message = f' ! QM TICK MULTIPLE found FAIL QM{qmtick.group(1)} date:"{qmtick.group(2)}" in "{survexblock.survexfile.path}" + comment:"{qmtick.group(3)}" ' + print(message) + DataIssue.objects.create(parser='survex', message=message, url=f'/survexfile/{survexblock.survexfile.path}.svx') + qm[0].ticked = True + qm[0].save() + def LoadSurvexQM(self, survexblock, qmline): insp = self.insp @@ -821,9 +839,13 @@ class LoadingSurvex(): if qmline: self.LoadSurvexQM(survexblock, qmline) else: - message = f' ! QM Unrecognised as valid in "{survexblock.survexfile.path}" QM{qml.group(1)} {qml.group(2)} : non-numeric station name?' - print(message) - DataIssue.objects.create(parser='survex', message=message, url=f'/survexfile/{survexblock.survexfile.path}.svx') + qmtick = self.rx_qm_tick.match(comment) + if qmtick: + self.TickSurvexQM(survexblock, qmtick) + else: + message = f' ! QM Unrecognised as valid in "{survexblock.survexfile.path}" QM{qml.group(1)} "{qml.group(2)}" : regex failure, typo?' + print(message) + DataIssue.objects.create(parser='survex', message=message, url=f'/survexfile/{survexblock.survexfile.path}.svx') included = self.rx_comminc.match(comment) @@ -1456,6 +1478,7 @@ def LoadSurvexBlocks(): SurvexDirectory.objects.all().delete() SurvexPersonRole.objects.all().delete() SurvexStation.objects.all().delete() + QM.objects.all().delete() # most of these are created by survex parsing. Better to lose the CSV ones than duplicate the survex ones print(" - survex Data Issues flushed") DataIssue.objects.filter(parser='survex').delete() DataIssue.objects.filter(parser='survexleg').delete() diff --git a/templates/qm.html b/templates/qm.html index 0bc02bd..0a36098 100644 --- a/templates/qm.html +++ b/templates/qm.html @@ -42,6 +42,11 @@ {% endif %} {{ qm.cave|safe }} cave description +

QM Number

+{{qm.number}} + +

Grade

+{{qm.grade}} {% if qm.block %}

Survexfile

@@ -49,15 +54,13 @@ {% endif %}

Location

-{{qm.location_description}} +{% if qm.block %} +Survex block: {{qm.blockname}}
-{{qm.blockname}} - -

QM Number

-{{qm.number}} - -

Grade

-{{qm.grade}} +{% endif %} +Nearest station: '{{qm.nearest_station_name}}' {{nearest_station_description}} +

QM Description

+{{qm.location_description}} {% if qm.found_by %}

Creation

@@ -67,7 +70,9 @@ Found by {{qm.found_by}} on {{qm.

Completion

{% if qm.ticked %} Ticked off log entry: {{qm.ticked_off_by}}
-Ticked off Description Page: {{qm.get_completion_url}} +Ticked off Description Page: {{qm.get_completion_url}}
+Tick off date: [For survex file ticks. not implemented yet, needs model change]
+Tick off comment: [For survex file ticks. not implemented yet, needs model change] {% else %} No completion description yet- STILL EXTANT. diff --git a/urls.py b/urls.py index ae54d0f..56c6fa5 100644 --- a/urls.py +++ b/urls.py @@ -177,7 +177,7 @@ trogglepatterns = [ # QMs pages - must precede other /caves pages? re_path(r'^cave/qms/([^/]+)/?$', caveQMs, name="caveQMs"), # Fixed. July 2022 - re_path(r'^cave/qms/(?P[^/]+)/(?P\d\d\d\d)-(?P[^0-9]*)?(?P\d*)(?P[ABCDXV\?]?)?$', qm, name="qm"), # Dogs breakfast + re_path(r'^cave/qms/(?P[^/]+)/(?P\d\d\d\d)-(?P\d*)(?P[ABCDXV\?]?)-?(?P[a-zA-Z]+.*)?$', qm, name="qm"), # Dogs breakfast # the resolution of a QM uses several fields together, there is no clean slug field. Artefact of history. # Prospecting Guide document