Jump to content
migo315

Coaster Platform

Recommended Posts

Oder bei den Übersetzungen machen wir nen mittel Ding. Ich hatte schon mal hier in diesem Thread über den Unterscheid der "statischen" und "dynamischen" Übersetzungen geredet. Statische Übersetzungen machen mit Abstand das meiste im Projekt aus. Jeder Text ist fast eine statische Übersetzung, die wieder verwendet wird und unter https://crowdin.com/project/coastercloud gepflegt werden kann. Statische Übersetzungen sind für mich per se OK. Ich übersetze etwas einmal und kann es immer wieder verwenden. Auch sogut wie alle Attribute sind statische Übersetzungen.

 

Die dynamischen Übersetzungen sind wirklich "Freitexte". Also welche, die konkret individuell nur auf den Park / Attraktion geschrieben werden. Davon gibt es nicht viele. Und aktuell kann man diese auch nicht in verschiedenen Sprachen hinterlegen. Jeweils für Parks und Attraktionen sind es "nur" folgende Bereiche:

- Beschreibung (die Kurzbeschreibung)
- Thema (ein Feld in dem man das Thema beschreibt wie "Western Stadt")
- Besonderheiten (die Sammlung der Besonderheiten wie "Ältester Coaster Deutschlands")
- Historie (Bei speziellen Events wie "2015 abgebrannt")

 

Ggfs. nehmen wir dann erstmal nur die dynamischen raus. Also komplett und beschränken die Pflege auf alles, was nicht lokalisiert werden muss oder über statische Übersetzungen funktioniert. Würde in diesem konkreten Fall bedeuten, dass die 4 Felder oben wegfallen würden. Wobei man Historie zumindest teilweise auch mit statischen Übersetzungen hinbekommt (sowas wie Eröffnet, Geschlossen etc).

 

 

Bei allen was ich hier offen diskutiere  stellt sich mir immer der Gedanke: Was bringt das Projekt weiter? Und aktuell habe ich das Gefühl, dass das Thema dynamische lokalisierung mich sehr ausbremst. Würde ein (temporär) wegfallen solcher Felder ggfs. den Fokus auf die restlichen Felder erhöhen? Oder nimmt es zuviel Attraktivität raus? Wäre es vll besser erstmal weniger Anzubieten aber dafür stärker auf die Pflege zu gehen? Das sind so Fragen, die ich mir aktuell Stelle.

Edited by migo315 (see edit history)

Share this post


Link to post
Share on other sites

Ich würde meine App über kurz oder lang schon mehrsprachig anbieten wollen. Daher wären korrekt gepflegte Übersetzungen natürlich eine schöne Sache. Oder wenigstens englisch und als Alternative deutsch. Hab meine App jetzt mal im Play Store platziert. Wenn jemand Interesse hat, kann er bescheid geben. Zurzeit ist diese noch im internen Test-Track, bis ich den Namen  usw. finalisiert habe.

Share this post


Link to post
Share on other sites
1 minute ago, migo315 said:

Habe leider kein Android mehr im Haus zum testen. Weißt du, wann ca die App komplett veröffentlichst? Ab dem Zeitpunkt darf ja defintiv kein Breaking Change mehr in der API vorkommen.

Kann sie auch für IOS anbieten, ist kein Thema - kostet mich nur Geld 😛 Die Veröffentlichung warte ich noch ab, da der Name im Augenblick auch sehr an Dein Projekt angelehnt ist (Coaster Cloud) und das sicher nicht ganz so in Ordnung ist. Es sollen auch noch eine Suchfunktion einfließen. Danach würde ich sie veröffentlichen und mal sehen, was so für Vorschläge der Anpassung kommen. Im Moment ist sie wirklich nur da, um zu zeigen, welche Daten man bekommen kann.

Share this post


Link to post
Share on other sites
vor 4 Minuten schrieb Tommy:

Die Veröffentlichung warte ich noch ab, da der Name im Augenblick auch sehr an Dein Projekt angelehnt ist (Coaster Cloud) und das sicher nicht ganz so in Ordnung ist.

 

Ja, bitte ruhig was anderes nehmen. Coaster Cloud soll nur die Platform heißen. Alles andere sind eigenständige Produkte, die nur Daten daraus ziehen. Ich mache das selber auch nicht anders. Der Alexa Skill, den ich geschrieben habe, heißt deswegen "Park Guide": https://www.amazon.de/migo-Park-Guide/dp/B07WRGM736/

 

Vor 2 Wochen habe ich auch mal mit ner App rumgespielt. Das Projekt nannte ich "Themepark Companion".

Wobei das wirklich nur zum "rumspielen" war. Ich hab gar nicht die Zeit neben Coaster Cloud noch irgendwelche andere Dinge zu entwickeln. Das überlasse ich dann euch 😉

Auch den Alexa Skill will ich eigentlich irgendwann mal abgegeben.

 

vor 8 Minuten schrieb Tommy:

Kann sie auch für IOS anbieten, ist kein Thema - kostet mich nur Geld

 Das nervt mich selber auch. Einmalig 99 $ wäre ich ja noch einverstanden. Aber jährlich finde ich da schon nervig. Zumindest für Anbieter for kostenlosen Apps könnte die da entgegegen kommen. Aber Apple eben ...

Share this post


Link to post
Share on other sites

Ich habe heute mal testweise ein wenig angebunden, um ein Gefühl zu bekommen. Und bin ehrlich gesagt bisher begeistert. Es fühlt sich "sauberer" an, weil man sich wirklich alles ziehen kann was man will ohne weiteren Belast.

 

Bisher alles nur lokal. Aber ich denke das ich die nächste Tage die GraphQL Schnittstelle Online habe. Dann können wir ja einmal zusammen evaluieren, was zukünftig sinnvoller ist. Beide Schnittstellen (REST und GraphQL) will ich zwecks Wartung nicht behalten. Es wird sich dann Entscheiden müssen, auf welche wir setzen.

Bildschirmfoto 2019-10-19 um 14.17.45.png

Share this post


Link to post
Share on other sites

Also wenn Du Dir die Mühe machst, dann präferiere ich die GraphQL-Schnittstelle definitiv, weil ich mir da alles so zusammenstellen kann, wie ich das möchte. Wichtig ist wie gesagt nur, dass es ausführlich dokumentiert ist. Gib einfach bescheid, wenn die Schnittstelle online ist. Dann stelle ich meine App noch um, bevor ich sie veröffentliche.

Share this post


Link to post
Share on other sites

Testweise schon etwas online: https://coaster.cloud/graphiql

 

Um die Wartezeiten aller Parks (für die wir LIVE Daten haben) abzufragen, kann zum Beispiel diese Abfrage genutzt werden:

Zitat

{
  allParks(filter: "tags.name:has_waiting_times") {
    park {
      name
      waitingTimes(sort: "minutes.desc") {
        name
        minutes
      }
    }
  }
}

 

 

Sowas wäre mit der REST API nicht möglich. Da müsste man jeden Park einzeln Abfragen.

 

Aber Wichtig: Das was online ist, habe ich in 2 Stunden gebaut. Es ist nicht fertig oder groß durchdacht. Es war lediglich um ein wenig damit "warm" zu werden. Daher noch nicht dagegen entwickeln, da sich Felder und Co sicherlich in den nächsten paar Tagen ändern werden.

Share this post


Link to post
Share on other sites

Das sieht sehr gut aus. Wichtig finde ich, dass noch Bedingungen gesetzt werden können. Also zum Beispiel Wartezeiten eines bestimmten Parks (via ID o. ä.), Wartezeiten größer als x Minuten,... und das auch bei anderen Elementen wie Attraktionen. Dort fände ich es zum Beispiel sehr cool, wenn man nach Attraktionen filtern könnte, die für Personen ab 100cm genutzt werden können o. ä.

Share this post


Link to post
Share on other sites
vor 9 Stunden schrieb Tommy:

lso zum Beispiel Wartezeiten eines bestimmten Parks (via ID o. ä.), Wartezeiten größer als x Minuten

 

Sehr gut! Bisher filter ich immer in der App anstatt bereits die API filtern zu lassen. Macht Sinn so ein Filter in der API einzubauen!

 

vor 9 Stunden schrieb Tommy:

und das auch bei anderen Elementen wie Attraktionen. Dort fände ich es zum Beispiel sehr cool, wenn man nach Attraktionen filtern könnte, die für Personen ab 100cm genutzt werden können o. ä. 

 

Das geht je bereits über die REST API. Wenn man zum Beispiel alle Attraktionen vom Phantasialand haben möchte, die man 100cm und einem Alter von 4 Jahren fahren darf, funktioniert folgende REST URL: https://api.coaster.cloud/parks/f7328b4a-3308-4823-b4b6-58fb9a254199/attractions?filter=regulation(100,4)

 

Alles, was die REST API kann, würde natürlich auch die GraphQL API dann können. Alles ändere wäre ja sonst witzlos. In der GraphQL API habe ich die Attraktionen mal (mit Namen) ebenfalls testweise umgesetzt. Die Abfrage der Größenbestimmung sieht dann so aus:

 

Zitat

{
  park(id: "f7328b4a-3308-4823-b4b6-58fb9a254199") {
    name,
      allAttractions(filter: "regulation(100,4)") {
        attraction {
          name
        }
      }
  }
}

 

 

Oder man möchte nur die aktuellen Wartezeiten vom Phantasialand:

Zitat

{
  park(id: "f7328b4a-3308-4823-b4b6-58fb9a254199") {
    name,
      waitingTimes(sort: "minutes.desc") {
        name
        minutes
      }
  }
}

 

Wie erwähnt: Setzt euch noch nicht mit der Syntax fest. Ich "spiele" gerade nur rum. Die finale Fassung wird wohl erst Mitte / Ende der Woche fest stehen. Langsam fang ich aber an GraphQL immer mehr zu lieben 🙂

Share this post


Link to post
Share on other sites

Für die vollständige Umsetzung der GraphQL werde ich wohl noch ein wenig länger dauern. Ich muss bei manchen Sachen echt noch ausloten, was wie am Besten umgesetzt wird. So sieht mein Plan aus:

 

- Die GraphQL wird in den nächsten Tagen immer weiter ausgebaut.

- Die REST API bleibt bis zum offiziellen "Release" der GraphQL ebenfalls bestehen

- Nach Release der GraphQL wird die REST API entfernt.

- Ich werde morgen bereits mit einem fetten Hinweis daraus aufmerksam machen, dass die REST API deprecated ist und mit der in Entwicklung befindlichen GraphQL ausgetauscht wird.

 

Ich plane die GraphQL bis zum 3.November fertig zu haben und zu releasen.

 

Mittlerweile habe ich einige Verbindungen gesetzt. Wenn man Efteling abfragt, kann man dazu nun auch die Wartezeiten (Queues) abfragen. Und zu jeder Queue die verknüpfte Attraktion (Attraction !== Queue, da eine Attraktion mehrere Queues haben kann). Die Abfrage sieht dann so aus:

 

Zitat

{
 park(id: "49f00560-9b8d-4c11-a3ed-f548192ef5d9") {
    name,
      state {
      label {
        de
      }
    }
    waitingTimes {
      name,
      minutes
      attraction {
        name
      }
    }
  }
}

 

Die "lokalisierung" von übersetzbaren Texten überlege ich so zu lösen, dass der Entwickler einfach die Sprache auswählt (siehe state.label.de im Beispiel oben). In der REST API hat der Entwickler immer die Sprache als Query Parameter einmal gesetzt. Zwar muss der Entwickler so an diversen Stellen die bevorzugte Sprache angeben, kann dafür flexibel an jeden Knoten entscheiden ob er deutsch oder englisch oder beides haben will.

Share this post


Link to post
Share on other sites

Den großteil der Park- und Attraktiondaten ist mittlerweile abgreifbar: https://api.coaster.cloud/playground

 

Die lokalisierung habe ich nochmal angepasst. Statt eine Ebene runter zu gehen, kann man die Sprache als Argument mitgeben. Wird keine Sprache angegeben, wird als Standard "englisch" genommen. Beispiel um den Status vom Phantasialand zu bekommen:

 

1765771914_Bildschirmfoto2019-10-29um22_11_22.thumb.png.25dce76d481b7f89c63b12bd931b15a3.png

 

1700995539_Bildschirmfoto2019-10-29um22_11_34.thumb.png.1e15744362e6bc770c0381950da07551.png

 

Ich habe dies angepasst, da ich stäker mit Argumenten arbeiten möchte in Zukunft. Eine Idee wäre zum Beispiel, dass der Entwickler bei Attributen (zb. die Höhe einer Attraktion) die Einheit angeben kann. Statt Meter zum Beispiel die Höhe in Fuß (auch: fiktives Beispiel):

Zitat

query {
  park(id: "f7328b4a-3308-4823-b4b6-58fb9a254199") {
    name,
    attributes {
      height(unit: "feet") {
        value
      }
    }
  }
}

 

Habt ihr Lust euch mal den aktuellen Stand (siehe https://api.coaster.cloud/playground) anzusehen und Feedback zu geben? Passt das für euch? Ist etwas unklar dokumentiert?

 

Edited by migo315 (see edit history)

Share this post


Link to post
Share on other sites

Von meiner Seite aus finde ich das gut. Später nice to have wäre eine Dokumentation, in der steht, welche Arten von Daten abgefragt werden können. Damit man nicht alle Objekte durchsuchen muss. Und vllt auch eine Art Changelog, damit man weiß, wenn neue Felder hinzugekommen oder ältere Felder weggefallen sind. Und was mir auffällt ist, dass eine Abfrage dieser Art doch relativ langsam ist:
 

{ parkCollection(itemsPerPage: 25) { parks { id, name, slug, } } }
 

Aber hier optimierst Du sicher noch.

Share this post


Link to post
Share on other sites
vor 10 Stunden schrieb Tommy:

Und was mir auffällt ist, dass eine Abfrage dieser Art doch relativ langsam ist:

 

Uiuiui, als ich das heute morgen direkt nach deiner Nachricht getestet habe, ist mir schon die Kinnlade runtergefallen. Die Antwortzeit lag bei ~3 Sekunden. Kurios: Die REST Api war weiterhin zügig. Dabei verwenden beide den identischen Code unter der Haube. Letztendlich lag die Ursache daran, dass die GraphQL API einen PHP Warning geschmießen hat. Und die werden nach Sentry gesendet. Wenn der Fehler also bei 25 Parks auch 25 mal Auftritt, wird dies 25 mal an Sentry gesendet. Und das hat die Performance runtergezogen.

 

Ich habe den PHP Warning gelöst, jetzt liegt die GraphQL wieder bei den ähnlichen Geschwindigkeit wie die REST Api.

Share this post


Link to post
Share on other sites
Am 31.10.2019 um 07:40 schrieb Tommy:

Aber hier optimierst Du sicher noch.

 

Habe heute mal was gemacht. Die REST API und die bisherige GraphQL API hat die Daten immer live aus der Datenbank gezogen, verarbeitet und ausgegeben. Ab heute werden die Daten aus der GraphQL aber bereits vorab verarbeitet und serialisiert gespeichert. Bei Abfragen wird daher keine einzige Datenbank Query mehr ausgeführt. Die Such Engine gibt das seralisierte Ergebnis zurück, welches dann nur noch ausgegeben werden muss. Das steigert die Performance. Hier der Vergleich:

 

REST API: 700 - 800 ms im Schnitt

Alte GraphQL: 300 - 500 ms im Schnitt

Aktuelle GraphQL: 100 - 200ms im Schnitt

 

Damit lässt sich arbeiten. Im November werde ich vermutlich auch den Hoster wechseln und auf eine Machine mit mehr Power gehen. Dann könnte sich der Wert auch noch verbessern.

 

Anmerkung: Sobald man Wartezeiten in der GraphQL abfragt sind die Zeiten eher bei ~400ms. Dann werden auch Datenbank Abfragen gemacht, da diese Daten noch nicht in der Such Engine gespeichert werden.

Share this post


Link to post
Share on other sites

Heute habe ich mich dem Thema Sortierung, Filterung und Facetten (Auswahlmöglichkeiten für Filter) gewidmet. Bisher war es so, dass ich 1:1 die Syntax erwarte, welche meine Such Engine benötigt. Ich habe diese quasi nur weitergegeben. Das hatte zwei Vorteile: Es war mega flexibel, da quasi jedes Feld aus der Such Engine frei zur Verfügung stand und ich musste keine "Zwischenschicht" einbauen. Nachteil war aber, dass es dadurch X mögliche Kombinationen gab die ich nicht dokumentieren wollte und das jede Änderung in meiner Such Engine ggfs. die oder andere Abfrage verfälscht.

 

Beispiel Sortierung:

Wenn man nach Name Sortieren möchte, musste man bisher über die REST API die Sortierung via Query Parameter mitgeben:

https://api.coaster.cloud/parks?sort=name.keyword.desc

"name.keyword" ist dabei das Feld in der Such Engine. Mal davon abgesehen, dass ja eigentlich nur ich die Feldnamen aus meiner SuchEngine kenne, könnte das Feld theoretisch auch jederzeit umbenannt werden. Uncool für Entwicker. In Zukunft will ich diese "flexibilität" auflösen und tatsächlich alle Sortierungen hart definieren. In GraphQL dann als ENUM darstellen. So kann jeder Entwickler über die GraphQL Doku leicht sehe, welche Sortiermöglichkeiten es gibt und kann bei der Syntax keine große Fehler machen (dank Validierung und Autocomplete). So stelle ich mir dies vor:

525713404_Bildschirmfoto2019-11-02um20_58_37.png.545e66697f3f261c5a5de1a707faa70b.png

 

Das gleiche auch bei Facetten. Hier war jedes Feld möglich und man musste 1:1 den Feldnamen aus der SuchEngine verwenden. Beispiel:

https://api.coaster.cloud/parks?facet[]=address.country.translation.de&facet[]=types.translation.de

Auch das möchte ich mit ENUMS lösen. Dieses Beispiel, um die Liste aller Länder und Park Typen zu erhalten, würde dann ca so aussehen:

590494657_Bildschirmfoto2019-11-02um20_59_02.png.a0d2b2bda339e211369eb43eb97d67c1.png

Und Filter ähnlich. Auch da definiere ich die Filtermöglichkeiten demnächst vor. Statt so ...

https://api.coaster.cloud/parks?filter[]=address.country.code:"DE"

... dann so um alle Parks aus Deutschland zu erhalten:

860221156_Bildschirmfoto2019-11-02um20_58_22.thumb.png.0609631de77a0db11d6af808e59ddda8.png

 

Der Vorteil: Alle Sortier- Filter- und Facettenmöglichkeiten sind fest definiert. Dadurch sind diese auch Dokumentiert (samt Validierung und Autocomplete). Und alle drei sind nicht mehr hart an der SuchEngine gefesellt, so dass interne Änderungen in der SuchEngine (oder gar der Austausch der SuchEngine) zu keine Veränderungen in der API führt.

 

Je mehr ich mit GraphQL arbeite, desto mehr merke ich, dass für eine so große öffentliche API diese weitaus geeigneter ist als REST.

 

Share this post


Link to post
Share on other sites

Nur zur Info: In den letzten Tagen sowie den nächsten Tagen wird man nicht viel von mir hören. Ich plane einen Serverumzug und werde leider(!) meinen aktuellen Hoster heroku.com verlassen. Die letzten Tage habe ich mehrere Hoster gestetet und den Umzug vorbereitet. Da mache ich die nächsten Tage auch weiter. Daher wird hier diese Woche nicht viel passieren.

Share this post


Link to post
Share on other sites

Serverumzug ist durch. Das Filterhandling habe ich nochmal angepasst und vereinfacht. Wenn ich zum Beispiel nach Achterbahnen von Vekoma suche, die man ab mindestens 120cm Größe fahren darf und sich in einem Radius von 50km meiner aktuellen Position befinden, sieht so eine Abfrage wie folgt aus:

 

487281994_Bildschirmfoto2019-11-09um00_21_48.thumb.png.e9e940b23e7651e943b6de004f46bc43.png

 

 

Share this post


Link to post
Share on other sites

Die API hat nun den offiziellen Namen Open Coaster Interface (OCI -  https://oci.coaster.cloud/). Klingt einfach außergewöhnlicher als "API". 😄

 

Bisher haben wir immernoch "offene Baustellen" bei der Übersetzung für folgende Felder:

Kurzbeschreibung, Besonderheiten, Feld "Thema" und Historie

Das sind alles Freitextfelder.

 

Ich will dies endlich abschließen und gedenke folgende Anpassungen:

- Kurzbeschreibung kann zukünftig separat für englisch und für deutsch gepflegt werden. Zukünftig können bis zu 500 Zeichen (anstatt wie bisher: 255) pro Sprache geschrieben werden.

- Besonderheiten wird komplett entfernt. Eine Besonderheit einer Attraktion / Park kann in der Kurzbeschreibung erwähnt werden (ala "Erste Achterbahn Deutschlands" etc)

- Thema wird komplett entfernt. Das Thema kann in der Kurzbeschreibung erwähnt werden (ala "Moviepark ist ein Freizeitpark zum Thema Film und Hollywood")

- Historie wird auf bestimmte Ereignisse eingeschränkt / alle Freitextfelder werden entfernt.

 

Somit gibt es dann nur ein einziges Freitextfeld wo je nach Sprache separat gepflegt werden muss (Kurzbeschreibung). Die Beiden Felder Thema und Besonderheiten können, soweit ich die bisherigen Daten mir angesehen habe, in der Regel mit einem Nebensatz auch in der Kurzbeschreibung erwähnt werden. Die Historie wird "geführter", da der Contributor nur noch aus einer Handvollen "Typen" wählen kann und es keine Freitextfelder mehr gibt. Die ein oder andere Historie könnte dadurch kürzer werden.

 

Hat da irgendjemand große Bedenken oder ähnliches? Grundsätzlich bedeutet dies ja nicht, dass dies nicht alles wieder mal eingebaut wird. Sofern mal eine "größere" Community mit vielen Contributor aus verschiedenen Länder am Projekt teilnnimmt und Daten pflegt, wären viele dieser Freitextfelder vermutlich kein Problem. Aber solang eben nur eine kleinere Gruppe pflegt, sollten wir diesen zusätzlichen Aufwand erstmal vermeiden.

 

Edited by migo315 (see edit history)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.