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: Von Mitspielern gemeldete Anwesenheitsereignisse tragen einen Gewichts-Multiplikator, um den Einfluss einzelner Melder zu reduzieren.
  • Werte werden bei jeder Anwesenheitsänderung vollständig neu berechnet (nicht delta-basiert), um Korrektheit zu garantieren und Drift zu verhindern.

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 ausstehende 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. Ausstehende, gemeldete oder entfernte Rezensionen werden von allen Berechnungen ausgeschlossen.

Design-Entscheidungen

  • Nur veröffentlichte Rezensionen zählen für den Durchschnitt. Gemeldete oder ausstehende Rezensionen werden ausgeschlossen, um Manipulation zu verhindern und Fairness zu gewährleisten.
  • Aggregate werden bei jeder Rezensionsänderung (Erstellen, Veröffentlichen, Zurückziehen, Löschen) neu berechnet, damit der angezeigte Wert immer aktuell ist.

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.

Verarbeitungspipeline

1
Phase 1: Geohash-Kachel-Expansion

Beginnt bei 4-stelligem Geohash (~20 km). Wenn weniger als 10 Kandidaten gefunden werden, wird auf 3-stellig (~100 km), dann 2-stellig (~500 km) erweitert. Blockierte Nutzer und bestehende Folgen werden ausgeschlossen.

2
Phase 2: Massen-Präferenzladung

Lädt Spielsystem-Favoriten, Vibe-Präferenzen, Team-Mitgliedschaften und Folge-Beziehungen für alle Kandidaten in einem einzigen Batch.

3
Phase 3: Bewertung

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

4
Phase 4: Paginierte Ergebnisse

Ergebnisse werden pro Geohash-Kachel 5 Minuten lang zwischengespeichert. 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").

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. Die Bounding-Box ist absichtlich etwas größer als der genaue Suchkreis, um sicherzustellen, dass keine Kandidaten übersehen werden.

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 ~2.4km × 4.9km Nachbarschaftsebene
6 chars ~0.6km × 1.2km Veranstaltungsortebene

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

Design-Entscheidungen

  • Die Bounding-Box ist absichtlich größer als der exakte Kreis. Die Haversine-Formel filtert dann auf den genauen Radius — dieser zweiphasige Ansatz nutzt den B-Baum-Index für Geschwindigkeit.

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