cricinfo 0.0.1 → 0.0.2

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.
@@ -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).