Compteur de points au tennis.

Cette semaine, c'est Nicolas qui vous propose un #KataOfTheWeek : Compteur de points au tennis.

Briefing du Kata : Rappel rapide des règles :

  • Pour gagner un match, il faut gagner deux sets (trois pour certains tournois pour les hommes mais on ne va pas s'attarder là dessus).
  • Pour gagner un set, il faut gagner normalement 6 jeux.
  • On est forcé d'avoir un écart de deux points pour gagner un set. 5-5 nous envoie à 7-5 pour gagner le set.
  • En revanche, "6-6" va entraîner un tie-break. Ceci consiste à démarrer un jeu où on compte les points de 1 en 1 et le premier joueur à atteindre 7 points avec 2 points d'écart gagne le tie-break et le set par la même occasion.
  • Pour gagner un jeu il faut marquer 4 balles avec deux points d'écart.
  • Les points d'un jeu sont comptés dans l'ordre suivant: 0, 15, 30, 40
  • Si il y a "40-40", on parle d'égalité. Il faudra alors marquer deux points consécutifs pour remporter le jeu. Si un joueur marque un point, ce dernier prend l'avantage (av). Si l'adversaire marque à son tour, on retourne à "40-40".

Le but du kata consiste à partir d'une chaîne de caractères composée d'une suite de 1 et de 2, représentant les balles marquées par chaque joueur, de donner le score correspondant au format suivant:

  • "S1-S2 P1-P2 X1-X2" si le match est encore en cours
  • "Player X Win !" si on a un gagnant.

S1 = Nombre de set gagné par 1 S2 = Nombre de set gagné par 2 P1 = Nombre de jeux du set courant gagné par 1 P2 = Nombre de jeux du set courant gagné par 2 X1 = Nombre de balles du jeu courant gagné par 1 X2 = Nombre de balles du jeu courant gagné par 2

Exemple : "11111111" : "0-0 2-0 0-0" "112111111112" : "0-0 2-0 30-15" "11212212121" : "0-0 0-0 av-40" "111111111111111111112222222222222222222211112222111111" : "0-0 6-6 6-0" "111111111111111111111111111111111111111111111111" : "Player 1 Win !"

Saurez-vous résoudre le problème ?

Bon courage !


Et voici une solution proposée par l'auteur en JavaScript :

const cleanSet = partie => ({P1:{...partie.P1,J:0,X:0},P2:{...partie.P2,J:0,X:0}});

const cleanGame = partie => ({P1:{...partie.P1,X:0},P2:{...partie.P2,X:0}});

const setIsWin = partie => {
    if ((partie.P1.J > 6)||(partie.P1.J > 5 && (partie.P1.J - partie.P2.J) > 1)) {
        return cleanSet({...partie, P1: {...partie.P1, S:partie.P1.S+1}});
    } else if ((partie.P2.J > 6)||(partie.P2.J > 5 && (partie.P2.J - partie.P1.J) > 1)) {
        return cleanSet({...partie, P2: {...partie.P2, S:partie.P2.S+1}});
    }
    return partie;
}

const gameIsWin = (partie) => {
    let min = 3;
    if (partie.P1.J === 6 && partie.P1.J === partie.P2.J) {
        min = 6;
    }
    if (partie.P1.X > min && (partie.P1.X - partie.P2.X) > 1) {
        return cleanGame({...partie, P1: {...partie.P1, J:partie.P1.J+1}});
    } else if (partie.P2.X > min && (partie.P2.X - partie.P1.X) > 1) {
        return cleanGame({...partie, P2: {...partie.P2, J:partie.P2.J+1}});
    }
    if (min === 3 && partie.P1.X > min && partie.P1.X === partie.P2.X) {
        return {P1:{...partie.P1,X:min},P2:{...partie.P2,X:min}};
    }
    return partie;
}

const printPoints = (x) => {
    switch(x) {
        case 4: return 'av';
        case 3: return '40';
        case 2: return '30';
        case 1: return '15';
        default: return '0';
    }
    return '0';
}

const printCurrentGame = (partie) => {
    if (partie.P1.J === 6 && partie.P1.J === partie.P2.J) {
        return `${partie.P1.X}-${partie.P2.X}`;
    }
    return `${printPoints(partie.P1.X)}-${printPoints(partie.P2.X)}`;
}

const stringifyScore = (stringOfPoints) => {
    let partie = {P1:{S:0,J:0,X:0},P2:{S:0,J:0,X:0}};
    let current;
    for (i in stringOfPoints) {
        current = stringOfPoints[i];
        if (current === '1') {
            partie = {...partie,P1:{...partie.P1,X:((partie.P1.X)+1)}}
        } else {
            partie = {...partie,P2:{...partie.P2,X:((partie.P2.X)+1)}}
        }
        partie = setIsWin(gameIsWin(partie));
        if (partie.P1.S === 2 || partie.P2.S === 2) {
            return `Player ${current} Win !`
        }
    }
    return `${partie.P1.S}-${partie.P2.S} ${partie.P1.J}-${partie.P2.J} ${printCurrentGame(partie)}`
}

Votre équipe TakiVeille