All projects Schätzle · Write-up
Scoring a guess by its ratio to the priceEin Tipp, gemessen am Verhältnis zum Preis
Schätzle is a price-guessing game for our afternoon meeting: everyone sees the same eBay listings and guesses a price, calls higher or lower, or sorts four by price, alone or in teams. A small Node server holds the rooms and reaches every phone and the meeting room’s screen over Server-Sent Events; until its eBay keys are set, the listings are demo items.Schätzle ist ein Preisrate-Spiel für unser Nachmittags-Meeting: Alle sehen dieselben eBay-Angebote und tippen einen Preis, sagen teurer oder billiger oder sortieren vier nach Preis, allein oder in Teams. Ein kleiner Node-Server hält die Räume und erreicht jedes Handy und den Bildschirm im Besprechungsraum per Server-Sent Events; bis seine eBay-Schlüssel gesetzt sind, sind die Angebote Demo-Artikel.
schaetzle.ewolution.cloud Source
- Type
- Web appWeb-App
- Stack
- Svelte 5 · Node · Server-Sent Events
- Year
- 2026
- Code
- Public on GitHubÖffentlich auf GitHub
A round at the meeting
Schätzle is a price-guessing game for our afternoon meeting, in the spirit of Guess the Price, which the meeting already plays. Whoever starts a game gets a room with a four-letter code, a link to share and a QR code for the meeting room’s screen. There are no accounts: a name is enough, and a reload or a locked phone puts you back in your seat with your score.
The host picks a mode (below), 5, 10 or 15 rounds, 20 to 90 seconds each, a price range, the themes to draw from, jokers and teams. In a round everyone sees the same listing, its photos and its condition, and types a price; “1.250”, “12,50” and “12.50” all read as meant. You see who has locked in, never what. The round ends when everyone online has guessed or the time is up, and the real price lands on the photo as a red price tag, with every guess on a line around it.
Scored by the ratio
A guess of 20€ for a 10€ item is as far off as 200€ for 100€, so the score looks at the ratio, not the difference: 1,000 × (1 − |log₂(guess ÷ price)|), never below 0. Too high and too low by the same factor score the same, and half or double the price scores nothing. A guess within 2% earns a “Bullseye” badge; speed doesn’t count.
The line at the reveal uses the same scale, so half and double the price sit the same distance either side of it. A band marks the stretch that scores at all, guesses more than eight times off are pinned to the ends, and close guesses stack in up to three lanes instead of covering each other.
Four modes on one scale
The ratio is the classic mode. Der Preis ist heiß, the German The Price Is Right, keeps it, but a guess over the price scores nothing, so the best guess is the closest one below it. Higher or lower shows the last item with its price and asks whether the next one costs more or less; one tap answers. A right call scores 500, plus up to 500 more the closer the two prices are: 500 + 500 × max(0, 1 − |log₂(price ÷ last)| ÷ 3). A call between 40€ and 44€ is worth more than one between 40€ and 400€, and a wrong one scores nothing.
Sort deals four items and asks for them cheapest first, one tap each. Each of the six pairs in the right order earns a sixth of 1,000, so swapping two neighbours still scores 833. Prices that are compared are always at least 10% apart, so every call has an answer, and sorting takes its four items a round from the same four eBay searches: a game still costs about five calls.
Every mode works alone or in two to four teams. A team scores its players’ average each round, so a team of two can beat a team of five, and everyone’s own ranking stays beside it. A joker, up to three per player, scores a round’s full 1,000 without a guess.
On the meeting room’s screen
Every room has a second address, its link followed by /screen, for the projector or a screen shared in a call. It watches without a seat, so it never counts as a player and has no controls: the host runs the game from a phone. It sizes itself to the screen without scrolling, from 720p to 1080p: a large QR code while people join, the item and the clock during a round, then the reveal, the teams’ standings and the winner. Where the browser allows it, it keeps the display from dimming.
One room, pushed to every phone
The server holds every game in memory: rooms, players, rounds and the clock. A move is a small JSON request, and after every change each player gets the room’s whole view again over Server-Sent Events. Nothing more is needed: players send a guess every few seconds, Node has no WebSocket server built in, and SSE already runs through Cloudflare’s tunnel for Pulse. A heartbeat every 20 seconds keeps Cloudflare from dropping a quiet stream.
EventSource gives up for good after one error page, such as Cloudflare’s 502 during a deploy, so the page reconnects by itself, with a growing wait, and at once when the tab comes back. The view carries no price before the reveal. Joining returns a secret token, kept in the browser per room, that every move carries. A host gone for 15 seconds hands the seat on, an empty room is forgotten after half an hour, and a deploy ends every game in progress.
eBay’s photos through its own origin
The live source is eBay’s Browse API on ebay.de: fixed-price listings in Germany, in euros, in the chosen range, never “for parts or not working”. The themes are curated keyword lists, and a blocklist keeps out titles that have no place in a work meeting. One game costs about five calls, and the server stops itself at 4,000 a day, below eBay’s default limit.
The photos come through Schätzle’s own origin, so the Content Security Policy stays at 'self' and eBay never sees the players’ addresses. Only photos the eBay source registered are served, only from eBay’s image host, and each is forgotten after 6 hours, eBay’s limit for showing listing data.
For now, Schätzle plays without eBay. Until the keys are set, games draw from 95 made-up listings with estimated prices, each shown as an emoji on a soft colour, and the game says “Demo” wherever it matters. Setting the two keys switches to live listings without a code change, if eBay accepts them: its documentation calls production access “intended for eBay partners”.
OTTO’s red, the family’s page
The page is the family’s: Folio’s tokens, Geist and the dot field. The colours come from OTTO’s public design tokens, its red for the price and its soft colours for the players and the demo items, but there is no OTTO logo or font: it’s a game, not an OTTO product. At the reveal, a ring of red and the players’ colours runs out from the tag through the dots.
The interface is in German and English: a settings button opens Language and Theme, each following the system until you choose, and it installs to a home screen. The server has no dependencies, sends a strict Content Security Policy and forwards the visit counter, Census, without cookies.
Eine Runde im Meeting
Schätzle ist ein Preisrate-Spiel für unser Nachmittags-Meeting, angelehnt an Guess the Price, das das Meeting schon spielt. Wer ein Spiel startet, bekommt einen Raum mit einem Code aus vier Buchstaben, einen Link zum Teilen und einen QR-Code für den Bildschirm im Besprechungsraum. Konten gibt es keine: Ein Name reicht, und nach einem Neuladen oder einem gesperrten Handy sitzt man wieder auf seinem Platz, mit seinen Punkten.
Der Host wählt eine Spielart (unten), 5, 10 oder 15 Runden, 20 bis 90 Sekunden pro Runde, eine Preisspanne, die Themen, aus denen gezogen wird, Joker und Teams. In einer Runde sehen alle dasselbe Angebot, seine Fotos und seinen Zustand, und tippen einen Preis; „1.250“, „12,50“ und „12.50“ werden alle so gelesen, wie sie gemeint sind. Man sieht, wer schon getippt hat, nie was. Die Runde endet, wenn alle, die online sind, getippt haben oder die Zeit um ist, und der echte Preis landet als rotes Preisschild auf dem Foto, mit jedem Tipp auf einer Linie drumherum.
Gewertet nach dem Verhältnis
20€ für einen Artikel, der 10€ kostet, liegen genauso weit daneben wie 200€ für 100€, deshalb wertet Schätzle das Verhältnis, nicht den Abstand: 1.000 × (1 − |log₂(Tipp ÷ Preis)|), nie unter 0. Zu hoch und zu niedrig um denselben Faktor zählen gleich, und der halbe oder doppelte Preis bringt nichts. Ein Tipp, der höchstens 2 % danebenliegt, bekommt das Abzeichen „Volltreffer“; Tempo zählt nicht.
Die Linie bei der Auflösung nutzt dieselbe Skala, also liegen der halbe und der doppelte Preis gleich weit links und rechts davon. Ein Band markiert den Bereich, der überhaupt punktet, Tipps, die mehr als achtmal daneben liegen, sitzen an den Enden, und nahe beieinanderliegende Tipps stapeln sich in bis zu drei Bahnen, statt sich zu verdecken.
Vier Spielarten auf einer Skala
Das Verhältnis ist die klassische Spielart. Der Preis ist heiß behält es, aber ein Tipp über dem Preis bringt nichts, also gewinnt der nächste Tipp darunter. Teurer oder billiger zeigt den letzten Artikel mit seinem Preis und fragt, ob der nächste mehr oder weniger kostet; einmal Antippen genügt. Richtig bringt 500 und bis zu 500 mehr, je näher die beiden Preise beieinanderliegen: 500 + 500 × max(0, 1 − |log₂(Preis ÷ letzter)| ÷ 3). 40€ gegen 44€ ist mehr wert als 40€ gegen 400€, und falsch bringt nichts.
Sortieren zeigt vier Artikel, die man vom günstigsten zum teuersten antippt. Jedes der sechs Paare in der richtigen Reihenfolge bringt ein Sechstel von 1.000, zwei vertauschte Nachbarn also noch 833. Preise, die verglichen werden, liegen immer mindestens 10 % auseinander, damit jede Frage eine Antwort hat, und Sortieren nimmt seine vier Artikel pro Runde aus denselben vier eBay-Suchen: Ein Spiel kostet weiter etwa fünf Aufrufe.
Jede Spielart geht allein oder in zwei bis vier Teams. Ein Team bekommt pro Runde den Schnitt seiner Leute, so kann ein Team aus zwei eins aus fünf schlagen, und die eigene Wertung jedes Spielers bleibt daneben. Ein Joker, bis zu drei pro Person, bringt die vollen 1.000 einer Runde, ohne zu tippen.
Auf dem Bildschirm im Besprechungsraum
Jeder Raum hat eine zweite Adresse, seinen Link mit /screen dahinter, für den Beamer oder einen in der Videokonferenz geteilten Bildschirm. Sie schaut zu, ohne einen Platz zu belegen, zählt also nie als Spieler und hat keine Bedienelemente: Der Host leitet das Spiel vom Handy aus. Sie passt sich dem Bildschirm an, ohne zu scrollen, von 720p bis 1080p: ein großer QR-Code, während alle beitreten, der Artikel und die Uhr in einer Runde, dann die Auflösung, der Stand der Teams und der Sieger. Wo der Browser es erlaubt, verhindert sie, dass der Bildschirm dunkel wird.
Ein Raum, an jedes Handy geschickt
Der Server hält jedes Spiel im Speicher: Räume, Spieler, Runden und die Uhr. Ein Zug ist eine kleine JSON-Anfrage, und nach jeder Änderung bekommt jeder Spieler die ganze Ansicht des Raums neu, per Server-Sent Events. Mehr braucht das Spiel nicht: Die Spieler schicken alle paar Sekunden einen Tipp, Node hat keinen WebSocket-Server eingebaut, und SSE läuft für Pulse schon durch Cloudflares Tunnel. Ein Heartbeat alle 20 Sekunden hält Cloudflare davon ab, einen stillen Stream zu kappen.
EventSource gibt nach einer einzigen Fehlerseite endgültig auf, etwa Cloudflares 502 während eines Deploys, deshalb verbindet sich die Seite selbst neu, mit wachsender Wartezeit, und sofort, wenn der Tab wieder sichtbar wird. Vor der Auflösung enthält die Ansicht keinen Preis. Beim Beitreten gibt es ein geheimes Token, das der Browser pro Raum aufhebt und das jeder Zug mitschickt. Ist der Host 15 Sekunden weg, geht sein Platz weiter, ein leerer Raum wird nach einer halben Stunde vergessen, und ein Deploy beendet jedes laufende Spiel.
eBays Fotos über die eigene Adresse
Die echte Quelle ist eBays Browse API auf ebay.de: Sofort-Kaufen-Angebote mit Standort Deutschland, in Euro, in der gewählten Spanne und nie als defekt oder als Ersatzteil angeboten. Die Themen sind ausgesuchte Suchbegriffe, und eine Sperrliste hält Titel fern, die in einem Arbeits-Meeting nichts zu suchen haben. Ein Spiel kostet etwa fünf Aufrufe, und der Server hört bei 4.000 am Tag von selbst auf, unter eBays Standardgrenze.
Die Fotos kommen über Schätzles eigene Adresse, so bleibt die Content Security Policy bei 'self', und eBay sieht die Adressen der Spieler nie. Ausgeliefert werden nur Fotos, die die eBay-Quelle angemeldet hat, nur von eBays Bild-Server, und jedes wird nach 6 Stunden vergessen, eBays Grenze für das Anzeigen von Angebotsdaten.
Im Moment spielt Schätzle allerdings ohne eBay. Bis die Schlüssel gesetzt sind, ziehen die Spiele aus 95 erfundenen Angeboten mit geschätzten Preisen, jedes als Emoji auf einer sanften Farbe, und das Spiel schreibt überall „Demo“ dazu, wo es darauf ankommt. Die zwei Schlüssel zu setzen, schaltet ohne Codeänderung auf echte Angebote um, wenn eBay sie annimmt: Seine Dokumentation nennt den Produktionszugang „intended for eBay partners“.
OTTOs Rot, die Seite der Familie
Die Seite ist die der Familie: Folios Tokens, Geist und das Punktefeld. Die Farben kommen aus OTTOs öffentlichen Design-Tokens, sein Rot für den Preis und seine sanften Farben für die Spieler und die Demo-Artikel, aber ohne OTTO-Logo und OTTO-Schrift: Es ist ein Spiel, kein OTTO-Produkt. Bei der Auflösung läuft ein Ring aus Rot und den Farben der Spieler vom Preisschild aus durch die Punkte.
Die Oberfläche gibt es auf Deutsch und Englisch: Ein Einstellungen-Knopf öffnet Sprache und Design, beide folgen dem System, bis man wählt, und sie lässt sich auf den Home-Bildschirm legen. Der Server hat keine Abhängigkeiten, schickt eine strenge Content Security Policy und leitet den Besuchszähler Census ohne Cookies weiter.