www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 6576222b7a74a836370dd66d3f9eceff798a9884
parent ea110681043bb548d1cc240817097753166f7d63
Author: Yoann Bonavero <yoann.b87@voila.fr>
Date:   Mon,  7 Feb 2011 18:41:30 +0100

Mise en forme quasi globale du code du fichier pticlic.php

Diffstat:
Mcode/serveur/php/pticlic.php | 366++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 262 insertions(+), 104 deletions(-)

diff --git a/code/serveur/php/pticlic.php b/code/serveur/php/pticlic.php @@ -12,16 +12,21 @@ function mDie($err,$msg) exit; } -if (!$db = new SQlite3($SQL_DBNAME)) { +if (!$db = new SQlite3($SQL_DBNAME)) mDie(1,"Erreur lors de l'ouverture de la base de données SQLite3"); -} -function initdb() { + +/** Initialise la base de données avec un nom d'utilisateur et un mot de passe +*/ +function initdb() +{ global $db; + $db->exec("insert into user(login, mail, hash_passwd, score) values('foo', 'foo@isp.com', '".md5('bar')."', 0);"); } -if ($do_initdb) { initdb(); } +if ($do_initdb) + initdb(); if(!isset($_GET['action']) || !isset($_GET['user']) || !isset($_GET['passwd'])) mDie(2,"La requête est incomplète"); @@ -30,18 +35,33 @@ if(!isset($_GET['action']) || !isset($_GET['user']) || !isset($_GET['passwd'])) $action = $_GET['action']; $user = $_GET['user']; $hash_passwd = md5($_GET['passwd']); + if ($hash_passwd !== $db->querySingle("SELECT hash_passwd FROM user WHERE login='".SQLite3::escapeString($user)."';")) mDie(3,"Utilisateur non enregistré ou mauvais mot de passe"); -function random_node() { + +/** Selectionne aléatoirement un noeud. +*/ +function random_node() +{ global $db; + return $db->querySingle("select eid from node where eid = (abs(random()) % (select max(eid) from node))+1 or eid = (select max(eid) from node where eid > 0) order by eid limit 1;"); } + // TODO : Yoann : peut-être faire une classe create_game avec les fonctions ci-dessous comme méthodes ? -function cg_build_result_sets($cloudSize, $centerEid, $r1, $r2) { +/** +* @param cloudSize : Taille du nuage. +* @param centerEid : Identifiant du mot central. +* @param r1 Type de la relation 1. +* @param r2 Type de la relation 2. +*/ +function cg_build_result_sets($cloudSize, $centerEid, $r1, $r2) +{ global $db; + // 'w' => weight (poids), 'd' => difficulté, 's' => select // Le select doit ranvoyer trois colonnes : // eid => l'eid du mot à mettre dans le nuage, @@ -75,216 +95,354 @@ function cg_build_result_sets($cloudSize, $centerEid, $r1, $r2) { ); $sumWeights = 0; - foreach ($sources as $k => $x) { + + foreach ($sources as $k => $x) + { $sumWeights += $x['w']; $sources[$k]['rsPos'] = 0; $sources[$k]['rsSize'] = 0; - if ($x['s'] !== false) { + + if ($x['s'] !== false) + { $sources[$k]['resultSet'] = array(); $res = $db->query($x['s']); $i = 0; - while ($i < 10 && $sources[$k]['resultSet'][] = $res->fetchArray()) { + + while ($i < 10 && $sources[$k]['resultSet'][] = $res->fetchArray()) + { $i++; $sources[$k]['rsSize']++; } - } else { + } + else + { $sources[$k]['resultSet'] = array(); - for ($i = 0; $i < 10; $i++) { + + for ($i = 0; $i < 10; $i++) + { $sources[$k]['resultSet'][] = array('eid'=>random_node(), 'r1'=>0, 'r2'=>0, 'r0'=>0, 'trash'=>1); $sources[$k]['rsSize']++; } } } + return array($sources, $sumWeights); } -function cg_choose_relations() { + +/** +* @return array : Tableau avec la relation 1 et la relation 2. +*/ +function cg_choose_relations() +{ $relations = array(5, 7, 9, 10, /* Pas d'icônes pour celles-ci. */ 13, 14, 22); $r1 = rand(0,count($relations)-1); $r2 = rand(0,count($relations)-2); - if ($r2 >= $r1) $r2++; + + if ($r2 >= $r1) + $r2++; + $r1 = $relations[$r1]; $r2 = $relations[$r2]; + return array($r1, $r2); } -function cg_build_cloud($cloudSize, $sources, $sumWeights) { +/** +* @param cloudSize : Taille du nuage. +* @param sources Les sources. +* @param sumWeights La somme des poids. +* @return array : Tableau avec comme premier élément le nuage et comme second élément le total de difficulté. +*/ +function cg_build_cloud($cloudSize, $sources, $sumWeights) +{ // On boucle tant qu'il n'y a pas eu au moins 2 sources épuisées $cloud = array(); $nbFailed = 0; $i = 0; $totalDifficulty = 0; - while ($i < $cloudSize && $nbFailed < 5*$cloudSize) { + + while ($i < $cloudSize && $nbFailed < 5*$cloudSize) + { // On choisit une source aléatoire en tennant compte des poids. $rands = rand(1,$sumWeights); $sumw = 0; $src = $sources['rand']; $srck = null; - foreach ($sources as $k => $x) { + + foreach ($sources as $k => $x) + { $sumw += $x['w']; - if ($rands < $sumw) { + + if ($rands < $sumw) + { $src = $x; $srck = $k; break; } } - if ($src['rsPos'] >= $src['rsSize']) { + + if ($src['rsPos'] >= $src['rsSize']) + { $nbFailed++; - if ($srck !== null) { + + if ($srck !== null) + { $sumWeights -= $src['w']; unset($sources[$srck]); } + continue; } + $res = $src['resultSet'][$src['rsPos']++]; - if (in_array($res['eid'], $cloud)) { + + if (in_array($res['eid'], $cloud)) + { $nbFailed++; continue; } + // position dans le nuage, difficulté, eid, probaR1, probaR2 $totalDifficulty += $src['d']; $cloud[$i] = array('pos'=>$i++, 'd'=>$src['d'], 'eid'=>$res['eid'], 'probaR1'=>$res['r1'], 'probaR2'=>$res['r2'], 'probaR0'=>$res['r0'], 'probaTrash'=>$res['trash']); } + $res = $sources['rand']['resultSet'][0]; - while ($i < $cloudSize) { + + while ($i < $cloudSize) + { $totalDifficulty += $sources['rand']['d']; $cloud[$i] = array('pos'=>$i++, 'd'=>$sources['rand']['d'], 'eid'=>random_node(), 'probaR1'=>$res['r1'], 'probaR2'=>$res['r2'], 'probaR0'=>$res['r0'], 'probaTrash'=>$res['trash']); } + return array($cloud, $totalDifficulty); } -function cg_insert($centerEid, $cloud, $r1, $r2, $totalDifficulty) { + +/** +* @param centerEid : Identifiant du mot central. +* @param cloud : Le nuage. +* @param r1 : Le type de la relation 1. +* @param r2 : Le type de la relation 2. +* @param totalDifficulty : La difficulté totale. +*/ +function cg_insert($centerEid, $cloud, $r1, $r2, $totalDifficulty) +{ global $db, $user; + // Insère dans la base une partie avec le mot central $centerEid, le nuage $cloud et les relations $r1 et $r2 $db->exec("begin transaction;"); - $db->exec("insert into game(gid, eid_central_word, relation_1, relation_2, difficulty) values (null, $centerEid, $r1, $r2, $totalDifficulty);"); + $db->exec("INSERT INTO game(gid, eid_central_word, relation_1, relation_2, difficulty) + VALUES (null, $centerEid, $r1, $r2, $totalDifficulty);"); $gid = $db->lastInsertRowID(); - $db->exec("insert into played_game(pgid, gid, login, played) values (null, $gid, null, 1);"); + + $db->exec("INSERT INTO played_game(pgid, gid, login, played) + VALUES (null, $gid, null, 1);"); $pgid = $db->lastInsertRowID(); - foreach ($cloud as $c) { - $db->exec("insert into game_cloud(gid, num, difficulty, eid_word, totalWeight, probaR1, probaR2, probaR0, probaTrash) values($gid, ".$c['pos'].", ".$c['d'].", ".$c['eid'].", 2, ".$c['probaR1'].", ".$c['probaR2'].", ".$c['probaR0'].", ".$c['probaTrash'].");"); - $db->exec("insert into played_game_cloud(pgid, gid, type, num, relation, weight, score) values($pgid, $gid, 0, ".$c['pos'].", $r1, ".$c['probaR1'].", 0);"); - $db->exec("insert into played_game_cloud(pgid, gid, type, num, relation, weight, score) values($pgid, $gid, 0, ".$c['pos'].", $r1, ".$c['probaR1'].", 0);"); + + foreach ($cloud as $c) + { + $db->exec("INSERT INTO game_cloud(gid, num, difficulty, eid_word, totalWeight, probaR1, probaR2, probaR0, probaTrash) + VALUES ($gid, ".$c['pos'].", ".$c['d'].", ".$c['eid'].", 2, ".$c['probaR1'].", ".$c['probaR2'].", ".$c['probaR0'].", ".$c['probaTrash'].");"); + + $db->exec("INSERT INTO played_game_cloud(pgid, gid, type, num, relation, weight, score) + VALUES ($pgid, $gid, 0, ".$c['pos'].", $r1, ".$c['probaR1'].", 0);"); + + $db->exec("INSERT INTO played_game_cloud(pgid, gid, type, num, relation, weight, score) + VALUES ($pgid, $gid, 0, ".$c['pos'].", $r1, ".$c['probaR1'].", 0);"); } + $db->exec("commit;"); } -function create_game($cloudSize) { + +/** Génère une partie pour une certaine taille de nuage. +* @param cloudSize : Taille du nuage. +*/ +function create_game($cloudSize) +{ global $db; + // select random node $centerEid = random_node(); + $r1 = cg_choose_relations(); $r2 = $r1[1]; $r1 = $r1[0]; $sources = cg_build_result_sets($cloudSize, $centerEid, $r1, $r2); $sumWeights = $sources[1]; $sources = $sources[0]; $cloud = cg_build_cloud($cloudSize, $sources, $sumWeights); $totalDifficulty = $cloud[1]; $cloud = $cloud[0]; cg_insert($centerEid, $cloud, $r1, $r2, $totalDifficulty); } -function random_game() { + +/** Retourne un identifiant de partie aléatoire de la liste de parties jouables +* @return gid : Identifiant de partie. +*/ +function random_game() +{ global $db; + return $db->querySingle("select gid from game where gid = (abs(random()) % (select max(gid) from game))+1 or gid = (select max(gid) from game where gid > 0) order by gid limit 1;"); } -function game2json($game_id) { + +/** Formate une partie en JSON en l'imprimant. +* @param game_id : L'identifiant d'une partie. +*/ +function game2json($game_id) +{ global $db, $user; + $db->exec("INSERT INTO played_game(pgid, gid, login, played) VALUES (null, $game_id, '".SQLite3::escapeString($user)."', 0);"); $pgid = $db->lastInsertRowID(); + // TODO Yoann : faire des tests d'erreur pour ces select ? $game = $db->query("select gid, (select name from node where eid = eid_central_word) as name_central_word, eid_central_word, relation_1, relation_2 from game where gid = ".$game_id.";"); $game = $game->fetchArray(); + echo "{gid:".$game_id.",pgid:$pgid,cat1:".$game['relation_1'].",cat2:".$game['relation_2'].",cat3:0,cat4:-1,"; echo "center:{id:".$game['eid_central_word'].",name:".json_encode("".$game['name_central_word'])."},"; echo "cloudsize:10,cloud:["; // TODO ! compter dynamiquement. $res = $db->query("select eid_word,(select name from node where eid=eid_word) as name_word from game_cloud where gid = ".$game_id.";"); $notfirst = false; - while ($x = $res->fetchArray()) { - if ($notfirst) { echo ","; } else { $notfirst=true; } + + while ($x = $res->fetchArray()) + { + if ($notfirst) + echo ","; + else + $notfirst=true; + echo "{id:".$x['eid_word'].",name:".json_encode("".$x['name_word'])."}"; } + echo "]}"; } -function main($action) { + +/** La fonction principale. +* @param action : Un identifiant d'action. +*/ +function main($action) +{ global $db, $user; + // Sinon tout est bon on effectu l'opération correspondant à la commande passée. // TODO : en production, utiliser : header("Content-Type: application/json; charset=utf-8"); header("Content-Type: text/plain; charset=utf-8"); - if ($action == 2) { // "Create partie" - // Requête POST : http://serveur/pticlic.php?action=2&nb=2&mode=normal&user=foo&passwd=bar - if(!isset($_GET['nb']) || !isset($_GET['mode'])) - mDie(2,"La requête est incomplète"); - $nbParties = intval($_GET['nb']); - for ($i = 0; $i < $nbParties; $i++) { - create_game(10); - } - } else if ($action == 0) { // "Get partie" - // Requête POST : http://serveur/pticlic.php?action=0&nb=2&mode=normal&user=foo&passwd=bar - if(!isset($_GET['nb']) || !isset($_GET['mode'])) - mDie(2,"La requête est incomplète"); - $nbGames = intval($_GET['nb']); - echo "["; - for ($i=0; $i < $nbGames; $i) { - game2json(random_game()); - if ((++$i) < $nbGames) { - echo ","; - } - } - echo "]"; - } else if($action == 1) { // "Set partie" - if (!isset($_GET['pgid']) || !isset($_GET['gid'])) - mDie(2,"La requête est incomplète"); - $pgid = intval($_GET['pgid']); - $gid = intval($_GET['gid']); + if ($action == 2) // "Create partie" + createGame(); + else if($action == 0) // "Get partie" + getGame(); + else if($action == 1) // "Set partie" + setGame(); + else + mDie(2,"Commande inconnue"); +} + + +/** Création d'une partie. +*/ +function createGame() +{ + // Requête POST : http://serveur/pticlic.php?action=2&nb=2&mode=normal&user=foo&passwd=bar + if(!isset($_GET['nb']) || !isset($_GET['mode'])) + mDie(2,"La requête est incomplète"); + + $nbParties = intval($_GET['nb']); + + for ($i = 0; $i < $nbParties; $i++) + create_game(10); +} + + +/** Récupération d'une partie. +*/ +function getGame() +{ + // Requête POST : http://serveur/pticlic.php?action=0&nb=2&mode=normal&user=foo&passwd=bar + if(!isset($_GET['nb']) || !isset($_GET['mode'])) + mDie(2,"La requête est incomplète"); + + $nbGames = intval($_GET['nb']); + + echo "["; + + for ($i=0; $i < $nbGames; $i) + { + game2json(random_game()); + + if ((++$i) < $nbGames) + echo ","; + } + + echo "]"; +} + + +/** Insertion des données d'une partie. +*/ +function setGame() +{ + global $db, $user; + + if (!isset($_GET['pgid']) || !isset($_GET['gid'])) + mDie(2,"La requête est incomplète"); + + $pgid = intval($_GET['pgid']); + $gid = intval($_GET['gid']); - if ($user != $db->querySingle("SELECT login FROM played_game WHERE pgid = $pgid and $gid = $gid and played = 0;")) - mDie(4,"Cette partie n'est associée à votre nom d'utilisateur, ou bien vous l'avez déjà jouée."); + if ($user != $db->querySingle("SELECT login FROM played_game WHERE pgid = $pgid and $gid = $gid and played = 0;")) + mDie(4,"Cette partie n'est associée à votre nom d'utilisateur, ou bien vous l'avez déjà jouée."); - $userReputation = log($db->querySingle("SELECT score FROM user WHERE login='".SQLite3::escapeString($user)."';")); + $userReputation = log($db->querySingle("SELECT score FROM user WHERE login='".SQLite3::escapeString($user)."';")); - $db->exec("begin transaction;"); - $db->exec("update played_game set played = 1 where pgid = $pgid;"); - - $r0 = 0; - $trash = -1; - $r1 = $db->querySingle("SELECT relation_1, relation_2 FROM game WHERE gid = $gid;", true); - $r2 = $r1['relation_2']; - $r1 = $r1['relation_1']; - $res = $db->query("SELECT num, difficulty, totalWeight, probaR1, probaR2, probaR0, probaTrash FROM game_cloud WHERE gid = $gid;"); - while ($row = $res->fetchArray()) { - $num = $row['num']; - $relanswer = intval($_GET[$row['num']]); - switch ($relanswer) { - case $r1: $answer = 0; $probaRx = "probaR1"; break; - case $r2: $answer = 1; $probaRx = "probaR2"; break; - case $r0: $answer = 2; $probaRx = "probaR3"; break; - case $trash: $answer = 3; $probaRx = "probaTrash"; break; - default: mDie(5, "Réponse invalide pour le mot $num."); - } - - $probas = array($row['probaR1']/$row['totalWeight'], $row['probaR2']/$row['totalWeight'], $row['probaR0']/$row['totalWeight'], $row['probaTrash']/$row['totalWeight']); - // Calcul du score. Score = proba[réponse de l'utilisateur]*coeff1 - proba[autres reponses]*coeff2 - // score = - proba[autres reponses]*coeff2 - $score = -0.7 * (($probas[0] + $probas[1] + $probas[2] + $probas[3]) - $probas[$answer]); - // ici, -0.7 <= score <= 0 - // score = proba[réponse de l'utilisateur]*coeff1 - proba[autres reponses]*coeff2 - $score += ($row['difficulty']/5) * $probas[$answer]; - // ici, -0.7 <= score <= 2 - // Adapter le score en fonction de la réputation de l'utilisateur (quand il est jeune, augmenter le score pour le motiver). - $score += min(2 - max(0, ($userReputation / 4) - 1), 2); - // ici, -0.7 <= score <= 4 - - $db->exec("insert into played_game_cloud(pgid, gid, type, num, relation, weight, score) values($pgid, $gid, 1, $num, $r1, ".$userReputation.", ".$score.");"); - $db->exec("update game_cloud set $probaRx = $probaRx + ".max($réputationJoueur,1)." where gid = $gid;"); - $db->exec("update game_cloud set totalWeight = totalWeight + ".max($réputationJoueur,1)." where gid = $gid;"); - $db->exec("update user set score = score + ".$score." where login = $user;"); + $db->exec("begin transaction;"); + $db->exec("update played_game set played = 1 where pgid = $pgid;"); + + $r0 = 0; + $trash = -1; + $r1 = $db->querySingle("SELECT relation_1, relation_2 FROM game WHERE gid = $gid;", true); + $r2 = $r1['relation_2']; + $r1 = $r1['relation_1']; + $res = $db->query("SELECT num, difficulty, totalWeight, probaR1, probaR2, probaR0, probaTrash FROM game_cloud WHERE gid = $gid;"); + + while ($row = $res->fetchArray()) + { + $num = $row['num']; + $relanswer = intval($_GET[$row['num']]); + + switch ($relanswer) + { + case $r1: $answer = 0; $probaRx = "probaR1"; break; + case $r2: $answer = 1; $probaRx = "probaR2"; break; + case $r0: $answer = 2; $probaRx = "probaR3"; break; + case $trash: $answer = 3; $probaRx = "probaTrash"; break; + default: mDie(5, "Réponse invalide pour le mot $num."); } - $db->exec("commit;"); - // On renvoie une nouvelle partie pour garder le client toujours bien alimenté. - game2json(random_game()); - } else { - die("Commande inconnue"); + + $probas = array($row['probaR1']/$row['totalWeight'], $row['probaR2']/$row['totalWeight'], $row['probaR0']/$row['totalWeight'], $row['probaTrash']/$row['totalWeight']); + // Calcul du score. Score = proba[réponse de l'utilisateur]*coeff1 - proba[autres reponses]*coeff2 + // score = - proba[autres reponses]*coeff2 + $score = -0.7 * (($probas[0] + $probas[1] + $probas[2] + $probas[3]) - $probas[$answer]); + // ici, -0.7 <= score <= 0 + // score = proba[réponse de l'utilisateur]*coeff1 - proba[autres reponses]*coeff2 + $score += ($row['difficulty']/5) * $probas[$answer]; + // ici, -0.7 <= score <= 2 + // Adapter le score en fonction de la réputation de l'utilisateur (quand il est jeune, augmenter le score pour le motiver). + $score += min(2 - max(0, ($userReputation / 4) - 1), 2); + // ici, -0.7 <= score <= 4 + + $db->exec("insert into played_game_cloud(pgid, gid, type, num, relation, weight, score) values($pgid, $gid, 1, $num, $r1, ".$userReputation.", ".$score.");"); + $db->exec("update game_cloud set $probaRx = $probaRx + ".max($réputationJoueur,1)." where gid = $gid;"); + $db->exec("update game_cloud set totalWeight = totalWeight + ".max($réputationJoueur,1)." where gid = $gid;"); + $db->exec("update user set score = score + ".$score." where login = $user;"); } + + $db->exec("commit;"); + // On renvoie une nouvelle partie pour garder le client toujours bien alimenté. + game2json(random_game()); } main($action);