générateur de licence avec doublon

sp4tz
Invité n'ayant pas de compte PHPfrance

03 mai 2010, 17:26

Bonjour à tous,

Je travail sur un nouveau projet et j'ai de la peine à me lancer.

Je dois générer 10'000 licences de 8 caractères en chiffre et lettre type "15HZ2A97".
Ces licences vont être envoyée pour impression et fournie avec un achat spécifique.

Le client va acheter le produit et trouver une carte avec le code pour activer son produit.

J'ai créé ce script qui me génère les codes et les transmets dans une BDD
<?php 

// Fichier de connexion à la base de donnée

// require_once('../fr/admin/Connections/xxx.php');

 

function MakeRandomLicence($length=7) {



// Déclaration des variables

$newlicence = "";

$num = array ('1', '2', '3', '4', '5', '6', '7', '8', '9');   

$alpha = array ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I','J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');

$code = array ();   





foreach ($num as $x) {

    foreach ($alpha as $y) {   

        array_push($code,"$y");   

        array_push($code,"$x");

		}

	}



for ( $i=0;$i<=$length;$i++)  

$newlicence= $newlicence.$code[array_rand($code) ];



return $newlicence; 

 

}

 



// On déclare le nombre total d'enregistrement voulu et on créé un boucle

// Inscription dans la base de donnée

for($i=1; $i<1001; $i++){

	$value = array(MakeRandomLicence());  

    	 

}$test = array_unique($value);

	foreach($test as $val){

 /* $insertSQL = "INSERT INTO `bwdb`.`keys` (`id`, `key`, `status`, `date`) VALUES (NULL, '$val','0', '')";																										 	mysql_select_db($database_xxx, $xxx);

	$Result1 = mysql_query($insertSQL, $xxx) or die(mysql_error());*/

	echo $val.'<br/>';

		}



?> 
Ce code fonctionne très bien, mais j'y rencontre un problème de taille et que je n'ai malheureusement pas trouvé de solution. Il y a pleins de DOUBLON!

J'ai essayé avec un array_unique() mais je ne dois probablement pas l'utiliser correctement.

ViPHP
ViPHP | 5462 Messages

03 mai 2010, 17:48

tu pourrais le faire direct via MYSQL grace a un HASH
$insertSQL = "INSERT INTO `keys` (`key`) VALUES (HEX(CRC32('$val' + NOW())))";
EDIT : dans $val , tu peu mettre le login de la personne par exemple :wink:

Mammouth du PHP | 672 Messages

04 mai 2010, 08:39

Bonjour.

Tu as vérifié le contenu de tes variables ?
for($i=1; $i<1001; $i++){
	$value = array(MakeRandomLicence());  
}
print_r($value); // Affiche le contenu du tableau $value
$test = array_unique($value);
Ca devrait te donner une bonne indication du problème :wink:

sp4tz
Invité n'ayant pas de compte PHPfrance

04 mai 2010, 10:56

Salut, merci pour vos réponses...

oui j'avais déjà testé le contenu vu que j'y trouve des doublons:
Array
(
[0] => U9VH6D3S
)

Array
(
[0] => ZLA4U58P
)

Array
(
[0] => K25U6E42
)

Array
(
[0] => K2O1UC49
)

Array
(
[0] => C1G8RA1L
)

Array
(
[0] => GPN893TV
)

Array
(
[0] => S7LH27M4
)


c'est supprimer les doublons que j'aimerais...

Mammouth du PHP | 672 Messages

04 mai 2010, 11:18

L'affichage du contenu, tu le fais à quel moment ?
Parce que dans ce que tu mets, on voit qu'il y a 7 Array de 1 élément :roll:

sp4tz
Invité n'ayant pas de compte PHPfrance

04 mai 2010, 13:30

ahhh ouai!!! je me suis planté dans la conception de mon array ! Merci je pense que c'est une bonne piste.

Eléphant du PHP | 422 Messages

04 mai 2010, 14:00

hello
//tableau de licence
$arrayLicence = array();
//var tmp
$tmpLicence = '';
for($i=1; $i<1001; $i++){

do{
//créer une licence
$tmpLicence =  MakeRandomLicence();
}
//temps qu'elle appartient au licence déjà faite on recommance
while(!in_array($tmpLicence,$arrayLicence)); 

$arrayLicence[] = $tmpLicence; // on la stock
         

}

print_r($arrayLicence);
nan ? j'ai pas testé :) attention au boucle infini :)

++
toujours faire une recherche sur http://www.php.net et/ou sur http://www.google.fr :)
utiliser http://ideone.com/ pour vos codes :)

sp4tz
Invité n'ayant pas de compte PHPfrance

04 mai 2010, 16:16

hum... merci beaucoup... effectivement cette apporche me semble beaucoup plus juste.

Code : Tout sélectionner

Fatal error: Maximum execution time of 60 seconds exceeded in C:\wamp\www\GarminSuisse\httpdocs\test\test.php on line 38
ligne 38 =
 array_push($code,"$y");  
qu'es tu en penses?

Eléphant du PHP | 422 Messages

05 mai 2010, 15:08

regarde du coté de set_time_limit()
toujours faire une recherche sur http://www.php.net et/ou sur http://www.google.fr :)
utiliser http://ideone.com/ pour vos codes :)

ViPHP
ViPHP | 5462 Messages

05 mai 2010, 15:16

ca changera rien la boucle est infinie...

Eléphant du PHP | 422 Messages

06 mai 2010, 15:29

ca moulline (10sec) un peut mais ca passe :))

<?php
set_time_limit(0);
$maxLoop = 10000;

function MakeRandomLicence($length=7){
	
	$car = array('a','z','e','r','t','y','u','i','o','p','q','s','d','f','g','h','j','k','l','m','w','x','c','v','b','n','1','2','3','4','5','6','7','8','9','0');
	$key = '';
	for($i=0;$i<$length;$i++){
		$key .= $car[rand(0,35)];
	}
	return $key;
}

//tableau de licence
$arrayLicence = array();
//var tmp
$tmpLicence = '';
for($i=0; $i<10000; $i++){
	$count = 0;
	do{
		//créer une licence
		$tmpLicence =  MakeRandomLicence();
		$count++;
		if($count>$maxLoop) exit('WARNING : plus de '.$maxLoop);
	}
	//temps qu'elle appartient au licence déjà faite on recommance
	while(in_array($tmpLicence,$arrayLicence));
	
	$arrayLicence[] = $tmpLicence; // on la stock
}

print_r($arrayLicence);

?>
toujours faire une recherche sur http://www.php.net et/ou sur http://www.google.fr :)
utiliser http://ideone.com/ pour vos codes :)

Mammouth du PHP | 672 Messages

06 mai 2010, 16:11

Ce n'est pas trop étonnant que ça mouline, vu que tu fais (au moins) 10 000 fois un test pour vérifier que la licence n'existe pas déjà - donc en comparant la licence créée aux X licences déjà créées.
En gros (je ne connais pas le fonctionnement exact de in_array() ), tu fais donc 1 + 2 + ... + 9999 comparaisons.
=> 49 995 000 comparaisons :shock:
Même si in_array() est optimisé, le temps de calcul est conséquent...

Il y a moyen d'optimiser un peu ton code.
Exemples :
Au lieu de comparer chaque licence créée à celles déjà dans le tableau, on fait l'opération à la fin du remplissage.

Code : Tout sélectionner

TANT QUE le tableau de licence contient moins de 10000 éléments On le remplit pour arriver à 10000 éléments On enlève les doublons (avec [b]array_unique()[/b] )
Ou en considérant que statistiquement parlant on n'aura jamais plus de 10% de doublons (par exemple) on peut créer un tableau plus gros.

Code : Tout sélectionner

TANT QUE le tableau de licence contient moins de 10000 éléments On le remplit pour arriver à 11000 éléments On enlève les doublons (avec [b]array_unique()[/b] ) FIN TANT QUE // optionnel - on peut aussi l'utiliser tel que dans la suite, en faisant des boucles de 1 à 10000 On réduit le tableau à 10000 éléments
Avec ces systèmes, tu devrais passer sous la barre de la seconde =D>

ViPHP
ViPHP | 5462 Messages

06 mai 2010, 16:17

en SQL c'est plus simple, chaque membre a son propre code

Sp4tz
Invité n'ayant pas de compte PHPfrance

11 mai 2010, 09:20

Hum... merci pour vos tuyaux... je crois que je touche au but.