Partage
  • Partager sur Facebook
  • Partager sur Twitter

Tirage aléatoire de données

Quand le jeu de la noisette devient un vrai problème d'écureuil !

    24 novembre 2015 à 10:53:05

    Bonjour,

    Je me tourne vers vous, car après plusieurs tentatives infructueuse, je ne parvient pas à résoudre mon problème. J'ai essayé divers méthodes que je posterais plus bas, mais le résultat ne correspond pas vraiment à mes besoins. je vous explique tout.

    J'ai mis en place un petit script, qui permet de faire le jeux de la noisette. En gros, nous avons une table ou nous stockons nos utilisateurs :

    CREATE TABLE `membres` (
      `id` int(11) NOT NULL,
      `prenom` varchar(20) CHARACTER SET latin1 NOT NULL,
      `couple` varchar(5) CHARACTER SET latin1 NOT NULL,
      `email` varchar(50) CHARACTER SET latin1 NOT NULL,
      `active` int(11) NOT NULL DEFAULT '0'
    ) ENGINE=InnoDB;


    id = ID de notre utilisateur, valeur unique.
    prenom = Le prénom de l'utilisateur.
    couple = un ID par couple (Charles & Marine auront le même ID de couple).
    email = l'adresse mail de la personne.
    active = Si la personne participe ou non.

    Le concept est relativement basique en apparence, en effet, le jeux de la noisette, permet d'attribuer à un joueur (écureuil), un des autres joueurs présent dans la table (noisette). Le but étant que le joueur en question face un cadeau à sa noisette.

    J'ai essayé plusieurs solutions, mais rien n'y fait, j'ai des lignes et des lignes de résultats, alors qu'initialement, j'ai seulement 8 entrées. Par exemple :

    SELECT * FROM `membres` AS a
    LEFT JOIN `membres` AS b
    ON a.id <> b.id
    GROUP BY a.id, b.id
    ORDER BY rand()

    * Dans un premier temps, je n'ai pas pris en compte la gestion des id.couple. Seulement le fait qu'un membre ne puisse pas ce tirer lui-même au sort.

    Initialement, je pensais faire une jointure de ma même table, avec un random sur la seconde partie du tableau, pour le tirage au sort de mes utilisateurs. A savoir que j'ai besoin de l'ensemble des données présentes dans les tableau, afin de permettre la génération du mail envoyé aux participants.

    Je sais pas si mes explications sont relativement explicite, si besoin je pourrais reformuler sans problèmes =)

    Merci pour votre aide, car que j'utilise du DISTINCT ou non, le résultat est le même, de même avec des requêtes imbriqués.. A moins que je m'y prenne vraiment mal :p (De l'indulgence, le SQL n'est pas mon fort.. Je suis de l'autre coté de la barrière, je suis du réseau ^^)

    Cordialement

    -
    Edité par slam2 24 novembre 2015 à 10:56:15

    • Partager sur Facebook
    • Partager sur Twitter
      24 novembre 2015 à 13:19:26

      Bonjour,

      Ta requête va te sortir tous les couples utilisateurs possibles, en aucun cas une attribution d'une noisette par écureuil ... le GROUP BY et le ORDER BY ne servent ici strictement à rien et sont même carrément faux :)

      Ce n'est d'ailleurs pas à ta requête de faire ce tirage, et ton modèle de données ne peut stocker ce tirage en l'état ... c'est à l'application de faire le tirage et de le stocker en base ...

      Si tu veux pouvoir mémoriser les parties et leur tirage, alors il te faut retravailler ce modèle ...

      Comment travailles-tu ? PHP/MySQL ?

      • Partager sur Facebook
      • Partager sur Twitter
      Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
        19 novembre 2017 à 22:27:01

        Salut !

        Je déterre mon ancien sujet, car je me reprend dans mon scripts ^^ ! Bon, entre temps, j'ai mis en place une gestion du tirage au sort géré principalement par PHP. Avec des bonnes boucles bien dégeulasses (pas du for, while, etc.).. A coup de bon gros IF des familles, avec à la clé, en cas de mauvaise génération un header(location: index.php) pour re-générer le tirage.. Autant dire que des fois, je rencontrais des erreurs de page générés par Firefox.. x) Soit :

        		## Génération du tableau d'attribution #############
        		$bdd_return = mysqli_query($link, "SELECT * FROM membres WHERE active=1 ORDER BY prenom Asc");
        		$bdd_random = mysqli_query($link, "SELECT * FROM membres WHERE active=1 ORDER BY RAND()");
        		$_SESSION['bdd_num'] = $bdd_rows 	= mysqli_num_rows($bdd_return);
        		
        		while ($row = mysqli_fetch_array($bdd_return, MYSQLI_ASSOC)) {
        			$offerer_id[] 	= $row["id"];
        			$offerer[] 		= $row["prenom"];
        			$offerer_sexe[]	= $row["sexe"];
        			$offerer_cid[] 	= $row["couple"];
        			$offerer_aid[] 	= $row["affinitee"];
        			$offerer_mail[] = $row["email"];
        		}
        
        		while ($row = mysqli_fetch_array($bdd_random, MYSQLI_ASSOC)) {
        			$receiver[] 	= $row["prenom"];
        			$receiver_id[] 	= $row["id"];
        			$receiver_cid[] = $row["couple"];
        			$receiver_aid[] = $row["affinitee"];
        		}
        
        		## Tirage au sort des participants ##########
        		for($i = 0; $i < $bdd_rows; $i++) {
        
        			if($offerer[$i] != $receiver[$i]) {
        				if	(
        						(($offerer_cid[$i] != $receiver_cid[$i]) OR ($offerer_cid[$i] = $receiver_cid[$i] == NULL)) AND
        						(($offerer_aid[$i] != $receiver_aid[$i]) OR ($offerer_aid[$i] = $receiver_aid[$i] == NULL)) AND
        						(isset($bdd_history) AND ($receiver_id[$i] != @$ruid_history))
        					) 
        				{
        
        					$_SESSION['offerer_id'][$i] 	= $offerer_id[$i];
        					$_SESSION['offerer'][$i] 	= $offerer[$i];
        					$_SESSION['offerer_sexe'][$i] 	= $offerer_sexe[$i];
        					$_SESSION['offerer_mail'][$i] 	= $offerer_mail[$i];
        					$_SESSION['receiver_id'][$i] 	= $receiver_id[$i];
        					$_SESSION['receiver'][$i] 	= $receiver[$i];
        					
        					# Divers Conditions d'affichages
        					if(!empty($offerer_mail[$i])) { $_SESSION['email'][$i] = $offerer_mail[$i] = $offerer_mail[$i]; } else { $_SESSION['email'][$i] = $offerer_mail[$i] = "<i>N/C</i>"; }
        
        
        					echo '<tr>
        							<td style="text-align:center">'.($i+1).'</td>
        							<td>'.$offerer[$i].'</td>
        							<td>'.$offerer_mail[$i].'</td>						
        							<td>'.$receiver[$i].'</td>
        						  </tr>';
        
        				} else { header("location: index.php"); } # Erreur tirage d'un couple, ReGénération
        			} else { header("location: index.php"); } # Erreur tirage d'un même participant, ReGénération
        		echo '</br>';
        		}



        La, maintenant, je pars sur un autre concept au niveau du tirage. Je pensais faire du stockage sur du tableau multidimensionnel, avec du random, etc., ou autres.

        Array ( [0] => Array ( [0] => 1 [1] => Gauthier ) [1] => Array ( [0] => 2 [1] => Myl�ne ) [2] => Array ( [0] => 3 [1] => Marine ) [3] => Array ( [0] => 4 [1] => Charles ) [4] => Array ( [0] => 5 [1] => Guillaume ) [5] => Array ( [0] => 6 [1] => Pauline ) [6] => Array ( [0] => 7 [1] => Rachel ) [7] => Array ( [0] => 8 [1] => Florian ) ) 



        Si vous avez d'autres idées, permettant de faire un truc beaucoup plus propre, je suis preneur :p !

        Merci d'avance ;)

        -
        Edité par slam2 19 novembre 2017 à 23:07:06

        • Partager sur Facebook
        • Partager sur Twitter
          20 novembre 2017 à 11:09:05

          Bonjour,

          Bon ... ce sujet ne concerne pas vraiment ta base de données, mais plutôt la logique PHP qui va te permettre de la remplir :p

          Et je pense que tu as encore du boulot d'apprentissage en PHP :-°

          slam2 a écrit:

          Le concept est relativement basique en apparence, en effet, le jeux de la noisette, permet d'attribuer à un joueur (écureuil), un des autres joueurs présent dans la table (noisette). Le but étant que le joueur en question face un cadeau à sa noisette.

          Commençons par la base de données ... Je ne sais pas comment tu veux stocker les données, si tu veux garder l'historique des parties, si tu veux permettre à un joueur de faire plusieurs partie ... Je vais donc partir un peu large, et tu simplifieras si besoin ...

          Tu as des parties, des joueurs et des noisettes (couple de joueurs pour une partie). Cela fait trois entités donc trois tables.

          • Une partie contient plusieurs noisettes, et une noisette appartient à une seule partie.
          • Une noisette contient un joueur écureuil, et un joueur peut faire plusieurs parties comme noisette.
          • Une noisette contient un joueur noisette, et un joueur peut faire plusieurs parties comme noisette.

          Le modèle de données serait donc :

          • joueur ( id_joueur [pk], prenom, etc. ) pour stocker les joueurs
          • partie ( id_partie [pk], date_partie, etc. ) pour stocker les parties
          • noisette ( id_couple [pk], id_partie [fk], id_ecureuil [fk], id_noisette [fk], etc. ) pour stocker les couples

          Tu commences par créer tous les joueurs possibles dans la table joueur.

          Lorsque tu ouvres une partie, tu crées un enregistrement dans la table partie (avec la date par exemple) et tu récupères l'id créé avec mysqli_insert_id dans une variable $_id_partie.

          Ton programme PHP peut alors afficher la liste des joueurs possibles (par exemple avec des cases à cocher), pour que l'utilisateur puisse choisir quels joueurs vont faire cette nouvelle partie.

          Il va valider cette liste.

          Ainsi tu peux récupérer la liste des joueurs choisis et leur affecter leur noisette :

          <html>
          	<head>
          		<meta charset="utf-8" />
          	</head>
          	<body>
          <?php
          	$link = mysqli_connect( '...', '...', '...', '...' );
          	mysqli_set_charset($link, "utf8");
          	
          	if( isset( $_POST['joueurs'], $_POST['id_partie'] ) ) {
          		
          		$joueurs = $_POST['joueurs'];
          		$ecureuils = $joueurs;
          		shuffle( $joueurs );
          		$noisettes = $joueurs;
          		$couples = array();
          		
          		foreach( $ecureuils as $ecureuil ) {
          			foreach( $noisettes as $cle => $noisette ) {
          				if( $ecureuil != $noisette ) {
          					$couples[ $ecureuil ] = $noisette;
          					unset( $noisettes[$cle] );
          					break;
          				}
          			}
          		}
          		
          		$requete = mysqli_prepare( $link, "
          			INSERT INTO noisette ( id_partie, id_ecureuil, id_noisette )
          			VALUES ( ?, ?, ? );" );
          		mysqli_stmt_bind_param( $requete, "ddd", $_POST['id_partie'], $ecureuil, $noisette );
          		
          		foreach( $couples as $ecureuil => $noisette ) {
          			mysqli_stmt_execute( $requete );
          		}
          	} elseif( isset( $_POST['new'] ) ) {
          		$requete = mysqli_query( $link, "INSERT INTO partie ( date_partie ) VALUES ( NOW() );" );
          		$id_partie = mysqli_insert_id( $link );
          		$requete = mysqli_query($link, "SELECT * FROM joueur ORDER BY prenom ASC");
          		$joueurs = mysqli_fetch_all($requete, MYSQLI_ASSOC);
          ?>
          		<p>Choisissez les joueurs de la partie :</p>
          		<form method="post">
          <?php
          			foreach( $joueurs as $joueur ) {
          ?>
          			<p><input type="checkbox" name="joueurs[]" value="<?php echo $joueur['id_joueur']; ?>" /> <?php echo $joueur['prenom']; ?></p>
          <?php
          			}
          ?>
          			<p><input type="hidden" name="id_partie" value="<?php echo $id_partie; ?>" /></p>
          			<p><input type="submit" value="Créer la partie" /></p>
          		</form>
          <?php
          	} elseif( isset( $_GET['partie']) ) {
          		$requete = mysqli_prepare($link, '
          			SELECT
          				P.id_partie,
          				DATE_FORMAT( P.date_partie, "%d/%m/%Y %H:%i:%s" ) AS date_partie,
          				J1.prenom AS ecureuil,
          				J2.prenom AS noisette
          			FROM
          				partie P
          					INNER JOIN noisette N
          						ON P.id_partie = N.id_partie
          					INNER JOIN joueur J1
          						ON N.id_ecureuil = J1.id_joueur
          					INNER JOIN joueur J2
          						ON N.id_noisette = J2.id_joueur
          			WHERE P.id_partie = ?
          			ORDER BY J1.prenom ASC'
          		);
          		mysqli_stmt_bind_param( $requete, "d", $_GET['partie'] );
          		mysqli_stmt_execute( $requete );
          		mysqli_stmt_bind_result( $requete, $id_partie, $date_partie, $ecureuil, $noisette );
          		
          		while( $joueur = mysqli_stmt_fetch( $requete ) ) {
          ?>
          		<p><?php echo $ecureuil; ?> a pour noisette <?php echo $noisette; ?></p>
          <?php
          		}
          	} else {
          		$requete = mysqli_query($link, '
          			SELECT
          				P.id_partie,
          				DATE_FORMAT( P.date_partie, "%d/%m/%Y %H:%i:%s" ) AS date_partie,
          				COUNT(*) AS nb_joueurs
          			FROM
          				partie P
          					INNER JOIN noisette N
          						ON P.id_partie = N.id_partie
          			GROUP BY P.id_partie, P.date_partie
          			ORDER BY date_partie ASC'
          		);
          		$parties = mysqli_fetch_all( $requete, MYSQLI_ASSOC );
          ?>
          		
          		<form method="post">
          			<p><input type="submit" name="new" value="Créer une nouvelle partie" /></p>
          		</form>
          		<table>
          			<thead>
          				<tr>
          					<th>ID</th>
          					<th>Débutée le</th>
          					<th>Nombre de joueurs</th>
          				</tr>
          			</thead>
          			<tbody>
          <?php
          		foreach( $parties as $partie ) {
          ?>
          				<tr>
          					<td><a href="?partie=<?php echo $partie['id_partie']; ?>"><?php echo $partie['id_partie']; ?></a></td>
          					<td><?php echo $partie['date_partie']; ?></td>
          					<td><?php echo $partie['nb_joueurs']; ?></td>
          				</tr>
          <?php
          		}
          	}
          ?>
          			</tbody>
          		</table>
          	</body>
          </html>

          -
          Edité par Benzouye 20 novembre 2017 à 12:05:34

          • Partager sur Facebook
          • Partager sur Twitter
          Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
            20 novembre 2017 à 15:39:30

            Je vois vraiment pas pourquoi le faire en PHP. On peut très bien le faire directement en SQL.

            Ce que je ne comprends pas bien, ce sont les relations écureuil / noisette.

            Dans une même partie, un joueur peut-il être écureuil et noisette en même temps, pour deux joueurs différent ?

            Exemple, si j'ai les joueurs Toto, tata, titi.

            Quelles sont les associations valides ?

            écureuil   noisette
            Toto       Tata
            Titi       Toto

            Ou

            écureuil noisette
            
            Toto     Tata
            Titi     Tutu




            • Partager sur Facebook
            • Partager sur Twitter

            Tirage aléatoire de données

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown