X-Git-Url: http://git.sourceforge.jp/view?p=shogi-server%2Fshogi-server.git;a=blobdiff_plain;f=mk_rate;h=dff397759b84727a692c6e74693f183da0d5015c;hp=dc6813e7e8710054b37c95a0782aa9a62a55a325;hb=89e8f3ebf0fd5d45c323d4a9eb4070eede4a5d10;hpb=18adb37a8f65a48feef7bce5fbfd10cd4842e6fb diff --git a/mk_rate b/mk_rate index dc6813e..dff3977 100755 --- a/mk_rate +++ b/mk_rate @@ -1,56 +1,95 @@ #!/usr/bin/ruby -## $Id$ - -## Copyright (C) 2006-2008 Daigo Moriwaki -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -# -# This calculates rating scores of every players from CSA files, and outputs a -# yaml file (players.yaml) that Shogi Server can read. -# -# Sample: -# $ ./mk_rate . > players.yaml -# $ ./mk_rate . && ./mk_rate . > players.yaml +# $Id$ # -# The conditions that games and players are rated as following: -# * Rated games, which were played by both rated players. -# * Rated players, who logged in the server with a name followed by a trip: -# "name,trip". -# * (Rated) players, who played more than $GAMES_LIMIT [15] (rated) games. +# Author:: Daigo Moriwaki +# Homepage:: http://sourceforge.jp/projects/shogi-server/ +# +#-- +# Copyright (C) 2006-2008 Daigo Moriwaki +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#++ +# +# == Synopsis +# +# mk_rate reads CSA files, calculates rating scores of each player, and then +# outputs a yaml file (players.yaml) that Shogi-server can recognize. +# +# == Usage +# +# ./mk_rate [options] DIR.. +# +# DIR:: +# CSA files are recursively looked up the directories. +# +# --half-life:: +# n [days] (default 60) +# +# --half-life-ignore:: +# m [days] (default 7) +# after m days, the half-life effect works +# +# --fixed-rate-player:: +# player whose rate is fixed at the rate +# +# --fixed-rate:: +# rate +# +# --help:: +# show this message # +# == PREREQUIRE # -# PREREQUIRE -# ========== +# Sample Command lines that isntall prerequires will work on Debian. # -# Sample Commands to isntall prerequires will work for Debian. +# * Ruby 1.8.7 +# +# $ sudo aptitude install ruby1.8 # # * Rubygems +# # $ sudo aptitude install rubygems # -# * Ruby bindings for the GNU Scientific Library (GSL) +# * Ruby bindings for the GNU Scientific Library (GSL[http://rb-gsl.rubyforge.org/]) +# # $ sudo aptitude install libgsl-ruby1.8 -# Or, download it from http://rb-gsl.rubyforge.org/ . # -# * RGL: Ruby Graph Library +# * RGL: {Ruby Graph Library}[http://rubyforge.org/projects/rgl/] +# # $ sudo gem install rgl -# Or, download it from http://rubyforge.org/projects/rgl/ . +# +# == Run +# +# $ ./mk_rate . > players.yaml +# +# or, if you do not want the file to be update in case of errors, +# +# $ ./mk_rate . && ./mk_rate . > players.yaml +# +# == How players are rated +# +# The conditions that games and players are rated as following: +# +# * Rated games, which were played by both rated players. +# * Rated players, who logged in the server with a name followed by a trip: "name,trip". +# * (Rated) players, who played more than $GAMES_LIMIT [15] (rated) games. # require 'yaml' require 'time' +require 'getoptlong' require 'gsl' require 'rubygems' require 'rgl/adjacency' @@ -336,6 +375,13 @@ class Rating end ## + # Translate by value + # + def translate!(value) + @rate += value + end + + ## # Make the values of @rate integer. # def integer! @@ -420,14 +466,19 @@ class WinLossMatrix end ## - # Removes a delete_index'th player and returns a new object. + # Removes players in a rows such as [1,3,5], and then returns a new + # object. # - def delete_row(delete_index) + def delete_rows(rows) + rows = rows.sort.reverse + copied_cols = [] (0...size).each do |i| - next if i == delete_index + next if rows.include?(i) row = @matrix.row(i).clone - row.delete_at(delete_index) + rows.each do |j| + row.delete_at(j) + end copied_cols << row end if copied_cols.size == 0 @@ -435,20 +486,13 @@ class WinLossMatrix else new_matrix = GSL::Matrix[*copied_cols] end - new_keys = @keys.clone - new_keys.delete_at(delete_index) - return WinLossMatrix.new(new_keys, new_matrix) - end - ## - # Removes players in a rows; [1,3,5] - # - def delete_rows(rows) - obj = self - rows.sort.reverse.each do |index| - obj = obj.delete_row(index) + new_keys = @keys.clone + rows.each do |j| + new_keys.delete_at(j) end - obj + + return WinLossMatrix.new(new_keys, new_matrix) end ## @@ -538,12 +582,11 @@ end # Half-life effect # After NHAFE_LIFE days value will get half. # 0.693 is constant, where exp(0.693) ~ 0.5 -NHALF_LIFE=60 def half_life(days) - if days < 7 + if days < $options["half-life-ignore"] return 1.0 else - Math::exp(-0.693/NHALF_LIFE*(days-7)) + Math::exp(-0.693/$options["half-life"]*(days-$options["half-life-ignore"])) end end @@ -608,7 +651,8 @@ def grep(file) black_id, white_id = $1.split(":").map {|a| a.strip} black_id = identify_id(black_id) white_id = identify_id(white_id) - if black_id && white_id && (black_id != white_id) + if black_id && white_id && (black_id != white_id) && + black_mark && white_mark add(black_mark, black_id, white_id, white_mark, time) end end @@ -634,10 +678,63 @@ def validate(yaml) return true end +def usage(io) + io.puts <