dragongoserver 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,19 @@
1
+ == 0.3.0 2009-07-10
2
+
3
+ * 1 bug-fix:
4
+ * Encoding-Klauseln fuer Ruby 1.9 ergaenzt
5
+ * 2 enhancements:
6
+ * new option --threshold=N
7
+ * Ruby 1.9 compatibility
8
+
9
+ == 0.2.0 2008-05-06
10
+
11
+ * 2 enhancements:
12
+ * new option --check-timeout-finished=userid
13
+ * new method finished_games_for_user
14
+ * 1 bug-fix:
15
+ * method renaming error (neue_zuege? -> new_moves?)
16
+
1
17
  == 0.1.0 2008-04-27
2
18
  * 4 enhancements:
3
19
  * new option -min/--min-wait in dgs script
data/bin/dgs CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # encoding: utf-8
2
3
 
3
4
  require 'rubygems'
4
5
  require 'dragongoserver'
@@ -6,10 +7,10 @@ require 'choice'
6
7
 
7
8
  version = Dragongoserver::VERSION::STRING
8
9
  Choice.options do
9
- header ''
10
- header 'Specific options:'
10
+ # header ''
11
+ # header 'Specific options:'
11
12
  #...
12
- separator ''
13
+ #separator ''
13
14
  separator 'Common options: '
14
15
 
15
16
  option :help do
@@ -51,19 +52,21 @@ Choice.options do
51
52
  long '--osd'
52
53
  desc 'Show messages as an on-screen-display, "osd_cat" must be installed (see http://www.ignavus.net/software.html for further details)'
53
54
  end
54
- if false
55
- short '-p'
56
- long '--port=PORT'
57
- desc 'The port to listen on (default 21)'
58
- cast Integer
59
- default 21
55
+
56
+ option :finished_games do
57
+ short '-fg'
58
+ long '--finished-games'
59
+ desc 'display the most recent finished games'
60
+ #cast Integer
61
+ #default 10
60
62
  end
61
- option :min_wait do
62
- short '-min'
63
- long '--min-wait=MIN'
64
- desc 'Minimum wait time between checks'
65
- cast Integer
66
- default 1
63
+
64
+ # listet auf, wie oft ein Spieler in den beendeten Spielen
65
+ # durch Timeout verloren hat
66
+ option :check_timeout_finished do
67
+ short '-ctf'
68
+ long '--check-timeout-finished'
69
+ cast Integer # User-id
67
70
  end
68
71
 
69
72
  option :with_name do
@@ -71,12 +74,50 @@ Choice.options do
71
74
  long '--with-name'
72
75
  desc 'Show games with name'
73
76
  end
77
+
78
+ option :min_wait do
79
+ short '-mw'
80
+ long '--min-wait'
81
+ desc 'Minimum wait time in minutes'
82
+ cast Integer
83
+ default 1
84
+ end
85
+
86
+ option :threshold do
87
+ short '-s'
88
+ long '--threshold'
89
+ desc 'Minimum number of waiting games'
90
+ cast Integer
91
+ default 1
92
+ end
93
+
94
+ end
74
95
 
96
+ if Choice.choices['check_timeout_finished']
97
+ puts "timeout check für user #{Choice.choices['check_timeout_finished']} ausgewählt"
98
+ dgs_username = ENV['DGS_USERNAME']
99
+ dgs_password = ENV['DGS_PASSWORD']
100
+ @dgs = Dgs.new(dgs_username, dgs_password)
101
+ finished = @dgs.finished_games_for_user(Choice.choices['check_timeout_finished'])
102
+ count = 0
103
+ finished.each {|g|
104
+ if g[:reason] == 'Time' and
105
+ g[:winner] != g[:player_color]
106
+ #p g[:winner] #
107
+ #g[:winner] != g[:player_color]
108
+ count += 1
109
+ end
110
+ }
111
+ puts "at least #{finished.size} finished games"
112
+ puts "#{count} games finished with timeout"
113
+ exit
75
114
  end
76
115
 
116
+ @cache_gameinfos = {}
77
117
  #p Choice.choices
78
118
  opt_waiting = Choice.choices['waiting'] # true/false
79
119
  opt_running = Choice.choices['running'] # true/false
120
+ opt_finished_games = Choice.choices['finished_games'] # true/false
80
121
  $opt_with_name = Choice.choices['with_name'] # true/false
81
122
  @opt_osd = Choice.choices['osd'] # true/false
82
123
  opt_waitingloop = Choice.choices['waitingloop'] # true/false
@@ -103,6 +144,39 @@ if opt_running
103
144
  end
104
145
  end
105
146
 
147
+ if opt_finished_games
148
+ =begin
149
+ <tr class=Row3 ondblclick="javascript:this.className=((this.className=='Row3')?'HilRow3':'Row3');">
150
+
151
+ <td class=Button><a class=Button href="game.php?gid=393488">393488</a></td>
152
+ <td><A href="sgf.php?gid=393488"><font color="#d50047">sgf</font></A></td>
153
+ <td><A href="userinfo.php?uid=107"><font color=black>maggie</font></a></td>
154
+ <td align=center><img src="17/b.gif" alt="b"></td>
155
+ <td>19</td>
156
+ <td>4</td>
157
+
158
+ <td>0.5</td>
159
+ <td>213</td>
160
+ <td>B+60.5</td>
161
+ <td align=center><img src="images/yes.gif" alt="Yes"></td>
162
+ <td>Yes</td>
163
+ <td>2008-04-23 22:48</td>
164
+
165
+ </tr>
166
+ =end
167
+ dgs = Dgs.new
168
+ finished_games = dgs.finished_games
169
+ if finished_games.size > 0
170
+ puts "you have a total of #{finished_games.size} finished games"
171
+ puts "finished games:"
172
+ finished_games.each { |game|
173
+ puts "#{game[:id]} #{game[:finished_at]}"
174
+ }
175
+ else
176
+ puts "you have no finished games"
177
+ end
178
+ end
179
+
106
180
  def plural(n)
107
181
  if n == 1
108
182
  ""
@@ -112,14 +186,30 @@ def plural(n)
112
186
  end
113
187
 
114
188
  def new_moves?(dgs)
115
- w = dgs.waiting_games
189
+ begin
190
+ w = dgs.waiting_games
191
+ rescue Timeout::Error
192
+ puts "timeout error. retrying in 30 secs"
193
+ sleep 30
194
+ retry
195
+ end
116
196
  if $opt_with_name
117
197
  print '['
118
198
  w.each {|game|
119
199
  print "#{game} "
120
- gi = dgs.gameinfo(game)
121
- print gi[:white][:name]+' '
122
- print gi[:black][:name]+','
200
+ # ggf. aus Cache holen, anstatt jedesmal neu von DGS ermitteln,
201
+ # da sich die Namen der Spieler in der Regel nicht waehrend der
202
+ # Laufzeit dieses Skripts aendern
203
+ gi=cache_gameinfo(game)
204
+ if gi
205
+ print "[c] "
206
+ end
207
+ unless gi
208
+ gi = dgs.gameinfo(game)
209
+ @cache_gameinfos[game] = gi
210
+ end
211
+ print gi[:white][:name]+' ' unless gi[:white][:name].include? "(#{dgs.username})"
212
+ print gi[:black][:name]+',' unless gi[:black][:name].include? "(#{dgs.username})"
123
213
  puts
124
214
  }
125
215
  puts ']'
@@ -128,9 +218,17 @@ def new_moves?(dgs)
128
218
  end
129
219
  #if dgs.waiting_games.size > 0 # @page.body.include?(NO_GAMES)
130
220
  if w.size > 0 # @page.body.include?(NO_GAMES)
131
- true
221
+ if $threshold
222
+ if w.size < $threshold.to_i
223
+ return false
224
+ else
225
+ return true
226
+ end
227
+ else
228
+ return true
229
+ end
132
230
  else
133
- false
231
+ return false
134
232
  end
135
233
  end
136
234
 
@@ -142,6 +240,7 @@ $nur_dringende = false # TODO:
142
240
  $min_secs = Choice.choices[:min_wait].to_i*60 #60*15
143
241
  $secs = $min_secs
144
242
  $count = 0
243
+ $threshold = Choice.choices[:threshold].to_i
145
244
  def osd_output?
146
245
  return @opt_osd
147
246
  end
@@ -154,10 +253,14 @@ def puts_x(arg)
154
253
  end
155
254
  end
156
255
 
256
+ def cache_gameinfo(game)
257
+ @cache_gameinfos[game]
258
+ end
259
+
157
260
  def schleife
158
261
  dgs = Dgs.new
159
- # dgs.login
160
- #page = dgs.page
262
+ $min_secs = Choice.choices[:min_wait].to_i*60 #60*15
263
+
161
264
  $dringend = false
162
265
  changes = false
163
266
  if $nur_dringende
@@ -170,31 +273,23 @@ def schleife
170
273
  elsif new_moves? dgs
171
274
  changes = true
172
275
  else
173
- # puts "keine neuen Zuege"
174
276
  puts "no waiting moves"
175
- #
176
277
  end
177
278
  if changes
178
279
  $count = 0
179
- # puts "neue Zuege, neue Methode"
180
280
  puts "waiting games"
181
281
  $secs = $secs / 2
182
282
  if $secs < $min_secs
183
283
  $secs = $min_secs
184
284
  end
185
- # puts "vermindere Abfrageintervall auf #{$secs} Sekunden(n)"
186
285
  puts "decreasing request interval to #{$secs} seconds"
187
- # puts "neue Zuege"
188
286
  puts "waiting games"
189
287
  if $dringend
190
288
  $osd.puts("DRINGENDE Spiele")
191
289
  end
192
- # puts("Deine Mitspieler bei Dragon Go Server warten auf deine Spielzuege")
193
290
  puts_x("Your opponents at Dragon Go Server are waiting for your moves")
194
- #-- $osd.puts("Deine Mitspieler bei Dragon Go Server warten auf deine Spielzuege")
195
- #-- $osd.flush
196
291
  else
197
- $count+=1
292
+ $count += 1
198
293
  if $count >= 3
199
294
  $secs = $secs*2
200
295
  # puts "erhoehe Abfrageintervall auf #{$secs} Sekunden(n)"
@@ -203,13 +298,20 @@ def schleife
203
298
  end
204
299
  end
205
300
  end
301
+
206
302
  if opt_waitingloop
207
303
  while 1
208
304
  # $osd = IO.popen("osd_cat -p middle -f -adobe-helvetica-*-*-*-*-24-*-*-*- *-*-*-* -s 3 -S lightgray --delay=60","w+")
209
305
  if osd_output?
210
306
  $osd = IO.popen("osd_cat -p middle -f -sony-fixed-medium-*-normal-*-24-*-*-*-*-*-*-* -s 3 -S lightgray --delay=60","w+")
211
307
  end
212
- schleife
308
+ begin
309
+ schleife
310
+ rescue SocketError
311
+ puts "SocketError - waiting 60 secs and retrying"
312
+ sleep 60
313
+ retry
314
+ end
213
315
  if osd_output?
214
316
  $osd.close_write
215
317
  $osd.close
@@ -1,7 +1,9 @@
1
- # $:.unshift File.dirname(__FILE__)
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
3
 
3
4
  module Dragongoserver
4
5
  end
5
6
 
6
7
  require 'dragongoserver/version'
7
8
  require 'dragongoserver/dragongoserver'
9
+ require 'dragongoserver/game'
@@ -12,8 +12,9 @@ class Dgs
12
12
  USER_AGENT_ALIAS = 'Mac Safari' # should work with every browser type
13
13
 
14
14
  SAVE_WAIT = 15 # wait n seconds before each request
15
- # if we are doing to many requests at DGS the account will be
16
- # temporarily blocked (for about 1 day)
15
+ # if we are doing too many requests at DGS the account (YOUR ACCOUNT)
16
+ # will be temporarily blocked (for about 1 day)
17
+
17
18
  attr_reader :username
18
19
 
19
20
  def initialize(username=nil,password=nil)
@@ -49,7 +50,7 @@ class Dgs
49
50
  end
50
51
  game_id=0
51
52
  user_id=0
52
- page.body.each {|line|
53
+ page.body.each_line {|line|
53
54
  if line =~ /gid=([0-9]+)"/
54
55
  game_id = $1.to_i
55
56
  # ??? games << {:game => game_id, :user => userid}
@@ -83,16 +84,174 @@ class Dgs
83
84
  raise "PageError: #{DGS_STATUS_PAGE} not found"
84
85
  end
85
86
 
86
- page = agent.click page.links.text('Show running games')
87
- page.body.each {|line|
87
+ # page = agent.click page.links.text('Show running games')
88
+ page = agent.click page.link_with(:text => 'Show running games')
89
+
90
+ # *_with(:text => "Show running games")
91
+ page.body.each_line {|line|
88
92
  if line =~ /gid=([0-9]+)"/
89
93
  games << $1.to_i
90
94
  end
91
95
  }
96
+
97
+ # BEGIN naechste Seite(n)
98
+ #p page.links
99
+ # page = agent.click page.link_with(:text => '=&gt;')
100
+ while true
101
+ begin
102
+ page = agent.click page.link_with(:text => '=>')
103
+ rescue
104
+ break # keine weitere Seite vorhanden
105
+ end
106
+
107
+ page.body.each {|line|
108
+ if line =~ /gid=([0-9]+)"/
109
+ games << $1.to_i
110
+ end
111
+ }
112
+ end
113
+ # END naechste Seite(n)
92
114
  # aus Bequemlichkeitsgruenden (gid= kommt mehrfach vor): uniq
93
115
  games.uniq
94
116
  end
117
+
118
+ # Array of your finished games
119
+ # http://www.dragongoserver.net/show_games.php?uid=10737
120
+ def finished_games
121
+ save_wait
122
+ games = []
123
+ #@home = 'http://www.dragongoserver.net/show_games.php?uid=10737' #TODO:
124
+ @home = DGS_STATUS_PAGE
125
+ agent = WWW::Mechanize.new
126
+ agent.user_agent_alias = USER_AGENT_ALIAS
127
+
128
+ page = agent.get(@home)
129
+ if page.body.include?(LOGGED_IN)
130
+ page = login(agent)
131
+ end
132
+
133
+ #if !page.body.include?(YOUR_TURN)
134
+ # raise "PageError: #{DGS_STATUS_PAGE} not found"
135
+ #end
136
+
137
+ # page = agent.click page.links.text('Show finished games')
138
+ page = agent.click page.link_with(:text => 'Show finished games')
139
+ page.body.each_line {|line|
140
+ if line =~ /gid=([0-9]+)"/
141
+ games << {:id => $1.to_i, :finished_at => DateTime.now}
142
+ end
143
+ }
144
+ page_no = 1
145
+
146
+ # p page.links.find { |l| l.title =~ /next page/ }
147
+ #p page.links
95
148
 
149
+ # naechste Seite
150
+ # while page.link_with(:text => '+')
151
+ while page.link_with(:title => 'next page [&amp;&gt;]')
152
+ page_no += 1
153
+ puts "at page_no = #{page_no}"
154
+ # page = agent.click page.link_with(:text => '+')
155
+ page = agent.click page.link_with(:title => 'next page [&amp;&gt;]')
156
+ # nochmal alle Spiele auf Folgeseite durchgehen
157
+ page.body.each {|line|
158
+ if line =~ /gid=([0-9]+)"/
159
+ games << {:id => $1.to_i, :finished_at => DateTime.now}
160
+ end
161
+ }
162
+ end
163
+
164
+ # aus Bequemlichkeitsgruenden (gid= kommt mehrfach vor): uniq
165
+ games.uniq
166
+ end
167
+
168
+ # same as finished_games but only the ids of the games
169
+ def finished_games_ids
170
+ result = []
171
+ finished_games.each { |e|
172
+ result << e[:id]
173
+ }
174
+ result
175
+ end
176
+
177
+ # http://www.dragongoserver.net/show_games.php?uid=31098&finished=1
178
+ # the first page of finished games for this user
179
+ def finished_games_for_user(user_id)
180
+ save_wait
181
+ games = []
182
+ @home = "http://www.dragongoserver.net/show_games.php?uid=#{user_id}&finished=1" #TODO:
183
+ #p @home
184
+ #@home = DGS_STATUS_PAGE
185
+ agent = WWW::Mechanize.new
186
+ agent.user_agent_alias = USER_AGENT_ALIAS
187
+
188
+ page = agent.get(@home)
189
+ if page.body.include?(LOGGED_IN)
190
+ page = login(agent)
191
+ page = agent.click page.link_with(:text => 'Users')
192
+ if !page.body.include?("Active users")
193
+ raise "Active users not diplaying"
194
+ end
195
+ form = page.forms.first
196
+ form.sf1 = user_id.to_s
197
+
198
+ page = agent.submit(form)
199
+ # page = agent.click page.links.text("#{user_id}")
200
+ page = agent.click page.link_with(:text => "#{user_id}")
201
+ # page = agent.click page.links.text("Show finished games")
202
+ page = agent.click page.link_with(:text => "Show finished games")
203
+ end
204
+ if !page.body.include?("Finished games for")
205
+ #p page.body
206
+ raise "Finished games for not on page"
207
+ end
208
+ #page = agent.click page.links.text('Show finished games')
209
+ one_game = {}
210
+ page.body.each {|line|
211
+ # p line
212
+ #p one_game
213
+ if line =~ /gid=([0-9]+)"/
214
+ one_game[:id] = $1.to_i
215
+ end
216
+ # <td align=center><img src="17/w.gif" alt="w"></td>
217
+ if line =~ /[wb].gif/ and
218
+ one_game[:id]
219
+ #p $1
220
+ color = line.split('.gif')[0][-1,1]
221
+ #p line.split('.gif')[0] #[-1,1]
222
+ #p color
223
+ if color == 'w'
224
+ one_game[:player_color] = :white
225
+ else
226
+ one_game[:player_color] = :black
227
+ end
228
+ end
229
+ # W+Time
230
+ if line =~ /[WB]\+/ and
231
+ one_game[:id]
232
+ color,reason = line.split('+')
233
+ if color[-1,1] == 'W'
234
+ one_game[:winner] = :white
235
+ else
236
+ one_game[:winner] = :black
237
+ end
238
+
239
+ one_game[:reason] = reason[0,reason.index('<')]
240
+ end
241
+ #<td>2008-04-19 10:29</td>
242
+ if line =~ /(\d+)-(\d+)-(\d+)/ and
243
+ one_game[:id]
244
+ d = Date.new($1.to_i,$2.to_i,$3.to_i)
245
+ one_game[:finished_at] = d
246
+ games << one_game
247
+ one_game = {}
248
+ end
249
+ }
250
+ # aus Bequemlichkeitsgruenden (gid= kommt mehrfach vor): uniq
251
+ #p games
252
+ games # .uniq
253
+ end
254
+
96
255
  # your rank as a GoRank object
97
256
  def get_rank
98
257
  save_wait
@@ -109,12 +268,15 @@ class Dgs
109
268
  raise "PageError: #{DGS_STATUS_PAGE} not found"
110
269
  end
111
270
  a = show_regexp(page.body, /(\d+)&nbsp;(kyu|dan)/)
112
- num = a[0]
271
+ num = a[0].to_i
113
272
  what = a[1].to_sym
114
273
  myRank = GoRank.new num, what
115
274
  myRank
116
275
  end
117
276
 
277
+ # rank is an alias to get_rank
278
+ alias :rank :get_rank
279
+
118
280
  # your id at DGS
119
281
  def userid
120
282
  save_wait
@@ -163,7 +325,7 @@ class Dgs
163
325
  @userinfo[:country] = nil
164
326
 
165
327
  result = Hash.new
166
- page.body.each {|line|
328
+ page.body.each_line {|line|
167
329
  #<td class="Rubric">Name</td><td>Thomas Preymesser</td>
168
330
  if line =~ /td class="Rubric"/
169
331
  #p line
@@ -183,12 +345,19 @@ class Dgs
183
345
  elsif a[0]=="Rating"
184
346
  #
185
347
 
186
- b = show_regexp(a[1], /(\d+)&nbsp;(kyu|dan)/)
187
- num = b[0]
188
- what = b[1].to_sym
189
- myRank = GoRank.new num, what
190
- result[:rating] = myRank
191
- #
348
+ if a[1] =~ /(\d+)&nbsp;(kyu|dan)/
349
+ b = show_regexp(a[1], /(\d+)&nbsp;(kyu|dan)/)
350
+ num = b[0].to_i
351
+ what = b[1].to_sym
352
+ begin
353
+ result[:rating] = GoRank.new num, what
354
+ rescue
355
+ raise "illegal rank: #{a[1]}\n#{num}/#{what}"
356
+ end
357
+ else
358
+ result[:rating] = nil
359
+ end
360
+ ##
192
361
  #result[:rating] = a[1]
193
362
  elsif a[0]=="Last access"
194
363
  result[:lastaccess] = DateTime.parse(a[1].gsub(/&nbsp;/,' '))
@@ -263,20 +432,22 @@ Time remaining: 9&nbsp;days&nbsp;and&nbsp;6&nbsp;hours</td>
263
432
  #elements = doc.search("//table[@class='GameInfos']").search('tr[@id='BlackInfo')
264
433
  elements = doc.search("//table[@class='GameInfos']")
265
434
  blackinfo = (elements/"tr[@id='blackInfo']")
266
- #pp blackinfo
267
435
  whiteinfo = (elements/"tr[@id='whiteInfo']")
268
- whiteinfo_name = (whiteinfo/"td[@class='Name']/a").inner_html
269
- blackinfo_name = (blackinfo/"td[@class='Name']/a").inner_html
270
- #pp whiteinfo
271
- #pp whiteinfo_name
272
- #pp blackinfo_name
273
- ##p whiteinfo_name.inner_html
436
+ whiteinfo_name = (whiteinfo/"td[@class='Name']/a").inner_text #2008-12-28 inner_html
437
+ blackinfo_name = (blackinfo/"td[@class='Name']/a").inner_text #2008-12-28 inner_html
274
438
  result[:black][:name] = blackinfo_name
275
439
  result[:white][:name] = whiteinfo_name
276
- # p result
440
+
277
441
  result
278
442
  end
279
443
 
444
+ # all games of the own user
445
+ # finished games + running games
446
+ # TODO: should return an array of game instances
447
+ def games
448
+ [4,5,6]
449
+ end
450
+
280
451
  private
281
452
 
282
453
  def show_regexp(a, re)
@@ -290,7 +461,8 @@ Time remaining: 9&nbsp;days&nbsp;and&nbsp;6&nbsp;hours</td>
290
461
  def login(agent)
291
462
  @home = DGS_INDEX_PAGE
292
463
  page = agent.get(@home)
293
- form = page.forms.with.name("loginform").first
464
+ #form = page.forms.with.name("loginform").first
465
+ form = page.form("loginform")
294
466
  form.fields.find {|f| f.name == 'userid'}.value = @username
295
467
  form.fields.find {|f| f.name == 'passwd'}.value = @password
296
468
  page = agent.submit(form, form.buttons.first)
@@ -301,4 +473,4 @@ Time remaining: 9&nbsp;days&nbsp;and&nbsp;6&nbsp;hours</td>
301
473
  sleep(SAVE_WAIT)
302
474
  end
303
475
 
304
- end
476
+ end