# -*- coding: utf-8 -*- module LORChess class RoundRobinTable require 'yaml' DATADIR = '2014/2-summertime' ROUNDS = 2 dir = File.dirname(__FILE__) players_yaml = File.expand_path("../../#{DATADIR}/players.yml", dir) @@db_players = YAML.load_file players_yaml results_yaml = File.expand_path("../../#{DATADIR}/results.yml", dir) @@db_results = YAML.load_file results_yaml @@dim = @@db_players.length @@rounds = ROUNDS || 1 # Sort players in numerical order @@db_players.sort! { |x,y| x['number'] <=> y['number'] } def initialize @players = @@db_players.map { |player| player['lor'] } @elo_points = @@db_players.map { |player| player['elo'].to_s } @game_scores = Array.new(@@rounds) { Array.new(@@dim) { Array.new(@@dim) } } @player_games = Array.new(@@dim, 0) @total_scores = Array.new(@@dim, 0.0) @player_places = Array.new(@@dim) @berger_coefs = Array.new(@@dim, 0.0) @buffer = '' # Players withdrew from tournament @players_withdrew = @@db_players .select { |player| player['status'] == 'withdrew' } .map { |player| player['lor'] } # Correlate the player with his number @player_numbers = {} @players.each_with_index { |player, i| @player_numbers[player] = i } fill_results calculate results_to_s # Withdraw players from tournament (seppuku) @players_withdrew.each do |player| num = @player_numbers[player] @players[num] = "#{player}" end end def fill_results @@db_results.each do |tour| if tour['games'] # zero-based round round = (tour['number'] - 1).div(@@dim - 1) tour['games'].each do |game| import game, round end end end end def import game, round num_white = @player_numbers[game['white']] num_black = @player_numbers[game['black']] score = game['result'].split ':' @game_scores[round][num_white][num_black] = score[0].to_f @game_scores[round][num_black][num_white] = score[1].to_f end def calculate @game_scores.each do |round| round.each_with_index do |row, index| games = 0 sum = 0.0 row.each do |score| unless score.nil? games += 1 sum += score end end @player_games[index] += games @total_scores[index] += sum end end calculate_berger player_data = [] @@dim.times do |i| player_data << { :number => i, :total => @total_scores[i], :berger => @berger_coefs[i] } end # Sort players in the reverse order to Berger coefficient player_data.sort! { |x,y| y[:berger] <=> x[:berger] } # Sort players in the reverse order to total score by the bubble # sorting, keeping the order of Berger coefficients for equal # total scores (@@dim - 1).times do |i| (@@dim - 2).downto(i) do |j| if player_data[j][:total] < player_data[j+1][:total] data = player_data[j] player_data[j] = player_data[j+1] player_data[j+1] = data end end end player_data.each_with_index do |data, i| @player_places[data[:number]] = (i + 1).to_s end end def calculate_berger @game_scores.each do |round| round.each_with_index do |row, index| berger = 0.0 row.each_with_index do |score, i| berger += score * @total_scores[i] unless score.nil? end @berger_coefs[index] += berger end end end def results_to_s @game_scores.map! do |round| round.map do |row| row.map { |cell| stylize_score cell } end end @player_games.map! { |num| num.to_s } @total_scores.map! { |score| stylize_score score } @berger_coefs.map! { |coef| coef.to_s } end # Replace the fractional part `0.5' by ½ def stylize_score score return '' if score.nil? frac = score.to_s.split '.' unless frac[0] == '0' str = frac[0] str += '½' if frac[1] == '5' else str = (frac[1] == '5') ? '½' : '0' end str end def to_html @buffer << "\n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @@dim.times do |i| @buffer << " \n" end @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @@dim.times do |i| @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @@dim.times do |j| unless j == i @@rounds.times do |round| @buffer << " \n" end else @buffer << " \n" * @@rounds end end @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" @buffer << " \n" end @buffer << " \n" @buffer << "
Таблица результатов\n" @buffer << "
Участникelo*#{(i + 1).to_s}ИгрыОчкиМестоБергер
* Средний elo на начало турнира
#{(i + 1).to_s}#{@players[i]}#{@elo_points[i]}#{@game_scores[round][i][j]}#{@player_games[i]}#{@total_scores[i]}#{@player_places[i]}#{@berger_coefs[i]}
\n" @buffer end end end