Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

SteinBP — Application de gestion de tournois de beer pong

v3.0

Présentation

SteinBP est une application web mobile-first conçue pour organiser et suivre des tournois de beer pong. Elle gère l'ensemble du cycle de vie d'un tournoi : inscriptions, création des brackets, saisie des scores en temps réel avec règles spéciales, et un système de progression RPG complet avec rangs, XP et badges — entièrement personnalisable depuis l'interface d'administration.

L'application est accessible depuis n'importe quel navigateur et installable sur mobile en tant que PWA.

La version courante est affichée discrètement en bas à droite de l'application. Pour activer l'incrément automatique du patch à chaque commit dans un nouveau clone, exécuter une fois :

npm run hooks:install

Une version déjà modifiée manuellement (pour une évolution mineure ou majeure) est conservée telle quelle par le hook.


Nouveautés v3 🆕

La version 3 ajoute un mode Défi hors tournoi, l'attribution des tricks au joueur qui les réalise et un palmarès repensé.

⚔️ Mode Défi (1v1)

Un match rapide entre deux joueurs, en dehors de tout tournoi. On choisit l'adversaire (compte lié ou invité), le vainqueur et les tricks. Les défis alimentent les tricks et l'XP au même titre que les matchs de tournoi, mais disposent d'un classement séparé (tête-à-tête par adversaire) — les titres de tournoi ne sont jamais dévalués.

🎯 Tricks attribués par joueur

La saisie de score demande désormais « Qui a fait quoi ? » : chaque trick est attribué au joueur précis qui l'a réalisé (parmi les 4 joueurs d'un match ou les 2 d'un défi). Les statistiques de tricks sont donc enfin justes — chacun ne récolte que ses propres exploits.

🆕 Deux nouveaux tricks

  • Redemption 🔥 — dernier verre rentré pour sauver le match
  • Contre son camp 🤦 — la bourde : balle envoyée dans son propre camp (ne rapporte pas d'XP)

🏆 Palmarès par joueur + filtres

Le palmarès n'est plus par équipe mais par joueur unique (agrégé sur l'ensemble de ses matchs), avec un filtre Tournois / Défis pour basculer entre les deux classements. Les joueurs liés à un compte sont cliquables vers leur profil.

Nouveautés v2

La version 2 introduit un système de méta-jeu autour des statistiques des joueurs, avec une expérience de profil entièrement repensée.

🎮 Système de progression RPG

Chaque joueur accumule de l'XP selon une formule configurable et monte en rangs (Recrue, Gobelet, Tankard, Stein, Maître…). La barre de progression et le rang sont visibles directement sur le profil.

🏅 Système de badges

27 badges débloquables répartis en 9 catégories, basés sur les statistiques du joueur : matchs joués, matchs gagnés, win rate, tournois, règles spéciales… Chaque badge a un seuil configurable et s'affiche sur le profil du joueur.

⚙️ Onglet Custom (admin)

Les admins peuvent tout personnaliser sans toucher au code :

  • Modifier les rangs (noms, emojis, seuils XP)
  • Configurer la formule XP (poids des différentes stats)
  • Créer, éditer et supprimer des badges librement
  • Réinitialiser rangs et badges indépendamment

🎯 Règles spéciales

Des règles de beer pong intégrées à la saisie des scores, qui alimentent directement les statistiques des joueurs. Depuis la v3, chaque trick est attribué au joueur qui l'a réalisé :

Règle Description
Balls Back 2 balles dans des verres différents
Game Over 2 balles dans le même verre
Rebond Balle qui rebondit avant d'entrer
Trickshot Tir avec technique spéciale
Redemption 🆕 Dernier verre rentré pour sauver le match
Contre son camp 🆕 Balle envoyée dans son propre camp (bourde)

🦸 Profil héros

Le profil joueur a été entièrement redesigné dans un style RPG : avatar hexagonal, carte héros, barre XP avec progression vers le rang suivant, grille de badges et statistiques détaillées incluant les règles spéciales.


Rôles et accès

Rôle Accès
Admin Tout : joueurs, tournois, palmarès, défis, profil, onglet Custom
Organisateur Ses propres tournois, palmarès, défis, profil
Joueur Son profil, ses tournois et leurs brackets, palmarès, défis

Fonctionnalités

Admin

  • Gestion des joueurs — valider ou refuser les inscriptions, modifier le rôle (admin / organisateur / joueur), supprimer un compte
  • Gestion des tournois — accès à tous les tournois, suppression
  • Création de tournoi — format élimination directe ou poules + arbre, nombre de tables, gobelets installés et objectif à mettre pour gagner
  • Dashboard en temps réel — suivi des matchs, assignation des tables, saisie des scores avec tricks attribués par joueur
  • Palmarès joueurs — classement des joueurs uniques, filtrable Tournois / Défis
  • Onglet Custom — personnalisation complète du système RPG (rangs, XP, badges)

Organisateur

  • Création et gestion de ses tournois
  • Inscription des équipes — ajout manuel ou liaison avec des comptes joueurs
  • Suivi en temps réel — même dashboard que l'admin pour ses tournois
  • Palmarès — accès en lecture

Joueur

  • Profil héros — avatar hexagonal, rang actuel, barre de progression XP
  • Statistiques complètes — matchs, tournois et défis (joués/gagnés), win rate, tricks (Balls Back, Rebonds, Trickshots, Game Over, Redemption, Contre son camp)
  • Défis — lancer un match 1v1 et suivre son classement tête-à-tête
  • Collection de badges — badges débloqués mis en avant, badges verrouillés en grisé
  • Historique des tournois — liste des participations avec équipe et résultat
  • Palmarès — classement des joueurs, filtrable Tournois / Défis

Système RPG

XP et rangs

L'XP d'un joueur est calculée selon une formule pondérée, configurable depuis l'onglet Custom :

XP = (matchs joués × poids_1) + (matchs gagnés × poids_2) + (tournois gagnés × poids_3)

Les défis comptent dans l'XP au même titre que les matchs de tournoi (un défi joué/gagné = un match joué/gagné).

Les rangs par défaut :

Rang Emoji XP minimum
Recrue 🍺 0
Gobelet I 🥤 5
Gobelet II 🥤 10
Tankard I 🍻 20
Tankard II 🍻 35
Stein I 🏆 50
Stein II 🏆 75
Maître 👑 100

Badges (32 par défaut)

Catégorie Badges
Matchs joués 🎯 Sniper · 🎮 Habitué · ⚔️ Guerrier · 🌟 Légende
Matchs gagnés 🥇 Vainqueur · 💪 Dominant · 👑 Roi de la table
Win rate 🎲 Tacticien · ⚡ Implacable · 🔮 Prophète
Tournois joués 🍺 Vétéran · 🎖️ Compétiteur · 🌍 Pro
Tournois gagnés 🏆 Conquérant · 💀 Inarrêtable
Balls Back 🔄 Boomerang · 🌀 Retour de flamme · 🧲 Maître du retour
Rebonds 🏓 Rebondisseur · 🦘 Kangourou · 🎯 Maestro
Trickshots 🎪 Showman · 🤹 Acrobate · 🎩 Magicien
Game Over 💥 Double Balle · 💣 Destructeur · ☠️ Terminator
Redemption 🔥 Phénix · 🛡️ Survivant · 💫 Immortel
Contre son camp 🤦 Boulet · 🃏 Saboteur

Tous les noms, emojis, seuils et catégories sont modifiables depuis l'onglet Custom.


Formats de tournoi

Élimination directe

Bracket classique : chaque défaite élimine l'équipe. L'application génère automatiquement l'arbre et gère les équipes "bye" pour les brackets non puissances de 2.

Poules + arbre final

Phase de groupes avec classement (victoires, différence de gobelets), suivie d'un bracket d'élimination directe. Le nombre de groupes et les équipes qualifiées par groupe sont configurables.


Déroulement d'un tournoi

  1. L'organisateur crée le tournoi et configure le format
  2. Les équipes sont inscrites (manuellement ou via les comptes joueurs)
  3. Le bracket / les groupes sont générés automatiquement
  4. Les matchs sont joués ; les scores sont saisis en temps réel depuis le dashboard (avec règles spéciales)
  5. Le bracket avance automatiquement jusqu'à la finale
  6. Le tournoi est clôturé, le palmarès est mis à jour et les statistiques joueurs sont recalculées

Mode Défi

Un défi est un match 1v1 joué en dehors de tout tournoi — idéal pour une partie rapide entre amis.

  1. Depuis le profil (ou l'accueil), ouvrir ⚔️ Défis → Nouveau défi
  2. Choisir l'adversaire : un joueur avec un compte lié, ou un simple nom (invité)
  3. Désigner le vainqueur et attribuer les tricks à chaque joueur
  4. Enregistrer

Les défis sont cloisonnés des tournois : ils ont leur propre classement tête-à-tête (bilan victoires/défaites face à chaque adversaire) et n'entrent jamais dans les titres de tournoi. En revanche, leurs tricks et l'XP gagnée comptent dans la progression RPG du joueur, exactement comme un match de tournoi.


Écran public

Chaque tournoi dispose d'une URL publique affichable sur grand écran ou TV pour suivre le bracket en direct, sans connexion requise.

Obtenir le lien

Depuis le dashboard d'un tournoi, un bouton 📺 Lien TV est disponible en haut à droite du header. Un clic copie automatiquement l'URL dans le presse-papier.

Format de l'URL

L'application utilisant un HashRouter, l'URL a toujours la forme :

https://votre-domaine/#/display/<id-du-tournoi>

⚠️ Le # est obligatoire — sans lui, Nginx reçoit la requête directement et retourne une erreur 404. Utilisez toujours le bouton 📺 Lien TV du dashboard pour éviter cette confusion.


Installation sur mobile (PWA)

L'application peut être installée directement depuis le navigateur :

Sur Android (Chrome)

  1. Ouvrir l'app dans Chrome
  2. Appuyer sur le menu ⋮ → Ajouter à l'écran d'accueil

Sur iPhone (Safari)

  1. Ouvrir l'app dans Safari
  2. Appuyer sur le bouton Partager → Sur l'écran d'accueil

Une fois installée, l'app se lance en plein écran sans barre de navigateur, comme une application native.


Inscription des joueurs

Les joueurs s'inscrivent via /register (email + mot de passe + pseudo). Le compte est en attente jusqu'à validation par un admin. Une fois approuvé, le joueur accède à son profil et peut être lié à des équipes dans les tournois.


Sécurité

1. Aucun compte par défaut

Aucun superuser n'est créé automatiquement : il est créé une seule fois à l'installation (voir Première installation) et se gère ensuite uniquement depuis le panel /_/.

Les anciennes versions créaient un superuser par défaut little@local.com. Sur une instance installée avec ces versions, supprimez ce compte (ou changez son mot de passe) depuis le panel → Collections → _superusers.

L'inscription publique (/register) ne peut créer qu'un compte joueur en attente : le rôle et la validation sont imposés côté serveur par les règles PocketBase.

2. Activer le MFA sur le superadmin PocketBase

Le panel /_/ donne un accès total à la base de données. Il est fortement recommandé d'y activer l'authentification à deux facteurs (TOTP) :

  1. Connectez-vous au panel PocketBase (/_/)
  2. Cliquez sur l'icône profil en bas à gauche
  3. Sélectionnez "Two-factor authentication"
  4. Scannez le QR code avec une application TOTP (Google Authenticator, Authy, 2FAS…)
  5. Confirmez avec le code généré

À partir de ce moment, chaque connexion au panel demande le code TOTP en plus du mot de passe.

3. Restreindre l'accès au panel d'administration

Le port direct de PocketBase (8091) n'est publié que sur 127.0.0.1 de la machine hôte. Pour accéder au panel sans l'exposer, passez par un tunnel SSH :

ssh -L 8091:127.0.0.1:8091 user@serveur
# puis ouvrir http://localhost:8091/_/

Le chemin /_/ reste aussi servi par le nginx de l'app : bloquez-le sur l'accès public au niveau du reverse proxy amont (BunkerWeb, etc.).

Protection contre le brute-force

PocketBase applique un rate limiting sur l'authentification, la création de compte et les demandes d'e-mail (migration enable_auth_rate_limits). L'IP client est lue dans X-Real-IP, renseigné par le nginx de l'app à partir du X-Forwarded-For du reverse proxy amont (réseaux privés uniquement). Après un déploiement, vérifiez dans le panel → Logs que les requêtes affichent bien l'IP réelle des clients et non celle du proxy.

4. Sauvegarder les données régulièrement

Toutes les données sont dans le volume Docker pocketbase_data. Pour faire une sauvegarde :

docker run --rm \
  -v steinbp-public_pocketbase_data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/pocketbase_backup_$(date +%Y%m%d).tar.gz -C /data .

Automatisez cette commande via un cron job sur votre serveur.

5. Maintenir PocketBase à jour

Les mises à jour de PocketBase corrigent régulièrement des failles de sécurité. Consultez les releases et mettez à jour PB_VERSION dans votre .env dès qu'une nouvelle version est disponible.


Stack technique

Élément Technologie
Frontend React 18 + TypeScript + Vite
Style Tailwind CSS
Backend PocketBase (SQLite + Auth + Storage)
Temps réel PocketBase Realtime (WebSockets)
Conteneurisation Docker + Nginx
PWA vite-plugin-pwa (Workbox)
Reverse proxy Externe et optionnel

Première installation

Au premier démarrage, créez le compte super-admin PocketBase une seule fois :

docker compose exec pocketbase ./pocketbase superuser create "<email>" "<mot-de-passe-long-et-unique>"

Ce compte donne accès au panel d'administration de la base de données (voir Restreindre l'accès au panel). Il n'est jamais recréé ni réinitialisé au redémarrage : les changements faits depuis le panel sont conservés.

Créer le premier utilisateur admin de l'application

Connectez-vous au panel PocketBase (/_/), ouvrez la collection users et créez un enregistrement avec les champs suivants :

Champ Valeur
email votre email
password votre mot de passe
username votre pseudo
display_name votre nom affiché
status approved
role admin

Gérer les utilisateurs suivants

Une fois connecté en tant qu'admin, tous les utilisateurs peuvent être approuvés et leur rôle modifié directement depuis l'interface de l'application — plus besoin de passer par PocketBase.


Déploiement

Docker — test local ou déploiement derrière un reverse proxy

  1. Copier le fichier d'environnement et l'éditer :

    cp .env.example .env
    Variable Description
    APP_PORT Port exposé sur la machine hôte (défaut : 80)
    VITE_POCKETBASE_URL URL de l'app accessible depuis le navigateur (ex : http://localhost)
  2. Lancer :

    docker compose up -d

L'application est accessible sur http://localhost (ou le port configuré).

En production, le reverse proxy et sa politique de sécurité restent propres à l'environnement d'hébergement. Il doit transmettre le trafic vers le service steinbp et laisser /api/ accessible à l'application. L'interface d'administration PocketBase /_/ doit être bloquée sur l'accès public.


Mettre à jour PocketBase

La version de PocketBase est définie dans le fichier .env via la variable PB_VERSION. Pour mettre à jour, modifiez cette valeur puis reconstruisez l'image :

# Dans .env
PB_VERSION=0.39.0
PB_SHA256=<sha256 de pocketbase_0.39.0_linux_amd64.zip>

Le hash se trouve dans le fichier checksums.txt de la release. Le build échoue si le fichier téléchargé ne correspond pas.

docker compose build pocketbase
docker compose up -d

Les releases disponibles sont listées sur github.com/pocketbase/pocketbase/releases.

Note : Il est recommandé de consulter le changelog avant de mettre à jour, car certaines versions peuvent introduire des changements incompatibles avec les migrations existantes.


Changelog

v3.0

  • ⚔️ Mode Défi : matchs 1v1 hors tournoi, avec classement tête-à-tête séparé
  • 🎯 Tricks attribués par joueur — la saisie de score demande « Qui a fait quoi ? », les stats de tricks sont enfin justes
  • 🆕 Deux nouveaux tricks : Redemption 🔥 et Contre son camp 🤦
  • 🏅 5 nouveaux badges (Phénix, Survivant, Immortel, Boulet, Saboteur) — 32 badges au total
  • 🏆 Palmarès par joueur unique avec filtre Tournois / Défis (fin des doublons par équipe)
  • 🥊 Stats de défis ajoutées au profil ; les défis rapportent de l'XP comme les matchs de tournoi
  • 🎲 Nombre de tables par défaut ramené à 1 à la création d'un tournoi

v2.0

  • ✨ Système de progression RPG (XP, rangs, barre de progression)
  • 🏅 27 badges débloquables répartis en 9 catégories
  • ⚙️ Onglet Custom : personnalisation complète des rangs, de la formule XP et des badges depuis l'UI
  • 🎯 Règles spéciales intégrées à la saisie des scores (Balls Back, Game Over, Rebond, Trickshot)
  • 🦸 Profil joueur entièrement redesigné (style RPG, avatar hexagonal, statistiques détaillées)
  • 🔄 Badges groupés par catégorie et triés par seuil dans l'interface admin
  • 📺 Bouton "Lien TV" dans le dashboard pour copier l'URL de l'écran public en un clic
  • 🖼️ Logo officiel affiché sur l'écran public (remplacement de l'emoji 🏓)

v1.0

  • 🏆 Gestion de tournois (élimination directe, poules + arbre)
  • 👥 Système de rôles (admin, organisateur, joueur)
  • 📊 Palmarès global et statistiques de base
  • 📺 Écran public en temps réel (/display/:id)
  • 📱 Installation PWA

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages