Pen & Paper - Rollenspiel > Werkstatt
Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Talwyn:
Anforderungen an die Covella-Kalender-Bibliothek
Als Entwickler einer App, die dem Informationsmanagement beim Leiten und Vorbereiten von Pen & Paper Rollenspielen (insbesondere mit Schwerpunkt auf Hexploration und einer offenen Sandbox), benötige ich eine Bibliothek, die geeignete Klassen und Funktionen für die Darstellung eines fiktionalen Kalenders zur Verfügung stellt. Folgende Anforderungen müssen dabei grundsätzlich erfüllt sein:
COVELLA-1
Die Bibliothek darf nicht an ein bestimmtes Kalendersystem gebunden sein. Stattdessen muss sie in der Lage sein, beliebige fiktionale Kalender abzubilden. Beispiele wären z.B. die Kalender aus bekannten Kampagnensettings wie Aventurien, den Vergessenen Reichen, Greyhawk, Dark Sun, Golarion, Glorantha oder Barsaive.
COVELLA-2
Die Definition eines Kalendersystems sollte so einfach wie möglich sein, so dass auch Anwender ohne Programmierkenntnisse in der Lage sind mit Hilfe einer kurzen Anleitung, den Kalender ihrer bevorzugten Kampagnenwelt abzubilden. Hierfür bietet sich eine domänenspezifische Sprache (domain-specific language) an, die sich nach Möglichkeit an der natürlichen Sprache orientieren sollte. Diese DSL sollte zunächst die gängigsten Fälle abdecken und soweit möglich mit sensible defaults arbeiten, um unnötige Schreibarbeit zu vermeiden (z.B. sollte davon ausgegangen werden, das ein Tag - sofern explizit nicht anders spezifiziert - 24 Stunden zu je 60 Minuten zu je 60 Sekunden hat).
COVELLA-3
Wurde ein Kalendersystem definiert, so ist es möglich hierzu eine Kalender-Instanz zu erzeugen, indem man einen Startzeitpunkt definiert. In Pseudocode ausgedrückt könnte das in etwa so aussehen:
--- Code: ---myCalendar = new Calendar based on system "Calendar of Harptos" with start date "13th Marpenoth 1485 DR"
--- Ende Code ---
COVELLA-4
Das Kalenderobjekt stellt eine Funktion bereit, die es ermöglicht, den gegenwärtigen Zeitwert zu verändern, indem man eine Größe addiert oder subtrahiert. Beispiele:
--- Code: ---advance myCalendar by 3 days
advance myCalendar by 4 hours and 30 minutes
rewind myCalendar by 1 year
--- Ende Code ---
COVELLA-5
Die Bibliothek sollte zumindest die Formatierung eines Datums als Zeichenkette unterstützen, nach Möglichkeit auch das Erzeugen eines Kalenderobjekts aus einer Zeichenkette, die ein bestimmtes Format hat. Beispiele:
--- Code: ---myCalendar = {
system: 'Calendar of Harptos' ,
interntalValue: 189798297898L
}
textualRepresentation = myCalendar.format() // assuming standard format
assert that textualRepresentation equals "13th Marpenoth 1485 DR"
--- Ende Code ---
COVELLA-6
Das Kalenderobjekt stellt Funktionen zur Verfügung, um auf die einzelnen Komponenten des in ihm gespeicherten Zeit-Werts zugreifen zu können:
--- Code: ---assert that myCalendar.getYear equals 1485
assert that myCalendar.getDayOfMonth equals 13 // start counting at 1, nobody wants to count days of month starting at 0
assert that myCalendar.getMonth equals 10 // start counting at 1, nobody wants to count month number starting at 0
assert that myCalendar.getMonthName equals "Marpenoth"
assert that myCalendar.getMonthAlias("poetic1") equals "Leafall"
assert that myCalendar.getYearName equals "Year of the Iron Dwarf's Vengeance"
--- Ende Code ---
Das mal als erster Wurf. Muss man sicher noch verfeinern, aber das funktioniert erfahrungsgemäß besser, wenn man sich gegenseitig den Ball zuspielen kann.
1of3:
--- Zitat ---myCalendar = {
system: 'Calendar of Harptos' ,
interntalValue: 189798297898L
}
--- Ende Zitat ---
OK. Nach meinem Begriff ist das kein Kalender, sondern ein Datum. Der Kalender ist das System. Aber das ist Terminologie.
Ein Datum ist also eine Klasse mit einem Zeitstempel, den man an Hand eines assoziierten Kalendersystems manipulieren kann:
- Man kann den Zeitstempel in Text umwandeln.
- Man kann aus einem passenden String einen Zeitstempel parsen.
- Man kann einen neuen Zeitstempel finden, der auf Beschreibungen wie "drei Monate später" passt.
In letzterem Fall sollten wir aufpassen: Es gibt einen Unterschied zwischen drei Monate später und drei Stunden später. Letzteres manpuliert den Zeitstempel in vorhersagbarer Weise, der Monat kann dagegen ulkige Sachen machen, also mal 30, mal 31 und mal 28 Tage später. Wir sollten hier darauf achten, zwei unterschiedliche Methoden anzubieten und die eine darf für Monat, Jahr oder sonstige verschieden lange Zeiteinheiten nicht funktionieren.
Parsen aus einem String ist grundsätzlich kein Problem. Schön wäre es natürlich, wenn man aus der Definition der formatierten Ausgabe auch gleich die passenden Informationen zum Parsing generiert. Aber ich hab ne Idee, wie das gehen könnte.
Ich würde noch ein Kriterium hinzufügen:
Covella-7
Es sollte möglich sein zu Teilintervallen zu navigieren. Also etwa zum dritten Montag im elften Monat.
--- Code: ---year therein month 11 therein third monday
--- Ende Code ---
Dann wird das Parsing auch direkt einfacher.
Aber ansonsten gehen wir völlig d'accord.
Talwyn:
Ja du hast Recht, das was ich hier als Kalender bezeichne ist ein Datum. Richtiger wäre:
--- Code: ---calendar = new Calendar("Calendar of Harptos")
myDate = calendar.getDate("13th Marpenoth 1485 DR")
// oder
myDate = calendar.getDate(1485, 10, 13)
--- Ende Code ---
1of3:
OK. Eine Frage bleibt dann noch:
--- Code: ---myDate.[b]getYear[/b] equals 1485
--- Ende Code ---
Wenn man jetzt ein Datum nach so einer Information, wie seinem Jahr fragt, was für ein Objekt erhält man dann?
Ich schlage vor:
- Das returnierte Objekt ist ein Interval.
- Intervalle haben je einen Zeitstempel, wo sie anfangen, und einen, wo sie aufhören.
- Intervalle können wohlbezeichnete Teilintervalle liefern.
Wenn man speziell nach einem Monat oder einem Jahr fragt, haben wir noch ein bisschen mehr, denn dieses Intervall entspricht auch einer bekannten Zeiteinheit. Diese Art von Interval...
- hat einen Bezeichner, also z.B. Woche, Monat.
- kann herausfinden, wievielte so bezeichnete Zeitintervall es in einem anderen wohlbezeichneten Zeitintervall ist, also z.B.
--- Code: ---november indexIn year // returns 10, weil Zählung fängt bei 0 an
--- Ende Code ---
- falls diese Art von Intervallen Namen hat, kann man sie natürlich nach ihrem Namen fragen
--- Code: ---myDate.getMonthName
--- Ende Code ---
Ist dann also identisch zu:
--- Code: ---myDate.getMonth.name ...
--- Ende Code ---
Talwyn:
Das Intervall ist sicher auch oft ein hilfreiches Konstrukt, ich würde das nur nicht mit dem Datum vermischen. Wenn ich ein Datum nach seinem Jahr frage, dann meine ich die Jahreszahl, denn das Datum selbst repräsentiert ja einen ganz bestimmten Punkt innerhalb des Intervalls, welches das Jahr natürlich in einem anderen Kontext.
Ein Zeitintervall wäre aus meiner Sicht hingegen eine eigene Klasse, die andere Funktionen bereitstellt. Convenience-Methoden zur Erzeugung eines Zeitintervalls auf Basis einer Jahreszahl sind aber natürlich nützlich:
--- Code: ---interval yearOfTheIronDwarfsVengeance = calendar getInterval for year 1485 // ==> [1485-01-01T00:00:00, 1486-01-01T00:00:00[
// oder aber:
interval yearOfTheIronDwarfsVengeance = myDate getInterval for unit year // ==> Same as above
--- Ende Code ---
Ich denke bei sowas immer auch an die Verwendung eines APIs im Sinne einer Schnittstelle. Selbige sollte einfach und intuitiv zu verwenden sein und auf den üblichen Use Case hin ausgelegt. Die interne Repräsentation der Daten darf ja gerne eine präzise Modellierung der Anwendungsdomäne sein, aber die Schnittstelle sollte einfach den Bedarf des Benutzers abdecken.
Navigation
[0] Themen-Index
[#] Nächste Seite
[*] Vorherige Sete
Zur normalen Ansicht wechseln