shogi-server source
Révision | b7c423c1acf55538449d03e639b4769c9d844832 (tree) |
---|---|
l'heure | 2015-12-13 18:59:20 |
Auteur | Daigo Moriwaki <daigo@debi...> |
Commiter | Daigo Moriwaki |
Merge branch '201512-leastdiff'
@@ -18,6 +18,9 @@ | ||
18 | 18 | b) Least_Time_Per_Move will be 0 for floodgate-600-10 games; |
19 | 19 | otherwise 1. |
20 | 20 | (Closes: #35839) |
21 | + * [shogi-server] shogi_server/pairing.rb: | |
22 | + - LeastDiff attempts more trials, depending of a number of players | |
23 | + to be matched. | |
21 | 24 | |
22 | 25 | 2015-11-27 Daigo Moriwaki <daigo at debian dot org> |
23 | 26 |
@@ -514,6 +514,22 @@ module ShogiServer | ||
514 | 514 | ret |
515 | 515 | end |
516 | 516 | |
517 | + # Total combinations of possible games among n players | |
518 | + # nC2 * (n-2)C2 * ... * 2C2 / (n/2)! | |
519 | + def total_posibilities(n) | |
520 | + n -= 1 if n.odd? | |
521 | + return 1 if n <= 2 | |
522 | + | |
523 | + ret = 1 | |
524 | + i = n | |
525 | + while i >= 2 do | |
526 | + ret *= ::ShogiServer::nCk(i,2) | |
527 | + i -= 2 | |
528 | + end | |
529 | + ret /= ::ShogiServer::factorial(n/2) | |
530 | + return ret | |
531 | + end | |
532 | + | |
517 | 533 | def match(players) |
518 | 534 | super |
519 | 535 | if players.size < 3 |
@@ -524,12 +540,16 @@ module ShogiServer | ||
524 | 540 | # Reset estimated rate |
525 | 541 | players.each {|p| p.estimated_rate = 0} |
526 | 542 | |
527 | - # 10 trials | |
528 | 543 | matches = [] |
529 | 544 | scores = [] |
530 | 545 | path = ShogiServer::League::Floodgate.history_file_path(players.first.game_name) |
531 | 546 | history = ShogiServer::League::Floodgate::History.factory(path) |
532 | - 10.times do | |
547 | + | |
548 | + # Increase trials, depending on a number of players | |
549 | + trials = [300, total_posibilities(players.size)/3].min | |
550 | + trials = [10, trials].max | |
551 | + log_message("Floodgate: %d trials" % [trials]) | |
552 | + trials.times do | |
533 | 553 | m = random_match(players) |
534 | 554 | matches << m |
535 | 555 | scores << calculate_diff_with_penalty(m, history) |
@@ -42,6 +42,25 @@ module ShogiServer | ||
42 | 42 | end |
43 | 43 | module_function :shuffle |
44 | 44 | |
45 | + def factorial(n) | |
46 | + return 1 if n<=1 | |
47 | + ret = 1 | |
48 | + while n >= 2 | |
49 | + ret *= n | |
50 | + n -= 1 | |
51 | + end | |
52 | + return ret | |
53 | + end | |
54 | + module_function :factorial | |
55 | + | |
56 | + def nCk(n, k) | |
57 | + return 0 if n < k | |
58 | + numerator = factorial(n) | |
59 | + denominator = factorial(k) * factorial(n - k) | |
60 | + return numerator / denominator | |
61 | + end | |
62 | + module_function :nCk | |
63 | + | |
45 | 64 | # See if the file is writable. The file will be created if it does not exist |
46 | 65 | # yet. |
47 | 66 | # Return true if the file is writable, otherwise false. |
@@ -499,6 +499,12 @@ class TestLeastDiff < Test::Unit::TestCase | ||
499 | 499 | assert_pairs([@a,@b,@h], players) |
500 | 500 | end |
501 | 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 | + | |
502 | 508 | def test_calculate_diff_with_penalty |
503 | 509 | players = [@a,@b] |
504 | 510 | assert_equal(@b.rate-@a.rate, @pairing.calculate_diff_with_penalty(players,nil)) |
@@ -597,6 +603,13 @@ class TestLeastDiff < Test::Unit::TestCase | ||
597 | 603 | |
598 | 604 | assert_equal(@b.rate-200, @pairing.get_player_rate(@x, @history)) |
599 | 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 | |
600 | 613 | end |
601 | 614 | |
602 | 615 | class TestExcludeUnratedPlayers < Test::Unit::TestCase |
@@ -61,3 +61,22 @@ class TestMkdir < Test::Unit::TestCase | ||
61 | 61 | end |
62 | 62 | |
63 | 63 | end |
64 | + | |
65 | +class TestFactorial < Test::Unit::TestCase | |
66 | + def test_factorial | |
67 | + assert_equal 1, ShogiServer::factorial(0) | |
68 | + assert_equal 1, ShogiServer::factorial(1) | |
69 | + assert_equal 2, ShogiServer::factorial(2) | |
70 | + assert_equal 6, ShogiServer::factorial(3) | |
71 | + end | |
72 | +end | |
73 | + | |
74 | +class TestnCk < Test::Unit::TestCase | |
75 | + def test_nCk | |
76 | + assert_equal 0, ShogiServer::nCk(2,5) | |
77 | + assert_equal 1, ShogiServer::nCk(2,2) | |
78 | + assert_equal 6, ShogiServer::nCk(4,2) | |
79 | + assert_equal 11*5*9, ShogiServer::nCk(12,4) | |
80 | + end | |
81 | +end | |
82 | + |