dragongoserver 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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