Aller au contenu

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

RB-PARTIE-001 — Format fixe 2v2

  • 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

RB-PARTIE-030 — Format de score padel

  • 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.)