Partage
  • Partager sur Facebook
  • Partager sur Twitter

Gérer des égalités dans un usort

Sujet résolu
    22 juillet 2021 à 12:39:53

    Bonjour,

    Je souhaiterais faire suite à un précédent sujet (ici) sans le réouvrir car ma question diffère légèrement.

    Pour remettre rapidement dans le contexte, je gère un site qui fait un suivi de parties de jeux de société, les gens entrent des parties avec des scores et ma requête trie les score avec usort pour attribuer des places et des points.

    Mon problème est quand il y a une égalité, je souhaiterais attribuer le même nombre de points aux deux joueurs mais le usort trie et donne la meilleure place au joueur qui a le pseudo qui est devant dans l'ordre alphabétique.

    Exemple : Steeve 57, Nico 57, Alex 35, Pierre 89 me renvoie Pierre 1er, Nico 2eme, Steeve 3ème, Alex 4ème. Je souhaiterais avoir Pierre 1er, Nico 2eme, Steeve 2ème, Alex 4ème.

    Je bloque et ne vois pas comment faire. Voici mon code.

    <!-- La connexion -->
    <?php include("../include/connexion_bdd.php"); ?>
    
    <?php
    
    //On crée la partie et on récupère son id
    $req = $bdd->prepare('INSERT INTO plays_parties (partie_jeu, duree_partie, nb_joueurs, partie_evenement, evenement, date_partie) VALUES(?, ?, ?, ?, ?, NOW())');
    $req->execute(array($_POST['id_jeu'], $_POST['duree_partie'], $_POST['nb_joueurs'], $_POST['partie_evenement'], $_POST['evenement']));
    
    
    //on affiche le dernier ID, ça fonctionne
    $lastid = $bdd->lastInsertId();
    
    //On ajoute les détails de la partie dans la table detail
    $resultat = $bdd->prepare('INSERT INTO plays_details (detail_partie, detail_joueur, detail_score, detail_place, detail_points, detail_coef, detail_pts_coef) VALUES(?, ?, ?, ?, ?, ?, ?)');
    
    
    // on fait une boucle sur le nombre de joueurs et on insère la ligne pour chaque joueur.
    const POINTS = [
        9 => [13, 9, 7, 4, 2, 1, 1, 1, 1],
        8 => [13, 9, 7, 4, 2, 1, 1, 1],
        7 => [13, 9, 7, 4, 2, 1, 1],
        6 => [13, 9, 7, 4, 2, 1],
        5 => [12, 8, 6, 4, 1], // quand il y a 5 joueurs, le 1er a un bonus de 13 points, le 2e : 9 points, ...
        4 => [11, 7, 5, 1], // pour 4 joueurs, le 1er obtient un bonus de 11 points, le 2e : 7 points, ...
        3 => [9, 5, 1],
        2 => [5, 1],
    ];
    
    if (isset($_POST['joueurs']) && is_array($_POST['joueurs']) /* && array_key_exists(count($_POST['joueurs']), BONUS)*/) {
        usort(
            $_POST['joueurs'],
            function ($a, $b) {
                return $b['score'] <=> $a['score'];
            }
        );
        foreach ($_POST['joueurs'] as $k => $joueur) {
            $resultat->execute([$lastid, $joueur['id_joueur'], $joueur['score'], $k + 1/*place*/, POINTS[count($_POST['joueurs'])][$k], $_POST['duree_partie'], $_POST['duree_partie'] * POINTS[count($_POST['joueurs'])][$k]]);
        }
    }
    
    // Redirection du visiteur vers la page partie créée
    header('Location: partie_enregistree.php');
    ?>
    

    Merci

    • Partager sur Facebook
    • Partager sur Twitter
      22 juillet 2021 à 13:33:44

      /*
          $scores = array_unique(
              array_column($_POST['joueurs'], 'score')
          );
      */
          usort(
              $_POST['joueurs'],
              function ($a, $b) {
                  return $b['score'] <=> $a['score'];
              }
          );
          $scores = [];
          foreach ($_POST['joueurs'] as $k => $joueur) {
              $scores[$joueur['score']] ??= $k;
          }
      //    rsort($scores);
      //    array_flip($scores);
          foreach ($_POST['joueurs'] as $joueur) {
              $index_score = $scores[$joueur['score']];
              $resultat->execute([
                  $lastid,
                  $joueur['id_joueur'],
                  $joueur['score'],
                  $index_score + 1,
                  POINTS[count($_POST['joueurs'])][$index_score],
                  $_POST['duree_partie'],
                  $_POST['duree_partie'] * POINTS[count($_POST['joueurs'])][$index_score],
              ]);
          }

      ? (pas testé, c'est peut être simplifiable et j'ai volontairement conservé en commentaires mon approche initiale)

      -
      Edité par julp 22 juillet 2021 à 16:12:28

      • Partager sur Facebook
      • Partager sur Twitter
        2 août 2021 à 10:03:48

        Bonjour,

        Je reviens vers toi après ta réponse. J'ai essayé tant bien que mal de me débrouiller seul mais en vain.

        Qu'est ce que tu entends à ta ligne 14 par ??= $k

        Il me met Parse error: syntax error, unexpected '='

        Merci

        • Partager sur Facebook
        • Partager sur Twitter
          2 août 2021 à 11:22:40

          L'opérateur ??= a été introduit par PHP 7.4.0 sinon essaie avec $scores[$joueur['score']] = $scores[$joueur['score']] ?? $k;

          -
          Edité par julp 2 août 2021 à 11:23:07

          • Partager sur Facebook
          • Partager sur Twitter
            2 août 2021 à 11:51:21

            Effectivement je suis en php 7.3

            et avec la nouvelle ligne ça fonctionne !

            Je ne comprends pas encore comment mais je vais chercher parce que j'aimerais comprendre :)

            Merci beaucoup pour ton aide

            • Partager sur Facebook
            • Partager sur Twitter
              2 août 2021 à 11:58:49

              Cette ligne associe la première place correspondante pour un score donné.

              Si je reprends ton exemple (Steeve 57, Nico 57, Alex 35, Pierre 89), ça va donner :

              $scores = [
                  89 => 0, // premier
                  57 => 1, // deuxième
                  35 => 3, // quatrième vu qu'on a précédemment 2 ex æquo
              ];

              La clé 2 (troisième) est ignorée/sautée via le ??= parce que 1 (la clé, qui correspond au deuxième) a déjà été attribuée au même score (57), il n'y a pas l'écrasement qu'on aurait eu avec une simple affectation (=)

              -
              Edité par julp 2 août 2021 à 12:00:42

              • Partager sur Facebook
              • Partager sur Twitter
                2 août 2021 à 12:53:44

                D'accord ça y est j'ai compris ! Je ne connaissais pas cette possibilité d'ignorer/sauter une clé avec ??=

                C'est très bon à savoir :) Je peux reprendre la suite du dev (je m'attaque maintenant à la création d'équipes !)

                Merci pour l'explication

                • Partager sur Facebook
                • Partager sur Twitter
                  2 août 2021 à 13:30:48

                  > Je ne connaissais pas cette possibilité d'ignorer/sauter une clé avec ??=

                  Ce n'est pas vraiment ça : ??= a pour d'affecter ce qui se trouve à droite si et seulement la variable (à gauche) est NULL (autrement dit, ne pas l'écraser si elle a déjà une valeur et que celle-ci n'est pas NULL) - sinon de ne rien faire/ne pas modifier l'opérande de gauche.

                  -
                  Edité par julp 2 août 2021 à 13:32:46

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Gérer des égalités dans un usort

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  • Editeur
                  • Markdown