Posts mit dem Label Software werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Software werden angezeigt. Alle Posts anzeigen

Samstag, 9. Januar 2016

MyFinds - die selbstgefundenen Caches durchsuchen und ein bisschen Statistik

Statistik hat ja für verschiedene Geocacher einen unterschiedlichen Stellenwert. Uns interessiert die Gesamtheit der nackten Geocaching-Statistik nicht so unbedingt, aber so ein paar Statistiken und besonders die von uns gefundenen Caches nach bestimmten Kriterien zu durchsuchen, interessiert uns manchmal dann doch. Dafür haben 25% von DerSchnelleLinus "MyFinds" programmiert. MyFinds ist in Python geschrieben und nutzt das Django Webframework.

So "richtig" neu ist MyFinds nicht, da es zwei ältere (ebenfalls selbst programmierte) Projekte vereint, nämlich pygcbrowse und pygcstats und außerdem die bereits vorhandenen Geocaching-Applikationen Cachekeeper und Mysterykeeper ergänzt.

Was MyFinds macht ist recht simpel: es liest die GPX-Datei des "Meine Funde" Pocket Queries ein und speichert die Daten zu den Caches in einer lokalen SQLite-Datenbank. Diese liefert dann die Daten für die Statistiken und die Suche. Das ganze wird über den Browser bedient, die Aufbereitung der Daten und die Ausgabe als HTML-Datei erfolgt über das bereits erwähnte Django Webframework, welches ebenfalls lokal einen Webserver bereit stellt.

Die Startseite des Applikation ist relativ unspektakulär, da hier einfach nur die drei Auswahlmöglichkeiten aufgelistet werden.

Startseite der MyFinds Applikation

Ein Klick auf den Link "Statistics" ruft die Statistik-Seite auf:

durch MyFinds generierte Statistiken

Wie zu sehen ist, werden sieben Statistiken aufgelistet - halt das, was uns mal so ab und an interessiert, nachzuschauen.

Etwas spannender ist da die Suche-Seite. Diese erlaubt es, die gefundenen Caches nach diversen Kriterien zu durchforsten:

Suchmaske
Wie zu sehen ist, stehen eine ganze Reihe von Suchmöglichkeiten zur Verfügung. Natürlich kann man auch mehrere Kriterien auswählen, die Suchbegriffe werden dann mittels "und" verknüpft. So würde z.B. "Cache Type: Traditional, Terrain = 4" nach allen Tradis mit einer T-Wertung  von 4 suchen.

Alle zur Verfügung stehenden Suchkriterien sind:
  • Suche nach Cache Owner
  • Such nach Cache Namen
  • Suche nach Cacheart
  • Auswahl nach Land
  • Auswahl nach Bundesland (bzw. Bundesstaat, Provinz etc.)
  • Auswahl nach Jahr des Fundes
  • Auswahl nach T-Wertung (inkl. T-Wertung "größer als" oder "kleiner als" oder "gleich")
  • Auswahl nach D-Wertung (inkl. D-Wertung "größer als" oder "kleiner als" oder "gleich")
  • Selektion nach Abstand von den Heimatkoordinaten
Das Ergebnis wird dann als Tabelle ausgegeben:

Ergebnis der Suche nach den Caches eines bestimmten Owners
Was wir ganz praktisch finden (und was deswegen auch eingebaut ist ;-) ), ist die Möglichkeit, sich die Position der Caches, welche im Suchergebnis aufgelistet sind, direkt auf einer OpenStreetMap Karte zeigen zu lassen. Diese wird direkt unterhalb der Tabelle automatisch angezeigt:

Ort der Caches aus dem Suchergebnis

Natürlich skaliert die Karte beliebig, d.h. es sind nicht nur "lokale" Karten (wie oben im Bildschirmfoto zu sehen), möglich. Das folgende Bildschirmfoto zeigt z.B. eine Karte mit unseren Funden 2015:

Karte
Klickt man in der Ergebnistabelle auf die GC-Nummer eines Caches, so werden dessen Details angezeigt:

Details zu einem gefundenen Cache
Wie gesagt ist MyFinds selbst geschrieben und damit nach unseren Wünschen gestaltet (das ist halt der Vorteil von selbst erstellter Software :-) ).
Wer Interesse an MyFinds hat, kann uns gerne kontaktieren. Auf dem eigenen Rechner wird lediglich Python 3.4 oder neuer und Django benötigt.

Donnerstag, 12. November 2015

Kartendienst Schutzgebiete in Deutschland

Geocaches darf bzw. sollte man nicht überall legen. Bei Groundspeak, also geocaching.com, ist wohl ein Punkt, den der Reviewer überprüft, ob der Cache in einem Schutzgebiet liegt. Entweder gelten dann Einschränkungen (wie z.B. "muss ohne verlassen des Weges erreichbar sein") oder es ist erst gar kein Auslegen des Caches erlaubt.

Das Problem dabei: wenn es nicht gerade ein bekanntes bzw. ausgeschildertes Gebiet ist, weiß man vielleicht gar nicht, dass man einen Cache in einem Schutzgebiet platziert hat.

Einen sehr gute Übersicht über Schutzgebiete in Deutschland gibt die Seite http://www.geodienste.bfn.de/schutzgebiete , auf der man sich diese anzeigen lassen kann.

Ruf man die obige URL auf, so erscheint eine Karte im Browserfenster, wie in der folgenden Abbildung zu sehen:

Startansicht der Webeite
Gezeigt wird Deutschland und markiert sind Naturschutzgebiete sowie Nationalparks.


Oben rechts wird standardmäßig eine Auswahlliste eingeblendet, welche Schutzgebiete auf der Karte angezeigt werden sollen. Neben den Naturschutzgebieten und Nationalparks stehen noch Biosphärenreservate, Naturparks, Landschaftsschutzgebiete, FFH-Gebiete und Vogelschutzgebiete zur Auswahl.

Auswahlliste der anzuzeigenden Schutzgebiete
In die Karte lässt sich dynamisch hineinzoomen, so dass man auch einen detaillierten Blick auf das Gebiet werfen kann, welche für einen selber von Interesse ist.

Sehr praktisch ist auch die Suchleiste links oben:

Suchleiste
Fängt man an, in das Textfeld zu tippen, werden dynamische Vorschläge zum gerade eingetippten gemacht:

Suchergebnisse werden dynamisch angezeigt
Wie zu sehen ist, wird dabei praktischerweise gleichzeitig nach Städte- / Ortsnamen als auch Namen von Schutzgebieten gesucht.

Was leider nicht möglich ist - jedenfalls wüssten wir nicht wie - ist, Koordinaten einzugeben und so zu sehen, ob diese in einem Schutzgebiet liegen.

Nichts desto trotz ist die Webseite http://www.geodienste.bfn.de/schutzgebiete ein sehr praktisches Hilfsmittel, um zu prüfen, ob eine neu geplanter Cache vielleicht in einem Schutzgebiet liegt.

Sonntag, 6. September 2015

Anzahl der Fund, DNFs, Wartungen etc der eigenen Caches auslesen

Statistiken gibt es beim Geocaching viele in jeglicher Ausprägung. Allerdings sind diese fast immer auf (eigene) Funde fokussiert.

Wer als Cacheowner z.B. wissen will, wie viele Funde die eigenen gelegten Caches haben, der schaut erst Mal in die Röhre. Jedenfalls gibt es keine uns bekannte Möglichkeit, dies zu sehen.
Wer "nur" eine handvoll Caches gelegt hat, kann dies natürlich noch relativ einfach und schnell von Hand erledigen. Für Cacheowner mit mehr als ein paar Caches, würde dies händisch viel zu lange dauern, etliche Dutzend Listings von Hand aufzurufen.

Da uns diese Zahlen aber interessieren, wurde - selbst ist der Geocacher - ein Python-Skript (für Python 3) geschrieben, welches die Anzahl der "Found it", "Didn't find it", "Write note", "Need Maintenance", "Owner Maintenance", "Temporarily Disable Listing", "Enable Listing" und "Needs Archived" Logs aus den Cachelistings extrahiert, zusammenrechnet und am Ende am Bildschirm ausgibt.

Die gewünschten Daten sind in jedem Listing bei geocaching.com zu finden und für jeden sichtbar, d.h. man muss nicht auf der Webseite eingelogt sein.

Was das Skript macht ist folgendes:
Es wird zuerst eine Datei cache_list.txt (die im selben Verzeichnis liegen muss die das Skript selbst) eingelesen, in der zeilenweise die GC-Nummer der abzurufenden Caches hinterlegt sind. Die Struktur der Datei ist also

GC2X3F0
GC3M3R8
GC3PGDD
GC3PM4E
...

Für jeden dieser Caches lädt das Skript die Webseite des Listing in den Speicher, parst das HTML der Webseite und extrahiert daraus die Logzahlen.
Während das Skript arbeitet werden die Daten für den jeweiligen Cache auf dem Bildschirm ausgegeben:

...
reading: GC4DRB0
Found it:  166 - Write note:  1 - Owner Maintenance:  1 -
---------------------------------------
reading: GC4EA6J
Found it:  99 - Didn't find it:  1 - Write note:  2 - Owner Maintenance:  2 -
----------------------------------------
...

Nachdem alle Listings abgerufen und geparst wurden, wird das Ergebnis ausgegeben.

Der komplette Python-Code des Skripts sieht so aus:

from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
from html.parser import HTMLParser
from datetime import datetime


class MyHTMLParser(HTMLParser):

    def __init__(self):
        HTMLParser.__init__(self)
        self.recording = 0
        self.cache_data = {"Found it": 0,
                           "Didn't find it": 0,
                           "Write note": 0,
                           "Owner Maintenance": 0,
                           "Needs Maintenance": 0,
                           "Temporarily Disable Listing": 0,
                           "Enable Listing": 0,
                           "Needs Archived": 0}
        self.cur_value = None

    def handle_starttag(self, tag, attrs):
        if tag == "img":
            for name, value in attrs:
                if name == "title" and value == "Found it":
                    self.cur_value = "Found it"
                elif name == "title" and value == "Owner Maintenance":
                    self.cur_value = "Owner Maintenance"
                elif name == "title" and value == "Didn't find it":
                    self.cur_value = "Didn't find it"
                elif name == "title" and value == "Write note":
                    self.cur_value = "Write note"
                elif name == "title" and value == "Needs Maintenance":
                    self.cur_value = "Needs Maintenance"
                elif name == "title" and value == "Temporarily Disable Listing":
                    self.cur_value = "Temporarily Disable Listing"
                elif name == "title" and value == "Enable Listing":
                    self.cur_value = "Enable Listing"
                elif name == "title" and value == "Needs Archived":
                    self.cur_value = "Needs Archived"
                self.recording = 1

    def handle_data(self, data):
        if self.recording:
            if self.cur_value == "Owner Maintenance":
                self.cache_data["Owner Maintenance"] = \
                    self.cache_data["Owner Maintenance"] + int(data)
                print("{}: {} - ".format(self.cur_value, data), end="")
            elif self.cur_value == "Needs Maintenance":
                self.cache_data["Needs Maintenance"] = \
                    self.cache_data["Needs Maintenance"] + int(data)
                print("{}: {} - ".format(self.cur_value, data), end="")
            elif self.cur_value == "Found it":
                self.cache_data["Found it"] = \
                    self.cache_data["Found it"] + int(data)
                print("{}: {} - ".format(self.cur_value, data), end="")
            elif self.cur_value == "Didn't find it":
                self.cache_data["Didn't find it"] = \
                    self.cache_data["Didn't find it"] + int(data)
                print("{}: {} - ".format(self.cur_value, data), end="")
            elif self.cur_value == "Write note":
                self.cache_data["Write note"] = \
                    self.cache_data["Write note"] + int(data)
                print("{}: {} - ".format(self.cur_value, data), end="")
            elif self.cur_value == "Needs Archived":
                self.cache_data["Needs Archived"] = \
                    self.cache_data["Needs Archived"] + int(data)
                print("{}: {} - ".format(self.cur_value, data), end="")
            elif self.cur_value == "Temporarily Disable Listing":
                self.cache_data["Temporarily Disable Listing"] = \
                    self.cache_data["Temporarily Disable Listing"] + int(data)
                print("{}: {} - ".format(self.cur_value, data), end="")
            elif self.cur_value == "Enable Listing":
                self.cache_data["Enable Listing"] = \
                    self.cache_data["Enable Listing"] + int(data)
                print("{}: {} - ".format(self.cur_value, data), end="")
            self.cur_value = None
            self.recording = 0

p = MyHTMLParser()
print("Starting at {}".format(datetime.now()))
with open("cache_list.txt", "r") as f:
    for cache in f:
        print("reading: {}".format(cache), end="")
        req = Request("http://coord.info/{}".format(cache))
        try:
            response = urlopen(req)
        except HTTPError as e:
            if e.code == 404:
                print("...is an invalid GC-number!", end="")
            else:
                print("Got HTTPError code {} when trying to fetch data for {}"
                      .format(e.code, cache))
        else:
            html = response.read().decode("utf-8")
            p.feed(html)
        print()
        print("-"*40)
print("Data on caches:")
print("Found it logs: {}".format(p.cache_data["Found it"]))
print("Didn't find it logs: {}".format(p.cache_data["Didn't find it"]))
print("Write note logs: {}".format(p.cache_data["Write note"]))
print("Need Maintenance logs: {}".format(p.cache_data["Needs Maintenance"]))
print("Owner Maintenance logs: {}".format(p.cache_data["Owner Maintenance"]))
print("Needs Archived logs: {}".format(p.cache_data["Needs Archived"]))
print("Temporarily Disable Listing: {}"
      .format(p.cache_data['Temporarily Disable Listing']))
print("Enable Listing logs: {}".format(p.cache_data["Enable Listing"]))
p.close()
print("Finished at {}".format(datetime.now()))

Das Skript arbeitet die Liste der GC-Nummer übrigens "stumpf" ab, d.h. es erfolgt keinerlei Prüfung, ob die GC-Nummer auch wirklich ein eigener Cache ist - von daher sollte man beim Anlegen der Datei mit den GC-Nummern sorgfältig sein.
Sollte die Liste eine ungültige (=nicht existierende) GC-Nummer enthalten, so gibt es Skript einen Hinweis am Bildschirm aus und fährt dann mit dem nächsten Cache fort.

Das Ergebnis sieht dann so aus (heutiger Stand für unsere 89 aktiven Caches):

Data on caches:
Found it logs: 8094
Didn't find it logs: 22
Write note logs: 176
Need Maintenance logs: 16
Owner Maintenance logs: 118
Needs Archived logs: 0
Temporarily Disable Listing: 11
Enable Listing logs: 11

Das ganze dauert übrigens ein bisschen, da die Server von Groundspeak ja nicht so schnell sind (und wir außerdem zu Hause noch eine relative lahme Internetanbindung haben). Für die 89 Cache wurde ca. 11 Minuten benötigt.

Was aber nicht wirklich schlimm ist, weil man diese Statistik ja nicht so häufig benötigt. Außerdem könnte man die Abrufe der Webseiten bei Bedarf noch parallelisieren.

Anzumerken ist auch noch, dass Web Scraping nicht zur "feinen englische Art" gehört - auch, wenn hier "nur" die Daten zu eigenen Caches abgerufen werden.
Wenn also jemand eine bessere / "feinere" Art kennt, an die Daten zu kommen, kann das gerne in den Kommentaren beschrieben werden.

Und auch bei Fragen / Anmerkung zum Skript bitte direkt an uns wenden.

Freitag, 14. August 2015

Cachekeeper - die eigenen Caches verwalten

Wer mehr als ein paar Caches legt kommt wahrscheinlich irgendwann nicht mehr umhin, eine gewisse Buchführung einzuführen. Wie z.B. "Welcher Cache hat welche Dose?", "Welches Logbuch ist in dem Cache?" oder "Wann wurde bei welchem Cache welche Wartung durchgeführt?".

Früher haben wir unsere Buchführung via CouchDB gemacht, darüber hatten wir hier im Blog im Juni 2013 bereits geschrieben. Das Verwaltung über die CouchDB Datenbank hat zwar eigentlich gut geklappt, erfüllte aber doch nicht so richtig alle Wünsche. Dazu gehören z.B. eine bessere Übersicht über durchgeführte Wartungen und eine Exportmöglichkeit für die Lösungen und Lösungswege unserer Mysteries (falls ein Cacher bei einem Rätsel mal nicht weiter kommt - obwohl die eigentlich alle gut lösbar sind ;-) ). Außerdem war noch gewünscht, sich eine Karte mit den Finalpositionen der eigenen Caches generieren zu lassen.

Also wurde im Frühjahr beschlossen, eine eigene Software für die Verwaltung der eigenen Caches zu schreiben.

Der Name: Cachekeeper.

Das ganze ist in Python und dem Webframework Django umgesetzt. Die Softwarebasis ist also die gleiche wie die von Mysterykeeper, welches hier im Blog im Mai dieses Jahres vorgestellt wurde.

Technisch gesehen wird Cachekeeper also über den Browser bedient, Django stellt die Daten (lokal) über den eingebauten Webserver bereit und die Daten an sich liegen in einer relationalen Datenbank.

Zu Cachekeeper an sich:

Zu jedem eigenen Cache kann man in Cachekeeper einen Eintrag anlegen. Dieser enthält folgende Pflichtangaben:

  • GC-Nummer (oder OC-Nummer)
  • Name des Caches
  • Cache-Typ (Tradi, Mystery, Multi, Letterbox...)
  • Dose
  • Finalkoordinaten
  • Gemarkung, in der der Cache liegt
außerdem gibt es noch folgende optionale Felder:
  • Notizen
  • Antworten (bei Mysteries wird hier die Lösung hinterlegt)
  • Geochecker-Link
  • OC-only Cache?
Das ganze sieht in der Eingabemaske so aus:

Eingabemaske zum Eingeben und Editieren von Caches
Des Weiteren können noch für jeden Cache Einträge für durchgeführte Wartungen hinterlegt werden, ebenso können für jedem Cache beliebig viele Anhänge (wie z.B. Bilder für das Listing, Logbuchvorlagen etc.) hochgeladen werden.

Die Eingabe über aller Daten erfolgt über das Admin-Frontend, welches in Django standardmäßig enthalten ist. Dieses ist auch auf dem Bildschirmfoto oben zu sehen.

Ruft man Cachekeeper im Browser über http://localhost:8000/cachekeeper auf, so sieht man die Startseite des Programms, welche wie folgt aussieht:

Startseite von Cachekeeper
Hier werden alle aktiven Caches tabellarisch aufgelistet, wobei die Tabelle per Mausklick auf die Spaltenüberschrift nach der entsprechenden Spalte umsortiert werden kann.

Klickt man auf eine der Cache-IDs gelangt man zur Seite mit den Details zum gewählten Cache:

Detailansicht zu einem Cache
Aufgelistet sind tabellarisch alle Details zum Cache, inklusive einer Auflistung, wann welche Wartung durchgeführt wurde und welche Anhänge dem Cache zugeordnet sind.

Apropos Wartung: Cachekeeper stellt auch eine Seite bereit, auf der alle Wartungen chronologisch auflistet sind. Dies sieht so aus:

chronologische Liste der durchgeführten Wartungen
Über der Tabelle auf der Startseite von Cachekeeper sind einige Links zu finden, die auf weitere Seiten der Anwendungen verlinken:

die Menüleiste von Cachekeeper
Der Link "OC-only Caches" ruft die Seite auf, auf der die Caches aufgelistet werden, die exklusiv bei opencaching.de gelistet sind. Ein Klick auf "all caches" erzeugt eine Tabelle der Caches wie auf der Startseite, in der aber alle Caches aufgeführt werden - egal ob aktiv oder archiviert.

Des Weiteren gibt es hier die Möglichkeit, die Lösungen für alle im Programm hinterlegten Mysteries zu exportieren.
Sinn dieser Funktion ist übrigens nicht, dass man die Lösungen für seinen eigenen Mysteries besonders einfach in irgendwelchen dubiosen Facebook Gruppen zur Verfügung stellen kann. Vielmehr man so die Lösungen seiner Mysteries "dabei haben", falls andere Geocacher mal Probleme beim Lösen haben sollten, ohne dass man direkt die ganze Cachekeeper Applikation dabei haben zu müssen.

Der Link "Stats" ruft die Statistikseite. Diese sieht so aus:

Statistikseite
Wie im Bildschirmfoto zu sehen ist, wird hier die Anzahl der aktiven Caches nach verschiedenen Kategorien gezeigt. Neben der im obigen Bild zu sehenden Zählung nach Cachetyp und Cachegröße gibt es noch Statistiken zu den eingesetzten Dosen, sowie den Caches pro Gemarkung.

Wie oben bereits erwähnt bietet Cachekeeper weiterhin die Möglichkeit, eine Karte mit allen Caches innerhalb einer Gemarkung bzw. in mehreren Gemarkungen zu generieren. Dies ist z.B. praktisch, wenn man dem lokalen Forstamt oder Ortsbürgermeister eine Karte der (eigenen) existierenden Caches vorlegen möchte, z.B. zwecks Einholen der Genehmigung weiterer Caches.

Als Kartendarstellung für die Cachekarte kann zwischen OSM und Google Maps gewählt werden.

Die Auswahlseite für die Gemarkung(en) sieht wie folgt aus:

Auswahl der Gemarkung
Wie zu sehen ist, ist die Auswahlseite zweigeteilt. Im oberen Bereich ist eine Auflistung alle Gemarkungen (Gemeinden / Orte), für die mindestens ein aktiver Cache in der Datenbank hinterlegt ist. Ein Klick auf "Google Map" bzw. "OSM" generiert die entsprechen Karte.

Diese sieht mit OSM als Kartenquelle so aus:

Beispielkarte mit Caches in einer Gemarkung
Die roten Kreise um die Marker entsprechen einem Radius von 161 m in Realitität. Die Karte kann optional aber auch ohne Kreise und nur mit Markern dargestellt werden.

Möchte man eine Karte mit Caches in mehreren Gemarkung erstellt, dann wählt man diese einfach über die zugehörige Checkbox im unteren Teil der Auswahlseite an (das Bildschirmfoto oben zeigt nicht die komplette Liste). Die Darstellung entspricht der der Caches in nur einer Gemarkung:

Beispielkarte für Caches in mehreren Gemarkungen
So weit, so gut. Wir haben Cachekeeper seit ein paar Monaten für uns im Einsatz. Und es ist schon ganz praktisch und übersichtlich. Jedenfalls übersichtlicher als die alte Lösung mit CouchDB.
Aktuell läuft Cachekeeper "nur" lokal auf einem unserer Laptops. Grundsätzlich wäre es aber auch ohne Probleme möglich, das Programm auf einer Server zu verfrachten, welcher über das Internet erreichbar ist.

Falls jemand Interesse an Cachekeeper für sich hat, kann er uns gerne kontaktieren. Wir löschen dann aber vorher die Datenbank mit den Daten unserer Caches ;-)

Für den (lokalen) Betrieb muss Python 3 und das Django-Webframework installiert sein. Außerdem muss, bevor die Dateien für Cachekeeper kopiert werden, ein Projekt und ein Applikation angelegt werden (was kein Problem ist). Dann werden die Cachekeeper Dateien kopiert und die Datenbank angelegt. Was auch kein Probem ist. Danach wäre Cachekeeper einsatzbereit.

Mittwoch, 3. Juni 2015

BLG - Update 20150602

Das Feedback zum Artikel zum ultimativen Loggenerator BLG war doch recht positiv und inspirierend, so dass es heute ein kleines Update gibt.

Neben ein paar Korrekturen "unter der Haube" besitzt BLG jetzt auch die Möglichkeit, eine Satz zum Wetter einzufügen, wobei man die Auswahl zwischen drei verschiedenen Wetterszenarien hat (nämlich: gute Wetter, Wetter ok, schlechtes Wetter). Die Sätze zum Wetter sind natürlich genau so pauschal wie die anderen Logtexte.

Will man eine Satz zum Wetter hinzufügen, so nutzt man dazu die Option -w (oder --weather) gefolgt vom zugehörigen Argument good, ok oder bad.

Das sieht dann z.B. so aus:

$ python3 blg.py -w good

Heute nochmal zum Cachen unterwegs gewesen.
Die Tour führte auch zu diesem Cache.
Der Wettergott war heute auch gut gelaunt und bescherte tolles Wetter.
DFDC


$ python3 blg.py -w ok

Heute nochmal zum Cachen unterwegs gewesen.
Die Tour führte auch zu diesem Cache.
Wettertechnisch hätte es besser sein können, aber was soll's.
Danke für die Dose & TFTC


$ python3 blg.py -w bad

Heute nochmal zum Cachen unterwegs gewesen.
Diese Dose wurde erfolgreich gesucht und gefunden.
Die Witterung war ziemlich unwirtlich, nichts desto trotz hat die Tour Spaß gemacht.
TFTC

Das ganze funktioniert natürlich auf auf Englisch, z.B.:

$ python3 blg.py -l en -w ok

Had some time today, so went out to do some caches.
Found this one without problems.
The weather could have been better, but the tour was fun anyway.
TFTC
-------------------------

Done - thanks for using BLG, the Bullshit Log Generator


Die neue Version steht natürlich zum Download bereit.

Also weiterhin viel Spaß mit dem Bullshit Log Generator :-)

Sonntag, 31. Mai 2015

BLG - der ultimative Geocaching Log Generator

Welcher Geocacher kennt das nicht: den ganzen Tag zum Geocaching unterwegs gewesen und dabei etliche Cache gemacht. Und aufgrund des Leistungsdrucks - die Statistik muss ja stimmen! - waren das so richtig viele Caches. Die müssen auch noch alle online geloggt werden - was eine Arbeit!

Da man schließlich nicht als langweilige und total unkreative Person auffallen möchte, kommen stupide Copy & Paste Logs nicht in Frage.

Also, was tun?

Keine Sorge - hier ist DAS Tool zur Lösung dieses Problems: BLG (ausgesprochen: bi-el-dschi).

BLG ist ein Generator für Geocaching Logs. Diese passen garantiert immer, weil die Logs zwar plausibel, aber völlig nichtssagend sind. Und, da die Logs aus einer Auswahl von vordefinierten Textbausteine per Zufallsgenerator zusammengebaut werden, ist die Anzahl der doppelten Logs gering.

BLG ist in Python geschrieben, und die Bedienung ist total simpel: eine installierte Version von Python 3 vorausgesetzt lädt man BLG einfach herunter, speichert die drei Dateien in ein beliebiges Verzeichnis und führt BLG aus. Und in Nullkommanichts hat man seine Logtexte. Genial einfach, einfach genial.

Hier mal ein Beispiel:

$ python3 blg.py -n 5

Heute ging es nochmal raus ins Freie zwecks Geocaching.
Ohne Probleme gesucht und geloggt.
TFTC
-------------------------
Heute wieder auf Cache-Tour gewesen.
Einer der besuchten Caches war dieser hier.
Danke für's Legen und Pflegen des Caches.
-------------------------
Heute wieder auf Cache-Tour gewesen.
Die Tour führte auch zu diesem Cache.
Danke für's (Pf-) Legen dieses Caches.
-------------------------
Heute nochmal zum Cachen unterwegs gewesen.
Dabei wurde auch diese Dose besucht.
Danke für's Legen und Pflegen des Caches.
-------------------------
Heute unterwegs gewesen, um den eine oder anderen Cache zu machen.
Ohne Probleme gesucht und geloggt.
DFDC
-------------------------


Wie zu sehen ist, werden über die Option -n=5 direkt fünf Logtext generiert.

Du bist öfter im Ausland unterwegs? Kein Problem, denn der BLG kann auch englische Logs generieren, einfach über die Option -l en:

$ python3 blg.py -l en
 

Been today on tour again for some caches.
One of the caches visited was this one.
Thanks for hiding and maintaining this cache.
-------------------------


Wem die hinterlegten Textbausteine auf Dauer zu langweilig sind - auch kein  Problem! Einfach die Datei "template_de.py" (welche die deutschen Textbausteine enthält) um eigene erweitern. Das geht ganz einfach mit jedem beliebigem Texteditor.

Hier nochmal der Download-Link für BLG: Link

Ach ja, zum Schluss noch eine Anmerkung: BLG steht für "Bullshit Log Generator" - womit dann alles gesagt wäre ;-)


Nachtrag: am 2.6. ist eine neuer Version von BLG erschienen. Mehr dazu in diesem Blogartikel.

Montag, 4. Mai 2015

Mysterykeeper - gelöste Rätsel-Caches verwalten

Bei Mysterycaches kommt es ja durchaus öfters vor, dass man ein Rätsel löst, aber nicht direkt bzw. zeitnah zum Suchen und Loggen kommt. Also muss man sich die Lösung und die Finalkoordinaten irgendwo speichern.

Klar gibt es das "Anmerkungen zu diesem Listing" Feld in jedem Listing bei geocaching.com, wo man Notizen jeglicher Art hinterlegen kann, die nur für einen selber sichtbar sind. Das ist zwar ganz praktisch, hat aber zwei Nachteile: Erstens muss man online sein, um die Notizen zu sehen und zweitens weiß man so noch nicht, welche Mysteries man gelöst hat, aber noch nicht geloggt. Letzteres könnte man zwar über ein eigene Liste lösen (so fern man Premium Mitglied bei gecaching.com ist), was aber auch ein zusätzlicher Arbeitsschritt wäre - und Listen sind auch noch online abrufbar.

Bis vor kurzem haben wir unsere Lösung für Mysteries (und auch andere Caches wie Multis) in einer JSON-Datei gespeichert (siehe dazu auch unseren Blogbeitrag "Speichern von Lösungen für Mystery- und Multi-Caches" aus Oktober 2013). Das hat auch ganz gut funktioniert, wurde zum Ende hin aber ein bisschen unübersichtlich, weil die JSON-Datei ziemlich lange wurde, eben weil (zu) viele Caches drin enthalten waren.

Also sollte was besseres und vor allem Dingen übersichtlicheres her. Mit GSAK ginge das wohl, aber hier im Hause seit vielen Jahren keine Windows-Lizenz mehr vorhanden, also fällt jede Windows-only Lösung aus.

Da sich 25% von DerSchnelleLinus gerade so wie so mit Django (dem Webframework Nr. 1 für Python) beschäftigten, war das natürlich eine guten Gelegenheit, eine Python- / Django-basierte Lösung zu Basteln.

Gesagt, getan. Das Projekt wurde "Mysterykeeper" getauft, weil es ja in erster Linie um das Speichern von Mysterylösungen geht. Aus heutiger Sicht, also nach dem Hack der geocheck.org Datenbank Ende Januar 2015,  hat der Namen natürlich eine gewisse "Ironie" - aber gut, die Programmierarbeit an "Mysterykeeper" hat bereits 2014 begonnen.

Da Mysterykeeper für die persönliche Nutzungen konzeptioniert ist, ist das ganze auch recht einfach gestrickt: die Eingabe von neuen Daten (=Lösungen) erfolgt über das Admin-Backend, welches Django standardmäßig an Bord hat. Die Abfrage und die Anzeige der Lösungen erfolgt als HTML-Seite, welche von dem Webserver ausgeliefert wird, welcher ebenfalls bei Django an Bord ist.

Da wir das ganze "nur" lokal auf unseren Laptops benutzen gibt es keine zusätzlich Authentifizierung oder Benutzerverwaltung. Diese könnte (bzw. sollte) man aber einbauen, wenn man das ganz über eine  "richtigen" Webserver laufen lässt, welcher über das Internet erreichbar ist.  Was mit und Dank Django auch kein Problem wäre. Ist aber wie gesagt unsererseits aktuell nicht geplant.

Wie das ganze so aussieht wird im folgenden anhand eines Beispiels gezeigt. Der Cache, der für das Beispiel verwendet wird, ist ein Mystery von uns, der bereits im Archiv ist - also kein Spoiler-Alarm.

Wie gesagt erfolgt die Eingabe einer Lösung über das Admin-Backend von Django. Bei laufendem Server ist es unter http://localhost:8000/admin/mysterykeeper/ zu erreichen. Ruft man diese URL auf, sieht man die Startseite der Admin-Backend für Mysterykeeper:

Startseite des Admin-Backends
Wie zu sehen ist, gibt es zwei Tabellen in der Datenbank von Mysterykeeper:
  • "Solution" zum Speichern der Cache-bezogen Daten / Lösungen
  • "Attachment" zum Speichern von Anhängen zum einem Cache (z.B. Bilder u.ä.)
Nach einem Klick auf "Add" gelangt man in die Eingabemaske, welche so aussieht:

Eingabemaske für neue (gelöste) Caches
Aktuell ist die Datenbank so aufgebaut, dass man die folgende Daten eingeben kann:
  • GC-Nummer
  • Cachename
  • Cachetyp
  • Notizen (beliebig langer Text)
  • Finalkoordinaten
  • geloggt (Checkbox - ausgewählt = ja)
  • Ort

Als Cachetyp kann man - neben "Unknown Cache" (der offiziellen Bezeichnung von Groundspeak für Mysteries), wie im obigen Beispiel - auch noch einige andere Cachetypen auswählen, wie im folgenden Bildschirmfoto zu sehen ist:

Cachetypen, welche man in Mysterykeeper speichern kann
Ein Klick auf "Save" speichert die Daten und man gelangt automatisch auf die Übersichtsseite aller gespeicherten Caches. Der zuletzt hinzugefügt steht immer als oberstes in der Liste:

Liste der in Mysterykeeper gespeicherten Lösungen
Wie oben erwähnt, kann man zu jeder Lösung auch noch (beliebig viele) Anhänge hinterlegen, und zwar über die folgende Eingabemaske:

Eingabemaske für Anhänge für gespeicherte Lösungen
So weit, so gut. Wie gesagt erfolgt die Anzeige und Abfrage der gespeicherten Lösung über HTML-Seiten, welche vom Django-Server ausgeliefert werden. Ruft man die URL http://localhost:8000/mysterykeeper/ auf, so erscheint folgende Startseite:

Liste der gelösten, aber noch nicht geloggten Caches

Aufgelistet werden, sortiert nach GC-Nummer, alles gelösten, aber noch nicht geloggten (=gefundenen) Caches. Die Sortierung lässt sich durch eine Klick auf die Spaltenüberschrift auch nach anderen Tabellenspalten sortieren.

Klick man auf die GC-Nummer, erscheinen die Details zum Cache:

Details zu einem in Mysterykeeper hinterlegtem Cache
Hier sieht man alles, was man in der Eingabemaske des Admin-Backends eingegeben hat. Die drei Schaltfläche "Show at Google Maps", "Show at OSM", "Show Listing" sind wohl selbsterklärend: Die ersten beiden rufen Google Maps bzw. Open Street Map auf und zeigen eine Karte, wo das Final des Caches mit einem Marker markiert ist. Letztere Schaltfläche ruft das Listing bei geocaching.com auf.

Ein Klick auf "Mark as logged" markiert den Cache als geloggt. Als Sicherung gegen versehentliches Anklicken erfolgt danach noch eine Sicherheitsabfrage, ob man den Cache wirklich als "geloggt" markieren möchte.

Sicherheitsabfrage, ob man einen Cache wirklich als "geloggt" kennzeichnen möchte.

Neben der Standardanzeige der gelösten, aber ungeloggten Caches, kann man sich auf der Startseite auch noch alles Caches (unabhängig davon, ob geloggt oder nicht) anzeigen lassen bzw. man kann sich auch nur alle geloggten Caches ausgeben lassen.

Ein weiteres Feature des Mysterykeepers ist die Suche nach gelösten, aber nicht geloggten Caches in einem frei bestimmbaren Umkreis um vorzugebende Koordinaten:

Suche nach gelösten Cache im Umkreis nach vorzugebenden Koordinaten
Das Ergebnis sieht dann z.B so aus:


So weit, so gut. Von der Funktionalität her bietet der Mysterykeeper alles, was wir für uns brauchen. Und wenn mal irgendwann noch was fehlt wird's halt dazu programmiert.

Wir selber haben das Programm seit einiger Zeit im Einsatz und es ist: praktisch. Vor allem haben wir nach der Datenübernahme aus der alten JSON-Datei erst Mal gesehen, wie viele gelöste aber noch nicht gesuchte und nicht geloggte Mysteries wird so haben...

Ob der Programmcode irgendwann auch mal in einem öffentlich zugänglichem Repositry liegen wird steht noch nicht fest. Nicht, weil er closed source oder streng geheim wäre oder so - aber in erster Linie nutzen wird Mysterykeeper ja für uns selber.

Falls jemand Interesse am Code hat und diesen haben möchte - kein Problem, können wir zusenden. Dazu uns einfach kontaktieren. Wer eine leise Ahnung von Python und Django hat sollte auch keine Probleme haben, den Mysterykeeper bei sich lokal zum Laufen zu bringen.

Und wenn sich noch jemand fragt, warum das Programm (noch) komplett auf Englisch ist: das ist a) die Macht der Gewohnheit und b) ein gegebener Anlass, später auch mal das i18n-Modul von Django zur Übersetzung / Eindeutschung zu nutzen.


Nachtrag: Mysterykeeper kann (natürlich) auch mit Caches umgehen, die bei opencaching.de gelistet sind. Bei einem Klick auf "Show Listing" wird dann halt die Seite von opencaching.de (statt geocaching.com) aufgerufen.

Donnerstag, 20. November 2014

Projektvorstellung: pygcbrowse - die gefundenen Geocaches durchsuchen

Webseiten und Programme, um Statistiken über die (bei geocaching.com) gefundenen Caches zu generieren, gibt es viele. Will man aber die gefundenen Caches nach bestimmten Kriterien durchsuchen, gibt es nicht mehr so viel. GSAK kann das zwar (neben vielen anderen Dinge), ist aber Windows-only und nicht frei.
Solche Suchkriterien wären z.B. "Welches sind eigentlich die Caches, die ich von Cacheowner SpamEgg gefunden habe?" oder auch komplexer wie "Welche Cache habe ich zwischen dem 1.1.2013 und 31.12.2013 von Cacheowner SpamEgg gefunden, die mindestens eine D-Wertung von 2.5 und eine T-Wertung von 2.0 haben?".

Das hier vorgestellte pygcbrowse ist genau auf dieses Durchsuchen spezialisiert. Vor kurzem ist die erste öffentliche Version 0.2.1 verfügbar gemacht worden.

pygcbrowse läuft auf allen Rechnern und Betriebssystemen, für die Python 3.2 oder höher verfügbar ist - also auch so gut wie allen Linux-Distributionen, MacOS und Windows.

Eine Installation im eigentlichen Sinne ist nicht notwendig. Man muss lediglich die aktuelle Version von pygcbrowse von der Download-Seite herunterladen und in ein beliebiges Verzeichnis entpacken. Dann benötigt man noch den "Meine Funde" Pocket Query - den man aber (leider) nur als Premium Mitglied bei geocaching.com generieren kann. Die GPX-Datei des Pocket Queries kopiert man dann am besten ins Verzeichnis, in dem pygcbrowse und dessen Dateien liegen.

Jetzt kann man das Programm über den Befehl python3 pygcbrowse.py starten.

pygcbrowse startet und liest dann die GPX-Datei des Pocket Queries ein, befüllt damit eine temporäre Datenbank im RAM des Computers, startet den eingebauten Server - der rein lokal läuft und keinerlei Online-Verbindung benötigt - und ruft die lokale Suchseite im Browser auf.

Das ganze sieht dann so aus:

Suchmaske von pygcbrowse

Hier man in den verschiedenen Formularfeldern seine Suchkriterien eintragen und auswählen, diese werden - sofern Suchbegriffe in mehrere Felder eingegeben werden - mit UND verknüpft.

Im folgenden Bild ist eine ausgefüllte Suchmaske für:
  • im Name des Cacheowners kommt Joerg vor
  • die D-Wertung ist 2.0 oder größer
  • das Logdatum liegt zwischen dem 1.1.2013 und 31.12.2013
zu sehen:

ausgefüllte Suchmaske von pygcbrowse

Ein Klick auf "Suche" startet die Suche und zeigt einen Augenblick später das Ergebnis:

Suchergebnis einer Suche mit pygcbrowse
Wie im Bildschirmfoto zu sehen ist, treffen die Suchkriterien auf drei gefundene Caches zu. Diese werden in der Tabelle nach Funddatum sortiert, ein Klick auf eine Spaltenüberschrift ändert die Sortierung danach.
Über der Tabelle sind nochmals die Suchkriterien aufgeführt sowie die Anzahl der Suchtreffer, unter der Tabelle die Gesamtzahl der gefundenen Caches.

Wie gesagt können Suchkriterien beliebig kombiniert werden. Würde kein Suchkriterium eingegeben und auf "Suche" geklickt, würden alle gefundenen Caches als Ergebnis angezeigt.

Wer jetzt Interesse an pygcbrowse hat: die vollständige und ausführliche Dokumentation (sowohl auf Deutsch als auch auf Englisch) kann man entweder bei ReadTheDocs online lesen oder auf der oben verlinkten Download-Seite als PDF-Datei herunterladen.

Montag, 10. November 2014

Pop-Up Label in Locus 3.4 - auch für Geocaches

Über Locus Map haben wir hier im Blog schon öfters geschrieben. Am 7.11.2014 ist die Version 3.4 der App erschienen, welche natürlich wieder diverse Neuerung bringt. Eine davon ist auch für das Geocaching ganz interessant, nämlich die "Pop-up Label".

Durch die Pop-up Label bekommt man jetzt schnell die Grundinfos zu einem Cache angezeigt, ohne ins Listing gehen zu müssen.

In der Standardansicht werden Caches auf der Karte dargestellt, wie im folgenden Bildschirmfotozu sehen:

Anzeige des Orts von Caches auf der Karte
In den Locus Versionen vor 3.4 hat ein Tippen auf das Cache-Symbol direkt das Listing geöffnet. Mit der Einführung der Pop-up Label öffnet sich jetzt beim Tippen auf das Symbol eben dieses Label. Das ganze sieht wie folgt aus:

Pop-up Label zu einem Cache
Zu sehen sind also der Schwierigskeitesgrad des Caches (D), die Geländewertung (T), die Cachegröße (S), die Anzahl der Trackables im Cache (TR) und die Anzahl zusätzlichen Wegpunkte (W). Besonders durch die Einblendung der D- und T-Wertung sowie Cachegröße kann man sich so schnell einen Überblick verschaffen, was einen bei dieser Dose erwartet.

Tipp man auf den Pfeil > , öffnet sich ein weiteres Menü:

das 2. Pop-up Label Menü
Wie im Bild oben zu sehen ist kann man sich hier direkt noch den Hinweis zum Cache anzeigen lassen. Oder sich von Locus zum Cache Navigieren lassen.

Wer ins komplette Listing des Caches möchte tippt einfach auf das Pop-up Label und schon öffnet sich das Listing wie gewohnt.

Wir haben das ganze heute bei einer Cachetour mal ausprobiert und es ist schon ganz praktisch. Allerdings braucht man jetzt einen Tipper mehr, um zum Listing zu gelangen - dieses ist ja nicht mehr direkt erreichbar. Empfanden wir aber nicht als nachteilig.

Jedenfalls hat auch die neue Version Locus 3.4 weitere interessante Neuerungen zu bieten, wie beschrieben auch für Geocacher. Wobei die Pop-up Label für alle Wegpunkte in Locus vorhanden sind, nicht nur für Geocaches.


Edit 11.11.2014: falsche Info im Text korrigiert - das "W" im Pop-up Label steht für Wegpunkt (nicht Anzahl der Beobachter)

Samstag, 25. Oktober 2014

Eine Karte der eigenen Caches erstellen

Neulich wollten wir eine Karte mit den Finalpositionen aller von uns gelegten, aktiven Caches erstellen (für das lokale Forstamt). Die Idee: auf einer Google Maps Karte alle Cache-Positionen mit Markern markieren.

Und wie macht man das? Nach kurzer Internetrecherche fanden sich diverse Seiten, die erklären, wie das geht. Die Umsetzung ist im Prinzip ganz einfach, da das ganze mit einer einzelnen HTML-Datei mit eingebettetem JavaScript realisierbar ist. Der Ablauf ist wie folgt:
  • in der Datei ist eine Liste mit den Koordinaten der Caches hinterlegt
  • diese wird mittels JavaScript eingelesen
  • dann erzeugt das Script über die API von Google Maps die passende Karte mit Markern
  • die Karte wird als HTML-Seite im Browser angezeigt
Der Code dafür sieht so aus:

<!DOCTYPE html> <html lang="en"> <head>     <title>Geocaches - Görgeshausen - Blog-Demo</title>     <meta charset="utf-8">     <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>     <style>         html, body, #map-canvas { height: 100%; margin: 2px; padding: 2px }         h1 {font-size:16px; font-family:helvetica, arial, sans; padding: 2px; margin: 0px;}         p {font-size:14px; font-family:helvetica, arial, sans; padding: 2px; margin: 0px;}     </style>     <script type="text/javascript"> var LocationData = [     [50.394533, 7.957633, "Dosenshow: Matchstick Container", "http://maps.google.com/mapfiles/ms/icons/red-dot.png" ],     [50.39742, 7.95443, "Letterbox Alter Grenzstein", "http://maps.google.com/mapfiles/ms/icons/red-dot.png" ],     [50.39592, 7.94455, "Sommer, Sonne, Kaktus", "http://maps.google.com/mapfiles/ms/icons/red-dot.png" ],     [50.400167, 7.95755 , "Dosenshow: Weithalskanister", "http://maps.google.com/mapfiles/ms/icons/red-dot.png"],     [50.39777, 7.94897, "Dosenshow: Mini Decon Container", "http://maps.google.com/mapfiles/ms/icons/red-dot.png"],     [50.401667, 7.946717, "Dosenshow: Mun-Kiste", "http://maps.google.com/mapfiles/ms/icons/red-dot.png"],     [50.405217, 7.942033, "Dosenshow: Nacro Container", "http://maps.google.com/mapfiles/ms/icons/red-dot.png"],     [50.40527, 7.96688, "Dosenshow: Keep it clear Container", "http://maps.google.com/mapfiles/ms/icons/red-dot.png"],     [50.3946, 7.9599, "(geplanter Cache)", "http://maps.google.com/mapfiles/ms/icons/blue-dot.png"],     [50.3968, 7.9585, "(geplanter Cache)", "http://maps.google.com/mapfiles/ms/icons/blue-dot.png"] ]; function initialize() {     var map =         new google.maps.Map(document.getElementById('map-canvas'));     var bounds = new google.maps.LatLngBounds();     var infowindow = new google.maps.InfoWindow();         for (var i in LocationData)     {         var p = LocationData[i];         var latlng = new google.maps.LatLng(p[0], p[1]);         bounds.extend(latlng);                 var marker = new google.maps.Marker({             position: latlng,             map: map,             title: p[2],             icon: p[3]         });             google.maps.event.addListener(marker, 'click', function() {             infowindow.setContent(this.title);             infowindow.open(map, this);         });     }         map.fitBounds(bounds); } google.maps.event.addDomListener(window, 'load', initialize); </script> </head> <body>     <h1>Caches im Görgeshäuser Wald</h1>     <p>rot=existent, blau=geplant</p>     <div id="map-canvas"></div> </body> </html>
Speichert man diese Datei lokal ab, z.B. als meine_caches.html und öffnet die Datei im Webbrowser, sieht das ganze so aus:

aus dem Skript generierte Karte
Wer das Listing oben inhaltlich nicht versteht und trotzdem eine eigene Karte erstellen möchte: keine Sorge, das geht trotzdem.

Angepasst werden muss dabei nur der Bereich var LocationData = [...]. Dort befinden sich die Daten für die Marker.

Jeder Marker wird durch eine Zeile wie

[50.394533, 7.957633, "Dosenshow: Matchstick Container", "http://maps.google.com/mapfiles/ms/icons/red-dot.png" ]

dargestellt. Diese enthält, in eckige Klammern [ ] eingeschlossen:
  • die Breitengrad-Koordinaten im Dezimalgradformat (1. Eintrag)
  • die Längengrad-Koordinaten im Dezimalgradformat (2. Eintrag)
  • den Namen des Caches (3. Eintrag)
  • die Farbe des Markers (4. Eintrag).
Der Name des Caches (also der 3. Eintrag der Liste) wird auf der Karte immer dann angezeigt, wenn man mit dem Mauszeiger über den Marker fährt. Natürlich kann man hier auch jeden anderen, beliebigen Text hinterlegen.

Name des Caches wird angezeigt

Die farbigen Marker sind im obigen Beispiel so gewählt, dass rote Marker die Position (unserer) existierenden Caches zeigen, blau die noch geplanten.
Wie man die Farben ein- und verteilt kann natürlich jeder selber bestimmten. Auf rot und blau (wie im obigen Beispiel) gibt es noch gelb (yellow-dot.png), lila (purple-dot.png) und grün (green-dot.png).

Die Cachekoordinaten, welche an erster und zweiter Position in der Liste stehen, müssen in Dezimalgrad (also z.B. 50.123456) angegeben werden und nicht in der beim Geocaching sonst üblichen Darstellung Grad mit Dezimalminuten (also z.B. 50° 12.345).

Die Umrechnung ist ganz einfach, auch ohne zusätzliche Tools (welche online aber reichlich vorhanden sind).
Zum Umrechnen nimmt man einfach die Dezimalminuten, teilt die Zahl durch 60. Das Ergebnis sind dann die Nachkommastellen für die Darstellung in Dezimalgrad.

Beispiel:
50° 21.345 wäre dann:
50 + 21.345/60 = 50 + 0,35575 = 50.35575

Wenn es sich beim Breitengrad im Süd-Koordinaten handelt und / oder beim Längengrad um West-Koordinaten, dann muss in der Dezimalgrad-Darstellung zusätzlich noch ein Minus-Zeichen davor (also wäre z.B. S 50°21.345 in Dezimalgrad -50.35575)

Somit steht einer eigenen Karte nichts mehr im Weg.

Sollten auf der Karte nach dem Aufruf die Marker fehlen, so ist in der Regel in der Liste der Caches ein Fehler. Dies könnte z.B. ein fehlendes Anführungszeichen oder ein fehlendes Komma sein.