OSDN Git Service

484ffd3c8d32ce6b8a9139b0e051c66ccb83fe24
[shogi-server/shogi-server.git] / shogi_server / league / floodgate.rb
1 require 'thread'
2 require 'ostruct'
3 require 'pathname'
4
5 module ShogiServer
6
7 class League
8   class Floodgate
9     class << self
10       # "floodgate-900-0"
11       #
12       def game_name?(str)
13         return /^floodgate\-\d+\-\d+$/.match(str) ? true : false
14       end
15     end
16
17     attr_reader :next_time, :league
18
19     def initialize(league, next_time=nil)
20       @league = league
21       @next_time = next_time
22       charge
23     end
24
25     def charge
26       now = Time.now
27       unless $DEBUG
28         # each 30 minutes
29         if now.min < 30
30           @next_time = Time.mktime(now.year, now.month, now.day, now.hour, 30)
31         else
32           @next_time = Time.mktime(now.year, now.month, now.day, now.hour) + 3600
33         end
34       else
35         # for test, each 30 seconds
36         if now.sec < 30
37           @next_time = Time.mktime(now.year, now.month, now.day, now.hour, now.min, 30)
38         else
39           @next_time = Time.mktime(now.year, now.month, now.day, now.hour, now.min) + 60
40         end
41       end
42     end
43
44     def match_game
45       players = @league.find_all_players do |pl|
46         pl.status == "game_waiting" &&
47         Floodgate.game_name?(pl.game_name) &&
48         pl.sente == nil
49       end
50       Pairing.match(players)
51     end
52
53
54     #
55     #
56     class History
57       @@mutex = Mutex.new
58
59       class << self
60         def factory
61           file = Pathname.new $options["floodgate-history"]
62           history = History.new file
63           history.load
64           return history
65         end
66       end
67
68       attr_reader :records
69
70       # file_path_name is a Pathname object for this storage
71       #
72       def initialize(file_path_name)
73         @records = []
74         @max_records = 100
75         @file = file_path_name
76       end
77
78       # Return a hash describing the game_result
79       # :game_id: game id
80       # :black:   Black's player id
81       # :white:   White's player id
82       # :winner:  Winner's player id or nil for the game without a winner
83       # :loser:   Loser's player id or nil for the game without a loser
84       #
85       def make_record(game_result)
86         hash = Hash.new
87         hash[:game_id] = game_result.game.game_id
88         hash[:black]   = game_result.black.player_id
89         hash[:white]   = game_result.white.player_id
90         case game_result
91         when GameResultWin
92           hash[:winner] = game_result.winner.player_id
93           hash[:loser]  = game_result.loser.player_id
94         else
95           hash[:winner] = nil
96           hash[:loser]  = nil
97         end
98         return hash
99       end
100
101       def load
102         return unless @file.exist?
103
104         yaml = @file.open("r") {|f| f.read}
105         @records = YAML.load(yaml)
106       end
107
108       def save
109         begin
110           @file.open("w+") do |f| 
111             f << YAML.dump(@records)
112           end
113         rescue Errno::ENOSPC
114           # ignore
115         end
116       end
117
118       def update(game_result)
119         record = make_record(game_result)
120         @@mutex.synchronize do 
121           load
122           @records << record
123           while @records.size > @max_records
124             @records.shift
125           end
126           save
127         end
128       end
129       
130       def last_win?(player_id)
131         rc = last_valid_game(player_id)
132         return false unless rc
133         return rc[:winner] == player_id
134       end
135       
136       def last_lose?(player_id)
137         rc = last_valid_game(player_id)
138         return false unless rc
139         return rc[:loser] == player_id
140       end
141
142       def last_valid_game(player_id)
143         records = nil
144         @@mutex.synchronize do
145           records = @records.reverse
146         end
147         rc = records.find do |rc|
148           rc[:winner] && 
149           rc[:loser]  && 
150           (rc[:black] == player_id || rc[:white] == player_id)
151         end
152         return rc
153       end
154     end # class History
155
156
157   end # class Floodgate
158
159
160 end # class League
161 end # module ShogiServer