From 8ea8d66e05e4920ff08f7dbec9b2431859dc5dcd Mon Sep 17 00:00:00 2001
From: Gnieark
Date: Tue, 8 Nov 2016 19:27:55 +0100
Subject: [PATCH] Scoring
---
countBattles.txt | 2 +-
src/DUEL.php | 80 +++++++++++++++++++++++
src/arenas/tron/ScoreLap.php | 16 +++--
src/arenas/tron/Trail.php | 13 +++-
src/arenas/tron/TronGame.php | 85 +++++-------------------
src/arenas/tron/doc-fr.html | 2 +-
src/functions.php | 123 ++++++++++++++---------------------
7 files changed, 167 insertions(+), 154 deletions(-)
create mode 100644 src/DUEL.php
diff --git a/countBattles.txt b/countBattles.txt
index e6d1b72..e6ad4d7 100755
--- a/countBattles.txt
+++ b/countBattles.txt
@@ -1 +1 @@
-1747
\ No newline at end of file
+1784
\ No newline at end of file
diff --git a/src/DUEL.php b/src/DUEL.php
new file mode 100644
index 0000000..0b158c5
--- /dev/null
+++ b/src/DUEL.php
@@ -0,0 +1,80 @@
+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){
+
+ }
+
+}
diff --git a/src/arenas/tron/ScoreLap.php b/src/arenas/tron/ScoreLap.php
index a529252..eb6f7a2 100644
--- a/src/arenas/tron/ScoreLap.php
+++ b/src/arenas/tron/ScoreLap.php
@@ -20,16 +20,22 @@ class ScoreLap
}
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(){
//apply draw match to all losers
- if(count($this->looserList) < 2) return;
+ if(count($this->loosers) < 2) return;
- foreach($loosers as $$looser1){
- foreach($loosers as $looser2){
+ foreach($this->loosers as $looser1){
+ foreach($this->loosers as $looser2){
if($looser1->playerIndex == $looser2->playerIndex) continue;
save_battle('tron', $looser1->id, $looser2->id, 0, 'id' );
}
@@ -41,7 +47,7 @@ class ScoreLap
//need to make losers List. simply array of orders
$loosersIndexArr = array();
- foreach($this->looserList as $looser){
+ foreach($this->loosers as $looser){
$loosersIndexArr[] = $looser->playerIndex;
}
foreach($this->loosers as $looser){
diff --git a/src/arenas/tron/Trail.php b/src/arenas/tron/Trail.php
index 9740d18..17604d0 100755
--- a/src/arenas/tron/Trail.php
+++ b/src/arenas/tron/Trail.php
@@ -18,11 +18,18 @@ class Trail {
public function emptyTrail(){
$this->trail = new SplStack();
}
+ public function getTrail(){
+ return $this->trail;
+ }
public function mergeWith($trailToMerge){
- foreach($trailToMerge as $value) {
- $this->trail->add($value);
+ if($trailToMerge->getTrail()->isEmpty()) return;
+
+ foreach($trailToMerge->getTrail() as $value) {
+ $this->trail->push($value);
}
+
}
+
public function add($value) {
if(!$this->trail->isEmpty()) {
if(Trail::kind($this->trail->bottom()) !== Trail::kind($value)) {
@@ -42,7 +49,7 @@ class Trail {
public function __toString(){
return json_encode($this->getTrailAsArray());
}
-
+
public function getTrailAsArray(){
$arr = array();
foreach($this->trail as $coord) {
diff --git a/src/arenas/tron/TronGame.php b/src/arenas/tron/TronGame.php
index 0d55fb6..f49905e 100755
--- a/src/arenas/tron/TronGame.php
+++ b/src/arenas/tron/TronGame.php
@@ -48,14 +48,16 @@ class TronGame
foreach($this->bots as $bot){
$trailsArr[] = $bot->trail->getTrailAsArray();
}
+ //error_log("*********".json_encode($trailsArr,true)."********");
return $trailsArr;
+
}
private function get_map_as_an_unique_trail(){
$trail = new Trail;
foreach($this->bots as $bot){
$trail->mergeWith($bot->trail);
}
- return trail;
+ return $trail;
}
public function get_lasts_trails(){
@@ -125,24 +127,33 @@ class TronGame
$response = curl_multi_getcontent($cr);
if($curlError !== "") {
+
//erreur curl, he loses
$scoreObj-> addLoser($currentBot);
$currentBot->loose();
-
+ error_log("no curl response".$playerIndex); //debug
+
}elseif(! $arr = json_decode($response,TRUE)){
+
//la reponse n'est pas un json, il a perdu
$scoreObj-> addLoser($currentBot);
$currentBot->loose();
+ error_log("la reponse est pas JSON".$playerIndex); //debug
}elseif(Direction::make($arr['play']) === false){
+
//tester ici la réponse
//he loose il utilise probablement une de ses propres cases
$scoreObj-> addLoser($currentBot);
$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
+
//le bot tente d'aller sur une case qui était prise au début du round
$scoreObj-> addLoser($currentBot);
$currentBot->loose();
+ error_log("Il joue sur une case deja prise".$playerIndex); //debug
}else{
//mettre de coté la direction du bot
$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
foreach ($aliveBots as $bot1){
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)){
//he loose
$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(){
//send init messages to bots
diff --git a/src/arenas/tron/doc-fr.html b/src/arenas/tron/doc-fr.html
index 1170785..d821de8 100755
--- a/src/arenas/tron/doc-fr.html
+++ b/src/arenas/tron/doc-fr.html
@@ -141,7 +141,7 @@ Les champs qui différent sont:
]
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).
-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.
+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.
Scoring
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":
diff --git a/src/functions.php b/src/functions.php
index 3c44b40..da9153e 100755
--- a/src/functions.php
+++ b/src/functions.php
@@ -9,6 +9,7 @@
# http://www.gnu.org/licenses/gpl-3.0-standalone.html
#
# -- END LICENSE BLOCK -----------------------------------------
+include(__DIR__."/DUEL.php");
function get_arenas_list(){
include (__DIR__."/arenas_lists.php");
@@ -203,99 +204,73 @@ function ELO_get_podium($arena){
}
return $podium;
}
-function ELO_get_k($elo){
- if ($elo < 1000){
- return 80;
- }
- 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
- * $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
+function save_battle($game,$bot1,$bot2,$result,$nameOrIds = 'name'){
+ /*
+ * Calculate new ELO ranks and save them on conn_bdd
+ */
+
global $lnMysql;
$game=substr($game,0,8); //limit 8 char for limitting mysql index size
-
- if($nameOrIds == "name"){
- //chercher les id de bot 1 et bot2
- $rs=mysqli_query($lnMysql,"SELECT name,id,ELO FROM bots
- WHERE name='".mysqli_real_escape_string($lnMysql,$bot1)."'
- OR name='".mysqli_real_escape_string($lnMysql,$bot2)."'");
+
+ if($nameOrIds == "name"){
+ for( $i=1; $i<3; $i++){
+ $str = "bot".$i;
+ $botName = $$str;
+ $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{
- $rs = mysqli_query($lnMysql, "SELECT name,id,ELO FROM bots
- WHERE id='".mysqli_real_escape_string($lnMysql,$bot1)."'
- OR id='".mysqli_real_escape_string($lnMysql,$bot2)."'");
- }
- while($r=mysqli_fetch_row($rs)){
- $bots[$r[0]]=$r[1];
- $actualELO[$r[0]]=$r[2];
+ //the same, but query by id
+ for( $i=1; $i<3; $i++){
+ $str = "bot".$i;
+ $botName = $$str;
+ $rs=mysqli_query($lnMysql,"SELECT id,ELO FROM bots WHERE id='".mysqli_real_escape_string($lnMysql,$botName)."'");
+ $r = mysqli_fetch_row($rs);
+ $bot[$i] = array(
+ 'id' => $r[0],
+ 'ELO' => $r[1]
+ );
+ }
}
- if((!isset($bots[$bot1])) OR (!isset($bots[$bot2]))){
- error (500,"database corrupt");
- die;
- }
-
- switch($resultat){
+ //apply $result
+ $duel = new DUEL( $bot[1]["ELO"] , $bot[2]["ELO"]);
+
+ switch ($result){
case 0:
+ $duel->drawGame();
$field="nulCount";
- $eloScore = 0.5;
break;
case 1:
- $field="player1_winsCount";
- $eloScore = 1;
+ $duel->oneWinsAgainstTwo();
+ $field="player1_winsCount";
break;
case 2:
- $field="player2_winsCount";
- $eloScore = 0;
- break;
+ $duel->twoWinsAgainstOne();
+ $field="player2_winsCount";
+ break;
default:
- error (500,"something impossible has happened");
+ error (500,"Oups");
break;
}
- $newRanks = ELO_get_new_ranks($actualELO[$bot1],$actualELO[$bot2],$eloScore);
-
- mysqli_multi_query($lnMysql,
- "
- UPDATE bots
- 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
+ //update ELO rank on database
+ 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"]."';
+ INSERT INTO arena_history(game,player1_id,player2_id,".$field.") VALUES
('".mysqli_real_escape_string($lnMysql,$game)."',
- '".$bots[$bot1]."',
- '".$bots[$bot2]."',
+ '".$bot[1]["id"]."',
+ '".$bot[2]["id"]."',
'1')
- ON DUPLICATE KEY UPDATE ".$field." = ".$field." + 1;");
-
+ ON DUPLICATE KEY UPDATE ".$field." = ".$field." + 1;
+ ");
}
function get_unique_id(){
//increment the number