cricinfo 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/Manifest.txt +1 -0
- data/README.rdoc +5 -1
- data/bin/cricinfo +28 -0
- data/lib/cricinfo.rb +11 -1
- data/lib/cricinfo/game.rb +16 -9
- data/lib/cricinfo/innings.rb +2 -1
- data/lib/cricinfo/scores.rb +55 -24
- data/spec/cricinfo_scores_spec.rb +50 -10
- metadata +28 -9
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
data/README.rdoc
CHANGED
@@ -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 { |
|
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
|
|
data/bin/cricinfo
ADDED
@@ -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
|
data/lib/cricinfo.rb
CHANGED
@@ -8,6 +8,16 @@ require 'cricinfo/game'
|
|
8
8
|
require 'cricinfo/scores'
|
9
9
|
|
10
10
|
module CricInfo
|
11
|
-
VERSION = '0.0.
|
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
|
data/lib/cricinfo/game.rb
CHANGED
@@ -13,15 +13,25 @@ module CricInfo
|
|
13
13
|
|
14
14
|
include GameTypes
|
15
15
|
|
16
|
-
|
17
|
-
|
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
|
-
@
|
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,
|
34
|
-
|
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
|
|
data/lib/cricinfo/innings.rb
CHANGED
@@ -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
|
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"
|
data/lib/cricinfo/scores.rb
CHANGED
@@ -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
|
10
|
+
RE_MATCH = /matchId=.*?">(.+?):\s*(\w+)\s+v\s+(\w+)<\/a>.*?<\/tr>(.*?)<\/tr>(.*?Start time (.*?)\s*<\/b>)?/
|
10
11
|
|
11
|
-
# team1/2,
|
12
|
-
|
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*&\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.
|
38
|
-
game.
|
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 |
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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.
|
19
|
-
game.
|
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.
|
36
|
-
game.
|
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.
|
45
|
-
game.
|
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.
|
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
|
-
|
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-
|
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
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
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.
|
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).
|