Tanelorn.net

Pen & Paper - Rollenspiel => Pen & Paper - Spielleiterthemen => Werkstatt => Thema gestartet von: 1of3 am 6.10.2016 | 17:37

Titel: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 6.10.2016 | 17:37
Zitat
Eine Herausforderung hierbei wird es sein, unterschiedliche (fiktive) Kalender zu unterstützen.

Das scheint mir jetzt gerade das einfachste an dem Unterfangen. Wenn du willst, helf ich da gern. Mit welcher Sprache willst du das genau machen? Ich vermute Java? (Mein Favorit ist Scala.)
Titel: Re: Re: Hexcrawl Weltenbau Support Tool - Brainstorming
Beitrag von: Talwyn am 6.10.2016 | 21:51
Für Android habe ich Scala noch nicht verwendet. Was ich mit Herausforderung bei den Kalendern meinte ist: Es sollte für Nicht-Programmierer möglich sein, auf relativ einfache Weise den Kalender ihrer Spielwelt so zu beschreiben, dass die App damit arbeiten kann.
Titel: Re: Re: Hexcrawl Weltenbau Support Tool - Brainstorming
Beitrag von: 1of3 am 7.10.2016 | 10:31
Verstehe. Dann schauen wir doch mal.

Ein Kalendersystem ist ein Objekt, das eine Liste von Tages-Zyklen enthält. Bei uns ist das der Jahreszyklus und der Wochenzyklus. (Wir können auch weitere Zyklen wie etwa den Mondzyklus oder die Jahreszeiten hinzunehmen.)

case class CalendarSystem (cycle : Days*)
Wir brauchen also Klassen für Mengen von Tagen. Diese Klassen sollten komponierbar sein und wieder Tage ergeben. Wir möchten zudem sicher wissen, wie viele Tage eine Instanz von Days enthält.

abstract class Days {
def number : Int}

case class SimpleDays(number: Int) extends Days{
def + (that: SimpleDays) = CompoundDays(List(this, that))
def + (those: CompoundDays) = CompoundDays(this + those.comps)
}

case class CompoundDays (comps : Seq[Days]) extends Days {
def number = comps map (_ number) sum
def + (that: SimpleDays) = CompoundDays(this.comps :+ that)
def + (those: CompoundDays) = CompoundDays(this.comps ++ those.comps)
}


Um das ganze brauchbar zu machen, müssen wir Tage mit einem Bezeichner ausstatten können, also z.B. Woche, Monat, Jahr. Zudem haben einige Days-Objekte Eigennamen, wie Mittwoch oder Januar. Um das ganze anschaulich zu machen, fügen wir passend benannte Setter hinzu.

Unsere abstrakte Klasse sieht nun so aus.

abstract class Days {
def number : Int
var designation: Option[String] = None
var name: Option[String] = None
def as(des : String) designation = Some(des)
def named(nam : String) name = Some(nam)
}


Für größere Konvenienz wählen wir zwei Factory-Funktionen für Tages-Objekte.
object Days{
def apply(number : Int) = SimpleDays(number)
def apply(names: String*) = names map (SimpleDays(1) named _) foldLeft(Days.empty,_+_)
}

Wir können einen Kalender nun so definieren.

val woche = Days("Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag") as "Woche"

val januar = Days 31 as "Monat" named "Januar"
val februar = Days 28 as "Monat" named "Februar"
val schaltFebruar = Days 29 as "Monat" named "Februar"
val maerz = Days 31 as "Monat" named "März"
val april = Days 30 as "Monat" named "April"
val mai = Days 31 as "Monat" named "Mai"
val juni = Days 30 as "Monat" named "Juni"
val juli = Days 31 as "Monat" named "Juli"
val august = Days 31 as "Monat" named "August"
val september = Days 30 as "Monat" named "September"
val oktober = Days 31 as "Monat" named "Oktober"
val november = Days 30 as "Monat" named "November"
val dezember = Days 31 as "Monat" named "Dezember"

val jahr = (januar + februar + maerz + april + mai + juni + juli + august + september + oktober + november + dezember) as "Jahr"

val schaltjahr =  (januar + schaltFebruar+ maerz + april + mai + juni + juli + august + september + oktober + november + dezember) as "Jahr"

julianisch = CalendarSystem (woche, jahr + jahr + jahr + schaltjahr)

Damit das System gültig ist, liefert der Konstruktor eine Fehlermeldung, wenn…


Mit einem Kalendersystem können wir aber noch nicht arbeiten. Wir brauchen mindestens ein Start-Datum, dass die Zykel synkronisiert. Wir müssen also für mindestens ein Jahr und einen Tag im Jahr wissen, welcher Wochentag das ist.

Wir brauchen also ein weiteres Objekt, nennen wir es Era. Nutzerfreundlich benutzen wir eine Factory-Funktion auf unserem CalendarSystem. Nennen wir sie startWith. Also in unserem Fall z.B.
val julianischerKalender = julianisch startWith ("Samstag", 1)
Ich nehme für die Funktion zunächst passende Überladungen an.

Nota bene: Der erste Januar im Jahre 1 war ein Samstag, jedenfalls wenn wir das ausrechnen. Die Planetenwoche war noch nicht sehr in Mode und die Zählung ab Christi Geburt noch nicht erfunden.

Es sollte vielleicht noch passende Funktionen geben, um ein Days-Objekt zu wiederholen. Ich hätte keine Lust den gregorianischen Kalender auf diese Weise zu schreiben. Natürlich kommen realiter Kalenderwechsel und Reformen vor. Davon würde ich absehen. That way lies madness.

Womöglich ist es aber gewünscht auch mit dem Jahr 1970 starten zu können, als mit einem Tag aus der ersten Jahresrunde. Da bräuchte es dann eine erweiterte startWith-Funktion. Das ließe sich vielleicht auch mit benannten Jahren, etwa im Stil vom Year of Blue Fire der Forgotten Realms oder den Konsulzählungen der Römer kombinieren.

Letztlich braucht es eine Klasse für bestimmte Daten mit passenden Gettern und Methoden wie next und previous.
Titel: Re: Re: Hexcrawl Weltenbau Support Tool - Brainstorming
Beitrag von: Antariuk am 7.10.2016 | 12:12
Ich verstehe von 1of3s Beitrag leider kaum etwas da ich 0,0 Programmierkenntnisse habe, aber wenn es um Kalendaerfunktionalitäten geht finde ich das Eberron Calendar Tool (https://www.wizards.com/dnd/ec/index.htm) von Wizards immer eine coole Vorlage um zu sehen, was man theoretisch machen könnte. Das Feature der Existenzebenen mit den waning/waxing/coterminous Zuständen könnten in anderen Settings auch Monde sein, wenn man das eine offen eintragbare Funktion macht.
Titel: Re: Re: Hexcrawl Weltenbau Support Tool - Brainstorming
Beitrag von: firstdeathmaker am 7.10.2016 | 12:46
Das Problem mit den Kalendern sehe ich auch eher darin, dass sie zwar in unserer realen Welt noch eingermaßen gut funktionieren (sieht man mal von den ganzen Ausnahmen ab), aber eben nur bedingt flexibel für sämtliche Fantasy-Settings funktionieren. Und ich will ein Fantasysetting vielleicht nicht nur nach äquitemporaler Zeit gelten lassen.

Ein wirklich umfassendes Kalendersystem für Fantasy, das man konfigurieren kann, sollte folgende Funktionen besitzen (nicht zwingend, aber um so mehr nach unten hin, um so flexibler wäre es):

Normaler heutiger benutzter Kalender
Kalender, die verschiedene Zeitalter und darin unterschiedliche Zeitrechnungen berücksichtigen. z.B. im ersten Zeitalter 8-Tage Wochen, 50-70 Tage Monate), im zweiten Zeitalter 5-Tage Wochen etc.
Lunare römische Kalender
Maya-Kalender
Weltenübergreifender Kalender (wie im oben geposteten Tool https://www.wizards.com/dnd/ec/index.htm) mit unterschiedlich schnell vergehender Zeit
Nichtlinearer Zeitfluss Kalender (für Zeitreisenszenarios mit alternativen Realitäten)
Nichtkonstanter Zeitfluss (Relativistischer Kalender für so etwas wie im Film "Interstellar")

Und da wird es halt extrem frickelig. Das Thema "Kalender" lasse ich bei meinem Tool bewusst aus. Dafür bräuchte man auch etwas mehr Dynamik als man mit HTML ohne weiteres realisieren kann.
Titel: Re: Re: Hexcrawl Weltenbau Support Tool - Brainstorming
Beitrag von: Talwyn am 7.10.2016 | 19:52
Sehr fleißig 1of3, das sieht schonmal super aus :). Ich würde es auch in einem vernünftigen Rahmen halten und Dinge wie Zeitreisen, Kalenderwechsel usw. ausschließen. Was man allerdings bräuchte, wäre eine Erweiterung, um Dinge wie Schaltjahre und Feiertage abbilden zu können am Beispiel des Calendar of Harptos (Forgotten Realms):

val tenday = Days 10 as "Tenday"

val hammer = Days 30 as "month" named "Hammer" aka "Deepwinter"
val midwinter = Days 1 as "holiday" named "Midwinter"
val alturiak = Days 30 as "month" named "Alturiak" aka "The Claw of Winter" or "The Claws of the Cold"
val ches = Days 30 as "month" named "Ches" aka "The Claw of Sunsets" with event "Spring Equinox" on 19
val tarsakh = Days 30 as "month" named "Tarsakh" aka "The Claw of Storms"
val greengrass = Days 1 as "holiday" named "Greengrass"
val mirtul = Days 30 as "month" named "Mirtul" aka "The Melting"
val kythorn = Days 30 as "month" named "Kythorn" aka "The Time of Flowers" with event "Summer Solstice" on 20
val flamerule = Days 30 as "month" named "Flamerule" aka "Summertide"
val midsummer = Days 1 as "holiday" named "Midsummer"
val shieldmeet = Days 1 as "holiday" named "Shieldmeet" occurring every 4 years startingAt 0
val eleasis = Days 30 as "month" named "Eleasis" aka "Highsun"
val eleint = Days 30 as "month" named "Eleint" aka "The Fading" with event "Autumn Equinox" on 21
val highharvesttide = Days 1 as "holiday" named "Highharvestide"
val marpenoth = Days 30 as "month" named "Marpenoth" aka "Leafall"
val uktar = Days 30 as "month" named "Uktar" aka "The Rotting"
val feastOfTheMoon = Days 1 as "holiday" named "Feast of the Moon"
val Nightal = Days 30 as "month" named "Nightal" aka "The Drawing Down" with event "Winter Solstice" on 20

val calendarOfHarptos = harptos // an dieser Stelle äußerst einfach, weil im Kalender des Harptos jedes Jahr immer mit einem frischen Zehntag beginnt.

Dementsprechend müsste man die Klassen erweitern, um diese Konstrukte abbilden zu können. Mal sehen, evtl. komme ich am Wochenende dazu was zu machen.
Titel: Re: Re: Hexcrawl Weltenbau Support Tool - Brainstorming
Beitrag von: 1of3 am 7.10.2016 | 20:26
Zitat
named "Alturiak" aka "The Claw of Winter"

Vielleicht einfacher: named ("Alturiak", "The Claw of Winter") Dann einfach ne Seq von Namen. Man kann natürlich aka als Alias verwenden, um Namen anzufügen.

Wie man schon jetzt Schaltjahre machen kann, hab ich ja beim julianischen Kalender gezeigt: Einfach verschiedene Jahre anlegen und addieren.

Eine Auszeichnung für besondere Ereignisse und Feiertage ist eine gute Idee. Schön wäre, wenn man relativ leicht verschiedene Zyklen schneiden kann, also im Stile von: Wenn ein Freitag der 13. eines Monats ist. Das ist bei ganz vielen Kulturen eine wichtige Methode für Tagesauszeichnungen.

Ich hab noch ein bisschen experimentiert. Ich würde noch erzwingen, dass Elemente eine Designation haben müssen, bevor man sie komponieren kann, also alles, was man addieren will muss vorher ein "as" bekommen. Dazu also gemäß Immutable Builder Pattern die Klasse ändern. Ich hab das noch mal gemacht und ein paar Bugs entfernt.

(Klicke zum Anzeigen/Verstecken)

Titel: Re: Re: Hexcrawl Weltenbau Support Tool - Brainstorming
Beitrag von: firstdeathmaker am 7.10.2016 | 21:53
Wie sähe das Kalendersystem eigentlich bei parallel laufenden Kalendern aus? Also z.B. wenn ich einen chinesischen und einen westlichen habe und ein Datum umrechnen möchte?

Wenn ich richtig gesehen hab, dann könnte man damit ja sogar Zeitalter realisieren und diese aneinander hängen. Aber was ist mit unterschiedlich schnell vergehenden Tagen? Z.b. Marstage und Erdtage?
Titel: Re: Re: Hexcrawl Weltenbau Support Tool - Brainstorming
Beitrag von: 1of3 am 7.10.2016 | 22:20
Ich hab für das Paket "Tag" als Referenzgröße gewählt. Unterschiedliche Tageslängen von Planeten sind so schwierig. Mehrere Kalender in ein System zu packen ist aber möglich.

Generell bräuchte es auf einem Datum eine Methode

def get(designator: String) = ???
Da kann man also problemlos get("Westliches Jahr") und get("Chinesisches Jahr"). Ich hadere momentan ein bisschen mit der Implementierung, aber das ist der Plan.


Edit: Ich muss den ersten Satz nach etwas nachdenken übrigens korrigieren. Nur weil ich die Objekte "Days" genannt habe und als "Standard-Tick" einen Tag im Kopf hatte, heißt das natürlich nicht, dass man nicht genauso gut von "Minutes" oder "Nanoseconds" ausgehen könnte. Ggf. möchte man dann ein Type-Alias ("type Minutes = Days") schreiben oder auch zwei, damit die Sachen nicht so merkwürdig heißen, aber die Funktionalität bleibt ja die selbe.


EditEdit: So. Getter funktioniert eingschränkt.
- Nicht bei negativen Daten oder Datum 0. Hier müsste man die Zyklen rückwärts durchlaufen.
- Nur beim primären Zyklus. Synchronisieren mit weiteren Zyklen geht noch nicht.
- Die Jahreszahl wird noch nicht angezeigt.

Hier einmal der vollständige Code bis jetzt.

(Klicke zum Anzeigen/Verstecken)
Titel: Re: Projekt FantasyCalender; war: Hexcrawl Weltenbau Support Tool
Beitrag von: 1of3 am 11.10.2016 | 08:17
So. Einige weitere Gedanken. firstdeathmakers Hinweis, auch kleinere Zeiteinheiten zu unterstützen ist gut. Ich hab die Klassen ein wenig umbenannt. Statt "Days" heißt es "Units" und die kleinste Einheit ist "Tick".

Spätestens damit ergeben sich für die Abwicklung verschiedene Konsequenzen. Die Builder-Objekte für die DSL sind zwar sehr nett, aber in der Verwendung sind sie enorm unhandlich. Zudem instanziieren wir sehr viele davon, was nicht günstig ist. Im Betrieb braucht es also eine einfachere Datenstruktur.

In der Vewendung braucht es etwa folgende Fragestellungen:

- Liebe $Zeiteinheit, die wievielte bist du in $AndererZeiteinheit?
- Liebes $Datum, was ist deine Standarddarstellung?
- Liebes $Datum, in welcher Ausgabe von $Zeiteinheit liegst du?
- Liebes $Zeitintervall, ich hätte gern ein Ereignis auf dir.
- Liebes $Datum, welche Ereignisse gibts bei dir?(1)

Ich hab mir mal ein paar Implementierungen angeguckt und die meisten schummeln. Einfach, weil sie z.B. wissen, dass dieses Ding namens November, der elfte Monat in dieser Sache namens Jahr ist. Die rechnen nicht, die lesen ab.

Was kann man machen:

Eine Era merkt sich zunächst mal nicht die Hierarchie der Builder-Objekte, sondern eine Klassifikation von Designationen, also Zeiteinheiten.

Besonders angenehm sind diejenigen, die sich uniform durchziehen. Die also erstens überall verfügbar und zweitens immer gleich lang sind. Bei uns z.B. Tage, Stunden und alles, was kürzer ist. Bei denen müssen wir nur wissen, wie lang sie sind.

Nicht ganz so hübsch, diejenigen, die zwar überall vorhanden, aber nicht immer gleich lang sind, z.B. Jahre und Monate.

Ganz hässlich sind diejenigen, die sporadisch vorkommen, also z.B. in Talwyns Harptos-Kalender die Monate und besonderen Feiertage, die sich abwechseln.

Bei jeder Designation sollte zudem stehen, worin sie standardmäßig gezählt wird. Wir zählen also Stunden für gewöhnlich in Bezug auf den laufenden Tag. Wir können uns natürlich, fragen wie viele Stunden seit Beginn des siderischen Monats, aber das ist nicht häufigste Anfrage. Also wenn ich ein Ding frage: "Das wie vielte bist du?", sollte es wissen, worin es standardmäßig gezählt wird.

Was alternative Namen angeht, wie Talwyn vorgeschlagen hat, würde ich eine Zuordnung (Map/Dictionary) benutzen, also z.B.

Zitat
val alturiak = Days 30 as "month" named "Alturiak" aka "poetic"->"The Claw of Winter" aka "poetic2"->"The Claws of the Cold"

Entsprechend kann man dann beliebig viele Varianten jeweils mit Bezeichner anfügen. Wir würden wahrscheinlich sowas wie
"short"->"Jan" für Januar wollen.

Für Ereignisse schwebt mir folgende Syntax vor:

event $eventName at $datum1 till $datum2 per $Designation given $condition §direction
Je nachdem, auf welchem Objekt man "event" aufruft können z.B. Anfang und Ende auch schon gesetzt sein. Direction gibts in drei Varianten: forewards, backwards und foreAndBack. Letzteres ist Standard, wenn es sich nicht um einmaliges Ereignis handelt.
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: Talwyn am 11.10.2016 | 10:38
Hab gerade leider keine Zeit, weil ich hier auf Arbeit blöderweise dafür bezahlt werde, unser Rechnungslegungssystem mit Salesforce zu integrieren, obwohl ich doch gerade viel lieber Rollenspielkalender programmieren würde ~;D Trotzdem sieht der Stand bisher schonmal gut aus - und: Siehste - ist nicht so trivial wie es zunächst aussieht, die Kalendersache. ;)

Da ist hinsichtlich meiner App tatsächlich z.B. die UI-Komponente für die Karte das kleinere Problem, da gibt es nämlich schon eine sehr schöne OpenSource-Implementierung.
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: Talwyn am 11.10.2016 | 10:41
Aber nur so als Frage: Wollen wir ein Github-Projekt für die Kalender-Library starten? Das wäre für mich auch eine schöne Gelegenheit, endlich mal ernsthaft mit Scala zu arbeiten (bislang habe ich es nur punktuell dort eingesetzt, wo mir Java zu unhandlich geworden ist, z.B. für XML-Verarbeitung).
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: 1of3 am 11.10.2016 | 11:23
Sehr gern. Dann komm ich endlich mal dazu mit Github zu arbeiten. ;)

Ich lad das heute Abend mal hoch.
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: Talwyn am 11.10.2016 | 11:43
Ich kann auch ein Repo mit einem Grundgerüst anlegen - Scala 2.11.8, sbt 0.13.12, Scalatest 2.11 3.0.0, MIT License?

Achso, und auch wichtig: Einen Namen braucht das Kind.

Wie wäre es mit libficcal (LIBrary for FICtional CALendars) oder kürzer ficcal oder fical oder Coolified "Fickle"? Oder ganz was anderes? Fantasy Calendar finde ich zu lang und auch nicht ganz passend.
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: 1of3 am 11.10.2016 | 12:28
Ja, mach mal gern.

Da ich deutscher Muttersprachler bin, löst "ficcal" bei mir keine besonders ehrfürchtige Reaktionen aus. ;)
Wie wärs mit "sideral"? Es gibt ja lunare und solare und lunisolare Kalender und wir transzendieren das. Oder... "Covella" war die Göttin, welche der römische Priesterkönig am Ersten des Monats angerufen hat.
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: Talwyn am 11.10.2016 | 13:10
Covella klingt doch gut. Ich mache mal.
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: Talwyn am 11.10.2016 | 13:36
Done: https://github.com/sandboxly/covella (https://github.com/sandboxly/covella)

Wenn du mir noch deinen Github Usernamen sagst, kann ich dich als Colaborator hinzufügen.

Die Ordnerstruktur für die Sourcen und Resourcen konnte ich leider nicht anlegen, da man leere Ordner nicht in ein Git Repo committen kann.

Ich schlage aber die bekannte Struktur vor: src/main/scala, src/main/resources, src/test/scala, src/test/resources

Wenn ich heute Abend Zeit finde, Setze ich noch Travis und Codeclimate auf.
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: 1of3 am 11.10.2016 | 15:37
Jo. Das bin ich. (https://github.com/Holothuroid)
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: Pyromancer am 11.10.2016 | 15:53
Hm, ich hätte das Ganze von der astronomischen Seite aufgezogen. Solare und lunare Zyklen (vielleicht mit mehreren Monden), Jahreszeiten, Feiertage, Sonnwenden und Tagundnachtgleichen, Aussaat und Ernte, wiederkehrende Wetterphänomene, darum geht es doch eigentlich, nicht darum, Tage runterzuzählen.
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: Talwyn am 11.10.2016 | 16:55
Doch, genau darum geht es mir persönlich. Der Kalender dient dazu, den Fortschritt der Ingame Zeit zu tracken. Aber womit du definitiv Recht hast, ist die Aussage, dass der Kalender die Mondphasen ebenfalls unterstützen sollte: In meiner aktuellen D&D Kampagne hat sich ein SC mit Lykanthropie angesteckt, da ist der Use Case also bereits gegeben. Auch sollten mehrere Monde unterstützt werden, das gibt es ja auch in genügend RPG Settings. Sollte aber relativ einfach zu machen sein. Schreibe nur gerade vom Telefon, da ist die Eingabe von Code sehr mühsam.


Gesendet von meinem Nexus 5 mit Tapatalk

Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: Talwyn am 11.10.2016 | 16:58
Was die Ereignisse angeht: Das wäre aus meiner Sicht nicht die Zuständigkeit einer allgemeinen Kalenderbibliothek, sondern eher die einer App(likation), die diese Bibliothek verwendet.


Gesendet von meinem Nexus 5 mit Tapatalk

Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: 1of3 am 11.10.2016 | 18:26
Hm, ich hätte das Ganze von der astronomischen Seite aufgezogen. Solare und lunare Zyklen (vielleicht mit mehreren Monden), Jahreszeiten, Feiertage, Sonnwenden und Tagundnachtgleichen, Aussaat und Ernte, wiederkehrende Wetterphänomene, darum geht es doch eigentlich, nicht darum, Tage runterzuzählen.

Das ist dem Programm im Grunde Wumpe. Du kannst damit auch synodischen, siderischen und tropischen Monat für fünf Monde tracken, wenn das dein Ding ist. Oder das Erscheinen der Feenkönigen bei Hofe nebst dem Flackern des Artefakts von Schnackpuck und die Aussaatzeit von Yamok-Wurzeln. Muss ich nicht wissen, deshalb hab ich ja versucht eine recht eingängige Spezialsprache zu schreiben, damit man ohne viel Aufmachung ein System zur Zeitmessung schreiben kann.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Antariuk am 11.10.2016 | 19:31
Kleiner Vorweg-Wunsch für ein Feature: ausdruckbare Ergebnisse, bzw. Exportation des Kalenders als Grafikdatei. Wenn das möglich ist bei einem so offen gehaltenen Ansatz. Würde die Benutzbarkeit für mich quasi verdoppeln ;)
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 11.10.2016 | 19:38
Ich bin mir nicht ganz sicher, was du mit Grafik meinst. Ich kann einen Kalender als Tabelle darstellen. Beschreib mal bitte, was du dir vorstellst..
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Antariuk am 11.10.2016 | 20:06
Ich bin mir nicht ganz sicher, was du mit Grafik meinst. Ich kann einen Kalender als Tabelle darstellen. Beschreib mal bitte, was du dir vorstellst..

Das man eine Übersicht des gebastelten Kalenders als JPG, BMP oder PNG exportieren kann um sie sich später auszudrucken, in Kampagnen-Handouts einzufügen oder in ein Wiki zu tun. So z.B.:

(https://abload.de/img/beaucal-minimonths1hbur.png)
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 11.10.2016 | 22:08
So,

habe mich ein wenig mit dem Code und den Konzepten auseinander gesetzt und kann jetzt endlich meinen unqualifizierten Senf dazu geben. Vorsicht, ab hier wird es für Nicht-Entwickler wahrscheinlich etwas kryptisch.

Grundsätzlich denke ich, wir sollten uns Modell vom Prozess der Konstruktion trennen: Wir brauchen ein möglichst einfaches, möglichst intuitives API, mit dem man einen Kalender definieren kann. Mir hat der erste Wurf von 1of3 sehr gut gefallen, und aus meiner Sicht wäre es wünschenswert, wenn das Skript für die Definition eines Kalenders so simpel bleiben könnte. Die gute Nachricht ist: Ich bin mir ziemlich sicher, das das auch klappt, aber dazu später mehr. Unabhängig von dieser Builder-API brauchen wir eine Datenstruktur, die die Domäne möglichst treffend abbildet. Wir haben also so gesehen zwei (oder mehr - auch dazu später mehr) "Pakete": Das Builder API und das Domänenmodell. Das Builder API definiert Funktionen, die - so sie aufgerufen werden - Objekte aus dem Domänenmodell erzeugen.

Für das Builder API bauen wir eine möglichst gut lesbare DSL (wie ja schon geschehen / bzw. begonnen)
Für das Domänenmodell modellieren wir so schnörkellos wie möglich unsere Anwendungsdomäne. Wir brauchen also geeignete Klassen, die die einzelnen Informationen, welche einen Kalender beschreiben, sowie die Beziehungen zwischen diesen Informationen möglichst einfach abbilden.

Wir sollten allerdings denke ich vermeiden, die Logik zur Konstruktion unserer Modellobjekte mit eben diesen Objekten zu vermischen: Die Definition eines Kalenders ist ein halbwegs komplexer Prozess, es lohnt sich diesen von der Repräsentation der Daten zu trennen, die von ihm (dem Prozess) erzeugt wird. Dazu verwendet man in der Regel das Builder Pattern (https://de.wikipedia.org/wiki/Erbauer_(Entwurfsmuster)). Selbiges ist ziemlich formalistisch definiert, weil es in der GoF-Bibel steht, aber so genau muss man das nicht nehmen. Wichtig ist die Essenz: Trenne einen komplexen Erzeugungs-Prozess vom (am Ende dieses Prozesses stehenden) Produkt. Ein Auto weiß nichts über den komplizierten Prozess, der durchlaufen werden musste, um es herzustellen, ebenso verhält es sich mit unserem Kalender.

Was das Builder API angeht, gefällt mir wie gesagt der ursprüngliche Vorschlag nach wie vor sehr gut, und ich denke auch, dass wir uns davon nicht weit entfernen müssen. Tage sind zwar sicherlich eine zu grobe Zeiteinheit für ein flexibles Kalendersystem, jedoch denke ich, dass in >95% aller klassichen RPG-Settings zumindest mal gilt, dass eine Stunde 60 Minuten und eine Minute 60 Sekunden hat. Selbst der 24-Stunden-Tag ist sehr weit verbreitet. Ich meine, dass diese Werte sich daher als sensible defaults anbieten - sie sind genau das, was in 95% zutrifft, von daher sollte es so einfach wie möglich sein, einen Kalender mit diesen Standardwerten zu erzeugen. Natürlich gibt es die Ausnahmen, und die sind auch nicht so extrem, dass man sie ignorieren könnte: Die Rotationsgeschwindigkeit von Planeten wird in Scifi-Settings häufig explizit definiert. Das Builder API sollte es also möglich machen, Tage mit 20 oder 32 Stunden zu definieren - oder Hell-Dunkel-Zyklen, die Soliden heißen und jeweils 4 Quartäre haben, welche unterteilt werden in jeweils 10000 Decamils. Dies sollte nach Möglichkeit ebenfalls mit dem Builder API relativ einfach zu beschreiben sein, da es sich bei solchen Konstrukten aber sicherlich um Exoten handelt, ist es aus meiner Sicht ok, wenn diese Spezialfälle eine etwas umständlichere Beschreibung durch die DSL erfordern. Für den Standardfall sollte es aber z.B. nicht nötig sein explizit zu definieren, dass ein Tag 24 Stunden zu 60 Minuten zu 60 Sekunden hat. Analog dazu plädiere ich für Convenience-Funktionen überall dort, wo es einen Fall gibt, den man in der überwältigenden Mehrheit der Fälle als Standard annehmen kann. Beispiel Events: Meist dürfte es sich hier um einen Tag - z.B. einen Feiertag handeln, insofern wäre es ein sensible default, von einer Dauer von einem Tag auszugehen. Ich denke auch, dass man standardmäßig annehmen kann, dass ein solcher Event sowohl vorwärts als auch rückwärts wiederholt werden sollte. Auch hier gibt es bestimmt genügend gute Beispiele für Ausnahmen, aber ich denke, unter dem Strich ist das API mit solchen Annahmen meistens einfacher zu verwenden.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 11.10.2016 | 22:21
@Antariuk: Covella soll erstmal wirklich nur eine Bibliothek werden, d.h. es handelt sich dabei nicht um eine Anwendung, die Endanwender auf ihrem Device ausführen können, um damit irgendwas zu tun. Stattdesen können andere Anwendungen Covella benutzen, um Funktionen rund um einen fiktional Kalender bereitzustellen. Das könnte dann zum Beispiel eine Kampagnen-Tagebuch-App sein, die ein Interface ähnlich z.B. Google Calendar hat, dabei aber auf einem FR- oder Golarion-Kalender läuft. Eine solche App könnte dann auch eine Funktion beinhalten, um die Kalenderdaten z.B. als PDF zu exportieren.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Anastylos am 11.10.2016 | 23:42
Es gibt bereits einen ziemlich guten Kalender http://donjon.bin.sh/fantasy/calendar/ (http://donjon.bin.sh/fantasy/calendar/)
Wobei es auf der Seite auch noch andere coole Sachen gibt. Wenn ihr ein eigenes Tool baut wünsche ich mir eine Option für zufällige Feiertage mit Namen.
Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: Pyromancer am 11.10.2016 | 23:48
Das ist dem Programm im Grunde Wumpe. Du kannst damit auch synodischen, siderischen und tropischen Monat für fünf Monde tracken, wenn das dein Ding ist. Oder das Erscheinen der Feenkönigen bei Hofe nebst dem Flackern des Artefakts von Schnackpuck und die Aussaatzeit von Yamok-Wurzeln. Muss ich nicht wissen, deshalb hab ich ja versucht eine recht eingängige Spezialsprache zu schreiben, damit man ohne viel Aufmachung ein System zur Zeitmessung schreiben kann.

Wie sieht es aus mit den Auf- und Untergangszeiten von Himmelskörpern?
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 12.10.2016 | 09:21
Nicht direkt. Also nicht in diesem Stadium. Also höchstens insofern, dass du die Dauer der Helligkeitsperiode für einen Breitengrad übers Jahr eingibst und ausrechnest.

Zitat
Tage sind zwar sicherlich eine zu grobe Zeiteinheit für ein flexibles Kalendersystem, jedoch denke ich, dass in >95% aller klassichen RPG-Settings zumindest mal gilt, dass eine Stunde 60 Minuten und eine Minute 60 Sekunden hat. Selbst der 24-Stunden-Tag ist sehr weit verbreitet. Ich meine, dass diese Werte sich daher als sensible defaults anbieten - sie sind genau das, was in 95% zutrifft, von daher sollte es so einfach wie möglich sein, einen Kalender mit diesen Standardwerten zu erzeugen.

Gut. Dann könen wir also leicht eine Schwelle über und eine unter dem Tag annehmen. Wenn user uns nichts erzählst, nehmen wir an, dass Tage wie gewohnt funktionieren. Das vereinfacht ein paar Dinge.

Zitat
Events: Meist dürfte es sich hier um einen Tag - z.B. einen Feiertag handeln, insofern wäre es ein sensible default, von einer Dauer von einem Tag auszugehen. Ich denke auch, dass man standardmäßig annehmen kann, dass ein solcher Event sowohl vorwärts als auch rückwärts wiederholt werden sollte.

Events standardmäßig mit Tageslänge ist OK für mich. Ich hab so Stiftungstage von irgendwelchen Tempeln im Kopf, die eben erst ab einem Zeitpunkt gestiftet sind. Aber klar. Standard muss sein, dass der Event sich in Zukunft und Vergangenheit ausstreckt. Wichtig wär mir halt z.B. Ostern berechnen zu können.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 12.10.2016 | 10:11
Ja wie gesagt, es sollte möglich sein. Man sollte es dem Anwender nur ersparen müssen, für alle 36 Feiertage seines Kalenders explizit angeben zu müssen, dass sie nur einen Tag lang dauern und in beide Richtungen wiederholt werden sollen.

Ich frage mich gerade überhaupt ob sowas wie Ostern tatsächlich auf Kalender-API-Level verankert werden sollte. Im Grunde ist das ja ein Ereignis, das nur für einen bestimmten Kulturkreis gilt. Ich würde das deswegen wohl eher als Datensatz betrachten, den man in einer Applikation speichert, die Covella verwendet, also so als würde ich in meinen Outlook-Kalender einen neuen Termin eintragen. Die Faerûnischen Feiertage wären hingegen ein anderes Biest, weil diese ja nicht an einem regulären Kalendertag auftreten - stattdessen handelt es sich bei ihnen ja effektiv um "Monate mit nur einem Tag".

@Anastylos: Im Moment bauen wir noch kein Tool für den Endanwender, sondern versuchen erstmal nur das Konstrukt "beliebiger fiktionaler Kalender" in Gestalt von Programmcode so zu formalisieren, dass man am Ende eine Bibliothek erhält, die es einfach macht, allerlei Anwendungen zu entwickeln, deren Funktionen sich um einen solchen fiktionalen Kalender drehen. Bei einer solchen Anwendung kann es sich dann z.B. um eine Art "Outlook-Kalender für Golarion" handeln, eine App, die den Fortschritt der Ingame-Zeit korrekt trackt, oder was auch immer. So weit sind wir aber momentan noch nicht, da der Anspruch eine generisch verwendbare Bibliothek zu entwickeln die Sache recht kompliziert macht.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 12.10.2016 | 10:33
Zitat
Ich frage mich gerade überhaupt ob sowas wie Ostern tatsächlich auf Kalender-API-Level verankert werden sollte. Im Grunde ist das ja ein Ereignis, das nur für einen bestimmten Kulturkreis gilt.

Ne, es geht mir nicht um Ostern an sich. Es geht mir um Aufgaben vom Typ: "Finde den ersten Sonntag nach dem ersten Vollmond im Frühling." Das ist Ostern. Oder eben: "Finde Freitag den 13." Mithin also Ereignisse, die über das Zusammenwirken verschiedener Zyklen definiert sind. Ostern ist so das komplexeste und bekannteste Beispiel in unserem Kulturkreis.

Du hast natürlich recht, dass die Feiertage im Harptos-Kalender - man nennt sowas auch "leere Tage" - ein anderes Ding sind.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 12.10.2016 | 10:50
Ja schon klar, aber nehmen wir dochmal Real-World-Kalender-Apps oder auch bestehende Datums-APIs wie etwa java.util.Calendar oder Joda-Time - die wissen in der Regel selbst nicht, wann Ostern ist. Wenn sie mir allerdings sagen, wann der Frühling beginnt und wie die Mondphasen verlaufen, dann kann ich als Anwender ausrechnen, wann Ostern ist. Ich finde daher, dass diese "Intelligenz" nicht innerhalb von Covella verortet werden sollte. Zur Illustration habe ich mal ein Diagramm angehängt.

Ich bin ein Fan von kleinen Software-Komponenten, die nur eine Sache tun, diese aber dafür gut. Und das "gut" ist leichter zu erreichen, wenn man die Komplexität gering hält. Im Prinzip ist das übrigens genau die Design-Philosophie, die hint den UNIX Pipes steckt, und dort, sowie in vielen davon inspirierten Architekturen hat sich das bewährt.

[gelöscht durch Administrator]
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 12.10.2016 | 10:58
Wahrscheinlich meinen wir das gleiche. Um sicher zu gehen: Welche Funktionalität sollte das Interface enthalten, das die Covella-Bibliothek der Anwendung bereitstellt?
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 12.10.2016 | 12:11
Ok, jetzt nähern wir uns dem Kern der Sache. Komme nur jetzt nicht dazu, das zu beschreiben. Ich sehe zu, dass ich es heute Abend schaffe, mir was aus den Fingern zu saugen.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 14.10.2016 | 09:28
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:

myCalendar = new Calendar based on system "Calendar of Harptos" with start date "13th Marpenoth 1485 DR"

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:

advance myCalendar by 3 days
advance myCalendar by 4 hours and 30 minutes
rewind myCalendar by 1 year

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:

myCalendar = {
    system: 'Calendar of Harptos' ,
    interntalValue: 189798297898L
}

textualRepresentation = myCalendar.format() // assuming standard format
assert that textualRepresentation equals "13th Marpenoth 1485 DR"

COVELLA-6
Das Kalenderobjekt stellt Funktionen zur Verfügung, um auf die einzelnen Komponenten des in ihm gespeicherten Zeit-Werts zugreifen zu können:

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"

Das mal als erster Wurf. Muss man sicher noch verfeinern, aber das funktioniert erfahrungsgemäß besser, wenn man sich gegenseitig den Ball zuspielen kann.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 14.10.2016 | 10:49
Zitat
myCalendar = {
    system: 'Calendar of Harptos' ,
    interntalValue: 189798297898L
}

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.

year therein month 11 therein third monday
Dann wird das Parsing auch direkt einfacher.


Aber ansonsten gehen wir völlig d'accord.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 14.10.2016 | 10:55
Ja du hast Recht, das was ich hier als Kalender bezeichne ist ein Datum. Richtiger wäre:

calendar = new Calendar("Calendar of Harptos")
myDate = calendar.getDate("13th Marpenoth 1485 DR")
// oder
myDate = calendar.getDate(1485, 10, 13)
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 14.10.2016 | 12:30
OK. Eine Frage bleibt dann noch:

myDate.[b]getYear[/b] equals 1485
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.

november indexIn year // returns 10, weil Zählung fängt bei 0 an
- falls diese Art von Intervallen Namen hat, kann man sie natürlich nach ihrem Namen fragen

myDate.getMonthName
Ist dann also identisch zu:

myDate.getMonth.name ...
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 14.10.2016 | 13:22
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:

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

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.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 14.10.2016 | 13:24
Und was die Namen angeht, wie wäre es mit sowas:

date.get(MONTH) ==> 10
date.getName(MONTH) ==> "Marpenoth"
date.get(YEAR) ==> 1485
date.getName(YEAR) ==> "Year of the Iron Dwarf's Vengeance"
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 14.10.2016 | 14:11
In Ordnung. Dann haben wir etwa folgende Funktionen auf einem Datum.

def get : Int
def getName : String
def getAlias : String
def getInterval : Interval

Jeweils parametrisiert mit der Einheit.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 14.10.2016 | 14:20
Klingt gut soweit.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Shihan am 14.10.2016 | 18:02
Mal eine Zwischenfrage, weil mich das als Entwickler auch interessiert:
Habe keinerlei Erfahrung mit Scala. Wie einfach lässt sich denn eine damit erstellte Bibliothek in ein bestehendes Java-Projekt einbinden?
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 14.10.2016 | 19:11
Grundsätzlich kein Problem. Sind .jar-Dateien, wenn der Compiler fertig ist.

Von Java auf Scala zugreifen wirkt manchmal etwas hässlich, weil Scala Operatoren als Methodennamen benutzen kann. Also Java kann ja z.B. nicht einfach "+" benutzen, um eine Funktion auf einem Objekt zu aufzurufen, das würde dann zu $plus umgewandelt. Wir können aber problemlos jeweils ein lesbares Alias einfügen, also meinetwegen "add".

Wenns dich interessiert: Basics von Venkat Submaraniam (https://www.youtube.com/watch?v=LH75sJAR0hc&index=1&list=PLFoD4sRO13ldJZXf4a2bUdRaQGeEqAqnK)
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 14.10.2016 | 23:02
Ich habe vor einen Java Wrapper für die Bibliothek zu bauen sobald sie mal steht. Weil, was 1of3 sagt gibt auch noch ein paar Sprachkonstrukte, die Java nicht so ohne weiteres beherrscht.


Gesendet von meinem Nexus 5 mit Tapatalk

Titel: Re: Projekt FantasyCalendar; war: Hexcrawl Weltenbau Support Tool
Beitrag von: Skeeve am 15.10.2016 | 17:53
Hm, ich hätte das Ganze von der astronomischen Seite aufgezogen. Solare und lunare Zyklen (vielleicht mit mehreren Monden), Jahreszeiten, Feiertage, Sonnwenden und Tagundnachtgleichen, Aussaat und Ernte, wiederkehrende Wetterphänomene, darum geht es doch eigentlich, nicht darum, Tage runterzuzählen.

Ungefähr das (lunare und solare Zyklen) wollte ich ungefähr zur gleichen Zeit auch schreiben. Wobei dies

Was ich mit Herausforderung bei den Kalendern meinte ist: Es sollte für Nicht-Programmierer möglich sein, auf relativ einfache Weise den Kalender ihrer Spielwelt so zu beschreiben, dass die App damit arbeiten kann.
das ganze vermutlich etwas komplizieren könnte...
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Boba Fett am 15.10.2016 | 18:35
Wenn ihr beim Programmieren eine Übung braucht, dann realisiert doch mal folgenden Kalender:

Wir nehmen die Erde als Umlaufzeit zum Vorbild, also 365 TAge im Jahr. Jedes 4. Jahr ein Schalttag, ausser in den Hunderten, wobei die "außer" Regel in den Tauserndern doch wieder eine Ausnahme bildet - die Tausender haben ein Schaltjahr.
Soweit so gut, das ist unsere Welt (derzeit).

Das Kalenderjahr beginnt bei der Tag-Nachtgleiche im Frühling der Nordheminsphäre.
Jeder Monat hat exakt 30 Tage.
Jede Woche hat 6 Tage, also hat Jeder Monat 5 Wochen.
(Die 12 x 30 Tage machen also schon mal 360 Tage im Jahr aus. Fehlen noch 5 ...)
Vor jedem Quartal (3 Monate) wird ein außerhalb der Monate und Wochentage liegender Tag an den Tagen der Tag/Nacht-gleiche, zu Midsommer und Midwinter zusätzlich eingeschoben.
Der Jahreswechsel bekommt einen weiteren extra Tag als allerletzter Tag im Jahr.
Der Schalttag wird zwischen dem letzten Tag und dem Quartalsbeginntag eingeschoben.

Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 15.10.2016 | 19:09
@Boba: Meinst du so?

val month = (Days(6) as "week") *5 as "month"
val quartal= Days(1) as "extra day" + month *3

val standardYear = quartal *4 as "year"
val leapYear = (quartal * 4 + Days(1) as "leap day" ) as "year"

val fourYearCycle = standardYear * 3 + leapYear

val century = fourYearCycle * 24 + standardYear * 4

val millenium = century * 9 + fourYearCycle * 25

val meinKalender = Calendar ( millenium )
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Skeeve am 16.10.2016 | 03:43
Ich glaube bei
val standardYear = quartal *4 as "year"
val leapYear = (quartal * 4 + Days(1) as "leap day" ) as "year"
fehlt noch der Jahreswechsel. Also vielleicht so:

val standardYear = quartal *4 as "year" + Days(1) as "turnOfTheYear"
val leapYear = (quartal * 4 + Days(1) as "leap day" ) as "year" + Days(1) as "turnOfTheYear"

Wobei ich keinen Plan habe ob das die korrekte Syntax ist.  Dazu habe ich viel zu wenig Ahnung von Scala und Java.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 16.10.2016 | 10:31
Das hat wenig mit Scala oder Java zu tun. Die Frage ist, wie die Funktionen geschrieben sind. ;)

Du hast allerdings nicht unrecht, ich hatte nur vier Extratage, also hieße es dann:

val standardYear = (quartal *4 + Days(1) as "extra day") as "year"
val leapYear = (quartal * 4  + Days(1) as "extra day" + Days(1) as "leap day" ) as "year"

Zur Erklärung: Das "as" fasst was davor kommt zu einer Zeiteinheit zusammen mit dem folgenden Bezeichner zusammen. Was die Operatoren tun, hängt davon ab, ob zwischendurch ein "as" fällt. Dadurch wird also gesteuert, was "+" tut.

Zur Verdeutlichung bezeichne ich nicht ausgezeichnete Einheiten mit Großbuchstaben (A, B, C),  ausgezeichnete - d.h. solche, die "as" bekommen haben - mit Großbuchstaben und Apostroph (A', B', C').

Es gilt: A' + B' => (A', B'). D.h. die Summe zweier ausgezeichneter Einheiten ist ein Compound, das sie enthält.
Wenn man nun ein Compound hat und addiert noch ein ausgezeichnetes Element, was soll passieren? - Das drite Element soll mit in die Klammer:
(A', B') + C' => (A', B', C').

Wenn man jetzt zwischendurch wieder "as" schreibt, passiert folgendes: (A', B')'. Das zusammengesetzte Element ist also ausgezichnet und damit abgeschlossen. (Intern ändert "as" den Datentyp.) Wenn man jetzt auf diesem ausgezeichneten Element etwas addiert, ist das Ergebnis anders: (A', B')' + C' => ( (A', B')', C' ). Es hat also ein weiteres Level erzeugt.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Skeeve am 16.10.2016 | 11:57
Das hat wenig mit Scala oder Java zu tun. Die Frage ist, wie die Funktionen geschrieben sind. ;)

Naja, um die Funktionien zu verstehen... hätte es auch eine andere Uhrzeit sein müssen. Aber nun macht sich hier auch langsam die Erkenntnis breit dass "as" und "named" gar keine Elemente von Java oder Scala sind, sondern selbstgemachte Methoden einer abstrakten Klasse (oder doch Funktionen?)

Aber mein Erkenntnissgewinn ist hier ja nicht Thema, also weiter machen....  ;)
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 16.10.2016 | 21:12
Och, ich erklär das gern. Aber du hast recht. Dass man diesen Unterschied nicht sofort erkennt, ist eine Eigenschaft von DSL-freundlichen Sprachen: Keine Semikola, Funktionsaufrufe brauchen keine Klammern, Zugriff auf Eigenschaften und Methoden brauchen keine Punkte. Das gleiche könnte man wohl auch in Groovy und einigen anderen modernen Sprachen machen. Und ja, es sind Instanz-Methoden, Scala kann keine Toplevel-Funktionen und statische Methoden werden durch Methoden auf Singletons ersetzt.

Aber kommen wir mal zurück:

Ich würde für Konvenienz neben Days auch direkt Month einführen.

Month(int) - gib mir einen Monat mit int Tagen.
Month(int,String) - gib mir einen Monat mit int Tagen und Namen String.

Wir sollten auch die typischen Bezeichnungen für Tag, Woche, Monat, Jahr direkt als internationalisierten String einfügen. Dann kann sich die Kundschaft für typische Fälle die Anführungszeichen sparen. Internationalisierte Strings gibts mit der Bibliothek Rapture wohl recht komfortabel, hab ich aber noch nicht ausprobiert.


Zum Format:

Das könnten wir mit einem handgemachten Stringkontext machen. Das sähe bei der Verwendung dann z.B. so aus:

date"""$number(day). $name(month) $number(year)"""
Wenn man in den Aufrufen keine Anführungszeichen verwendet, kann man zur Berandung auch einmal, statt dreimal die Anführungszeichen machen. Hinter den Kulissen wird ein String mit einem solchen Präfix wie date als StringContext (http://scala-lang.org/files/archive/nightly/docs/library/index.html#scala.StringContext) behandelt und der Compiler sucht dann eine Methode namens date.

Die Methode sollte dann ein DateFormat zurückgeben, das hat:
- eine Methode "to" um ein Datum zum String zu machen.
- eine PartialFunction (http://scala-lang.org/files/archive/nightly/docs/library/index.html#scala.PartialFunction) "from" um aus einem String ein Datum zu machen.

Der Kalender hält eine Liste mit DateFormats vor. Wenn der User dann einen String parsen will, werden alle partiellen Funktionen durchlaufen, ob eine passt.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Skeeve am 17.10.2016 | 01:06
Dass man diesen Unterschied nicht sofort erkennt, ist eine Eigenschaft von DSL-freundlichen Sprachen: Keine Semikola, Funktionsaufrufe brauchen keine Klammern, Zugriff auf Eigenschaften und Methoden brauchen keine Punkte.

Ja! Man kann Python zwar recht großzügig umbauen und verbiegen , aber ganz so frei wie bei Scala wird man es wohl nicht hinbekommen...
Aber ich habe gerade ein Beispiel entdeckt. Ich glaube aus val leapYear = (quartal * 4  + Days(1) as "extra day" + Days(1) as "leap day" ) as "year" könnte man z.B. leapYear = (quartal * 4  + Days(1) |as| "extra day" + Days(1) |as| "leap day" ) |as| "year" machen und das wäre ein gültiger Python-Ausdruck den man durch den Python-Parser jagen könnte und bei passender Metaprogrammierung würde das Teil dann auch das gewünschte machen.
Oder man baut sich seinen eigenen speziell an die neue Sprache angepassten Parser. Das geht fast immer,  aber ob man den Aufwand treiben möchte.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 19.10.2016 | 16:10
Mir sind noch ein paar Fragen zur Benutzung gekommen:

Bei einigen Zeiteinheiten fangen wir beim Zählen bei Null an. Es kann z.B. "0 Uhr 5 Minuten" sein. Aber egal, ob die Woche bei Sonntag oder Montag anfängt, es ist der erste Tag. Ebenso haben wir keinen nullten Tag im Monat und keinen nullten Monat im Jahr.

Wenn jetzt also jemand Datum#get(month) bzw. Datum#get(hour) sagt, erwartet er da ggf. unterschiedliche Ergebnisse. Jetzt gibts zwei Möglichkeiten: Entweder in der Dokumentation steht: "Die Rückgaben fangen bei 0 an zu zählen, achte drauf ggf. was draufzuaddieren, wenn du das Ergebnis benutzt!", oder wir erweitern das Modell, das man das Verhalten einstellen kann. Auch dann fragt sich, was der Standard sein soll, wenn man nichts einstellt: 0 oder 1?

Was findet denn die geneigte Userschaft sinnvoller?



Damit verwandt: Wir sagen zwar, dass wir unsere Jahre zählen, aber wir zählen sie nicht so, wir wir alles andere Zählen. Ein Jahr 0 gibts nicht und die davor sind auch nicht negativ. An dieser Stelle würde ich aber so rigoros sein und zu sagen: Das sind keine Zahlen. Das sind Jahresnamen. Das Jahr heißt "1980 n. Chr." bzw. "43 v. Chr." oder wie mans gern mag. Wer an der Stelle also get(year) statt getName(year) abfragt, bekommt nicht das gewünschte.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Antariuk am 19.10.2016 | 16:55
Ich glaube ich fände es einfacher wenn eine Zählung standardmäßig bei 1 beginnt und ich als Option dann einstellen kann das es alternativ doch 0 sein soll.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 19.10.2016 | 20:14
Ich bin als Informatiker zwar gewöhnt bei der 0 mit dem Zählen zu beginnen. Aber angesichts der Tatsache, dass die DSL auch für Nicht-Programmierer intuitiv verwendbar sein soll schließe ich mich dem an.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Skeeve am 22.10.2016 | 01:46
... und ich schliesse mich da auch ganz Talwyn an.

Aber um noch was anderes interessantes anzusprechen: was soll die DSL eigentlich machen bz. was gehört alles zu einer DSL?

Dient die nur als Basis für solche Kalender (http://www.tanelorn.net/index.php/topic,100105.msg134426528.html#msg134426528) oder sollen auch Funktionen rein wie "gehe vom aktuellen Datum einen Tick weiter und nennen mir den neuen Zeiitpunkt/das Datum" (falls der kleinstmögliche Schritt ein Tag ist, könnte man auch sagen "gehe einen Tag weiter und gibt mir das Datum"). Andere denkbare Funktionen: Fragen wie "welches Datum ist in einem Monat?".

Mir ist mittlerweile bewusst geworden, dass hier auf der Erde der Schritt auf "einen Tag später" oder "eine Woche später" zwar reichlich einfach und klar definiert ist. Aber welcher Termin ist bei "einen Monat später" gemeint wenn das aktuelle Datum z.b. der 31.Oktober ist? Bei "ein Jahr später" haben hier ja auch all diejenigen ein kleines Problem, die am 29. Feburar geboren wurden.

Ich weiß schon warum es bei meiner Welt dreizehn Monate mit jeweils 28 Tagen (4 Wochen a 7 Tage) gibt... Wenn ich mir schon eine eigene Welt ausdenke, dann kann ich da ja auch ein paar Sachen einfach halten.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 23.10.2016 | 17:49
Ja, was kann passieren, wenn man vom 31. Oktober einen Monat weiter geht? Entweder 30. November, also den letztmöglichen Termin oder Bumm. Deshalb meinte ich oben schon, dass es da zwei Methoden geben sollte.

"later 1 month" liefert den 30. November, "+ 1 month" einen Fehler. Vorzugsweise einen Compilerfehler.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 23.10.2016 | 21:03
Ich denke man muss zwischen uniformen und nicht-uniformen Zeiteinheiten unterscheiden. Uniform wären z.B. Tage, Stunden Minuten und Sekunden. Für diese ist es einfach eine advanceBy Funktion zu definieren. Für alles andere muss man ein Verhalten definieren und dabei bleiben, da es nicht die eine sich aufdränge richtige Lösung gibt.


Gesendet von meinem SM-T813 mit Tapatalk

Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 24.10.2016 | 09:27
OK. Fallen euch im Falle von nicht uniformen Einheiten Varianten ein, außer vom Übergang von einer kürzeren zu einer längeren Variante ggf. das letzte Datum auszugeben?
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 24.10.2016 | 11:42
Für den Fall des Monats:

var d = Date(2016, 10, 31)
d advanceBy (1, MONTH)
println(d.format) // 30.11.2016

Für den Fall des Jahres

var d = Date(2016, 2, 29)
d.advanceBy (1, YEAR)
println(d.format) // 28.02.2017

Erscheint mir halbwegs intuitiv und leicht zu verstehen.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 25.10.2016 | 14:16
Jo. Das ändert ein bisschen den Vorgang. Mit diesen Eigenschaften sind unsere Einheiten nicht mehr rein kompositionell. Es reicht nicht mehr zu wissen, welche Einheit in welcher anderen Einheit wie oft enthalten ist. Das Modell braucht Informationen über die einzelne Einheit.

Wenn wir das sowieso tun müssen, können wir uns die Umwandlung von den Builder-Objekten in den Kalender vereinfachen.

Ich schlage also vor: Wir machen eine Klasse TimeUnit (o.ä.) an der man all diese Dinge einstellen kann. Standardmäßig bieten wir Kandidaten wie Month, Week, Year, Hour, Minute, Second, Day an. Dann können User die entweder so benutzen, sie modifizieren ("Meine Monate sind alle gleich lang!") oder ganz neue bauen.

Das erspart uns beim parsen herauszufinden, was für eine Einheit das ist.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Talwyn am 25.10.2016 | 15:55
Klingt gut. Habe nur leider momentan wenig Zeit für das Projekt, da ich aus so einer Laune heraus einen Fernkurs zum Thema Machine Learning belegt habe und nun feststellen muss, dass das einen Sack voll Arbeit bedeutet.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 26.11.2016 | 13:05
Frage an den Kundenkreis.

Wenn ich sagen möchte: Monat 5.

Welchen Operator, welches Zeichen, welches Wort würdet ihr dazwischen erwarten. Doppelpunkt scheidet aus. Also: "monat: 5" geht nicht als Eingabe. Was kann ich stattdessen nehmen, was einigermaßen einleuchtend scheint?
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: achlys am 27.11.2016 | 02:02
Ein "=" "Monat=5", wobei ich der Klarheit wegen in der Ausgabe "Monatsnummer = 5" nehmen würde, oder man dreht es um: "5. Monat"

Gesendet mit nem Smartphone. Tippfehler dürfen behalten werden.

Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 27.11.2016 | 10:31
OK. Gleichheitszeichen geht auch nicht. Da hab ich nicht dran gedacht.


Gesendet von meinem K011 mit Tapatalk

Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: sir_paul am 27.11.2016 | 11:30
Wie wäre es mit "ist" als Operator oder halt auf englisch "is". Dann könnte man einfach schreiben Tag ist 3,  Monat ist 5, etc.


Gesendet von meinem Nexus 9 mit Tapatalk

Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: achlys am 27.11.2016 | 17:13
Ein Pfeil? '->'
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 26.01.2017 | 21:16
Pfeil wäre möglich. Produziert grundsätzlich Tupel, also A->B ist das selbe wie (A,B), aber da könnte man mit implicits zaubern.

Nächste Frage. Aktuell sieht unser westlicher Kalender (wenn wir Schaltsekunden ignorieren) so aus:

Zitat

// Zeiteinheiten

 var millis = Tick("millisecond") countFromZero
  var seconds = Cycle from millis(1000) named "second" countFromZero
  var minutes = Cycle from seconds(60) named "minute" countFromZero
  var hours = Cycle from minutes(60) named "hour" countFromZero
  var days= Cycle from hours(24) named "day"
  var months= IrregularUnit("month")
  var years = IrregularUnit("year")

// Ausprägungen unregelmäßiger Zeiteinheiten

val january  = days(31) as month named "January" aka ("short","Jan")
  val february = days(28) as month named "February" aka ("short","Feb")
  val march = days(31) as month named "March" aka ("short","Mar")
  val april  = days(30) as month named "April" aka ("short","Apr")
  val may = days(31) as month named "May" aka ("short","May")
  val june  = days(30) as month named "June" aka ("short","Jun")
  val july = days(31) as month named "July" aka ("short","Jul")
  val august = days(31) as month named "August" aka ("short","Aug")
  val september  = days(30) as month named "September" aka ("short","Sep")
  val october  = days(31) as month named "October" aka ("short","Oct")
  val november = days(30) as month named "November" aka ("short","Nov")
  val december  = days(31) as month named "December" aka ("short","Dec")


  val standardYear = january + february + march + april + may + june + july +
                       august + september + october + november + december as year

  val leapFebruary = day(29) as month named "February"aka ("short","Feb")

  val leapYear = january + leapFebruary + march + april + may + june + july +
                   august + september + october + november + december as year

  val october1582 = october exclude (5 to 14)

  val year1582 = january + february + march + april + may + june + july +
    august + september + october1582 + november + december as year

// Wir bauen uns die Schaltregel und den Wechsel von Julianisch auf Gregorianisch

  val westernEra =
    Era given 1582 have year1582                                                    // wenn eine Jahreszahl abgefragt wird, wir das 1. Passende geliefert
      given  (x => x > 1582 && x%100==0 && x%400!=0) have standardYear
      given (_ % 4 == 0) have leapYear
      rest standardYear 
      exclude 0 // Jahr 0 gibts nicht.
      setEraNames ( x =>  Map( "default" ->  (if (x>=0) x + " CE" else x + " BCE") ) )  // setzt die Jahresnamen

// Wir machen einen Kalender draus

val westernCalendar = Calendar(westernEra)


Zur Verschönerung könnte man noch Funktionen wie divisbleBy und notDivisibleBy definieren. Teilbarkeit ist für Schaltregeln ein ziemlich übliches Kriterium.


Was jetzt noch fehlt, sind sekundäre Zyklen. Also bei uns z.B. die Wochen.

Um solche sekundären Zyklen anzuhängen, braucht es drei Informationen:
a) Welchen Zyklus
b) Wo soll ich ihn anhängen, also irgendeinen Zeitpunkt in der primären Ära.
c) Welchen Zeitpunkt des sekundären Zyklus möchte ich genau synchronisieren.

Bis auf (a) sollen die beiden anderen Angaben optional sein. Das ist soweit kein Problem. Fehlt (b) gehen wir von Datum 0 aus. Fehlt (c), nehmen wir an, der Anfang des sekundären Zyklus ist gemeint.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: TKarn am 13.01.2018 | 19:06
Ich bin gerade auf das Thema gestossen. Wie weit ist das Projekt denn fortgeschritten? Gibt es das Programm irgendwo?
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 9.05.2018 | 15:01
Hallo TKarn,

ich hatte deine Anfrage nicht gesehen, entschuldige bitte.

Du findest auf http://github.com/holothuroid/covella Quellcode. Der hat allerdings momentan noch einen Fehler. Für Zeiten vor 0 macht es Probleme, wenn man Schaltjahre benutzt.

Ich hab es letzte Woche eine Implementation hinbekommen, die regelmäßige Schaltjahre (alle 4 Jahre oder so) auch für Werte unter 0 hinbekommt. Ich würde noch einige Sachen ergänzen, korrigieren, refaktorieren und testen, bevor ich die nächste Version veröffentliche.

Es sei denn natürlich, du oder jemand anders möchte sich mit dem Quellcode auseinandersetzen. Dann kann ichs jederzeit hochschieben.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: TKarn am 9.05.2018 | 15:09
Vielen Dank für die Antwort. Ich schaue es mir mal an.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 14.05.2018 | 17:47
So. Habe nun die aktuelle Version hochgeladen.

- Die Syntax für die häufigsten Problemstellungen ist mit Convenience-Funktion year() deutlich einfacher.

- Calendar optimiert automatisch, wenn man eine Schaltregel mit den eingebauten Funktionen (divisibleBy, notDivisibleBy, congruent) definiert. Oder eigens kreierten, die PeriodicFunction implementieren. Das habe ich für Symmetry454 mal vorgemacht. Der Kalender wird dadurch um Größenordnungen performanter.

- Intern habe ich den Code so umstrukturiert, dass so ziemlich alle optionalen Features wie (Namen, Zählung nicht ab 0 o.ä.) über Decorators laufen. Das hält die Komposit-Klassen klein. Ein paar einfache Unit-Tests habe ich auch hinzugefügt.

Was noch fehlt, ist eine spezielle Meta-Ära, um Wechsel im Kalendersystem effizient zu behandeln.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: TKarn am 15.05.2018 | 10:28
Das läuft dann alles unter SCALA? Was muss ich sonst noch alles installieren?
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 15.05.2018 | 10:42
Ich weiß jetzt nicht genau, inwieweit du vom Fach bist...

Ich benutze zum Entwickeln:
Java Development Kit
Scala
SBT - Scala Build Tool
Intellij Idea IDE mit Scala Plugin.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: TKarn am 15.05.2018 | 11:51
Naja, so vom Fach bin nicht, aber auch nicht ganz unbedarft.  Bin Steuerungsprogrammierer.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 25.05.2018 | 15:09
[1] Normaler heutiger benutzter Kalender
[2] Kalender, die verschiedene Zeitalter und darin unterschiedliche Zeitrechnungen berücksichtigen. z.B. im ersten Zeitalter 8-Tage Wochen, 50-70 Tage Monate), im zweiten Zeitalter 5-Tage Wochen etc.
[3]Lunare römische Kalender
[4]Maya-Kalender
[5]Weltenübergreifender Kalender (wie im oben geposteten Tool https://www.wizards.com/dnd/ec/index.htm) mit unterschiedlich schnell vergehender Zeit
[6]Nichtlinearer Zeitfluss Kalender (für Zeitreisenszenarios mit alternativen Realitäten)
[7]Nichtkonstanter Zeitfluss (Relativistischer Kalender für so etwas wie im Film "Interstellar")

1 Läuft, in diversen Geschmacksrichtungen (https://github.com/Holothuroid/Covella/blob/Holothuroid-patch-1/covella/examples/WesternCalendar.scala)
2 Läuft so lala. Bessere Implementation in Arbeit.
3 Solange du weißt, wie die aussehen, läuft.
4 Läuft (https://github.com/Holothuroid/Covella/blob/Holothuroid-patch-1/covella/examples/MayaCalendar.scala)
5 Wenn du mir ne Definition für den Eberron-Kalender lieferst, kein Problem.
6 Das ist wohl ein gänzlich anderer Anwendungsbereich.
7 Grundsätzlich kein Problem. Die Kalender in den Beispielen sind mehrheitlich mit einem Days-Objekt parameterisiert. Du musst nur verschieden lange Days übergeben und das funktioniert. Ggf. wäre noch eine Methode nützlich, die alle Zeiteinheiten in einem Kalender mit einem Präfix versieht, damit solche Kopien voneinander unterscheidbar bleiben.


Das man eine Übersicht des gebastelten Kalenders als JPG, BMP oder PNG exportieren kann um sie sich später auszudrucken, in Kampagnen-Handouts einzufügen oder in ein Wiki zu tun. So z.B.:

Das macht in allgemeiner Form ehrlich gesagt wenig Sinn. Eine zwei dimensionale Struktur ist für unseren Kalender praktisch, weil wir zwei unabhägnige Zyklen haben: Jahre und Wochen. Es kann aber sein, dass du nur einen Zyklus hast oder deutlich mehr. Siehe die Maya oben. Du kannst natürlich alle Daten von bis als Liste ausgeben.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: TKarn am 25.05.2018 | 16:12
Hab mir das alles mal installiert, habe aber noch Probleme, den Kalender zum Laufen zu bekommen. Sind noch irgendwelche fehlenden Bibliotheken. Aber ich bin dran.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 26.05.2018 | 07:46
Hmmmm. Womöglich musst du noch irgendwelche Dinge bei IntelliJ anmelden? Die IDE muss letztlich wissen, wo die anderen Sachen liegen. - Kannst du über das Menü ein neues "Scala-Projekt mit SBT" erzeugen?

Falls ja, läuft das? Also kannst du eine .scala-Datei erzeugen mit

object MyFirstProgram extends App {
println("Hello World")
}

Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: TKarn am 27.05.2018 | 11:38
Danke für den Tipp. Ich hoffe, ich habe nächste Woche etwas Zeit, mich damit zu beschäftigen.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 31.05.2018 | 13:49
So, da das ja nachgefragt wurde, habe ich mir die Daten für die Eberron-Ebenen aus dem Source Code für den Calculator bei Wizards gezogen. Die Monde sind da auch irgendwie kodiert, aber daraus bin ich nicht schlau geworden.

Ich präsentiere also den Eberron-Kalender mit Sonnenjahr und Ebenen.

case class EberronCalendar(days : TimeUnit = CommonDays.days){

  lazy val weeks = 'week of days withNames("Sul","Mol","Zol","Wir","Zor","Far","Sar")

  lazy val months = 'month of (weeks, 4)

  lazy val years = 'year of months withNames(
    "Zarantyr","Olarune","Therendor",
    "Eyre","Dravago","Nymm",
    "Lharvion","Barrakas","Rhaan",
    "Sypheros","Aryth","Vult"
  )


  lazy val solarCalendar = Calendar(years) setTimestampZero 998

  // Name, Orbit, RemainsNotable, StartingPosition

  private val planeData = Vector(
    ("Danvi",134400,33600,50400),
    ("Dolurrh",33600,336,8559),
    ("Fernia",1680,28,1344),
    ("Irian",1008,10,420),
    ("Lamannia",364,7,94),
    ("Mabar",1680,3,422),
    ("Risia",1680,28,505),
    ("Shavarath",12096,336,4032),
    ("Syrania",3360,1,841),
    ("Thelanis",75600,2352,20076),
    ("Xoriat",2352000,336,588168)
  )

  def planeNames = planeData.map(_._1)

  lazy val planesFactory = Satellites.withPhases(("Remote","Waxing"),("Coterminous","Waning"))

  /**
    * The planes orbiting the world of Eberron as a CalendarSystem.
    * Except for Dal Quor, which is always remote, and Kythri which is utterly random.
    */

  lazy val planes : Vector[Calendar] = planeData.map{
    case (name,orbit,remainsNotable,startingPosition) =>
      {
      val phase = if (startingPosition < orbit/2) 1 else 2
      val day = startingPosition % (orbit/2)

      planesFactory.make(name.toLowerCase,orbit,days,remainsNotable) setTimestampZero (0,phase,day)
      }
    }


  lazy val eberronCalendar : Calendar = planes.foldLeft (CalendarSystem(Vector(solarCalendar )))
    { case (sys: Calendar,simple: Calendar) => sys synchronise simple}

}

Zu dem Zweck habe ich gleich eine kleine Fabrik programmiert, die eben solche kreisenden Objekte macht.

Dazu gibts jetzt die Möglichkeit, einem Kalender berechnete Werte hinzuzufügen. Wenn man z.B. Kalenderwochen haben will, die Informationen aus zwei Zyklen brauchen (also Jahreszyklus und Wochenzyklus), oder sonstige Informationen einem Datum hinzufügen will.

Ansonsten diverse Korrekturen in den Beispielen, jetzt im Repository.
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: Skeeve am 11.09.2022 | 12:58
[So, betätige ich mich auch mal als Thread-Nekromant...]

Es hat etwas gedauert diesen Thread hier auf Tanelorn wieder zu finden, aber vor ein paar Tagen hatte ich sofort an diese Diskussion gedacht und mich gefragt ob irgendwer der damals hier Schreibenden zufällig hier (einfach mal draufklicken) (https://fantasy-calendar.com/) involviert ist?
Titel: Re: Covella - Fantasy-Kalender - DSL für beliebige Systeme von Zeitmessung
Beitrag von: 1of3 am 11.09.2022 | 12:59
Also ich nicht.