This commit is contained in:
Gnieark 2016-11-08 19:27:55 +01:00
parent c4e99fccc7
commit 8ea8d66e05
7 changed files with 170 additions and 157 deletions

View File

@ -1 +1 @@
1747 1784

80
src/DUEL.php Normal file
View 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){
}
}

View File

@ -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){

View File

@ -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)) {
@ -42,7 +49,7 @@ class Trail {
public function __toString(){ public function __toString(){
return json_encode($this->getTrailAsArray()); return json_encode($this->getTrailAsArray());
} }
public function getTrailAsArray(){ public function getTrailAsArray(){
$arr = array(); $arr = array();
foreach($this->trail as $coord) { foreach($this->trail as $coord) {

View File

@ -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,73 +194,7 @@ 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

View File

@ -141,7 +141,7 @@ Les champs qui différent sont:
&nbsp;&nbsp;]<br /> &nbsp;&nbsp;]<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>

View File

@ -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 ($result){
switch($resultat){
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