├── .gitignore ├── LICENSE ├── README.md ├── analyze.sh ├── clear.sh ├── examples ├── curve.png ├── output.png └── score.png ├── kill.sh ├── result.sh ├── scripts ├── automonitor ├── curve.gp ├── map.gp ├── parse.awk └── process.py ├── start.tmpl ├── Helios2010 ├── Helios2011 ├── Helios2015 ├── Marlik ├── Oxsy └── WrightEagle ├── start_left ├── start_right └── test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | log.d 2 | log.d_* 3 | result.d 4 | result.d_* 5 | result.html 6 | index.html 7 | *.*~ 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Aijun Bai 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # autotest2d 2 | Auto test scripts for RoboCup soccer simulation 2d games 3 | 4 | ## Usages 5 | * Configure `PROCES` in `test.sh` as the number of simultaneously running rcssservers (each rcssserver will run in a different port automatically) 6 | * Configure `CLIENTS` in `test.sh` to be the list of client machines running teams 7 | * Make sure you can login to `CLIENTS` using `ssh` without typing password from the machine (which is a server) you run `test.sh` 8 | * Deploy the testing teams (left and right) to `CLIENTS`, for example, using `scp` 9 | * Configure `start_left` and `start_right` scripts to start left and right teams 10 | * Run `test.sh` from the central server to start the auto test 11 | * Use in combination with [lanmonitor](https://github.com/wrighteagle2d/lanmonitor) to monitor the testing status 12 | 13 | ## Files 14 | * test.sh -- run auto test 15 | * kill.sh -- stop test 16 | * result.sh -- show result 17 | * analyze.sh -- show more information 18 | * start\_left -- script to start left team 19 | * start\_right -- script to start right team 20 | * start.tmpl -- templates of start scripts 21 | * scripts/automonitor -- start monitors 22 | 23 | ## Example outputs: 24 | - Output: 25 | ![examples/output.png](examples/output.png "Output") 26 | 27 | - Game Curve: 28 | ![examples/curve.png](examples/curve.png "Game Curve") 29 | 30 | - Score Map: 31 | ![examples/score.png](examples/score.png "Score Map") 32 | 33 | -------------------------------------------------------------------------------- /analyze.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CURVE="true" 4 | MAP="true" 5 | 6 | RESULT_DIR="result.d" 7 | CURVE_DATA="$RESULT_DIR/curve" 8 | MAP_DATA="$RESULT_DIR/map" 9 | GNUPLOT_CURVE="./scripts/curve.gp" 10 | GNUPLOT_MAP="./scripts/map.gp" 11 | 12 | [ -d $RESULT_DIR ] || exit 13 | 14 | 15 | if [ $CURVE = "true" ]; then 16 | ./result.sh --curve > $CURVE_DATA 17 | $GNUPLOT_CURVE 18 | else 19 | echo "$0 -c to output winrate curve" 20 | fi 21 | 22 | if [ $MAP = "true" ]; then 23 | ./result.sh --map > $MAP_DATA 24 | $GNUPLOT_MAP 25 | else 26 | echo "$0 -m to output score map" 27 | fi 28 | 29 | 30 | -------------------------------------------------------------------------------- /clear.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash - 2 | #=============================================================================== 3 | # 4 | # FILE: clear.sh 5 | # 6 | # USAGE: ./clear.sh 7 | # 8 | # DESCRIPTION: 9 | # 10 | # OPTIONS: --- 11 | # REQUIREMENTS: --- 12 | # BUGS: --- 13 | # NOTES: --- 14 | # AUTHOR: YOUR NAME (), 15 | # ORGANIZATION: 16 | # CREATED: 02/24/2016 17:36 17 | # REVISION: --- 18 | #=============================================================================== 19 | 20 | set -o nounset # Treat unset variables as an error 21 | 22 | rm -fr log.d/ result.d/ log.d_* result.d_* result.html 23 | 24 | -------------------------------------------------------------------------------- /examples/curve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wrighteagle2d/autotest2d/665a89b86c376e3ce2dd7b4a8fea4a9f89a31fca/examples/curve.png -------------------------------------------------------------------------------- /examples/output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wrighteagle2d/autotest2d/665a89b86c376e3ce2dd7b4a8fea4a9f89a31fca/examples/output.png -------------------------------------------------------------------------------- /examples/score.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wrighteagle2d/autotest2d/665a89b86c376e3ce2dd7b4a8fea4a9f89a31fca/examples/score.png -------------------------------------------------------------------------------- /kill.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>/dev/null 4 | 5 | killall -9 test.sh 6 | killall -9 rcssserver 7 | killall -9 rcssserver.bin 8 | 9 | rm -f "/tmp/autotest::temp" 10 | 11 | -------------------------------------------------------------------------------- /result.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RESULT_DIR="result.d" 4 | PARSE="../scripts/parse.awk" 5 | PROCESS="../scripts/process.py" 6 | 7 | cd $RESULT_DIR 2>/dev/null || exit 8 | 9 | spinner() { 10 | local DELAY=0.05 11 | 12 | while [ 1 ]; do 13 | echo -n '/' ; sleep $DELAY 14 | echo -n '-' ; sleep $DELAY 15 | echo -n '\' ; sleep $DELAY 16 | echo -n '|' ; sleep $DELAY 17 | done 18 | } 19 | 20 | SPINNER_PID=-1 21 | if [ $# -le 0 ]; then 22 | spinner & 23 | SPINNER_PID=$! 24 | fi 25 | 26 | RESULT=`mktemp` 27 | RESULT_LIST=`ls -1 | grep '[0-9]\+' | sort -n` 28 | echo >>$RESULT 29 | 30 | parseall() { 31 | local TITLE="N/A" 32 | local CACHE_DIR="cache.d" 33 | local CACHE_FILE="$CACHE_DIR/cache" 34 | 35 | mkdir $CACHE_DIR 2>/dev/null 36 | touch $CACHE_FILE 37 | chmod 777 $CACHE_DIR $CACHE_FILE 2>/dev/null 38 | 39 | for i in $RESULT_LIST; do 40 | if [ "$TITLE" = "N/A" ]; then 41 | TITLE=`cat $i | grep '\' | sed -e 's/\t//g'` 42 | if [ -z "$TITLE" ]; then 43 | TITLE="N/A" 44 | fi 45 | fi 46 | if [ ! -f $CACHE_DIR/$i ]; then 47 | local OUTPUT=`awk -f $PARSE $i` 48 | if [ ! -z "$OUTPUT" ]; then 49 | echo "$OUTPUT" >>$CACHE_FILE 50 | touch $CACHE_DIR/$i 51 | fi 52 | fi 53 | done 54 | 55 | echo $TITLE 56 | cat $CACHE_FILE 57 | } 58 | 59 | parseall | python $PROCESS $* >>$RESULT 60 | 61 | if [ $SPINNER_PID -gt 0 ]; then 62 | exec 2>/dev/null 63 | kill $SPINNER_PID 64 | fi 65 | 66 | cat $RESULT 67 | rm -f $RESULT 68 | 69 | -------------------------------------------------------------------------------- /scripts/automonitor: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #第一个参数是server所在机器ip,第二个参数时同时比赛的场数 4 | #调用实例:./automonitor 160 2 5 | 6 | HOST="localhost" 7 | NUM=1 8 | 9 | if [ ! -z $1 ]; then 10 | HOST="192.168.26.$1" 11 | fi 12 | 13 | if [ ! -z $2 ]; then 14 | NUM=$2 15 | fi 16 | 17 | for i in `seq 1 $NUM`; do 18 | PORT=`expr 5000 + $i \* 1000` 19 | rcssmonitor --server-host $HOST --server-port $PORT --auto-reconnect-mode on --auto-reconnect-wait 5 & 20 | done 21 | -------------------------------------------------------------------------------- /scripts/curve.gp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/gnuplot -persist 2 | # 3 | # 4 | # G N U P L O T 5 | # Version 4.2 patchlevel 3 6 | # last modified Mar 2008 7 | # System: Linux 2.6.25-gentoo-r6 8 | # 9 | # Copyright (C) 1986 - 1993, 1998, 2004, 2007, 2008 10 | # Thomas Williams, Colin Kelley and many others 11 | # 12 | # Type `help` to access the on-line reference manual. 13 | # The gnuplot FAQ is available from http://www.gnuplot.info/faq/ 14 | # 15 | # Send bug reports and suggestions to 16 | # 17 | set terminal png font '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansCondensed.ttf,11' size 1280,800 18 | set output "result.d/curve.png" 19 | unset clip points 20 | set clip one 21 | unset clip two 22 | set bar 1.000000 23 | set border 31 front linetype -1 linewidth 1.000 24 | set xdata 25 | set ydata 26 | set zdata 27 | set x2data 28 | set y2data 29 | set timefmt x "%d/%m/%y,%H:%M" 30 | set timefmt y "%d/%m/%y,%H:%M" 31 | set timefmt z "%d/%m/%y,%H:%M" 32 | set timefmt x2 "%d/%m/%y,%H:%M" 33 | set timefmt y2 "%d/%m/%y,%H:%M" 34 | set timefmt cb "%d/%m/%y,%H:%M" 35 | set boxwidth 36 | set style fill empty border 37 | set style rectangle back fc lt -3 fillstyle solid 1.00 border -1 38 | set dummy x,y 39 | set format x "% g" 40 | set format y "% g" 41 | set format x2 "% g" 42 | set format y2 "% g" 43 | set format z "% g" 44 | set format cb "% g" 45 | set angles radians 46 | set grid 47 | set key title "" 48 | set key inside right top vertical Right noreverse enhanced autotitles nobox 49 | set key noinvert samplen 4 spacing 1 width 0 height 0 50 | unset label 51 | unset arrow 52 | set style increment default 53 | unset style line 54 | unset style arrow 55 | set style histogram clustered gap 2 title offset character 0, 0, 0 56 | unset logscale 57 | set offsets 0, 0, 0, 0 58 | set pointsize 1 59 | set encoding default 60 | unset polar 61 | unset parametric 62 | unset decimalsign 63 | set view 60, 30, 1, 1 64 | set samples 100, 100 65 | set isosamples 10, 10 66 | set surface 67 | unset contour 68 | set clabel '%8.3g' 69 | set mapping cartesian 70 | set datafile separator whitespace 71 | unset hidden3d 72 | set cntrparam order 4 73 | set cntrparam linear 74 | set cntrparam levels auto 5 75 | set cntrparam points 5 76 | set size ratio 0 1,1 77 | set origin 0,0 78 | set style data points 79 | set style function lines 80 | set xzeroaxis linetype -2 linewidth 1.000 81 | set yzeroaxis linetype -2 linewidth 1.000 82 | set zzeroaxis linetype -2 linewidth 1.000 83 | set x2zeroaxis linetype -2 linewidth 1.000 84 | set y2zeroaxis linetype -2 linewidth 1.000 85 | set ticslevel 0.5 86 | set mxtics default 87 | set mytics default 88 | set mztics default 89 | set mx2tics default 90 | set my2tics default 91 | set mcbtics default 92 | set xtics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 93 | set xtics autofreq 94 | set ytics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 95 | set ytics autofreq 96 | set ztics border in scale 1,0.5 nomirror norotate offset character 0, 0, 0 97 | set ztics autofreq 98 | set nox2tics 99 | set noy2tics 100 | set cbtics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 101 | set cbtics autofreq 102 | set title "game count - win rate curve" 103 | set title offset character 0, 0, 0 font "" norotate 104 | set timestamp bottom 105 | set timestamp "" 106 | set timestamp offset character 0, 0, 0 font "" norotate 107 | set rrange [ * : * ] noreverse nowriteback # (currently [0.00000:10.0000] ) 108 | set trange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] ) 109 | set urange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] ) 110 | set vrange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] ) 111 | set xlabel "game_count" 112 | set xlabel offset character 0, 0, 0 font "" textcolor lt -1 norotate 113 | set x2label "" 114 | set x2label offset character 0, 0, 0 font "" textcolor lt -1 norotate 115 | set xrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) 116 | set x2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) 117 | set ylabel "rate" 118 | set ylabel offset character 0, 0, 0 font "" textcolor lt -1 rotate by 90 119 | set y2label "" 120 | set y2label offset character 0, 0, 0 font "" textcolor lt -1 rotate by 90 121 | set yrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) 122 | set y2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) 123 | set zlabel "" 124 | set zlabel offset character 0, 0, 0 font "" textcolor lt -1 norotate 125 | set zrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) 126 | set cblabel "" 127 | set cblabel offset character 0, 0, 0 font "" textcolor lt -1 rotate by 90 128 | set cbrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) 129 | set zero 1e-08 130 | set lmargin -1 131 | set bmargin -1 132 | set rmargin -1 133 | set tmargin -1 134 | set locale "C" 135 | set pm3d explicit at s 136 | set pm3d scansautomatic 137 | set pm3d interpolate 1,1 flush begin noftriangles nohidden3d corners2color mean 138 | set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB 139 | set palette rgbformulae 7, 5, 15 140 | set colorbox default 141 | set colorbox vertical origin screen 0.9, 0.2, 0 size screen 0.05, 0.6, 0 front bdefault 142 | set loadpath 143 | set fontpath 144 | set fit noerrorvariables 145 | show grid 146 | plot 'result.d/curve' u 1:2:3:4 with errorbars lt 0 title "95% confidence interval", 'result.d/curve' u 1:2 with lines title "win rate" lt 1 lw 2 147 | # EOF 148 | -------------------------------------------------------------------------------- /scripts/map.gp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/gnuplot -persist 2 | # 3 | # 4 | # G N U P L O T 5 | # Version 4.4 patchlevel 3 6 | # last modified March 2011 7 | # System: Linux 3.2.0-25-generic 8 | # 9 | # Copyright (C) 1986-1993, 1998, 2004, 2007-2010 10 | # Thomas Williams, Colin Kelley and many others 11 | # 12 | # Type `help` to access the on-line reference manual. 13 | # The gnuplot FAQ is available from http://www.gnuplot.info/faq/ 14 | # 15 | # Send bug reports and suggestions to 16 | # 17 | set terminal png font '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansCondensed.ttf,11' size 1280,800 18 | set output "result.d/map.png" 19 | unset clip points 20 | set clip one 21 | unset clip two 22 | set bar 1.000000 23 | set border 31 front linetype -1 linewidth 1.000 24 | set xdata 25 | set ydata 26 | set zdata 27 | set x2data 28 | set y2data 29 | set timefmt x "%d/%m/%y,%H:%M" 30 | set timefmt y "%d/%m/%y,%H:%M" 31 | set timefmt z "%d/%m/%y,%H:%M" 32 | set timefmt x2 "%d/%m/%y,%H:%M" 33 | set timefmt y2 "%d/%m/%y,%H:%M" 34 | set timefmt cb "%d/%m/%y,%H:%M" 35 | set boxwidth 36 | set style fill empty border 37 | set style rectangle back fc lt -3 fillstyle solid 1.00 border -1 38 | set dummy x,y 39 | set format x "% g" 40 | set format y "% g" 41 | set format x2 "% g" 42 | set format y2 "% g" 43 | set format z "% g" 44 | set format cb "% g" 45 | set angles radians 46 | set grid 47 | set key title "" 48 | set key inside right top vertical Right noreverse enhanced autotitles nobox 49 | set key noinvert samplen 4 spacing 1 width 0 height 0 50 | unset label 51 | unset arrow 52 | set style increment default 53 | unset style line 54 | unset style arrow 55 | set style histogram clustered gap 2 title offset character 0, 0, 0 56 | unset logscale 57 | set offsets 0, 0, 0, 0 58 | set pointsize 1 59 | set encoding default 60 | unset polar 61 | unset parametric 62 | unset decimalsign 63 | set view map 64 | set samples 100, 100 65 | set isosamples 10, 10 66 | set surface 67 | unset contour 68 | set clabel '%8.3g' 69 | set mapping cartesian 70 | set datafile separator whitespace 71 | unset hidden3d 72 | set cntrparam order 4 73 | set cntrparam linear 74 | set cntrparam levels auto 5 75 | set cntrparam points 5 76 | set size ratio 0 1,1 77 | set origin 0,0 78 | set style data points 79 | set style function lines 80 | set xzeroaxis linetype -2 linewidth 1.000 81 | set yzeroaxis linetype -2 linewidth 1.000 82 | set zzeroaxis linetype -2 linewidth 1.000 83 | set x2zeroaxis linetype -2 linewidth 1.000 84 | set y2zeroaxis linetype -2 linewidth 1.000 85 | set ticslevel 0.5 86 | set mxtics default 87 | set mytics default 88 | set mztics default 89 | set mx2tics default 90 | set my2tics default 91 | set mcbtics default 92 | set xtics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 93 | set xtics autofreq norangelimit 94 | set ytics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 95 | set ytics autofreq norangelimit 96 | set ztics border in scale 1,0.5 nomirror norotate offset character 0, 0, 0 97 | set ztics autofreq norangelimit 98 | set nox2tics 99 | set noy2tics 100 | set cbtics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 101 | set cbtics autofreq norangelimit 102 | set title "score map" 103 | set title offset character 0, 0, 0 font "" norotate 104 | set timestamp bottom 105 | set timestamp "" 106 | set timestamp offset character 0, 0, 0 font "" norotate 107 | set rrange [ * : * ] noreverse nowriteback # (currently [8.98847e+307:-8.98847e+307] ) 108 | set trange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] ) 109 | set urange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) 110 | set vrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) 111 | set xlabel "" 112 | set xlabel offset character 0, 0, 0 font "" textcolor lt -1 norotate 113 | set x2label "" 114 | set x2label offset character 0, 0, 0 font "" textcolor lt -1 norotate 115 | set xrange [ * : * ] noreverse nowriteback # (currently [-2.00000:12.0000] ) 116 | set x2range [ * : * ] noreverse nowriteback # (currently [-0.500000:11.5000] ) 117 | set ylabel "" 118 | set ylabel offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270 119 | set y2label "" 120 | set y2label offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270 121 | set yrange [ * : * ] noreverse nowriteback # (currently [-1.00000:7.00000] ) 122 | set y2range [ * : * ] noreverse nowriteback # (currently [-0.500000:6.50000] ) 123 | set zlabel "" 124 | set zlabel offset character 0, 0, 0 font "" textcolor lt -1 norotate 125 | set zrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) 126 | set cblabel "" 127 | set cblabel offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270 128 | set cbrange [ * : * ] noreverse nowriteback # (currently [0.00000:0.0900000] ) 129 | set zero 1e-08 130 | set lmargin -1 131 | set bmargin -1 132 | set rmargin -1 133 | set tmargin -1 134 | set locale "en_US.UTF-8" 135 | set pm3d implicit at s 136 | set pm3d scansautomatic 137 | set pm3d interpolate 1,1 flush begin noftriangles nohidden3d corners2color mean 138 | set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB 139 | set palette rgbformulae 7, 5, 15 140 | set colorbox default 141 | set colorbox vertical origin screen 0.9, 0.2, 0 size screen 0.05, 0.6, 0 front bdefault 142 | set loadpath 143 | set fontpath 144 | set fit noerrorvariables 145 | set palette gray negative 146 | show grid 147 | plot 'result.d/map' using 1:2:3 with image title "prob" 148 | # EOF 149 | -------------------------------------------------------------------------------- /scripts/parse.awk: -------------------------------------------------------------------------------- 1 | BEGIN { 2 | valid = 0 3 | 4 | waiting_ln = -1 5 | player_disconnected_ln = -1 6 | coach_disconnected_ln = -1 7 | 8 | left_score = -1 9 | right_score = -1 10 | 11 | left_shoot_count = 0 12 | 13 | miss_count = 0 14 | } 15 | 16 | { 17 | if ($0 ~ /Waiting after end of match/) { 18 | waiting_ln = NR 19 | } 20 | else if ($0 ~ /A player disconnected/) { 21 | if (player_disconnected_ln <= 0) { 22 | player_disconnected_ln = NR 23 | } 24 | } 25 | else if ($0 ~ /An online coach disconnected/) { 26 | if (coach_disconnected_ln <= 0) { 27 | coach_disconnected_ln = NR 28 | } 29 | } 30 | else if ($0 ~ /Score:/) { 31 | left_score = $2 32 | right_score = $4 33 | } 34 | else if ($0 ~ /miss a turn_neck/) { 35 | miss_count += 1 36 | } 37 | else if ($0 ~ /shoot at/) { 38 | left_shoot_count += 1 39 | } 40 | } 41 | 42 | END { 43 | if (waiting_ln >= 0 && player_disconnected_ln > waiting_ln && coach_disconnected_ln > waiting_ln) { 44 | valid = 1 45 | } 46 | 47 | if (left_score >= 0 && right_score >= 0) { 48 | print left_score, right_score, left_shoot_count, valid, miss_count, FILENAME 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /scripts/process.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | import math 5 | from collections import defaultdict 6 | from optparse import OptionParser 7 | 8 | class Color: 9 | (NONE, RED, ORANGE, GREEN, BLUE, PURPLE, GRAY) = range(7) 10 | 11 | class Face: 12 | (NORMAL, MONOSPACE) = range(2) 13 | 14 | class Context: 15 | class Line: 16 | def __init__(self, string, color=Color.NONE, face=Face.NORMAL): 17 | self.color = color 18 | self.face = face 19 | self.string = string 20 | 21 | def __init__(self): 22 | self.lines = [] 23 | 24 | def add_line(self, line): 25 | self.lines.append(line) 26 | 27 | def dump(self, method): 28 | for line in self.lines: 29 | print method(line) 30 | 31 | #dump methods 32 | def console(line): 33 | string = "" 34 | 35 | if line.color == Color.RED: 36 | string += "\033[01;31m" 37 | elif line.color == Color.GREEN: 38 | string += "\033[01;32m" 39 | elif line.color == Color.ORANGE: 40 | string += "\033[01;33m" 41 | elif line.color == Color.BLUE: 42 | string += "\033[01;34m" 43 | elif line.color == Color.PURPLE: 44 | string += "\033[01;35m" 45 | elif line.color == Color.GRAY: 46 | string += "\033[01;30m" 47 | 48 | string += line.string 49 | 50 | if line.color != Color.NONE: 51 | string += "\033[0m" 52 | 53 | return string 54 | 55 | def no_color(line): 56 | return line.string 57 | 58 | def discuz(line): 59 | string = "" 60 | 61 | if line.color == Color.RED: 62 | string += "[color=Red]" 63 | elif line.color == Color.ORANGE: 64 | string += "[color=Orange]" 65 | elif line.color == Color.GREEN: 66 | string += "[color=Green]" 67 | elif line.color == Color.BLUE: 68 | string += "[color=Blue]" 69 | elif line.color == Color.PURPLE: 70 | string += "[color=Purple]" 71 | elif line.color == Color.GRAY: 72 | string += "[color=Gray]" 73 | 74 | if line.face == Face.MONOSPACE: 75 | string += "[font=Monospace]" 76 | 77 | string += line.string 78 | 79 | if line.face != Face.NORMAL: 80 | string += "[/font]" 81 | if line.color != Color.NONE: 82 | string += "[/color]" 83 | 84 | return string 85 | 86 | def html(line): 87 | string = "" 88 | line.face = Face.MONOSPACE #special case for html output 89 | 90 | if line.color == Color.RED: 91 | string += "" 92 | elif line.color == Color.ORANGE: 93 | string += "" 94 | elif line.color == Color.GREEN: 95 | string += "" 96 | elif line.color == Color.BLUE: 97 | string += "" 98 | elif line.color == Color.PURPLE: 99 | string += "" 100 | elif line.color == Color.GRAY: 101 | string += "" 102 | 103 | if line.face == Face.MONOSPACE: 104 | string += "" 105 | 106 | string += line.string.replace(" ", " ") 107 | 108 | if line.face != Face.NORMAL: 109 | string += "" 110 | if line.color != Color.NONE: 111 | string += "" 112 | 113 | return string + "
" 114 | 115 | class GameData: 116 | class Result: 117 | def __init__(self, index, filename, left_score, right_score, left_points, right_points, left_shoot_count, valid, miss): 118 | self.index = index 119 | self.filename = filename 120 | self.left_score = left_score 121 | self.right_score = right_score 122 | self.left_points = left_points 123 | self.right_points = right_points 124 | self.left_shoot_count = left_shoot_count 125 | self.valid = valid 126 | self.miss = miss 127 | 128 | def __init__(self, verbose, curve, map): 129 | self.count = 0 130 | self.filename = 'null' 131 | self.result_list = [] 132 | 133 | self.remaining_count = -1 134 | 135 | self.attention = 4.0 136 | 137 | self.left_goals = 0 138 | self.right_goals = 0 139 | 140 | self.left_points = 0 141 | self.right_points = 0 142 | 143 | self.left_total_shoot_count = 0 144 | 145 | self.win_count = 0 146 | self.draw_count = 0 147 | self.lost_count = 0 148 | 149 | self.left_score_distri = {} 150 | self.right_score_distri = {} 151 | self.diff_score_distri = {} 152 | 153 | self.score_map = defaultdict(dict) 154 | self.left_min_score = 6000 155 | self.left_max_score = -1 156 | self.right_min_score = 6000 157 | self.right_max_score = -1 158 | 159 | self.verbose = verbose 160 | self.curve = curve 161 | self.map = map 162 | self.context = Context() 163 | 164 | self.avg_left_goals = 0.0 165 | self.avg_right_goals = 0.0 166 | 167 | self.avg_left_points = 0.0 168 | self.avg_right_points = 0.0 169 | 170 | self.win_rate = 0.0 171 | self.lost_rate = 0.0 172 | self.expected_win_rate = 1.0 173 | 174 | self.max_win_rate = 1.0 175 | self.min_win_rate = 0.0 176 | 177 | self.win_rate_standard_deviation = 0.0 178 | self.confidence_intervel_left = 0.0 179 | self.confidence_intervel_right = 0.0 180 | 181 | def add_line(self, string, color=Color.PURPLE, face=Face.NORMAL): 182 | self.context.add_line(Context.Line(string, color, face)) 183 | 184 | def add_newline(self): 185 | self.context.add_line(Context.Line("")) 186 | 187 | def update(self, left_score, right_score, left_shoot_count, valid, miss, filename): 188 | self.count += 1 189 | 190 | self.left_score_distri[left_score] = self.left_score_distri.get(left_score, 0) + 1 191 | self.right_score_distri[right_score] = self.right_score_distri.get(right_score, 0) + 1 192 | self.diff_score_distri[left_score - right_score] = self.diff_score_distri.get(left_score - right_score, 0) + 1 193 | 194 | if self.score_map.has_key(left_score) and self.score_map[left_score].has_key(right_score): 195 | self.score_map[left_score][right_score] += 1 196 | else: 197 | self.score_map[left_score][right_score] = 1 198 | 199 | self.left_min_score = min(self.left_min_score, left_score) 200 | self.left_max_score = max(self.left_max_score, left_score) 201 | self.right_min_score = min(self.right_min_score, right_score) 202 | self.right_max_score = max(self.right_max_score, right_score) 203 | 204 | left_points = 0 205 | right_points = 0 206 | if left_score > right_score: 207 | left_points += 3 208 | self.win_count += 1 209 | elif left_score < right_score: 210 | right_points += 3 211 | self.lost_count += 1 212 | else: 213 | left_points += 1 214 | right_points += 1 215 | self.draw_count += 1 216 | 217 | self.result_list.append(self.Result(self.count, filename, left_score, right_score, left_points, right_points, left_shoot_count, valid, miss)) 218 | 219 | self.left_goals += left_score 220 | self.right_goals += right_score 221 | self.left_points += left_points 222 | self.right_points += right_points 223 | 224 | self.left_total_shoot_count += left_shoot_count 225 | 226 | if self.curve: 227 | game_count = float(self.count) 228 | self.win_rate = self.win_count / game_count 229 | self.compute_confidence_interval() 230 | 231 | print self.count, self.win_rate, self.confidence_intervel_left, self.confidence_intervel_right 232 | 233 | def gen_score_distri(self, score_distri): 234 | def bar(percentage): 235 | length = 33 236 | bar_length = int(length * percentage) 237 | 238 | percentage_string = "%.2f%%" % (percentage * 100) 239 | while len(percentage_string) < 6: 240 | percentage_string = " " + percentage_string 241 | 242 | line = "[" 243 | for i in range(bar_length): 244 | line += "#" 245 | for i in range(length - bar_length): 246 | line += " " 247 | line += "] %s" % (percentage_string) 248 | return line 249 | 250 | lines = [] 251 | scores = sorted(score_distri.keys()) 252 | for score in range(scores[0], scores[-1] + 1): 253 | count = 0 254 | percentage = 0.0 255 | if score_distri.has_key(score): 256 | count = score_distri[score] 257 | percentage = score_distri[score] / float(self.count) 258 | 259 | lines.append(Context.Line("`%4d:%6d " % (score, count) + bar(percentage), Color.BLUE, Face.MONOSPACE)) 260 | 261 | return lines 262 | 263 | def compute_confidence_interval(self): 264 | game_count = float(self.count) 265 | 266 | self.win_rate_standard_deviation = math.sqrt(self.win_rate * (1.0 - self.win_rate)); 267 | self.confidence_intervel_left = self.win_rate - 1.96 * self.win_rate_standard_deviation / math.sqrt(game_count) 268 | self.confidence_intervel_right = self.win_rate + 1.96 * self.win_rate_standard_deviation / math.sqrt(game_count) 269 | 270 | if self.confidence_intervel_left < 0.0: 271 | self.confidence_intervel_left = 0.0 272 | if self.confidence_intervel_right > 1.0: 273 | self.confidence_intervel_right = 1.0 274 | 275 | 276 | def compute(self): 277 | game_count = float(self.count) 278 | 279 | try: 280 | file = open("total_rounds", "r") 281 | self.remaining_count = int(file.read().strip()) - self.count 282 | file.close() 283 | except: 284 | pass 285 | 286 | self.avg_left_goals = self.left_goals / game_count 287 | self.avg_right_goals = self.right_goals / game_count 288 | 289 | self.avg_left_points = self.left_points / game_count 290 | self.avg_right_points = self.right_points / game_count 291 | 292 | self.win_rate = self.win_count / game_count 293 | self.lost_rate = self.lost_count / game_count 294 | 295 | self.compute_confidence_interval() 296 | 297 | try: 298 | self.expected_win_rate = self.win_rate / (self.win_rate + self.lost_rate) 299 | except: 300 | pass 301 | 302 | if self.remaining_count > 0: 303 | self.max_win_rate = (self.win_count + self.remaining_count) / (game_count + self.remaining_count) 304 | self.min_win_rate = self.win_count / (game_count + self.remaining_count) 305 | 306 | def format(self): 307 | def summary(): 308 | self.add_line(self.title, color=Color.BLUE) 309 | 310 | non_valid = sum(1 for e in self.result_list if not e.valid) 311 | miss_count = sum(e.miss for e in self.result_list if e.miss) 312 | miss_matches = sum(1 for e in self.result_list if e.miss) 313 | 314 | self.add_newline() 315 | self.add_line("Left Team Goals Distribution:") 316 | map(lambda line: self.context.add_line(line), self.gen_score_distri(self.left_score_distri)) 317 | 318 | self.add_newline() 319 | self.add_line("Right Team Goals Distribution:") 320 | map(lambda line: self.context.add_line(line), self.gen_score_distri(self.right_score_distri)) 321 | 322 | self.add_newline() 323 | self.add_line("Diff Goals Distribution:") 324 | map(lambda line: self.context.add_line(line), self.gen_score_distri(self.diff_score_distri)) 325 | 326 | self.add_newline() 327 | if self.remaining_count > 0: 328 | self.add_line("Game Count: %d (%d left)" % (self.count, self.remaining_count)) 329 | else: 330 | self.add_line("Game Count: %d" % (self.count)) 331 | 332 | self.add_line("Goals: %d : %d (diff: %d)" % (self.left_goals, self.right_goals, self.left_goals - self.right_goals)) 333 | self.add_line("Points: %d : %d (diff: %d)" % (self.left_points, self.right_points, self.left_points - self.right_points)) 334 | self.add_line("Avg Goals: %.2f : %.2f (diff: %.2f)" % (self.avg_left_goals, self.avg_right_goals, self.avg_left_goals - self.avg_right_goals)) 335 | self.add_line("Avg Points: %.2f : %.2f (diff: %.2f)" % (self.avg_left_points, self.avg_right_points, self.avg_left_points - self.avg_right_points)) 336 | self.add_line("Left Team: Win %d, Draw %d, Lost %d" % (self.win_count, self.draw_count, self.lost_count)) 337 | self.add_line("Left Team: WinRate %.2f%%, ExpectedWinRate %.2f%%" % (self.win_rate * 100, self.expected_win_rate * 100)) 338 | self.add_line("Left Team: 95%% Confidence Interval [%.2f%%, %.2f%%]" % (self.confidence_intervel_left * 100, self.confidence_intervel_right * 100)) 339 | 340 | if self.left_total_shoot_count > 0: 341 | self.add_line("Left Team: Shoot Success Rate %.2f%%, (%d/%d, %.2f shoots per match)" % (self.left_goals / float(self.left_total_shoot_count) * 100, self.left_goals, self.left_total_shoot_count, self.left_total_shoot_count / float(self.count))) 342 | 343 | if self.remaining_count > 0: 344 | self.add_line("Left Team: MaxWinRate %.2f%%, MinWinRate %.2f%%" % (self.max_win_rate * 100, self.min_win_rate * 100), Color.GRAY) 345 | 346 | if non_valid: 347 | self.add_line("Non Valid Game Count: %d (%.2f%%)" % (non_valid, non_valid / float(self.count) * 100), Color.RED) 348 | if miss_count: 349 | self.add_line("Total Miss Count: %d (in %d matches, %.2f%%)" % (miss_count, miss_matches, miss_matches / float(self.count) * 100), Color.RED) 350 | 351 | def details(): 352 | left_attention = self.avg_left_goals - self.avg_right_goals - self.attention 353 | right_attention = self.avg_left_goals - self.avg_right_goals + self.attention 354 | min_diff = left_attention 355 | max_diff = right_attention 356 | 357 | self.add_newline() 358 | self.add_line("Game Details:") 359 | self.add_newline() 360 | for result in self.result_list: 361 | line = Context.Line("%3d%6d:%d%6d:%d [%s]" % (result.index, result.left_score, result.right_score, result.left_points, result.right_points, result.filename)) 362 | if result.valid: 363 | diff = result.left_score - result.right_score 364 | if diff <= min_diff: 365 | min_diff = diff 366 | line.color = Color.ORANGE 367 | elif diff >= max_diff: 368 | max_diff = diff 369 | line.color = Color.ORANGE 370 | elif diff <= left_attention or diff >= right_attention: 371 | line.color = Color.GREEN 372 | else: 373 | line.color = Color.RED 374 | 375 | if self.verbose or line.color != Color.NONE: 376 | self.context.add_line(line) 377 | 378 | if options.html: 379 | summary() 380 | details() 381 | else: 382 | details() 383 | summary() 384 | 385 | def generate_context(self, lines): 386 | self.title = lines.pop(0) 387 | 388 | for line in lines: 389 | parts = line.split() 390 | parts = map(int, parts[:-1]) + parts[-1:] 391 | self.update(*parts) 392 | 393 | if not self.curve and not self.map: 394 | self.compute() 395 | self.format() 396 | 397 | if self.map: 398 | self.gen_score_map() 399 | 400 | def run(self, lines, method): 401 | self.generate_context(lines) 402 | self.context.dump(method) 403 | 404 | def gen_score_map(self): 405 | print "# (%d, %d) * (%d, %d)" % (self.left_min_score, self.left_max_score, self.right_min_score, self.right_max_score) 406 | 407 | for i in range(self.left_min_score, self.left_max_score + 1): 408 | for j in range(self.right_min_score, self.right_max_score + 1): 409 | share = 0.0 410 | 411 | if self.score_map.has_key(i) and self.score_map[i].has_key(j): 412 | share = self.score_map[i][j] / float(self.count) 413 | 414 | print i, j, share 415 | 416 | print 417 | 418 | 419 | usage = "Usage: %prog [options]" 420 | 421 | parser = OptionParser(usage=usage) 422 | parser.add_option("-C", "--console", action="store_true", dest="console", default=True, help="print with color to console [default]") 423 | parser.add_option("-N", "--no-color", action="store_true", dest="no_color", default=False, help="print without color to console") 424 | parser.add_option("-D", "--discuz", action="store_true", dest="discuz", default=False, help="print as discuz code format") 425 | parser.add_option("-H", "--html", action="store_true", dest="html", default=False, help="print as html format") 426 | parser.add_option("-S", "--simplify", action="store_true", dest="simplify", default=False, help="output simplify") 427 | parser.add_option("-A", "--curve", action="store_true", dest="curve", default=False, help="output winrate curve data") 428 | parser.add_option("-M", "--map", action="store_true", dest="map", default=False, help="output score map data") 429 | parser.add_option("-T", "--temp", action="store_true", dest="temp", default=False, help="can be killed any time") 430 | 431 | (options, args) = parser.parse_args() 432 | 433 | lines = [] 434 | for line in sys.stdin: 435 | line = line.strip() 436 | if len(line) > 0: 437 | lines.append(line) 438 | 439 | if len(lines) <= 1: #at least two lines: title + result 440 | print "No results found, exit" 441 | sys.exit(1) 442 | 443 | game_data = GameData(not options.simplify, options.curve, options.map) 444 | 445 | if options.discuz: 446 | game_data.run(lines, discuz) 447 | elif options.html: 448 | print """ 449 | 450 | 451 | 452 | Test Results 453 | 454 | 455 | """ 456 | if options.temp: 457 | print "

Test Results (Can be killed any time!)

" 458 | else: 459 | print "

Test Results

" 460 | print """ 461 |
462 | Winning Rate 463 | Score Map 464 |
465 |

466 | """ 467 | game_data.run(lines, html) 468 | print """ 469 | 470 | """ 471 | elif options.no_color: 472 | game_data.run(lines, no_color) 473 | else: 474 | game_data.run(lines, console) 475 | 476 | -------------------------------------------------------------------------------- /start.tmpl/Helios2010: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ssh -f $1 "ulimit -t 300 && cd helios && ./start.sh -h $2 -p $3 &> /dev/null" 4 | sleep 5 5 | -------------------------------------------------------------------------------- /start.tmpl/Helios2011: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ssh -f $1 "ulimit -t 300 && cd helios && ./start.sh $2 $3 $4 $5 &> /dev/null" 4 | 5 | sleep 5 6 | -------------------------------------------------------------------------------- /start.tmpl/Helios2015: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ssh -f $1 "ulimit -t 300 && cd helios && ./start.sh $2 $3 $4 $5 &> /dev/null" 4 | 5 | sleep 5 6 | -------------------------------------------------------------------------------- /start.tmpl/Marlik: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ssh -f $1 "ulimit -t 300 && cd marlik && ./start.sh $2 $3 $4 $5 &> /dev/null" 4 | 5 | sleep 5 6 | -------------------------------------------------------------------------------- /start.tmpl/Oxsy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ssh -f $1 "ulimit -t 300 && cd /home/oxsy && ./start.sh $2 $3 &> /dev/null" 4 | sleep 5 5 | -------------------------------------------------------------------------------- /start.tmpl/WrightEagle: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VERSION="Release" 4 | 5 | if [ ! -z $7 ]; then #msg log dir name 6 | ssh -f $1 "ulimit -t 300 && ulimit -c unlimited && cd WrightEagle && ./start.sh -h $2 -p $3 -o $6 -l $7 -v $VERSION" 7 | else 8 | ssh -f $1 "ulimit -t 300 && ulimit -c unlimited && cd WrightEagle && ./start.sh -h $2 -p $3 -o $6 -v $VERSION" 9 | fi 10 | 11 | sleep 5 12 | -------------------------------------------------------------------------------- /start_left: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VERSION="Release" 4 | 5 | if [ ! -z $7 ]; then #msg log dir name 6 | ssh -f $1 "ulimit -t 300 && ulimit -c unlimited && cd WrightEagle && ./start.sh -h $2 -p $3 -o $6 -l $7 -v $VERSION" 7 | else 8 | ssh -f $1 "ulimit -t 300 && ulimit -c unlimited && cd WrightEagle && ./start.sh -h $2 -p $3 -o $6 -v $VERSION" 9 | fi 10 | 11 | sleep 5 12 | -------------------------------------------------------------------------------- /start_right: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ssh -f $1 "ulimit -t 300 && cd helios && ./start.sh $2 $3 $4 $5 &> /dev/null" 4 | 5 | sleep 5 6 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PROCES=5 #number of simultaneously running servers 4 | 5 | #CLIENTS=( 6 | # "192.168.26.102" 7 | # "192.168.26.103" 8 | # "192.168.26.104" 9 | # "192.168.26.110" 10 | # "192.168.26.120" 11 | # "192.168.26.102" 12 | # "192.168.26.103" 13 | # "192.168.26.110" 14 | # "192.168.26.120" 15 | # "192.168.26.102" 16 | # "192.168.26.103" 17 | #) #IPs of machines running clients,CLIENTS=("localhost") for testing on localhost,has to be configured as password-less login for SSH 18 | 19 | CLIENTS=("localhost") 20 | 21 | #CLIENTS=("192.168.26.102" "192.168.26.103") 22 | 23 | ROUNDS=200 #number of games for each server 24 | DEFAULT_PORT=6000 #default port connecting to server 25 | CONTINUE="false" #continue from last test 26 | GAME_LOGGING="false" #record RCG logs 27 | TEXT_LOGGING="false" #record RCL logs 28 | MSG_LOGGING="false" #record MSG logs for WrightEagle 29 | TEMP="false" #can be killed any time? 30 | TRAINING="false" #training mode 31 | RANDOM_SEED="-1" #random seed, -1 means random seeding 32 | SYNCH_MODE="1" #synch mode 33 | FULLSTATE_L="0" #full state mode for left 34 | FULLSTATE_R="0" #full state mode for right 35 | 36 | ############# do not need to change following parameters 37 | RESTART_AS_TEMP="false" 38 | IN_WRAPPER="false" 39 | TEMP_MARKER="/tmp/autotest::temp" 40 | 41 | while getopts "r:p:ctkio" flag; do 42 | case "$flag" in 43 | r) ROUNDS=$OPTARG;; 44 | p) PROCES=$OPTARG;; 45 | c) CONTINUE="true";; 46 | t) TEMP="true";; 47 | o) TRAINING="true";; 48 | k) RESTART_AS_TEMP="true";; 49 | i) IN_WRAPPER="true";; 50 | esac 51 | done 52 | 53 | ############### 54 | if [ $RESTART_AS_TEMP = "true" ]; then 55 | if [ $IN_WRAPPER = "true" ]; then 56 | sleep 0.5 57 | ./test.sh -ct 58 | rm -f $0 59 | exit 60 | fi 61 | 62 | WRAPPER=`mktemp` 63 | cp $0 $WRAPPER 64 | chmod +x $WRAPPER 65 | $WRAPPER -ik & 66 | ./kill.sh 67 | exit 68 | fi 69 | 70 | echo "\$PROCES = $PROCES" 71 | echo "\$ROUNDS = $ROUNDS" 72 | echo "\$CONTINUE = $CONTINUE" 73 | echo "\$TEMP = $TEMP" 74 | echo "\$TRAINING = $TRAINING" 75 | echo "\$RANDOM_SEED = $RANDOM_SEED" 76 | 77 | rm -f $TEMP_MARKER 78 | if [ $TEMP = "true" ]; then 79 | touch $TEMP_MARKER 80 | chmod 777 $TEMP_MARKER 81 | fi 82 | 83 | RESULT_DIR="result.d" 84 | LOG_DIR="log.d" 85 | TOTAL_ROUNDS_FILE="$RESULT_DIR/total_rounds" 86 | TIME_STAMP_FILE="$RESULT_DIR/time_stamp" 87 | HTML="$RESULT_DIR/index.html" 88 | HTML_GENERATING_LOCK="/tmp/autotest_html_generating" 89 | 90 | run_server() { 91 | ulimit -t 300 92 | echo rcssserver $* 93 | rcssserver $* 94 | } 95 | 96 | server_count() { 97 | ps -o pid= -C rcssserver | wc -l 98 | } 99 | 100 | match() { 101 | local HOST=$1 102 | local PORT=$2 103 | 104 | local OPTIONS="" 105 | 106 | local COACH_PORT=`expr $PORT + 1` 107 | local OLCOACH_PORT=`expr $PORT + 2` 108 | 109 | local a=`expr $PORT / 1000` 110 | local b=`expr $a + 1` 111 | 112 | a=`expr $a % ${#CLIENTS[@]}` 113 | b=`expr $b % ${#CLIENTS[@]}` 114 | 115 | local LEFT_CLIENT=${CLIENTS[$a]} 116 | local RIGHT_CLIENT=${CLIENTS[$b]} 117 | 118 | OPTIONS="$OPTIONS -server::port=$PORT" 119 | OPTIONS="$OPTIONS -server::coach_port=$COACH_PORT" 120 | OPTIONS="$OPTIONS -server::olcoach_port=$OLCOACH_PORT" 121 | OPTIONS="$OPTIONS -player::random_seed=$RANDOM_SEED" 122 | OPTIONS="$OPTIONS -server::nr_normal_halfs=2 -server::nr_extra_halfs=0" 123 | OPTIONS="$OPTIONS -server::penalty_shoot_outs=false -server::auto_mode=on" 124 | OPTIONS="$OPTIONS -server::game_logging=$GAME_LOGGING -server::text_logging=$TEXT_LOGGING" 125 | OPTIONS="$OPTIONS -server::game_log_compression=1 -server::text_log_compression=1" 126 | OPTIONS="$OPTIONS -server::game_log_fixed=1 -server::text_log_fixed=1" 127 | OPTIONS="$OPTIONS -server::synch_mode=$SYNCH_MODE" 128 | OPTIONS="$OPTIONS -server::fullstate_l=$FULLSTATE_L -server::fullstate_r=$FULLSTATE_R" 129 | OPTIONS="$OPTIONS -server::team_r_start=\"./start_right $RIGHT_CLIENT $HOST $PORT $COACH_PORT $OLCOACH_PORT\"" 130 | 131 | if [ $TRAINING = "true" ]; then 132 | OPTIONS="$OPTIONS -server::coach=true -server::coach_w_referee=true" 133 | fi 134 | 135 | rm -f $HTML_GENERATING_LOCK 136 | generate_html 137 | 138 | for i in `seq 1 $ROUNDS`; do 139 | local TIME="`date +%Y%m%d%H%M`_$RANDOM" 140 | local RESULT="$RESULT_DIR/$TIME" 141 | 142 | if [ ! -f $RESULT ]; then 143 | local MSG_LOG_DIR="Logfiles_$TIME" 144 | local FULL_OPTIONS="" 145 | 146 | FULL_OPTIONS="$OPTIONS -server::game_log_dir=\"./$LOG_DIR/\" -server::text_log_dir=\"./$LOG_DIR/\"" 147 | FULL_OPTIONS="$FULL_OPTIONS -server::game_log_fixed_name=\"$TIME\" -server::text_log_fixed_name=\"$TIME\"" 148 | 149 | if [ $MSG_LOGGING = "true" ]; then 150 | FULL_OPTIONS="$FULL_OPTIONS -server::team_l_start=\"./start_left $LEFT_CLIENT $HOST $PORT $COACH_PORT $OLCOACH_PORT $TRAINING $MSG_LOG_DIR\"" 151 | else 152 | FULL_OPTIONS="$FULL_OPTIONS -server::team_l_start=\"./start_left $LEFT_CLIENT $HOST $PORT $COACH_PORT $OLCOACH_PORT $TRAINING\"" 153 | fi 154 | 155 | run_server $FULL_OPTIONS &>$RESULT 156 | fi 157 | 158 | sleep 1 159 | generate_html 160 | done 161 | } 162 | 163 | generate_html() { 164 | if [ ! -f $HTML_GENERATING_LOCK ]; then 165 | touch $HTML $HTML_GENERATING_LOCK 166 | chmod 777 $HTML $HTML_GENERATING_LOCK 2>/dev/null #allow others to delete or overwrite 167 | 168 | if [ $TEMP = "true" ]; then 169 | ./result.sh -HT >$HTML 170 | else 171 | ./result.sh --html >$HTML 172 | fi 173 | 174 | ./analyze.sh 2>/dev/null 175 | echo -e "


" >>$HTML 176 | echo -e "

"`whoami`" @ "`date`"

" >>$HTML 177 | rm -f $HTML_GENERATING_LOCK 178 | fi 179 | } 180 | 181 | autotest() { 182 | export LANG="POSIX" 183 | 184 | if [ `server_count` -gt 0 ]; then 185 | echo "Error: other server running, exit" 186 | exit 187 | fi 188 | 189 | if [ $CONTINUE = "false" ]; then 190 | if [ -d $RESULT_DIR ]; then 191 | echo "Warning: previous test result left, backuped" 192 | mv $RESULT_DIR ${RESULT_DIR}_`date +"%F_%H%M"` 193 | mv $LOG_DIR ${LOG_DIR}_`date +"%F_%H%M"` 194 | fi 195 | mkdir $RESULT_DIR || exit 196 | mkdir $LOG_DIR || exit 197 | TOTAL_ROUNDS=`expr $PROCES '*' $ROUNDS` 198 | echo $TOTAL_ROUNDS >$TOTAL_ROUNDS_FILE 199 | echo `date` >$TIME_STAMP_FILE 200 | else 201 | if [ ! -d $RESULT_DIR ]; then 202 | echo "Error: can not find previous test result" 203 | exit 204 | fi 205 | PRE_TOTAL_ROUNDS=`./result.sh --no-color | awk '{print $3}' | grep '[013]:[013]' | wc -l` 206 | TOTAL_ROUNDS=`expr $PROCES '*' $ROUNDS + $PRE_TOTAL_ROUNDS` 207 | echo $TOTAL_ROUNDS >$TOTAL_ROUNDS_FILE 208 | echo `date` >>$TIME_STAMP_FILE 209 | fi 210 | 211 | local IP_PATTERN='192\.168\.[0-9]\{1,3\}\.[0-9]\{1,3\}' 212 | local SERVER_HOSTS=(`/sbin/ifconfig | grep -o "inet addr:$IP_PATTERN" | grep -o "$IP_PATTERN"`) 213 | local HOST="localhost" 214 | 215 | if [ ${#SERVER_HOSTS[@]} -gt 0 ]; then 216 | HOST=${SERVER_HOSTS[0]} 217 | fi 218 | 219 | local i=0 220 | while [ $i -lt $PROCES ]; do 221 | local PORT=`expr $DEFAULT_PORT + $i \* 1000` 222 | match $HOST $PORT & 223 | i=`expr $i + 1` 224 | sleep 1 225 | done 226 | } 227 | 228 | autotest & 229 | 230 | --------------------------------------------------------------------------------