boston_marathon 0.0.1
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/.gitignore +12 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +28 -0
- data/README.md +99 -0
- data/Rakefile +11 -0
- data/boston_marathon.gemspec +29 -0
- data/lib/boston_marathon/record_not_found.rb +7 -0
- data/lib/boston_marathon/result.rb +95 -0
- data/lib/boston_marathon/result_set.rb +18 -0
- data/lib/boston_marathon/version.rb +3 -0
- data/lib/boston_marathon.rb +40 -0
- data/test/helper.rb +14 -0
- data/test/test_boston_marathon.rb +97 -0
- data/test/test_result.rb +47 -0
- data/test/vcr_cassettes/bad_bib.yml +175 -0
- data/test/vcr_cassettes/bib_200.yml +152 -0
- data/test/vcr_cassettes/bib_43.yml +154 -0
- data/test/vcr_cassettes/ryan_hall.yml +156 -0
- data/test/vcr_cassettes/top_20_women.yml +1226 -0
- metadata +186 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
boston_marathon (0.0.1)
|
5
|
+
nokogiri (= 1.5.0)
|
6
|
+
rest-client (= 1.6.7)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
fakeweb (1.3.0)
|
12
|
+
mime-types (1.17.2)
|
13
|
+
nokogiri (1.5.0)
|
14
|
+
redgreen (1.2.2)
|
15
|
+
rest-client (1.6.7)
|
16
|
+
mime-types (>= 1.16)
|
17
|
+
shoulda-context (1.0.0)
|
18
|
+
vcr (1.11.3)
|
19
|
+
|
20
|
+
PLATFORMS
|
21
|
+
ruby
|
22
|
+
|
23
|
+
DEPENDENCIES
|
24
|
+
boston_marathon!
|
25
|
+
fakeweb (= 1.3.0)
|
26
|
+
redgreen (>= 1.2.2)
|
27
|
+
shoulda-context (~> 1.0.0)
|
28
|
+
vcr (= 1.11.3)
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
Boston Marathon
|
2
|
+
===============
|
3
|
+
|
4
|
+
A Ruby wrapper for race results from the [2011 Boston Marathon](http://www.baa.org/races/boston-marathon/results-commentary/results-search.aspx).
|
5
|
+
Result data is retrieved by parsing HTML documents with [Nokogiri](http://nokogiri.org/),
|
6
|
+
so this version of the gem will work as long as the format of the site doesn't change.
|
7
|
+
|
8
|
+
Install / Getting Started
|
9
|
+
-------------------------
|
10
|
+
|
11
|
+
gem install boston_marathon
|
12
|
+
|
13
|
+
Usage
|
14
|
+
-----
|
15
|
+
|
16
|
+
### Look up an athlete's result by their bib number
|
17
|
+
|
18
|
+
result = BostonMarathon.result(43)
|
19
|
+
result.name # => 'Krah, Nathan M.'
|
20
|
+
result.time # => '2:22:24'
|
21
|
+
result.pace # => '0:05:26'
|
22
|
+
result.place # => '29'
|
23
|
+
|
24
|
+
Like ActiveRecord, a RecordNotFound exception is raised when looking up a bib that has no result.
|
25
|
+
|
26
|
+
### Search the results
|
27
|
+
|
28
|
+
This method will return a maximum of 25 entries, a limit imposed by the Boston Marathon website.
|
29
|
+
To specify a smaller limit, use the VarTargetCount param.
|
30
|
+
|
31
|
+
top_20_women = BostonMarathon.results({'GenderID' => 2, 'VarTargetCount' => 20})
|
32
|
+
top_20_women.each do |result|
|
33
|
+
puts "#{result.gender_place.rjust(2)}. #{result.name}"
|
34
|
+
end
|
35
|
+
|
36
|
+
Query Params for #results
|
37
|
+
-------------------------
|
38
|
+
|
39
|
+
- BibNumber
|
40
|
+
- LastName
|
41
|
+
- FirstName
|
42
|
+
- GenderID
|
43
|
+
- City
|
44
|
+
- StateID
|
45
|
+
- CountryOfResID
|
46
|
+
- ReportingSegmentID
|
47
|
+
- QualClassID
|
48
|
+
- AwardsDivisionID
|
49
|
+
- VarTargetCount
|
50
|
+
|
51
|
+
### IDs for genders
|
52
|
+
|
53
|
+
{"1" => "M", "2" => "F"}
|
54
|
+
|
55
|
+
### IDs for reporting segments
|
56
|
+
|
57
|
+
{"1" => "Runners", "2" => "Wheelchairs", "3" => "Handcycles"}
|
58
|
+
|
59
|
+
### IDs for qualification classes
|
60
|
+
|
61
|
+
{"8" => "Handcycle", "2" => "Mobility Impaired", "4" => "Push Rim Wheelchair Class 1 (Quad)", "5" => "Push Rim Wheelchair Class 2 (Quad)", "6" => "Push Rim Wheelchair Class 3 (Open)", "7" => "Push Rim Wheelchair Class 4 (Open)", "1" => "Visually Impaired (B1, B2, B3)"}
|
62
|
+
|
63
|
+
### IDs for awards divisions
|
64
|
+
|
65
|
+
{"1" => "18-39 Age Group", "2" => "40-44 Age Group", "9" => "45-49 Age Group", "3" => "50-54 Age Group", "10" => "55-59 Age Group", "4" => "60-64 Age Group", "11" => "65-69 Age Group", "8" => "70-74 Age Group", "12" => "75-79 Age Group", "13" => "80+ Age Group"}
|
66
|
+
|
67
|
+
### IDs for states
|
68
|
+
|
69
|
+
{"5" => "Alabama", "4" => "Alaska", "64" => "Alberta", "8" => "American Samoa", "9" => "Arizona", "7" => "Arkansas", "2" => "Armed Forces Americas", "3" => "Armed Forces Europe", "6" => "Armed Forces Pacific", "65" => "British Columbia", "10" => "California", "11" => "Colorado", "12" => "Connecticut", "14" => "Delaware", "13" => "District Of Columbia", "16" => "Federated States of Micronesia", "15" => "Florida", "17" => "Georgia", "18" => "Guam", "19" => "Hawaii", "21" => "Idaho", "22" => "Illinois", "23" => "Indiana", "20" => "Iowa", "24" => "Kansas", "25" => "Kentucky", "26" => "Louisiana", "29" => "Maine", "67" => "Manitoba", "30" => "Marshall Island", "28" => "Maryland", "27" => "Massachusetts", "31" => "Michigan", "32" => "Minnesota", "35" => "Mississippi", "33" => "Missouri", "36" => "Montana", "39" => "Nebraska", "43" => "Nevada", "68" => "New Brunswick", "40" => "New Hampshire", "41" => "New Jersey", "42" => "New Mexico", "44" => "New York", "66" => "Newfoundland and Labrador", "37" => "North Carolina", "38" => "North Dakota", "34" => "Northern Mariana Islands", "71" => "Northwest Territories", "70" => "Nova Scotia", "77" => "Nunavut", "45" => "Ohio", "46" => "Oklahoma", "72" => "Ontario", "47" => "Oregon", "50" => "Palau", "48" => "Pennsylvania", "73" => "Prince Edward Island", "49" => "Puerto Rico", "74" => "Quebec", "51" => "Rhode Island", "75" => "Saskatchewan", "52" => "South Carolina", "53" => "South Dakota", "54" => "Tennessee", "55" => "Texas", "56" => "Utah", "59" => "Vermont", "58" => "Virgin Islands", "57" => "Virginia", "60" => "Washington", "62" => "West Virginia", "61" => "Wisconsin", "63" => "Wyoming", "76" => "Yukon"}
|
70
|
+
|
71
|
+
### IDs for countries
|
72
|
+
|
73
|
+
{"196"=>"Venezuela", "168"=>"Saint Lucia", "54"=>"Djibouti", "25"=>"Belize", "82"=>"Hong Kong", "197"=>"Vietnam", "169"=>"Sao Tome and Principe", "26"=>"Burkina Faso", "110"=>"Luxembourg", "83"=>"Honduras", "55"=>"Dominica", "27"=>"Belarus", "84"=>"Hungary", "140"=>"Oman", "56"=>"Dominican Republic", "28"=>"Bolivia", "112"=>"Madagascar", "85"=>"Indonesia", "141"=>"Pakistan", "113"=>"Morocco", "29"=>"Botswana", "86"=>"India", "57"=>"Ecuador", "170"=>"Saint Vincent and the Grenadines", "142"=>"Palestine", "114"=>"Malaysia", "87"=>"Ireland", "58"=>"Egypt", "171"=>"Sudan", "143"=>"Panama", "115"=>"Malawi", "59"=>"El Salvador", "172"=>"Switzerland", "144"=>"Paraguay", "116"=>"Mexico", "30"=>"Brazil", "88"=>"Islamic Republic of Iran", "200"=>"Yugoslavia", "173"=>"Suriname", "145"=>"Peru", "117"=>"Mongolia", "31"=>"Brunei Darussalam", "89"=>"Iraq", "60"=>"Spain", "174"=>"Slovakia", "146"=>"Philippines", "118"=>"Maldives", "32"=>"Bulgaria", "201"=>"Congo, The Democratic Republic of the", "202"=>"Zambia", "175"=>"Sweden", "147"=>"Poland", "119"=>"Mali", "61"=>"Estonia", "203"=>"Zimbabwe", "176"=>"Swaziland", "148"=>"Portugal", "90"=>"Iceland", "62"=>"Ethiopia", "177"=>"Syrian Arab Republic", "34"=>"British Virgin Islands", "91"=>"Israel", "149"=>"Korea, Democratic People's Republic of", "63"=>"Fiji", "204"=>"Burundi", "178"=>"Tanzania, United Republic of", "35"=>"Central African Republic", "64"=>"Finland", "205"=>"Bosnia and Herzegovina", "179"=>"Thailand", "120"=>"Malta", "2"=>"Afghanistan", "93"=>"Italy", "65"=>"France", "206"=>"Eritrea", "36"=>"Canada", "3"=>"Netherlands Antilles", "94"=>"Jamaica", "37"=>"Cayman Islands", "150"=>"Yemen", "122"=>"Moldova, Republic of", "4"=>"Albania", "95"=>"Jordan", "66"=>"Gabon", "208"=>"Lao People's Democratic Republic", "38"=>"Congo", "209"=>"Slovenia", "151"=>"Qatar", "123"=>"Monaco", "5"=>"Algeria", "96"=>"Japan", "67"=>"Gambia", "39"=>"Chad", "68"=>"United Kingdom", "180"=>"Tajikistan", "124"=>"Mozambique", "97"=>"Kenya", "10"=>"Antigua and Barbuda", "181"=>"Turkmenistan", "153"=>"Romania", "125"=>"Mauritius", "7"=>"Andorra", "98"=>"Kyrgyzstan", "69"=>"Guinea-Bissau", "154"=>"South Africa", "11"=>"Argentina", "40"=>"Chile", "8"=>"Angola", "183"=>"Togo", "155"=>"Russian Federation", "12"=>"Armenia", "210"=>"Macedonia, The Former Yugoslav Republic of", "127"=>"Mauritania", "41"=>"China", "99"=>"Cambodia", "184"=>"Tonga", "211"=>"Taiwan", "156"=>"Rwanda", "128"=>"Myanmar", "13"=>"Aruba", "70"=>"Georgia", "42"=>"Cote d'Ivoire (Ivory Coast)", "212"=>"Serbia and Montenegro", "157"=>"Samoa", "129"=>"Namibia", "14"=>"Australia", "71"=>"Equatorial Guinea", "43"=>"Cook Islands", "186"=>"Trinidad and Tobago", "158"=>"Saudi Arabia", "72"=>"Germany", "15"=>"Austria", "187"=>"Tunisia", "159"=>"Senegal", "100"=>"Korea, Republic of", "73"=>"Ghana", "44"=>"Cameroon", "16"=>"Azerbaijan", "188"=>"Turkey", "101"=>"Kuwait", "45"=>"Colombia", "17"=>"Bahamas", "189"=>"United Arab Emirates", "130"=>"Nauru", "75"=>"Greece", "46"=>"Comoros", "18"=>"Bangladesh", "102"=>"Kazakhstan", "131"=>"Nicaragua", "76"=>"Grenada", "47"=>"Costa Rica", "19"=>"Barbados", "103"=>"Latvia", "160"=>"Seychelles", "132"=>"Netherlands", "48"=>"Croatia", "104"=>"Libyan Arab Jamahiriya", "161"=>"Singapore", "133"=>"Nepal", "77"=>"Guatemala", "49"=>"Cuba", "105"=>"Liberia", "190"=>"Uganda", "162"=>"Sierra Leone", "134"=>"Nigeria", "106"=>"Lesotho", "20"=>"Belgium", "78"=>"Guinea", "191"=>"Ukraine", "163"=>"San Marino", "135"=>"Papua New Guinea", "107"=>"Lebanon", "21"=>"Benin", "192"=>"Uruguay", "164"=>"Solomon Islands", "136"=>"Niger", "50"=>"Cape Verde", "108"=>"Liechtenstein", "193"=>"United States of America", "165"=>"Somalia", "51"=>"Cyprus", "109"=>"Lithuania", "22"=>"Bermuda", "194"=>"Uzbekistan", "166"=>"Sri Lanka", "138"=>"Norway", "52"=>"Czech Republic", "23"=>"Bahrain", "80"=>"Guyana", "195"=>"Vanatu", "167"=>"Saint Kitts and Nevis", "139"=>"New Zealand", "53"=>"Denmark", "24"=>"Bhutan", "81"=>"Haiti"}
|
74
|
+
|
75
|
+
License
|
76
|
+
-------
|
77
|
+
|
78
|
+
(The MIT License)
|
79
|
+
|
80
|
+
Copyright (c) 2011 John B. Hall
|
81
|
+
|
82
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
83
|
+
a copy of this software and associated documentation files (the
|
84
|
+
'Software'), to deal in the Software without restriction, including
|
85
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
86
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
87
|
+
permit persons to whom the Software is furnished to do so, subject to
|
88
|
+
the following conditions:
|
89
|
+
|
90
|
+
The above copyright notice and this permission notice shall be
|
91
|
+
included in all copies or substantial portions of the Software.
|
92
|
+
|
93
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
94
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
95
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
96
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
97
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
98
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
99
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "boston_marathon/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'boston_marathon'
|
7
|
+
s.version = BostonMarathon::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.date = '2011-11-25'
|
10
|
+
s.summary = "Ruby wrapper for race results from the 2011 Boston Marathon"
|
11
|
+
s.authors = ["John B. Hall"]
|
12
|
+
s.email = 'johnbrianhall@gmail.com'
|
13
|
+
|
14
|
+
s.add_runtime_dependency 'rest-client', '= 1.6.7'
|
15
|
+
s.add_runtime_dependency 'nokogiri', '= 1.5.0'
|
16
|
+
|
17
|
+
s.add_development_dependency 'redgreen', ">= 1.2.2"
|
18
|
+
s.add_development_dependency 'vcr', '1.11.3'
|
19
|
+
s.add_development_dependency 'fakeweb', '1.3.0'
|
20
|
+
s.add_development_dependency 'shoulda-context', '~> 1.0.0'
|
21
|
+
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
s.files = `git ls-files`.split("\n")
|
25
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
26
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
27
|
+
s.require_paths = ["lib"]
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module BostonMarathon
|
2
|
+
|
3
|
+
class Result
|
4
|
+
|
5
|
+
ATTR_TRANSLATE = {
|
6
|
+
'm/f' => 'gender',
|
7
|
+
'st' => 'state',
|
8
|
+
'ctry' => 'country',
|
9
|
+
'ctz' => 'citizenship',
|
10
|
+
'proj. time' => 'projected_time',
|
11
|
+
'offl. time' => 'time',
|
12
|
+
'overall' => 'place',
|
13
|
+
'gender' => 'gender_place',
|
14
|
+
'division' => 'division_place'
|
15
|
+
}
|
16
|
+
|
17
|
+
attr_reader :attrs
|
18
|
+
|
19
|
+
def initialize(header, infogrid)
|
20
|
+
@header = header # athlete bib, name, age, gender, city, state, country
|
21
|
+
@infogrid = infogrid # splits and finish info (pace, time, place, gender_place, division_place)
|
22
|
+
set_attrs
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method, *args)
|
26
|
+
m = method.to_s.downcase
|
27
|
+
if @attrs.has_key? m
|
28
|
+
@attrs[m]
|
29
|
+
else
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# ATHLETE
|
37
|
+
|
38
|
+
def athlete_keys
|
39
|
+
['Bib', 'Name', 'Age', 'M/F', 'City', 'St', 'Ctry', 'Ctz', '']
|
40
|
+
end
|
41
|
+
|
42
|
+
def athlete_values
|
43
|
+
cleanse(@header.css('td'))
|
44
|
+
end
|
45
|
+
|
46
|
+
# RESULT (which contains splits and finish info)
|
47
|
+
|
48
|
+
def results_rows
|
49
|
+
@results_rows ||= @infogrid.css('tr')
|
50
|
+
end
|
51
|
+
|
52
|
+
# SPLITS
|
53
|
+
|
54
|
+
def split_keys
|
55
|
+
cleanse(results_rows[0].css('th')[1..-1])
|
56
|
+
end
|
57
|
+
|
58
|
+
def split_values
|
59
|
+
cleanse(results_rows[1].css('td'))
|
60
|
+
end
|
61
|
+
|
62
|
+
# FINISH INFO
|
63
|
+
|
64
|
+
def finish_info_keys
|
65
|
+
cleanse(results_rows[2].css('th')[1..-1])
|
66
|
+
end
|
67
|
+
|
68
|
+
def finish_info_values
|
69
|
+
cleanse(results_rows[3].css('td'))
|
70
|
+
end
|
71
|
+
|
72
|
+
def set_attrs
|
73
|
+
athlete = hashify(athlete_keys, athlete_values)
|
74
|
+
splits = {'splits' => hashify(split_keys, split_values)}
|
75
|
+
finish_info = hashify(finish_info_keys, finish_info_values)
|
76
|
+
@attrs = athlete.merge(splits).merge(finish_info)
|
77
|
+
end
|
78
|
+
|
79
|
+
# hashify does not belong on the result model. Move it later.
|
80
|
+
# usage: hashify(["dog", "cat"], ["woof", "meow"]) # => {"cat"=>"meow", "dog"=>"woof"}
|
81
|
+
def hashify(keys, values)
|
82
|
+
keys = keys.map(&:downcase).map{ |k| ATTR_TRANSLATE.has_key?(k) ? ATTR_TRANSLATE[k] : k }
|
83
|
+
arr_of_arrs = keys.zip(values).delete_if { |arr| arr[0] == "" }
|
84
|
+
Hash[arr_of_arrs]
|
85
|
+
end
|
86
|
+
|
87
|
+
# cleanse does not belong on the result model. Move it later.
|
88
|
+
# remove whitespaces and instances of
|
89
|
+
def cleanse(arr)
|
90
|
+
arr.map{|cell| cell.inner_text.gsub(/\302\240/, ' ').strip}
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module BostonMarathon
|
2
|
+
|
3
|
+
class ResultSet < Array
|
4
|
+
|
5
|
+
def initialize(response)
|
6
|
+
noko = Nokogiri::HTML(response.body)
|
7
|
+
results = []
|
8
|
+
headers = noko.css('.tr_header')
|
9
|
+
infogrids = noko.css('.table_infogrid')
|
10
|
+
unless headers.empty? || infogrids.empty?
|
11
|
+
headers.zip(infogrids).map { |arr| results << Result.new(arr[0], arr[1]) }
|
12
|
+
end
|
13
|
+
replace(results)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'rest_client'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
require 'boston_marathon/record_not_found'
|
7
|
+
require 'boston_marathon/result_set'
|
8
|
+
require 'boston_marathon/result'
|
9
|
+
|
10
|
+
module BostonMarathon
|
11
|
+
|
12
|
+
BASE_URL = "http://registration.baa.org/2011/cf/Public/iframe_ResultsSearch.cfm?mode=results"
|
13
|
+
RESULTS_PER_PAGE = 25 # up to 25 results can be retrieved at a time
|
14
|
+
RACE_CAP = 30000 # an arbitrary number that's larger than the number of race participants
|
15
|
+
|
16
|
+
class << self
|
17
|
+
|
18
|
+
# returns the result for a specific bib number
|
19
|
+
def result(bib)
|
20
|
+
result_set = fetch({'BibNumber' => bib})
|
21
|
+
raise BostonMarathon::RecordNotFound if result_set.empty?
|
22
|
+
result_set[0]
|
23
|
+
end
|
24
|
+
|
25
|
+
# returns a max of RESULTS_PER_PAGE results.
|
26
|
+
# see README for list of query params
|
27
|
+
def results(params)
|
28
|
+
fetch({'VarTargetCount' => RACE_CAP}.merge params)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def fetch(params={})
|
34
|
+
response = RestClient.post BASE_URL, params
|
35
|
+
BostonMarathon::ResultSet.new(response)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# I know it's bad to require rubygems, but I haven't yet figured out how to get around it
|
2
|
+
require 'rubygems'
|
3
|
+
require 'test/unit'
|
4
|
+
require 'redgreen'
|
5
|
+
require 'vcr'
|
6
|
+
require 'fakeweb'
|
7
|
+
require 'shoulda-context'
|
8
|
+
require 'boston_marathon'
|
9
|
+
|
10
|
+
VCR.config do |c|
|
11
|
+
c.cassette_library_dir = 'test/vcr_cassettes'
|
12
|
+
c.stub_with :fakeweb
|
13
|
+
c.default_cassette_options = { :record => :once }
|
14
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
class TestBostonMarathon < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "when looking up a result by an INVALID bib number" do
|
6
|
+
|
7
|
+
should "raise a RecordNotFound exception" do
|
8
|
+
assert_raise BostonMarathon::RecordNotFound do
|
9
|
+
VCR.use_cassette('bad_bib') do
|
10
|
+
@result = BostonMarathon.result('a')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when looking up a result by a VALID bib number" do
|
18
|
+
|
19
|
+
setup do
|
20
|
+
VCR.use_cassette('bib_43') do
|
21
|
+
@result = BostonMarathon.result(43)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
should "have the correct athlete attributes" do
|
26
|
+
expected = ['43', 'Krah, Nathan M.', '25', 'M', 'Boston', 'MA', 'USA']
|
27
|
+
tested = [@result.bib, @result.name, @result.age, @result.gender, @result.city, @result.state, @result.country]
|
28
|
+
assert_equal expected, tested
|
29
|
+
end
|
30
|
+
|
31
|
+
should "have the correct splits" do
|
32
|
+
expected = {
|
33
|
+
'5k' => '0:16:40',
|
34
|
+
'10k' => '0:33:24',
|
35
|
+
'15k' => '0:50:03',
|
36
|
+
'20k' => '1:06:46',
|
37
|
+
'half' => '1:10:25',
|
38
|
+
'25k' => '1:23:42',
|
39
|
+
'30k' => '1:40:39',
|
40
|
+
'35k' => '1:57:52',
|
41
|
+
'40k' => '2:14:53'
|
42
|
+
}
|
43
|
+
assert_equal expected, @result.splits
|
44
|
+
end
|
45
|
+
|
46
|
+
should "have the correct finish info" do
|
47
|
+
expected = ['0:05:26', '', '2:22:24', '29', '29', '25']
|
48
|
+
tested = [@result.pace, @result.projected_time, @result.time, @result.place, @result.gender_place, @result.division_place]
|
49
|
+
assert_equal expected, tested
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when searching for" do
|
55
|
+
|
56
|
+
context "the top 20 women" do
|
57
|
+
|
58
|
+
setup do
|
59
|
+
VCR.use_cassette('top_20_women') do
|
60
|
+
@results = BostonMarathon.results({'GenderID' => 2, 'VarTargetCount' => 20})
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
should "return the results of the 20 fastest female runners" do
|
65
|
+
assert_equal 20, @results.length
|
66
|
+
assert_equal ["F"], @results.map(&:gender).uniq
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
context "someone matching very specific attributes" do
|
72
|
+
|
73
|
+
setup do
|
74
|
+
VCR.use_cassette('ryan_hall') do
|
75
|
+
@results = BostonMarathon.results({
|
76
|
+
'BibNumber' => 3,
|
77
|
+
'LastName' => 'Hall',
|
78
|
+
'FirstName' => 'Ryan',
|
79
|
+
'ReportingSegmentId' => 1,
|
80
|
+
'GenderID' => 1,
|
81
|
+
'City' => 'Mammoth Lakes',
|
82
|
+
'StateID' => '10',
|
83
|
+
'CountryOfResID' => 193
|
84
|
+
})
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
should "return the athlete we're looking for" do
|
89
|
+
assert_equal 1, @results.length
|
90
|
+
assert_equal "Hall, Ryan", @results[0].name
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|