football_api 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +31 -0
  9. data/Rakefile +2 -0
  10. data/football_api-0.0.1.gem +0 -0
  11. data/football_api-0.0.2.gem +0 -0
  12. data/football_api-0.0.3.gem +0 -0
  13. data/football_api.gemspec +36 -0
  14. data/lib/football_api/base_request.rb +75 -0
  15. data/lib/football_api/card.rb +19 -0
  16. data/lib/football_api/comment.rb +13 -0
  17. data/lib/football_api/commentary.rb +79 -0
  18. data/lib/football_api/competition.rb +54 -0
  19. data/lib/football_api/errors.rb +13 -0
  20. data/lib/football_api/event.rb +19 -0
  21. data/lib/football_api/fixture.rb +44 -0
  22. data/lib/football_api/goal.rb +17 -0
  23. data/lib/football_api/match.rb +59 -0
  24. data/lib/football_api/match_bench.rb +27 -0
  25. data/lib/football_api/match_info.rb +14 -0
  26. data/lib/football_api/match_stats.rb +29 -0
  27. data/lib/football_api/match_substitutions.rb +27 -0
  28. data/lib/football_api/match_summary.rb +39 -0
  29. data/lib/football_api/match_team.rb +22 -0
  30. data/lib/football_api/mixins/requestable.rb +19 -0
  31. data/lib/football_api/mixins/symbolizer.rb +59 -0
  32. data/lib/football_api/player.rb +12 -0
  33. data/lib/football_api/standing.rb +104 -0
  34. data/lib/football_api/version.rb +3 -0
  35. data/lib/football_api.rb +32 -0
  36. data/spec/commentary_spec.rb +112 -0
  37. data/spec/competition_spec.rb +27 -0
  38. data/spec/fixture_spec.rb +90 -0
  39. data/spec/helpers/json_helper.rb +41 -0
  40. data/spec/json/commentaries.json +1967 -0
  41. data/spec/json/competitions.json +23 -0
  42. data/spec/json/fixtures.json +4559 -0
  43. data/spec/json/matches.json +17 -0
  44. data/spec/json/standings.json +719 -0
  45. data/spec/match_spec.rb +25 -0
  46. data/spec/spec_helper.rb +115 -0
  47. data/spec/standing_spec.rb +37 -0
  48. metadata +346 -0
@@ -0,0 +1,39 @@
1
+ module FootballApi
2
+ class MatchSummary
3
+
4
+ attr_accessor :id, :local_team_goals, :local_team_yellowcards, :local_team_redcards,
5
+ :visitor_team_goals, :visitor_team_yellowcards, :visitor_team_redcards
6
+
7
+ # For the teams goals, the api returns an empty array
8
+ # when there are no goals.
9
+ # Goals is an hash if there are goals to present.
10
+ def initialize(hash = {})
11
+ @id = hash[:id]
12
+
13
+ @local_team_goals = parse_team_goals(hash[:localteam])
14
+ @local_team_yellowcards = parse_cards(hash[:localteam][:yellowcards], :yellow)
15
+ @local_team_redcards = parse_cards(hash[:localteam][:redcards], :red)
16
+
17
+ @visitor_team_goals = parse_team_goals(hash[:visitorteam])
18
+ @visitor_team_yellowcards = parse_cards(hash[:visitorteam][:yellowcards], :yellow)
19
+ @visitor_team_redcards = parse_cards(hash[:visitorteam][:redcards], :red)
20
+ end
21
+
22
+ def parse_team_goals(hash = {})
23
+ return [] if !hash[:goals] || hash[:goals].is_a?(Array) || !hash[:goals][:player]
24
+
25
+ Array(hash[:goals][:player]).map do |player|
26
+ FootballApi::Goal.new(player.merge(score: player.to_s.to_i))
27
+ end
28
+ end
29
+
30
+ # If the cards struct has no members, its type is an array, so we must do
31
+ # the type validation before sending it to new.
32
+ # Like with the goals, the only way to iterpolate through all the records
33
+ # is with the hash key.
34
+ def parse_cards(hash, type)
35
+ return [] if !hash.is_a?(Hash) || !hash[:player]
36
+ Array(hash[:player]).map { |card| FootballApi::Card.new(card.merge(type: type)) }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,22 @@
1
+ module FootballApi
2
+ class MatchTeam
3
+
4
+ attr_accessor :id, :players
5
+
6
+ def initialize(hash = {}, key)
7
+ @id = hash[:comm_match_id]
8
+ @players = parse_players(hash, key)
9
+ end
10
+
11
+ def parse_players(hash = {}, key)
12
+ players = []
13
+ Array(hash[:comm_match_teams][key][:player]).each do |player|
14
+ players << FootballApi::Player.new(player)
15
+ end
16
+ Array(hash[:comm_match_subs][key][:player]).each do |player|
17
+ players << FootballApi::Player.new(player)
18
+ end
19
+ players
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ module FootballApi
2
+ module Requestable
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ attr_accessor :action, :json_id, :params_method
9
+
10
+ ##
11
+ # Options can be any of the class attributes
12
+ def api_options(options = {})
13
+ self.action = options.delete(:action).to_s if options[:action]
14
+ self.json_id = options.delete(:json_key) if options[:json_key]
15
+ self.params_method = options.delete(:action_params)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,59 @@
1
+ module FootballApi
2
+ module Symbolizer
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ HASH_OR_ARRAY_KEYS = %i(player substitution comment)
8
+
9
+ module ClassMethods
10
+ # Custom deep symbolize of an hash
11
+ # So we can override the mess of some footbal-api arrays
12
+ def custom_deep_symbolic_hash(hash)
13
+ {}.tap do |h|
14
+ Hash(hash).each do |key, value|
15
+ key = symbolyze_key(key)
16
+ h[key] = map_value(key, value)
17
+ end
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ # Convert key to symbol
24
+ def symbolyze_key(key)
25
+ key.to_sym rescue key
26
+ end
27
+
28
+ # Recursive way of checking all hash
29
+ def map_value(key, value)
30
+ case value
31
+ when Array
32
+ value.map { |v| map_value(nil, v) }
33
+ when Hash
34
+ return custom_deep_symbolic_hash(value) unless is_a_custom_key?(key)
35
+ map_value(nil, array_from_mess(value))
36
+ else
37
+ value
38
+ end
39
+ end
40
+
41
+ def is_a_custom_key?(key)
42
+ HASH_OR_ARRAY_KEYS.include?(key)
43
+ end
44
+
45
+ # Since the custom keys come as an hash like: => { '1': { ... }, '2': { ... } }
46
+ # OR!
47
+ # A simple object from the root
48
+ # We need to unify the return value and return a simple array of objects
49
+ # Ugly? yup! as f*ck!
50
+ def array_from_mess(hash)
51
+ return key_contains_object?(hash.keys.first) ? [hash] : hash.values
52
+ end
53
+
54
+ def key_contains_object?(key)
55
+ (key.to_s =~ /[0-9]/) == nil
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,12 @@
1
+ module FootballApi
2
+ class Player
3
+ attr_accessor :number, :name, :pos, :id
4
+
5
+ def initialize(hash = {})
6
+ @number = hash[:number]
7
+ @name = hash[:name]
8
+ @pos = hash[:pos]
9
+ @id = hash[:id]
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,104 @@
1
+ module FootballApi
2
+ class Standing < FootballApi::BaseRequest
3
+ include FootballApi::Requestable
4
+
5
+ api_options action: :standings, action_params: :standing_params, json_key: :teams
6
+
7
+ class << self
8
+ attr_accessor :competition_id
9
+
10
+ def all_from_competition(competition)
11
+ self.competition_id = competition.is_a?(Competition) ? competition.id : competition
12
+
13
+ Array(response).map{ |standing| new(standing) }
14
+ end
15
+
16
+ def standing_params
17
+ { comp_id: self.competition_id }
18
+ end
19
+ end
20
+
21
+ # Response sample :
22
+ # [
23
+ # {
24
+ # "stand_id"=>"12049092",
25
+ # "stand_competition_id"=>"1204",
26
+ # "stand_season"=>"2014/2015",
27
+ # "stand_round"=>"22",
28
+ # "stand_stage_id"=>"12041081",
29
+ # "stand_group"=>"",
30
+ # "stand_country"=>"England",
31
+ # "stand_team_id"=>"9092",
32
+ # "stand_team_name"=>"Chelsea",
33
+ # "stand_status"=>"same",
34
+ # "stand_recent_form"=>"WWLDW",
35
+ # "stand_position"=>"1",
36
+ # "stand_overall_gp"=>"22",
37
+ # "stand_overall_w"=>"16",
38
+ # "stand_overall_d"=>"4",
39
+ # "stand_overall_l"=>"2",
40
+ # "stand_overall_gs"=>"51",
41
+ # "stand_overall_ga"=>"19",
42
+ # "stand_home_gp"=>"10",
43
+ # "stand_home_w"=>"10",
44
+ # "stand_home_d"=>"0",
45
+ # "stand_home_l"=>"0",
46
+ # "stand_home_gs"=>"24",
47
+ # "stand_home_ga"=>"3",
48
+ # "stand_away_gp"=>"12",
49
+ # "stand_away_w"=>"10",
50
+ # "stand_away_d"=>"0",
51
+ # "stand_away_l"=>"0",
52
+ # "stand_away_gs"=>"24",
53
+ # "stand_away_ga"=>"3",
54
+ # "stand_gd"=>"32",
55
+ # "stand_points"=>"52",
56
+ # "stand_desc"=>"Promotion - Champions League (Group Stage)"
57
+ # }, ...
58
+ # ]
59
+
60
+ attr_accessor :stand_id, :stand_competition_id, :stand_season, :stand_round, :stand_stage_id,
61
+ :stand_group, :stand_country, :stand_team_id, :stand_team_name, :stand_status,
62
+ :stand_recent_form, :stand_position, :stand_overall_gp, :stand_overall_w,
63
+ :stand_overall_d, :stand_overall_l, :stand_overall_gs, :stand_overall_ga,
64
+ :stand_home_gp, :stand_home_w, :stand_home_d, :stand_home_l, :stand_home_gs,
65
+ :stand_home_ga, :stand_away_gp, :stand_away_w, :stand_away_d, :stand_away_l,
66
+ :stand_away_gs, :stand_away_ga, :stand_gd, :stand_points, :stand_desc
67
+
68
+ def initialize(hash = {})
69
+ @stand_id = hash[:stand_id]
70
+ @stand_competition_id = hash[:stand_competition_id]
71
+ @stand_season = hash[:stand_season]
72
+ @stand_round = hash[:stand_round]
73
+ @stand_stage_id = hash[:stand_stage_id]
74
+ @stand_group = hash[:stand_group]
75
+ @stand_country = hash[:stand_country]
76
+ @stand_team_id = hash[:stand_team_id]
77
+ @stand_team_name = hash[:stand_team_name]
78
+ @stand_status = hash[:stand_status]
79
+ @stand_recent_form = hash[:stand_recent_form]
80
+ @stand_position = hash[:stand_position]
81
+ @stand_overall_gp = hash[:stand_overall_gp]
82
+ @stand_overall_w = hash[:stand_overall_w]
83
+ @stand_overall_d = hash[:stand_overall_d]
84
+ @stand_overall_l = hash[:stand_overall_l]
85
+ @stand_overall_gs = hash[:stand_overall_gs]
86
+ @stand_overall_ga = hash[:stand_overall_ga]
87
+ @stand_home_gp = hash[:stand_home_gp]
88
+ @stand_home_w = hash[:stand_home_w]
89
+ @stand_home_d = hash[:stand_home_d]
90
+ @stand_home_l = hash[:stand_home_l]
91
+ @stand_home_gs = hash[:stand_home_gs]
92
+ @stand_home_ga = hash[:stand_home_ga]
93
+ @stand_away_gp = hash[:stand_away_gp]
94
+ @stand_away_w = hash[:stand_away_w]
95
+ @stand_away_d = hash[:stand_away_d]
96
+ @stand_away_l = hash[:stand_away_l]
97
+ @stand_away_gs = hash[:stand_away_gs]
98
+ @stand_away_ga = hash[:stand_away_ga]
99
+ @stand_gd = hash[:stand_gd]
100
+ @stand_points = hash[:stand_points]
101
+ @stand_desc = hash[:stand_desc]
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,3 @@
1
+ module FootballApi
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,32 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext/object'
3
+ require 'active_support/core_ext/hash'
4
+ require 'active_support/core_ext/numeric'
5
+ require 'active_support/core_ext/string'
6
+ require 'active_support/core_ext/time'
7
+ require 'active_support/time_with_zone'
8
+ require 'httparty'
9
+ require 'football_api/mixins/requestable'
10
+ require 'football_api/mixins/symbolizer'
11
+ require 'football_api/base_request'
12
+ require 'football_api/card'
13
+ require 'football_api/comment'
14
+ require 'football_api/commentary'
15
+ require 'football_api/competition'
16
+ require 'football_api/errors'
17
+ require 'football_api/event'
18
+ require 'football_api/fixture'
19
+ require 'football_api/goal'
20
+ require 'football_api/match'
21
+ require 'football_api/match_info'
22
+ require 'football_api/match_stats'
23
+ require 'football_api/match_summary'
24
+ require 'football_api/match_team'
25
+ require 'football_api/player'
26
+ require 'football_api/standing'
27
+ require 'football_api/match_bench'
28
+ require 'football_api/match_substitutions'
29
+ require 'football_api/version'
30
+
31
+ module FootballApi
32
+ end
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe FootballApi::Commentary do
4
+ let(:match_id) { 1788007 }
5
+ let(:static_id) { 1755579 }
6
+ let(:default) { JSONHelper::Commentaries.get(:default) }
7
+ let(:uri) {
8
+ "#{@base_url}/api/?APIKey=#{@api_key}&Action=commentaries&match_id=#{match_id}"
9
+ }
10
+
11
+ before(:each) do
12
+ stub_request(:get, uri)
13
+ .with(headers: @headers)
14
+ .to_return(status: 200, body: default.to_json)
15
+ end
16
+
17
+ let(:request_response) { FootballApi::Commentary.all_from_match(match_id) }
18
+
19
+ describe '.all_from_match' do
20
+ it 'sets match id' do
21
+ # doing a :static_id validation, this value must be set before request
22
+ # we can't request a match that we dont already have some information
23
+ # like :match_id and :match_static_id
24
+
25
+ expect(request_response).not_to be_nil
26
+ expect(request_response.static_id.to_i).to eq(static_id)
27
+ end
28
+
29
+ it 'sets all match summary cards' do
30
+ summary = request_response.match_summary
31
+
32
+ expect(summary).not_to be_nil
33
+ expect(summary.local_team_yellowcards.size).to eq(2)
34
+ expect(summary.local_team_redcards.size).to eq(0)
35
+ expect(summary.visitor_team_yellowcards.size).to eq(4)
36
+ expect(summary.visitor_team_redcards.size).to eq(0)
37
+ end
38
+
39
+ it 'sets all match summary goals' do
40
+ summary = request_response.match_summary
41
+
42
+ expect(summary).not_to be_nil
43
+ expect(summary.local_team_goals.size).to eq(1)
44
+ expect(summary.visitor_team_goals.size).to eq(2)
45
+ end
46
+
47
+ it 'sets local team and players' do
48
+ local_team = request_response.local_match_team
49
+
50
+ expect(local_team).not_to be_nil
51
+ expect(local_team.players.size).to eq(18)
52
+ expect(local_team.id).to eq(request_response.match_id)
53
+ end
54
+
55
+ it 'sets visitor team and players' do
56
+ visitor_team = request_response.visitor_match_team
57
+
58
+ expect(visitor_team).not_to be_nil
59
+ expect(visitor_team.players.size).to eq(18)
60
+ expect(visitor_team.id).to eq(request_response.match_id)
61
+ end
62
+
63
+ it 'sets match bench' do
64
+ match_bench = request_response.match_bench
65
+
66
+ expect(match_bench).not_to be_nil
67
+ expect(match_bench.match_id).to eq(request_response.match_id)
68
+ end
69
+
70
+ it 'sets local team bench' do
71
+ match_bench = request_response.match_bench
72
+
73
+ expect(match_bench.local_team).not_to be_nil
74
+ expect(match_bench.local_team.players.size).to eq(7)
75
+ end
76
+
77
+ it 'sets visitor team bench' do
78
+ match_bench = request_response.match_bench
79
+
80
+ expect(match_bench.visitor_team).not_to be_nil
81
+ expect(match_bench.visitor_team.players.size).to eq(7)
82
+ end
83
+
84
+ it 'sets match substitutions' do
85
+ match_substitutions = request_response.match_substitutions
86
+
87
+ expect(match_substitutions).not_to be_nil
88
+ expect(match_substitutions.match_id).to eq(request_response.match_substitutions.match_id)
89
+ end
90
+
91
+ it 'sets local team substitutions' do
92
+ match_substitutions = request_response.match_substitutions
93
+
94
+ expect(match_substitutions.local_team).not_to be_nil
95
+ expect(match_substitutions.local_team.size).to be(3)
96
+ end
97
+
98
+ it 'sets visitor team substitutions' do
99
+ match_substitutions = request_response.match_substitutions
100
+
101
+ expect(match_substitutions.visitor_team).not_to be_nil
102
+ expect(match_substitutions.visitor_team.size).to be(3)
103
+ end
104
+
105
+ it 'sets commentaries' do
106
+ commentaries = request_response.commentaries
107
+
108
+ expect(commentaries).not_to be_nil
109
+ expect(commentaries.size).to eq(111)
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe FootballApi::Competition do
4
+ let(:response) { JSONHelper::Competitions.get(:all) }
5
+ let(:uri) { "#{@base_url}/api/?APIKey=#{@api_key}&Action=competitions" }
6
+
7
+ before(:each) do
8
+ stub_request(:get, uri)
9
+ .with(headers: @headers)
10
+ .to_return(status: 200, body: response.to_json)
11
+ end
12
+ let(:request_response) { FootballApi::Competition.all }
13
+
14
+ describe '.all' do
15
+ it 'not_fails' do
16
+ expect(request_response).not_to be_nil
17
+ expect(request_response.size).to eq(1)
18
+ end
19
+
20
+ it 'has_competition' do
21
+ competition = request_response.first
22
+
23
+ expect(competition).not_to be_nil
24
+ expect(competition.id).not_to be_nil
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe FootballApi::Fixture do
4
+ let(:competition_id) { 1204 }
5
+
6
+ describe '.where from_to_date ' do
7
+ let(:response) { JSONHelper::Fixtures.get(:from_to_date) }
8
+
9
+ let(:from_date) { '01.01.2015' }
10
+ let(:to_date) { '01.02.2015' }
11
+ let(:from_to_parameters) {
12
+ { :comp_id => competition_id, :from_date => from_date, :to_date => to_date }
13
+ }
14
+ let(:uri) {
15
+ "#{@base_url}/api/?APIKey=#{@api_key}&Action=fixtures"\
16
+ "&comp_id=#{competition_id}&from_date=#{from_date}&to_date=#{to_date}"
17
+ }
18
+
19
+ before(:each) do
20
+ stub_request(:get, uri)
21
+ .with(headers: @headers)
22
+ .to_return(status: 200, body: response.to_json)
23
+ end
24
+
25
+ let(:request_response) { FootballApi::Fixture.where(from_to_parameters) }
26
+
27
+ it 'not_fails' do
28
+ expect(request_response).not_to be_nil
29
+ expect(request_response.size).to eq(40)
30
+ end
31
+
32
+ it 'has_first_match' do
33
+ fixture = request_response.first
34
+ expect(fixture.match).not_to be_nil
35
+ expect(fixture.match.match_comp_id.to_i).to eq(competition_id)
36
+ expect(fixture.match_events.size).to eq(2)
37
+ expect(fixture.match_timer).to be_blank
38
+ end
39
+
40
+ it 'has_last_match' do
41
+ fixture = request_response.last
42
+ expect(fixture.match).not_to be_nil
43
+ expect(fixture.match.match_comp_id.to_i).to eq(competition_id)
44
+ expect(fixture.match_events.size).to eq(4)
45
+ expect(fixture.match_timer).to be_blank
46
+ end
47
+ end
48
+
49
+ describe '.where match_date ' do
50
+ let(:response) { JSONHelper::Fixtures.get(:match_date) }
51
+
52
+ let(:match_date) { '01.01.2015' }
53
+ let(:date_parameters) {
54
+ { :comp_id => competition_id, :match_date => match_date }
55
+ }
56
+ let(:uri) {
57
+ "#{@base_url}/api/?APIKey=#{@api_key}&Action=fixtures"\
58
+ "&comp_id=#{competition_id}&match_date=#{match_date}"
59
+ }
60
+
61
+ before(:each) do
62
+ stub_request(:get, uri)
63
+ .with(headers: @headers)
64
+ .to_return(status: 200, body: response.to_json)
65
+ end
66
+
67
+ let(:request_response) { FootballApi::Fixture.where(date_parameters) }
68
+
69
+ it 'not_fails' do
70
+ expect(request_response).not_to be_nil
71
+ expect(request_response.size).to eq(10)
72
+ end
73
+
74
+ it 'has_first_match' do
75
+ fixture = request_response.first
76
+ expect(fixture.match).not_to be_nil
77
+ expect(fixture.match.match_comp_id.to_i).to eq(competition_id)
78
+ expect(fixture.match_events.size).to eq(2)
79
+ expect(fixture.match_timer).to be_blank
80
+ end
81
+
82
+ it 'has_last_match' do
83
+ fixture = request_response.last
84
+ expect(fixture.match).not_to be_nil
85
+ expect(fixture.match.match_comp_id.to_i).to eq(competition_id)
86
+ expect(fixture.match_events.size).to eq(12)
87
+ expect(fixture.match_timer).to be_blank
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,41 @@
1
+ # Automatically loads json files with an associated class for loading fixture
2
+ module JSONHelper
3
+ class << self
4
+ # Uhuhuh! What a cache!
5
+ def cache
6
+ @cache ||= {}
7
+ end
8
+
9
+ def cache_or_load(path)
10
+ cache[path] ||= begin
11
+ file = File.read(path)
12
+ JSON.parse(file).symbolize_keys
13
+ end
14
+ end
15
+
16
+ def load_file(name)
17
+ path = File.expand_path("../../json/#{name}", __FILE__)
18
+ cache_or_load(path)
19
+ end
20
+ end
21
+
22
+ # TODO: Better way to deal with this.
23
+ # Declaring a class for each one was too much.
24
+ # With this, it works, but is too meta, I think.
25
+ class Generic
26
+ def self.get(name)
27
+ new.get(name)
28
+ end
29
+
30
+ def get(name)
31
+ file_name = "#{File.basename(self.class.name.underscore)}.json"
32
+ fixtures = ::JSONHelper.load_file(file_name)
33
+ fixtures[name.to_sym].clone
34
+ end
35
+ end
36
+
37
+ Dir[File.expand_path('../../json/*.json', __FILE__)].each do |file_name|
38
+ klass_name = "#{File.basename(file_name, '.json').camelize}"
39
+ JSONHelper.const_set(klass_name, Class.new(Generic))
40
+ end
41
+ end