cricinfo 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ === 0.0.2 2010-07-14
2
+
3
+ * updated match regex
4
+ * added bin/cricinfo script with 'list' command
5
+
1
6
  === 0.0.1 2010-03-14
2
7
 
3
8
  * 1 major enhancement:
@@ -2,6 +2,7 @@
2
2
  ./Manifest.txt
3
3
  ./README.rdoc
4
4
  ./Rakefile
5
+ ./bin/cricinfo
5
6
  ./lib/cricinfo/game.rb
6
7
  ./lib/cricinfo/innings.rb
7
8
  ./lib/cricinfo/scores.rb
@@ -13,7 +13,11 @@ An interface to cricinfo.com game data (current games only).
13
13
  == SYNOPSIS:
14
14
 
15
15
  c = CricInfo::Scores.new
16
- c.games.each { |g| puts game.summary }
16
+ c.games.each { |game| puts game.summary }
17
+
18
+ game = c.games.first
19
+ puts game.inns1.runs
20
+ puts game.inns1.wickets
17
21
 
18
22
  == INSTALL:
19
23
 
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.dirname(__FILE__) + '/../lib'
4
+ require 'cricinfo'
5
+
6
+ def error(message)
7
+ puts "ERROR: #{message}"
8
+ end
9
+
10
+ def usage(exit = true)
11
+ puts "usage: cricinfo <command>"
12
+ exit 1 if exit
13
+ end
14
+
15
+ begin
16
+ command = ARGV[0]
17
+ usage unless command
18
+
19
+ case command
20
+ when 'list'
21
+ c = CricInfo::Scores.new
22
+ c.games.each { |game| puts game.summary }
23
+ else
24
+ error("unrecognised command #{command}")
25
+ usage
26
+ end
27
+
28
+ end
@@ -8,6 +8,16 @@ require 'cricinfo/game'
8
8
  require 'cricinfo/scores'
9
9
 
10
10
  module CricInfo
11
- VERSION = '0.0.1'
11
+ VERSION = '0.0.2'
12
12
  end
13
13
 
14
+ # array monkey patch
15
+ # http://snippets.dzone.com/posts/show/3332
16
+ class Array
17
+ def permutations
18
+ return [self] if size < 2
19
+ perm = []
20
+ each { |e| (self - [e]).permutations.each { |p| perm << ([e] + p) } }
21
+ perm
22
+ end
23
+ end
@@ -13,15 +13,25 @@ module CricInfo
13
13
 
14
14
  include GameTypes
15
15
 
16
- attr_reader :inns1, :inns2
17
- attr_accessor :start_time, :name, :type
16
+ attr_accessor :start_time, :name, :type, :innings
17
+ # team1 is the team batting first (first innings)
18
+ attr_accessor :team1, :team2
18
19
 
19
20
  def initialize
20
- @inns1 = Innings.new
21
- @inns2 = Innings.new
21
+ @innings = []
22
22
  @type = GAMETYPE_ODI # assume ODI by default
23
23
  end
24
24
 
25
+ def inns1; @innings[0]; end
26
+ def inns2; @innings[1]; end
27
+ def inns3; @innings[2]; end
28
+ def inns4; @innings[3]; end
29
+
30
+ def add_innings
31
+ @innings.push(Innings.new)
32
+ @innings[-1]
33
+ end
34
+
25
35
  def type_string
26
36
  gtype = ["Unknown game type", "Test match", "ODI", "T20"]
27
37
  type >= 0 && type <= GAMETYPE_T20 ? gtype[type] : gtype[0]
@@ -30,11 +40,8 @@ module CricInfo
30
40
  # returns a string summarising the game data
31
41
  def summary
32
42
  out = ''
33
- out += "%s: %s v %s (%s)\n" % [name, inns1.team, inns2.team, type_string]
34
- if(!start_time)
35
- out += inns1.summary if inns1.summary
36
- out += inns2.summary if inns2.summary
37
- end
43
+ out += "%s: %s v %s (%s)\n" % [name, team1, team2, type_string]
44
+ out += innings.collect { |i| i.summary }.join
38
45
  out
39
46
  end
40
47
 
@@ -7,7 +7,8 @@ module CricInfo
7
7
  # returns a string summarising the innings data
8
8
  def summary
9
9
  return '' unless overs || runs # overs can be blank if innings over
10
- out = "%s %d/%d" % [team, runs, wickets]
10
+ out = "%s %d" % [team, runs]
11
+ out += "/%d" % [wickets] if wickets
11
12
  out += " declared" if declared
12
13
  out += " (%s ov)" % [overs] if overs
13
14
  out += "\n"
@@ -1,3 +1,4 @@
1
+
1
2
  module CricInfo
2
3
  class Scores
3
4
  include CricInfo::GameTypes
@@ -6,10 +7,11 @@ module CricInfo
6
7
  SCORES_PATH = "/s/2497/Scores"
7
8
 
8
9
  # match name, team1, team2, inningsdata, start_time
9
- RE_MATCH = /matchId=\d+">(.+?):\s*(\w+)\s+v\s+(\w+)<\/a>.*?<\/tr>(.*?)<\/tr>(.*?Start time (.*?)\s*<\/b>)?/
10
+ RE_MATCH = /matchId=.*?">(.+?):\s*(\w+)\s+v\s+(\w+)<\/a>.*?<\/tr>(.*?)<\/tr>(.*?Start time (.*?)\s*<\/b>)?/
10
11
 
11
- # team1/2, runs, wickets, declared, overs (overs optional)
12
- RE_INNINGS = /<b>\s*(\w+)\s*<\/b>\s*<b>\s*(\d+)\/(\d+)(d)?\s*(\(([\d\.]+))?/
12
+ # team1/2, i1runs, i1wickets, i1decl, i2wickets, i2decl, overs
13
+ # (overs optional)
14
+ RE_INNINGS = /<b>\s*(\w+)\s*<\/b>\s*<b>\s*(\d+)(?:\/(\d+))?(d)?(?:\s*&amp;\s*(\d+)\/(\d+)(d)?)?\s*(?:\(([\d\.]+))?/
13
15
 
14
16
  # start_time (e.g. Start time 09:30 GMT)
15
17
  RE_START = /<b>\s*Start\s+time\s+(.*?)\s*<\/b>/
@@ -32,33 +34,28 @@ module CricInfo
32
34
 
33
35
  game = Game.new
34
36
  game.name = match_name
35
- inns_count = 0
36
37
  game.type = GAMETYPE_TEST if match_name.match(/Test/)
37
- game.inns1.team = team1
38
- game.inns2.team = team2
38
+ game.team1 = team1
39
+ game.team2 = team2
39
40
  game.start_time = start ? Time.parse(start) : nil
40
41
 
41
42
  # parse innings data
42
- idata.scan(RE_INNINGS) do |team, runs, wickets, declared, junk, overs|
43
- inns_count += 1
44
- inns = inns_count == 1 ? game.inns1 : game.inns2
45
-
46
- if inns_count == 1 && game.inns1.team != team
47
- # need to switch innings teams
48
- # (order is different to that shown in match name)
49
- tmp = game.inns1.team
50
- game.inns1.team = game.inns2.team
51
- game.inns2.team = tmp
52
- end
53
-
54
- game.type = GAMETYPE_TEST if overs.to_f > Game::OVERS_ODI
55
-
56
- inns.runs = runs.to_i
57
- inns.wickets = wickets.to_i
58
- inns.overs = overs
59
- inns.declared = declared ? true : false
43
+ idata.scan(RE_INNINGS) do |data|
44
+ team, i1runs, i1wickets, i1decl, i2runs, i2wickets, i2decl, overs = *data
45
+ game.type = GAMETYPE_TEST if overs && overs.to_f > Game::OVERS_ODI
46
+ inns1 = add_innings(game, team, i1runs, i1wickets, i1decl)
47
+ inns2 = add_innings(game, team, i2runs, i2wickets, i2decl)
48
+
49
+ # overs given applies to the last innings
50
+ inns = inns2 ? inns2 : inns1
51
+ inns.overs = overs ? overs : nil
60
52
  end
61
53
 
54
+ # rorder innings: attempt to guess innings order.
55
+ # find first valid permutation of innings order.
56
+ list = game.innings.permutations.detect { |i| valid_innings_order(i) }
57
+ game.innings = list if list
58
+
62
59
  @games.push(game)
63
60
  end
64
61
 
@@ -66,6 +63,40 @@ module CricInfo
66
63
 
67
64
  private
68
65
 
66
+ # return true if the order of the list of innings is valid.
67
+ def valid_innings_order(list)
68
+ return true if list.length <= 1
69
+
70
+ # any innings with overs attached must be the last innings.
71
+ over_inns = list.detect { |i| i.overs }
72
+ return false if over_inns && over_inns != list[-1]
73
+
74
+ # the first and second innings must be different teams.
75
+ return false if list[0].team == list[1].team
76
+
77
+ # - a team can only bat twice in a row if it is following on.
78
+ # -- (a team can only follow on if it is > 200 runs behind)
79
+ (1...list.length).each do |i|
80
+ if list[i].team == list[i - 1].team
81
+ # team batted twice
82
+ return false unless list[i - 2].runs > list[i - 1].runs + 200
83
+ end
84
+ end
85
+
86
+ return true # innings order is valid
87
+ end
88
+
89
+ def add_innings(game, team, runs, wickets, decl)
90
+ return unless runs
91
+
92
+ inns = game.add_innings
93
+ inns.team = team
94
+ inns.runs = runs.to_i
95
+ inns.wickets = wickets ? wickets.to_i : 10
96
+ inns.declared = decl ? true : false
97
+ inns
98
+ end
99
+
69
100
  def self.fetch_score_data
70
101
  Net::HTTP.get(SCORES_HOST, SCORES_PATH) || ''
71
102
  end
@@ -6,7 +6,7 @@ describe CricInfo::Scores do
6
6
  FIXTURE_PATH = File.dirname(__FILE__) + '/fixtures'
7
7
 
8
8
  # Scores1.html
9
- it "should initialize and parse score data" do
9
+ it "should initialize and parse score data 1" do
10
10
  CricInfo::Scores.should_receive(:fetch_score_data).and_return(fixture(1))
11
11
  c = CricInfo::Scores.new
12
12
  c.should_not be_nil
@@ -15,15 +15,15 @@ describe CricInfo::Scores do
15
15
  game = c.games[0]
16
16
  game.name.should == "5th ODI"
17
17
  game.type.should == GAMETYPE_ODI
18
- game.inns1.team.should == "NZ"
19
- game.inns2.team.should == "AUS"
18
+ game.team1.should == "NZ"
19
+ game.team2.should == "AUS"
20
20
  game.inns1.runs.should == 219
21
21
  game.inns1.wickets.should == 8
22
22
  game.inns1.overs.should == "46.4"
23
23
  end
24
24
 
25
25
  # Scores4.html
26
- it "should initialize and parse score data" do
26
+ it "should initialize and parse score data 4" do
27
27
  CricInfo::Scores.should_receive(:fetch_score_data).and_return(fixture(4))
28
28
  c = CricInfo::Scores.new
29
29
  c.should_not be_nil
@@ -32,8 +32,8 @@ describe CricInfo::Scores do
32
32
  game = c.games[1]
33
33
  game.name.should == "5th ODI"
34
34
  game.type.should == GAMETYPE_ODI
35
- game.inns1.team.should == "NZ"
36
- game.inns2.team.should == "AUS"
35
+ game.team1.should == "NZ"
36
+ game.team2.should == "AUS"
37
37
  game.inns1.runs.should == 241
38
38
  game.inns1.wickets.should == 9
39
39
  game.inns2.runs.should == 129
@@ -41,24 +41,64 @@ describe CricInfo::Scores do
41
41
  game.inns2.overs.should == "33.3"
42
42
 
43
43
  game = c.games[0] # not started
44
- game.inns1.team.should == "MUMB"
45
- game.inns2.team.should == "RTHAN"
44
+ game.team1.should == "MUMB"
45
+ game.team2.should == "RTHAN"
46
46
  game.start_time.should == Time.parse("09:30 GMT")
47
47
  end
48
48
 
49
49
  # Scores5.html
50
- it "should initialize and parse score data" do
50
+ it "should initialize and parse score data 5" do
51
51
  CricInfo::Scores.should_receive(:fetch_score_data).and_return(fixture(5))
52
52
  c = CricInfo::Scores.new
53
53
  c.should_not be_nil
54
54
 
55
55
  c.games.length.should == 1
56
56
  game = c.games[0] # BAN v ENG
57
- game.inns1.team.should == "ENG" # note: order different to game name
57
+ game.team1.should == "BAN"
58
+ game.team2.should == "ENG"
59
+ game.inns1.team.should == "ENG" # note: order different to game team names
58
60
  game.inns2.team.should == "BAN"
59
61
  game.inns1.declared.should == true
60
62
  end
61
63
 
64
+ # Scores6.html
65
+ # 3 innings
66
+ it "should initialize and parse score data 6" do
67
+ CricInfo::Scores.should_receive(:fetch_score_data).and_return(fixture(6))
68
+ c = CricInfo::Scores.new
69
+ c.should_not be_nil
70
+
71
+ c.games.length.should == 2
72
+ game = c.games[1] # BAN v ENG
73
+ game.innings.length.should == 3
74
+
75
+ game.inns1.team.should == "ENG"
76
+ game.inns2.team.should == "BAN"
77
+ game.inns3.team.should == "ENG"
78
+ end
79
+
80
+ # Scores7.html (doctored from Scores6.html)
81
+ # 4 innings
82
+ it "should initialize and parse score data 7" do
83
+ CricInfo::Scores.should_receive(:fetch_score_data).and_return(fixture(7))
84
+ c = CricInfo::Scores.new
85
+ c.should_not be_nil
86
+
87
+ c.games.length.should == 2
88
+ game = c.games[1] # BAN v ENG
89
+ game.innings.length.should == 4
90
+
91
+ game.inns1.team.should == "ENG"
92
+ game.inns1.runs.should == 599
93
+ game.inns1.wickets.should == 6
94
+ game.inns1.declared.should == true
95
+ game.inns2.team.should == "BAN"
96
+ game.inns2.runs.should == 296
97
+ game.inns2.wickets.should == 10
98
+ game.inns3.team.should == "ENG"
99
+ game.inns4.team.should == "BAN"
100
+ end
101
+
62
102
  private
63
103
 
64
104
  def fixture(number)
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cricinfo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
5
11
  platform: ruby
6
12
  authors:
7
13
  - Andrew S Williams
@@ -9,19 +15,25 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-03-14 00:00:00 +10:30
18
+ date: 2010-07-14 00:00:00 +09:30
13
19
  default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: hoe
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 5
30
+ segments:
31
+ - 2
32
+ - 3
33
+ - 3
23
34
  version: 2.3.3
24
- version:
35
+ type: :development
36
+ version_requirements: *id001
25
37
  description: An interface to cricinfo.com game data (current games only).
26
38
  email:
27
39
  - sobakasu@gmail.com
@@ -37,6 +49,7 @@ files:
37
49
  - ./Manifest.txt
38
50
  - ./README.rdoc
39
51
  - ./Rakefile
52
+ - ./bin/cricinfo
40
53
  - ./lib/cricinfo/game.rb
41
54
  - ./lib/cricinfo/innings.rb
42
55
  - ./lib/cricinfo/scores.rb
@@ -63,21 +76,27 @@ rdoc_options:
63
76
  require_paths:
64
77
  - lib
65
78
  required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
66
80
  requirements:
67
81
  - - ">="
68
82
  - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
69
86
  version: "0"
70
- version:
71
87
  required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
72
89
  requirements:
73
90
  - - ">="
74
91
  - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
75
95
  version: "0"
76
- version:
77
96
  requirements: []
78
97
 
79
98
  rubyforge_project: cricinfo
80
- rubygems_version: 1.3.5
99
+ rubygems_version: 1.3.7
81
100
  signing_key:
82
101
  specification_version: 3
83
102
  summary: An interface to cricinfo.com game data (current games only).