OSDN Git Service

utils/eval_graph.rb: Support Fischer time control.
[shogi-server/shogi-server.git] / test / TC_pairing.rb
1 $:.unshift File.join(File.dirname(__FILE__), "..")
2 require 'test/unit'
3 require 'shogi_server'
4 require 'shogi_server/league.rb'
5 require 'shogi_server/player'
6 require 'shogi_server/pairing'
7 require 'test/mock_log_message'
8
9 def same_pair?(a, b)
10   unless a.size == 2 && b.size == 2
11     return false
12   end
13
14   return true if [a.first, a.last] == b || [a.last, a.first] == b
15 end
16
17 class TestPairing < Test::Unit::TestCase  
18   def setup
19     @pairing= ShogiServer::Pairing.new
20     $pairs = []
21     def @pairing.start_game(p1,p2)
22       $pairs << [p1,p2]
23     end
24     @a = ShogiServer::BasicPlayer.new
25     @a.name = "a"
26     @a.win  = 1
27     @a.loss = 2
28     @a.rate = 0
29     @a.last_game_win = false
30     @b = ShogiServer::BasicPlayer.new
31     @b.name = "b"
32     @b.win  = 10
33     @b.loss = 20
34     @b.rate = 1500
35     @b.last_game_win = true
36     @c = ShogiServer::BasicPlayer.new
37     @c.name = "c"
38     @c.win  = 100
39     @c.loss = 200
40     @c.rate = 1000
41     @c.last_game_win = true
42     @d = ShogiServer::BasicPlayer.new
43     @d.name = "d"
44     @d.win  = 1000
45     @d.loss = 2000
46     @d.rate = 1800
47     @d.last_game_win = true
48   end
49
50   def test_include_newbie
51     assert(@pairing.include_newbie?([@a]))
52     assert(!@pairing.include_newbie?([@b]))
53     assert(@pairing.include_newbie?([@b,@a]))
54     assert(!@pairing.include_newbie?([@b,@c]))
55   end
56 end
57
58 class TestStartGame < Test::Unit::TestCase
59   def setup
60     @pairing= ShogiServer::StartGame.new
61     $called = 0
62     def @pairing.start_game(p1,p2)
63       $called += 1
64     end
65     @a = ShogiServer::BasicPlayer.new
66     @a.name = "a"
67     @a.win  = 1
68     @a.loss = 2
69     @a.rate = 0
70     @b = ShogiServer::BasicPlayer.new
71     @b.name = "b"
72     @b.win  = 10
73     @b.loss = 20
74     @b.rate = 1500
75     @c = ShogiServer::BasicPlayer.new
76     @c.name = "c"
77     @c.win  = 100
78     @c.loss = 200
79     @c.rate = 1000
80     @d = ShogiServer::BasicPlayer.new
81     @d.name = "d"
82     @d.win  = 1000
83     @d.loss = 2000
84     @d.rate = 2000
85   end
86
87   def test_match_two_players
88     players = [@a,@b]
89     @pairing.match(players)
90     assert_equal(1, $called)
91   end
92
93   def test_match_one_player
94     players = [@a]
95     @pairing.match(players)
96     assert_equal(0, $called)
97   end
98
99   def test_match_zero_player
100     players = []
101     @pairing.match(players)
102     assert_equal(0, $called)
103   end
104
105   def test_match_three_players
106     players = [@a,@b,@c]
107     @pairing.match(players)
108     assert_equal(1, $called)
109   end
110
111   def test_match_four_players
112     players = [@a,@b,@c,@d]
113     @pairing.match(players)
114     assert_equal(2, $called)
115   end
116 end
117
118 class TestStartGameWithoutHumans < Test::Unit::TestCase
119   def setup
120     @pairing= ShogiServer::StartGameWithoutHumans.new
121     $paired = []
122     $called = 0
123     def @pairing.start_game(p1,p2)
124       $called += 1
125       $paired << [p1,p2]
126     end
127     @a = ShogiServer::BasicPlayer.new
128     @a.name = "a"
129     @a.win  = 1
130     @a.loss = 2
131     @a.rate = 0
132     @b = ShogiServer::BasicPlayer.new
133     @b.name = "b"
134     @b.win  = 10
135     @b.loss = 20
136     @b.rate = 1500
137     @c = ShogiServer::BasicPlayer.new
138     @c.name = "c"
139     @c.win  = 100
140     @c.loss = 200
141     @c.rate = 1000
142     @d = ShogiServer::BasicPlayer.new
143     @d.name = "d"
144     @d.win  = 1000
145     @d.loss = 2000
146     @d.rate = 2000
147     @e = ShogiServer::BasicPlayer.new
148     @e.name = "e"
149     @e.win  = 3000
150     @e.loss = 3000
151     @e.rate = 3000
152     @f = ShogiServer::BasicPlayer.new
153     @f.name = "f"
154     @f.win  = 4000
155     @f.loss = 4000
156     @f.rate = 4000
157     @g = ShogiServer::BasicPlayer.new
158     @g.name = "g"
159     @g.win  = 5000
160     @g.loss = 5000
161     @g.rate = 5000
162     @h = ShogiServer::BasicPlayer.new
163     @h.name = "h"
164     @h.win  = 6000
165     @h.loss = 6000
166     @h.rate = 6000
167   end
168
169   def test_match_one_player
170     players = [@a]
171     @pairing.match(players)
172     assert_equal(0, $called)
173   end
174
175   def test_match_one_player_human
176     @a.name += "_human"
177     players = [@a]
178     @pairing.match(players)
179     assert_equal(0, $called)
180   end
181
182   def test_match_two_players
183     players = [@a,@b]
184     @pairing.match(players)
185     assert_equal(1, $called)
186   end
187
188   def test_match_two_players_humans
189     @a.name += "_human"
190     @b.name += "_human"
191     players = [@a,@b]
192     @pairing.match(players)
193     assert_equal(1, $called)
194   end
195
196   def test_match_zero_player
197     players = []
198     @pairing.match(players)
199     assert_equal(0, $called)
200   end
201
202   def test_match_three_players
203     players = [@a,@b,@c]
204     @pairing.match(players)
205     assert_equal(1, $called)
206   end
207
208   def test_match_three_players_a_human
209     @a.name += "_human"
210     players = [@a,@b,@c]
211     @pairing.match(players)
212     assert_equal(1, $called)
213     assert_equal(1, players.size)
214     assert_equal(@c, players[0])
215   end
216
217   def test_match_three_players_b_human
218     @b.name += "_human"
219     players = [@a,@b,@c]
220     @pairing.match(players)
221     assert_equal(1, $called)
222     assert_equal(1, players.size)
223     assert_equal(@c, players[0])
224   end
225
226   def test_match_three_players_c_human
227     @c.name += "_human"
228     players = [@a,@b,@c]
229     @pairing.match(players)
230     assert_equal(1, $called)
231     assert_equal(1, players.size)
232     assert_equal(@c, players[0])
233   end
234
235   def test_match_three_players_ab_human
236     @a.name += "_human"
237     @b.name += "_human"
238     players = [@a,@b,@c]
239     @pairing.match(players)
240     assert_equal(1, $called)
241     assert_equal(1, players.size)
242     assert_equal(@b, players[0])
243   end
244
245   def test_match_three_players_bc_human
246     @b.name += "_human"
247     @c.name += "_human"
248     players = [@a,@b,@c]
249     @pairing.match(players)
250     assert_equal(1, $called)
251     assert_equal(1, players.size)
252     assert_equal(@c, players[0])
253   end
254
255   def test_match_four_players
256     players = [@a,@b,@c,@d]
257     @pairing.match(players)
258     assert_equal(2, $called)
259   end
260
261   def test_match_four_players_ab_human
262     @a.name += "_human"
263     @b.name += "_human"
264     players = [@a,@b,@c,@d]
265     @pairing.match(players)
266     assert_equal(2, $paired.size)
267     assert(same_pair?([@a,@c], $paired[0]))
268     assert(same_pair?([@b,@d], $paired[1]))
269   end
270
271   def test_match_four_players_bc_human
272     @b.name += "_human"
273     @c.name += "_human"
274     players = [@a,@b,@c,@d]
275     @pairing.match(players)
276     assert_equal(2, $paired.size)
277     assert(same_pair?([@a,@b], $paired[0]))
278     assert(same_pair?([@c,@d], $paired[1]))
279   end
280
281   def test_match_four_players_abc_human
282     @a.name += "_human"
283     @b.name += "_human"
284     @c.name += "_human"
285     players = [@a,@b,@c,@d]
286     @pairing.match(players)
287     assert_equal(2, $paired.size)
288     assert(same_pair?([@a,@d], $paired[0]))
289     assert(same_pair?([@b,@c], $paired[1]))
290   end
291
292   def test_match_four_players_bcd_human
293     @b.name += "_human"
294     @c.name += "_human"
295     @d.name += "_human"
296     players = [@a,@b,@c,@d]
297     @pairing.match(players)
298     assert_equal(2, $paired.size)
299     assert(same_pair?([@a,@c], $paired[0]))
300     assert(same_pair?([@b,@d], $paired[1]))
301   end
302
303   def test_match_four_players_abcd_human
304     @a.name += "_human"
305     @b.name += "_human"
306     @c.name += "_human"
307     @d.name += "_human"
308     players = [@a,@b,@c,@d]
309     @pairing.match(players)
310     assert_equal(2, $paired.size)
311     assert(same_pair?([@a,@b], $paired[0]))
312     assert(same_pair?([@c,@d], $paired[1]))
313   end
314
315   def test_match_eight_players_efgh_human
316     @e.name += "_human"
317     @f.name += "_human"
318     @g.name += "_human"
319     @h.name += "_human"
320     players = [@a,@b,@c,@d,@e,@f,@g,@h]
321     @pairing.match(players)
322     assert_equal(4, $paired.size)
323     assert(same_pair?([@e,@c], $paired[0]))
324     assert(same_pair?([@d,@g], $paired[1]))
325     assert(same_pair?([@a,@f], $paired[2]))
326     assert(same_pair?([@b,@h], $paired[3]))
327   end
328 end
329
330 class TestLeastDiff < Test::Unit::TestCase
331
332   class MockLeague
333     def initialize
334       @players = []
335     end
336
337     def add(player)
338       @players << player
339     end
340
341     def find(name)
342       @players.find do |p|
343         p.name == name
344       end
345     end
346   end
347
348   def setup
349     $league = MockLeague.new
350
351     @pairing= ShogiServer::LeastDiff.new
352     $paired = []
353     $called = 0
354     def @pairing.start_game(p1,p2)
355       $called += 1
356       $paired << [p1,p2]
357     end
358
359     @file = Pathname.new(File.join(File.dirname(__FILE__), "floodgate_history.yaml"))
360     @history = ShogiServer::League::Floodgate::History.new @file
361
362     @a = ShogiServer::BasicPlayer.new
363     @a.player_id = "a"
364     @a.name = "a"
365     @a.win  = 1
366     @a.loss = 2
367     @a.rate = 500
368     @b = ShogiServer::BasicPlayer.new
369     @b.player_id = "b"
370     @b.name = "b"
371     @b.win  = 10
372     @b.loss = 20
373     @b.rate = 800
374     @c = ShogiServer::BasicPlayer.new
375     @c.player_id = "c"
376     @c.name = "c"
377     @c.win  = 100
378     @c.loss = 200
379     @c.rate = 1000
380     @d = ShogiServer::BasicPlayer.new
381     @d.player_id = "d"
382     @d.name = "d"
383     @d.win  = 1000
384     @d.loss = 2000
385     @d.rate = 1500
386     @e = ShogiServer::BasicPlayer.new
387     @e.player_id = "e"
388     @e.name = "e"
389     @e.win  = 3000
390     @e.loss = 3000
391     @e.rate = 2000
392     @f = ShogiServer::BasicPlayer.new
393     @f.player_id = "f"
394     @f.name = "f"
395     @f.win  = 4000
396     @f.loss = 4000
397     @f.rate = 2150
398     @g = ShogiServer::BasicPlayer.new
399     @g.player_id = "g"
400     @g.name = "g"
401     @g.win  = 5000
402     @g.loss = 5000
403     @g.rate = 2500
404     @h = ShogiServer::BasicPlayer.new
405     @h.player_id = "h"
406     @h.name = "h"
407     @h.win  = 6000
408     @h.loss = 6000
409     @h.rate = 3000
410     @x = ShogiServer::BasicPlayer.new
411     @x.player_id = "x"
412     @x.name = "x"
413
414     @abcdefg1 = ShogiServer::BasicPlayer.new
415     @abcdefg1.player_id = "abcdefg1"
416     @abcdefg1.name = "abcdefg1"
417     @abcdefg1.rate = 2100
418     @abcdefg2 = ShogiServer::BasicPlayer.new
419     @abcdefg2.player_id = "abcdefg2"
420     @abcdefg2.name = "abcdefg2"
421     @abcdefg2.rate = 2200
422     @abcdxyz = ShogiServer::BasicPlayer.new
423     @abcdxyz.player_id = "abcdxyz"
424     @abcdxyz.name = "abcdxyz"
425     @abcdxyz.rate = 2300
426
427     $league.add(@a)
428     $league.add(@b)
429     $league.add(@c)
430     $league.add(@d)
431     $league.add(@e)
432     $league.add(@f)
433     $league.add(@g)
434     $league.add(@h)
435     $league.add(@x)
436     $league.add(@abcdefg1)
437     $league.add(@abcdefg2)
438     $league.add(@abcdxyz)
439   end
440
441   def teardown
442     @file.delete if @file.exist?
443   end
444
445   def assert_pairs(x_array, y_array)
446     if (x_array.size != y_array.size)
447       assert_equal(x_array.size, y_array.size)
448       return
449     end
450     i = 0
451
452     if (x_array.size == 1)
453       assert_equal(x_array[0].name, y_array[0].name)
454       return
455     end
456
457     ret = true
458     while i < x_array.size
459       if i == x_array.size-1
460         assert_equal(x_array[i].name, y_array[i].name)
461         break
462       end
463       px1 = x_array[i]
464       px2 = x_array[i+1]
465       py1 = y_array[i]
466       py2 = y_array[i+1]
467
468       if ! ((px1.name == py1.name && px2.name == py2.name) ||
469             (px1.name == py2.name && px2.name == py1.name))
470         ret = false
471       end
472       i += 2
473     end
474
475     assert(ret)
476   end
477
478   def test_match_one_player
479     players = [@a]
480     assert_equal(0, @pairing.calculate_diff_with_penalty(players,nil))
481     r = @pairing.match(players)
482     assert_pairs([@a], r)
483   end
484
485   def test_match_two_players
486     players = [@a,@b]
487     assert_equal(@b.rate-@a.rate, @pairing.calculate_diff_with_penalty([@a,@b],nil))
488     assert_equal(@b.rate-@a.rate, @pairing.calculate_diff_with_penalty([@b,@a],nil))
489     r = @pairing.match(players)
490     assert_pairs([@a,@b], r)
491   end
492
493   def test_match_three_players
494     players = [@h,@a,@b]
495     assert_equal(300,  @pairing.calculate_diff_with_penalty([@a,@b,@h],nil))
496     assert_equal(2200, @pairing.calculate_diff_with_penalty([@b,@h,@a],nil))
497     r = @pairing.match(players)
498     assert_pairs([@a,@b,@h], r)
499     assert_pairs([@a,@b,@h], players)
500   end
501
502   def test_match_many_players
503     players = [@a,@b,@h,@a,@b,@h,@a,@b,@h,@a,@b,@h,@a,@b,@h,@a,@b,@h,@a,@b,@h,@a,@b,@h,@a,@b,@h,@a,@b,@h]
504     r = @pairing.match(players)
505     assert true
506   end
507
508   def test_calculate_diff_with_penalty
509     players = [@a,@b]
510     assert_equal(@b.rate-@a.rate, @pairing.calculate_diff_with_penalty(players,nil))
511
512     dummy = nil
513     def @history.make_record(game_result)
514       {:game_id => "wdoor+floodgate-900-0-a-b-1", 
515        :black => "b",  :white => "a",
516        :winner => "a", :loser => "b"}
517     end
518     @history.update(dummy)
519     assert_equal(@b.rate-@a.rate+400, @pairing.calculate_diff_with_penalty(players, @history))
520   end
521
522   def test_calculate_diff_with_penalty2
523     players = [@a,@b,@g,@h]
524     assert_equal(@b.rate-@a.rate+@h.rate-@g.rate, @pairing.calculate_diff_with_penalty(players,nil))
525   end
526
527   def test_calculate_diff_with_penalty2_1
528     players = [@a,@b,@g,@h]
529     assert_equal(@b.rate-@a.rate+@h.rate-@g.rate, @pairing.calculate_diff_with_penalty(players,nil))
530     dummy = nil
531     def @history.make_record(game_result)
532       {:game_id => "wdoor+floodgate-900-0-a-b-1", 
533        :black => "b",  :white => "a",
534        :winner => "a", :loser => "b"}
535     end
536     @history.update(dummy)
537     assert_equal(@b.rate-@a.rate+400+@h.rate-@g.rate, @pairing.calculate_diff_with_penalty(players, @history))
538   end
539
540   def test_calculate_diff_with_penalty2_2
541     players = [@a,@b,@g,@h]
542     assert_equal(@b.rate-@a.rate+@h.rate-@g.rate, @pairing.calculate_diff_with_penalty(players,nil))
543     dummy = nil
544     def @history.make_record(game_result)
545       {:game_id => "wdoor+floodgate-900-0-a-b-1", 
546        :black => "g",  :white => "h",
547        :winner => "h", :loser => "g"}
548     end
549     @history.update(dummy)
550     assert_equal(@b.rate-@a.rate+400+@h.rate-@g.rate, @pairing.calculate_diff_with_penalty(players, @history))
551     #assert_equal(@b.rate-@a.rate+400+@h.rate-@g.rate+400, @pairing.calculate_diff_with_penalty(players, [@b,@a,@h,@g]))
552   end
553
554   def test_calculate_diff_with_penalty2_3
555     players = [@a,@b,@g,@h]
556     assert_equal(@b.rate-@a.rate+@h.rate-@g.rate, @pairing.calculate_diff_with_penalty(players,nil))
557     dummy = nil
558     def @history.make_record(game_result)
559       {:game_id => "wdoor+floodgate-900-0-a-b-1", 
560        :black => "g",  :white => "h",
561        :winner => "h", :loser => "g"}
562     end
563     @history.update(dummy)
564     def @history.make_record(game_result)
565       {:game_id => "wdoor+floodgate-900-0-a-b-1", 
566        :black => "b",  :white => "a",
567        :winner => "a", :loser => "b"}
568     end
569     @history.update(dummy)
570     assert_equal(@b.rate-@a.rate+400+@h.rate-@g.rate+400, @pairing.calculate_diff_with_penalty(players, @history))
571   end
572
573   def test_calculate_diff_with_kin_4_players
574     players = [@abcdefg1, @abcdxyz]
575     assert_equal(@abcdxyz.rate - @abcdefg1.rate + 400, @pairing.calculate_diff_with_penalty(players,nil))
576   end
577
578   def test_calculate_diff_with_kin_7_players
579     players = [@abcdefg1, @abcdefg2]
580     assert_equal(@abcdefg2.rate - @abcdefg1.rate + 800, @pairing.calculate_diff_with_penalty(players,nil))
581   end
582
583   def test_get_player_rate_0
584     assert_equal(2150, @pairing.get_player_rate(@x, @history))
585
586     @x.estimated_rate = 0
587     dummy = nil
588     def @history.make_record(game_result)
589       {:game_id => "wdoor+floodgate-900-0-x-a-1", 
590        :black => "x",  :white => "a",
591        :winner => "x", :loser => "a"}
592     end
593     @history.update(dummy)
594     assert_equal(@a.rate+200, @pairing.get_player_rate(@x, @history))
595
596     @x.estimated_rate = 0
597     def @history.make_record(game_result)
598       {:game_id => "wdoor+floodgate-900-0-x-b-1", 
599        :black => "x",  :white => "b",
600        :winner => "b", :loser => "x"}
601     end
602     @history.update(dummy)
603
604     assert_equal(@b.rate-200, @pairing.get_player_rate(@x, @history))
605   end
606
607   def test_total_posibilities
608     assert_equal 1, @pairing.total_posibilities(2)
609     assert_equal 1, @pairing.total_posibilities(3)
610     assert_equal 3, @pairing.total_posibilities(4)
611     assert_equal 945, @pairing.total_posibilities(10)
612   end
613 end
614
615 class TestExcludeUnratedPlayers < Test::Unit::TestCase
616   def setup
617     @pairing= ShogiServer::ExcludeUnratedPlayers.new
618     @a = ShogiServer::BasicPlayer.new
619     @a.name = "a"
620     @a.win  = 1
621     @a.loss = 2
622     @a.rate = 0
623     @b = ShogiServer::BasicPlayer.new
624     @b.name = "b"
625     @b.win  = 10
626     @b.loss = 20
627     @b.rate = 1500
628     @c = ShogiServer::BasicPlayer.new
629     @c.name = "c"
630     @c.win  = 100
631     @c.loss = 200
632     @c.rate = 1000
633     @d = ShogiServer::BasicPlayer.new
634     @d.name = "d"
635     @d.win  = 1000
636     @d.loss = 2000
637     @d.rate = 2000
638   end
639
640   def test_match_without_any_players
641     players = []
642     @pairing.match(players)
643     assert_equal([], players)
644   end
645
646   def test_match_without_unrated_player_1
647     players = [@b, @c, @d]
648     @pairing.match(players)
649     assert_equal([@b, @c, @d], players)
650   end
651
652   def test_match_without_unrated_player_2
653     players = [@b]
654     @pairing.match(players)
655     assert_equal([@b], players)
656   end
657
658   def test_match_with_unrated_player_1
659     players = [@a, @b, @c, @d]
660     @pairing.match(players)
661     assert_equal([@b, @c, @d], players)
662   end
663
664   def test_match_with_unrated_player_2
665     players = [@a]
666     @pairing.match(players)
667     assert_equal([], players)
668   end
669 end