Donnerstag, 7. November 2013

Fehlersuche und Codeanalyse mittels _cartrigde.lua

Voraussetzung: "Der Einstieg in lua“

Abbildung 1: Bei der Zonendefinition wird der Identifier des Steinbruchs mit kleinem s angelegt
In diesem Tutorial wollen wir uns mit Fehlersuche bzw. Codeanalyse beschäftigen. Genauer gesagt geht es darum sich anzuschauen welcher lua Code aus dem Urwigo Projekt generiert wird.
Dies kann uns in zweierlei Hinsicht nützlich sein.
  • Erweitern der lua-Kenntnisse sowie Analyse der Wherigo-API
  • Fehlersuche
Zunächst beschäftigen wir uns mit dem zweiten Punkt: Das Scenario ist folgendes:
Wir haben eine Zone Steinbruch definiert, die wir im Lua user functions Bereich ansprechen wollen bzw. der Aktivitätsstatus wir dort verändern möchten.
Abb. 1 zeigt das Anlegen der Zone. Erfahrene Wherigo-Entwickler werden auf den ersten Blick feststellen, dass wir neben Namen und Bild auch den Identifier festgelegt haben.

Abbildung 2: Im lua Teil wird das Objekt fälschlicherweise mit großem S angesprochen
Im Lua user functions Bereich nehmen wir unseren Steinbruch und setzen die Aktivät auf true.
Wer erkennt hier schon unseren Fehler? Kleiner Tipp: Bei diesem Code würde das Projekt gar nicht erst starten. Würden wir die Anweisung in einer Funktion verwenden, die erst während dem Spiel ausgeführt wird, z.B onStart würde die Fehlermeldung folgendermaßen lauten:
Lua method call failed. .../urwigo-src-23fd04e4-6177-45ca-a89a-2ffc8589ff08.lua:323: attempt to index global 'Steinbruch' (a nil value)

Abbildung 3: Wichitg für die Lesbarkeit im Testmodus ist Verschlüsselung sowie die Verschleierung der Identifier und Texte zu deaktivieren
Die Ursache der Fehlermeldung ist schnell erklärt: Während der Identifier in Abb.1 auf steinbruch mit kleinem s gesetzt wurde wird im lua Part versucht die Zone mit großem S anzusprechen.
Da der Code case-sensitive ausgewertet wird ist Groß- und Kleinschreibung wichtig. Schließlich befinden wir uns ja nicht im Windows-DOS-Modus.

Diesen Fehler erkennt man beim zweiten Mal sehr zügig. Was aber, wenn wir noch nicht so erfahren sind? Hier kann ein Blick in die lua Datei helfen, die von Urwigo aus dem Projekt erzeugt wird und neben den Bildern als zip Datei (oder besser gesagt als gwz Datei) zum wherigo.com Server hochgeladen wird.
Wir wollen also einen Blick in die generierte lua Datei werfen. Dazu ist es wichtig, dass wir wie in Abb.3 erkennbar ist, die Verschleierung und Verschlüsselung der Texte, Antworten und vorallem der Identifiers aufheben. Die Identifiers dürfen auf keinen Fall verscheiert werden, wenn wir eigenen lua Code schreiben. Die ersten beiden Kästchen dienen der besseren Lesbarkeit während der Testphase, sollten vor dem Hochladen zu wherigo.com aber wieder gesetzt werden.
(Nicht dass es euch so wie mir geht und ihr ein paar Minuten nach der Veröffentlichung des neuesten Wherigos eine eMail bekommt in der euch ein Cachingkollege mit breitestem Grinsen alle Antworten und Spoilerbild zuschickt, weil ihr vergessen habt die Verschlüsselung zu aktivieren...)

Abbildung 4: Das Bauen des package ist nicht neues und kennen wir schon als Vorbereitung für's Hochladen
Jetzt könnt ihr euch kurz entspannt zurücklehen, denn der Teil mit dem Erstellen eines Packets sollte euch wohlbekannt sein.
Für den weiteren Vorgang nehmen wir an, wir haben die gwz Datei ExtractLua.gwz genannt und in dem Ordner "C:\tmp\ExtractLua" abgespeichert.

Abbildung 5: Beispiel für das Entpacken der gwz-Datei mit 7zip
Um die lua Datei aus der gwz Archivdatei zu extrahieren, bedienen wir uns eines Zip-Programmes unserer Wahl. WinZip, WinRar sollten selbsterklärend sein. Ich habe 7zip verwendet, da es sich hierbei um ein kostenlos nutzbares Tool handelt, dass allen Ansprüchen der Extrahierung gerecht wird. Wenn man den Schritt "Packet bauen - auspacken - Lua Datei anschauen" mehrmals wiederholt (nach der Behebung des ersten Fehlers wartet der zweite) empfiehlt es sich den Extraktionsbefehl über die Kommandozeile abzusetzen, da er dort recht leicht wiederholt werden kann (z.B Pfeil aufwärts in der Konsole). Der Parameter e steht für Auspacken, während der Schalter y für das Überschreiben vorhandener Dateien steht. Deswegen sollte man die gwz Datei außerhalb des Projektordners auspacken.

Abbildung 6: In der von Urwigo erstellten lua Datei kann man gut sehen, woran der Fehler liegt: Groß- und Kleinschreibung des Identifiers stimmen nicht überein
Wie ihr eure gwz Datei entpackt ist aber euch überlassen. Wichtig ist, dass am Ende eine _cartridge.lua Datei herauskommt, die ihr dann mit einem Texteditor öffnen könnt. Ich habe dies mit dem vim Editor gemacht, da mir dann ein farbliches Syntax-Highlighting sicher ist. Wer bereits mit dem IntellijIDEA arbeitet (siehe Lua im externen Editor bearbeiten) kann natürlich sich dort die Datei anschauen.

Nun aber zur Fehleranalyse. In Abb. 6 erkennt ihr an dem oberen bzw. unteren roten Kreis, dass die Identifier sich in Groß- und Kleinschreibung unterscheiden und ihr habt den Fehler somit gefunden.

Ich hatte zu Beginn des Tutorial einen weiteren Nutzen der Codeanalyse angesprochen. Dies wird durch Betrachtung des mittleren roten Kreises deutlich:
Der Codeteil function objExtractLuaTest:OnStart() end enthält nämlich alle Codeanweisung, die beim Starten des Wherigo ausgeführt werden. Ich seht auch wie der Identifier des Cartridges gebildet wird, wenn er nicht von euch vorgegeben wird: Mit einem simplen Prefix obj der vor den Namen gesetzt wird.
Anstatt die Startanweisungen als lua Block aufwändig über Urwigo einzugeben, könnt ich auch einfach in euerer lua Datei diesen Codeteil verwenden.
Auf diese Weise hab ich mir nach und nach angeschaut, wir Textausgaben (MessageBoxen), Benutzeneingaben (Input), Timer, Zonen und Gegenstände verwendet werden, sodass ich heute nur noch die Objekte in Urwigo definiere (UUID-Erzeugung ist zwar möglich aber recht aufwändig) und alles andere direkt in lua schreibe, was sich bei aufwändigeren WherIGos wie Minesweeper, Cachopoly, Schiffe versenken... als wesentlich schneller herausgestellt hat und ihr habt die Codeanweisungen zentral in einer (später mehreren) Lua Dateien und könnt so euren Code besser nachvollziehen.

Samstag, 17. August 2013

IPhone Player Update erfolgreich

Wie ich mittlerweile von mehreren Feedbacks mitbekommen habe ist das aktuelle 1.4.2 Version des PiGo Player soweit daß auch kompliziertere  Wherigos wie Scotland Yard oder Minesweeper zu spielen sind. Also Update einspielen und los geht's. Um weitere Rückmeldungen bin ich immer noch dankbar

Sonntag, 28. Juli 2013

Buggy und T5er

Jaja kaum ist das Kind anderthalb kann es schon Buggyverschüsse öffnen. Aber da hat es die Rechnung ohne T5er Papa gemacht

Freitag, 26. Juli 2013

Minesweeper überall als PlayAnywhere spielen


Abbildung 1: Wenn du zu weit entfernt von vordefinierten Spielfeldern bist, kannst du dein Feld selbst aufziehen. Markiere ObenLinks ...
Minesweeper ist mit der Version 2.0 nun auch als PlayAnywhere verfügbar.

Dabei kommt ein neuartiges Lokalisierungverfahren zum Einsatz:

Beim Start des Spieles prüft das Gerät selbstständig ob es sich im 1-km-Radius zu einem vordefinerten Spielfeld (z. Zt Koblenz/Ehrenbreitstein - Emsland und Holland sind in Planung) befindet und wählt dieses automatisch aus.

Ist kein passendes Spielfeld in der Nähe, wird automatisch auf PlayAnywhere-Modus umgeschaltet und der Spieler wird zur Definition der Ecken LinksOben sowie RechtsUnten aufgefordert. Am Ende erhält er wie gewohnt Zahlen für die Buchstaben A, B, C und D, die er in die Formel im Geocaching.com Listing eintragen kann um die Tupperdose zu besuchen.

Abbildung 2: ... und danach UntenRechts und schon bist du fertig und kannst loslegen.

Minesweeper auch in deiner Stadt?

Du wohnst ein wenig entfernt von Koblenz und möchtest Minesweeper auch in deiner Caching-Homezone anbieten?
Schreib mir einfach ne Nachricht und ich kann ein vordefiniertes Spielfeld auch für deinen Ort eintragen, bzw. dir bei der PlayAnywhere-Formel helfen.

Donnerstag, 25. Juli 2013

Endlich dynamische Wherigos auf dem iPhone? Update für Apfel-Player PiGo erschienen

Es gibt ein neues Update für den PiGo Player. Und es gibt damit neue Hoffnung auf komplexere Wherigos wie Cachopoly, Schiffe versenken, Scotland Yard, Siedler oder Minesweeper


Abbildung 1: Die Auflistung von Cachopoly in den Beispiel-Wherigos auf der iTunes Seite lässt hoffen, dass nun auch dynamische Wherigos mit PiGo spielbar sind.
Wie auf der iTunes Seite verkündet ist das 1.4 Update für PiGo verfügbar und hat allerei Bugfixes dabei.
1) Various minor updates.
2) Improved audio playback.
3) Added active zones as possible command targets.
4) Allow selection of universal commands with no targets.
5) Consider active zones for command text.
6) All input/views allow timers, etc. to run normally.
7) Updated map display.
8) Reversed angle for: Wherigo.VectorToPoint
9) Changed action tracking for items.
10) Added geocache search!
11) Fixed restore of boolean values. Thanks Knut!
    


Besonders gespannt bin ich auf die Überarbeitung der Timer sowie die VectorToPoint Anpassung. Letzteres könnte die Ursache dafür sein, dass Minesweeper beim Project-Eck-Event nicht für Apfeljünger spielbar war.
Es gibt also Hoffnung. Da ich selbst (überaus zufrieden) auf der Android-Welle surfe, bin ich auf euer Feedback angewiesen und gespannt.

Schreibt eure Erfahrungen ruhig als Antwort zu diesenm Post

Dienstag, 18. Juni 2013

GSAK-Macros: Buttons und Online Index

Voraussetzung: Der Einstieg in die GSAK Macro Welt

Einen Button für das Macro definieren


Abbildung 1: Wie heißt mein Button, welchen Text und Beschreibung soll er erhalten und wo ist das zugehörige Macro?
Damit wir den großen Batzen an Macrowissen aus dem Macro Einstiegstutorial besser verdauen können, wird es heute etwas übersichtlicher. Wir wollen lediglich bestehende Macros mit Buttons versehen und diese in er Speedbar (oberhalb der Cacheübersicht, da wo schon "Datei öffnen", "Drucken" usw definiert sind) anordnen.
Wir beginnen mit Macro->Button Configuration und wählen im ersten Feld einen noch unbelegten Button, z.B 7 - M7. Im nächsten Feld geben wir den zugehörigen Text ein. Dieser sollte nicht zu lange sein, damit er in die standardmäßig definierten 28 x 28 Pixel passt. (Alternativ kann man unten links die Breite raufsetzen, wenn der Button breiter werden soll). Für unseren "Init" Text reichen 28 Pixel aber aus. Button Description and Hint bezeichnet den Text der erscheint, wenn man mit der Maus über dem Button ein paar Sekunden verweilt und kann dazu genutzt werden eine genauere Beschreibung einzublenden.
Das wichtigste Feld ist der Macro file name in dem man den Pfad zum geschriebenen oder heruntergeladenen Macro (siehe unten) eintragen bzw. auswählen kann.
Ganz nützlich ist auch die Vorschau unten rechts im Abschnitt Toolbar sample wo ihr euch direkt ansehen könnt, ob der Text nicht zu lang für die Breite ist.

Abbildung 2: Um die Speedbar anzupassen, einfach den Button auswählen (eigene Buttons sind unter Macros) und per Drag&Drop auf die Speedbar ziehen.
Ist der Button erst einmal definiert, gilt es ihn noch auf die Speedbar zu ziehen. Dazu öffnen wir Macro->Add Button to Tool Bar wählen unter Macros (dort sind die 20 selbst definierbaren Buttons zu finden) unseren Init-Button aus und ziehen ihn per Drag'n'Drop auf unsere Speedbar an die gewünschte Stelle und ...
sind schon fertig. So einfach geht das.
Um einen Button wieder zu entfernen ziehen wir ihn einfach von der Speedbar aus nach unten, bis er außerhalb der Speedbar ist und quasi verschwindet. Maustaste loslassen und unser Button ist zwar nicht Geschichte, aber nicht mehr auf der Speedbar sichtbar.
So sammeln sich je nach Intensität und Funktionen mit denen man GSAK nutzt mehr und mehr Buttons / Macroshortcuts in der Speedbar an. Zum Glück ist dort ne Menge Platz.

Abbildung 3: Je intensiver man GSAK nutzt, desto größer wird die Button-Anzahl in der Speedbar.

Macro Online Index

Es muss aber nicht immer ein selbstgeschriebenes Macro sein. Geht man auf Macro->Run/Manage->Online Macro Index oder direkt auf http://gsak.net/board/MacroIndex.php so hat man Zugang zu einer riesigen Bibliothek an Macros für jeden Zweck. Gebt das passende Schlagwort (z.B Project81 für ein Macro, das euch die Caches raussucht, deren D/T Wertung euch noch für die Matrix fehlt) und klickt auf den blauen Macronamen.

Abbildung 4: Im Online Index existiert bereits eine Flut von fertigen Macros die viel nützliche Funktionen bereit stellen
Die darauf folgende Seite ist wie ein Forum aufgebaut und ihr könnt die (Weiter-)Entwicklung des Macros studieren. Zum Download des Macros geht ihr zum letzten Eintrag und ladet so die aktuellste Version des Macros hinunter. Bei der Frage, was der Browser mit dem Macro machen soll, wählt ihr "Öffnen mit GSAK" und anschließend Install the macro.
Wenn euch das Macro gefällt könnt ihr wieder nen Button definieren und ihn auf die Toolbar schieben. Oder das Macro in euren Programmablauf einbauen, so wie wir das mit dem MoveFound-Macro im Init-Macro vollzogen haben.

Montag, 17. Juni 2013

Minesweeper ist online !!!

Keine zwei Wochen mehr bis zum Event der Events. Heute schonmal der erste (kleine) Paukenschlag: Um FTF-Stress während des Events zu vermeiden und um Erfahrungen mit dem neuen Minesweeper-WherIGo im freien Feld zu erhalten, wurde heute die Minensuchversion fürs GPSr freigeschaltet.
Unter GC4B061 kann man ab sofort hoch oben auf der Festung Ehrenbreitstein Minen suchen, markieren, graben und hoffen dass man nicht in die Luft fliegt. Natürlich alles im Secure-Mode mit Reset-Funktion. Wir wollen ja nicht, dass jemand ernsthaft zu schaden kommt.
Das Cartrigde erhaltet ihr über das GC-Listing oder direkt von der Wherigo-Seite.
Also Cartrigde runterladen, Listing ausdrucken (enthält Anleitung), ab ins Auto und auf geht's. Ein jungfräuliches Logbuch wartet schon auf euch.

Einführung in die GSAK Macro Welt

Voraussetzung: Pocket Queries importieren
Nachdem die letzen Tutorials sich mit PQs und deren Nutzung in GSAK beschäftigten, geht es dieses Mal mehr um GSAK selbst.
Ich möchte heute auf eine ganz entscheidene Komponente aufmerksam machen, die Verwendung von Macros. Mit diesen steht euch ein mächtiges Tool zur Verfügung um die tägliche Arbeit mit dem Programm zu vereinfachen und zu automatisieren.
Wir wollen zum Einstieg in die Macrowelt ein solches schreiben, dass in unserer Datenbank nach gefundenden bzw. eigenen Caches sucht und diese in eine eigene Datenbank verschiebt, damit wir in unserer default Datenbank nur noch Caches halten, die wir suchen wollen.
Dazu legen wir zunächst zwei Datenbanken mit dem Namen foundDB und ownDB an, indem wir auf Database-->New klicken und den gewüschten Namen eintragen.

Abbildung 1: Unser erster eigener Filter ist nicht zu kompliziert und beinhaltet als einzige Einschränkung uns selbst als Owner

Danach begeben wir uns an die Definition der Filter. Für unsere Funde stellt uns GSAK bereits einen Filter My Found Caches (GSAK Default) bereit, für unsere selbst gelegten Caches müssen wir allerdings ein klein bischen Arbeit investieren.
Nach einem Klick auf Search->Filter (alternativ Strg + F) erscheint das Fenster aus Abb.1. Da wir uns nicht auf bestimmte Cachearten oder andere Filterkritieren einschränken wollen müssen wir lediglich in der Zeile Placed by unseren Nickname eintragen und den Filter unter dem Namen My Own Caches abspeichern. (Auch hier ist der Name eigentlich Schall und Rauch, sollte aber im Hinterkopf behalten werden, da wir ihn später im Macro benötigen).
Mit einem Klick auf Save können wir die Speicheraktion einleiten.

Abbildung 2: Um die Verschiebung der Caches zu steuern legen wir eine Moveaktion an.
Die Filter sind vorbereitet, als nächstes geht es ums Verschieben. In GSAK muss man dafür im Move/Copy Dialog (erreichbar unter Database->Move/Copy Waypoints) angeben, wohin verschoben werden soll (je nach MoveAction foundDB bzw. ownDB), ob die Werte verschoben oder kopiert werden sollen und wie mit Werten umgegangen werden soll, die bereits in der Zieldatenbank vorhanden bzw. nicht vorhanden sind. Wir wollen aus der alten Datenbank verschieben, mit Einfügen bzw. Ersetzen in der neuen Datenbank. Den gesamten Dialog speichern wir als MoveAction Move to foundDB ab um es später im Macro verwenden zu können.
Damit unser Wissen auch lang hält, dürft ihr jetzt als Übung eine MoveAction definieren, die alle eigenen Caches in die passende Datenbank verschiebt. Die benötigte Datenbank sowie Filter haben wir weiter oben bereits vorbereitet.

Abbildung 3: In unserem ersten Macro verschieben wir alle Found in die foundDB und alle eigenen Cache nach ownDB
Die Vorbereitungen sind abgeschlossen, nun geht es endlich zum Macro an sich. Über Macro->Edit/Create gelangen wir zu einem Dialog wie in Abb. 3 zu sehen ist. (Genaugenommen bin ich über Macro->Run/Manage gegangen, da mein Macro bereits existierte. Da ihr es neu anlegen müsst, ist die Create Methode eure Wahl.
Die ersten Zeilen sind geprägt mit Infos über das Macro. Wer ist der Autor, wie heißt es und wichtig, falls ihr es im öffentlich Macro-GSAK-Verzeichnis einstellen wollt: Beschreibung und Version des Macros.
Alles was mit einem # beginnt ist Kommentarzeile und wird beim Abspielen des Macros nicht beachtet. So richtig los geht es erst in Zeile 8 mit der Anweisung FILTER.
Über das Attribute Name wählt ihr den vordefinierten Filter aus, der auf die akutell geöffnete Datenbank -sollte default sein-gesetzt werden soll.
Danach prüft das Macro ob es Caches gibt, für die diese Filterkriterien zutreffen. Auf deutsch: "Hab ich gerade gefundene Caches in meiner Datenbank".
Dies ist nach Zeile 10 definitiv nicht mehr so, denn hier wird mittels MOVECOPY mit den vordefinierten Einstellungen Move to foundDB alles verschoben, was der Filter hergibt.
Der Befehl ENDIF ist notwendig, falls ihr für die Caches aus dem Filter mehrere Kommandos ausführen wollt. Alles zwischen IF und ENDIF wird ausgeführt, wenn die Bedingung $_FilterCount > 0 zutrifft. $_FilterCount ist eine vordefinierte Variable von GSAK die beim Setzen eines Filters mit der Anzahl der Zeilen gefüllt wird, für die der Filter zutrifft. Um sicher zu stellen, dass ihr die weiteren Befehle nicht auf der foundDB sondern auf der Default Datenbank ausführt, setzt ihr die aktive Datenbank wieder auf Default. Es gab Versionen von GSAK, da wurde nach dem MOVECOPY die Zieldatenbank als aktive Datenbank gesetzt. Heute ist das nicht mehr so, aber sicher ist sicher und man sieht auch wie man eine Datenbank geziehlt auswählt.
Die letzten fünf Zeilen wiederholen eigenlich nur die ersten fünf, außer dass statt der gefundenen nun die eigenen gefiltert und verschoben werden.

Abbildung 4: Unser Init-Macro sollen die PQs herunterladen, gefunden und eigene Caches verschieben und abgelaufene Event entfernen.
Zum Abschluss des Tutorials erweitern wir das Aufgabengebiet unseres Macros auf alles was beim Start von GSAK durchgeführt werden soll:
  • Lade die aktuellen PQs
  • Verschiebe gefundene und eigene Caches
  • Entferne Event, die bereits stattgefunden haben
'Moment', wird sich der aufmerksame Leser von Pocket Queries importieren denken, 'bei der Definition der PQs haben doch die gefundenen sowie eigenen Caches ausgeschlossen'.
Dies ist soweit richig. In späteren Tutorials sehen wir, wie sich GSAK hervorragend zur Statistikgenerierung eignet. Dafür ist es aber notwendig alle gefundenen Caches in einer Datenbank zu pflegen. Aus diesem Grunde lasse ich alle paar Tage eine myFinds-PQ mitlaufen, die mir die gefundenen Caches im 50 km zuschickt. Details folgen in der versprochenen Fortsetzung.
Eigene Cache landen zwar immer noch recht selten in der Default Datenbanken (höchstens durch einmalige PQs die zwischendurch geniert werden bzw durch Einzelimport per GPX file-Button auf der GC-Seite) aber der Filter und die MoveAction diesbezüglich frisst kein bzw. nicht viel Brot und stört insofern nicht weiter. Sicher ist sicher, gell.

Nun aber zum Macro, als allererstes selektieren wir die Default-DB und führen mittels GcGetPg das Abrufen und Verarbeiten der PQs aus. Hier muss darauf geachtet werden das richtige Settings zu nehmen. Damit es zum letzten Tutorial passt, müsst ihr MyPQDLSettings statt PQDLMW nehmen.
Da wir das Verschieben der Funde a) als eigenes Macro belassen möchten (um diesen Schritt alleine ausführen zu können), b) aber die Anweisungen nicht wiederholen möchten (Codeduplikation ist für den Entwickler immer ein rotes Tuch) nutzen wir die Möglichkeit das jedes Macro Untermacros ausführen kann. Mit Macro unter der Angabe des Dateinahmens führen wir so in unserem Init-Macro einfach das MoveFounds Macro aus. Beide Datei müssen dafür im selben Macroverzeichnis sein, aber das schlägt euch GSAK beim Abspeichern schon korrekt vor.

Nach dem Motto, das Beste kommt zum Schluss nutzen wir in den letzen Zeilen den MFilter. Mit diesem Tool kann man OnTheFly Filter definieren, die a) nicht gespeichert werden müssen und b) nicht die Cache-Ansicht verändern. Will heißen MFilter betrifft nur die Auswahl der Caches im Macro. Sobald das Macro endet wird der Wert verworfen, während FILTER die Auswahl der in GSAK angezeigten Caches manipuliert. Im Where Attribute von MFilter führen wir SQL-ähnlich eine Einschränkung auf den Cachetyp (Event, Z für Megaevent und CITO) sowie das Plazierungsdatum was bei Events dem Tag des Events entspricht. date('now') ist eine GSAK-, bzw. sqlite-interne Funktion um das Tagesdatum zu ermitteln.
Auch hier wird wieder kontrolliert, ob überhaupt abgelaufene Events vorhanden sind und gegebenenfalls mit macrodelete action=delscope (löscht alle selektierten Caches) und macrodelete action=commit (schreibt die zunächst lokale Änderung auf die sqlite-Datenbank durch) entfernt. Hier sieht man auch warum IF mit ENDIF abgeschossen werden muss, da zwei Zeilen von der Bedingung betroffen sind.
Dies soll für heute reichen. Beim nächsten Mal wird es etwas einfacher. Da kümmern wir uns um den Klicki-Bunti-Teil "Wie definiere ich für mein Macro nen hübschen Button?"

Freitag, 14. Juni 2013

Pocket Queries in GSAK importieren

Voraussetzung: Daily Pocket Queries erstellen
In den ersten beiden PQ Tutorials wurde erklärt wie man ne PQ bzw. eine Reihe von regelmäßigen PQs erstellt. Heute geht es darum wie GSAK mit diesen PQs seine lokale Datenbank aktuell hält.

Abbildung 1: GSAK kann Pocket Queries über die Geocaching.com api herunterladen und verarbeiten.
Der Download der PQs ist relativ einfach zu handeln. Ihr klickt einfach auf Geocaching.com access und anschließend auf Download PocketQueries. Im darauffolgenden Fenster (siehe Abb. 1) werden alle verfügbaren PQs angezeigt, die ihr einzeln auswählen könntet. Im unteren Teil könnt ihr festlegen, wo die PQs abgelegt werden sollen und dass sie nach dem Download verarbeitet werden. Typischerweise werden sie in die vordefinierte Datenbank default importiert.

Abbildung 2: Normalerweise möchte man jede PQ nur einmal herunterladen
Jetzt wäre es bei einem Daily-Update ja eher suboptimal jedes Mal zu prüfen welche PQ bereits geladen wurde und welche noch zu markieren ist. Deswegen fühlen wir uns als fortgeschrittener User und lassen die Maustaste beim Reiter Advanced interagieren.
Wenn unser Bildschirm Abb. 2 ähnelt, wählen wir Download all Pocket Queries not yet downloaded und speichern die Einstellung der Download Pocket Queries Funktion als MyPQDLSettings ab. Der Name darf frei gewählt werden, ihr solltet ihn euch aber gut merken, in späteren Tutorials werden wir den Download-Schritt mittels Macros weiter automatisieren.

Abbildung 3: Der Download läuft. Zeit um sich zurückzulehnen oder den nächsten Mysterie zu lösen
Danach heißt es für ein paar Sekunden / Minuten sich zurückzulehen und abzuwarten, denn nun beginnt GSAK die PQs herunterzuladen und anschließend mit den bereits bestehenden Caches in der Datenbank zu mergen. D.h. neue werden hinzugefügt, bestehende werden aktualisert, falls sie nicht von euch als gesperrt markiert wurden (RMT auf Cache -> Edit -> Checkbox lock auswählen.)
Je nach Internetgeschwindigkeit (oder gerade zuschlagener Telekom-Drossel) könnt ihr auch die nächste Cachetour planen oder WherIBlog durchstöbern.

Abbildung 4: Nach der Verarbeitung der PQs erfolgt eine ausführliche Zusammenfassung der Ereignisse
Ist der Download und die Verarbeitung beendet, erhaltet ihr eine Übersicht der geladenen Waypoints, der aktualiserten Cache, der gelöschten Caches und vieles mehr. Am interessantesten bei dieser Ansicht ist die Tabelle Waypoints in each file .
Hier könnt ihr schnell kontrollieren, ob in euren PQs noch Platz ist, oder ob die 1000er Marke erreicht sind. Wie man in Abb. 4 erkennen kann sieht es noch ganz entspannt aus, lediglich im Zeitraum von September 2010 bis August 2011 könnte es vorkommen, dass die am weitesten entfernten Caches nicht mehr erfasst werden, wenn in den nächsten zwei Tagen die Cacheraktivität steigt und damit die Anzahl der in den letzten 7 Tagen aktualiserten Caches aus diesem Zeitraum über die Millegrenze steigt.
Was sehr positiv zu bewerten ist, ist die Tatsache, dass in der w27er Query noch genügend Platz ist. Diese PQ wird nämlich jeden Tag wachsen, da wir ja erst Juni 2013 haben und die PQ alle zukünftigen Caches bis zum November erfassen wird. Sollte der Wert hier die 1000 erreichen, sollte man darüber nachdenken eine w28 einzuführen.

Mittwoch, 12. Juni 2013

Pocket Queries für's tägliche Update

Voraussetzung: Der Einstieg in die Pocket Queries

Im Einsteigertutorial wurde beschrieben wie man eine einmalige PQ für Caches rund um einen Ort definiert.
Jetzt geht es darum mit GSAK eine möglichst aktuelle lokale Datenbank zu pflegen um sich eine eigenen Cacheauswahl aufs GPSr zu laden.

Geocaching.com API und tägliche PQ als erste Ansätze

Wozu der Aufwand mit PQs wird sich so manch einer denken, ich hab doch die Geocaching.com API und kann mir die Caches von GSAK aus direkt laden. Das stimmt, aber bei nem Limit von 6000 Caches pro Monat kommt man da auch nicht weit.

Abbildung 1: Die Daily-PQ soll jeden Montag, Mittwoch und Freitag laufen.
Der nächste Ansatz ist, sich jeden Tag eine PQ mit den Caches rund um seine Home-Location schicken zu lassen. Eigentlich keine schlechte Idee, es sei denn, man schaut mal, wie weit man damit kommt. Die meisten werden den 10 km Radius nicht überschreiten. D.h. wenn ich nicht im Nachbarort sondern einen Ort weiter unterwegs sein möchte, ist meine lokale Datenbank schon außerhalb ihrer Reichweite.

Was kann ich tun, um meinen Radius zu vergrößern


Daher stelle ich hier drei Optimierungsmöglichkeiten vor, um unseren Radius auszudehnen. Ich komme so auf eine lokale Datenbank, die Caches bis zu 50 Kilometer entfernt erfasst. Das sind meistens zw. 60 und 80 km Fahrstrecke und sollte als Home-Zone ausreichen. Alles darüber hinaus ist besser mit Spezial-PQs wie im Einsteiger-Tutorial beschrieben zu lösen.

Abbildung 2: Es reicht vollkommen aus, wenn ich nur die Änderungen der letzten 7 Tage mitbekomme.
Als erste Optimierung lasse ich mir nur die noch nicht gefundenen, nicht die eigenen und nur die Caches raussuchen, die in den letzten 7 Tagen ein Update (neuer Logeintrag, Listing oder Koors geändert) erfahren haben. Ausgehend von einer einmalig initialisierten Datenbank reicht es ja nur die Änderungen mitzubekommen.
Um den Initialzustand zu erhalten kann ich auf die 6000 Caches aus der API setzen oder mir ne Woche lang jeden Tag 5 PQ zuschicken, die alle aktiven Caches enthalten.
Außerdem werden die meisten Caches in den Sommermonaten mind. einmal im Monat angegangen, sodass ich recht schnell ne ziemlich komplette Datenbank haben. Was nicht dabei ist, ist meistens so schwierig, dass es eher unwahrscheinlich ist, dass ich einen solchen Cache spontan angehe.

Abbildung 3: Neben Home Location und Reduzierung des Radius kann man gut über das Datum der Cacheauslegung mehrere PQs trennen.
Aber auch das ist noch viel zu viel, da im Sommer die meisten Caches innerhalb der letzten 7 Tagen angegangen werden.
Als zweite Optimierung müssen wir eine Möglichkeit finden, nicht eine sondern 4 PQs pro Tag zu erhalten (1 PQ sollte man sich immer für Notfälle oder Spontansuchen übrig halten). Da stellt sich die Frage, wie kann man die Caches voneinander trennen, also in Gruppen bzw. Packete aufteilen. Die Entfernung von zu Hause ist keine Möglichkeit, da immer die nähesten genommen werden. Eine PQ mit Tradies, eine mit Multis u.s.w. ist zwar nen Ansatz aber kein guter, da es mehr als 4 Cachetypen gibt und der Radius für die Tradis wesentlich kleiner ist als für Multis oder gar WherIGos.
Was sich dagegen hervorragend anbietet, ist die Unterscheidung nach Plazierungsdatum, also wann wurde der Cache gelegt. Vereinfach gesagt, eine PQ für die ganz alten Dosen bis 2009, eine für 2010 und 2011, eine für 2012 und die vierte für das aktuelle Jahr. Dabei werdet ihr feststellen, dass für die aktuellen Monate immer schwieriger wird, die 1000er Marke nicht zu knacken, besonders da jeden Tag der Zeitraum größer wird. Dafür verschinden aber immer mehr Dosen aus den "alten Zeiten", da ihr sie entweder gefunden habt oder sie archiviert werden, da Versteck "verbrannt" ist, Naturschützer und Behörden aufmerksam geworden sind oder die Owner nicht mehr die Zeit für die Dosenpflege aufbringen wollen. Es lohnt sich also ab und zu zu konrollieren wie viele Caches im Schnitt durch ein PQ erfasst werden und die Zeiträume zu verschieben. Dann heißt es 2000-2010, 2011-Juni2012, Juli2012-Feb2013, März2013-Dez2013.

Abbildung 4: Da in den letzten 2 Jahren die Cacheanzahl explodiert ist, muss der Zeitraum umso kleiner gewählt werden, je näher er am Tagesdatum liegt. Auch reichen 4 PQs nicht mehr aus. Deswegen alle zwei Tage jeweils 4 ergibt 8 PQs.
Je nach Radius den ihr abdecken wollt, reichen aber auch 4 PQs nicht mehr aus. Ich bin deswegen zur Tradeoff gelangt, dass es reicht jeden zweiten Tag eine aktuelle Datenbank zu besitzen. Wie in Abb. 4 erkennbar ist, wird Montags, Mittwoch und Freitags die Caches Begin bis 01. Juni 2011 erfasst und Dienstags, Donnerstags und Samstags alle Caches ab 02. Juni 2011 bis heute.
Eine Codierung der Suchzeiten im PQNamen hilft ungemein, die Zeitfenster zu koordinieren. In der ersten Runde hab ich noch ein PQ frei. Sobald w27_021212-011113 die 1000er Marke regelmäßig knackt wird w24... zu w14... (d.h. Montags ausgeführt) und eine neue PQ w28_020713-010114erstellt. Wenn dann Ende des Jahres auch die achte PQ gefüllt ist, geht der Tanz von vorne los. Da muss ich entweder einen dritten Tag einführen (also mit 2 Tage alten Cachedaten leben) oder den Radius reduzieren. Der entspricht bei mir z.Zt 50 km, was verdammt viel ist, da die Fahrstrecke im Schnitt das 1,4 bis 1,5 fache der Luftlinie, also gut 70 km entspricht.
 Oder ich schreib weniger Tutorials und "bereinige" die PQ-Zone von den alten Caches .

Damit endet der zweite Teil der PQ-Einführung. Wir haben dieses Mal gelernt, wie man PQs so definieren und teilen kann, dass sie sich dazu eigenen eine lokale Datenbank wie z.B GSAK mit regelmäßigen Updates zu versorgen. Im nächsten Teil geht es darum, wie man die erzeugten PQs in GSAK importiert und was man damit machne kann.

Dienstag, 11. Juni 2013

Der Einstieg in die Pocket Queries

Ausnahmsweise geht es mal nicht um Wherigos sondern dieses Mal um Pocket Queries und (in den nächsten Tagen folgend) um GSAK und die Nutzung von Pocket Queries in GSAK. Vorneweg sei gesagt, dass das Feature der Pocket Queries (nachfolgend PQs genannt) nur den Premium Members zur Verfügung steht. Aber wer sich ein bischen mehr mit Geocaching beschäftig (und schonmal weiß das es nicht "Kätsching" heißt), der kommt schnell an den Punkt an dem er bereit ist 30 € im Jahr für sein Hobby zu zahlen. Da ich kein Freund von schlechten Übersetzungen bin, habe ich die Spracheinstellung meines GC-Profil auf englisch gelassen (ja, es gab mal eine Zeit, da war Geokätisch nicht Trendsportart Nr 1 und die Webseite wurde nur auf englisch betrieben). Es sollte aber keine allzu große Transferleistung sein, das Szenario mit deutscher Spracheinstellung nachzuspielen.

Was ist ein PQ?

Eine Pocket Query ist das Ergebnis einer Suchanfrage, mit der wir von geocaching.com die Daten mehrere Caches auf einmal erhalten. Technisch gesehen handelt es sich um eine GPX-Datei, was wiederum ein Datenformat zur Speicherung von Geodaten (GPS-Daten) auf Basis des XML-Standart ist. Wir erhalten die PQ, verpackt in einem zip Container als eMail, können sie vom geocaching.com Server herunterladen oder über die Geocaching.com API in Programme wie GSAK importieren.

Was mache ich mit einer PQ?

Es gibt zwei bedeutende Anwendungsscenarien für PQs:
  • Entpacken und als GPX aufs GPSr laden (z.B beim Garmin Oregon in \Garmin\GPX)
  • In GSAK importieren und somit eine lokale Datenbank aufbauen aus der heraus man Cache nach bestimmten Kriterien auswählen und aufs GPSr exportieren kann
Da es sich hier um ein erweitertes GSAK Turorial handelt, bevorzuge ich natürlich die zweite Variante. Ziel ist es einen möglichst aktuellen Zustand der potentiellen Cachegegenden zu haben um auf die Schnelle die 1000 Caches dabei zu haben, die man evtl. beim Wochenendausflug angehen möchte.

Wie erstelle ich eine PQ?


Abbildung 1: Wie heißt meine PQ, wann soll sie generiert werden und welche Cachetypen sind erlaubt?
Als Einstieg hab ich mir folgendes einfaches Scenario überlegt: Ich möchte gerne 1000 Caches rund um Freiburg haben. Es sollen Caches sein, die ich aktuell suchen kann, also weder inaktive noch Dosen, die von mir sind oder die ich bereits besucht habe.
Dazu gehen wir auf die PQ-Übersicht http://www.geocaching.com/pocket/default.aspx und wählen dort "Create a new Query". Anschließend kommen wir zur Konfigurationsübersicht wie in Abb. 1 zu sehen. Neben einem möglichst sprechenden Namen geben wir ein, dass wir die PQ einmal generieren, sie aber für spätere erneute Verwendung behalten und dem zu Folge nicht löschen möchten.
Außerdem setzen wir das Maximallimit von 500 auf 1000 Caches rauf und schließen keinen Cachetyp aus. ( Man könnte hier auch nur Tradies und Multis auswählen, aber solche Spielereien sind jedem selbst überlassen.)

Abbildung 2: Auch Cachegröße, gefundene, eigene und deaktiverte Dosen oder Dosen die mir zu schwer oder zu hoch im Baum sind lassen sich herausfiltern
Ebenso wie bei den Cachetypen wollen wir keine Cachegrößen ausschließen. Es wäre aber auch möglich nur nach den ganz großen Large Dose zu suchen.
Wo wir allerdings einschränkend aktiv werden ist die nächste Passage. So haben wir weder an bereits gefundenen noch an eigenen Caches Interesse. Auch deaktivierte Caches lassen wir links liegen.
Und was ist mit archivierten Caches? Die werden nie in PQs mitgeliefert. Für unseren Fall ganz praktisch. In späteren Tutorial werden wir aber sehen, dass das auch so seine Tücken hat.
Weitere Einschränkungen nehmen wir jetzt noch nicht vor. Im nächsten Tutorial wird die Sache hier aber schon ganz anders aussehen.
Auch bei Schwierigkeit und Terrain lassen wir die Auswahl offen. Freunde der Klettercaches könnten natürlich hier mit >= 5 oder vllt besser noch >= 4,5 die Auswahl verfeinern.
Nur noch angedeutet könnten wir in der Within Box ganze Länder bzw. Regionen / Bundesländer herausfiltern. Aber Vorsicht, mehr als 1000 Dosen gibt eine PQ nie heraus. Die Auswahl dürfte so in den wenigsten Fällen vollständig sein, wenn es nicht gerade Lichtenstein oder Vatikan sein soll.

Abbildung 3: Ganz wichtig ist der Mittelpunkt unserer Suche
Wo wir wieder aktiv werden, ist der From Origin Part der Konfiguration. Hier gibt es neben der Homezone (vorausgesetzt ihr habt eure Home Location ordentlich gepflegt) auch die Möglichkeit rund um eine gemessene Koordinate zu suchen. Da wir unser Schwarzwald-Urlaub-Quartier in Freiburg beziehen möchten, wählen wir die Koors dieser Stadt. Man kann auch nen GC-Code eines Caches angeben, dann werden dessen Koors als Mittelpunkt der Suche herangezogen.
Beim Radius hab ich die Suche auf dem Maximum von 100 Milen gelassen. Diese Obergrenze macht aber nur Sinn, wenn ich wesentlich kleinere Werte eintrage. 1000 Caches findet man heute oft im 20-30 km Radius. Aber 100 ist OK, wir wollen uns ja eigentlich gar nicht auf den Radius einschränken und bei der Suche werden die ersten 1000 Dosen, gemessen vom Mittelpunkt herangezogen.
Wann die Dose gelegt wurde ist uns (diese Mal genauso egal wie die Attribute die sie hat. Eltern mit kinderwagenkompatiblen Kindern können hier aber genauso einschränkend aktiv werden wie Taucher die nur Unterwassendosen suchen möchten. Da der Schwachpunkt bei der Filterung nach Attributen jedoch die Pflege eben dieser durch den Cacheowner darstellt, ist auch hier Vorsicht bei der Einschränkung geboten.

Abbildung 4: Die generierte Pocket Query würde uns per eMail zugeschickt, wenn da nicht die Einschränkung auf die 500 Caches wäre.
Den Abschluss der Konfigurationsmöglichkeiten bildet der eMail-Versand. Hier kann man der gewünschte eMail-Empfänger eingetragen werden, die Komprimierung ins Zip Format sollte man immer aktiv schalten um den Datentraffic nicht unnötig zu erhöhen. Der Name der PQ als FileName des Zips ist auch ne praktische Sache.
Einen Hacken hat die eMail-Verschickerei allerdings. Sie funktioniert nur bei PQs bis 500 Caches. Sind mehr in der PQ enthalten, so muss man die Datei händisch downloaden. Dies ist auch über die Hauptseite unter dem Reiter Pocket Queries Ready For Download möglich. Gilt auch für bereits per eMail verschickte PQs.

In diesem Tutorial haben wir gelernt wie man eine einfache PQ mit zu suchenden Caches rund um einen Ort erstellen. In der nächsten Ausgabe schauen wir, wie wir GSAK mit DailyUpdates versorgen können.

Freitag, 7. Juni 2013

Minesweeper beim Project-Eck kurz vor der Veröffentlichung

Es sind noch gut drei Wochen bis es endlich los geht und Project-Eck seine Tore öffnet. Unter anderem wird auch der neue Minesweeper-Wherigo verfügbar sein. Die Finaldose ist bereits versteckt und es laufen die letzten Beta-Tests.

Abbildung 1: So in etwas wird es aussehen, wenn du vor der Entscheidung deines Lebens stehst: Risikiere ich zu graben oder versuche ich es lieber nebenan?
Das Spiel orientiert sich dabei an der Windows-Version, die wir schon seit vielen Jahren kennen: Laufe über das Spielfeld und entscheide für jedes Minenfeld, ob du graben möchtest oder doch lieber das Feld als Mine markierst.

Abbildung 2: Puh, nochmals Glück gehabt, oder war es gut kalkuliert?. Nach dem Graben auf einem Feld weiß man ob die Rechnung aufgegangen ist oder ob man sich verrechnet hat
Hat man sich zum Graben durchgerungen, dauert es nicht lange bis man über Erfolg oder Desaster informiert wird. Hab ich richtig gerechnet? Wenn ja, dann wirst du mit weiteren Informationen belohnt, die dir hoffentlich helfen werden weitere Minen auszumachen. Manchmal hilft auch einfach nur raten.

Abbildung 3: Die Rechnung geht aber nicht immer auf. Aber keine Angst. Wenn du ne Mine erwischt hast beginnt das Spiel von vorne und es heißt wieder: "Neues Spiel, neues Glück"
Strapaziere deine Glück aber nicht zu sehr. Beim ersten Fehlgriff war es das mit deiner Baggerkarriere und du fliegst samt deinem Grubengrabgerät in die Luft. Aber im Gegensatz zur Realität geht es klimplich aus und du kannst sofort wieder von vorne starten. Obwohl: So wenig ist es schon schade, dass man dem WIG-Player keine Vibrationskommandos mitgeben kann, ähnlich nem Gamepad-Kontroller.

Abbildung 4: Ganz so viele Minen wird es nicht geben, aber ein Kinderspiel ist es trotzdem nicht.
Es sind nicht mehr viele Male die ihr noch schlafen müsst ehe das Christkind kommt, äh ich meine bis zum Event der Events. Bis dahin könnt ihr ja am PC fleißig üben, um vor Ort beim Graben gewappnet zu sein.

Donnerstag, 6. Juni 2013

Wherigo ohne Zonen

Voraussetzung: "Der Einstieg in lua“
Im heutigen Tutorial geht es darum einen Wherigo ohne Zonen zu programmieren. Dies kann hilfreich sein, wenn die benötigte WIG-Lösung viele Zonen bräuchte bzw. die Zonen nicht sichtbar sein sollen.
Die kann bei einem schachbrettartigen Spielfeld sinnvoll sein, z.B ein Memory-Spiel oder dem beim Projekt-Eck verfügbaren Minesweeper-Spiel. Ansonsten hätte wir selbst bei einem 4x4 Memory 16 aktive Felder. Mit dem Oregon undenkbar.

Ermittlung der aktuellen "Zone"


Abbildung 1: Bei der Ermittlung wo der Spieler gerade steht wird über alle Felder iteriert
Das Zauberwort heißt hier (mal wieder) Player.ObjectLocation. Damit kann festgestellt werden, wo sich der Spieler gerade befindet. Danach wird "lediglich" über alle vorher definierten Felder (z.B das Feld A2 auf unserem Schachbrett, Definition folgt weiter unten im Tutorial) iteriert und geprüft, ob der Abstand zum Feld einen definierten Mindestabstand distance entspricht. Dieses Attribut haben wir global festgelegt, z.B distance = 5 (Meter).

Abbildung 2: Die Klasse Field enthält alle benötigten Werte: Name, Index und vorallem die Location
Ein Feld wird dabei durch die Klasse Field definiert. Sie enthält neben Namen und Index(sinnvoll für Verwendung von Arrays) die Eigenschaft Location, die aus der GPS-Koordinate des Mittelpunktes besteht. Freunde des OnProximity Event (siehe Zone als Kreis) kennen diese Logik bereits. Der Radius der virtuellen Zone wird durch die obige Variable distance definiert.
Sobald das erste Feld diese Bedingung erfüllt (distance sollte passend zum Abstand zwischen den Feldern so gewählt sein, dass immer nur 1 Feld nahe genug ist), speichern wir es als activeField und führen die Aktionen aus, die wir normalerweise im onEnter oder onProximity definieren. Im Listing wird dazu die Methode handleField aufgerufen, die dann die gewünschten Anweisungen enthält.
Außerdem wird die Variable foundField auf true gesetzt und der Schleifendurchlauf mit break abgebrochen, denn schließlich haben wir unser aktives Feld ja gefunden. Wenn alle Felder durchlaufen sind, aber kein Feld gefunden wurde, so befindet sich der Spieler außerhalb des Spielfeldes (zur Sicherheit nochmals mit Spielfeld:Contains(Player) abgsichert, könnte auch weggelassen werden) so wird das activeField auf fieldOutside(definiert als Feld mit Namen "outside" und Index -1) gesetzt und eine MessageBox ausgegeben, dass man sich doch gefälligst wieder zurück zum Spielfeld begeben sollte. Diesen Teil habe ich in einer Methode out ausgelagert.
Spielfeld habe ich als wirkliche Zone definitert, damit der Spieler sich über den gewohnten Navigationpfeil leiten lassen kann um das Spiel zu beginnen / wieder aufzunehmen. Ganz ohne Zonen geht es also nicht, wenn man die Usabiltiy nicht außer Acht lassen möchte.

Nebenläufige Programmierung und ihre Tücken

Was aber sollen die Vergleich von activeField in Zeile 47 und 54?
Um das zu verstehen muss man wissen, dass die Methode calcActiveField regelmäßig angestoßen werden muss, da sich der Spieler dreisterweise bewegen möchte. Ein Timer mit Interval 1-5 Sekunden (je größer die Felder desto seltener, nicht zu oft, damit das Oregon mitkommt) bietet sich hier an.
Wenn wir die obigen Vergleiche nicht einbauen, wird die handleField Routine alle 5 Sekunden ausgeführt, was bei nem stattfindenen Dialog sehr unangenehm ist und dazu führt, dass der Spieler die gestellte Aufgabe womöglich nie durchführen kann. Also lieber handleField nur einmal ausführen und dann erst wieder wenn der Spieler das Feld wechselt. Das gleiche gilt für den Fall, dass er sich außerhalb des Spielfeldes verlaufen hat. Auch da reicht es wenn die MessageBox nur einmal angezeigt wird.
Bei sehr großer Anzahl von Felder kann es zu der Situation kommen, dass der aktuelle Schleifendurchlauf noch läuft, während der Timer schon wieder das Signal gibt den nächsten Durchlauf zu starten. Um Fehler oder Wechselwirkungen bei dieser Art der parallelen Abläufe zu verhindern bildet die boolean Variable runningActiveFieldCalculation, als Mutex-Variable eingesetzt, einen Schutz gegen gleichzeitiges Ausführen mehrerer Schleifendurchläufe. Vereinfacht gesagt: So lange ein Iterier-über-alle-Felder-Durchlauf läuft besitzt die Variable den Wert true und weist damit weitere Versuche ab. (! Ich rede bewußt von Abweisen, nicht von Blockieren). Erst wenn der kritische Programmteil abgarbeitet ist wird er mit runningActiveFieldCalculation = false wieder freigegeben.

Wann endet das Spiel?

Die ersten drei Zeilen steuern die Beendigung des Spieles. So soll die Methode endGame() aufgerufen werden, wenn das Spiel als beendet markiert wurde, die notwendige Benachrichtigung an der Spieler ("Gewonnen, gehe zum Final bei N 50° ....") noch nicht vollzogen ist. Die beiden boolean Variablen werden irgendwo in handleField gesetzt, z.B wenn alle Memory-Paare aufgedeckt sind. Zeile 32-35 sind aber nicht zwingend notwendig für die Implementierung des Wherigos ohne Zonen.
Am Ende des Listing beginnt die Implementierung von handleField. Besonders bei Schachbrett-Spielfeldern ist es für den Spieler sehr hilfreich gesagt zu bekommen, wo er sich befindet.
Bei der weiteren Abarbeitung des Feld bitte nicht vergessen ob die Siegbedingung (s.o.) erfüllt ist und das Spiel beendet werden kann.

Spielfeld definieren

Ich hoffe ihr habt noch ein wenig Saft im Aufmerksamkeitstank, denn jetzt wird es richtig knifflig.
Was haben wir?
Wir haben zwei Koordinaten für die Eckpunkte unseres Spielfeldes (ObenLinks und UntenRechts)
Was wollen wir berechnen?
Ein schachbrettartiges Spielfeld mit rows Zeilen und columns Spalten, z.B 3 x 5 Felder. Siehe Abb. 5 als Beispiel
Wie machen wir das
Vereinfacht gesagt ermitteln wir Breite und Höhe des Spielfeldes, teilen diese durch die Anzal der Spalten bzw. Zeilen und iterieren über alle Felder (bei 3 x 5 => 15 Felder) und setzen den Mittelpunkt des Feldes. Zum Schluss setzen wir noch die Ecken ObenLinks, ObenRechts, UntenLinks und UntenRechts als Points der wirklichen Zone Spielfeld und schalten es aktiv und sichtbar.

Abbildung 3: Ausgehend von den Ecken ObenLinks sowie UntenRechts wird das Spielfeld ermittelt

Nun im Detail von oben nach unten, beginnend mit den Zeilen 452 und 453. Dort werden die beiden gegenüberliegenden Eckpunkte unserer Rechteckes definiert. Mit Wherigo.VectorToPoint ermitteln wird den Abstand d sowie den Winkelb zwischen den beiden Punkten. Dies ist ähnlich dem Peilen von einer Koordianten zur anderen mittels Entfernung und Winkel. Ein Winkel b von 135° bedeutet, dass man von firstLoc schräg nach rechts unten gehen muss um zu lastLoc zu gelangen.
Die Variable dist hält den Abstand in Meter fest. Zeile 456 ermittelt den Anteil der Distanz in X-Richtung (also auf der genordeten Karte nach rechts). Wie wir an math.sqrt erkennen, kommt hier der Pythagoras-Klassiker a² + b² = c² zum Einsatz. Wer die Berechnung von distX verstanden hat, wird auch mit distY sowie degX und degY zurechtkommen. Die Modulo-Rechnung mit 360 soll verhindern, dass unser Peilwinkel größer als 360° wird.
Wer es genau wissen möchte, dem kann folgende Debug Zeile helfen:
print("b " .. b .. " dist " .. dist .. " distX ".. distX .. " distY " .. distY .." degX " .. degX .. " degY " .. degY)
In der Kurzversion wird zwischen 456 und 459 die Höhe und Breite sowie der Peilwinkel ermittelt um ein Rechteck aufzuziehen, dessen Verhältnis Höhe / Breite dem Verhältnis Zeilen / Spalten entspricht. Abb. 4 und 5 zeigen zwei Beispiele wie das resultierende Spielfeld aussehen kann. ObenLinks und UntenRechts sind auf beiden Abbildungen gleich, nämlich N 50.3691166666667 E 7.6164 bzw. N 50.3680333333333 E 7.61715.

Abbildung 4: Das Spielfeld mit 5 Zeilen und 3 Spalten ist höher als breit ...

Abbildung 5: während 3 Zeilen und 5 Spalten eher breit als hoch ist

Danach wird die Ecke ObenLinks aka firstLoc als Start der Zeile gesetzt. Dies entspricht in unserem Schachbrett A1. (Bitte entschuldigt den Unterschied zum realen Schachbrett, ich habe gerade erst gesehen, dass dort Zeile 1 die unterste Zeile ist. Bei mir ist es die oberste).
Ist der Rest der Division durch die Anzahl der Spalten 1 (tritt in unserem 3 x 5 Beispiel Abb. 5 bei 1, 6 und 11 auf) so wandert unsere Position nach unten, da wir eine neue Zeile starten. "Nach unten" ist aber nicht genau senkrecht (das wären 180°), sondern abhängig vom Peilwinkel den das Rechteck haben soll (im Beispiel SüdSüdWest bzw. 191,43°). Zur Erinnerung Wherigo.TranslatePoint berechnet den Punkt der von firstLoc aus distY Meter in Richtung degY geht. Vektorrechnung für Anfänger.
math.floor macht übrigens nichts anderes als das Ergenis des Bruches abzurunden, damit 0, 1 bzw. 2 herauskommt. (In der ersten Zeile müssen wir noch nicht nach unten verschieben)

Wenn wir nicht gerade das erste Element einer Zeile antreffen, so müssen wir vom Zeilenanfang nach rechts gehen. Genauer genommen in Richtung degX (OstSüdOst oder 101.43°, merkwürdigerweise genau 90° weniger als degY ). Auch hier gehen wir abhängig von der Spalte in der wir uns befinden 1/4, 2/4, 3/4, 4/4 nach rechts um unsere Position neu zu berechnen.

Zum Abschluss noch etwas entspanntes, um das Tutorial sanft ausklingen zu lassen. Um unsere Zone Spielfeld zu erzeugen setzen wir die Ecken ObenLinks, ObenRechts, UntenRechts und UntenLinks als Points, machen sie sichtbar und aktiv.
Die ganz aufmerksamen unter euch werden jetzt zurecht sagen: Moment, das Spielfeld ist kleiner als die Fläche die von den Feldern abgedeckt wird, denn die Eckpunkte von Spielfeld sind die Mittelpunkte der Eckkreise. Dies ist korrekt, aber Spielfeld dient lediglich dazu den Spieler zurück zur Spielfläche zu führen, wenn der diese früher erreicht als vom GPSr angezeigt so ist dies nicht wirklich schlimm, sollte aber bei der Messung der beiden Ecken ObenLinks und UntenRechts beachtet werden.
Vielen Dank an dieser Stelle an bodenseepingu, der mir seinen Quellcode von Geomemory zur Verfügung stellte und so die nötigen Denkanstöße gab ein Feld mit zwei gegenüberliegenden Eckpunkten aufzuziehen.

Freitag, 19. April 2013

Dein WheriGo in Hamburg, München, Köln, Berlin ....

Voraussetzung: "Der Einstieg in lua“
Was passiert, wenn man einen Wherigo veröffentlich hat, der gut ankommt? Richtig auf kurz oder lang kommen die Anfragen "Tolle Sache, können wir den in Leipzig, München, Hamburg, Berlin .... auch veröffentlichen?"
Wenn der Wherigo keine Ortmerkmale verlangt ist dies ja auch kein Problem. Vorallem wenn man ein Spielfeld braucht, das man an beliebiger Stelle spielen kann.
Möchte man aber keinen PlayAnywhere daraus bauen, bzw. dem Spieler das lästige und oft nicht verstandene Abstecken des Spielfeldes ersparen, so kann man mehrere Locations vordefinieren und dem Spieler eine MultipeChoice-Box vorlegen (die aber bei vielen Anfragen schon mal sehr lang ist und mit viel Scrollen verbunden ist)
Doch muss das sein? Wäre es nicht viel angenehmer, das Cartrigde entscheidet selbst wo gespielt werden soll? Wenn ich bei N 50° 56.000, E 6° 57.000 stehe macht es wenig Sinn die norddeutsche Version zu wählen. Nein einzig "Köln" ist die Option, die für mich Sinn macht.

Abbildung 1: Definition der möglichen Locations und Auswahl der nähesten

Wie soll aber das Cartrigde entscheiden welches die richtige Version ist? Natürlich über die Abstände zu den Spielfeldern. Dabei definiert man die möglichen Orte als Array wie in Zeile 227 - 229 zu sehen ist.
In diesem Beispiel geht es um ein rechteckiges Spielfeld bei dem ObenLinks und UntenRechts als Koordinaten definiert sind. Wie man daraus ein Rechteck berechnet seht ihr im nächsten Teil. (Wird die Tage folgen)
Zur Abstandsberechnung nehmen wir die Ecke ObenLinks.

Danach misst man mit Player.ObjectLocation seinen eigenen Standort. Der Rest ist ein ganz normaler Min/Max-Algorithmus:
  • Schaue für jede Location ob sie näher ist als das bisherige Minimum. (Oder ob es noch kein Minimum gab)
  • Wenn dem so ist, setze die Entfernung zur Location als neues Minimum und merke dir den Index. (Die Entfernung brauchen wir für den nächsten Vergleich und den Index als Pointer auf die Location)
Nach der Schleife über alle Locations greifen wir mit dem Index auf die näheste zu und setzten den die beiden Punkte für unser Rechteck.

Freitag, 29. März 2013

Der (Fast-)Mytery "STAUSCHAU"

Eigentlich sollte es ein neuer Mystery werden, aber leider erlauben die (bei mir immer beliebteren :-( ) Guidelines keinen Links auf externe Seiten.
Bevor die stundenlange Arbeit gänzlich umsonst war, möchte ich Euch lieber hier im Blog mit dem Spaß beglücken ein wenig Stauverursacher zu spielen.
Da es keine Dose gibt, kann ich euch zusätzlich zum Spaßfaktor nur mit Erwähnung der drei Plätze hier im Blog ködern. Sobald ihr die Buchstaben A-H durch Experimentieren herausgefunden habt schickt sie mir per eMail. Bitte NICHT als Kommentar posten, wir wollen doch niemanden den Rätselspaß verderben.
STAUSCHAU


Abbildung 1: Noch ist alles im grünen Bereich. Muss wohl außerhalb des Berufverkehrs sein.
Beim Studieren meines Autoclub-Magazins wurde ich auf eine sehr interessante Website aufmerksam. Auf
http://traffic-simulation.de
gibt es die Möglichkeit verschiedene Stauszenarien zu simulieren. Was anfänglich als "Na ja" aussah entpuppte sich schnell zum Suchtfaktor, so dass ich die Seite erst nach Stunden wieder verlassen konnte.
Da kam auch die Idee an diesem Spaß andere teilhaben zu lassen. Um diesen Rätselcache zu lösen, musst du mehrere Szenarien simulieren um die Antworten zu erhalten. Die Aufgaben sind extra so gestellt, dass auch bei mehrmaligen Versuchen eine eindeutige Lösung herauskommt. Solltest du dennoch Probleme haben und zwischen 2 Möglichkeiten schwanken so schick mir ne eMail und ich helfe dir gerne weiter. Bevor es zu den Aufgaben gibt noch zwei Tipps
  • Zur Zeitmessung bzw. zur punktgenauen Änderung der Parameter empfiehlt es sich die Simulationsgeschwindigkeit auf 1-fach herunter zu drehen.
  • Erhöhe die Parameter langsam, wenn z.B das Ergebnis auf 50 genau sein soll, empfiehlt es sich in 10er Schritten die Messwert zu verändern.

Abbildung 2: Kurz vor dem Kollaps: Zuviel Verkehr für zu wenig Straße. Willkommen in der Realität.

Nun aber zur ersten Aufgabe. 25 KFZs, davon 20 % LKWs fahren im Kreis. Die restlichen Parameter auf der Seite bleiben auf den voreingestellten Werten. Nach einiger Zeit entsteht zwangsmäßig der Stau und man kann beobachten, wie er sich rückwärts, also mit dem Uhrzeigersinn bewegt.
A bezeichnet die Zeit in Minuten, die er braucht um eine Runde rückwärts zu vollziehen. Die Antwort soll dabei auf 2 Minuten gerundet sein, also 2, 4, 6, 8, 10, 12 oder 14 Min usw.

B: Nun reduzieren wir die Anzahl der Autos auf 15 und die LWWs auf 1,5 (kleine Transferaufgabe). Wie lange braucht der Stau für die Runde rückwärts nun? Wieder in Zweiminutenschritten.

Kommen wir zum nächsten Scenario, der Zufahrt von Autos auf eine zweispurige Straße.

Die Einstellparameter bleiben auf den Standardwerten von 2800 KFZs pro Stunde auf der Hauptstraße, 400 KFZs, die auffahren und einem zwanzigprozentigen LKW-Anteil. C: Messe die Zeit, bis der Stau auf der Zufahrtsstraße, die Stelle erreicht, wo sich die Zufahrtstraße mit dem Haupt-Zufluss verbindet. Führe die Messung mehrere Male durch um den Mittelwert zu bestimmen und runde wieder auf 2 Minuten.

Stelle den Hauptfluss auf 1000 KFZ, davon 200 LKWs, den Zufluss auf 100 KFZ und starte das Scenarion neu. Ab wie viel Autos Zufluss staut es sich auf der Auffahrt, d.h. die Schlange auf der Zufahrt wird immer länger. Führe den Versuch wieder mehrere Mal durch und runde das Ergebnis D auf 50 KFZ. (50, 100, 150, 200 ....)


Abbildung 3: So sieht es in der Realität meistens aus: Stau und kein Ende in Sicht
Schraube den Zufluss hoch auf das Maximum von 1800 KFZ und lassen den Stau anschwellen. Reduziere danach den Zufluss auf der Auffahrt langsam. Ab wie viel KFZ Zufluss E ist die Auffahrt wieder frei?
Lasse der Zufahrt nach jeder Änderung ausreichend Zeit und drehe langsam herunter. Das Ergebnis ist wieder auf 50 genau anzugeben.
Das ist ja wohl der Gipfel. Und vor dem Gipfel kommt die Steigung

Auch hier bleiben die Standardeinstellungen auf 2800 KFZ und 20% LKW.
Was ist bessere Tempolimit F, d.h. wann breitet sich der Rückstau am langsamsten aus? 40 km/h, 80 km/h, 120 km/h oder frei Fahrt für freie Bürger?

Wir reduzieren die Kfz auf 1800 pro Stunde und setzten das Tempolimit aus, d.h wir setzen es hoch auf 140 km/h.
G: Wie Prozent LKWs verkraftet die Straße noch ohne dass es Stau gibt? (in 10 % Schritten)


Abbildung 4: Und wenn gar nichts hilft, dann wird halt ne Baustelle eingerichtet
Die K*** ist am dampfen und der Stau ist da. (Stelle hierfür den Anteil der LKW auf 100 % und warte bis der Stau angewachsen ist)
Dann aber wird es Samstag Nacht, Geisterstunde, das Wochenendfahrverbot für LKWs greift (schiebe den Prozentregeler auf 0).
Wie löst sich der Stau auf, wenn die Anzahl der Kfz bei 1800 bleibt?
  • direkt? G = 3
  • gar nicht? G = 5
  • erst nach längerer Zeit? G = 1
A B C D E F G H
               
Zum Schluss noch ne Kontrollsumme: Alle Buchstaben zusammen sollten 1081 ergeben.