Swiss aka Round Robin

By LordHawk on Jul 02, 2007

i made this code when i was working with Magic-league, now that i am no longer with magic-league i will let my swiss code free.

# $y = &erf($x) - normalized error function
sub erf { &erf2($_[0]/1.414213562373095); }

# $y = &erf2($x) - unnormalized error function
sub erf2 { 
  local($x)=$_[0];
  $x >= 4 ? return 1 : $x <= -4 ? return 0 : 0;
  local($n,$sum,$term,$x2) = (0, 0.5, $x/1.772453850905516, $x*$x);
  while ($term > 1E-10 || $term < -1E-10) {
    $n++; $sum += $term; $term *= - ($x2 * ($n+$n-1))/(($n+$n+1) * $n); 
    }
  $sum;
  }

# (E(win),E(loss)) = &outcome(rating1, rating2)
sub outcome { local($_) = &erf2(($_[0]-$_[1])/400); ($_, 1-$_); }

# (E(win)) = &outcome_cached(difference in ratings)
sub outcome_cached { 
  $ratings'ocache{$_[0]} || ($ratings'ocache{$_[0]}=&erf2($_[0]/400));
  }

# @lines = &format_table($columns, @align, @row1, @row2, ...)
sub format_table { local($columns, @data) = @_;
  local($i, $j, $l, @align, @width, @lines);

  # initialise widths
  @width = (0) x $columns;

  # extract alignments
  @align = splice(@data, 0, $columns);

  # measure columns
  $j = 0;
  for $i (@data) {
    $l = length($i);
    $width[$j] = $l if $width[$j] < $l;
    $j = 0 if ++$j == $columns;
    }

  # format rows
  @lines = ();
  $j = 0;
  for $i (@data) {
    local($pad) = ' ' x ($width[$j] - length($i));
    push(@lines, '') unless $j;
    $lines[$#lines] .= ($align[$j] eq 'l') ? "$i$pad " : "$pad$i ";
    $j = 0 if ++$j == $columns;
    }

  for $i (@lines) { $i =~ s/ $//; }
  @lines;
  }

# $i = &round($f) - round to nearest integer
sub round { int($_[0] + ($_[0] >=0 ? 0.5 : -0.5)); }

# very simple binary search
sub search { local(*sub, $low, $high) = @_; local($mid);
  while ($high - $low > 1) {
    $mid = int(($low+$high)/2);
    if (&sub($mid) < 0) { $low = $mid; } else { $high = $mid; }
    }
  $mid;
  }

# very simple binary search
sub search4 { local(*sub, $low, $high, $thresh) = @_; local($mid);
  while ($high - $low > $thresh) {
    $mid = ($low+$high)/2;
    if (&sub($mid) < 0) { $low = $mid; } else { $high = $mid; }
    }
  $mid;
  }

# &load_ratings - load Magic-league ratings database
sub load_ratings { local($database, $lines_only) = @_;
  local(@fields, $i, $player, $spread);

  if ((!-f "$database.fmt") || -M _ > -M "$database.db") {
    open(HANDLE, "<$database.db") || die "open($database.db): $!\n";
    while (<HANDLE>) { chop; s/\s*#.*$//; next unless length; @_ = 
split;
      for $i (1..2) {
    $player = $_[$i];
    $rating{$player} = $_[6+$i];
    $games{$player}++;
    $spread = $_[2+$i] - $_[5-$i];
    if ($spread > 0) { $wins{$player}++; }
    elsif ($spread < 0) { $losses{$player}++; }
    else { $ties{$player}++; }
    $last{$player} = $_[0] if $last{$player} < $_[0];
    }
      }
    close(HANDLE);
    &make_fmt_file($database);
    }
  open(HANDLE, "<$database.fmt") || die "open($database.fmt): $!\n";
  while (<HANDLE>) { 
    last if $_ eq "EOF\n";
    push(@lines, $_); 
    next if $lines_only;
    next unless /^\s*[-\d]/;
    chop;
    s/^\s+//;
    ($rank, $player, @fields) = split(/\s+/);
    die "Bad line in $database.fmt: $_\n" unless $#fields == 4;
    ($rating{$player}, $wins{$player}, $losses{$player}, 
$ties{$player},
      $last{$player}) = @fields;
    $games{$player} = $wins{$player} + $losses{$player} + 
$ties{$player};
    }
  close(HANDLE);
  die "$database.fmt is incomplete.\n" unless $_ eq "EOF\n";
  }

# &make_fmt_file - create DOoM cached results file
sub make_fmt_file { local($database) = @_;
  local($player);

  open(HANDLE, ">$database.fmt") 
    || die "open(>$database.fmt): $!\n";

  @cells = (7, 'r', 'l', 'r', 'r', 'r', 'r', 'l', 'Rank', 'Player', 
'Rating',
    'Won', 'Lost', 'Tied', 'Last');
  $last=''; $rank=0; $tiedPlayers = 1;
  for (sort { 
    $rating{$b} <=> $rating{$a} ||
    $wins{$b} <=> $wins{$a} ||
    $losses{$a} <=> $losses{$b} ||
    $ties{$b} <=> $ties{$a} ||
    $last{$b} <=> $last{$a} ||
    $a cmp $b 
    } keys %last) {
    if (/^\*/) {
      next;
      $thisrank = '-';
      }
    else {
      if (length($last) && $rating{$_} == $rating{$last}
    && $wins{$_} == $wins{$last} && $losses{$_} == $losses{$last}
    && $ties{$_} == $ties{$last} && $last{$_} == $last{$last})
    { $tiedPlayers++; }
      else { $rank+=$tiedPlayers; $tiedPlayers=1; $last=$_; }
      $thisrank = $rank;
      }
    $wins{$_} = 0 unless defined $wins{$_};
    $losses{$_} = 0 unless defined $losses{$_};
    $ties{$_} = 0 unless defined $ties{$_};
    push(@cells, $thisrank, $_, $rating{$_}, $wins{$_},
      $losses{$_}, $ties{$_}, $last{$_});
    }
  print HANDLE join("\n", &format_table(@cells)), "\nEOF\n";
  close(HANDLE);
  }
1;

Comments

Sign in to comment.
Bullet_Dodger   -  Oct 30, 2008

No description
sigh

 Respond  
Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.