Zum Inhalt springen

Sprachreferenz

EZScript ist die kleine Sprache hinter jedem skriptfähigen Feld in Poker Club HQ. Diese Seite ist die Syntax; Turnierdaten ist die Liste dessen, worauf du sie richten kannst.

ArtBeispiele
Zahl10, 1.5, -20
Text"1st", " • ", "\n"
Wahr oder falschtrue, false
Liste[100, 60, 40]
Objekt{name: "Alice", chips: 12000}

Gib einem Wert mit = einen Namen und benutze dann den Namen:

places = 1 + totalBuyIns / 5

+=, -=, *=, /= und %= verändern einen bestehenden Namen an Ort und Stelle.

In einem mehrzeiligen Skript dürfen mehrere Anweisungen in einer Zeile stehen, wenn du sie mit ; trennst. Das ist in einer Vorlage nützlich, wo das ganze Skript zwischen ein Klammernpaar passen muss:

{{ cards = highHand.pokerHandToCards; cards.pokerCardsToHandName }}
KategorieOperatoren
Arithmetik+ - * / %
Vergleich== != < > <= >=
Logik&& || !

Die Rangfolge entspricht der normalen Arithmetik: * / % binden stärker als + -, danach kommen die Vergleiche, dann &&, dann \|\|. Setz im Zweifel Klammern.

+ verbindet auch Text, nicht nur Zahlen:

{{ p = chipLeaders.first; p.shortName + " — " + p.currentChips.round.toCompactDecimalString }}

if ist ein Ausdruck, liefert also einen Wert, statt nur einen Zweig auszuwählen. Du kannst es überall dort verwenden, wo ein Wert hingehört, auch mitten in einer größeren Rechnung:

if totalBuyIns < 10 { [100, 60, 40] }
else if totalBuyIns < 17 { [150, 90, 60] }
else { [180, 110, 70, 40] }
{{ "Players" + if (currentPlayerCount == 1) { "" } else { "s" } }}

Die Prüfung muss wirklich wahr oder falsch ergeben. Eine Zahl oder ein Stück Text reicht nicht: Schreib count > 0, nicht count.

Klammern um die Prüfung sind optional.

Meistens ist eine Listen-Methode wie map oder where kürzer und klarer als eine Schleife, aber Schleifen gibt es, wenn du sie brauchst:

// Über die Elemente einer Liste
for p in playersActive { … }
// Mit der Position dazu — Index zuerst, Element danach
for i, p in playersActive { … }
// Solange etwas gilt
while (n > 0) { n -= 1 }
// Zählend
for i = 0; i < 10; i += 1 { … }

break verlässt eine Schleife vorzeitig, continue springt zum nächsten Durchlauf. Die Variablen einer Schleife gehören ihr und verschwinden, wenn sie endet.

Eine Funktion schreibst du mit func, und meistens gibst du sie direkt an eine Listen-Methode weiter:

players.where(func(p) { p.bountyChipWinnings > 0 })

Gib ihr einen Namen, wenn du sie mehr als einmal brauchst:

func toName(p) { p.shortName }

Eine Funktion liefert den Wert ihrer letzten Zeile zurück, ein return gibt es nicht.

amounts = [100, 60, 40]
amounts[0] // 100
amounts.count // 3
amounts[1] = 75 // einen Eintrag ändern
player = {name: "Alice", chips: 12000}
player.name // Alice
player.chips = 15000
player.seat = 4 // ein Name, den es noch nicht gab, wird ergänzt

Objekte akzeptieren auch player["name"], was praktisch ist, wenn der Schlüssel selbst in einer Variablen steckt.

// Das ist ein Kommentar
points = ln(c + 1) / p * 10 // und das hier auch

Kommentare sind der sauberste Weg, eine alternative Formel aufzuheben, ohne sie zu löschen. Die eingebaute Punkteformel bringt zwei deaktivierte Alternativen über der aktiven Zeile mit.

FunktionBeschreibung
now()Die aktuelle Zeit, in Millisekunden
was(x), changed(x), becameTrue(x)Mit dem Stand von vor einer Sekunde vergleichen — nur in Warnungsbedingungen
round(x)Auf die nächste ganze Zahl runden
min(a, b, …), max(a, b, …)Kleinster / größter der Werte
asNumber(x), asInteger(x), asString(x)Zwischen Arten umwandeln
sqrt(x), cbrt(x), hypot(a, b)Wurzeln und Hypotenuse
exp(x), ln(x), log10(x), log2(x)Exponential- und Logarithmusfunktionen
sin(x), cos(x), tan(x)Trigonometrie, im Bogenmaß
asin(x), acos(x), atan(x)Umkehrfunktionen dazu
degToRad(x), radToDeg(x)Winkel umrechnen

PI steht als Konstante zur Verfügung.

Das sind die Eigenschaften, die aus einer nackten Zahl etwas machen, das man auf einen Bildschirm stellen kann. Schreib sie ohne Klammern.

EigenschaftMacht aus 1250Gut für
toCompactDecimalString1.25KBlinds und Chipstände
toCurrencyString$1,250Auszahlungen und Preispools
toCompactCurrencyString$1.25KGeld auf engem Raum
toPercentStringBrüche als Prozent
withOrdinalSuffix1250thPlatzierungen — 1st, 2nd, 3rd
round, ceil, floor, abs1250Eine Division aufräumen
toInt, toDouble, toStringDie Art wechseln
isEven, isOddAbwechselnde Ausgabe
isFinite, isInfinite, isNaNGegen Division durch null absichern

Die kompakten Formen behalten drei signifikante Stellen, aus 1500 wird also 1.5K, aus 1250 dagegen 1.25K. Runde vorher, wenn du ein kürzeres Ergebnis willst.

Diese lesen eine Zahl als Millisekunden, also in der Einheit, die now() und jeder …Dt-Wert verwenden. Eine Sekundenzahl braucht vorher ein * 1000.

EigenschaftBeispielausgabe (deutsch)
toTimeString20:15:00
toHMTimeString20:15
toDateString20. Juli — mit Jahr, wenn es nicht das laufende ist
toDateAndTimeString20. Juli, 20:15:00
toDateIfNotTodayAndTimeStringheute 20:15:00, an anderen Tagen mit Datum davor
toTimeDurationString0:20:00
toHMTimeDurationString0:20 — Stunden und Minuten, wobei die Sekunden abgeschnitten und nicht gerundet werden
toCompactTimeDurationString20:00
toApproximateDurationString50 Min. — eine einzige Einheit, und als einzige hier mit Wörtern in der Sprache der App

toApproximateDurationString wählt die Einheit für dich: Stunden über zwei Stunden, Minuten über zwei Minuten, darunter Sekunden. Innerhalb der Einheit wird auf die nächste gerundet, zwei Stunden fünfzig Minuten ergeben also 3 Std. Das passt zu einem Countdown, wo 0:50 mehrdeutig ist — fünfzig Minuten oder fünfzig Sekunden? — und wo die genauen Sekunden bei mehreren verbleibenden Stunden nur stören.

Die beiden Zeitspannen am Ende sind die einzigen in dieser Tabelle, die überall gleich aussehen.

{{ (secondsLeftInLevel * 1000).toCompactTimeDurationString }}
{{ now().toTimeString }}

Eigenschaften, ohne Klammern geschrieben:

isEmpty, isNotEmpty, count, length, toUpperCase, toLowerCase, toSentenceCase, toNumber, toInt

Methoden, mit Klammern geschrieben:

MethodeBeschreibung
contains(text)Kommt das darin vor?
startsWith(text), endsWith(text)Fängt es damit an oder hört es damit auf?
indexOf(text)An welcher Stelle kommt es vor? -1, wenn gar nicht
replace(from, to), replaceAll(from, to)Text ersetzen
substring(start [, end])Ein Stück davon
slice(start [, end])Dasselbe, aber negative Positionen zählen vom Ende
split(separator)In eine Liste zerlegen
strip([characters])Die Enden abschneiden

Eigenschaften: isEmpty, isNotEmpty, count, length, first, last

Methoden:

MethodeBeschreibung
map(fn)Jedes Element umwandeln
where(fn)Nur die passenden Elemente behalten
sort([keyFn])Eine sortierte Kopie, in natürlicher Reihenfolge oder nach dem, was die Funktion liefert
take(n), skip(n)Die ersten n, oder alles nach den ersten n
takeFirstWhere(n, fn), takeLastWhere(n, fn)Die ersten oder letzten n Treffer
reverse()Eine umgedrehte Kopie
reduce(fn [, initial])Alles zu einem Wert zusammenfassen
flatMap(fn)Umwandeln und die Ergebnisse dann flach machen
join([separator [, lastSeparator]])Zu Text zusammenfügen
zip(list, … [, combineFn])Element für Element mit anderen Listen paaren

Zwei davon lohnen einen genaueren Blick.

sort nimmt einen Schlüssel. Für absteigende Sortierung negierst du ihn:

players.sort(func(p) { -p.totalEliminated })

join nimmt ein zweites Trennzeichen für das letzte Element, und genau das lässt eine gesprochene Warnung menschlich klingen:

{{ e.players.map(func(p) { p.toPlayerName() }).join(", ", ", and ") }}

Bei drei Spielern liest sich das als „Alice, Bob, and Carol“ statt als „Alice, Bob, Carol“. Das letzte Trennzeichen wird genau so verwendet, wie du es schreibst, deshalb gehört das Komma mit hinein. Bei zwei Spielern ergibt es „Alice, and Bob“.

Auf Deutsch willst du hier kein Komma vor dem „und“, also join(", ", " und "). Das ergibt „Alice, Bob und Carol“ und bei zweien „Alice und Bob“.

Nimm "\n" als Trennzeichen, um jedes Element in eine eigene Zeile zu setzen. So bauen die Widgets für Auszahlungen und Knockouts ihre Spalten.

In einem Feld Wert oder TTS-text ist alles außerhalb von {{ }} wörtlich und alles darin ein Ausdruck:

Level {{ blindLevelNumber }} von {{ blindLevelCount }}

Ein Ausdruck, der fehlschlägt oder nichts liefert, steuert eine leere Zeichenkette bei.

Eine Regel solltest du kennen: Wenn jeder Ausdruck einer Vorlage leer ausfällt, gilt die ganze Vorlage als leer, und der wörtliche Text um die Klammern herum fällt mit weg. Das hier:

Ante {{ anteText }}

zeigt also gar nichts an, wenn anteText leer ist, statt ein einsames Ante stehen zu lassen. So verschwinden die eingebauten Elemente title und subtitle auf Levels, die keine haben, ganz ohne Bedingung.

Die Regel gilt nur ganz oder gar nicht. Hat eine Vorlage zwei Ausdrücke und nur einer fällt leer aus, bleibt der wörtliche Text stehen und der leere hinterlässt einfach eine Lücke.