Zdrojové soubory jsou k dispozici pod
GNU GENERAL PUBLIC LICENSE
, Sven Dražan (c) 2013
<?php /** * Tournament of strategies for N-trophy 2013. * Available under the GNU GENERAL PUBLIC LICENSE, see copying.txt * * @author Sven Dražan <sven@mail.muni.cz> */ function html_header($title) { return '<!DOCTYPE html> <html lang="cz" dir="ltr" class="client-nojs"> <head> <title>'.$title.'</title> <meta charset="UTF-8" /> </head> <style type="text/css"> body { font-family: Verdana; font-size: 13px; } table.results { text-align:center; border-top: 1px solid black; border-right: 1px solid black; } .results a { text-decoration: none; } table.results th { background-color: rgb(150,180,250); border-left: 1px solid rgb(0,0,50); border-bottom: 1px solid rgb(0,0,50); } table.results td { border-left: 1px solid rgb(0,0,50); border-bottom: 1px solid rgb(0,0,50); } td.podraz { background-color: rgb(255,100,100); } td.spoluprace { background-color: rgb(100,255,100); } td.celkem { border-left: 2px solid rgb(0,0,50); color: rgb(100,100,100); font-weight: bold; } td.body { color: rgb(50,0,50); font-weight: bold; } div.errorbox { border: 1px solid red; background-color: rgb(255,100,100); } .hint { cursor:help; } textarea, .edit { width: 97%; } .smaller { font-size: 80%; } .left { text-align: left; } table.results td a { font-size: 80%; color: black; } table.results td a:hover { font-size: 80%; color: blue; } checkbox { float: left; } .invisible { display:none; } </style> <body> '; } echo html_header('Čmelosauři - Turnaj strategií'); /** * Checks wheather the pattern consists only of 0s and 1s and is at most 6 characters long. */ function check_pattern($pat) { $pat .= ''; if ($pat == '*') return true; if (strlen($pat) > 6) return 'vzor je moc dlouhý'; for ($i = 0; $i<strlen($pat); $i++) { if ($pat[$i] != '0' && $pat[$i] != '1') return 'znak vzoru "'.$pat[$i].'" není 0 ani 1'; } return true; } /** * Loads the strategy from an array of text lines into an strategy array. * In case of errors an message is returned, otherwise the strategy array. * * A correct strategy consists of lines expressing individual rules. * Each rule consists of a pattern and a choice part separated by spaces. * The pattern part has form [01]{0,7} or [01]{0,7}:[01]{0,7} where the semicolon * divides the history of the other player from the strategy's own history. * * A choice without history '*' must be present for a strategy to be correct. */ function load_strategy($lines) { $s = array(); $type = 'deterministic'; foreach ($lines as $i => $line) { $index = $i+1; $line = trim($line); if ($line == '' || strpos($line,'#') === 0) continue; if (($delim = strpos($line,' ')) === false) return "Chyba v pravidle č.".$index.": chybí mezera"; $patternstr = trim(substr($line,0,$delim)); $choice = trim(substr($line,$delim+1)); $parts = explode(':',$patternstr); if (count($parts) > 2) return 'Chyba v pravidle č.'.$index.': ve vzoru "'.$patternstr.'" se oddělovač ":" vyskytuje více než jednou'; if (count($parts) == 1) $parts[] = '*'; $otherpattern = $parts[0]; $mypattern = $parts[1]; $othercheck = check_pattern($otherpattern); if ($othercheck !== true) return 'Chyba v pravidle č.'.$index.': vzor "'.$otherpattern.'": '.$othercheck; $mycheck = check_pattern($mypattern); if ($mycheck !== true) return 'Chyba v pravidle č.'.$index.': vzor "'.$mypattern.'": '.$mycheck; if (!is_numeric($choice)) return 'Chyba v pravidle č. '.$index.': volba '.$choice.' není číslo'; if ($choice < 0 || $choice > 1) return 'Chyba v pravidle č. '.$index.' volba '.$choice.' není v intervalu [0,1]'; if ($choice > 0 && $choice < 1) $type = 'probabilistic'; $s[$index] = array('otherpattern' => $otherpattern, 'mypattern' => $mypattern, 'choice' => $choice+0.0, 'num' => $index); } $defchoice = false; foreach ($s as $rule) { if ($rule['otherpattern'] == '*' && $rule['mypattern'] == '*') $defchoice = true; } $s['type'] = $type; $s['def'] = $lines; if (!$defchoice) return 'Chyba v definici, chybí implicitní pravidlo *'; return $s; } /* * Returns a choice {0,1} given the strategy and a history of my previous choices * and the choices of the other player. */ function makechoice($s,$mychoices,$otherchoices,&$rulenum,&$deterministic) { foreach ($s as $index => $rule) { if ($index == 'type') continue; if (($rule['mypattern'] == '*' || substr($mychoices,0,strlen($rule['mypattern'])) === $rule['mypattern']) && ($rule['otherpattern'] == '*' || substr($otherchoices,0,strlen($rule['otherpattern'])) === $rule['otherpattern']) ) { $rulenum = $rule['num']; if ($rule['choice'] == 1.0 || $rule['choice'] == 0.0) { $deterministic &= true; return $rule['choice']; } else { $deterministic &= false; return (mt_rand(1,100)/100 < $rule['choice'] ? 1 : 0); } } } } /* * Returns an array(1 => score1, 2 => score2) depending on choice1 and choice2. */ function getscore($c1,$c2) { $scores = array('00' => array(1,1), // Positive scores / kg of fruit rewards '01' => array(5,0), '10' => array(0,5), '11' => array(3,3)); /*$scores = array('00' => array(10,10), // Negative scores / years in prison '01' => array(0,25), '10' => array(25,0), '11' => array(1,1));*/ return $scores[$c1.$c2.'']; } /* * Plays $iter number of rounds between two given strategies. * Returns an array (choices1, choices2, score1, score2, type) * * If both strategies played using only deterministic rules * deterministic == true, else false. */ function playgame($s1, $s2, $iter, $errors = 0) { $choices = array(1 => '', 2 => ''); $rules = array(1 => array(), 2 => array()); $scores = array(1 => 0, 2 => 0); $deterministic = true; for ($i = 0; $i< $iter; $i++) { $tmp = 0; $choice1 = makechoice($s1,$choices[1],$choices[2],$tmp,$deterministic); if ($errors > 0 && mt_rand(0,100) < $errors) { $choice1 = -$choice1+1; //FIXME into rules or choices } $rules[1][] = $tmp; $choice2 = makechoice($s2,$choices[2],$choices[1],$tmp,$deterministic); if ($errors > 0 && mt_rand(0,100) < $errors) { $choice2 = -$choice2+1; //FIXME into rules or choices } $rules[2][] = $tmp; $score = getscore($choice1, $choice2); $choices[1] = $choice1.$choices[1]; $choices[2] = $choice2.$choices[2]; $scores[1] += $score[0]; $scores[2] += $score[1]; } return array('choices' => $choices, 'rules' => $rules, 'scores' => $scores, 'deterministic' => $deterministic); } /* * Reverses a string. */ function strflip($str) { $res = ''; $len = strlen($str); for ($i = 0; $i < $len; $i++) { $res .= $str[$len-$i-1]; } return $res; } function rule2str($rule) { return $rule['otherpattern'].':'.$rule['mypattern'].' '.$rule['choice']; } /** * Prints a series of games of the two given strategies. */ function printgames($games,$s1,$s2,$toplink = false) { $iter = strlen($games['games'][1]['choices'][1]); $out = ''; if ($toplink) $out .= '<a href="#top">Nahoru na přehled výsledků</a><br/><br/>'; else $out .= '<a href="summary.html">Výsledky</a> | <a href="summary_sorted.html">Seřazené</a><br/><br/>'; $out .= '<table class="" cellpadding="0" cellspacing="0">'; for ($g = 1; $g <= count($games['games']); $g++) { $game = $games['games'][$g]; $out .= '<td> <table class="results smaller" cellpadding="2px" cellspacing="0"> <tr> <th></th> <th colspan="4">'.$s1['name'].'</th> <th></th> <th colspan="4">'.$s2['name'].'</th> </tr> <tr> <th>#</th> <th title="Historie">H</th> <th title="Pravidlo">P</th> <th title="Volba">V</th> <th title="Body">B</th> <th></th> <th title="Body">B</th> <th title="Volba">V</th> <th title="Pravidlo">P</th> <th title="Historie">H</th> </tr>'; $coopcntr1 = 0; $coopcntr2 = 0; for ($i = 0; $i < $iter; $i++) { $out .= '<tr>'; $out .= '<td>'.($i+1).'</td>'; $out .= '<td>'.($i>0?(substr($game['choices'][1],-$i,6)):'').'</td>'; $out .= '<td class="hint" title="'.rule2str($s1[$game['rules'][1][$i]]).'">'.$game['rules'][1][$i].'.</td>'; $choice1 = $game['choices'][1][$iter-$i-1]; if ($choice1 == 1) $coopcntr1++; $choice2 = $game['choices'][2][$iter-$i-1]; if ($choice2 == 1) $coopcntr2++; $score = getscore($choice1,$choice2); $out .= '<td class="'.($choice1==1?'spoluprace':'podraz').'">'.$choice1.'</td>'; $out .= '<td>'.$score[0].'</td>'; $out .= '<td></td>'; $out .= '<td>'.$score[1].'</td>'; $out .= '<td class="'.($choice2==1?'spoluprace':'podraz').'">'.$choice2.'</td>'; $out .= '<td class="hint" title="'.rule2str($s2[$game['rules'][2][$i]]).'">'.$game['rules'][2][$i].'.</td>'; $out .= '<td>'.($i>0?(substr($game['choices'][2],-$i,6)):'').'</td>'; $out .= '</tr>'; } $out .= '<tr><td colspan="3">Celkem</td> <td>'.$coopcntr1.':'.($iter-$coopcntr1).'</td> <td class="celkem">'.$game['scores'][1].'</td> <td> </td> <td class="celkem">'.$game['scores'][2].'</td> <td>'.$coopcntr2.':'.($iter-$coopcntr2).'</td> <td colspan="2">Celkem</td> </tr>'; $out .= '</table></td><td> </td>'; } $out .= '</table>'; return $out; } /** * Plays a tournament all against all given strategies. * Each game between two strategies has $rounds rounds and in case of * probabilistic strategies the optional $repeat parameter may be given to * specify how many times should each game be repeated, in this case the * overall score is a total over all repeated games. * * Results are a 2D array of individual games indexed by indices of both * strategies. An order of strategies according to score is also given. */ function tournament($strategie,$rounds,$repeat,&$gameresults,&$order,$errors) { $gameresults = array(); $order = array(); for ($i = 0; $i<count($strategie); $i++) { $rowsum = 0; $gameresults[$i] = array(); for ($j = 0; $j<count($strategie); $j++) { if ($j >= $i) { $games = array('games' => array(), 'score' => array(1 => 0, 2 => 0)); if ($strategie[$i]['type'] == 'deterministic' && $strategie[$j]['type'] == 'deterministic' && $errors == 0) { $game = playgame($strategie[$i],$strategie[$j],$rounds); $games['games'][1] = $game; $games['score'][1] = $game['scores'][1] * $repeat; $games['score'][2] = $game['scores'][2] * $repeat; } else { for ($k = 1; $k <= $repeat; $k++) { $game = playgame($strategie[$i],$strategie[$j],$rounds,$errors); $games['games'][$k] = $game; if ($game['deterministic'] && $errors == 0) { $games['score'][1] = $game['scores'][1] * $repeat; $games['score'][2] = $game['scores'][2] * $repeat; break; } else { $games['score'][1] += $game['scores'][1]; $games['score'][2] += $game['scores'][2]; } } } $gameresults[$i][$j] = $games; } else { $games = $gameresults[$j][$i]; $games2 = array('games' => array(), 'score' => array(1 => $games['score'][2], 2 => $games['score'][1])); foreach ($games['games'] as $index => $game) { $games2['games'][$index] = array( 'choices' => array(1 => $game['choices'][2], 2 => $game['choices'][1]), 'rules' => array(1 => $game['rules'][2], 2 => $game['rules'][1]), 'scores' => array(1 => $game['scores'][2], 2 => $game['scores'][1])); } $gameresults[$i][$j] = $games2; $games = $games2; } $rowsum += $games['score'][1]; } $order[$i] = $rowsum; } asort($order); $order = array_reverse($order,true); //comment out for negative rewards $min = min($order); $max = max($order); /* Best gets 5 points, worst 0, others proportionaly */ foreach ($order as $index => $sum) { $points = 5.0 * ($sum - $min) / ($max - $min); $order[$index] = array('sum' => $sum, 'points' => $points); } $gameresults['minsumscore'] = $min; $gameresults['maxsumscore'] = $max; $min = $gameresults[0][0]['score'][1]; $max = $min; for ($i = 0; $i<count($strategie); $i++) { for ($j = 0; $j<count($strategie); $j++) { $min = min($min,$gameresults[$i][$j]['score'][1]); $max = max($max,$gameresults[$i][$j]['score'][1]); } } $gameresults['minscore'] = $min; $gameresults['maxscore'] = $max; return true; } /* Returns a rgb CSS value of the given number that must be between 0 and 1. */ function rainbow_scale($scale) { $rainbow = array( array(255, 0, 0), // 0.0 array(255, 255, 0), array(0, 255, 0) ); $cnt = count($rainbow)-1; $low = floor($scale*$cnt); if ($low == $cnt) $low--; $high = $low + 1; $low_w = 1 - ($scale * $cnt - $low); $high_w = 1 - ($high - $scale * $cnt); $r = $rainbow[$low][0]*$low_w + $rainbow[$high][0]*$high_w; $g = $rainbow[$low][1]*$low_w + $rainbow[$high][1]*$high_w; $b = $rainbow[$low][2]*$low_w + $rainbow[$high][2]*$high_w; return 'rgb('.round($r).','.round($g).','.round($b).')'; } /* * Gives results of a tournament as a table with scores and links. * Rows and columns are in given order. * If $outdir != '' then links to strategies and their respecitve results * are included. */ function scoreboard($strategie, $gameresults, $order, $points, $outdir = '') { $order2 = $order; //foreach resets internal array counter, so a copy must be made $scoreboard = '<table class="results" cellpadding="2px" cellspacing="0"><tr><td>Strategie</td>'; if ($outdir != '') { $scoreboard .= '<td>Def</td>'; } global $default_strategies; foreach ($order as $i) { if ($strategie[$i]['name'] == $default_strategies[$strategie[$i]['type']]['name']) { $name = $strategie[$i]['name']; } else { $name = $strategie[$i]['name'].'<br/><span class="smaller">('.$default_strategies[$strategie[$i]['type']]['name'].')</span>'; } if ($outdir != '') { $scoreboard .= '<th><a href="'.$strategie[$i]['num'].'.txt" title="'.$strategie[$i]['name'].'">'.$name.'</a>'; } else { $scoreboard .= '<th>'.$name.'</th>'; } } $scoreboard .= '<td>Suma</td><td>Body</td>'; $scoreboard .= '</tr>'; foreach ($order as $i) { $scoreboard .= '<tr>'; $scorepage = ''; if ($strategie[$i]['name'] == $default_strategies[$strategie[$i]['type']]['name']) { $name = $strategie[$i]['name']; } else { $name = $strategie[$i]['name'].'<br/><span class="smaller">('.$default_strategies[$strategie[$i]['type']]['name'].')</span>'; } if ($outdir != '') { $scorepage = $strategie[$i]['num'].'.html'; $strategydef = $strategie[$i]['num'].'.txt'; $scoreboard .= '<th class="left"><a href="'.$scorepage.'">'.$name.'</a></th>'; $scoreboard .= '<th><a href="'.$strategydef.'" title="Definice strategie">'.$strategie[$i]['num'].'</a></th>'; } else { $scoreboard .= '<th>'.$name.'</th>'; } foreach ($order2 as $j) { $gametitle = $i.'vs'.$j; $games = $gameresults[$i][$j]; //1 - in case of negative rewards $scoreboard .= '<td style="background-color:'.rainbow_scale($games['score'][1] / $gameresults['maxscore']).'"><a href="'.$scorepage.'#'.$gametitle.'" title="'. $strategie[$i]['name'].' vs. '.$strategie[$j]['name'].'">'. $games['score'][1].':'.$games['score'][2].'</a></td>'; } //1 - in case of negative rewards $scoreboard .= '<td class="celkem" style="background-color:'.rainbow_scale(($points[$i]['sum']-$gameresults['minsumscore'])/($gameresults['maxsumscore']-$gameresults['minsumscore'])).'">'.$points[$i]['sum'].'</td>'; //5 - in case of negative rewards //5 - in case of negative rewards $scoreboard .= '<td class="body" style="background-color:'.rainbow_scale(($points[$i]['points'])/5.0).'">'.round($points[$i]['points'],2).'</td></tr>'."\n"; } $scoreboard .= '</table><br/>'; return $scoreboard; } function file_zip_contents($file,$data,$zip) { if (!is_null($zip)) { if (is_array($data)) { $zip->addFromString($file, implode($data)); } else if (is_string($data)) { $zip->addFromString($file, $data); } } else file_put_contents($file,$data); } /* Gives results of a tournament in ordered and nonordered form. * * In case an outdir is specified, the results are printed into separate files * $outdir.'summary_sorted' with an overall sorted table of results and * $outdir.'summary' with an overall sorted table of unsorted results and * $outdir.$i for all the games of strategy # $i. */ function print_tournament($strategie, $gameresults, $order, $outdir = '', $zip = null) { $out = '<a name="top" />'; if ($outdir != '') { if (is_null($zip) && !file_exists($outdir)) { mkdir($outdir); } for ($i = 0; $i<count($strategie); $i++) { file_zip_contents($outdir.$strategie[$i]['num'].'.txt',$strategie[$i]['def'],$zip); } } $plain = array_keys($strategie); sort($plain); $sorted = array_keys($order); //$scoreboard = scoreboard($strategie, $gameresults, $plain, $order, $outdir); $scoreboard_sorted = scoreboard($strategie, $gameresults, $sorted, $order, $outdir); if ($outdir == '') { echo '<a name="top" />'; echo '<h1>Výsledky turnaje řazené</h1>'; echo $scoreboard_sorted.'<br/><br/>'; //echo '<h1>Výsledky turnaje neřazené</h1>'; //echo $scoreboard.'<br/><br/>'; if (spost('show_games') != '') { echo '<h1>Průběh utkání</h1>'; for ($i = 0; $i<count($strategie); $i++) { for ($j = 0; $j<count($strategie); $j++) { echo '<a name="'.$i.'vs'.$j.'" />'; echo printgames($gameresults[$i][$j],$strategie[$i],$strategie[$j],true); echo '<br/>'; } } } } else { $summary = html_header('Výsledky turnaje řazené'); $summary .= '<h1>Výsledky turnaje řazené</h1>'; $summary .= $scoreboard_sorted; $summary .= '</body></html>'; $summary_file_sort = $outdir.'summary_sorted.html'; file_zip_contents($summary_file_sort,$summary,$zip); $summary = html_header('Výsledky turnaje'); $summary .= '<h1>Výsledky turnaje</h1>'; $summary .= $scoreboard; $summary .= '</body></html>'; $summary_file = $outdir.'summary.html'; file_zip_contents($summary_file,$summary,$zip); if (is_null($zip)) { echo "<h1>Výsledky</h1>\n"; echo "<ul>\n"; echo '<li><a target="_blank" href="'.$summary_file_sort.'">Celkový přehled seřazených výsledků</a></li>'; echo '<li><a target="_blank" href="'.$summary_file.'">Celkový přehled výsledků</a></li>'; echo "</ul>\n"; echo "<h2>Průběhy utkání</h2>\n"; echo "<ul>\n"; for ($i = 0; $i<count($strategie); $i++) { echo '<li><a target="_blank" href="'.$outdir.$strategie[$i]['num'].'.html">'.$strategie[$i]['name'].'</a></li>'; $page = html_header('Výsledky '.$strategie[$i]['name']); $page .= '<h1>Průběhy utkání strategie '.$strategie[$i]['name'].'</h1>'; $page .= '<a name="top" />'; for ($j = 0; $j<count($strategie); $j++) { $page .= '<a name="'.$i.'vs'.$j.'" />'; $page .= '<h2>Proti strategii '.$strategie[$j]['name'].'</h2>'; $page .= printgames($gameresults[$i][$j],$strategie[$i],$strategie[$j]); $page .= '<br/>'; } $page .= '</body></html>'; file_zip_contents($outdir.$strategie[$i]['num'].'.html',$page,$zip); } echo "</ul><br/><br/><br/>\n"; echo true; } else { for ($i = 0; $i<count($strategie); $i++) { $page = html_header('Výsledky '.$strategie[$i]['name']); $page .= '<h1>Průběhy utkání strategie '.$strategie[$i]['name'].'</h1>'; $page .= '<a name="top" />'; for ($j = 0; $j<count($strategie); $j++) { $page .= '<a name="'.$i.'vs'.$j.'" />'; $page .= '<h2>Proti strategii '.$strategie[$j]['name'].'</h2>'; $page .= printgames($gameresults[$i][$j],$strategie[$i],$strategie[$j]); $page .= '<br/>'; } $page .= '</body></html>'; file_zip_contents($outdir.$strategie[$i]['num'].'.html',$page,$zip); } echo "<h1>Výsledky</h1>\n"; echo '<a href="vysledky/'.substr($outdir,0,strlen($outdir)-1).'.zip">Balík s výsledky</a>'; return true; } } } /** * Checks wheater there exists a posted variable of the given name. * If it exists its value is returned, else null. */ function spost($name) { if (isset($_POST[$name])) return $_POST[$name]; else return null; } function sreq($name) { if (isset($_REQUEST[$name])) return $_REQUEST[$name]; else return null; } $default_strategies = array( 'bad' => array('file' => 'bad.txt', 'name' => 'Podvodník'), 'good' => array('file' => 'good.txt', 'name' => 'Dobrák'), 'chuck' => array('file' => 'chuck.txt', 'name' => 'Chuck'), 'random' => array('file' => 'random.txt', 'name' => 'Random'), 'clumsy' => array('file' => 'nesika.txt', 'name' => 'Nešika'), 'joker' => array('file' => 'joker.txt', 'name' => 'Joker'), 'tft' => array('file' => 'oko_za_oko.txt', 'name' => 'Oko za oko'), 'tf2t' => array('file' => 'oko_za_dve_oci.txt', 'name' => 'Oko za dvě oči'), 'tftfgv' => array('file' => 'tit4tat_fgv.txt', 'name' => 'Oko za oko odpouštějící'), 'chuck_agr' => array('file' => 'chuck_agr.txt', 'name' => 'Chuck troufalý'), 'chuck_odp' => array('file' => 'chuck_fgv.txt', 'name' => 'Chuck odpouštějící'), 'elefant' => array('file' => 'slon.txt', 'name' => 'Slon'), 'random_start' => array('file' => 'random_start.txt', 'name' => 'Random start'), 'oscilator' => array('file' => 'oscilator.txt', 'name' => 'Oscilátor'), 'twoface' => array('file' => 'twoface.txt', 'name' => 'Two face'), 'pavlov' => array('file' => 'pavlov.txt', 'name' => 'Pavlov'), //'envy' => array('file' => 'envy.txt', 'name' => 'Envy'), ); /** * Prints the forms for strategy input. */ function printform() { global $default_strategies; $stratcntr = spost('pocet_strategii'); if (spost('default') !== null) { $stratcntr = 18; $_POST['pocet_strategii'] = 18; /*$files = array('bad.txt','good.txt','chuck.txt','random.txt','nesika.txt','joker.txt'); $names = array('Podvodník','Dobrák','Chuck','Náhoda','Nešika','Joker'); foreach ($files as $index => $file) { $_POST['strategie'.$index] = file_get_contents('default/'.$file); $_POST['nazev_strategie'.$index] = $names[$index]; $_POST['typ_strategie'.$index] = }*/ $index = 0; foreach ($default_strategies as $type => $strat) { $_POST['strategie'.$index] = file_get_contents('default/'.$strat['file']); $_POST['nazev_strategie'.$index] = $strat['name']; $_POST['typ_strategie'.$index] = $type; $index++; } } echo '<form method="post" action="strategie.php">'; echo '<table cellspacing="0" border="0" width="100%">'; if (!is_numeric($stratcntr) || (($stratcntr % 6) !== 0) || ($stratcntr < 6) || ($stratcntr > 30)) $stratcntr = 6; for ($j=0; $j < ($stratcntr/6); $j++) { echo '<tr>'; for ($i=$j*6; $i<($j+1)*6; $i++) { echo '<td>Jméno hráče<br /> <input name="nazev_strategie'.$i.'" value="'.spost('nazev_strategie'.$i).'" class="edit" type="text" /> <select name="typ_strategie'.$i.'" class="edit">'; foreach ($default_strategies as $key => $sdata) { echo '<option value="'.$key.'" '.(spost('typ_strategie'.$i) == $key?' selected="selected"':'').'>'.$sdata['name'].'</option>'; } echo '<option value="custom" '.(spost('typ_strategie'.$i) == 'custom' || spost('typ_strategie'.$i) == ''?' selected="selected"':'').'">Vlastní definice</option>'; echo '</select> <br />Definice<br />'; if (spost('typ_strategie'.$i) !== 'custom' && spost('typ_strategie'.$i) != '') { $_POST['strategie'.$i] = file_get_contents('default/'.$default_strategies[spost('typ_strategie'.$i)]['file']); } echo '<textarea '.(spost('show_definitions')?'':' class="invisible"').' name="strategie'.$i.'" rows="15" wrap="off">'.spost('strategie'.$i).'</textarea></td>'; } echo '</tr>'; } echo '<tr><td colspan="4">'; echo 'Počet kol každého utkání <select name="pocet_kol">'; for ($i=2; $i<16; $i++) echo '<option value="'.($i*10).'"'.(spost('pocet_kol') == ($i*10)?' selected="selected"':'').'>'.($i*10).'</option>'; echo '</select> '; echo 'Počet opakování turnaje <select name="pocet_opakovani">'; for ($i=1; $i<11; $i++) echo '<option value="'.$i.'"'.(spost('pocet_opakovani') == $i?' selected="selected"':'').'>'.$i.'</option>'; echo '</select> '; echo '<input type="submit" name="odeslat" value="Odehrát turnaj" class="button">'; echo '<div style="float:right">Počet strategií <select name="pocet_strategii">'; for ($i=1; $i<6; $i++) echo '<option value="'.($i*6).'"'.(spost('pocet_strategii') == ($i*6)?' selected="selected"':'').'>'.($i*6).'</option>'; echo '</select> '; echo '<input type="submit" name="zmenit" value="Změnit" class="button"></div></td>'; echo '<td colspan="2" style="text-align:right;"> <a href="format.php" target="_blank">Formát definice strategií</a> <input type="submit" name="default" value="Nahrát příklady" class="button" /> </td>'; echo '</tr> <tr> <td class="left">Chyby v prostředí <input name="chyby" type="text" value="'.(is_numeric(spost('chyby'))?spost('chyby'):'0').'" maxlength="2" style="width:2em"/>%</td> <td colspan="5" class="left"> Výstup do ZIPu <input name="zip" value="zip" class="checkbox" type="checkbox"> Ukázat výsledky her<input name="show_games" value="1" '.(spost('show_games')?' checked="checked"':'').' class="checkbox" type="checkbox"/> Ukázat definice strategií<input name="show_definitions" value="1" '.(spost('show_definitions')?' checked="checked"':'').' class="checkbox" type="checkbox"> </td></tr>'; echo '</table></form>'; } function load_strategies() { $err = ''; global $default_strategies; $strategie = array(); $stratcntr = spost('pocet_strategii'); if (!is_numeric($stratcntr) || (($stratcntr % 6) !== 0) || ($stratcntr < 6) || ($stratcntr > 30)) $stratcntr = 6; if (spost('odeslat') !== null || spost('zmenit') !== null) { for ($i = 0; $i<$stratcntr; $i++) { $name = spost('nazev_strategie'.$i); $type = spost('typ_strategie'.$i); if ($name == '') $name = $default_strategies[$type]['name']; $data = spost('strategie'.$i); if ($data != null && $data != '') { $data = explode("\n",$data); $tmp = load_strategy($data); if (is_string($tmp) === true) { $err .= 'Chyba v definici strategie #'.$i.' ('.$name.'):<br />'; $err .= $tmp.'<br />'; } else { $tmp['num'] = str_pad(($i+1).'',3,'0',STR_PAD_LEFT); $tmp['name'] = $name; $tmp['type'] = $type; $strategie[] = $tmp; } } } } if ($err != '') { echo '<div class="errorbox">'.$err.'</div>'; } return $strategie; } /** * Multibyte safe version of trim() * Always strips whitespace characters (those equal to \s) * * @author Peter Johnson * @email phpnet@rcpt.at * @param $string The string to trim * @param $chars Optional list of chars to remove from the string ( as per trim() ) * @param $chars_array Optional array of preg_quote'd chars to be removed * @return string */ function mb_trim( $string, $chars = "", $chars_array = array() ) { for( $x=0; $x<iconv_strlen( $chars ); $x++ ) $chars_array[] = preg_quote( iconv_substr( $chars, $x, 1 ) ); $encoded_char_list = implode( "|", array_merge( array( "\s","\t","\n","\r", "\0", "\x0B" ), $chars_array ) ); $string = mb_ereg_replace( "^($encoded_char_list)*", "", $string ); $string = mb_ereg_replace( "($encoded_char_list)*$", "", $string ); return $string; } /** * Loads strategies from separate files given as another filelist file. * * File names are expected to be in form "XXX - Name.txt" where XXX is the * number. * * The first line of each file is expected to contain the name of the strategy. * * The file encoding is expected to be UTF-8. */ function load_file_strategies($filelist,$dirprefix = '') { $strategie = array(); $list = file($filelist); foreach ($list as $file) { $file = trim($file); $data = file($dirprefix.$file); $tmp = load_strategy($data); if (is_string($tmp) === true) echo $tmp; else { $tmp['file'] = $dirprefix.$file; $tmp['num'] = mb_substr($file,0,3); $tmp['name'] = mb_trim(mb_substr($data[0],1,mb_strlen($data[0],'UTF-8'),'UTF-8')); $strategie[] = $tmp; } } return $strategie; } ?> <h1>Turnaj strategií</h1> <p style="font-size:80%"> Zde můžete zkoušet svoje čmelosauří strategie do turnaje. Nezapomeňte si své rozpracované strategie vždy uložit do souboru na lokální disk, po vypnutí prohlížeče bude obsah formulářů vymazán. Návrat na <a href="zadani.html">zadání</a>.<br /> Pokud by někdo chtěl provádět vlastní experimenty, zdrojový PHP kod je k dispozici <a href="zdroj.php">zde</a>. <b>Otázky od týmů a naše odpovědi na ně najdete <a href="otazky.html">zde</a></b>. <br /> </p> <?php printform(); echo '<img src="cmelosaurus2.png" style="float:right" />'; $strategie = load_strategies(); // $strategie = load_file_strategies('list.txt','strategie/'); // mt_srand(1); if (spost('odeslat') != null && count($strategie) > 0) { $rounds = spost('pocet_kol')+0; if (!is_numeric($rounds) || $rounds < 20 || $rounds > 150) $rounds = 20; $repeat = spost('pocet_opakovani')+0; if (!is_numeric($repeat) || $repeat < 1 || $repeat > 10) $repeat = 1; $errors = spost('chyby')+0.0; if (!is_numeric($errors) || $errors < 0 || $errors > 50) $errors = 0; $gameresults = array(); $order = array(); tournament($strategie,$rounds,$repeat,$gameresults,$order,$errors); $time = time(); if (spost('zip') == 'zip') { $zip = new ZipArchive; $res = $zip->open('vysledky/'.$time.'.zip', ZipArchive::CREATE); if ($res === true) { $zip->addEmptyDir($time); print_tournament($strategie,$gameresults, $order, $time.'/', $zip); $zip->close(); } else { echo 'ZIP failed'; print_tournament($strategie,$gameresults, $order); } } else { print_tournament($strategie, $gameresults, $order); } } ?> </body> </html>