Page 1 sur 1

Casse tête de tri? qui relève le défi?

Posté : 30 juin 2008, 23:57
par speccy666
Aie! je suis obligé de vous poser un problème complexe...je bloque complètement malgré toute mes recherches.... et c'est rare!

J'ai des joueurs (stockés dans une table) situés sur différentes planètes (champs pseudo, score, planete)... chaque 4 jours, je vérifie les scores sur chaque planète :
je prend 1/3 des premiers en scores et je l'ai fait avancer vers la planète suivante, les 1/3 suivants restent sur la même planete, et les derniers joueurs restants reculent d'une planete.

Au niveau de l'algorithme, ce n'est pas trop compliqué...
Je crée une table tampon identique à celle d'origine.
pour chaque planète :
1) calculer le nombre de candidats sur cette planète.
2) calculer le nombre de joueurs qui montent, qui restent et qui descendent ainsi que leur rang dans la table.
3) classer les enregistrement par ordre décroissant des scores.
4) Transférer les X candidats vers une table temporaire en affectant la nouvelle planète d'arrivée.


Le problème est bien dans le concret sous MYSQL pour transférer les enregistrements et pour les UPdatés... Comment transférer des enregistrements d'un rang à un autre (ex: du 3eme au 6eme)
Comment changer(update?) le champ planete avec la nouvelle planete (update select ne fonctionne pas)...

Je vous met mon code au cas où quelques passionnées s'intéresse au pb.

//on efface l'ancienne table si elle existe  et on crée la nouvelle
$requete="DROP TABLE IF EXISTS TABLETRANSFERTGALAXIE";
$resultat=mysql_query($requete) or die(mysql_error());	
//---CREE la nouvelle  table HISTORIQUE pour les scores de GALAXIE		
$requete="CREATE TABLE IF NOT EXISTS TABLETRANSFERTGALAXIE select pseudo,scoreplanete,planete,bestplanete from statsjoueurs2 where 1=0";
$resultat=mysql_query($requete) or die(mysql_error());
//pour chaque planete en partant de la terre, on  classe et on compte le nombre de partants, de restants et de reculants
$rq="select nomplanete from listeplanetes";
$resultat=mysql_query($rq) or die(mysql_error());
while ($donnees = mysql_fetch_array($resultat)) 
{
	//selectionne tous les enregistrements d'UNE planete
	$planete=$donnees['nomplanete'];
	$rq="select count(*) as nombresurplanete from statsjoueurs2 where planete='$planete'";
	$resultatplanete=mysql_query($rq) or die(mysql_error());
	$donneesplanete = mysql_fetch_array($resultatplanete);
	//calcule le nombre de candidats au transfert sur une planete
	$nbcandidats=$donneesplanete['nombresurplanete'];
	//calcule le nombre de candidats qui montent , restent ou descendent sur les planetes.
	$nbUP=round($nbcandidats/3);
	$nbSTAY=round($nbcandidats/3);
	$nbDOWN=$nbcandidats-$nbSTAY-$nbUP;
	echo $nbUP."..".$nbSTAY."..".$nbDOWN."<br/>";
	//calcule le rang des enregistrements à aller chercher dans la table (ATTENTION: enregistrements CLASSES en ordre DECROISSANT DE SCORE PLANETE)
	$rangUP=$nbUP-1;
	$rangSTAY=$rangUP+$nbSTAY;
	//-------transfert des candidats vers la table
		//on selectionne les candidats de cette planete qui vont avancer
		$rq="select pseudo,scoreplanete,planete,bestplanete from statsjoueurs2 where planete='$planete' ORDER BY scoreplanete DESC limit 0,".$nbUP;
		$resultattransfert=mysql_query($rq) or die(mysql_error());
		while ($donneestransfert = mysql_fetch_array($resultattransfert))
		{
			$pseudojoueur=$donneestransfert['pseudo'];
			$score=$donneestransfert['scoreplanete'];
			$rq="insert into statsjoueurs2(pseudo,scoreplanete,planete) values('$pseudojoueur','$score,'uranus')";
			$transfert=mysql_query($rq) or die(mysql_error());
		}
}

Code : Tout sélectionner

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; -- -- Base de données: `questar` -- -- -------------------------------------------------------- -- -- Structure de la table `statsjoueurs2` -- CREATE TABLE `statsjoueurs2` ( `pseudo` varchar(12) NOT NULL, `departement` varchar(2) NOT NULL, `region` varchar(30) NOT NULL, `scoremois` mediumint(9) NOT NULL, `scoreannee` mediumint(8) unsigned NOT NULL, `scoremoispourcent` float(3,1) unsigned NOT NULL, `bestscoremois` mediumint(8) unsigned NOT NULL, `bestscoremoispourcent` tinyint(3) unsigned NOT NULL, `planete` varchar(8) NOT NULL, `scoreplanete` mediumint(9) NOT NULL, `bestplanete` varchar(8) NOT NULL, `nbqcmfaitmois` smallint(4) unsigned NOT NULL, `nbqcmfaitannee` smallint(5) unsigned NOT NULL, `nbqcmever` mediumint(8) unsigned NOT NULL, `nbquestionsmois` tinyint(9) NOT NULL, `nbquestionsannee` mediumint(9) NOT NULL, `nbquestionsever` mediumint(9) NOT NULL, `nbquestionsjustesmois` mediumint(9) NOT NULL, `passachetemois` tinyint(3) unsigned NOT NULL, `passacheteever` tinyint(3) unsigned NOT NULL, `visaachetemois` tinyint(3) unsigned NOT NULL, PRIMARY KEY (`pseudo`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- -- Contenu de la table `statsjoueurs2` -- INSERT INTO `statsjoueurs2` (`pseudo`, `departement`, `region`, `scoremois`, `scoreannee`, `scoremoispourcent`, `bestscoremois`, `bestscoremoispourcent`, `planete`, `scoreplanete`, `bestplanete`, `nbqcmfaitmois`, `nbqcmfaitannee`, `nbqcmever`, `nbquestionsmois`, `nbquestionsannee`, `nbquestionsever`, `nbquestionsjustesmois`, `passachetemois`, `passacheteever`, `visaachetemois`) VALUES ('A1', '', '', 55, 0, 0.0, 0, 0, 'terre', 100000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('A2', '', '', 55, 0, 0.0, 0, 0, 'terre', 200000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('A3', '', '', 55, 0, 0.0, 0, 0, 'terre', 300000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('A4', '', '', 55, 0, 0.0, 0, 0, 'terre', 400000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('A5', '', '', 55, 0, 0.0, 0, 0, 'terre', 500000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('A6', '', '', 0, 0, 0.0, 0, 0, 'terre', 600000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('A7', '', '', 0, 0, 0.0, 0, 0, 'terre', 700000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('A8', '', '', 0, 0, 0.0, 0, 0, 'terre', 800000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('B1', '', '', 0, 0, 0.0, 0, 0, 'mars', 100000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('B2', '', '', 0, 0, 0.0, 0, 0, 'mars', 200000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('B3', '', '', 0, 0, 0.0, 0, 0, 'mars', 300000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('B4', '', '', 0, 0, 0.0, 0, 0, 'mars', 400000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('B5', '', '', 0, 0, 0.0, 0, 0, 'mars', 500000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('C1', '', '', 0, 0, 0.0, 0, 0, 'jupiter', 100000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('C2', '', '', 0, 0, 0.0, 0, 0, 'jupiter', 200000, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ('essai', '', '', 0, 0, 0.0, 0, 0, 'uranus', 666, '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); -- -- Structure de la table `listeplanetes` -- CREATE TABLE `listeplanetes` ( `idplanete` tinyint(3) unsigned NOT NULL auto_increment, `nomplanete` varchar(10) NOT NULL, PRIMARY KEY (`idplanete`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ; -- -- Contenu de la table `listeplanetes` -- INSERT INTO `listeplanetes` (`idplanete`, `nomplanete`) VALUES (1, 'terre'), (2, 'mars'), (3, 'jupiter'), (4, 'saturne'), (5, 'uranus'), (6, 'neptune'), (7, 'pluton');

Posté : 01 juil. 2008, 07:07
par Patriboom
Voici une piste

//On récupère d'abord le nombre de joueurs pour chaque planetes.
$nb_joueurs = array();
     $requete1 = "SELECT ...COUNT(id) AS Combien_joueurs FROM copie_de_la_table GROUP BY planete";
while (fetch) {
     $nb_joueurs[$id_planete] = Combien_joueurs
     //On traite les premiers, en les augmentant d'une planète
     $requete2 = "UPDATE table_originale SET planete = planete + 1 WHERE PSEUDO IN (SELECT PSEUDO FROM copie_de_la_table WHERE planete = ".$Valeur_fetch." LIMIT 0, ($nb_joueurs/3))";

     //On traite les derniers, en les descendant d'une planète
     $requete3 = "UPDATE table_originale SET planete = planete + 1 WHERE PSEUDO IN (SELECT PSEUDO FROM copie_de_la_table WHERE planete = ".$Valeur_fetch." LIMIT   ($nb_joueurs/3)*2, ($nb_joueurs/3))";

}
Ensuite, on peut détruire la table de travail (copie_de_la_table), les changements ayant été faits.


Je n'ai pas soigné la présentation, il est très tard.

Posté : 01 juil. 2008, 10:08
par Berzemus
Je n'ai pas soigné la présentation, il est très tard.
ou tôt.. :D

Posté : 01 juil. 2008, 10:38
par speccy666
MErci mais Mysql ne supporte pas cette syntaxe :
 UPDATE statsjoueurs2 SET planete = 'jupiter' WHERE pseudo IN(
SELECT pseudo
FROM statsjoueurs
LIMIT 3 , 4
) 
Message d'erreur : #1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

Et c'est bien la le problème...

De plus, il ne faut pas que je ré-écrive dans la table d'origine avant la fin du classement sinon je vais prendre des gens d'une planète qui auront déjà été avancés.

Merci pour cet essai, vive le Québec! héhé!.... ceci dit je suis toujours bloqué! :cry:

Posté : 01 juil. 2008, 11:06
par Berzemus
et euh, tu as quelle version de MySQL ? (me semble pas l'avoir vue..)

Posté : 01 juil. 2008, 12:54
par speccy666
Version du client MySQL: 5.0.37

Posté : 01 juil. 2008, 13:14
par Sékiltoyai
Euh, le client ne nous intéresse pas, c'est le serveur que l'on veut...

Posté : 01 juil. 2008, 13:22
par speccy666
Ah ben disons que je suis en local là.... j'ai pas fait les test sur ma base FREE...

sinon FREE m'annonce :

# Version du serveur: 5.0.45
# Version du protocole: 10

sur la console sql.free.fr

Posté : 01 juil. 2008, 14:05
par Patriboom
Si t'as accès à la structure de la base de données, mets des planètes sous forme de valeurs numériques
Mercure = 1
Venus = 2
Terre = 3

Ce sera beaucoup plus facile à traiter.
Quand viendra le temps de l'affichage, il te suffira de puiser les équivalences dans un tableau
$Nom_planete = Array("soleil","Mercure","Venus","Terre", ...);
Si tu n'oses pas jouer dans tes données, tu n'as pas à changer le champ planete, tu n'as qu'à en ajouter un numérique. Le champ actuel ne servira plus et voilà tout.


Pour ce qui est du non-fonctionnement de planete="mercure", tu peux toujours fonctionner avec LIKE

Et si tu ne peux modifier la structure de la table, tu peux toujours travailler avec un tableau comme ci-haut pour faire les recherches aussi bien que pour traiter les données

Posté : 01 juil. 2008, 14:18
par speccy666
pour ceux qui seraient intéressés :
<?php
include("donneesconnection.php");
//onefface l'ancien fichier historique s'il n'existe pas et on crée le nouveau
$requete="DROP TABLE IF EXISTS tabletransfertgalaxie";
$resultat=mysql_query($requete) or die(mysql_error());	
//---CREE la nouvelle  table HISTORIQUE pour les scores de GALAXIE		
$requete="CREATE TABLE IF NOT EXISTS tabletransfertgalaxie select * from statsjoueurs2 where 1=0";
$resultat=mysql_query($requete) or die(mysql_error());
// pour accélérer l'indexation et les requetes multiples sur une table
//mysql_query("LOCK TABLES TABLETRANSFERTGALAXIE WRITE");
//pour chaque planete en partant de la terre, on  classe et on compte le nombre de partants, de restants et de reculants
$rq="select idplanete,nomplanete from listeplanetes";
$resultat=mysql_query($rq) or die(mysql_error());
while ($donnees = mysql_fetch_array($resultat)) 
{
	//selectionne tous les enregistrements d'UNE planete
	$planete=$donnees['nomplanete'];
	$rq="select count(*) as nombresurplanete from statsjoueurs2 where planete='$planete'";
	$resultatplanete=mysql_query($rq) or die(mysql_error());
	$donneesplanete = mysql_fetch_array($resultatplanete);
	//calcule le nombre de candidats au transfert sur une planete
	$nbcandidats=$donneesplanete['nombresurplanete'];
	//calcule le nombre de candidats qui montent , restent ou descendent sur les planetes.
	$nbUP=round($nbcandidats/3);
	$nbSTAY=round($nbcandidats/3);
	$nbDOWN=$nbcandidats-$nbSTAY-$nbUP;
	echo $nbUP."..".$nbSTAY."..".$nbDOWN."<br/>";
	//calcule le rang des enregistrements à aller chercher dans la table (ATTENTION: enregistrements CLASSES en ordre DECROISSANT DE SCORE PLANETE)
	$rangUP=$nbUP-1;
	$rangSTAY=$rangUP+$nbSTAY;
	//-------transfert des candidats vers la table TAMPON
	//cherche les noms des planetes transfert
	$index=$donnees['idplanete'];
	$idup=$index+1;
	$idplaneteup = "select idplanete,nomplanete from listeplanetes where idplanete='$idup'";
	$res=mysql_query($idplaneteup) or die(mysql_error());
	$donneesidplanete = mysql_fetch_array($res);
	$planeteup=$donneesidplanete['nomplanete'];
	$iddown=$index-1;
	$idplanetedown = "select idplanete,nomplanete from listeplanetes where idplanete='$iddown'";
	$res=mysql_query($idplanetedown) or die(mysql_error());
	$donneesidplanete = mysql_fetch_array($res);
	$planetedown=$donneesidplanete['nomplanete'];
	// précise les valeurs limite: exemple : si on recule depuis la terre, on arrive sur ...terre!
	if ($planetedown==""){$planetedown="terre";};
	if ($planeteup==""){$planeteup="pluton";};
	echo "<br/>planete UP :".$planeteup." planete STAY: ".$planete." Planete DOWN: ".$planetedown;
	
	//met les candidats en mode transfert
		$rq="update statsjoueurs2 SET transfertplanete=true";
		$a=mysql_query($rq) or die(mysql_error());	
		//on transfere tous les candidats pour cette planete dans le SAS d'embarquement--> table TAMPON
		echo "<br/>insertion dans la table GALAXIE";
		$rq="insert into tabletransfertgalaxie select * from statsjoueurs2 where planete='$planete' ORDER BY scoreplanete DESC";
		$a=mysql_query($rq) or die(mysql_error());
		echo "<br/>EFFACEMENT des mêmes enregistrements dans la table statsjoueurs2";
		//on EFFACE tous les candidats pour cette planete de la table d'origine
		$rq="delete from statsjoueurs2 where planete='$planete'";
		$a=mysql_query($rq) or die(mysql_error());		
		//modifie les DERNIERS enregistrements(+tousle reste pour le coté technique imposé) avec la valeur de la nouvelle planete atteinte
		$rq="update tabletransfertgalaxie SET planete='$planetedown' where transfertplanete=true order by scoreplanete desc limit ".$nbcandidats;
		$a=mysql_query($rq) or die(mysql_error());
		//modifie les enregistrements des joueurs qui RESTENT(+tous les autres pour le coté technique imposé) avec la valeur de la planete où ils restent
		$rq="update tabletransfertgalaxie SET planete='$planete' where transfertplanete=true order by scoreplanete desc  limit ".($nbUP+$nbSTAY);
		$a=mysql_query($rq) or die(mysql_error());
		//modifie les PREMIERS enregistrements(+tousle reste pour le coté technique imposé) avec la valeur de la nouvelle planete atteinte
		$rq="update tabletransfertgalaxie SET planete='$planeteup' where transfertplanete=true order by scoreplanete desc limit ".$nbUP;
		$a=mysql_query($rq) or die(mysql_error());	
		$rq="update tabletransfertgalaxie SET transfertplanete=false";
		$a=mysql_query($rq) or die(mysql_error());	
		echo"<br/>fini";
		
}
		//RE TRANSFERT DE TOUS LES ENREGISTREMENTS affectés par le transfert
		$rq="insert into statsjoueurs2 select * from tabletransfertgalaxie";
		$a=mysql_query($rq) or die(mysql_error());
//affichage du résultat		
$rq="select * from statsjoueurs2 order by planete desc,scoreplanete desc";
$resultat=mysql_query($rq) or die(mysql_error());
while ($donnees = mysql_fetch_array($resultat)) 
{
	echo "<br/>pseudo: ".$donnees['pseudo']."----------planete: ".$donnees['planete']."-------------score: ".$donnees['scoreplanete'];
}