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.
Algorithmus-Verzeichnis
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%]
| 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
≥ 95% und ≥ 5 Spiele
≥ 5 Spiele (jeder Punktestand)
< 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
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.
Lädt Spielsystem-Favoriten, Vibe-Präferenzen, Team-Mitgliedschaften und Folge-Beziehungen für alle Kandidaten in einem einzigen Batch.
Berechnet Geschmacksähnlichkeit (Jaccard auf Spielsystemen + Vibes) und soziale Überschneidung (Team-Überschneidung + gegenseitige Folgen). Ergebnisse sind datenschutzbewusst: versteckte Felder reduzieren verfügbare Signale.
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
| 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
Findet Sessions, die deine Lieblings-Spielsysteme UND Lieblings-Vibes teilen. Das sind die stärksten Treffer.
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)
| 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
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.
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
| 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.
Trending & Beliebt
Trending in deiner Nähe zeigt standortbezogene Spiele-Sessions basierend auf der Teilnehmerbeteiligung in deinem geografischen Bereich.
Auswahlkriterien
| Parameter | Wert |
|---|---|
| Geografischer Bereich | Geohash-4-Kachel (~20km × 20km) (~20km × 20km) |
| Zeitraum | Nächste 14 Tage |
| Sichtbarkeit | Nur öffentliche Sessions |
| Sortierung | participants DESC, created_at DESC |
| Obergrenze | Top 5 per tile |
| Cache-TTL | 10 minutes |
Design-Entscheidungen
- Das 14-Tage-Zeitfenster verhindert, dass historisch beliebte Spiele dominieren — nur anstehende Sessions werden berücksichtigt.
- Geohash-4-Begrenzung (~20 km × 20 km) hält die Ergebnisse echt lokal, statt beliebte Spiele von der anderen Seite der Stadt anzuzeigen.
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₄)
| 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.