MatchTimes.perl

MatchTimes.perl

text/plain — 15.7 KB

File contents

#!/usr/bin/perl

# This script takes the user data input and generates two plots.  The first plot shows
# the times for each match and the judging.   The second plot shows which teams play
# which and is used to make sure that no team plays too often or little.
# The text output has the team pairings, schedule, and a list of which teams are
# played by each team.  The script also creates a tab delimited file with the competition
# and judging schedule that can be read directly into the scoring spread sheet.  The team
# names are then pulled into the schedule and it is ready for formatting, printing, and then
# handing out to the teams.  The file name is MatchAndJudgeTimes.tab.
# 
# We started with pairings developed by Tim Burks and then worked with them until
# we had judging times that were not too close to competition matches and so that
# they do not compete in subsequent matches.
#
# Use this script by simply running it on a unix machine or cygwin Windows machine
# and ploting the resulting MatchTimes.gnu file with gnuplot.  Gnuplot sends two
# plots to the default x11 screen.  It also generates MatchTimes.ps and MatchPairings.ps.
# These can be converted with Acrobat to pdf's.  This conversion can also be done
# under cygwin with the "convert" command with
#   convert MatchTimes.ps MatchTimes.pdf
#   convert MatchPairings.ps MatchPairings.pdf
#
# The times for the Judging and team matches are not connected.  They must work
# in concert with eachother at the event.  The only way I have figured out how
# to do this is to make a set of plots and then figure out where things should go
# and then update the lists below by hand.
# 
# The script works for any number of matchs, teams, and rounds.
#
#
# Michael and Wyn Schuh
# Los Altos, CA
# Michael@Boardsailor.com
#
# Version     Date    Who      Comments
#  1.5     05 Nov 05  Schuhs   First working version.
#  1.6     05 Nov 05  Schuhs   Reworked the pairings to give teams more time and
#                              added MatchAndJudgeTimes.tab file.
#  1.7     06 Nov 05  Schuhs   (Austin and Michael) Made number of teams dynamic, automaticly find
#                              the number of matches per round, checks for errors in number of judgings
#                              and repeated pairings.  Fixed pairings so 6 is on table 1 in first match
#                              of round d.

#
# Start of user data input.
#

$StartTime = 75;  # Start time in minutes.  60 is 1:00 PM.

#   Round     a   b   c   d   e
@Cycle   = (  7,  7,  7,  6,  5 );  # Time between matches in each round
@Break   = ( 20,  0,  10, 0, 20 );  # Break time before each round

$JudgingTimeSlotLength = 10;  # This is the amount of time given to each judging session.
$FirstBreak = $Break[0] + 5;  # Used to have the judging start five minutes after the first competition match starts.

#                      Break  J1  J2   P
@Judgings = ( [ $FirstBreak,   3,  2, 10 ],  # First Set
              [           0,   1,  3,  8 ],
              [           0,   2,  1, 11 ],
              [           0,   4,  5,  3 ],  # Second Set
              [           0,   6,  4,  7 ],
              [           0,   5,  6,  9 ],
              [          10,   7,  8, 12 ],  # Third Set
              [           0,   9,  7,  6 ],
              [           0,   8,  9,  5 ],
              [           0,  10, 11,  2 ],  # Fourth Set
              [           0,  12, 10,  4 ],
              [           0,  11, 12,  1 ] );

@Matchings = (
   [                # Round a
     [  4,  8 ],
     [ 11,  7 ], 
     [  5,  9 ], 
     [  6, 10 ],
 ], [               # Round b
     [ 12,  7 ],
     [  8,  9 ], 
     [ 10, 11 ], 
     [  2, 12 ],
     [  3,  1 ], 
 ], [               # Round c
     [  1,  5 ],
     [  4, 11 ],
     [ 10,  2 ], 
     [ 12,  3 ],
 ], [               # Round d
     [  6,  4 ], 
     [  7,  1 ],
     [  9,  3 ], 
     [  8,  5 ],
     [  2,  6 ], 
 ], [               # Round e
     [  1,  2 ],
     [  3,  4 ], 
     [  5,  6 ], 
     [  7,  8 ], 
     [  9, 10 ], 
     [ 11, 12 ],
 ]
     );

$NumberOfTeams = 0;  # Number of the highest team.  This is assumed to be the number of teams.
foreach $i ( 0 .. $#Matchings ) {
  push @Matches, $#{$Matchings[$i]} + 1;   # Number of matches in each round.
  foreach $match ( 0 .. $#{$Matchings[$i]} ) {
     $NumberOfTeams = $Matchings[$i][$match][0] if $Matchings[$i][$match][0] > $NumberOfTeams; 
     $NumberOfTeams = $Matchings[$i][$match][1] if $Matchings[$i][$match][1] > $NumberOfTeams; 
  }
} 

if ( $NumberOfTeams != $#Judgings+1 ) {  # Check to make sure we have the right number of Judgings.
   printf "\nERROR:  The number of teams, $NumberOfTeams, does not equal the number of Judgings, %d\n\n",$#Judgings+1;
   exit(-5);
}

#
# End of user data input.
#

#  t1 t2     # t1 and t2 are filled with the number of times at each table.
for ( 0 .. $NumberOfTeams ) {
    push @TableCountForEachTeam , [0, 0];   # Used to count the number of times a team plays at table 1 and table 2.
}
foreach $i ( 0 .. $NumberOfTeams ) {
  foreach $j ( 0 .. $NumberOfTeams ) {
    $PairingsTable[$i][$j] = 0;   # 2D Used to keep track of the number of times a team plays each other team.
  }
}

$time = $StartTime;

GP_CommandFile_HeaderFill();   # Write the first part of the plot command file.

push @JudgeTimesAndTeamsTabs, "Competition Round Schedule\n";           # Build the contents for the MatchAndJudgeTimes.tab file.
push @JudgeTimesAndTeamsTabs, "Round\tMatch\tTime\tTable 1\tTable 2\n"; 

@RoundNames = (qw(A B C D E)); # Used to label matches with letters.

# Make the plot command lines and data files for showing when each team competes and for the pairings chart.
foreach $RoundNumber ( 0 .. $#Matches ) {
  open(GP,">MatchTimes$RoundNumber.data");
  open(GPP,">MatchPairings$RoundNumber.data");
  $RoundMatches = $Matches[$RoundNumber];
  $time += $Break[$RoundNumber];
  foreach $Match ( 1 .. $RoundMatches ) { 
     $timeEnd = $time + $Cycle[$RoundNumber];
     $GPtimeStart = sprintf "%d:%2.2d",int($time/60), $time%60;        # Set the match start and end times.
     $GPtimeEnd   = int($timeEnd/60) . ":" . $timeEnd%60;
     $GPtimeCent  = int(($time+$timeEnd)/120) . ":" . (($time+$timeEnd)/2)%60;
     $Table1team = $Matchings[$RoundNumber][$Match-1][0];     # Get the team names.
     $Table2team = $Matchings[$RoundNumber][$Match-1][1];
     $TableCountForEachTeam[$Table1team][0] += 1;             # Keep track of how many times the
     $TableCountForEachTeam[$Table2team][1] += 1;             # teams play at each table.
     push @MatchTimesAndTeams, sprintf "  $RoundNames[$RoundNumber] %6d       $GPtimeStart  %6d  %6d\n",$Match,$Table1team,$Table2team;
     push @JudgeTimesAndTeamsTabs, sprintf "$RoundNames[$RoundNumber]\t%d\t$GPtimeStart\t=Team%d\t=Team%d\n",$Match,$Table1team,$Table2team;
     push @{ $TableCountForEachTeam[$Table1team] }, $Table2team;   # Add the competing team to the list.
     push @{ $TableCountForEachTeam[$Table2team] }, $Table1team;   # Add the competing team to the list.

     printf GP "$GPtimeStart   %5.1f\n",  $Table1team - .4;   # Box for competition schedule.
     printf GP "$GPtimeEnd     %5.1f\n",  $Table1team - .4; 
     printf GP "$GPtimeEnd     %5.1f\n",  $Table1team + .4; 
     printf GP "$GPtimeStart   %5.1f\n",  $Table1team + .4; 
     printf GP "$GPtimeStart   %5.1f\n\n",$Table1team - .4; 

     printf GP "$GPtimeStart   %5.1f\n",  $Table2team - .4; 
     printf GP "$GPtimeEnd     %5.1f\n",  $Table2team - .4; 
     printf GP "$GPtimeEnd     %5.1f\n",  $Table2team + .4; 
     printf GP "$GPtimeStart   %5.1f\n",  $Table2team + .4; 
     printf GP "$GPtimeStart   %5.1f\n\n",$Table2team - .4; 

     printf GPC "set label \"t1\" at \"$GPtimeCent\", $Table1team center tc lt %d\n",$RoundNumber+1;
     printf GPC "set label \"t2\" at \"$GPtimeCent\", $Table2team center tc lt %d\n",$RoundNumber+1;

     printf GPP "%5.1f   %5.1f\n",   $Table1team-.5, $Table2team-.5;     # Box for pairings chart
     printf GPP "%5.1f   %5.1f\n",   $Table1team-.5, $Table2team+.5; 
     printf GPP "%5.1f   %5.1f\n",   $Table1team+.5, $Table2team+.5; 
     printf GPP "%5.1f   %5.1f\n",   $Table1team+.5, $Table2team-.5; 
     printf GPP "%5.1f   %5.1f\n\n", $Table1team-.5, $Table2team-.5; 

     printf GPP "%5.1f   %5.1f\n",   $Table2team-.5, $Table1team-.5;     # Box for pairings chart
     printf GPP "%5.1f   %5.1f\n",   $Table2team-.5, $Table1team+.5; 
     printf GPP "%5.1f   %5.1f\n",   $Table2team+.5, $Table1team+.5; 
     printf GPP "%5.1f   %5.1f\n",   $Table2team+.5, $Table1team-.5; 
     printf GPP "%5.1f   %5.1f\n\n", $Table2team-.5, $Table1team-.5; 

     $PairingsTable[$Table1team][$Table2team] += 1;  # Increment the number of times each team is paired with the other.
     $PairingsTable[$Table2team][$Table1team] += 1;
     $ErrorString = ($PairingsTable[$Table1team][$Table2team] > 1) ? " Error" : "";  # Check to see if they have more than 1 pairing.
     $TextColor = ($PairingsTable[$Table1team][$Table2team] > 1) ? 0 : $RoundNumber+1;  # Use black text if they have more than 1 pairing. 
     push @GPC, sprintf "set label \"$RoundNames[$RoundNumber]%d$ErrorString\" at $Table1team, $Table2team center tc lt %d\n",$Match,$TextColor;
     push @GPC, sprintf "set label \"$RoundNames[$RoundNumber]%d$ErrorString\" at $Table2team, $Table1team center tc lt %d\n",$Match,$TextColor;

     $time = $timeEnd
  }
  close(GP);
  close(GPP);
}

push @JudgeTimesAndTeamsTabs, " \n", " \n", "\tJudging Schedule\n"; 
push @JudgeTimesAndTeamsTabs, "\tSession\tTime\tRobot Design Go to Judging Room\tTeam Categories Go to Judging Room\tProgramming Go to your Pit Table\n"; 
$time = $StartTime;
open(GP,">MatchJudgeTimes.data");
foreach $JudgingRoundNumber ( 0 .. $#Judgings ) {
     $time += $Judgings[$JudgingRoundNumber][0]; # Add in the time for the break

     $timeEnd = $time + $JudgingTimeSlotLength;
     $GPtimeStart = sprintf "%d:%2.2d",int($time/60), $time%60;        # Set the Judging start and end times.
     $GPtimeEnd   = int($timeEnd/60) . ":" . $timeEnd%60;
     $GPtimeCent  = int(($time+$timeEnd)/120) . ":" . (($time+$timeEnd)/2)%60;
     $Judge1team = $Judgings[$JudgingRoundNumber][1];
     $Judge2team = $Judgings[$JudgingRoundNumber][2];
     $Judge3team = $Judgings[$JudgingRoundNumber][3];
     push @JudgeTimesAndTeams, sprintf "%4d      $GPtimeStart %8d %10d %10d\n",$JudgingRoundNumber+1,$Judge1team,$Judge2team,$Judge3team;
     push @JudgeTimesAndTeamsTabs, sprintf "\t%d\t$GPtimeStart\t=Team%d\t=Team%d\t=Team%d\n",$JudgingRoundNumber+1,$Judge1team,$Judge2team,$Judge3team;

     printf GP "$GPtimeStart   %5.1f\n", $Judge1team - .4; 
     printf GP "$GPtimeEnd     %5.1f\n", $Judge1team - .4; 
     printf GP "$GPtimeEnd     %5.1f\n", $Judge1team + .4; 
     printf GP "$GPtimeStart   %5.1f\n", $Judge1team + .4; 
     printf GP "$GPtimeStart   %5.1f\n\n", $Judge1team - .4; 

     printf GP "$GPtimeStart   %5.1f\n", $Judge2team - .4; 
     printf GP "$GPtimeEnd     %5.1f\n", $Judge2team - .4; 
     printf GP "$GPtimeEnd     %5.1f\n", $Judge2team + .4; 
     printf GP "$GPtimeStart   %5.1f\n", $Judge2team + .4; 
     printf GP "$GPtimeStart   %5.1f\n\n", $Judge2team - .4; 

     printf GP "$GPtimeStart   %5.1f\n", $Judge3team - .4; 
     printf GP "$GPtimeEnd     %5.1f\n", $Judge3team - .4; 
     printf GP "$GPtimeEnd     %5.1f\n", $Judge3team + .4; 
     printf GP "$GPtimeStart   %5.1f\n", $Judge3team + .4; 
     printf GP "$GPtimeStart   %5.1f\n\n", $Judge3team - .4; 

     printf GPC "set label \"j1\" at \"$GPtimeCent\", $Judge1team center tc lt 6\n";
     printf GPC "set label \"j2\" at \"$GPtimeCent\", $Judge2team center tc lt 6\n";
     printf GPC "set label \"P\" at \"$GPtimeCent\", $Judge3team center tc lt 6\n";

     $time = $timeEnd
}
close (GP);

GP_CommandFile_TrailerFill();

print "Check the list below to make sure that each team competes on each table half the time.\n";
print "The Table_1 and Table_2 columns contain the number of time they compete on the two tables.\n\n";
print "  Team#   Table_1  Table_2 | Teams Competing against this team.\n";
for $i ( 1 .. $NumberOfTeams ) {
    #printf "%5d  %8d  %7d %5d\n",$i,$TableCountForEachTeam[$i][0],$TableCountForEachTeam[$i][1],$#{$TableCountForEachTeam[$i]};
    #printf "%5d  %8d  %7d %5d\n",$i,$TableCountForEachTeam[$i][0],$TableCountForEachTeam[$i][1],$TableCountForEachTeam[$i][2];
    printf "%5d  %8d  %7d   |",$i,$TableCountForEachTeam[$i][0],$TableCountForEachTeam[$i][1];
    for $j ( 2 .. $#{$TableCountForEachTeam[$i]} ) { printf "%6d",$TableCountForEachTeam[$i][$j]; } print "\n";
}

print "\n\nMatch Start times and team numbers\n";
print "Round  Match  StartTime  Team_1  Team_2\n"; 
print @MatchTimesAndTeams;

print "\n\nJudging Start times and team numbers\n";
print "Round  StartTime  Judging_1  Judging_2 Programming\n"; 
print @JudgeTimesAndTeams;

# Create a tab delimited file for the match and judging schedule.
# Read this file into Microsoft Excel by using the Data/ImportExternalData/ImportData tool.
open(MSE,">MatchAndJudgeTimes.tab");
print MSE  @JudgeTimesAndTeamsTabs;
close(MSE);

# Check to see if teams play each other more than once.
foreach $i ( 0 .. $NumberOfTeams ) {
  foreach $j ( $i .. $NumberOfTeams ) {
    print "\nError: Teams $i and $j play each other more than once.\n"  if $PairingsTable[$i][$j] > 1;
  }
}

# Print out the current date and time.
print "\n"; system ("date");


# End
#
#================================================================================
#================================================================================
#================================================================================
#

sub GP_CommandFile_HeaderFill {
open(GPC,">MatchTimes.gnu");
print GPC '
# Tell gnuplot that the x data is in time format
set xdata time

# Set the time format which will be used for xrange and maybe other things.
set timefmt "%H"

set style data lines

# %R = %H:%M   (hours:minutes)
set format x "%R"
 
set xrange ["0:0":"3:00"]
set autoscale x
';
printf GPC "
set yrange [0:%d] rever
set yti 1,1,$NumberOfTeams
",$NumberOfTeams+1;
print GPC '

set timefmt "%H:%M"
unset label  # Clear any labels that might have been set from a privious loading of this file.
';
}

#
#================================================================================
#================================================================================
#================================================================================
#
sub GP_CommandFile_TrailerFill {
print GPC '
set time
set tit "Match Times"
set xlab "Time"
set ylab "Team Number"
plot "MatchTimes0.data" using 1:2 notit, \
     "MatchTimes1.data" using 1:2 notit, \
     "MatchTimes2.data" using 1:2 notit, \
     "MatchTimes3.data" using 1:2 notit, \
     "MatchTimes4.data" using 1:2 notit, \
     "MatchJudgeTimes.data"  using 1:2 notit
pause -1 
set term post color solid
set output "MatchTimes.ps"
replot
set output

unset label  # Clear any labels that might have been set from a privious loading of this file.
';

print GPC "@GPC";

print GPC '
set term x11
set xdata
set format x
';
printf GPC "
set xrange [0:%d]
set xti 1,1,$NumberOfTeams
",$NumberOfTeams+1;
print GPC '
set tit "Team Pairings\nErrors are noted by \'Error\' in the pairings label."
set xlab "Team Number"
plot "MatchPairings0.data" using 1:2 notit, \
     "MatchPairings1.data" using 1:2 notit, \
     "MatchPairings2.data" using 1:2 notit, \
     "MatchPairings3.data" using 1:2 notit, \
     "MatchPairings4.data" using 1:2 notit
pause -1
set term post color solid
set output "MatchPairings.ps"
replot;
';
close(GPC);
}