2
0
mirror of https://expo.survex.com/repositories/troggle/.git synced 2026-02-08 04:38:42 +00:00

cartesian survex blocks now handled

This commit is contained in:
2025-10-31 22:32:14 +02:00
parent c6647907e5
commit 7bbc413902
6 changed files with 92 additions and 37 deletions

View File

@@ -37,12 +37,10 @@ class TroggleModelAdmin(admin.ModelAdmin):
js = ("jquery/jquery.min.js", "js/QM_helper.js") # not currently available to troggle, see media/js/README js = ("jquery/jquery.min.js", "js/QM_helper.js") # not currently available to troggle, see media/js/README
class RoleInline(admin.TabularInline): # class RoleInline(admin.TabularInline):
model = SurvexPersonRole # model = SurvexPersonRole
extra = 4 # extra = 4
class SurvexBlockAdmin(TroggleModelAdmin):
inlines = (RoleInline,)
class PersonLogEntryInline(admin.TabularInline): class PersonLogEntryInline(admin.TabularInline):
model = PersonLogEntry model = PersonLogEntry
@@ -82,9 +80,6 @@ class QMAdmin(TroggleModelAdmin):
list_display = ("__str__", "grade") list_display = ("__str__", "grade")
list_display_links = ("__str__",) list_display_links = ("__str__",)
list_filter = ('grade', 'cave', 'expoyear') list_filter = ('grade', 'cave', 'expoyear')
# list_editable = ("comment", "page_ref", "grade")
# list_per_page = 20
# raw_id_fields = ("found_by", "ticked_off_by")
class PersonExpeditionAdmin(TroggleModelAdmin): class PersonExpeditionAdmin(TroggleModelAdmin):
search_fields = ("person__first_name", "person__slug", "expedition__year") search_fields = ("person__first_name", "person__slug", "expedition__year")
@@ -103,10 +98,12 @@ class SurvexStationAdmin(TroggleModelAdmin):
class SurvexFileAdmin(TroggleModelAdmin): class SurvexFileAdmin(TroggleModelAdmin):
search_fields = ("path",) search_fields = ("path",)
# class SurvexBlockAdmin(TroggleModelAdmin):
# inlines = (RoleInline,)
class SurvexBlockAdmin(TroggleModelAdmin): class SurvexBlockAdmin(TroggleModelAdmin):
search_fields = ("name", ) search_fields = ("name", "title")
list_display = ["survexfile", "name"] list_display = ["survexfile", "name", "title", "scanswallet", "ref_text"]
class DrawingFileAdmin(TroggleModelAdmin): class DrawingFileAdmin(TroggleModelAdmin):
search_fields = ("dwgname",) search_fields = ("dwgname",)

View File

@@ -203,7 +203,7 @@ class SurvexFix(models.Model):
But this does not include the virtual *fix locations which are But this does not include the virtual *fix locations which are
in locations.py in locations.py
""" """
objects = SurvexBlockLookUpManager() # overwrites Survexfix.objects and enables lookup() objects = SurvexBlockLookUpManager() # overwrites Survexfix.objects and enables lookup() but is this a mistake, Block?
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
class Meta: class Meta:
ordering = ("name",) ordering = ("name",)

View File

@@ -44,7 +44,12 @@ def legs_by_expo(expos):
else: else:
success = "" success = ""
tourists = PersonExpedition.objects.filter(expedition=expedition, noncaver=True).count() tourists = PersonExpedition.objects.filter(expedition=expedition, noncaver=True).count()
legsbyexpo.append((expedition, {"success":success, "people": expoers, "tourists": tourists, "nsurvexlegs": legsyear, "survexleglength": survexleglength, "nblocks": nblocks})) missing_length = ( nblocks > 0 and survexleglength <= 1)
if missing_length:
print(expedition, nblocks, survexleglength, missing_length)
legsbyexpo.append((expedition, {"success":success, "people": expoers, "tourists": tourists,
"nsurvexlegs": legsyear, "survexleglength": survexleglength, "nblocks": nblocks, "missing_length": missing_length}))
legsbyexpo.reverse() legsbyexpo.reverse()
return legsbyexpo, addupsurvexlegs, addupsurvexlength return legsbyexpo, addupsurvexlegs, addupsurvexlength

View File

@@ -1,5 +1,6 @@
import copy import copy
import io import io
import math
import os import os
import re import re
import subprocess import subprocess
@@ -70,7 +71,7 @@ dup_includes = 0
debugprint = False # Turns on debug printout for just one *include file debugprint = False # Turns on debug printout for just one *include file
debugprinttrigger = "!" debugprinttrigger = "!"
dataissues = [] dataissues = set()
class SurvexLeg: class SurvexLeg:
"""No longer a models.Model subclass, so no longer a database table""" """No longer a models.Model subclass, so no longer a database table"""
@@ -108,9 +109,12 @@ def set_walletdate(w):
w.save() w.save()
def stash_data_issue(parser=None, message=None, url=None, sb=None): def stash_data_issue(parser=None, message=None, url=None, sb=None):
"""Avoid hitting the database for error messages until the end of the import""" """Avoid hitting the database for error messages until the end of the import
use a set, we do not want identically duplicate issues
"""
global dataissues global dataissues
dataissues.append((parser, message, url, sb)) dataissues.add((parser, message, url, sb))
def store_data_issues(): def store_data_issues():
"""Take the stash and store it permanently in the database instead """Take the stash and store it permanently in the database instead
@@ -129,8 +133,8 @@ def store_data_issues():
di_list.append(DataIssue(parser=parser, message=message, url=url)) di_list.append(DataIssue(parser=parser, message=message, url=url))
# Now commit to db # Now commit to db
DataIssue.objects.bulk_create(di_list) DataIssue.objects.bulk_create(di_list)
dataissues = [] # in database now, so empty cache dataissues = set()
def get_offending_filename(path): def get_offending_filename(path):
"""Used to provide the URL for a line in the DataErrors page """Used to provide the URL for a line in the DataErrors page
which reports problems on importing data into troggle which reports problems on importing data into troggle
@@ -285,7 +289,8 @@ class LoadingSurvex:
rx_teamone = re.compile(r"(?i)^\s*(.*)\s*$") rx_teamone = re.compile(r"(?i)^\s*(.*)\s*$")
rx_person = re.compile(r"(?i) and |/| / |, | , |&| & | \+ |^both$|^none$") rx_person = re.compile(r"(?i) and |/| / |, | , |&| & | \+ |^both$|^none$")
rx_tapelng = re.compile(r"(?i).*(tape|length).*$") rx_tapelng = re.compile(r"(?i).*(tape|length).*$") # normal tape
rx_cartlng = re.compile(r"(?i).*([-+]?\d*\.\d+)") # cartesian units and scale
rx_cave = re.compile(r"(?i)caves-(\d\d\d\d)/([-\d\w]+|\d\d\d\d-?\w+-\d+)") rx_cave = re.compile(r"(?i)caves-(\d\d\d\d)/([-\d\w]+|\d\d\d\d-?\w+-\d+)")
rx_comment = re.compile(r"([^;]*?)\s*(?:;\s*(.*))?\n?$") rx_comment = re.compile(r"([^;]*?)\s*(?:;\s*(.*))?\n?$")
@@ -779,17 +784,46 @@ class LoadingSurvex:
def LoadSurvexUnits(self, survexblock, line): def LoadSurvexUnits(self, survexblock, line):
# all for 4 survex files with measurements in feet. bugger. # all for 4 survex files with measurements in feet. bugger.
# Won't need this once we move to using cavern or d3dump output for lengths # ..and all the cartesian files (ARGE) with scaling factors
tapeunits = self.rx_tapelng.match(line) # tape|length tapeunits = self.rx_tapelng.match(line) # tape|length
if not tapeunits: if not tapeunits:
angle = re.match(r"(?i).*(degrees|grads|percent).*$", line)
if angle:
# we don't care
return
lruds = re.match(r"(?i).*(left|right|up|down).*$", line)
if lruds:
# we don't care
return
scale = self.rx_cartlng.match(line)
if scale:
message = f"! *UNITS SCALE '{line}' ({survexblock}) {survexblock.survexfile.path} {len(scale.groups())} {scale.groups()[0]=}"
print(self.insp + message)
stash_data_issue(parser="survexunits", message=message, url=None, sb=(survexblock.survexfile.path))
self.unitsfactor = float(scale.groups()[0])
else:
message = f"! *UNITS SCALE FAIL '{line}' ({survexblock}) {survexblock.survexfile.path} "
print(self.insp + message)
stash_data_issue(parser="survexunits", message=message, url=None, sb=(survexblock.survexfile.path))
metres = re.match(r"(?i).*(METRIC|METRES|METERS)$", line)
if metres:
self.units = "metres"
else:
message = f"! *UNITS not meters - not converted '{line}' ({survexblock}) {survexblock.survexfile.path}"
print(self.insp + message)
stash_data_issue(parser="survexunits", message=message, url=None, sb=(survexblock.survexfile.path))
return
return return
convert = re.match(r"(?i)(\w*)\s*([\.\d]+)\s*(\w*)", line) convert = re.match(r"(?i)(\w*)\s*([\.\d]+)\s*(\w*)", line)
if convert: if convert:
factor = convert.groups()[1] factor = convert.groups()[1]
self.unitsfactor = float(factor) self.unitsfactor = float(factor)
if debugprint: if True:
message = ( message = (
f"! *UNITS NUMERICAL conversion [{factor}x] '{line}' ({survexblock}) {survexblock.survexfile.path}" f" *UNITS NUMERICAL conversion [{factor}x] '{line}' ({survexblock}) {survexblock.survexfile.path}"
) )
print(self.insp + message) print(self.insp + message)
stash_data_issue(parser="survexunits", message=message) stash_data_issue(parser="survexunits", message=message)
@@ -960,6 +994,8 @@ class LoadingSurvex:
"""This reads compass, clino and tape data but only keeps the tape lengths, """This reads compass, clino and tape data but only keeps the tape lengths,
the rest is discarded after error-checking. the rest is discarded after error-checking.
Now skipping the error checking - returns as soon as the leg is not one we count. Now skipping the error checking - returns as soon as the leg is not one we count.
Much less checking for Cartesian data.
REPLACE ALL THIS by reading the .log output of cavern for the file. REPLACE ALL THIS by reading the .log output of cavern for the file.
But we need the lengths per Block, not by File. dump3d will do lengths per block. But we need the lengths per Block, not by File. dump3d will do lengths per block.
@@ -979,17 +1015,35 @@ class LoadingSurvex:
if self.datastar["type"] == "passage": if self.datastar["type"] == "passage":
return return
if self.datastar["type"] == "cartesian": if self.datastar["type"] == "cartesian":
# message = f" ! CARTESIAN data in {survexblock.survexfile.path} {self.unitsfactor=}."
# stash_data_issue(
# parser="survexleg", message=message, url=None, sb=(survexblock.survexfile.path)
# )
ls = sline.lower().split()
# CARTESIAN, so there should be 5 fields: from to dx dy dz
# we don't care what they are called, we just use the last 3
if len(ls) != 5:
print(f" Line: {sline}\nsvxline: {svxline}")
message = f" ! Not 5 CARTESIAN fields in line '{sline.lower()}' {self.datastar=} {ls=} in\n{survexblock}\n{survexblock.survexfile}\n{survexblock.survexfile.path}"
stash_data_issue(
parser="survexleg", message=message, url=None, sb=(survexblock.survexfile.path)
)
return
leglength = math.sqrt(float(ls[2])**2 + float(ls[3])**2 + float(ls[4])**2)
if self.unitsfactor:
leglength = leglength * self.unitsfactor
self.legsnumber += 1
survexblock.legslength += leglength
self.slength += leglength
return return
if self.datastar["type"] == "nosurvey": if self.datastar["type"] == "nosurvey":
return return
if self.datastar["type"] == "diving": if self.datastar["type"] == "diving":
return return
if self.datastar["type"] == "cylpolar": if self.datastar["type"] == "cylpolar":
return return
if debugprint:
print(
f" !! LEG data lineno:{self.lineno}\n !! sline:'{sline}'\n !! datastar['tape']: {self.datastar['tape']}"
)
if self.datastar["type"] != "normal": if self.datastar["type"] != "normal":
return return
@@ -1174,7 +1228,6 @@ class LoadingSurvex:
# this produces a lot of printout, so don't print it # this produces a lot of printout, so don't print it
reftxt = refline.groups()[0] # only one item in this tuple reftxt = refline.groups()[0] # only one item in this tuple
if reftxt: if reftxt:
print(f"{self.insp} *REF quoted text: '{reftxt}' in {survexblock.survexfile.path}")
# only store it if not an empty string # only store it if not an empty string
survexblock.ref_text = reftxt survexblock.ref_text = reftxt
survexblock.save() survexblock.save()
@@ -1265,7 +1318,7 @@ class LoadingSurvex:
if args == "": if args == "":
# naked '*data' which is relevant only for passages. Ignore. Continue with previous settings. # naked '*data' which is relevant only for passages. Ignore. Continue with previous settings.
return return
# DEFAULT | NORMAL | CARTESIAN| NOSURVEY |PASSAGE | TOPOFIL | CYLPOLAR | DIVING # DEFAULT | NORMAL | CARTESIAN| NOSURVEY |PASSAGE | TOPOFIL | CYLPOLAR | DIVING -- all ignored
ls = args.lower().split() ls = args.lower().split()
if ls[0] == "default": if ls[0] == "default":
self.datastar = copy.deepcopy(self.datastardefault) self.datastar = copy.deepcopy(self.datastardefault)
@@ -1307,9 +1360,8 @@ class LoadingSurvex:
# print(message,file=sys.stderr) # print(message,file=sys.stderr)
# stash_data_issue(parser='survex', message=message) # stash_data_issue(parser='survex', message=message)
self.datastar["type"] = ls[0] self.datastar["type"] = ls[0]
elif ls[0] == "cartesian": # We should not ignore this ?! Default for Germans ? elif ls[0] == "cartesian": # Handled in the legs calc.
# message = f" ! - *data {ls[0].upper()} blocks ignored. {survexblock.name}|{args}" # message = f" ! - *data {ls[0].upper()} blocks ignored. {survexblock.name}|{args}"
# print(message)
# print(message,file=sys.stderr) # print(message,file=sys.stderr)
# stash_data_issue(parser='survex', message=message) # stash_data_issue(parser='survex', message=message)
self.datastar["type"] = ls[0] self.datastar["type"] = ls[0]
@@ -2964,7 +3016,7 @@ def LoadSurvexBlocks():
print(" - Flushing survex Data Issues ") print(" - Flushing survex Data Issues ")
global dataissues global dataissues
dataissues = [] dataissues = set()
DataIssue.objects.filter(parser="survex").delete() DataIssue.objects.filter(parser="survex").delete()
DataIssue.objects.filter(parser="xSvxDate").delete() DataIssue.objects.filter(parser="xSvxDate").delete()
DataIssue.objects.filter(parser="survexleg").delete() DataIssue.objects.filter(parser="survexleg").delete()

View File

@@ -27,15 +27,15 @@ in an <a href="/repositories/loser/.git/tree/docs/smklengths.ods">ODS-format spr
legsbyexpo: ((expedition, {"success":success, "people": expoers, "tourists": tourists, "nsurvexlegs": legsyear, "survexleglength": survexleglength, "nblocks": nblocks})) legsbyexpo: ((expedition, {"success":success, "people": expoers, "tourists": tourists, "nsurvexlegs": legsyear, "survexleglength": survexleglength, "nblocks": nblocks}))
--> -->
<table> <table>
<tr><th>Year</th><th>Survex<br>Survey<br>Blocks</th><th>Survex<br>Survey Legs</th><th>Survex <br>length(m)</th><th>Cavers</th><th>Non-cavers</th><th>meters/caver</th></tr> <tr><th>Year</th><th>Survex<br>Survey<br>Blocks</th><th>Survex<br>Survey<br>Legs</th><th>Survex <br>length(m)</th><th>Cavers</th><th>Non-cavers</th><th>meters/caver</th></tr>
{% for legs in legsbyexpo %} {% for legs in legsbyexpo %}
<tr> <tr>
<td style="text-align:center"><a href="{{ legs.0.get_absolute_url }}">{{legs.0}}</a></td> <td style="text-align:center"><a href="{{ legs.0.get_absolute_url }}">{{legs.0}}</a></td>
<td style="text-align:center">{{legs.1.nblocks}}</td> <td style="text-align:center"><a href="/wallets/year/{{legs.0}}">{{legs.1.nblocks}}</a></td>
<td style="text-align:center">{{legs.1.nsurvexlegs|rjust:"10"|floatformat:"0g"}} </td> <td style="text-align:center"><a href="/survexfilewild/{{legs.0}}">{{legs.1.nsurvexlegs|rjust:"10"|floatformat:"0g"}}</a></td>
<td style="text-align:right">{{legs.1.survexleglength|floatformat:"0g"}}</td> <td style="text-align:right">{% if legs.1.missing_length %}<span style="color:red">{% else %}<span>{% endif %}{{legs.1.survexleglength|floatformat:"0g"}}</span> </td>
<td style="text-align:right">{{legs.1.people|floatformat:"0g"}}</td> <td style="text-align:right">{{legs.1.people|floatformat:"0g"}}</td>
<td style="text-align:right">{{legs.1.tourists|floatformat:"0g"}}</td> <td style="text-align:center">{{legs.1.tourists|floatformat:"0g"}}</td>
<td style="text-align:right">{{legs.1.success|floatformat:"1g"}}</td> <td style="text-align:right">{{legs.1.success|floatformat:"1g"}}</td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@@ -9,6 +9,7 @@ plans and elevations. It also contains scans of centre-line survex output on whi
hand-drawn passage sections are drawn. These hand-drawn passages will eventually be hand-drawn passage sections are drawn. These hand-drawn passages will eventually be
traced to produce Tunnel or Therion drawings and eventually the final complete cave survey. traced to produce Tunnel or Therion drawings and eventually the final complete cave survey.
<p>Link to <a href="/expedition/{{year}}">logbooks and calendar for {{year}}</a>. <p>Link to <a href="/expedition/{{year}}">logbooks and calendar for {{year}}</a>.
<p>Link to <a href="/survexfilewild/{{year}}">unwalleted survex files for {{year}}</a>.
{% include 'wallet_new.html' %} {% include 'wallet_new.html' %}