Scoring
This commit is contained in:
parent
c4e99fccc7
commit
8ea8d66e05
|
@ -1 +1 @@
|
||||||
1747
|
1784
|
80
src/DUEL.php
Normal file
80
src/DUEL.php
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
<?php
|
||||||
|
class DUEL{
|
||||||
|
public $rank1;
|
||||||
|
public $rank2;
|
||||||
|
|
||||||
|
private $factor = 400;
|
||||||
|
|
||||||
|
public function __construct($r1,$r2){
|
||||||
|
$this->rank1 = $r1;
|
||||||
|
$this->rank2 = $r2;
|
||||||
|
}
|
||||||
|
private function get_k($rank){
|
||||||
|
if ($rank < 1000) return 80;
|
||||||
|
if ($rank < 2000) return 50;
|
||||||
|
if ($rank <= 2400) return 30;
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
|
private function changeScores($score){
|
||||||
|
$this->rank1 = $this->rank1 + $this->get_k($this->rank1) * ($score - (1/ (1 + pow(10,(($this->rank2 - $this->rank1) / $this->factor)))));
|
||||||
|
$this->rank2 = $this->rank2 + $this->get_k($this->rank2) * (1 - $score - (1/ (1 + pow(10,(($this->rank1 - $this->rank2) / $this->factor)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function oneWinsAgainstTwo(){
|
||||||
|
$this->changeScores(1);
|
||||||
|
}
|
||||||
|
public function twoWinsAgainstOne(){
|
||||||
|
$this->changeScores(0);
|
||||||
|
}
|
||||||
|
public function drawGame(){
|
||||||
|
$this->changeScores(0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ELO
|
||||||
|
{
|
||||||
|
public $rank = 1500; //default rank
|
||||||
|
|
||||||
|
public function __construct($v=1500) {
|
||||||
|
$this->rank = $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function ELO_get_new_ranks($elo1,$elo2,$score){
|
||||||
|
/*
|
||||||
|
* return an array containing new ELO scores after a battle
|
||||||
|
* $score : 0 player 2 won
|
||||||
|
* 0.5 draws
|
||||||
|
* 1 player 1 won
|
||||||
|
*/
|
||||||
|
|
||||||
|
//good luck for understanding it
|
||||||
|
//(see https://blog.antoine-augusti.fr/2012/06/maths-et-code-le-classement-elo/)
|
||||||
|
return array(
|
||||||
|
$elo1 + ELO_get_k($elo1) * ($score - (1/ (1 + pow(10,(($elo2 - $elo1) / 400))))),
|
||||||
|
$elo2 + ELO_get_k($elo2) * (1 - $score - (1/ (1 + pow(10,(($elo1 - $elo2) / 400)))))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function looseAgainst(ELO $winer){
|
||||||
|
|
||||||
|
}
|
||||||
|
public function winAgainst(ELO $looser){
|
||||||
|
|
||||||
|
}
|
||||||
|
public function drawAgainst(ELO $drawPlayer){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,16 +20,22 @@ class ScoreLap
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLoosersList(){
|
public function getLoosersList(){
|
||||||
return $this->$loosers;
|
//return losers as a digest array
|
||||||
|
$arr = array();
|
||||||
|
|
||||||
|
foreach($this->loosers as $looser){
|
||||||
|
$arr[] = array("id" => $looser->id,"order" => $looser->playerIndex);
|
||||||
|
}
|
||||||
|
return $arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function ApplyDraws(){
|
private function ApplyDraws(){
|
||||||
|
|
||||||
//apply draw match to all losers
|
//apply draw match to all losers
|
||||||
if(count($this->looserList) < 2) return;
|
if(count($this->loosers) < 2) return;
|
||||||
|
|
||||||
foreach($loosers as $$looser1){
|
foreach($this->loosers as $looser1){
|
||||||
foreach($loosers as $looser2){
|
foreach($this->loosers as $looser2){
|
||||||
if($looser1->playerIndex == $looser2->playerIndex) continue;
|
if($looser1->playerIndex == $looser2->playerIndex) continue;
|
||||||
save_battle('tron', $looser1->id, $looser2->id, 0, 'id' );
|
save_battle('tron', $looser1->id, $looser2->id, 0, 'id' );
|
||||||
}
|
}
|
||||||
|
@ -41,7 +47,7 @@ class ScoreLap
|
||||||
|
|
||||||
//need to make losers List. simply array of orders
|
//need to make losers List. simply array of orders
|
||||||
$loosersIndexArr = array();
|
$loosersIndexArr = array();
|
||||||
foreach($this->looserList as $looser){
|
foreach($this->loosers as $looser){
|
||||||
$loosersIndexArr[] = $looser->playerIndex;
|
$loosersIndexArr[] = $looser->playerIndex;
|
||||||
}
|
}
|
||||||
foreach($this->loosers as $looser){
|
foreach($this->loosers as $looser){
|
||||||
|
|
|
@ -18,11 +18,18 @@ class Trail {
|
||||||
public function emptyTrail(){
|
public function emptyTrail(){
|
||||||
$this->trail = new SplStack();
|
$this->trail = new SplStack();
|
||||||
}
|
}
|
||||||
public function mergeWith($trailToMerge){
|
public function getTrail(){
|
||||||
foreach($trailToMerge as $value) {
|
return $this->trail;
|
||||||
$this->trail->add($value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
public function mergeWith($trailToMerge){
|
||||||
|
if($trailToMerge->getTrail()->isEmpty()) return;
|
||||||
|
|
||||||
|
foreach($trailToMerge->getTrail() as $value) {
|
||||||
|
$this->trail->push($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function add($value) {
|
public function add($value) {
|
||||||
if(!$this->trail->isEmpty()) {
|
if(!$this->trail->isEmpty()) {
|
||||||
if(Trail::kind($this->trail->bottom()) !== Trail::kind($value)) {
|
if(Trail::kind($this->trail->bottom()) !== Trail::kind($value)) {
|
||||||
|
|
|
@ -48,14 +48,16 @@ class TronGame
|
||||||
foreach($this->bots as $bot){
|
foreach($this->bots as $bot){
|
||||||
$trailsArr[] = $bot->trail->getTrailAsArray();
|
$trailsArr[] = $bot->trail->getTrailAsArray();
|
||||||
}
|
}
|
||||||
|
//error_log("*********".json_encode($trailsArr,true)."********");
|
||||||
return $trailsArr;
|
return $trailsArr;
|
||||||
|
|
||||||
}
|
}
|
||||||
private function get_map_as_an_unique_trail(){
|
private function get_map_as_an_unique_trail(){
|
||||||
$trail = new Trail;
|
$trail = new Trail;
|
||||||
foreach($this->bots as $bot){
|
foreach($this->bots as $bot){
|
||||||
$trail->mergeWith($bot->trail);
|
$trail->mergeWith($bot->trail);
|
||||||
}
|
}
|
||||||
return trail;
|
return $trail;
|
||||||
|
|
||||||
}
|
}
|
||||||
public function get_lasts_trails(){
|
public function get_lasts_trails(){
|
||||||
|
@ -125,24 +127,33 @@ class TronGame
|
||||||
$response = curl_multi_getcontent($cr);
|
$response = curl_multi_getcontent($cr);
|
||||||
|
|
||||||
if($curlError !== "") {
|
if($curlError !== "") {
|
||||||
|
|
||||||
//erreur curl, he loses
|
//erreur curl, he loses
|
||||||
$scoreObj-> addLoser($currentBot);
|
$scoreObj-> addLoser($currentBot);
|
||||||
$currentBot->loose();
|
$currentBot->loose();
|
||||||
|
error_log("no curl response".$playerIndex); //debug
|
||||||
|
|
||||||
}elseif(! $arr = json_decode($response,TRUE)){
|
}elseif(! $arr = json_decode($response,TRUE)){
|
||||||
|
|
||||||
//la reponse n'est pas un json, il a perdu
|
//la reponse n'est pas un json, il a perdu
|
||||||
$scoreObj-> addLoser($currentBot);
|
$scoreObj-> addLoser($currentBot);
|
||||||
$currentBot->loose();
|
$currentBot->loose();
|
||||||
|
error_log("la reponse est pas JSON".$playerIndex); //debug
|
||||||
|
|
||||||
}elseif(Direction::make($arr['play']) === false){
|
}elseif(Direction::make($arr['play']) === false){
|
||||||
|
|
||||||
//tester ici la réponse
|
//tester ici la réponse
|
||||||
//he loose il utilise probablement une de ses propres cases
|
//he loose il utilise probablement une de ses propres cases
|
||||||
$scoreObj-> addLoser($currentBot);
|
$scoreObj-> addLoser($currentBot);
|
||||||
$currentBot->loose();
|
$currentBot->loose();
|
||||||
|
error_log("La reponse ne contient pas une direction".$playerIndex); //debug
|
||||||
|
|
||||||
}elseif($initialMapAsATrail->contains($currentBot->trail->last()->addDirection(Direction::make($arr['play'])))){ //ounch
|
}elseif($initialMapAsATrail->contains($currentBot->trail->last()->addDirection(Direction::make($arr['play'])))){ //ounch
|
||||||
|
|
||||||
//le bot tente d'aller sur une case qui était prise au début du round
|
//le bot tente d'aller sur une case qui était prise au début du round
|
||||||
$scoreObj-> addLoser($currentBot);
|
$scoreObj-> addLoser($currentBot);
|
||||||
$currentBot->loose();
|
$currentBot->loose();
|
||||||
|
error_log("Il joue sur une case deja prise".$playerIndex); //debug
|
||||||
}else{
|
}else{
|
||||||
//mettre de coté la direction du bot
|
//mettre de coté la direction du bot
|
||||||
$currentBot->nextDir = Direction::make($arr['play']);
|
$currentBot->nextDir = Direction::make($arr['play']);
|
||||||
|
@ -157,7 +168,7 @@ class TronGame
|
||||||
//pour tous les bots encore vivants, on teste si deux d'entre eux ne cibleraient pas la même case
|
//pour tous les bots encore vivants, on teste si deux d'entre eux ne cibleraient pas la même case
|
||||||
foreach ($aliveBots as $bot1){
|
foreach ($aliveBots as $bot1){
|
||||||
foreach ($aliveBots as $bot2){
|
foreach ($aliveBots as $bot2){
|
||||||
if($bot1-> $playerIndex == $bot2-> $playerIndex) continue;
|
if($bot1->playerIndex == $bot2->playerIndex) continue;
|
||||||
if($bot1->trail->last()->addDirection($bot1->nextDir) == $bot2->trail->last()->addDirection($bot2->nextDir)){
|
if($bot1->trail->last()->addDirection($bot1->nextDir) == $bot2->trail->last()->addDirection($bot2->nextDir)){
|
||||||
//he loose
|
//he loose
|
||||||
$scoreObj-> addLoser($bot1);
|
$scoreObj-> addLoser($bot1);
|
||||||
|
@ -183,74 +194,8 @@ class TronGame
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private function get_multi_IAS_Responses($iasUrls, $postParams){
|
|
||||||
//bug here le resultat retourné ne prend pas les bots ayant déjà perdus
|
|
||||||
|
|
||||||
|
|
||||||
//same as the get_IAS_Responses function
|
|
||||||
// but more than one bot requested parallely
|
|
||||||
|
|
||||||
$cmh = curl_multi_init();
|
|
||||||
for ($i = 0; $i < count($iasUrls); $i++){
|
|
||||||
if(isset($postParams[$i])){ //dont use already deads bots
|
|
||||||
$data_string = json_encode($postParams[$i]);
|
|
||||||
|
|
||||||
//error_log($data_string);
|
|
||||||
|
|
||||||
$ch[$i] = curl_init($iasUrls[$i]);
|
|
||||||
curl_setopt($ch[$i], CURLOPT_CUSTOMREQUEST, "POST");
|
|
||||||
curl_setopt($ch[$i], CURLOPT_SSL_VERIFYHOST, false);
|
|
||||||
curl_setopt($ch[$i], CURLOPT_SSL_VERIFYPEER, false);
|
|
||||||
curl_setopt($ch[$i], CURLOPT_POSTFIELDS, $data_string);
|
|
||||||
curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true);
|
|
||||||
curl_setopt($ch[$i], CURLOPT_HTTPHEADER, array(
|
|
||||||
'Content-Type: application/json',
|
|
||||||
'Content-Length: ' . strlen($data_string))
|
|
||||||
);
|
|
||||||
curl_multi_add_handle($cmh,$ch[$i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//send the requests
|
|
||||||
do {
|
|
||||||
$returnVal = curl_multi_exec($cmh, $runningHandles);
|
|
||||||
}while($runningHandles > 0);
|
|
||||||
|
|
||||||
|
|
||||||
//Get results
|
|
||||||
|
|
||||||
for ($i = 0; $i < count($iasUrls); $i++){
|
|
||||||
|
|
||||||
if(isset($postParams[$i])){
|
|
||||||
// Check for errors
|
|
||||||
$curlError = curl_error($ch[$i]);
|
|
||||||
if($curlError == "") {
|
|
||||||
$response = curl_multi_getcontent($ch[$i]);
|
|
||||||
if(! $arr = json_decode($response,TRUE)){
|
|
||||||
$arr=array();
|
|
||||||
}
|
|
||||||
$res[$i] = array(
|
|
||||||
'messageSend' => json_encode($postParams[$i]),
|
|
||||||
'response' => $response,
|
|
||||||
'httpStatus' => curl_getinfo($ch[$i])['http_code'],
|
|
||||||
'responseArr' => $arr
|
|
||||||
);
|
|
||||||
|
|
||||||
}else{
|
|
||||||
$res[$i] = false;
|
|
||||||
}
|
|
||||||
//close
|
|
||||||
curl_multi_remove_handle($cmh, $ch[$i]);
|
|
||||||
curl_close($ch[$i]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// Clean up the curl_multi handle
|
|
||||||
curl_multi_close($cmh);
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function init_game(){
|
public function init_game(){
|
||||||
//send init messages to bots
|
//send init messages to bots
|
||||||
$logs = "";
|
$logs = "";
|
||||||
|
|
|
@ -141,7 +141,7 @@ Les champs qui différent sont:
|
||||||
]<br />
|
]<br />
|
||||||
</p>
|
</p>
|
||||||
<p>L'ordre des "queues" des serpents dans ce tableau correspond à l'ordre des joueurs. Donc votre serpent est representée par la queue correspondant à player-index (le décompte de player-index commence par 0).</p>
|
<p>L'ordre des "queues" des serpents dans ce tableau correspond à l'ordre des joueurs. Donc votre serpent est representée par la queue correspondant à player-index (le décompte de player-index commence par 0).</p>
|
||||||
<p>L'ordre des couples de coordonnées de chaque bot, est dans le sens queue vers la tête. Les bots grandissent à chaque tour en déplaçant leur tête.</p>
|
<p>L'ordre des couples de coordonnées de chaque bot, est dans le sens tête vers queue. Les bots grandissent à chaque tour en déplaçant leur tête.</p>
|
||||||
<h2>Scoring</h2>
|
<h2>Scoring</h2>
|
||||||
<p>Le scorring (classement EHLO) reste sur une logique de duels, bien que ce jeu puisse contenir plus de deux bots par match. Le score est modifié au fur et à mesure de la partie à chaque fois qu'un bot "décède":</p>
|
<p>Le scorring (classement EHLO) reste sur une logique de duels, bien que ce jeu puisse contenir plus de deux bots par match. Le score est modifié au fur et à mesure de la partie à chaque fois qu'un bot "décède":</p>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
# http://www.gnu.org/licenses/gpl-3.0-standalone.html
|
# http://www.gnu.org/licenses/gpl-3.0-standalone.html
|
||||||
#
|
#
|
||||||
# -- END LICENSE BLOCK -----------------------------------------
|
# -- END LICENSE BLOCK -----------------------------------------
|
||||||
|
include(__DIR__."/DUEL.php");
|
||||||
|
|
||||||
function get_arenas_list(){
|
function get_arenas_list(){
|
||||||
include (__DIR__."/arenas_lists.php");
|
include (__DIR__."/arenas_lists.php");
|
||||||
|
@ -203,99 +204,73 @@ function ELO_get_podium($arena){
|
||||||
}
|
}
|
||||||
return $podium;
|
return $podium;
|
||||||
}
|
}
|
||||||
function ELO_get_k($elo){
|
|
||||||
if ($elo < 1000){
|
|
||||||
return 80;
|
function save_battle($game,$bot1,$bot2,$result,$nameOrIds = 'name'){
|
||||||
}
|
|
||||||
if ($elo < 2000){
|
|
||||||
return 50;
|
|
||||||
}
|
|
||||||
if ($elo <= 2400){
|
|
||||||
return 30;
|
|
||||||
}
|
|
||||||
return 20;
|
|
||||||
}
|
|
||||||
function ELO_get_new_ranks($elo1,$elo2,$score){
|
|
||||||
/*
|
/*
|
||||||
* return an array containing new ELO scores after a battle
|
* Calculate new ELO ranks and save them on conn_bdd
|
||||||
* $score : 0 player 2 won
|
*/
|
||||||
* 0.5 draws
|
|
||||||
* 1 player 1 won
|
|
||||||
*/
|
|
||||||
|
|
||||||
//good luck for understanding it
|
|
||||||
//(see https://blog.antoine-augusti.fr/2012/06/maths-et-code-le-classement-elo/)
|
|
||||||
return array(
|
|
||||||
$elo1 + ELO_get_k($elo1) * ($score - (1/ (1 + pow(10,(($elo2 - $elo1) / 400))))),
|
|
||||||
$elo2 + ELO_get_k($elo2) * (1 - $score - (1/ (1 + pow(10,(($elo1 - $elo2) / 400)))))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function save_battle($game,$bot1,$bot2,$resultat,$nameOrIds = 'name'){
|
|
||||||
//$bots1 and $bots2 are bots'names
|
|
||||||
//resultat: 0 match nul, 1 bot1 gagne 2 bot 2 gagne
|
|
||||||
|
|
||||||
global $lnMysql;
|
global $lnMysql;
|
||||||
$game=substr($game,0,8); //limit 8 char for limitting mysql index size
|
$game=substr($game,0,8); //limit 8 char for limitting mysql index size
|
||||||
|
|
||||||
if($nameOrIds == "name"){
|
if($nameOrIds == "name"){
|
||||||
//chercher les id de bot 1 et bot2
|
for( $i=1; $i<3; $i++){
|
||||||
$rs=mysqli_query($lnMysql,"SELECT name,id,ELO FROM bots
|
$str = "bot".$i;
|
||||||
WHERE name='".mysqli_real_escape_string($lnMysql,$bot1)."'
|
$botName = $$str;
|
||||||
OR name='".mysqli_real_escape_string($lnMysql,$bot2)."'");
|
$rs=mysqli_query($lnMysql,"SELECT id,ELO FROM bots WHERE name='".mysqli_real_escape_string($lnMysql,$botName)."'");
|
||||||
|
$r = mysqli_fetch_row($rs);
|
||||||
|
$bot[$i] = array(
|
||||||
|
'id' => $r[0],
|
||||||
|
'ELO' => $r[1]
|
||||||
|
);
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
$rs = mysqli_query($lnMysql, "SELECT name,id,ELO FROM bots
|
//the same, but query by id
|
||||||
WHERE id='".mysqli_real_escape_string($lnMysql,$bot1)."'
|
for( $i=1; $i<3; $i++){
|
||||||
OR id='".mysqli_real_escape_string($lnMysql,$bot2)."'");
|
$str = "bot".$i;
|
||||||
}
|
$botName = $$str;
|
||||||
while($r=mysqli_fetch_row($rs)){
|
$rs=mysqli_query($lnMysql,"SELECT id,ELO FROM bots WHERE id='".mysqli_real_escape_string($lnMysql,$botName)."'");
|
||||||
$bots[$r[0]]=$r[1];
|
$r = mysqli_fetch_row($rs);
|
||||||
$actualELO[$r[0]]=$r[2];
|
$bot[$i] = array(
|
||||||
|
'id' => $r[0],
|
||||||
|
'ELO' => $r[1]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((!isset($bots[$bot1])) OR (!isset($bots[$bot2]))){
|
//apply $result
|
||||||
error (500,"database corrupt");
|
$duel = new DUEL( $bot[1]["ELO"] , $bot[2]["ELO"]);
|
||||||
die;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($resultat){
|
switch ($result){
|
||||||
case 0:
|
case 0:
|
||||||
|
$duel->drawGame();
|
||||||
$field="nulCount";
|
$field="nulCount";
|
||||||
$eloScore = 0.5;
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
$field="player1_winsCount";
|
$duel->oneWinsAgainstTwo();
|
||||||
$eloScore = 1;
|
$field="player1_winsCount";
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
$field="player2_winsCount";
|
$duel->twoWinsAgainstOne();
|
||||||
$eloScore = 0;
|
$field="player2_winsCount";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error (500,"something impossible has happened");
|
error (500,"Oups");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$newRanks = ELO_get_new_ranks($actualELO[$bot1],$actualELO[$bot2],$eloScore);
|
//update ELO rank on database
|
||||||
|
mysqli_multi_query($lnMysql,"
|
||||||
mysqli_multi_query($lnMysql,
|
UPDATE bots SET ELO = '".$duel->rank1."' WHERE id='".$bot[1]["id"]."';
|
||||||
"
|
UPDATE bots SET ELO = '".$duel->rank2."' WHERE id='".$bot[2]["id"]."';
|
||||||
UPDATE bots
|
INSERT INTO arena_history(game,player1_id,player2_id,".$field.") VALUES
|
||||||
SET ELO='".$newRanks[0]."'
|
|
||||||
WHERE id='".$bots[$bot1]."';
|
|
||||||
|
|
||||||
UPDATE bots
|
|
||||||
SET ELO='".$newRanks[1]."'
|
|
||||||
WHERE id='".$bots[$bot2]."';
|
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO arena_history(game,player1_id,player2_id,".$field.") VALUES
|
|
||||||
('".mysqli_real_escape_string($lnMysql,$game)."',
|
('".mysqli_real_escape_string($lnMysql,$game)."',
|
||||||
'".$bots[$bot1]."',
|
'".$bot[1]["id"]."',
|
||||||
'".$bots[$bot2]."',
|
'".$bot[2]["id"]."',
|
||||||
'1')
|
'1')
|
||||||
ON DUPLICATE KEY UPDATE ".$field." = ".$field." + 1;");
|
ON DUPLICATE KEY UPDATE ".$field." = ".$field." + 1;
|
||||||
|
");
|
||||||
}
|
}
|
||||||
function get_unique_id(){
|
function get_unique_id(){
|
||||||
//increment the number
|
//increment the number
|
||||||
|
|
Loading…
Reference in New Issue
Block a user