Zum Inhalt springen

Offene Algorithmen & Code

Jeder Algorithmus, der dein Erlebnis beeinflusst, ist hier dokumentiert — in verständlicher Sprache, mit den tatsächlichen Formeln und direkten Links zum Quellcode.

Wenn ein Algorithmus entscheidet, wer dein Profil sieht, wie deine Zuverlässigkeit bewertet wird oder welche Sessions in deinem Feed erscheinen — diese Entscheidungen beeinflussen reale Begegnungen. Eine Strafe für späte Absagen ist nicht nur eine Zahl; sie ist der Unterschied zwischen einem vollen Tisch und einem abgesagten Spieleabend.

Wir glauben, dass du es verdienst zu verstehen, wie jedes Bewertungs- und Matching-System funktioniert. Nicht in vagen Marketing-Begriffen — in echter Mathematik, mit den realen Gewichtungen, Schwellenwerten und Design-Kompromissen erklärt.

Jeder Abschnitt unten dokumentiert eines unserer Algorithmensysteme. Du findest die Formel, die Überlegungen hinter wichtigen Entscheidungen und einen direkten Link zum Quellcode auf GitHub. Wenn etwas nicht stimmt, kannst du ein Issue eröffnen.

Spieler-Zuverlässigkeitswert

Der Spieler-Zuverlässigkeitswert ist eine auf Teilnahme basierende Kennzahl, die deine tatsächliche Historie an Spieltischen widerspiegelt — nicht deine Beliebtheit, nicht deine sozialen Verbindungen, nur ob du auftauchst, wenn du es sagst.

So funktioniert's

Score = (weighted_sum / game_count) × 100

Begrenzt auf Bereich [0%, 100%]

Gewichtung der Anwesenheitsstatus
Status Spieler-Gewichtung Host-Gewichtung
Teilgenommen +1.0 +1.0
Späte Absage (<24h) −0.3 −1.2
Nicht erschienen −1.0 −1.5
Entschuldigt 0.0 0.0
Früh abgesagt (>24h) 0.0 0.0

Stufen-Klassifikation

Zuverlässig

≥ 95% und ≥ 5 Spiele

Aktiv

≥ 5 Spiele (jeder Punktestand)

Neuling

< 5 Spiele

Design-Entscheidungen

  • Gastgeber erhalten strengere Strafen für späte Absagen und Nichterscheinen, da sie jeden angemeldeten Teilnehmer dieses Spiels betreffen, nicht nur sich selbst.
  • Troll-Resistenz: Die Anwesenheit wird durch einen gewichteten Konsens der Meldungen geklärt (siehe Anwesenheits-Auflösung) — ein einzelner Melder kann also keinen Status festlegen. Erst eine Teilnahme-Schwelle und eine Mehrheit müssen zustimmen, bevor eine Strafe greift.
  • Werte werden bei jeder Anwesenheitsänderung vollständig neu berechnet (nicht delta-basiert), um Korrektheit zu garantieren und Drift zu verhindern.

Anwesenheits-Auflösung

Wenn ein Spiel endet, können Gastgeber und Teilnehmer jeweils einen Anwesenheitsbericht für dieselbe Person abgeben — und sie sind sich nicht immer einig. Die Anwesenheits-Auflösung führt diese Berichte in einem einzigen, verbindlichen Status zusammen, der in den Spieler-Zuverlässigkeitswert einfließt. Es ist ein Konsens-System mit einer bewussten Tendenz zu „Teilgenommen": eine Abwesenheit muss durch eine Mehrheit bewiesen werden, nie einfach angenommen.

Auflösungsmethoden

Früher Konsens

Jeder genehmigte Teilnehmer hat einen Bericht abgegeben, sodass der Status bei Spielende sofort feststeht — ohne Wartezeit.

Zeitablauf

Wenn die Meldungen ausbleiben, schließt sich das Spiel automatisch nach Ablauf des Zeitfensters und klärt jeden Spieler anhand der vorliegenden Berichte.

Manuell

Eine Administratorin oder ein Administrator kann die Anwesenheit direkt auflösen, wenn ein Streitfall eine menschliche Entscheidung erfordert.

Wie ein Status entschieden wird

1
Teilnahme-Schwelle

Mindestens die Hälfte der übrigen Teilnehmer muss berichten. Darunter gilt der Spieler als „Teilgenommen".

2
Entschuldigt-Übersteuerung durch Gastgeber

Wenn der Gastgeber eine Person als „Entschuldigt" markiert, setzt sich das durch — der Gastgeber ist nur für Entschuldigungen maßgeblich.

3
Nicht-erschienen-Mehrheit

Mehr als die Hälfte der gewichteten Stimmen muss auf „Nicht erschienen" lauten, damit eine Abwesenheit festgehalten wird.

4
Standard: Teilgenommen

Alles andere — ein Gleichstand, keine Berichte oder ein Solo-Spiel — wird als „Teilgenommen" aufgelöst.

Berichte können bis zu 72 Stunden nach Spielende abgegeben werden; Spiele schließen 12 Stunden nach ihrer geplanten Endzeit automatisch ab.

Design-Entscheidungen

  • Standard Teilgenommen: Kein einzelner Bericht kann einen Spieler jemals bestrafen. Eine Abwesenheit erfordert eine bewiesene Mehrheit.
  • Der Gastgeber kann entschuldigen, aber nur der Konsens kann ein „Nicht erschienen" festlegen — die Gastgeber-Befugnis ist bewusst begrenzt.
  • Berichte werden gewichtet, sodass unzuverlässige Melder weniger Einfluss haben. Die genauen Schwellen zum Missbrauchsschutz werden bewusst nicht veröffentlicht.

SL-Bewertungen & Rezensionen

SL-Bewertungen aggregieren Community-Feedback für Spielleiter in einen Durchschnittswert und eine Rezensionsanzahl. Nur veröffentlichte Rezensionen fließen in die Aggregation ein — gemeldete oder versteckte Rezensionen werden vollständig ausgeschlossen.

So funktioniert's

Durchschnittsbewertung = COALESCE(AVG(rating), 0)

Anzahl Bewertungen = COUNT(*) WHERE status = 'published'

Kompetenzabzeichen = TOP 3 Tags nach Häufigkeit in veröffentlichten Bewertungen

Nur Rezensionen mit Status „veröffentlicht" sind eingeschlossen. Gemeldete oder versteckte Rezensionen werden von allen Berechnungen ausgeschlossen.

Design-Entscheidungen

  • Nur veröffentlichte Rezensionen zählen für den Durchschnitt. Gemeldete oder versteckte Rezensionen werden ausgeschlossen, um Manipulation zu verhindern und Fairness zu gewährleisten.
  • Aggregate werden neu berechnet, wenn eine Rezension erstellt oder gelöscht wird oder ihren Status ändert (z. B. wenn eine gemeldete Rezension versteckt oder wiederhergestellt wird). So bleibt der angezeigte Wert mit dem aktuellen veröffentlichten Bestand synchron.

Spieler-Entdeckung

Die Spieler-Entdeckung schlägt dir nahegelegene Spieler basierend auf Geschmackskompatibilität und sozialer Überschneidung vor. Sie nutzt deine Spielsystem-Präferenzen, Vibe-Präferenzen, Team-Mitgliedschaften und sozialen Verbindungen, um Leute zu finden, mit denen du gerne spielst. Die Ergebnisse werden von einem Hintergrund-Job vorberechnet und aus dem Cache geliefert für schnelle Ladezeiten.

Verarbeitungspipeline

1
Phase 1: Geohash-Kachel-Expansion

Führt eine einzelne Abfrage über die 4-stellige Geohash-Kachel (~20 km) und die umgebende 3-stellige Kachel (~100 km) gleichzeitig aus, sodass Stadt- und Regionalnachbarn zusammen erfasst werden. Blockierte Nutzer und bestehende Folgen werden per SQL-Unterabfrage ausgeschlossen. Der geografische Kandidaten-Pool ist auf 50 begrenzt, um den Speicher zu schonen.

2
Phase 2: Geschmacksbasierte Ergänzung

Wenn der Betrachter Lieblingsspielsysteme hat, werden zusätzliche Kandidaten mit denselben Präferenzen einbezogen — auch außerhalb des geografischen Radius — um Geschmacksaffinität abzubilden.

3
Phase 3: SQL-First-Bewertung

Eine einzelne SQL-JOIN-Abfrage berechnet alle Überschneidungen (gemeinsame Spielsysteme, Vibes, Teams und gegenseitige Folgen) direkt in der Datenbank. Dadurch wird das Laden großer Datenmengen in PHP vermieden. Die Datenbank liefert höchstens 100 bewertete Zeilen zurück.

4
Phase 4: Bewertung

Berechnet Geschmacksähnlichkeit (Jaccard auf Spielsystemen + Vibes) und soziale Überschneidung (Team-Überschneidung + gegenseitige Folgen). Ergebnisse sind datenschutzbewusst: versteckte Felder reduzieren verfügbare Signale.

5
Phase 5: Zwischengespeicherte & paginierte Ergebnisse

Ergebnisse werden von einem Hintergrund-Job vorberechnet und pro Betrachter und Geohash-Kachel 5 Minuten lang zwischengespeichert. Die Seite liest nur aus dem Cache — wenn der Cache leer ist, wird ein „Wir suchen noch"-Status angezeigt, während der Job läuft. Paginiert mit 12 pro Seite.

So funktioniert's

Geschmack: J(A, B) = |A ∩ B| / |A ∪ B|

  Computed on game systems + vibes, averaged

Sozial: (Team-Überschneidung + gegenseitiges Folgen) / Komponenten

Zusammengesetzt:

  if taste & social: score = taste × 0.7 + social × 0.3

  if taste only: score = taste

  if social only: score = social

Gewichtung der Bewertungskomponenten
Komponente Gewichtung (beide verfügbar)
Geschmacksähnlichkeit 0.7
Soziale Überschneidung 0.3

Wenn nur ein Signaltyp verfügbar ist, erhält er 100% Gewichtung.

Design-Entscheidungen

  • Datenschutzbewusste Neugewichtung: Wenn ein Kandidat versteckte Felder hat (Spielsysteme, Vibes, Teams), werden diese Signale von der Bewertung ausgeschlossen und die verbleibenden Signale erhalten anteilig mehr Gewicht.
  • Blockierte Nutzer werden vollständig vom Kandidatenpool ausgeschlossen — sie erscheinen nie als Entdeckungsergebnis.
  • Wenn alle Signale versteckt sind (nur Standort sichtbar), erscheint der Kandidat mit „In der Nähe" als einzigem Treffergrund, damit die UI trotzdem etwas Sinnvolles anzeigt.

Session-Empfehlungen

Session-Empfehlungen schlagen dir Spiele und Kampagnen vor, die zu deinen Präferenzen passen. Sie nutzen einen zweistufigen Ansatz, um die besten Treffer zuerst anzuzeigen, ohne Nutzer zu benachteiligen, die keine Vibe-Präferenzen festgelegt haben.

Two-Query-Ansatz

1
Erweiterte Abfrage (Primär)

Findet Sessions, die deine Lieblings-Spielsysteme UND Lieblings-Vibes teilen. Das sind die stärksten Treffer.

2
Fallback-Abfrage

Findet Sessions nach Lieblings-Spielsystemen unabhängig von Vibes. Zeigt relevante Sessions auch ohne Vibe-Überschneidung.

Ergebnisse werden nach Typ+ID dedupliziert, wobei erweiterte Ergebnisse zuerst angezeigt werden. Maximal 12 Empfehlungen gesamt.

Präferenzauflösung

erlaubt = (Favoriten + implizierte_Favoriten) − vermiedene

Boosted: erlaubt UND Lieblingsvibes

Fallback: erlaubt (alle Vibes)

Regeln zur Präferenzauflösung
Regel Verhalten
Basis-Spiel favorisiert Erweiterungen werden zu impliziten_Favoriten
Explizit vermieden Hat immer Vorrang vor Favorit oder implizit
Vibe-Exklusivität Einen favorisieren vermeidet automatisch seinen Partner

Design-Entscheidungen

  • Favorisierte Basisspiele schließen automatisch ihre Erweiterungen als „implizite Favoriten" ein — du musst nicht jede Erweiterung einzeln favorisieren.
  • Explizite Meidungs-Präferenzen haben immer Vorrang vor Favoriten oder impliziten — wenn du ein System meidest, bleibt es ausgeschlossen, auch wenn es eine Erweiterung eines Favoriten ist.
  • Vibe-Gegenseitigkeit: Einen Vibe zu favorisieren meidet automatisch seinen Partner (z. B. „Kompetitiv" meidet automatisch „Kooperativ").

Treffen

Ein Treffen (Gathering) ist eine leichtere, systemübergreifende Session wie ein Brettspiel-Abend. In den Entdeckungs-Feeds sind Treffen auf etwa eines pro Seite begrenzt und werden bei gleichem Datum knapp unter fokussierten Einzelsystem-Spielen eingeordnet, damit sie nie spezifische Spiele verdrängen. In deinen Empfehlungen erscheint ein Treffen, sobald eines der angebotenen Systeme deinen Favoriten entspricht — behandelt wie jedes andere Spiel.

Näherungs-Engine

Die Näherungs-Engine betreibt geografische Abfragen zum Finden nahegelegener Sessions, Spieler und Veranstaltungsorte. Sie nutzt einen zweiphasigen Ansatz: einen schnellen Bounding-Box-Filter gefolgt von präziser Haversine-Abstandsberechnung.

Zweiphasen-Ansatz

1
Phase 1: Bounding-Box-Vorfilter

Nutzt einen zusammengesetzten (Breitengrad, Längengrad) B-Baum-Index für schnelle Zeileneliminierung. Das Rechteck ist die kleinste Box, die den Suchkreis enthält — ihre Ecken reichen über den Kreis hinaus, sodass nichts übersehen wird.

2
Phase 2: Haversine-Abstand

Wendet die Haversine-Formel für präzise Abstandsberechnung an und filtert Ergebnisse auf den exakten Radius.

So funktioniert's

d = 2R × arcsin(√(

  sin²(Δlat / 2) +

  cos(lat₁) × cos(lat₂) × sin²(Δlng / 2)

))

wobei R = 6371 km (Erdradius)

Geohash-Kachelgrößen

Geohash-Präzisionsstufen und ungefähre Kachelgrößen
Präzision Ungefähre Größe Verwendung
4 chars ~20km × 20km Städtisches Caching
5 chars ~4.9km × 4.9km Nachbarschaftsebene
6 chars ~0.6km × 1.2km Veranstaltungsortebene

Hub-Ergebnisse werden pro Geohash-Kachel (5-stellig ≈ 4,9 km × 4,9 km) mit 15-minütiger TTL zwischengespeichert.

Design-Entscheidungen

  • Die Bounding-Box ist das kleinste Rechteck, das den Suchkreis umschließt (ihre Ecken ragen über den Kreis hinaus). Die Haversine-Formel filtert dann auf den genauen Radius — dieser zweiphasige Ansatz nutzt den B-Baum-Index für Geschwindigkeit.

Standort-Offenlegung & Datenschutz

Jede Adresse und Entfernung, die du siehst — auf einer Spiel-, Kampagnen- oder Veranstalterseite — wird von einem einzigen Service entschieden. Die Standort-Offenlegung staffelt, wie viel von einem Ort sichtbar wird, basierend auf der Art des Ortes und deinem Verhältnis zum Gastgeber. Datenschutz ist der Standard, nicht die Ausnahme.

Adress-Stufen

Exakt

Vollständige Straßenadresse

Stadt

Nur der Ortsname

Region

„In deiner Nähe" (geohash-basiert)

Keine

Nichts sichtbar (blockierter Betrachter oder nicht auflösbarer Ort)

Entscheidungsmatrix (private Orte)

Dein Verhältnis zum Gastgeber Angezeigte Adresse
Gastgeber oder genehmigter Teilnehmer Exakt
Freund oder Teammitglied Stadt
Fremder oder Gast Region
Blockiert Keine

Verifizierte gewerbliche Veranstaltungsorte (Cafés, Spieleläden, Bibliotheken, Gemeindezentren, Conventions, Bars) zeigen jedem ihre exakte Adresse — sie sind öffentliche Räume.

Entfernungsanzeige

Verifizierter gewerblicher Ort

Genaue Entfernung (z. B. „4,2 km entfernt")

Jeder andere Ort

Auf das nächste 5-km-Raster gerundet (z. B. „≈ 5 km entfernt"), mit einer 5-km-Schwelle — exakte Positionen lassen sich nicht trilaterieren.

Design-Entscheidungen

  • Fail-closed: Wenn sich etwas nicht bestimmen lässt, offenbart der Service das Mindeste (Region oder nichts) — nie mehr.
  • Genaue Entfernungen sind verifizierten öffentlichen Orten vorbehalten. Private Orte erhalten immer eine gerasterte Entfernung, um Trilateration zu verhindern.
  • Eine öffentliche Veranstalterseite erfordert einen gewerblichen Typ, der verifiziert oder admin-verwaltet ist. „Sonstige" und typenlose Orte kommen nie infrage.

Plattform-Score

Der Plattform-Score rangiert Spielsysteme nach Community-Engagement mittels einer gewichteten Formel, die Favoriten, Spiele gesamt, Kampagnen und aktive (geplante) Sessions berücksichtigt.

So funktioniert's

score = (favorites × w₁) + (games × w₂)

      + (campaigns × w₃) + (active_games × w₄)

Typdifferenzierte Bewertungsgewichtungen
Metrik Brettspiele Pen-&-Paper-RPGs
Favoriten 10 10
Spiele gesamt 3 3
Kampagnen 5 15
Aktive Spiele (geplant) 20 10

Design-Entscheidungen

  • Brettspiele gewichten aktive Sessions am höchsten (20 Punkte), da ein aktuell geplantes Spiel das stärkste Signal für Community-Engagement ist.
  • TTRPGs gewichten Kampagnen am höchsten (15 Punkte), da laufendes Kampagnenspiel die primäre Aktivitätskennzahl für Tabletop-Rollenspielgruppen ist.

Lies den Code selbst

Jeder hier dokumentierte Algorithmus läuft aus unserem Open-Source-Repository. Klone es, prüfe es, eröffne ein Issue — es gehört dir.

Du bist offline — einige Funktionen sind möglicherweise nicht verfügbar
Wieder online