Much QM re-engineering

This commit is contained in:
Philip Sargent 2023-03-17 20:01:52 +00:00
parent de54576d11
commit 7345e3a328
10 changed files with 252 additions and 178 deletions

View File

@ -47,11 +47,11 @@ class SurvexBlockAdmin(TroggleModelAdmin):
inlines = (RoleInline,) inlines = (RoleInline,)
class QMsFoundInline(admin.TabularInline): # class QMsFoundInline(admin.TabularInline):
model = QM # model = QM
fk_name = "found_by" # fk_name = "found_by"
fields = ("number", "grade", "location_description", "comment") # need to add foreignkey to cave part # fields = ("number", "grade", "location_description", "comment") # need to add foreignkey to cave part
extra = 1 # extra = 1
class PersonLogEntryInline(admin.TabularInline): class PersonLogEntryInline(admin.TabularInline):
@ -64,7 +64,7 @@ class LogbookEntryAdmin(TroggleModelAdmin):
prepopulated_fields = {"slug": ("title",)} prepopulated_fields = {"slug": ("title",)}
search_fields = ("title", "expedition__year") search_fields = ("title", "expedition__year")
date_heirarchy = "date" date_heirarchy = "date"
inlines = (PersonLogEntryInline, QMsFoundInline) # inlines = (PersonLogEntryInline, QMsFoundInline)
class Media: class Media:
css = {"all": ("css/troggleadmin.css",)} # this does not exist css = {"all": ("css/troggleadmin.css",)} # this does not exist
@ -91,12 +91,12 @@ class PersonAdmin(TroggleModelAdmin):
class QMAdmin(TroggleModelAdmin): class QMAdmin(TroggleModelAdmin):
search_fields = ("found_by__cave__kataster_number", "number", "found_by__date") search_fields = ("number", "expoyear")
list_display = ("__str__", "grade", "found_by", "ticked_off_by") list_display = ("__str__", "grade")
list_display_links = ("__str__",) list_display_links = ("__str__",)
list_editable = ("found_by", "ticked_off_by", "grade") # list_editable = ("comment", "page_ref", "grade")
list_per_page = 20 # list_per_page = 20
raw_id_fields = ("found_by", "ticked_off_by") # raw_id_fields = ("found_by", "ticked_off_by")
class PersonExpeditionAdmin(TroggleModelAdmin): class PersonExpeditionAdmin(TroggleModelAdmin):

View File

@ -1,4 +1,5 @@
import os import os
import os
import re import re
from collections import defaultdict from collections import defaultdict
from datetime import datetime, timezone from datetime import datetime, timezone
@ -161,12 +162,25 @@ class Cave(TroggleModel):
def __str__(self, sep=": "): def __str__(self, sep=": "):
return str(self.slug()) return str(self.slug())
def get_QMs(self): def get_open_QMs(self):
"""Searches for all QMs that reference this cave.""" """Searches for all QMs that reference this cave."""
# qms = self.qm_set.all().order_by('expoyear', 'block__date') # qms = self.qm_set.all().order_by('expoyear', 'block__date')
qms = QM.objects.filter(cave=self).order_by( qms = QM.objects.filter(cave=self).order_by(
"expoyear", "block__date" "expoyear", "block__date"
) # a QuerySet, see https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by ) # a QuerySet, see https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by
qmsopen = qms.filter(ticked=False)
return qmsopen # a QuerySet
def get_ticked_QMs(self):
"""Searches for all QMs that reference this cave."""
qms = QM.objects.filter(cave=self).order_by(
"expoyear", "block__date"
)
qmticked = qms.filter(ticked=True)
return qmticked # a QuerySet
def get_QMs(self):
qms = self.get_open_QMs() | self.get_ticked_QMs() # set union operation
return qms # a QuerySet return qms # a QuerySet
def kat_area(self): def kat_area(self):

View File

@ -144,38 +144,19 @@ class QM(TroggleModel):
number = models.IntegerField( number = models.IntegerField(
help_text="this is the sequential number in the year, only unique for CSV imports", help_text="this is the sequential number in the year, only unique for CSV imports",
) )
grade = models.CharField(max_length=1, blank=True, null=True, help_text="A/B/C/D/X")
cave = models.ForeignKey("Cave", related_name="QMs", blank=True, null=True, on_delete=models.SET_NULL) 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 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 with last char added blockname = models.TextField(blank=True, null=True) # NB truncated copy of survexblock name with last char added
expoyear = models.CharField( expoyear = models.CharField(max_length=4, blank=True, null=True)
max_length=4, blank=True, null=True ticked = models.BooleanField(default=False)
) # 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
ticked_off_by = models.ForeignKey(
LogbookEntry, related_name="QMs_ticked_off", blank=True, null=True, on_delete=models.SET_NULL
) # unused, ever?!
GRADE_CHOICES = (
("A", "A: Large obvious lead"),
("B", "B: Average lead"),
("C", "C: Tight unpromising lead"),
("D", "D: Dig"),
("X", "X: Unclimbable or horrid"),
("V", "V: Vertical"),
) # also seen "?" in imported data - see urls.py
grade = models.CharField(max_length=1, choices=GRADE_CHOICES)
location_description = models.TextField(blank=True) location_description = models.TextField(blank=True)
nearest_station_description = models.CharField(max_length=400, blank=True, null=True) completion_description = models.TextField(blank=True)
completion_date = models.DateField(blank=True, null=True)
nearest_station_name = models.CharField(max_length=200, blank=True, null=True) nearest_station_name = models.CharField(max_length=200, blank=True, null=True)
resolution_station_name = models.CharField(max_length=200, blank=True, null=True) resolution_station_name = models.CharField(max_length=200, blank=True, null=True)
nearest_station = models.ForeignKey("SurvexStation", blank=True, null=True, on_delete=models.SET_NULL)
area = models.CharField(max_length=100, blank=True, null=True) area = models.CharField(max_length=100, blank=True, null=True)
completion_description = models.TextField(blank=True, null=True) page_ref = models.TextField(blank=True, null=True)
comment = models.TextField(blank=True, null=True) comment = models.TextField(blank=True, null=True)
def __str__(self): def __str__(self):
@ -228,8 +209,8 @@ class QM(TroggleModel):
), ),
) )
def get_next_by_id(self): def get_next_by_id(self): # called in template
return QM.objects.get(id=self.id + 1) return QM.objects.get(id=self.id + 1)
def get_previous_by_id(self): def get_previous_by_id(self): # called in template
return QM.objects.get(id=self.id - 1) return QM.objects.get(id=self.id - 1)

View File

@ -536,9 +536,11 @@ def caveQMs(request, slug):
def qm(request, cave_id, qm_id, year, grade=None, blockname=None): def qm(request, cave_id, qm_id, year, grade=None, blockname=None):
"""Reports on one specific QM """Reports on one specific QM
Fixed and working July 2022, for both CSV imported QMs Fixed and working July 2022, for both CSV imported QMs
needs refactoring though.
290 has several QMS with the same number, grade, year (2108) and first 8 chars of the survexblock. This crashes things. Needs refactoring though! Uses extremely baroque way of getting the QMs instead of querying for QM objects
directly, presumably as a result of a baroque history.
Many caves have several QMS with the same number, grade, year (2018) and first 8 chars of the survexblock. This crashes things, so the terminal char of the survexblock name was added
""" """
year = int(year) year = int(year)
@ -547,7 +549,7 @@ def qm(request, cave_id, qm_id, year, grade=None, blockname=None):
# CSV import QMs, use old technique # CSV import QMs, use old technique
try: try:
c = getCave(cave_id) c = getCave(cave_id)
manyqms = c.get_QMs() manyqms = c.get_open_QMs() | c.get_ticked_QMs() # set union operation
qm = manyqms.get(number=qm_id, expoyear=year) qm = manyqms.get(number=qm_id, expoyear=year)
return render(request, "qm.html", {"qm": qm}) return render(request, "qm.html", {"qm": qm})
except QM.DoesNotExist: except QM.DoesNotExist:
@ -565,12 +567,12 @@ def qm(request, cave_id, qm_id, year, grade=None, blockname=None):
qmslug = f"{cave_id}-{year}-{blockname=}{qm_id}{grade}" qmslug = f"{cave_id}-{year}-{blockname=}{qm_id}{grade}"
print(f"{qmslug=}") print(f"{qmslug=}")
c = getCave(cave_id) c = getCave(cave_id)
manyqms = c.get_QMs() manyqms = c.get_open_QMs() | c.get_ticked_QMs() # set union operation
qmqs = manyqms.filter(expoyear=year, blockname=blockname, number=qm_id, grade=grade) qmqs = manyqms.filter(expoyear=year, blockname=blockname, number=qm_id, grade=grade)
if len(qmqs) > 1: if len(qmqs) > 1:
for q in qmqs: for q in qmqs:
print(qmqs) print(qmqs)
message = f"Multiple QMs with the same cave, year, number, grade AND first 8 chars of the survexblock name. (Could be caused by incomplete databasereset). Fix this in the survex file(s). {cave_id=} {year=} {qm_id=} {blockname=}" message = f"Multiple QMs with the same cave, year, number, grade AND first-several+terminal chars of the survexblock name. (Could be caused by incomplete databasereset). Fix this in the survex file(s). {cave_id=} {year=} {qm_id=} {blockname=}"
return render(request, "errors/generic.html", {"message": message}) return render(request, "errors/generic.html", {"message": message})
else: else:
qm = qmqs.get(expoyear=year, blockname=blockname, number=qm_id, grade=grade) qm = qmqs.get(expoyear=year, blockname=blockname, number=qm_id, grade=grade)
@ -588,7 +590,7 @@ def qm(request, cave_id, qm_id, year, grade=None, blockname=None):
{"badslug": f"Failed get {cave_id=} {year=} {qm_id=} {grade=} {blockname=}"}, {"badslug": f"Failed get {cave_id=} {year=} {qm_id=} {grade=} {blockname=}"},
) )
except MultipleObjectsReturned: except MultipleObjectsReturned:
message = f"Multiple QMs with the same cave, year, number, grade AND first 8 chars of the survexblock name. (Could be caused by incomplete databasereset). Fix this in the survex file(s). {cave_id=} {year=} {qm_id=} {blockname=}" message = f"Multiple QMs with the same cave, year, number, grade AND first-several+terminal chars of the survexblock name. (Could be caused by incomplete databasereset). Fix this in the survex file(s). {cave_id=} {year=} {qm_id=} {blockname=}"
return render(request, "errors/generic.html", {"message": message}) return render(request, "errors/generic.html", {"message": message})
except QM.DoesNotExist: except QM.DoesNotExist:
# raise # raise

79
md5bash.sh Normal file
View File

@ -0,0 +1,79 @@
#!/bin/bash
# read in the input string from command line arguments
input=$1
# pad the input string with a single "1" bit
padded_input="$input"$(echo -ne '\x80')
# pad the input string to a multiple of 512 bits (64 bytes)
while (( $(echo -n "$padded_input" | wc -c) % 64 != 56 ))
do
padded_input="$padded_input"$(echo -ne '\x00')
done
# append the length of the input string (in bits) as a 64-bit little-endian integer
length=$(echo -n "$input" | wc -c)
length=$(echo "obase=16; $length * 8" | bc | xxd -p -c 16 | tac | tr -d '\n')
while (( $(echo -n "$length" | wc -c) < 16 ))
do
length="$length"0
done
padded_input="$padded_input"$(echo -ne "$length" | xxd -r -p)
# initialize the buffer (A, B, C, D)
A="67452301"
B="efcdab89"
C="98badcfe"
D="10325476"
# process the input in 512-bit (64-byte) chunks
for (( i=0; i<$(echo -n "$padded_input" | wc -c)/64; i++ ))
do
chunk=$(echo -n "$padded_input" | dd bs=64 skip=$i count=1 2>/dev/null | xxd -p -c 64)
# initialize the message schedule (M)
M=()
for (( j=0; j<16; j++ ))
do
word=$(echo -ne "${chunk:$j*8:8}" | xxd -r -p | od -An -tu4 -v)
M+=($word)
done
for (( j=16; j<64; j++ ))
do
word1=${M[j-15]}
s0=$(( (word1>>7 | word1<<25) ^ (word1>>18 | word1<<14) ^ (word1>>3) ))
word2=${M[j-2]}
s1=$(( (word2>>17 | word2<<15) ^ (word2>>19 | word2<<13) ^ (word2>>10) ))
M+=($((M[j-16] + s0 + M[j-7] + s1)))
done
# initialize the working variables
AA=$A
BB=$B
CC=$C
DD=$D
# round 1
for (( j=0; j<16; j++ ))
do
F=$(( (B & C) | (~B & D) ))
g=$j
dTemp=$((D))
D=$((C))
C=$((B))
B=$((B + ((A + F + M[g] + 0xd76aa478) & 0xffffffff)))
A=$((dTemp))
done
# round 2
for (( j=16; j<32; j++ ))
do
F=$(( (D & B) | (~D & C) ))
g=$(( (5*j + 1) % 16 ))
dTemp=$((D))
D=$((C))
C=$((B))

View File

@ -65,7 +65,6 @@ def parseCaveQMs(cave, inputFile, ticked=False):
nqms = parse_KH_QMs(kh, inputFile=inputFile, ticked=ticked) nqms = parse_KH_QMs(kh, inputFile=inputFile, ticked=ticked)
return nqms return nqms
# qmPath = settings.EXPOWEB+inputFile
qmPath = Path(settings.EXPOWEB, inputFile) qmPath = Path(settings.EXPOWEB, inputFile)
with open(qmPath, "r") as qmCSVContents: with open(qmPath, "r") as qmCSVContents:
@ -76,15 +75,17 @@ def parseCaveQMs(cave, inputFile, ticked=False):
n = 0 n = 0
nqms = 0 nqms = 0
for line in qmReader: for line in qmReader:
#"Number","Grade","Area","Description","Page reference","Nearest survey station","Completion description","Comment"
try: try:
n += 1 n += 1
year = int(line[0][1:5]) year = int(line[0][1:5])
f"PH_{int(year)}_{int(n):02d}" f"PH_{int(year)}_{int(n):02d}"
QMnum = re.match(r".*?-\d*?-X?(?P<numb>\d*)", line[0]).group("numb") QMnum = re.match(r".*?-\d*?-X?(?P<numb>\d*)", line[0]).group("numb")
newQM = QM() newQM = QM() # creates python object, does not touch db yet
# newQM.found_by=placeholder # newQM.found_by=placeholder
newQM.number = QMnum newQM.number = QMnum
newQM.cave = caveid newQM.cave = caveid
newQM.expoyear = year
newQM.blockname = "" newQM.blockname = ""
if line[1] == "Dig": if line[1] == "Dig":
newQM.grade = "D" newQM.grade = "D"
@ -92,32 +93,28 @@ def parseCaveQMs(cave, inputFile, ticked=False):
newQM.grade = line[1] newQM.grade = line[1]
newQM.area = line[2] newQM.area = line[2]
newQM.location_description = line[3] newQM.location_description = line[3]
newQM.page_ref = line[4]
# In the table, completion is indicated by the presence of a completion discription. # In the table, completion is indicated by the presence of a completion discription.
newQM.completion_description = line[4] newQM.nearest_station_name = line[5]
newQM.nearest_station_description = line[5] newQM.completion_description = line[6]
if newQM.completion_description: if newQM.completion_description:
newQM.ticked = True newQM.ticked = True
else: else:
newQM.ticked = False newQM.ticked = False
newQM.comment = line[6] newQM.comment = line[7]
try: try:
# year and number are unique for a cave in CSV imports # year and number are unique for a cave in CSV imports
preexistingQM = QM.objects.get( preexistingQM = QM.objects.get(
number=QMnum, found_by__date__year=year number=QMnum, expoyear=year, cave=caveid,
) # if we don't have this one in the DB, save it )
if ( if preexistingQM:
preexistingQM.new_since_parsing is False message = f" ! - {qmPath} PRE-EXISTING QM - should not exist ! {str(line)} "
): # if the pre-existing QM has not been modified, overwrite it - VERY OLD THING print(message)
DataIssue.objects.create(parser="QMs", message=message)
preexistingQM.delete() preexistingQM.delete()
newQM.expoyear = year newQM.save()
newQM.save()
else: # otherwise, print that it was ignored
print((" - preserving " + str(preexistingQM) + ", which was edited in admin \r"))
except QM.DoesNotExist: # if there is no pre-existing QM, save the new one except QM.DoesNotExist: # if there is no pre-existing QM, save the new one
newQM.expoyear = year
newQM.save() newQM.save()
nqms += 1 nqms += 1
except KeyError: # check on this one except KeyError: # check on this one
@ -130,6 +127,12 @@ def parseCaveQMs(cave, inputFile, ticked=False):
print(message) print(message)
DataIssue.objects.create(parser="QMs", message=message) DataIssue.objects.create(parser="QMs", message=message)
continue continue
except:
message = f" ! - {qmPath} UNKNOWN error {str(line)} "
print(message)
DataIssue.objects.create(parser="QMs", message=message)
raise
continue
return nqms return nqms
@ -139,8 +142,9 @@ def parse_KH_QMs(kh, inputFile, ticked):
khQMs = khQMfile.readlines() khQMs = khQMfile.readlines()
nqms = 0 nqms = 0
for line in khQMs: for line in khQMs:
# <dt><a href="sibria.htm#qC1997-161-27" name="C1997-161-27">C1997-161-27</a> A<dd>Sib: pitch at end of Fuzzy Logic [Paradox Rift - continues] [sep.fuzzy.13]
res = re.search( res = re.search(
r"name=\"[CB](?P<year>\d*)-(?P<cave>\d*)-(?P<number>\d*).*</a> (?P<grade>[ABDCV])<dd>(?P<description>.*)\[(?P<nearest_station>.*)\]", r"name=\"[CB](?P<year>\d*)-(?P<cave>\d*)-(?P<number>\d*).*</a> (?P<grade>[ABCDX])<dd>(?P<location_description>.*)\[(?P<nearest_station_name>.*)\]",
line, line,
) )
if res: if res:
@ -157,8 +161,10 @@ def parse_KH_QMs(kh, inputFile, ticked):
} }
nonLookupAttribs = { nonLookupAttribs = {
"ticked": ticked, "ticked": ticked,
"nearest_station_name": res["nearest_station"], "page_ref": "",
"location_description": res["description"], "completion_description": "",
"nearest_station_name": res["nearest_station_name"],
"location_description": res["location_description"],
} }
# Create new. We know it doesn't exist as we deleted evrything when we started. # Create new. We know it doesn't exist as we deleted evrything when we started.
instance = QM.objects.create(**nonLookupAttribs, **lookupAttribs) instance = QM.objects.create(**nonLookupAttribs, **lookupAttribs)
@ -169,8 +175,11 @@ def parse_KH_QMs(kh, inputFile, ticked):
def Load_QMs(): def Load_QMs():
deleteQMs() deleteQMs()
n204 = parseCaveQMs(cave="204-steinBH", inputFile=r"1623/204/qm.csv") #Number Grade Area Description Page reference Nearest station Completion description Comment
n234 = parseCaveQMs(cave="234-Hauch", inputFile=r"1623/234/qm.csv") n204 = parseCaveQMs(cave="204-steinBH", inputFile=r"1623/204/qm-204.csv") # TAB separated values
#"Number","Grade","Area","Description","Page reference","Nearest survey station","Completion description","Comment"
n234 = parseCaveQMs(cave="234-Hauch", inputFile=r"1623/234/qm-234.csv") # COMMA separated values, with quotes.
n161 = parseCaveQMs(cave="161-KH", inputFile="1623/161/qmtodo.htm", ticked=False) n161 = parseCaveQMs(cave="161-KH", inputFile="1623/161/qmtodo.htm", ticked=False)
t161 = parseCaveQMs(cave="161-KH", inputFile="1623/161/qmdone.htm", ticked=True) t161 = parseCaveQMs(cave="161-KH", inputFile="1623/161/qmdone.htm", ticked=True)
# parseCaveQMs(cave='balkonhoehle',inputFile=r"1623/264/qm.csv") # parseCaveQMs(cave='balkonhoehle',inputFile=r"1623/264/qm.csv")

View File

@ -1309,7 +1309,10 @@ class LoadingSurvex:
insp = self.insp insp = self.insp
# create a short, hopefully-unique name for this block to be used in the QM id # create a short, hopefully-unique name for this block to be used in the QM id
blockname = survexblock.name[:6] + survexblock.name[-1:] if len(survexblock.name) < 7:
blockname = survexblock.name
else:
blockname = survexblock.name[:6] + survexblock.name[-1:]
# logslug = f'D{int(qmyear)}_{blockname}_{int(qm_no):03d}' # logslug = f'D{int(qmyear)}_{blockname}_{int(qm_no):03d}'
qm_ticked = False # default qm_ticked = False # default
@ -1319,7 +1322,7 @@ class LoadingSurvex:
self.TickSurvexQM(survexblock, qmline) self.TickSurvexQM(survexblock, qmline)
return return
if qm_grade not in ["A", "B", "C", "D", "X", "V", "?"]: if qm_grade not in ["A", "B", "C", "D", "X"]: # "V", "?" not allowed in survex file QMs
message = f" ! QM{qm_no} INVALID code '{qm_grade}' [{blockname}] '{survexblock.survexfile.path}'" message = f" ! QM{qm_no} INVALID code '{qm_grade}' [{blockname}] '{survexblock.survexfile.path}'"
print(insp + message) print(insp + message)
stash_data_issue( stash_data_issue(
@ -1336,7 +1339,7 @@ class LoadingSurvex:
pass pass
else: else:
qm_ticked = True qm_ticked = True
print(f"{survexblock.survexfile.cave} {survexblock}:{qm_no}{qm_grade} {qmline.group(4)}", file=sys.stderr) # print(f"{survexblock.survexfile.cave} {survexblock}:{qm_no}{qm_grade} {qmline.group(4)}", file=sys.stderr)
if resolution_station_name: if resolution_station_name:
qm_ticked = True qm_ticked = True
# if qmline.group(6) and qmline.group(6) != "-": # if qmline.group(6) and qmline.group(6) != "-":

View File

@ -20,39 +20,42 @@
<li><a href="{% url 'caveQMs' '1626-359' %}">1626-359 QMs</a> Homecoming <li><a href="{% url 'caveQMs' '1626-359' %}">1626-359 QMs</a> Homecoming
</ul> </ul>
<p>For how to set up your own QMs, see <a href="/handbook/survey/qmentry.html">Adding QMs </a>.
<p>For full explanation of the current status of the QM system(s), see <a href="/handbook/troggle/scriptsqms.html">scriptsqms page</a>. <p>For full explanation of the current status of the QM system(s), see <a href="/handbook/troggle/scriptsqms.html">scriptsqms page</a>.
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<h3>Extant</h3> <h3>Open leads</h3>
<p>{% if cave.get_QMs %} <ul>{% for QM in cave.get_open_QMs %}
<ul>
{% for QM in cave.get_QMs %}
{% if QM.ticked %}
{% else %}
<li><a href="{{QM.get_absolute_url}}">{{QM}}</a> <li><a href="{{QM.get_absolute_url}}">{{QM}}</a>
{% if QM.nearest_station_description %}&vellip;<em>{{QM.nearest_station_description}}</em>&vellip;{% endif %} {{QM.location_description}} <b>{{QM.grade}}</b> {% if QM.nearest_station_name %}&sect;<em>{{QM.nearest_station_name}}</em>&sect;{% endif %}
{{QM.location_description}} <b>{{QM.grade}}</b>
{% if QM.block %} <a href="/survexfile/{{QM.block.survexfile.path}}.svx">{{QM.block}}.svx</a> {{QM.block.date}} {% endif %}</li> {% if QM.block %} <a href="/survexfile/{{QM.block.survexfile.path}}.svx">{{QM.block}}.svx</a> {{QM.block.date}} {% endif %}</li>
{% endif %} {% empty %}
<li>No open leads.
{% endfor %} {% endfor %}
</ul> </ul>
&sect; QM.nearest_station_name<br />
&star; QM.resolution_station_name<br />
<h3>Ticked off</h3> <h3>Ticked off</h3>
<ul> <ul>{% for QM in cave.get_ticked_QMs %}
{% for QM in cave.get_QMs %}
{% if QM.ticked %}
<li><a href="{{QM.get_absolute_url}}">{{QM}}</a> <li><a href="{{QM.get_absolute_url}}">{{QM}}</a>
{% if QM.nearest_station %}&vellip;<em>{{QM.nearest_station}}</em>&vellip;{% endif %} {% if QM.nearest_station_name %}&sect;<em>{{QM.nearest_station_name}}</em>&sect;{% endif %}
{% if QM.nearest_station_name %}&vellip;<em>{{QM.nearest_station_name}}</em>&vellip;{% endif %} {% if QM.resolution_station_name %}&star;<em>{{QM.resolution_station_name}}</em>&star;{% endif %}
{% if QM.nearest_station_description %}&vellip;<em>{{QM.nearest_station_description}}</em>&vellip;{% endif %} {{QM.location_description}} <b>{{QM.grade}}</b> {{QM.location_description}} <b>{{QM.grade}}</b>
{% if QM.block %} <a href="/survexfile/{{QM.block.survexfile.path}}.svx">{{QM.block}}.svx</a> {{QM.block.date}} {% endif %} {% if QM.block %} <a href="/survexfile/{{QM.block.survexfile.path}}.svx">{{QM.block}}.svx</a> {{QM.block.date}} {% endif %}
{% if QM.completion_description %} {% if QM.completion_description %}
Completion page: <a href="/{{QM.get_completion_url}}">{{QM.completion_description}}</a> Completion page: <a href="/{{QM.get_completion_url}}">{{QM.completion_description}}</a>
{% endif %} {% endif %}
{% endif %} {% if QM.comment %}
Comment: <a href="/{{QM.get_completion_url}}">{{QM.comment}}</a>
{% endif %}
{% empty %}
<li>No ticked leads.
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %}</p> </p>
&sect; QM.nearest_station_name<br />
&star; QM.resolution_station_name<br />
{% endblock %} {% endblock %}

View File

@ -18,16 +18,4 @@ Hacked up list of caves with grade "?"
{% endfor %} } {% endfor %} }
<br /><br /> <br /><br />
------------------------------------------------------<br /> ------------------------------------------------------<br />
Hacked up list of caves with grade "V"
<br /><br />
{% for qm in object_list %}
{% if qm.grade == "V" %}<br />
"{{qm.id}}": ["{{qm.expoyear}}","{{qm.cave}}",{% if qm.ticked %}"TICKed",{% else %}"OPEN",{% endif %}
"{{qm.blockname}}","QM{{qm.number}}","{{qm.grade}}","{{qm.nearest_station_name}}","{{qm.resolution_station_name}}",
<a href="{{qm.get_absolute_url}}">"{{qm.get_absolute_url}}"</a>
]{% if not forloop.last %},{% endif %}
{% endif %}
{% endfor %} }
{% endblock %}

View File

@ -2,6 +2,75 @@
{% load link %} {% load link %}
{% block title %} QM: {{qm|safe}} {% endblock %} {% block title %} QM: {{qm|safe}} {% endblock %}
{% block contentheader %} {% block contentheader %}
{% endblock %}
{% block related %}
{% endblock %}
{% block content %}
<table id="cavepage">
<tr>
<th id="kat_no"><a class="whitetext" href="{{qm.get_previous_by_id.get_absolute_url}}">Previous QM</a></th>
<th id="name">QM &nbsp;&nbsp;{{qm|safe}}</th>
<th id="status"><a class="whitetext" href="{{qm.get_next_by_id.get_absolute_url}}">Next QM</a></th>
</tr>
</table>
{% if qm.ticked %}
<h3>This QM is TICKED</h3>
{% if qm.resolution_station_name %}
The survey station which record the continuation of the cave past this QM is <b>{{qm.resolution_station_name}}</b>.<br />
{%endif %}
Tick off comment: '{{qm.comment}}'</a> <br />
Tick off completion description: '{{qm.completion_description}}' </a> <br />
Tick off url: <a href="/{{qm.get_completion_url}}">{{qm.get_completion_url}}</a> WRONG <br />
Tick off date: '{{qm.completion_date}}' [For survex file ticks. not implemented yet]</a> <br />
{% endif %}
{% if qm.cave %}
<h3>Cave: {{qm.cave|safe }}</h3>
<a href="{% url 'caveQMs' qm.cave|safe %}">All QMs on this cave </a>{{ qm.cave|safe }} <br>
<a href="/{{ qm.cave.url }}"> Cave description </a> {{ qm.cave|safe }}
{% else %}
<h3>This QM is OPEN</h3>
Comment: '{{qm.comment}}'</a> <br />
{% endif %}
QM page_ref: '{{qm.page_ref}}'<br>
<h3>QM Number: {{qm.number}} Grade: {{qm.grade}} </h3>
<p>Explanation of Grade letters: <a href="/handbook/survey/qm.html">Handbook - QM grades</a>
{% if qm.block %}
<h3>Survexfile</h3>
{{qm.block.date}} <a href="/survexfile/{{qm.block.survexfile.path}}.svx">{{qm.block}}.svx</a>
{% endif %}
<h3>QM original closest survey station</h3>
{% if qm.block %}
Survex block: {{qm.blockname}}
<br>
{% endif %}
Nearest station: '{{qm.nearest_station_name}}' {{nearest_station_description}}
<h3>QM original description</h3>
{{qm.location_description}}
{% if qm.found_by %}
<h3>Creation</h3>
Found by <a href="{{qm.found_by.get_absolute_url}}">{{qm.found_by}}</a> on {{qm.found_by.date}}.
{% endif %}
<hr />
<h3>QMs available for these caves from CSV import</h3> <h3>QMs available for these caves from CSV import</h3>
<ul> <ul>
<li><a href="{% url 'caveQMs' '1623-161' %}">1623-161 QMs</a> Maybe OUT OF DATE. See <a href="/1623/161/qmdone.htm">the curated list <b>instead</b></a> <li><a href="{% url 'caveQMs' '1623-161' %}">1623-161 QMs</a> Maybe OUT OF DATE. See <a href="/1623/161/qmdone.htm">the curated list <b>instead</b></a>
@ -18,79 +87,5 @@
</ul> </ul>
<p>For full explanation of the current status of the QM system(s), see <a href="/handbook/troggle/scriptsqms.html">scriptsqms page</a>. <p>For full explanation of the current status of the QM system(s), see <a href="/handbook/troggle/scriptsqms.html">scriptsqms page</a>.
<hr />
<table id="cavepage">
<tr>
<th id="kat_no"><a class="whitetext" href="{{qm.get_previous_by_id.get_absolute_url}}">Previous QM</a></th>
<th id="name">QM &nbsp;&nbsp;{{qm|safe}}</th>
<th id="status"><a class="whitetext" href="{{qm.get_next_by_id.get_absolute_url}}">Next QM</a></th>
</tr>
</table>
{% endblock %}
{% block related %}
{% endblock %}
{% block content %}
<h3>Cave</h3>
{% if qm.cave %}
<a href="{% url 'caveQMs' qm.cave|safe %}">{{ qm.cave|safe }} QMs</a> <br>
{% else %}
{% if qm.cave %}
<a href="{% url 'caveQMs' qm.cave|safe %}">{{ qm.cave|safe }} QMs</a> <br>
{% endif %}
{% endif %}
<a href="/{{ qm.cave.url }}">{{ qm.cave|safe }} cave description</a>
<h3>QM Number</h3>
{{qm.number}}
<h3>Grade</h3>
{{qm.grade}}
<p>Explanation of Grade letters: <a href="/handbook/survey/qm.html">Handbook - QM grades</a>
{% if qm.block %}
<h3>Survexfile</h3>
{{qm.block.date}} <a href="/survexfile/{{qm.block.survexfile.path}}.svx">{{qm.block}}.svx</a>
{% endif %}
{% if qm.ticked %}
<h3>Ticked</h3>
This QM is TICKED
{% endif %}
{% if qm.resolution_station_name %}
<h3>resolution_station_name</h3>
{{qm.resolution_station_name}}
{% endif %}
<h3>Location</h3>
{% if qm.block %}
Survex block: {{qm.blockname}}
<br>
{% endif %}
Nearest station: '{{qm.nearest_station_name}}' {{nearest_station_description}}
<h3>QM Description</h3>
{{qm.location_description}}
{% if qm.found_by %}
<h3>Creation</h3>
Found by <a href="{{qm.found_by.get_absolute_url}}">{{qm.found_by}}</a> on {{qm.found_by.date}}.
{% endif %}
<h3>Completion</h3>
{% if qm.ticked %}
Ticked off log entry: <a href="{{qm.ticked_off_by.get_absolute_url}}">{{qm.ticked_off_by}}</a><br />
Ticked off date: <a href="/{{qm.get_completion_url}}">{{qm.get_completion_url}}</a> WRONG <br />
Tick off date: [For survex file ticks. not implemented yet, needs model change]</a> <br />
Tick off completion description: {{qm.completion_description}}</a>
{% else %}
No completion description yet- STILL EXTANT.
{% endif %}
<h3>Comment</h3>
{{qm.comment}}
{% endblock %} {% endblock %}