diff --git a/css/solar.css b/css/solar.css
index 0ed35e1..d31b0bf 100644
--- a/css/solar.css
+++ b/css/solar.css
@@ -1165,6 +1165,53 @@ input[type='range']::-webkit-slider-runnable-track {
to { transform: translateY(472.5px); }
}
+/* --- Bananenschale ------------------------------------------------------
+ Der Ostergruss. Ausgeloest wird er selten und nur waehrend der Fahrt (siehe
+ bananeVielleicht() in js/solar/skodaMQTT.js); hier steht, wie er aussieht.
+
+ Zwei Bewegungen greifen ineinander: die Schale laeuft mit der Strasse mit,
+ und wenn sie unter der Vorderachse ist, kommt der Wagen ins Schleudern. Der
+ Vorlauf der zweiten Bewegung ist deshalb kein Gefuehl, sondern gerechnet:
+ die Schale startet 40 Einheiten ueber dem Bild, die Vorderachse liegt bei
+ 97, macht 137 Einheiten - bei 437 Einheiten je Sekunde sind das 0,31 s.
+
+ Der Wagen dreht sich um seinen Schwerpunkt, nicht um die Bildmitte; ohne
+ transform-box: view-box bezoege sich transform-origin auf den Rahmen der
+ Gruppe und der Bogen saehe falsch aus. */
+.skoda-auto .bananenschale { display: none; }
+.skoda-auto.banane .bananenschale {
+ display: block;
+ animation: skoda-schale 1.5s linear;
+}
+.skoda-auto .bananenschale use {
+ fill: #e8c74a;
+ stroke: rgba(120, 92, 12, 0.75);
+ stroke-width: 0.8;
+}
+.skoda-auto .bananenschale .strunk { fill: #b8912c; }
+
+.skoda-auto.banane #wagen {
+ transform-box: view-box;
+ transform-origin: 112px 250px;
+ animation: skoda-schleudern 1.2s 0.31s ease-in-out;
+}
+
+@keyframes skoda-schale {
+ from { transform: translateY(-40px); }
+ to { transform: translateY(560px); }
+}
+
+/* Erst ein Ausbrechen nach rechts, dann das Gegenlenken, dann austrudeln -
+ in dieser Reihenfolge faengt sich ein Fahrzeug wieder. */
+@keyframes skoda-schleudern {
+ 0% { transform: rotate(0deg) translateX(0); }
+ 18% { transform: rotate(4.5deg) translateX(5px); }
+ 45% { transform: rotate(-3.5deg) translateX(-4px); }
+ 70% { transform: rotate(1.8deg) translateX(2px); }
+ 88% { transform: rotate(-0.7deg) translateX(-1px); }
+ 100% { transform: rotate(0deg) translateX(0); }
+}
+
/* --- Fahrtwind ----------------------------------------------------------
Vier Streifen neben dem Wagen, die von vorn nach hinten laufen. Sichtbar
nur, solange zeichneFahrt() dem SVG die Klasse "faehrt" gibt.
@@ -1222,6 +1269,14 @@ input[type='range']::-webkit-slider-runnable-track {
.skoda-auto .strasse .leitlinie {
animation: none;
}
+ /* Der Ostergruss faellt ganz aus: ein schleuderndes Fahrzeug ist genau die
+ Art Bewegung, die abbestellt wurde. Ausgeloest wird er hier gar nicht
+ erst - das prueft das Skript zusaetzlich. */
+ .skoda-auto.banane .bananenschale,
+ .skoda-auto.banane #wagen {
+ animation: none;
+ }
+ .skoda-auto.banane .bananenschale { display: none; }
}
.skoda-auto .rad rect { fill: rgba(18, 20, 24, 0.9); }
diff --git a/js/solar/skodaMQTT.js b/js/solar/skodaMQTT.js
index 99be232..e73ef5b 100644
--- a/js/solar/skodaMQTT.js
+++ b/js/solar/skodaMQTT.js
@@ -547,6 +547,35 @@ function zeichneAbzeichen(w) {
}
}
+/* ------------------------------------------------------------ Ostergruß */
+
+/*
+ * Ganz selten liegt eine Bananenschale auf der Fahrbahn.
+ *
+ * Geprüft wird alle 20 Sekunden, und nur während der Fahrt; die Chance liegt
+ * bei zwei Prozent. Das ist im Mittel einmal in gut sechzehn Minuten Fahrt -
+ * selten genug, dass man es kaum erwartet, und häufig genug, dass es
+ * irgendwann jemand sieht.
+ *
+ * Der Auftritt dauert anderthalb Sekunden, danach fällt die Klasse wieder ab.
+ * Wer Bewegungen abbestellt hat, bekommt ihn gar nicht erst - ein
+ * schleuderndes Auto ist genau das, was damit gemeint ist.
+ */
+const BANANE_TAKT = 20000;
+const BANANE_CHANCE = 0.02;
+const BANANE_DAUER = 1600;
+
+function bananeVielleicht() {
+ const bild = $("skodaAuto");
+ if (!bild || !bild.classList.contains("faehrt")) return;
+ if (bild.classList.contains("banane")) return; // läuft schon
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
+ if (Math.random() >= BANANE_CHANCE) return;
+
+ bild.classList.add("banane");
+ setTimeout(function () { bild.classList.remove("banane"); }, BANANE_DAUER);
+}
+
/**
* Fahrt anzeigen: Fahrtwind am Fahrzeug, Abzeichen im Kopf der Kachel.
*
@@ -559,6 +588,9 @@ function zeichneFahrt(w) {
const bild = $("skodaAuto");
if (bild) {
bild.classList.toggle("faehrt", w.faehrt);
+ // Hält der Wagen mitten im Schleudern an, bleibt sonst eine Schale auf
+ // der Fahrbahn liegen, die niemand mehr überfährt.
+ if (!w.faehrt) bild.classList.remove("banane");
}
const abzeichen = $("skodaUnterwegs");
if (abzeichen) {
@@ -1496,6 +1528,7 @@ document.addEventListener("readystatechange", function () {
ladeLadungen(); ladeKurve(); ladeFahrten(); ladeStrecke();
}, 300000);
setInterval(ladeGesundheit, 900000);
+ setInterval(bananeVielleicht, BANANE_TAKT);
// Leaflet rechnet die Kachelanordnung selbst neu, sobald es erfährt, dass
// sein Container eine andere Größe hat.
diff --git a/restricted/skoda.php b/restricted/skoda.php
index 351a2e4..9df30e0 100644
--- a/restricted/skoda.php
+++ b/restricted/skoda.php
@@ -108,6 +108,14 @@
120 Grad versetzt ein. -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -423,6 +453,8 @@
Klima und Lüftung steuern
+
+