Règles métier — Parties
Ce document décrit les règles métier du domaine Partie (appelée "match" dans certains contextes), cœur fonctionnel de Primatch.
Terminologie
Dans Primatch, on parle de "partie" (et non de "match"). Le format est toujours 2 contre 2 (4 joueurs). Le format "simple" (1v1) n'existe pas dans le MVP.
Création d'une partie
- Toutes les parties sont au format 2 contre 2 (4 joueurs : 2 équipes de 2)
- Le format simple (1v1) n'est pas disponible dans le MVP
RB-PARTIE-002 — Types de partie
| Type | Code | Impact sur le niveau |
| Amicale | friendly | ❌ Aucun impact sur le niveau ni la fiabilité |
| Compétitive | competitive | ✅ Impacte le niveau et le score de fiabilité |
RB-PARTIE-003 — Visibilité
| Visibilité | Description |
public | Visible par tous les joueurs, rejoignable librement |
private | Sur invitation uniquement (lien partageable ou pseudo/email) |
RB-PARTIE-004 — Environnement
indoor : Intérieur semi-covered : Semi-couvert outdoor : Extérieur
RB-PARTIE-005 — Données obligatoires à la création
| Champ | Règle |
| Date et heure | Dans le futur |
| Type | friendly ou competitive |
| Visibilité | public ou private |
| Environnement | indoor, semi-covered ou outdoor |
| Lieu | Club référencé OU adresse libre |
| Durée | 60, 90, 120, 150 ou 180 minutes |
| Intervalle de niveau | min–max (valeurs décimales entre 1.0 et 10.0) |
| Nombre de sets | 1, 2 ou 3 |
RB-PARTIE-006 — Créateur inscrit automatiquement
- Le créateur de la partie est automatiquement inscrit comme participant
Rejoindre une partie
RB-PARTIE-010 — Rejoindre dans l'intervalle de niveau
- Si le niveau du joueur est dans l'intervalle défini, il peut rejoindre directement
- Il choisit sa position parmi les emplacements disponibles (Équipe A Gauche, Équipe A Droite, Équipe B Gauche, Équipe B Droite)
RB-PARTIE-011 — Demande hors intervalle
- Si le niveau du joueur est hors de l'intervalle, il voit un bouton « Demander à participer »
- Une demande est envoyée à l'organisateur via
POST /api/v1/games/{id}/join → le joueur est ajouté avec le statut pending - L'organisateur reçoit une notification de type
participation_request - L'organisateur consulte ses demandes en attente via
GET /api/v1/games/{id}/pending-requests - Si accepté (
POST /api/v1/games/{id}/players/{userId}/approve) → le statut passe à confirmed, le joueur reçoit une notification participation_approved - Si refusé (
POST /api/v1/games/{id}/players/{userId}/reject) → le joueur est retiré de la partie et reçoit une notification participation_rejected - Si l'approbation rend la partie complète (4 joueurs confirmés), le statut de la partie passe automatiquement à
full
RB-PARTIE-012 — Positions
- Les 4 emplacements : Équipe A Gauche, Équipe A Droite, Équipe B Gauche, Équipe B Droite
- Descriptions des rôles : Gauche = Revés (revers, construction défensive), Droite = Drive (coup droit, finition offensive). Ces descriptions sont affichées dans l'interface pour aider les débutants à comprendre les conventions du padel.
- L'équipe (
team) et la position (position) sont obligatoires lors de l'inscription à une partie (POST /api/v1/games/{id}/join). L'API retourne une erreur 422 si l'un des deux champs est manquant. Le bouton « Rejoindre » depuis la liste des parties redirige vers la page de détail où le joueur sélectionne un emplacement libre avant de confirmer. - Une position déjà prise (par un joueur inscrit ou un invité) est grisée et non sélectionnable
- Un joueur peut changer de position tant que la partie n'est pas « En cours »
- Le changement s'effectue via
PATCH /api/v1/games/{id}/position avec le payload { team: "A"|"B", position: "left"|"right" }
RB-PARTIE-012b — Slots invités
- Le créateur peut ajouter des invités (joueurs non inscrits sur l'application) à la partie
- Un invité occupe un emplacement classique (équipe + position) mais est identifié par un nom libre (max 100 caractères) au lieu d'un compte utilisateur
- Les invités comptent dans le nombre total de participants (4 max)
- Seul le créateur de la partie peut ajouter (
POST /api/v1/games/{id}/guests) ou retirer (DELETE /api/v1/games/{id}/guests/{slotId}) des invités - Les invités peuvent être ajoutés dès la création (via le pré-remplissage) ou après
- Un invité est visuellement distingué des joueurs inscrits (badge « Invité », couleur accent)
RB-PARTIE-013 — Composition des équipes
- Manuelle : les joueurs choisissent eux-mêmes leur position via la modale de sélection
- Tirage au sort : déclenché par le créateur via
POST /api/v1/games/{id}/draw, répartition aléatoire des équipes et positions - Après un tirage au sort, les joueurs peuvent toujours ajuster manuellement leur position
RB-PARTIE-014 — Interface de sélection de position
- La modale de sélection affiche une vue terrain avec les 4 emplacements
- Chaque emplacement affiche soit les initiales et le nom du joueur occupant, soit une icône
+ (libre) - La position actuelle du joueur (en mode changement) est marquée « Occupée »
- Le bouton « Confirmer ma position » reste désactivé tant qu'aucun emplacement libre n'est sélectionné
- Le clic sur un emplacement libre du terrain (hors modale) déclenche directement l'inscription du joueur
Cycle de vie d'une partie
RB-PARTIE-020 — Statuts
| Statut | Description |
| Ouverte | Partie créée, en attente de joueurs (moins de 4 inscrits) |
| Complète | 4 joueurs inscrits, en attente de la date du match |
| En cours | La date/heure du match est atteinte (passage automatique) |
| Terminée | Le match est terminé, en attente de saisie du score |
| Score validé | Les 4 joueurs ont validé le score — partie archivée |
| Annulée | Partie annulée par le créateur |
stateDiagram-v2
[*] --> Ouverte : Création
Ouverte --> Complète : 4 joueurs inscrits
Complète --> Ouverte : Un joueur quitte
Complète --> EnCours : Heure du match atteinte (auto)
EnCours --> Terminée : Fin du match (manuelle ou auto +3h)
Terminée --> ScoreValidé : 4 joueurs valident le score
Ouverte --> Annulée : Annulation par le créateur
Complète --> Annulée : Annulation par le créateur
EnCours --> Annulée : Annulation par le créateur
RB-PARTIE-021 — Quitter une partie
- Un joueur peut quitter une partie avant qu'elle ne passe en statut « En cours »
- La partie repasse en statut « Ouverte » si elle n'est plus complète
- Notification envoyée au créateur et aux autres participants
RB-PARTIE-022 — Annulation
- Le créateur peut annuler la partie tant qu'elle n'est pas « Terminée »
- Notification d'annulation envoyée à tous les participants (in-app, push, email)
Score et validation
- Score par set (ex : 6-4, 7-5, 6-3)
- Le nombre de sets correspond à celui configuré lors de la création (1, 2 ou 3 sets)
- Scores de set valides :
6-0, 6-1, 6-2, 6-3, 6-4, 7-5, 7-6
RB-PARTIE-031 — Saisie du score
- N'importe quel joueur participant peut saisir le score après le match
RB-PARTIE-032 — Validation croisée (4 joueurs)
- Une fois le score saisi, les 4 joueurs reçoivent une notification pour valider
- Chaque joueur peut valider ou contester (en proposant un score alternatif)
- Si contestation → nouveau cycle de validation pour tous
- La partie passe en « Score validé » quand les 4 joueurs ont confirmé
- Timeout : 24 heures → si un joueur ne valide pas, le score est automatiquement validé
RB-PARTIE-033 — Impact sur le niveau
- Seules les parties compétitives impactent le niveau et le score de fiabilité
- Les parties amicales sont archivées dans l'historique mais sans effet sur le niveau
Réservation de piste
RB-PARTIE-040 — Types de lieu
- Club référencé : sélectionné depuis la liste des clubs (seedés ou référencés)
- Lieu libre : adresse saisie en texte libre
RB-PARTIE-041 — Réservation via l'app (clubs avec gestionnaire validé)
- Si le club a un gestionnaire validé avec des créneaux disponibles → réservation d'un créneau possible directement via l'app
- La demande est soumise à validation par le gestionnaire du club (accepted/rejected)
RB-PARTIE-042 — Piste déjà réservée
- Le joueur peut déclarer que la piste est déjà réservée (OUI/NON) pour les réservations faites hors de l'app (téléphone, site du club, etc.)