ahl_scraper 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +85 -0
- data/.ruby-version +1 -0
- data/.solargraph.yml +15 -0
- data/.travis.yml +6 -0
- data/.vscode/settings.json +11 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +25 -0
- data/Gemfile.lock +114 -0
- data/LICENSE.txt +21 -0
- data/README.md +235 -0
- data/Rakefile +8 -0
- data/ahl_scraper.gemspec +27 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/lib/ahl_scraper.rb +55 -0
- data/lib/ahl_scraper/fetchers/division_data_fetcher.rb +19 -0
- data/lib/ahl_scraper/fetchers/game_data_fetcher.rb +29 -0
- data/lib/ahl_scraper/fetchers/game_event_data_fetcher.rb +19 -0
- data/lib/ahl_scraper/fetchers/player_data_fetcher.rb +25 -0
- data/lib/ahl_scraper/fetchers/player_games/data_fetcher.rb +30 -0
- data/lib/ahl_scraper/fetchers/playoff_bracket_data_fetcher.rb +19 -0
- data/lib/ahl_scraper/fetchers/season_data_fetcher.rb +15 -0
- data/lib/ahl_scraper/fetchers/season_end_date_fetcher.rb +34 -0
- data/lib/ahl_scraper/fetchers/season_game_ids_fetcher.rb +21 -0
- data/lib/ahl_scraper/fetchers/season_start_date_fetcher.rb +30 -0
- data/lib/ahl_scraper/fetchers/season_type_fetcher.rb +33 -0
- data/lib/ahl_scraper/fetchers/team_data_fetcher.rb +19 -0
- data/lib/ahl_scraper/fetchers/team_games/data_fetcher.rb +22 -0
- data/lib/ahl_scraper/fetchers/team_roster_data_fetcher.rb +67 -0
- data/lib/ahl_scraper/fixed_games/1001050.json +2182 -0
- data/lib/ahl_scraper/fixed_games/1018774.json +2573 -0
- data/lib/ahl_scraper/fixed_games/1020527.json +2483 -0
- data/lib/ahl_scraper/games.rb +46 -0
- data/lib/ahl_scraper/games/events.rb +8 -0
- data/lib/ahl_scraper/helpers/birthdate_helper.rb +27 -0
- data/lib/ahl_scraper/helpers/elapsed_time_helper.rb +24 -0
- data/lib/ahl_scraper/helpers/ice_time_helper.rb +18 -0
- data/lib/ahl_scraper/helpers/parameterize_helper.rb +35 -0
- data/lib/ahl_scraper/helpers/period_time_helper.rb +25 -0
- data/lib/ahl_scraper/helpers/season_dates_helper.rb +14 -0
- data/lib/ahl_scraper/player_games.rb +19 -0
- data/lib/ahl_scraper/players.rb +12 -0
- data/lib/ahl_scraper/playoff_brackets.rb +17 -0
- data/lib/ahl_scraper/resource.rb +38 -0
- data/lib/ahl_scraper/resources/game.rb +373 -0
- data/lib/ahl_scraper/resources/game_list_item.rb +57 -0
- data/lib/ahl_scraper/resources/games/coach.rb +23 -0
- data/lib/ahl_scraper/resources/games/events/shot.rb +10 -0
- data/lib/ahl_scraper/resources/games/goal.rb +161 -0
- data/lib/ahl_scraper/resources/games/goalie.rb +106 -0
- data/lib/ahl_scraper/resources/games/info.rb +83 -0
- data/lib/ahl_scraper/resources/games/on_ice_skater.rb +35 -0
- data/lib/ahl_scraper/resources/games/overtime.rb +48 -0
- data/lib/ahl_scraper/resources/games/penalty.rb +101 -0
- data/lib/ahl_scraper/resources/games/penalty_shot.rb +82 -0
- data/lib/ahl_scraper/resources/games/period.rb +31 -0
- data/lib/ahl_scraper/resources/games/referee.rb +23 -0
- data/lib/ahl_scraper/resources/games/shootout_attempt.rb +61 -0
- data/lib/ahl_scraper/resources/games/skater.rb +94 -0
- data/lib/ahl_scraper/resources/games/star.rb +47 -0
- data/lib/ahl_scraper/resources/games/team.rb +85 -0
- data/lib/ahl_scraper/resources/goalie_game_list_item.rb +69 -0
- data/lib/ahl_scraper/resources/player.rb +71 -0
- data/lib/ahl_scraper/resources/playoff_bracket.rb +21 -0
- data/lib/ahl_scraper/resources/playoff_brackets/game.rb +43 -0
- data/lib/ahl_scraper/resources/playoff_brackets/round.rb +31 -0
- data/lib/ahl_scraper/resources/playoff_brackets/series.rb +73 -0
- data/lib/ahl_scraper/resources/playoff_brackets/team.rb +39 -0
- data/lib/ahl_scraper/resources/roster_player.rb +71 -0
- data/lib/ahl_scraper/resources/season.rb +93 -0
- data/lib/ahl_scraper/resources/season_list_item.rb +30 -0
- data/lib/ahl_scraper/resources/seasons/team.rb +77 -0
- data/lib/ahl_scraper/resources/skater_game_list_item.rb +65 -0
- data/lib/ahl_scraper/resources/team_game_list_item.rb +64 -0
- data/lib/ahl_scraper/resources/team_list_item.rb +20 -0
- data/lib/ahl_scraper/roster_players.rb +11 -0
- data/lib/ahl_scraper/seasons.rb +31 -0
- data/lib/ahl_scraper/services/games/create_skaters_service.rb +72 -0
- data/lib/ahl_scraper/services/games/on_ice_statlines_service.rb +117 -0
- data/lib/ahl_scraper/services/games/penalty_shot_statlines_service.rb +38 -0
- data/lib/ahl_scraper/services/games/penalty_shots_service.rb +30 -0
- data/lib/ahl_scraper/services/games/penalty_statlines_service.rb +62 -0
- data/lib/ahl_scraper/services/games/scoring_statlines_service.rb +115 -0
- data/lib/ahl_scraper/services/games/shootout_statlines_service.rb +42 -0
- data/lib/ahl_scraper/services/games/team_on_ice_goals_service.rb +152 -0
- data/lib/ahl_scraper/services/games/time_splits_service.rb +70 -0
- data/lib/ahl_scraper/services/seasons/teams_service.rb +20 -0
- data/lib/ahl_scraper/team_games.rb +17 -0
- data/lib/ahl_scraper/teams.rb +11 -0
- data/lib/ahl_scraper/version.rb +5 -0
- metadata +138 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AhlScraper
|
4
|
+
class TeamListItem < Resource
|
5
|
+
attr_reader :season_id
|
6
|
+
|
7
|
+
def initialize(raw_data, season_id)
|
8
|
+
@raw_data = raw_data
|
9
|
+
@season_id = season_id
|
10
|
+
end
|
11
|
+
|
12
|
+
def name
|
13
|
+
@name ||= @raw_data[:row][:name]
|
14
|
+
end
|
15
|
+
|
16
|
+
def id
|
17
|
+
@id ||= @raw_data[:prop][:team_code][:teamLink].to_i
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AhlScraper
|
4
|
+
module RosterPlayers
|
5
|
+
class << self
|
6
|
+
def retrieve_all(team_id, season_id)
|
7
|
+
TeamRosterDataFetcher.new(team_id, season_id).call&.map { |player| RosterPlayer.new(player, team_id, season_id) }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ahl_scraper/services/seasons/teams_service"
|
4
|
+
|
5
|
+
require "ahl_scraper/resources/seasons/team"
|
6
|
+
|
7
|
+
module AhlScraper
|
8
|
+
module Seasons
|
9
|
+
@season_data = nil
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def list
|
13
|
+
@season_data ||= SeasonDataFetcher.new.call&.map { |season_data| SeasonListItem.new(season_data) }
|
14
|
+
@season_data
|
15
|
+
end
|
16
|
+
|
17
|
+
def retrieve(season_id)
|
18
|
+
@season_data ||= SeasonDataFetcher.new.call&.map { |season_data| SeasonListItem.new(season_data) }
|
19
|
+
season = @season_data.find { |s| season_id.to_i == s.id }
|
20
|
+
Season.new(season)
|
21
|
+
end
|
22
|
+
|
23
|
+
def retrieve_all
|
24
|
+
@season_data ||= SeasonDataFetcher.new.call
|
25
|
+
@season_data.map do |season|
|
26
|
+
Season.new(season)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AhlScraper
|
4
|
+
module Games
|
5
|
+
class CreateSkatersService
|
6
|
+
def initialize(skater_data, goal_data, penalty_data, shootout_data, penalty_shot_data, opts)
|
7
|
+
@skater_data = skater_data
|
8
|
+
@goal_data = goal_data
|
9
|
+
@penalty_data = penalty_data
|
10
|
+
@shootout_data = shootout_data
|
11
|
+
@penalty_shot_data = penalty_shot_data
|
12
|
+
@opts = opts
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
scoring_statlines = ScoringStatlinesService.new(team_goals, skater_ids, @opts).call
|
17
|
+
on_ice_statlines = OnIceStatlinesService.new(@goal_data, @opts[:team_id], skater_ids).call
|
18
|
+
penalty_statlines = PenaltyStatlinesService.new(@penalty_data, @opts[:team_id], skater_ids).call
|
19
|
+
penalty_shot_statlines = PenaltyShotStatlinesService.new(@penalty_shot_data, @opts[:team_id], skater_ids).call
|
20
|
+
shootout_statlines = ShootoutStatlinesService.new(@shootout_data, @opts[:team_id], skater_ids).call
|
21
|
+
|
22
|
+
skaters.map do |s|
|
23
|
+
id_key = s[:id].to_s
|
24
|
+
Skater.new(
|
25
|
+
s,
|
26
|
+
{
|
27
|
+
**@opts,
|
28
|
+
scoring_statline: scoring_statlines[id_key],
|
29
|
+
on_ice_statline: on_ice_statlines[id_key],
|
30
|
+
penalty_statline: penalty_statlines[id_key],
|
31
|
+
penalty_shot_statline: penalty_shot_statlines[id_key],
|
32
|
+
shootout_statline: shootout_statlines[id_key],
|
33
|
+
}
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def team_goals
|
41
|
+
@goal_data.filter { |g| g[:team][:id] == @opts[:team_id] }
|
42
|
+
end
|
43
|
+
|
44
|
+
def skater_ids
|
45
|
+
@skater_ids ||= @skater_data.map { |skater| skater[:info][:id] }
|
46
|
+
end
|
47
|
+
|
48
|
+
def skaters
|
49
|
+
@skater_data.map do |s|
|
50
|
+
{
|
51
|
+
id: s[:info][:id],
|
52
|
+
first_name: s[:info][:firstName],
|
53
|
+
last_name: s[:info][:lastName],
|
54
|
+
position: s[:info][:position],
|
55
|
+
birthdate: s[:info][:birthDate],
|
56
|
+
number: s[:info][:jerseyNumber],
|
57
|
+
starting: s[:starting] == 1,
|
58
|
+
captaincy: %w[A C].include?(s[:status]) ? s[:status] : nil,
|
59
|
+
home_team: @opts[:home_team],
|
60
|
+
team_id: @opts[:team_id],
|
61
|
+
team_abbreviation: @opts[:team_abbreviation],
|
62
|
+
faceoff_attempts: s[:stats][:faceoffAttempts],
|
63
|
+
faceoff_wins: s[:stats][:faceoffWins],
|
64
|
+
hits: s[:stats][:hits],
|
65
|
+
penalty_minutes: s[:stats][:penaltyMinutes],
|
66
|
+
sog_as: s[:stats][:shots],
|
67
|
+
}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AhlScraper
|
4
|
+
module Games
|
5
|
+
class OnIceStatlinesService
|
6
|
+
def initialize(goal_data, team_id, skater_ids)
|
7
|
+
@goal_data = goal_data
|
8
|
+
@team_id = team_id
|
9
|
+
@skater_ids = skater_ids
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
@goal_data.each do |goal|
|
14
|
+
next if goal[:properties][:isPenaltyShot] == "1"
|
15
|
+
|
16
|
+
goal_status = goal[:team][:id] == @team_id ? "gf" : "ga"
|
17
|
+
on_scoring_team = goal[:team][:id] == @team_id
|
18
|
+
plus_player_ids = goal[:plus_players].map { |pl| pl[:id].to_s }
|
19
|
+
minus_player_ids = goal[:minus_players].map { |pl| pl[:id].to_s }
|
20
|
+
skater_ids = on_scoring_team ? plus_player_ids : minus_player_ids
|
21
|
+
opposing_skater_ids = on_scoring_team ? minus_player_ids : plus_player_ids
|
22
|
+
goal_situation = find_goal_situation(goal, on_scoring_team)
|
23
|
+
goal_player_counts = find_goal_player_counts(skater_ids, opposing_skater_ids, on_scoring_team)
|
24
|
+
|
25
|
+
skater_ids.map(&:to_s).each do |skater_id|
|
26
|
+
on_ice_statlines[skater_id] ||= blank_statline
|
27
|
+
on_ice_statlines[skater_id]["#{goal_status}_as".to_sym] += 1
|
28
|
+
on_ice_statlines[skater_id]["#{goal_status}_#{goal_situation}".to_sym] += 1
|
29
|
+
next unless opposing_skater_ids.length >= 3 && skater_ids.length >= 3 && opposing_skater_ids.length <= 6 && skater_ids.length <= 6
|
30
|
+
|
31
|
+
on_ice_statlines[skater_id]["#{goal_status}_#{goal_player_counts}".to_sym] += 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
on_ice_statlines
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def on_ice_statlines
|
41
|
+
@on_ice_statlines ||= @skater_ids.map { |s_id| [s_id.to_s, blank_statline] }.to_h
|
42
|
+
end
|
43
|
+
|
44
|
+
def find_goal_player_counts(skater_ids, opposing_skater_ids, on_scoring_team)
|
45
|
+
on_scoring_team ? "#{skater_ids.length}v#{opposing_skater_ids.length}" : "#{opposing_skater_ids.length}v#{skater_ids.length}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_goal_situation(goal, on_scoring_team)
|
49
|
+
return "pp" if (goal[:properties][:isPowerPlay] == "1" && on_scoring_team) || (goal[:properties][:isShortHanded] == "1" && !on_scoring_team)
|
50
|
+
|
51
|
+
return "sh" if goal[:properties][:isShortHanded] == "1" && on_scoring_team || (goal[:properties][:isPowerPlay] == "1" && !on_scoring_team)
|
52
|
+
|
53
|
+
return "en" if goal[:properties][:isEmptyNet] == "1" && on_scoring_team
|
54
|
+
|
55
|
+
return "ex" if goal[:properties][:isEmptyNet] == "1" && !on_scoring_team
|
56
|
+
|
57
|
+
if goal[:plus_players].length == 6 ||
|
58
|
+
(goal[:properties][:isPowerPlay] == "1" && goal[:plus_players].length == goal[:minus_players].length) ||
|
59
|
+
(goal[:properties][:isShortHanded] == "1" && goal[:plus_players].length == goal[:minus_players].length)
|
60
|
+
|
61
|
+
return on_scoring_team ? "ex" : "en"
|
62
|
+
end
|
63
|
+
|
64
|
+
"ev"
|
65
|
+
end
|
66
|
+
|
67
|
+
def blank_statline
|
68
|
+
{
|
69
|
+
gf_as: 0,
|
70
|
+
gf_ev: 0,
|
71
|
+
gf_pp: 0,
|
72
|
+
gf_sh: 0,
|
73
|
+
gf_ex: 0,
|
74
|
+
gf_en: 0,
|
75
|
+
gf_6v6: 0,
|
76
|
+
gf_6v5: 0,
|
77
|
+
gf_6v4: 0,
|
78
|
+
gf_6v3: 0,
|
79
|
+
gf_5v6: 0,
|
80
|
+
gf_5v5: 0,
|
81
|
+
gf_5v4: 0,
|
82
|
+
gf_5v3: 0,
|
83
|
+
gf_4v6: 0,
|
84
|
+
gf_4v5: 0,
|
85
|
+
gf_4v4: 0,
|
86
|
+
gf_4v3: 0,
|
87
|
+
gf_3v6: 0,
|
88
|
+
gf_3v5: 0,
|
89
|
+
gf_3v4: 0,
|
90
|
+
gf_3v3: 0,
|
91
|
+
ga_as: 0,
|
92
|
+
ga_ev: 0,
|
93
|
+
ga_pp: 0,
|
94
|
+
ga_sh: 0,
|
95
|
+
ga_ex: 0,
|
96
|
+
ga_en: 0,
|
97
|
+
ga_6v6: 0,
|
98
|
+
ga_6v5: 0,
|
99
|
+
ga_6v4: 0,
|
100
|
+
ga_6v3: 0,
|
101
|
+
ga_5v6: 0,
|
102
|
+
ga_5v5: 0,
|
103
|
+
ga_5v4: 0,
|
104
|
+
ga_5v3: 0,
|
105
|
+
ga_4v6: 0,
|
106
|
+
ga_4v5: 0,
|
107
|
+
ga_4v4: 0,
|
108
|
+
ga_4v3: 0,
|
109
|
+
ga_3v6: 0,
|
110
|
+
ga_3v5: 0,
|
111
|
+
ga_3v4: 0,
|
112
|
+
ga_3v3: 0,
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AhlScraper
|
4
|
+
module Games
|
5
|
+
class PenaltyShotStatlinesService
|
6
|
+
def initialize(penalty_shot_data, team_id, skater_ids)
|
7
|
+
@penalty_shot_data = penalty_shot_data
|
8
|
+
@team_id = team_id
|
9
|
+
@skater_ids = skater_ids
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
@penalty_shot_data.each do |penalty_shot|
|
14
|
+
skater_id = penalty_shot[:shooter][:id].to_s
|
15
|
+
penalty_shot_statlines[skater_id] ||= blank_statline
|
16
|
+
|
17
|
+
penalty_shot_statlines[skater_id][:attempts] += 1
|
18
|
+
penalty_shot_statlines[skater_id][:goals] += 1 if penalty_shot[:isGoal]
|
19
|
+
end
|
20
|
+
|
21
|
+
penalty_shot_statlines
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def penalty_shot_statlines
|
27
|
+
@penalty_shot_statlines ||= @skater_ids.map { |s_id| [s_id.to_s, blank_statline] }.to_h
|
28
|
+
end
|
29
|
+
|
30
|
+
def blank_statline
|
31
|
+
{
|
32
|
+
attempts: 0,
|
33
|
+
goals: 0,
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AhlScraper
|
4
|
+
module Games
|
5
|
+
class PenaltyShotsService
|
6
|
+
attr_reader :penalty_shot_data
|
7
|
+
|
8
|
+
def initialize(penalty_shot_data)
|
9
|
+
@penalty_shot_data = penalty_shot_data
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
ordered_penalty_shots.map.with_index { |ps, i| PenaltyShot.new(ps, { number: i + 1 }) }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def ordered_penalty_shots
|
19
|
+
@ordered_penalty_shots ||= penalty_shot_data.sort do |a, b|
|
20
|
+
[a[:period][:id].to_i, convert_time(a[:time])] <=> [b[:period][:id].to_i, convert_time(b[:time])]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def convert_time(game_time)
|
25
|
+
time = game_time.split(":")
|
26
|
+
time[0].to_i * 60 + time[1].to_i
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AhlScraper
|
4
|
+
module Games
|
5
|
+
class PenaltyStatlinesService
|
6
|
+
def initialize(penalty_data, team_id, skater_ids)
|
7
|
+
@penalty_data = penalty_data
|
8
|
+
@team_id = team_id
|
9
|
+
@skater_ids = skater_ids
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
@penalty_data.each do |penalty|
|
14
|
+
next unless penalty[:takenBy]
|
15
|
+
|
16
|
+
skater_id = penalty_statlines[penalty[:takenBy][:id].to_s] ? penalty[:takenBy][:id].to_s : false
|
17
|
+
next unless skater_id
|
18
|
+
|
19
|
+
penalty_statlines[skater_id][penalty_type(penalty)] += 1
|
20
|
+
penalty_statlines[skater_id][:penalty_minutes] += penalty[:minutes].to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
penalty_statlines
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def penalty_statlines
|
29
|
+
@penalty_statlines ||= @skater_ids.map { |s_id| [s_id.to_s, blank_statline] }.to_h
|
30
|
+
end
|
31
|
+
|
32
|
+
def blank_statline
|
33
|
+
{
|
34
|
+
penalty_minutes: 0,
|
35
|
+
minors: 0,
|
36
|
+
double_minors: 0,
|
37
|
+
majors: 0,
|
38
|
+
fights: 0,
|
39
|
+
misconducts: 0,
|
40
|
+
game_misconducts: 0,
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def penalty_type(penalty)
|
45
|
+
case penalty[:description]
|
46
|
+
when /double minor/i
|
47
|
+
:double_minors
|
48
|
+
when /major/i
|
49
|
+
:majors
|
50
|
+
when /fighting/i
|
51
|
+
:fights
|
52
|
+
when /game misconduct/i
|
53
|
+
:game_misconducts
|
54
|
+
when /misconduct/i
|
55
|
+
:misconducts
|
56
|
+
else
|
57
|
+
:minors
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AhlScraper
|
4
|
+
module Games
|
5
|
+
class ScoringStatlinesService
|
6
|
+
def initialize(goal_data, skater_ids, opts = {})
|
7
|
+
@goal_data = goal_data
|
8
|
+
@skater_ids = skater_ids
|
9
|
+
@opts = opts
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
@goal_data.each do |goal|
|
14
|
+
plus_player_count = goal[:plus_players].length
|
15
|
+
minus_player_count = goal[:minus_players].length
|
16
|
+
goalscorer_id = scoring_statlines[goal[:scoredBy][:id].to_s] ? goal[:scoredBy][:id].to_s : false # Make sure goal does not belong to goalie
|
17
|
+
a1_id = goal[:assists][0]&.dig(:id) && scoring_statlines[goal[:assists][0]&.dig(:id).to_s] ? goal[:assists][0]&.dig(:id).to_s : false # Make sure assist exists and does not belong to goalie
|
18
|
+
a2_id = goal[:assists][1]&.dig(:id) && scoring_statlines[goal[:assists][1]&.dig(:id).to_s] ? goal[:assists][1]&.dig(:id).to_s : false # Make sure assist exists and does not belong to goalie
|
19
|
+
|
20
|
+
add_points(goalscorer_id, a1_id, a2_id, "as")
|
21
|
+
if goal[:properties][:isPenaltyShot].to_i.positive?
|
22
|
+
scoring_statlines[goalscorer_id][:goals_ps] += 1
|
23
|
+
elsif extra_skater?(goal, plus_player_count, minus_player_count)
|
24
|
+
add_points(goalscorer_id, a1_id, a2_id, "ex")
|
25
|
+
elsif goal[:properties][:isEmptyNet].to_i.positive?
|
26
|
+
add_points(goalscorer_id, a1_id, a2_id, "en")
|
27
|
+
elsif goal[:properties][:isPowerPlay].to_i.positive?
|
28
|
+
add_points(goalscorer_id, a1_id, a2_id, "pp")
|
29
|
+
elsif goal[:properties][:isShortHanded].to_i.positive?
|
30
|
+
add_points(goalscorer_id, a1_id, a2_id, "sh")
|
31
|
+
elsif plus_player_count == minus_player_count
|
32
|
+
add_points(goalscorer_id, a1_id, a2_id, "ev")
|
33
|
+
add_points(goalscorer_id, a1_id, a2_id, "5v5") if plus_player_count == 5 && minus_player_count == 5
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
scoring_statlines
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def scoring_statlines
|
43
|
+
@scoring_statlines ||= @skater_ids.map { |s_id| [s_id.to_s, blank_statline] }.to_h
|
44
|
+
end
|
45
|
+
|
46
|
+
def blank_statline
|
47
|
+
{
|
48
|
+
goals_as: 0,
|
49
|
+
a1_as: 0,
|
50
|
+
a2_as: 0,
|
51
|
+
points_as: 0,
|
52
|
+
primary_points_as: 0,
|
53
|
+
goals_ps: 0,
|
54
|
+
primary_points_ps: 0,
|
55
|
+
goals_ev: 0,
|
56
|
+
a1_ev: 0,
|
57
|
+
a2_ev: 0,
|
58
|
+
points_ev: 0,
|
59
|
+
primary_points_ev: 0,
|
60
|
+
goals_5v5: 0,
|
61
|
+
a1_5v5: 0,
|
62
|
+
a2_5v5: 0,
|
63
|
+
points_5v5: 0,
|
64
|
+
primary_points_5v5: 0,
|
65
|
+
goals_pp: 0,
|
66
|
+
a1_pp: 0,
|
67
|
+
a2_pp: 0,
|
68
|
+
points_pp: 0,
|
69
|
+
primary_points_pp: 0,
|
70
|
+
goals_sh: 0,
|
71
|
+
a1_sh: 0,
|
72
|
+
a2_sh: 0,
|
73
|
+
points_sh: 0,
|
74
|
+
primary_points_sh: 0,
|
75
|
+
goals_ex: 0,
|
76
|
+
a1_ex: 0,
|
77
|
+
a2_ex: 0,
|
78
|
+
points_ex: 0,
|
79
|
+
primary_points_ex: 0,
|
80
|
+
goals_en: 0,
|
81
|
+
a1_en: 0,
|
82
|
+
a2_en: 0,
|
83
|
+
points_en: 0,
|
84
|
+
primary_points_en: 0,
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_points(goalscorer_id, a1_id, a2_id, situation)
|
89
|
+
if goalscorer_id
|
90
|
+
scoring_statlines[goalscorer_id]["goals_#{situation}".to_sym] += 1
|
91
|
+
scoring_statlines[goalscorer_id]["primary_points_#{situation}".to_sym] += 1
|
92
|
+
end
|
93
|
+
if a1_id
|
94
|
+
scoring_statlines[a1_id]["a1_#{situation}".to_sym] += 1
|
95
|
+
scoring_statlines[a1_id]["primary_points_#{situation}".to_sym] += 1
|
96
|
+
end
|
97
|
+
scoring_statlines[a2_id]["a2_#{situation}".to_sym] += 1 if a2_id
|
98
|
+
|
99
|
+
scoring_statlines[goalscorer_id]["points_#{situation}".to_sym] += 1 if goalscorer_id
|
100
|
+
scoring_statlines[a1_id]["points_#{situation}".to_sym] += 1 if a1_id
|
101
|
+
scoring_statlines[a2_id]["points_#{situation}".to_sym] += 1 if a2_id
|
102
|
+
end
|
103
|
+
|
104
|
+
def extra_skater?(goal, scoring_team_player_count, defending_team_skater_count)
|
105
|
+
return true if scoring_team_player_count == 6
|
106
|
+
|
107
|
+
if (goal[:isPowerPlay].to_i.positive? || goal[:isShortHanded].to_i.positive?) && scoring_team_player_count == defending_team_skater_count
|
108
|
+
return true
|
109
|
+
end
|
110
|
+
|
111
|
+
false
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|