3 ## Copyright (C) 2004 NABEYA Kenichi (aka nanami@2ch)
4 ## Copyright (C) 2007-2008 Daigo Moriwaki (daigo at debian dot org)
6 ## This program is free software; you can redistribute it and/or modify
7 ## it under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 2 of the License, or
9 ## (at your option) any later version.
11 ## This program is distributed in the hope that it will be useful,
12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ## GNU General Public License for more details.
16 ## You should have received a copy of the GNU General Public License
17 ## along with this program; if not, write to the Free Software
18 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #return SwissPairing.new
27 return ExcludeSacrifice.new(SwissPairing.new)
28 #return RandomPairing.new
29 #return ExcludeSacrifice.new(RandomPairing.new)
35 log_message("Floodgate[%s]: too few players [%d]" %
36 [self.class, players.size])
38 log_message("Floodgate[%s]: found %d players. Pairing them..." %
39 [self.class, players.size])
43 def start_game(p1, p2)
46 Game.new(p1.game_name, p1, p2)
49 def include_newbie?(players)
50 return players.find{|a| a.rate == 0} == nil ? false : true
53 def delete_player_at_random(players)
54 return players.delete_at(rand(players.size))
57 def delete_player_at_random_except(players, a_player)
58 candidates = players - [a_player]
59 return delete_player_at_random(candidates)
62 def delete_most_playing_player(players)
63 # TODO ??? undefined method `<=>' for nil:NilClass
64 max_player = players.max {|a,b| a.win + a.loss <=> b.win + b.loss}
65 return players.delete(max_player)
68 def delete_least_rate_player(players)
69 min_player = players.min {|a,b| a.rate <=> b.rate}
70 return players.delete(min_player)
73 def pairing_and_start_game(players)
74 return if players.size < 2
75 if players.size % 2 == 1
76 log_warning("#Players should be even: %d" % [players.size])
79 sorted = players.sort{ rand < 0.5 ? 1 : -1 }
81 pairs = [[sorted.shift]]
82 while !sorted.empty? do
83 if pairs.last.size < 2
84 pairs.last << sorted.shift
86 pairs << [sorted.shift]
90 start_game(pair.first, pair.last)
95 class RandomPairing < Pairing
98 return if players.size < 2
100 if players.size % 2 == 1
101 delete_player_at_random(players)
103 pairing_and_start_game(players)
107 class SwissPairing < Pairing
110 return if players.size < 2
112 win_players = players.find_all {|a| a.last_game_win?}
113 remains = players - win_players
114 if win_players.size >= 2
115 if win_players.size % 2 == 1
116 # if include_newbie?(win_players)
117 remains << delete_player_at_random(win_players)
119 # remains << delete_least_rate_player(win_players)
122 pairing_and_start_game(win_players)
124 remains.concat(win_players)
126 return if remains.size < 2
127 if remains.size % 2 == 1
128 delete_player_at_random(remains)
129 # delete_most_playing_player(remains)
131 pairing_and_start_game(remains)
135 class ExcludeSacrifice
136 attr_accessor :sacrifice
138 def initialize(pairing)
140 @sacrifice = "gps500+e293220e3f8a3e59f79f6b0efffaa931"
145 players.size % 2 == 1 &&
146 players.find{|a| a.player_id == @sacrifice}
147 log_message("Floodgate: first, exclude %s" % [@sacrifice])
148 players.delete_if{|a| a.player_id == @sacrifice}
150 @pairing.match(players)
153 # Delegate to @pairing
154 def method_missing(message, *arg)
155 @pairing.send(message, *arg)
157 end # class ExcludeSacrifice