boston_marathon 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ *.gem
2
+ *.rbc
3
+ .DS_Store
4
+ .bundle
5
+ .rvmrc
6
+ .yardoc
7
+ Gemfile.lock
8
+ coverage/*
9
+ doc/*
10
+ log/*
11
+ pkg/*
12
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # gem dependencies are specified in boston_marathon.gemspec
4
+ gemspec
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,11 @@
1
+ require 'bundler'
2
+ include Rake::DSL
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require 'rake/testtask'
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'test'
8
+ end
9
+
10
+ desc "Run tests"
11
+ task :default => :test
@@ -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,7 @@
1
+ module BostonMarathon
2
+
3
+ class RecordNotFound < Exception
4
+
5
+ end
6
+
7
+ 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 &nbsp;
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,3 @@
1
+ module BostonMarathon
2
+ VERSION = '0.0.1'
3
+ 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