From dc14a3fcd922e1c1c248e7374c78bfe5bf000341 Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 30 Sep 2024 13:34:52 -0400 Subject: [PATCH 01/14] Add GetBoxscoreByGameIdAsync method and refactorings - Added `GetBoxscoreByGameIdAsync` method in NhlApi.cs with documentation. - Added `GetBoxscoreByGameIdAsync` method to INhlGameApi interface. - Implemented `GetBoxscoreByGameIdAsync` in NhlGameApi.cs. - Added comment on manual boxscore assignment due to API changes. --- Nhl.Api/Src/Api/NhlApi.cs | 8 ++++++++ Nhl.Api/Src/GameApi/INhlGameApi.cs | 10 +++++++++- Nhl.Api/Src/GameApi/NhlGameApi.cs | 10 ++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Nhl.Api/Src/Api/NhlApi.cs b/Nhl.Api/Src/Api/NhlApi.cs index d238565e..6cd4c4af 100644 --- a/Nhl.Api/Src/Api/NhlApi.cs +++ b/Nhl.Api/Src/Api/NhlApi.cs @@ -706,6 +706,14 @@ public async Task GetPlayerStatisticsBySeasonAndFi public async Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionGoalieFilter expressionGoalieFilter, GoalieStatisticsFilter goalieStatisticsFilterToSortBy = GoalieStatisticsFilter.Wins, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default) => await _nhlStatisticsApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionGoalieFilter, goalieStatisticsFilterToSortBy, limit, offsetStart, cancellationToken); + /// + /// Returns the NHL game direct box score including information such as summaries, linescores, shots by period and more + /// + /// The NHL game identifier, Example: 2023020204 + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation + /// Returns the NHL game direct box score including information such as summaries, linescores, shots by period and more + public async Task GetBoxscoreByGameIdAsync(int gameId, CancellationToken cancellationToken = default) => await _nhlGameApi.GetBoxscoreByGameIdAsync(gameId, cancellationToken); + /// /// Releases and disposes all unused or garbage collected resources for the Nhl.Api /// diff --git a/Nhl.Api/Src/GameApi/INhlGameApi.cs b/Nhl.Api/Src/GameApi/INhlGameApi.cs index 09f62b16..56397136 100644 --- a/Nhl.Api/Src/GameApi/INhlGameApi.cs +++ b/Nhl.Api/Src/GameApi/INhlGameApi.cs @@ -1,4 +1,4 @@ -namespace Nhl.Api; +namespace Nhl.Api; /// /// The official unofficial NHL Game API providing various NHL information game information, game schedules, live game feeds and more @@ -132,4 +132,12 @@ public interface INhlGameApi /// A cancellation token that can be used by other objects or threads to receive notice of cancellation /// Returns the NHL game meta data for the specified game id, including the teams, season states and more public Task GetGameMetadataByGameIdAsync(int gameId, CancellationToken cancellationToken = default); + + /// + /// Returns the NHL game meta data for the specified game id, including the teams, season states and more + /// + /// The NHL game identifier, Example: 2023020204 + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation + /// Returns the NHL game meta data for the specified game id, including the teams, season states and more + public Task GetBoxscoreByGameIdAsync(int gameId, CancellationToken cancellationToken = default); } diff --git a/Nhl.Api/Src/GameApi/NhlGameApi.cs b/Nhl.Api/Src/GameApi/NhlGameApi.cs index c9f63641..3f1d9ac3 100644 --- a/Nhl.Api/Src/GameApi/NhlGameApi.cs +++ b/Nhl.Api/Src/GameApi/NhlGameApi.cs @@ -161,11 +161,21 @@ public async Task GetGameCenterBoxScoreByGameIdAsync(int gam await Task.WhenAll(gameCenterBoxScoreTask, boxScoreTask); var gameCenterBoxScore = await gameCenterBoxScoreTask; + + // We manually assign the boxscore to the object as the NHL API has moved the boxscore to a different endpoint gameCenterBoxScore.Boxscore = await boxScoreTask; return gameCenterBoxScore; } + /// + /// Returns the NHL game direct box score including information such as summaries, linescores, shots by period and more + /// + /// The NHL game identifier, Example: 2023020204 + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation + /// Returns the NHL game direct box score including information such as summaries, linescores, shots by period and more + public async Task GetBoxscoreByGameIdAsync(int gameId, CancellationToken cancellationToken = default) => await _nhlApiWebHttpClient.GetAsync($"/gamecenter/{gameId}/right-rail", cancellationToken); + /// /// Returns the NHL game meta data for the specified game id, including the teams, season states and more /// From f92c86e7c15aaf7ce665dcf575ef002c8a1f29e4 Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Tue, 1 Oct 2024 21:37:49 -0400 Subject: [PATCH 02/14] Add date and time estimation for NHL play-by-play events Introduced functionality to estimate and include the date and time of each play in the NHL game center play-by-play feed. Key changes include: - Added necessary `using` directives for threading, tasks, and collections. - Modified `GameCenterPlay` class to include a computed `Period` property and a new `EstimatedDateTimeOfPlay` property. - Added a static `HashSet` named `AllSeasons` to `SeasonYear` class. - Implemented `AddDateTimeOfPlayForEachPlay` method in `NhlGameService`. - Updated `GetGameCenterPlayByPlayByGameIdAsync` method and related interfaces to include a new `includeEventDateTime` parameter. - Modified test methods to use `TimeOnly` instead of `string`. --- .../Http/NhlScoresHtmlReportsApiHttpClient.cs | 2 + .../Models/Game/GameCenterPlayByPlay.cs | 9 +- Nhl.Api.Domain/Models/Season/SeasonYears.cs | 31 +++- Nhl.Api.Domain/Services/NhlGameService.cs | 157 +++++++++++++++++- Nhl.Api.Tests/GameTests.cs | 28 ++-- Nhl.Api/Src/Api/NhlApi.cs | 5 +- Nhl.Api/Src/GameApi/INhlGameApi.cs | 3 +- Nhl.Api/Src/GameApi/NhlGameApi.cs | 19 ++- Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs | 17 +- 9 files changed, 238 insertions(+), 33 deletions(-) diff --git a/Nhl.Api.Common/Http/NhlScoresHtmlReportsApiHttpClient.cs b/Nhl.Api.Common/Http/NhlScoresHtmlReportsApiHttpClient.cs index fa84d331..c5ddec6a 100644 --- a/Nhl.Api.Common/Http/NhlScoresHtmlReportsApiHttpClient.cs +++ b/Nhl.Api.Common/Http/NhlScoresHtmlReportsApiHttpClient.cs @@ -1,5 +1,7 @@ using System; using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; namespace Nhl.Api.Common.Http; /// diff --git a/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs b/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs index 81b3ebe7..8966e425 100644 --- a/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs +++ b/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs @@ -294,8 +294,7 @@ public class GameCenterPlay /// The period number for the NHL game center play by play
/// Example: 1 ///
- [JsonProperty("period")] - public int Period { get; set; } + public int Period => this.PeriodDescriptor?.Number ?? 0; /// /// The period descriptor for the NHL game center play by play
@@ -364,6 +363,12 @@ public class GameCenterPlay ///
[JsonProperty("details")] public GameCenterDetails Details { get; set; } + + /// + /// The estimated time of the play for the NHL game center play by play, these are not exact times and are close approximations of each game event
+ /// Example: 2024-01-13T20:12:23Z + ///
+ public DateTimeOffset EstimatedDateTimeOfPlay { get; set; } } /// diff --git a/Nhl.Api.Domain/Models/Season/SeasonYears.cs b/Nhl.Api.Domain/Models/Season/SeasonYears.cs index 068e8149..1770d9fa 100644 --- a/Nhl.Api.Domain/Models/Season/SeasonYears.cs +++ b/Nhl.Api.Domain/Models/Season/SeasonYears.cs @@ -1,4 +1,6 @@ - + +using System.Collections.Generic; + namespace Nhl.Api.Models.Season; /// @@ -6,6 +8,33 @@ namespace Nhl.Api.Models.Season; /// public class SeasonYear { + /// + /// A collection of all the NHL seasons + /// + public static readonly HashSet AllSeasons = + [ + "19171918", "19181919", "19191920", "19201921", "19211922", "19221923", + "19231924", "19241925", "19251926", "19261927", "19271928", "19281929", + "19291930", "19301931", "19311932", "19321933", "19331934", "19341935", + "19351936", "19361937", "19371938", "19381939", "19391940", "19401941", + "19411942", "19421943", "19431944", "19441945", "19451946", "19461947", + "19471948", "19481949", "19491950", "19501951", "19511952", "19521953", + "19531954", "19541955", "19551956", "19561957", "19571958", "19581959", + "19591960", "19601961", "19611962", "19621963", "19631964", "19641965", + "19651966", "19661967", "19671968", "19681969", "19691970", "19701971", + "19711972", "19721973", "19731974", "19741975", "19751976", "19761977", + "19771978", "19781979", "19791980", "19801981", "19811982", "19821983", + "19831984", "19841985", "19851986", "19861987", "19871988", "19881989", + "19891990", "19901991", "19911992", "19921993", "19931994", "19941995", + "19951996", "19961997", "19971998", "19981999", "19992000", "20002001", + "20012002", "20022003", "20032004", "20052006", "20062007", "20072008", + "20082009", "20092010", "20102011", "20112012", "20122013", "20132014", + "20142015", "20152016", "20162017", "20172018", "20182019", "20192020", + "20202021", "20212022", "20222023", "20232024", "20242025", "20252026", + "20262027", "20272028", "20282029", "20292030", "20302031", "20312032", + "20322033", "20332034", "20342035" + ]; + /// /// The NHL season 1917-1918 /// diff --git a/Nhl.Api.Domain/Services/NhlGameService.cs b/Nhl.Api.Domain/Services/NhlGameService.cs index f537ad5d..acd5ec91 100644 --- a/Nhl.Api.Domain/Services/NhlGameService.cs +++ b/Nhl.Api.Domain/Services/NhlGameService.cs @@ -1,11 +1,26 @@ -namespace Nhl.Api.Services; +using System.Collections.Generic; +using System.Globalization; +using System.Text.RegularExpressions; +using System; +using System.Threading.Tasks; +using Nhl.Api.Common.Http; +using Nhl.Api.Models.Game; +using System.Linq; +using Nhl.Api.Models.Schedule; + +namespace Nhl.Api.Services; /// /// The NHL game service, enabling data enrichment and functionality to the Nhl.Api /// public interface INhlGameService { - + /// + /// A method to add the time of play for each play in the game center play by play + /// + /// A game center play by play object + /// All of the game center play by play information with the time of play for each play + Task AddDateTimeOfPlayForEachPlay(GameCenterPlayByPlay gameCenterPlayByPlay); } /// @@ -13,4 +28,142 @@ public interface INhlGameService /// public class NhlGameService : INhlGameService { + private readonly NhlScoresHtmlReportsApiHttpClient _nhlScoresHtmlReportsApiHttpClient = new(); + + /// + /// A method to add the estimated time of play for each play in the game center play by play + /// + /// A game center play by play object + /// All of the game center play by play information with the time of play for each play + public async Task AddDateTimeOfPlayForEachPlay(GameCenterPlayByPlay gameCenterPlayByPlay) + { + var gameId = gameCenterPlayByPlay.Id.ToString(CultureInfo.InvariantCulture)[4..]; + var scoreReport = await this._nhlScoresHtmlReportsApiHttpClient.GetStringAsync($"/{gameCenterPlayByPlay.Season}/PL{gameId}.HTM", default); + + var regex = Regex.Matches(scoreReport, @"(?<=)Period(.*?)(?=)", RegexOptions.Compiled, TimeSpan.FromSeconds(5)).ToList(); + + if (string.IsNullOrWhiteSpace(scoreReport) || regex.Count == 0) + { + try + { + var gameStart = DateTimeOffset.Parse($"{gameCenterPlayByPlay.StartTimeUTC}", CultureInfo.InvariantCulture); + var timeSpanOffset = TimeSpan.Parse(gameCenterPlayByPlay.VenueUTCOffset, CultureInfo.InvariantCulture); + + // Set offset + gameStart = gameStart.AddHours(timeSpanOffset.TotalHours); + + // Set average delay in start time + gameStart = gameStart.Add(TimeSpan.FromMinutes(8.5)); + + var averageTimeDelayInIntermission = TimeSpan.FromMinutes(18); + + // Average time of a period including stoppage + var timeOfPeriod = TimeSpan.FromMinutes(35); + + foreach (var play in gameCenterPlayByPlay.Plays) + { + var period = play.Period; + var timeElapsed = TimeSpan.Zero; + + if (period > 1) + { + var regularPeriodTime = period <= 3 ? ((period - 1) * timeOfPeriod) : TimeSpan.FromMinutes(105); + var averageDelayInIntermission = period <= 3 ? ((period - 1) * averageTimeDelayInIntermission) : TimeSpan.FromMinutes(60); + timeElapsed += averageDelayInIntermission + regularPeriodTime; + } + + timeElapsed += TimeOnly.Parse($"00:{play.TimeInPeriod}", CultureInfo.InvariantCulture).ToTimeSpan(); + if (period > 3) + { + timeElapsed += period * TimeSpan.FromMinutes(10); + } + + timeElapsed += TimeSpan.FromSeconds(5); + play.EstimatedDateTimeOfPlay = gameStart.Add(timeElapsed); + } + } + catch + { + } + } + else + { + try + { + var startTimeOfEachPeriod = new Dictionary> + { + { 1, [] }, + { 2, [] }, + { 3, [] }, + { 4, [] }, + { 5, [] }, + }; + + for (var i = 0; i < regex.Count; i++) + { + var match = regex[i].Value; + var value = Regex.Match(match, @"([0-9]{1,2}:[0-9]{2})", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(30)).Groups[0].Value; + var time = TimeOnly.Parse($"{value} PM", CultureInfo.InvariantCulture); + var dateTime = DateTime.Parse($"{gameCenterPlayByPlay.GameDate} {time} {gameCenterPlayByPlay.EasternUTCOffset}", CultureInfo.InvariantCulture); + + if (i <= 1) + { + startTimeOfEachPeriod[1].Add(dateTime); + } + else if (i is >= 2 and <= 3) + { + startTimeOfEachPeriod[2].Add(dateTime); + } + else if (i is >= 4 and <= 5) + { + startTimeOfEachPeriod[3].Add(dateTime); + } + else if (i is >= 6 and <= 7) + { + startTimeOfEachPeriod[4].Add(dateTime); + } + else if (i <= 9) + { + startTimeOfEachPeriod[5].Add(dateTime); + } + } + + var playsByPeriod = gameCenterPlayByPlay.Plays.GroupBy(x => x.Period).ToDictionary(x => x.Key, x => x.ToList()); + + foreach (var playsForPeriod in playsByPeriod) + { + var startTime = startTimeOfEachPeriod[playsForPeriod.Key].FirstOrDefault(); + var endTime = startTimeOfEachPeriod[playsForPeriod.Key].LastOrDefault(); + var distanceBetweenPlays = endTime - startTime; + var timeBetweenPlays = distanceBetweenPlays / playsForPeriod.Value.Count; + + var multiplier = CalculateMultiplier(startTime, endTime, playsForPeriod.Value.Count); + for (var i = 0; i < playsForPeriod.Value.Count; i++) + { + var play = playsForPeriod.Value[i]; + var timeElapsed = TimeOnly.Parse($"00:{playsForPeriod.Value[i].TimeInPeriod}", CultureInfo.InvariantCulture).ToTimeSpan(); + play.EstimatedDateTimeOfPlay = startTime.Add(timeElapsed + (timeBetweenPlays * (i * multiplier))); + } + } + } + catch + { + } + } + + return gameCenterPlayByPlay; + } + + /// + /// A linear + /// + private double CalculateMultiplier(DateTime startTime, DateTime endTime, int events) + { + // Calculate duration in minutes + var duration = (endTime - startTime).TotalMinutes; + + var multiplier = ((41 * duration) + (2 * events) - 381) / 3000; + + return multiplier; + } } diff --git a/Nhl.Api.Tests/GameTests.cs b/Nhl.Api.Tests/GameTests.cs index 5800e273..58c99259 100644 --- a/Nhl.Api.Tests/GameTests.cs +++ b/Nhl.Api.Tests/GameTests.cs @@ -210,13 +210,13 @@ public async Task GetGameMetadataByGameIdAsync_Return_Valid_Information(int game [TestMethodWithRetry(RetryCount = 5)] public async Task NhlScoresHtmlReportsApiHttpClient_Can_Parse_Html_Report_For_Start_End_Period_Times() { - var dictionary = new Dictionary> + var dictionary = new Dictionary> { - { "P1", new List() }, - { "P2", new List() }, - { "P3", new List() }, - { "OT", new List() }, - { "SH", new List() }, + { "P1", new List() }, + { "P2", new List() }, + { "P3", new List() }, + { "OT", new List() }, + { "SH", new List() }, }; var httpClient = new NhlScoresHtmlReportsApiHttpClient(); @@ -224,29 +224,31 @@ public async Task NhlScoresHtmlReportsApiHttpClient_Can_Parse_Html_Report_For_St var regex = Regex.Matches(gameReport, @"(?<=)Period(.*?)(?=)", RegexOptions.Compiled, TimeSpan.FromSeconds(30)).ToList(); - for (int i = 0; i < regex.Count; i++) + for (var i = 0; i < regex.Count; i++) { var match = regex[i].Value; - var value = Regex.Match(match, @"([0-9]{1,2}:[0-9]{2}\s[A-Z]{3})", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(30)).Groups[0].Value; + var value = Regex.Match(match, @"([0-9]{1,2}:[0-9]{2})", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(30)).Groups[0].Value; + var time = TimeOnly.Parse($"{value} PM"); + if (i <= 1) { - dictionary["P1"].Add(value); + dictionary["P1"].Add(time); } else if (i >= 2 && i <= 3) { - dictionary["P2"].Add(value); + dictionary["P2"].Add(time); } else if (i >= 4 && i <= 5) { - dictionary["P3"].Add(value); + dictionary["P3"].Add(time); } else if (i >= 6 && i <= 7) { - dictionary["OT"].Add(value); + dictionary["OT"].Add(time); } else if (i <= 9) { - dictionary["SH"].Add(value); + dictionary["SH"].Add(time); } } } diff --git a/Nhl.Api/Src/Api/NhlApi.cs b/Nhl.Api/Src/Api/NhlApi.cs index 6cd4c4af..040b4715 100644 --- a/Nhl.Api/Src/Api/NhlApi.cs +++ b/Nhl.Api/Src/Api/NhlApi.cs @@ -516,9 +516,10 @@ public async Task GetGameScoreboardAsync(CancellationToken cance /// /// The NHL game identifier, Example: 2023020204 /// A cancellation token that can be used by other objects or threads to receive notice of cancellation + /// A flag to include the event date and time for the NHL game center play by play feed /// Returns the NHL game center feed for the specified game id, including the game information, game status, game venue and more - public async Task GetGameCenterPlayByPlayByGameIdAsync(int gameId, CancellationToken cancellationToken = default) => - await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(gameId, cancellationToken); + public async Task GetGameCenterPlayByPlayByGameIdAsync(int gameId, bool includeEventDateTime = false, CancellationToken cancellationToken = default) => + await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(gameId, includeEventDateTime, cancellationToken); /// /// Returns the NHL game center feed for the specified game id, including the game information, game status, game venue and more diff --git a/Nhl.Api/Src/GameApi/INhlGameApi.cs b/Nhl.Api/Src/GameApi/INhlGameApi.cs index 56397136..721f4516 100644 --- a/Nhl.Api/Src/GameApi/INhlGameApi.cs +++ b/Nhl.Api/Src/GameApi/INhlGameApi.cs @@ -105,9 +105,10 @@ public interface INhlGameApi /// Returns the NHL game center feed for the specified game id, including the game information, game status, game venue and more /// /// The NHL game identifier, Example: 2023020204 + /// A flag to determine whether the event timestamp for each play by play event is included /// A cancellation token that can be used by other objects or threads to receive notice of cancellation /// Returns the NHL game center feed for the specified game id, including the game information, game status, game venue and more - public Task GetGameCenterPlayByPlayByGameIdAsync(int gameId, CancellationToken cancellationToken = default); + public Task GetGameCenterPlayByPlayByGameIdAsync(int gameId, bool includeEventDateTime = false, CancellationToken cancellationToken = default); /// /// Returns the NHL game center feed for the specified game id, including the game information, game status, game venue and more diff --git a/Nhl.Api/Src/GameApi/NhlGameApi.cs b/Nhl.Api/Src/GameApi/NhlGameApi.cs index 3f1d9ac3..84503a9c 100644 --- a/Nhl.Api/Src/GameApi/NhlGameApi.cs +++ b/Nhl.Api/Src/GameApi/NhlGameApi.cs @@ -1,3 +1,7 @@ +using System.Globalization; +using System.Text.RegularExpressions; +using Nhl.Api.Common.Http; +using Nhl.Api.Models.Game; using Nhl.Api.Services; namespace Nhl.Api; @@ -9,6 +13,8 @@ public class NhlGameApi : INhlGameApi private static readonly NhlShiftChartHttpClient _nhlShiftChartHttpClient = new(); private static readonly NhlApiWebHttpClient _nhlApiWebHttpClient = new(); private static readonly NhlTeamService _nhlTeamService = new(); + private static readonly NhlScoresHtmlReportsApiHttpClient _nhlScoresHtmlReportsApiHttpClient = new(); + private static readonly NhlGameService _nhlGameService = new(); /// /// The official unofficial NHL Game API providing various NHL information game information, game schedules, live game feeds and more @@ -133,10 +139,19 @@ public async Task GetGameScoreboardAsync(CancellationToken cance /// Returns the NHL game center feed for the specified game id, including the game information, game status, game venue and more /// /// The NHL game identifier, Example: 2023020204 + /// A flag to determine whether the event timestamp for each play by play event is included /// A cancellation token that can be used by other objects or threads to receive notice of cancellation /// Returns the NHL game center feed for the specified game id, including the game information, game status, game venue and more - public async Task GetGameCenterPlayByPlayByGameIdAsync(int gameId, CancellationToken cancellationToken = default) => - await _nhlApiWebHttpClient.GetAsync($"/gamecenter/{gameId}/play-by-play", cancellationToken); + public async Task GetGameCenterPlayByPlayByGameIdAsync(int gameId, bool includeEventDateTime = false, CancellationToken cancellationToken = default) + { + var gameCenterPlayByPlay = await _nhlApiWebHttpClient.GetAsync($"/gamecenter/{gameId}/play-by-play", cancellationToken); + if (includeEventDateTime) + { + gameCenterPlayByPlay = await _nhlGameService.AddDateTimeOfPlayForEachPlay(gameCenterPlayByPlay); + } + + return gameCenterPlayByPlay; + } /// /// Returns the NHL game center feed for the specified game id, including the game information, game status, game venue and more diff --git a/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs b/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs index d7bda13e..ca314f38 100644 --- a/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs +++ b/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs @@ -167,7 +167,7 @@ public async Task GetTotalPlayerStatisticValueByTypeAndSeasonAsync(PlayerEn var tasks = schedule.Games.Select(async game => { // Count number of game events where player won a faceoff - var gameCenterPlayByPlay = await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(game.Id, cancellationToken); + var gameCenterPlayByPlay = await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(game.Id, includeEventDateTime: false, cancellationToken); return gameCenterPlayByPlay.Plays.Count(play => { var playerId = (int)playerEnum; @@ -233,10 +233,8 @@ public async Task GetTotalPlayerStatisticValueByTypeAndSeasonAsync(int play var tasks = schedule.Games.Select(async game => { // Count number of game events where player won a faceoff - var gameCenterPlayByPlay = await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(game.Id, cancellationToken); - return gameCenterPlayByPlay.Plays.Count(play => - { - return playerGameCenterStatistic switch + var gameCenterPlayByPlay = await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(game.Id, includeEventDateTime: false, cancellationToken); + return gameCenterPlayByPlay.Plays.Count(play => playerGameCenterStatistic switch { PlayerGameCenterStatistic.FaceOffWon => play.TypeDescKey == "faceoff" && play.Details.WinningPlayerId == playerId, PlayerGameCenterStatistic.FaceOffLost => play.TypeDescKey == "faceoff" && play.Details.LosingPlayerId == playerId, @@ -250,8 +248,7 @@ public async Task GetTotalPlayerStatisticValueByTypeAndSeasonAsync(int play PlayerGameCenterStatistic.CommittedPenalty => play.TypeDescKey == "penalty" && play.Details.CommittedByPlayerId == playerId, PlayerGameCenterStatistic.Takeaway => play.TypeDescKey == "takeaway" && play.Details.PlayerId == playerId, _ => false, - }; - }); + }); }); // Wait for all tasks to complete @@ -317,7 +314,7 @@ public async Task GetTotalPlayerStatisticValueByTypeAndSeasonAsync(int play var tasks = schedule.Games.Select(async game => { // Count number of game events where player won a faceoff - var gameCenterPlayByPlay = await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(game.Id, cancellationToken); + var gameCenterPlayByPlay = await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(game.Id, includeEventDateTime: false, cancellationToken); var gameStatisticTotals = new Dictionary { { PlayerGameCenterStatistic.FaceOffWon, 0 }, @@ -411,7 +408,7 @@ public async Task GetTotalPlayerStatisticValueByTypeAndSeasonAsync(int play var tasks = schedule.Games.Select(async game => { // Count number of game events where player won a faceoff - var gameCenterPlayByPlay = await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(game.Id, cancellationToken); + var gameCenterPlayByPlay = await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(game.Id, includeEventDateTime: false, cancellationToken); var gameStatisticTotals = new Dictionary { { PlayerGameCenterStatistic.FaceOffWon, 0 }, @@ -519,7 +516,7 @@ public async Task { // Count number of game events where player won a faceoff - var gameCenterPlayByPlay = await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(game.Id, cancellationToken); + var gameCenterPlayByPlay = await _nhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(game.Id, includeEventDateTime: false, cancellationToken); gameCenterPlayByPlay.Plays.ForEach(play => { From ebf99a6444ea2aae98bcf94e0f8d8c41bda7edf1 Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Tue, 1 Oct 2024 21:58:53 -0400 Subject: [PATCH 03/14] Add gameType parameter to NhlApi methods Introduced a new `gameType` parameter to several methods in the `NhlApi` class and its interface `INhlStatisticsApi` to specify the type of game (e.g., Regular Season) for which statistics are requested. Updated method signatures to include `gameType` with a default value of `GameType.RegularSeason`: - `GetPlayerStatisticsBySeasonAndFilterExpressionAsync` - `GetGoalieStatisticsBySeasonAndFilterExpressionAsync` - `GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync` - `GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync` Modified endpoint URL construction to append the `gameTypeId` query parameter. Updated XML documentation comments and test methods in `StatisticsTests.cs` to reflect these changes. --- Nhl.Api.Tests/StatisticsTests.cs | 34 +++++++++++++------ Nhl.Api/Src/Api/NhlApi.cs | 20 ++++++----- .../Src/StatisticsApi/INhlStatisticsApi.cs | 12 ++++--- Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs | 20 ++++++----- 4 files changed, 55 insertions(+), 31 deletions(-) diff --git a/Nhl.Api.Tests/StatisticsTests.cs b/Nhl.Api.Tests/StatisticsTests.cs index 9a86c3e7..4b041ec2 100644 --- a/Nhl.Api.Tests/StatisticsTests.cs +++ b/Nhl.Api.Tests/StatisticsTests.cs @@ -1,5 +1,6 @@ using System.Collections.Concurrent; using System.Linq; +using System.Security.AccessControl; using System.Threading; using Newtonsoft.Json; using Nhl.Api.Enumerations.Game; @@ -1305,9 +1306,10 @@ public async Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync_ValidInput int limit = 10; // Example limit int offsetStart = 0; // Example offset CancellationToken cancellationToken = default; + var gameType = GameType.RegularSeason; // Act - var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, cancellationToken); + var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken); // Assert Assert.IsNotNull(result); @@ -1322,13 +1324,14 @@ public async Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync_NullSeason string seasonYear = null; var expressionPlayerFilter = ExpressionPlayerFilter.Empty; PlayerStatisticsFilter playerStatisticsFilterToSortBy = PlayerStatisticsFilter.Points; - int limit = 10; int offsetStart = 0; CancellationToken cancellationToken = default; + var gameType = GameType.RegularSeason; + // Act & Assert - await Assert.ThrowsExceptionAsync(() => nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, cancellationToken)); + await Assert.ThrowsExceptionAsync(() => nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken)); } [TestMethodWithRetry(RetryCount = 5)] @@ -1342,9 +1345,10 @@ public async Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync_NullPlayer int limit = 10; int offsetStart = 0; CancellationToken cancellationToken = default; + var gameType = GameType.RegularSeason; // Act & Assert - await Assert.ThrowsExceptionAsync(() => nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, cancellationToken)); + await Assert.ThrowsExceptionAsync(() => nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken)); } [TestMethodWithRetry(RetryCount = 5)] @@ -1358,9 +1362,11 @@ public async Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync_InvalidLim int limit = -5; // Invalid limit int offsetStart = 0; CancellationToken cancellationToken = default; + var gameType = GameType.RegularSeason; + // Act & Assert - await Assert.ThrowsExceptionAsync(() => nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, cancellationToken)); + await Assert.ThrowsExceptionAsync(() => nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken)); } [TestMethodWithRetry(RetryCount = 5)] @@ -1374,9 +1380,10 @@ public async Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync_InvalidOff int limit = 10; int offsetStart = -3; // Invalid offset CancellationToken cancellationToken = default; + var gameType = GameType.RegularSeason; // Act & Assert - await Assert.ThrowsExceptionAsync(() => nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, cancellationToken)); + await Assert.ThrowsExceptionAsync(() => nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken)); } @@ -1388,13 +1395,14 @@ public async Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync_NullSeason string seasonYear = null; var expressionPlayerFilter = ExpressionGoalieFilter.Empty; GoalieStatisticsFilter playerStatisticsFilterToSortBy = GoalieStatisticsFilter.Wins; - int limit = 10; int offsetStart = 0; CancellationToken cancellationToken = default; + var gameType = GameType.RegularSeason; + // Act & Assert - await Assert.ThrowsExceptionAsync(() => nhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, cancellationToken)); + await Assert.ThrowsExceptionAsync(() => nhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken)); } [TestMethodWithRetry(RetryCount = 5)] @@ -1408,9 +1416,10 @@ public async Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync_NullPlayer int limit = 10; int offsetStart = 0; CancellationToken cancellationToken = default; + var gameType = GameType.RegularSeason; // Act & Assert - await Assert.ThrowsExceptionAsync(() => nhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, cancellationToken)); + await Assert.ThrowsExceptionAsync(() => nhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken)); } [TestMethodWithRetry(RetryCount = 5)] @@ -1424,9 +1433,10 @@ public async Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync_InvalidLim int limit = -5; // Invalid limit int offsetStart = 0; CancellationToken cancellationToken = default; + var gameType = GameType.RegularSeason; // Act & Assert - await Assert.ThrowsExceptionAsync(() => nhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, cancellationToken)); + await Assert.ThrowsExceptionAsync(() => nhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken)); } [TestMethodWithRetry(RetryCount = 5)] @@ -1440,8 +1450,10 @@ public async Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync_InvalidOff int limit = 10; int offsetStart = -3; // Invalid offset CancellationToken cancellationToken = default; + var gameType = GameType.RegularSeason; + // Act & Assert - await Assert.ThrowsExceptionAsync(() => nhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, cancellationToken)); + await Assert.ThrowsExceptionAsync(() => nhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken)); } } diff --git a/Nhl.Api/Src/Api/NhlApi.cs b/Nhl.Api/Src/Api/NhlApi.cs index 040b4715..d2e67043 100644 --- a/Nhl.Api/Src/Api/NhlApi.cs +++ b/Nhl.Api/Src/Api/NhlApi.cs @@ -663,10 +663,11 @@ public async TaskThe player real-time statistics filter to sort the player statistics by, see for more information on valid player statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL player statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL real-time player game center statistics for players matching the filter expression for the specified season. - public async Task GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerRealtimeStatisticsFilter playerRealtimeStatisticsFilterToSortBy = PlayerRealtimeStatisticsFilter.OvertimeGoals, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default) => - await _nhlStatisticsApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerRealtimeStatisticsFilterToSortBy, limit, offsetStart, cancellationToken); + public async Task GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerRealtimeStatisticsFilter playerRealtimeStatisticsFilterToSortBy = PlayerRealtimeStatisticsFilter.OvertimeGoals, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default) => + await _nhlStatisticsApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerRealtimeStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken); /// /// Returns all the NHL time-on-ice player game center statistics for players matching the provided filter expression for a specified season, including even-strength time on ice, overtime time on ice, time on ice per game, and more @@ -676,10 +677,11 @@ public async Task GetRealtimePlayerStatist /// The player time-on-ice statistics filter to sort the player statistics by, see for more information on valid player statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL player statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL time-on-ice player game center statistics for players matching the filter expression for the specified season. - public async Task GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerTimeOnIceStatisticsFilter playerTimeOnIceStatisticsFilterToSortBy = PlayerTimeOnIceStatisticsFilter.TimeOnIce, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default) => - await _nhlStatisticsApi.GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerTimeOnIceStatisticsFilterToSortBy, limit, offsetStart, cancellationToken); + public async Task GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerTimeOnIceStatisticsFilter playerTimeOnIceStatisticsFilterToSortBy = PlayerTimeOnIceStatisticsFilter.TimeOnIce, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default) => + await _nhlStatisticsApi.GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerTimeOnIceStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken); /// /// Returns all the NHL player game center statistics for a specific player for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more @@ -689,10 +691,11 @@ public async Task GetTimeOnIcePlayerStati /// The player statistics filter to sort the player statistics by, see for more information on valid player statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL player statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL player game center statistics for a specific player for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more - public async Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerStatisticsFilter playerStatisticsFilterToSortBy = PlayerStatisticsFilter.Points, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default) => - await _nhlStatisticsApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, cancellationToken); + public async Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerStatisticsFilter playerStatisticsFilterToSortBy = PlayerStatisticsFilter.Points, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default) => + await _nhlStatisticsApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionPlayerFilter, playerStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken); /// /// Returns all the NHL goalie statistics for a specific player for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more @@ -702,10 +705,11 @@ public async Task GetPlayerStatisticsBySeasonAndFi /// The goalie statistics filter to sort the goalie statistics by, see for more information on valid goalie statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL goalie statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL goalie statistics for a specific goalie for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more - public async Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionGoalieFilter expressionGoalieFilter, GoalieStatisticsFilter goalieStatisticsFilterToSortBy = GoalieStatisticsFilter.Wins, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default) => - await _nhlStatisticsApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionGoalieFilter, goalieStatisticsFilterToSortBy, limit, offsetStart, cancellationToken); + public async Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionGoalieFilter expressionGoalieFilter, GoalieStatisticsFilter goalieStatisticsFilterToSortBy = GoalieStatisticsFilter.Wins, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default) => + await _nhlStatisticsApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionGoalieFilter, goalieStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken); /// /// Returns the NHL game direct box score including information such as summaries, linescores, shots by period and more diff --git a/Nhl.Api/Src/StatisticsApi/INhlStatisticsApi.cs b/Nhl.Api/Src/StatisticsApi/INhlStatisticsApi.cs index 2b182d18..6d2ab418 100644 --- a/Nhl.Api/Src/StatisticsApi/INhlStatisticsApi.cs +++ b/Nhl.Api/Src/StatisticsApi/INhlStatisticsApi.cs @@ -122,9 +122,10 @@ public interface INhlStatisticsApi /// The player statistics filter to sort the player statistics by, see for more information on valid player statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL player statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL player game center statistics for a specific player for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more - public Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerStatisticsFilter playerStatisticsFilterToSortBy = PlayerStatisticsFilter.Points, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default); + public Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerStatisticsFilter playerStatisticsFilterToSortBy = PlayerStatisticsFilter.Points, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default); /// /// Returns all the NHL goalie statistics for a specific player for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more @@ -134,9 +135,10 @@ public interface INhlStatisticsApi /// The goalie statistics filter to sort the goalie statistics by, see for more information on valid goalie statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL goalie statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL goalie statistics for a specific goalie for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more - public Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionGoalieFilter expressionGoalieFilter, GoalieStatisticsFilter goalieStatisticsFilterToSortBy = GoalieStatisticsFilter.Wins, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default); + public Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionGoalieFilter expressionGoalieFilter, GoalieStatisticsFilter goalieStatisticsFilterToSortBy = GoalieStatisticsFilter.Wins, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default); /// /// Returns all the NHL real time player game center statistics for a specific player for a specific season including face off percentage, points per game, overtime goals, short handed points, power play points, shooting percentage, shots, time on ice per game and more @@ -146,9 +148,10 @@ public interface INhlStatisticsApi /// The player statistics filter to sort the player statistics by, see for more information on valid player statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL player statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL player game center statistics for a specific player for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more - public Task GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerRealtimeStatisticsFilter playerRealtimeStatisticsFilterToSortBy = PlayerRealtimeStatisticsFilter.OvertimeGoals, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default); + public Task GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerRealtimeStatisticsFilter playerRealtimeStatisticsFilterToSortBy = PlayerRealtimeStatisticsFilter.OvertimeGoals, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default); /// /// Returns all the NHL time on ice player game center statistics for a specific player for a specific season including even time on ice, overtime time on ice, over time on ice per over time game time on ice per game and more @@ -158,8 +161,9 @@ public interface INhlStatisticsApi /// The player statistics filter to sort the player statistics by, see for more information on valid player statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL player statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL player time on ice statistics for a specific season including even time on ice, overtime time on ice, time on ice per game, and more - public Task GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerTimeOnIceStatisticsFilter playerTimeOnIceStatisticsFilterToSortBy = PlayerTimeOnIceStatisticsFilter.EvenTimeOnIce, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default); + public Task GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerTimeOnIceStatisticsFilter playerTimeOnIceStatisticsFilterToSortBy = PlayerTimeOnIceStatisticsFilter.EvenTimeOnIce, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default); } diff --git a/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs b/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs index ca314f38..47a3cdb0 100644 --- a/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs +++ b/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs @@ -539,9 +539,10 @@ public async TaskThe player statistics filter to sort the player statistics by, see for more information on valid player statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL player statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL player game center statistics for a specific player for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more - public async Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerStatisticsFilter playerStatisticsFilterToSortBy = PlayerStatisticsFilter.Points, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default) + public async Task GetPlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerStatisticsFilter playerStatisticsFilterToSortBy = PlayerStatisticsFilter.Points, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(seasonYear)) { @@ -564,7 +565,7 @@ public async Task GetPlayerStatisticsBySeasonAndFi throw new ArgumentException("Offset start must be greater than or equal to 0"); } - var endpoint = new StringBuilder($"/skater/summary?cayenneExp=seasonId={seasonYear}&limit={limit}&start={offsetStart}&sort={playerStatisticsFilterToSortBy.GetEnumMemberValue()}"); + var endpoint = new StringBuilder($"/skater/summary?cayenneExp=seasonId={seasonYear}&limit={limit}&start={offsetStart}&sort={playerStatisticsFilterToSortBy.GetEnumMemberValue()}&gameTypeId={(int)gameType}"); if (expressionPlayerFilter.IsValidExpression) { endpoint.Append($"&{expressionPlayerFilter}"); @@ -581,9 +582,10 @@ public async Task GetPlayerStatisticsBySeasonAndFi /// The goalie statistics filter to sort the goalie statistics by, see for more information on valid goalie statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL goalie statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL goalie statistics for a specific goalie for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more - public async Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionGoalieFilter expressionGoalieFilter, GoalieStatisticsFilter goalieStatisticsFilterToSortBy = GoalieStatisticsFilter.Wins, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default) + public async Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionGoalieFilter expressionGoalieFilter, GoalieStatisticsFilter goalieStatisticsFilterToSortBy = GoalieStatisticsFilter.Wins, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(seasonYear)) { @@ -606,7 +608,7 @@ public async Task GetGoalieStatisticsBySeasonAndFi throw new ArgumentException("Offset start must be greater than or equal to 0"); } - var endpoint = new StringBuilder($"/goalie/summary?cayenneExp=seasonId={seasonYear}&limit={limit}&start={offsetStart}&sort={goalieStatisticsFilterToSortBy.GetEnumMemberValue()}"); + var endpoint = new StringBuilder($"/goalie/summary?cayenneExp=seasonId={seasonYear}&limit={limit}&start={offsetStart}&sort={goalieStatisticsFilterToSortBy.GetEnumMemberValue()}&gameTypeId={(int)gameType}"); if (expressionGoalieFilter.IsValidExpression) { endpoint.Append($"&{expressionGoalieFilter}"); @@ -623,9 +625,10 @@ public async Task GetGoalieStatisticsBySeasonAndFi /// The player statistics filter to sort the player statistics by, see for more information on valid player statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL player statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL player game center statistics for a specific player for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more - public async Task GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerRealtimeStatisticsFilter playerRealtimeStatisticsFilterToSortBy = PlayerRealtimeStatisticsFilter.OvertimeGoals, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default) + public async Task GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerRealtimeStatisticsFilter playerRealtimeStatisticsFilterToSortBy = PlayerRealtimeStatisticsFilter.OvertimeGoals, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(seasonYear)) { @@ -648,7 +651,7 @@ public async Task GetRealtimePlayerStatist throw new ArgumentException("Offset start must be greater than or equal to 0"); } - var endpoint = new StringBuilder($"/skater/realtime?cayenneExp=seasonId={seasonYear}&limit={limit}&start={offsetStart}&sort={playerRealtimeStatisticsFilterToSortBy.GetEnumMemberValue()}"); + var endpoint = new StringBuilder($"/skater/realtime?cayenneExp=seasonId={seasonYear}&limit={limit}&start={offsetStart}&sort={playerRealtimeStatisticsFilterToSortBy.GetEnumMemberValue()}&gameTypeId={(int)gameType}"); if (expressionPlayerFilter.IsValidExpression) { endpoint.Append($"&{expressionPlayerFilter}"); @@ -665,9 +668,10 @@ public async Task GetRealtimePlayerStatist /// The player statistics filter to sort the player statistics by, see for more information on valid player statistics filters /// The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results /// The offset to start the results from when reviewing the NHL player statistics + /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL player game center statistics for a specific player for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more - public async Task GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerTimeOnIceStatisticsFilter playerTimeOnIceStatisticsFilterToSortBy = PlayerTimeOnIceStatisticsFilter.TimeOnIce, int limit = -1, int offsetStart = 0, CancellationToken cancellationToken = default) + public async Task GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionPlayerFilter expressionPlayerFilter, PlayerTimeOnIceStatisticsFilter playerTimeOnIceStatisticsFilterToSortBy = PlayerTimeOnIceStatisticsFilter.TimeOnIce, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(seasonYear)) { @@ -690,7 +694,7 @@ public async Task GetTimeOnIcePlayerStati throw new ArgumentException("Offset start must be greater than or equal to 0"); } - var endpoint = new StringBuilder($"/skater/timeonice?cayenneExp=seasonId={seasonYear}&limit={limit}&start={offsetStart}&sort={playerTimeOnIceStatisticsFilterToSortBy.GetEnumMemberValue()}"); + var endpoint = new StringBuilder($"/skater/timeonice?cayenneExp=seasonId={seasonYear}&limit={limit}&start={offsetStart}&sort={playerTimeOnIceStatisticsFilterToSortBy.GetEnumMemberValue()}&gameTypeId={(int)gameType}"); if (expressionPlayerFilter.IsValidExpression) { endpoint.Append($"&{expressionPlayerFilter}"); From 965bfe5281f09032939c3a9d76d65beb56fdc4ca Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Wed, 2 Oct 2024 14:09:20 -0400 Subject: [PATCH 04/14] Increased timeouts, rename methods, and improve play logic Made `EstimatedDateTimeOfPlay` nullable in `GameCenterPlay`. Renamed methods for clarity: - `AddDateTimeOfPlayForEachPlay` to `AddEstimatedDateTimeOfPlayForEachPlay` in `INhlGameService` and `NhlGameService`. Updated `NhlGameApi` to use the renamed method. Improved logic and comments in `NhlGameService` for estimating play time. --- Nhl.Api.Common/Http/NhlApiWebHttpClient.cs | 2 +- Nhl.Api.Common/Http/NhlCmsHttpClient.cs | 4 +- Nhl.Api.Common/Http/NhlEApiHttpClient.cs | 4 +- .../Http/NhlShiftChartHttpClient.cs | 2 +- .../Http/NhlStaticAssetsApiHttpClient.cs | 2 +- .../Http/NhlSuggestionApiHttpClient.cs | 2 +- .../Models/Game/GameCenterPlayByPlay.cs | 2 +- Nhl.Api.Domain/Services/NhlGameService.cs | 71 ++++++++++++------- Nhl.Api/Src/GameApi/NhlGameApi.cs | 2 +- 9 files changed, 56 insertions(+), 35 deletions(-) diff --git a/Nhl.Api.Common/Http/NhlApiWebHttpClient.cs b/Nhl.Api.Common/Http/NhlApiWebHttpClient.cs index 430d8bd1..76303d35 100644 --- a/Nhl.Api.Common/Http/NhlApiWebHttpClient.cs +++ b/Nhl.Api.Common/Http/NhlApiWebHttpClient.cs @@ -20,7 +20,7 @@ public class NhlApiWebHttpClient : NhlApiHttpClient /// /// The dedicated NHL web api HTTP Client for the Nhl.Api /// - public NhlApiWebHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: "v1", timeoutInSeconds: 30) + public NhlApiWebHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: "v1", timeoutInSeconds: 60) { } diff --git a/Nhl.Api.Common/Http/NhlCmsHttpClient.cs b/Nhl.Api.Common/Http/NhlCmsHttpClient.cs index b3656e5c..6358776c 100644 --- a/Nhl.Api.Common/Http/NhlCmsHttpClient.cs +++ b/Nhl.Api.Common/Http/NhlCmsHttpClient.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Net.Http; namespace Nhl.Api.Common.Http; @@ -18,7 +18,7 @@ public class NhlCmsHttpClient : NhlApiHttpClient /// /// The dedicated NHL HTTP client for NHL player images and content /// - public NhlCmsHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: string.Empty, timeoutInSeconds: 30) + public NhlCmsHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: string.Empty, timeoutInSeconds: 60) { } diff --git a/Nhl.Api.Common/Http/NhlEApiHttpClient.cs b/Nhl.Api.Common/Http/NhlEApiHttpClient.cs index 7248c3ad..831df5f2 100644 --- a/Nhl.Api.Common/Http/NhlEApiHttpClient.cs +++ b/Nhl.Api.Common/Http/NhlEApiHttpClient.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Net.Http; namespace Nhl.Api.Common.Http; @@ -19,7 +19,7 @@ public class NhlEApiHttpClient : NhlApiHttpClient /// /// The dedicated NHLe Api web api HTTP Client for the Nhl.Api /// - public NhlEApiHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: string.Empty, timeoutInSeconds: 30) + public NhlEApiHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: string.Empty, timeoutInSeconds: 60) { } diff --git a/Nhl.Api.Common/Http/NhlShiftChartHttpClient.cs b/Nhl.Api.Common/Http/NhlShiftChartHttpClient.cs index df2d7051..bf61667b 100644 --- a/Nhl.Api.Common/Http/NhlShiftChartHttpClient.cs +++ b/Nhl.Api.Common/Http/NhlShiftChartHttpClient.cs @@ -18,7 +18,7 @@ public class NhlShiftChartHttpClient : NhlApiHttpClient /// /// The dedicated NHL HTTP client for the shift charts for individual live game feeds /// - public NhlShiftChartHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: string.Empty, timeoutInSeconds: 30) + public NhlShiftChartHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: string.Empty, timeoutInSeconds: 60) { } diff --git a/Nhl.Api.Common/Http/NhlStaticAssetsApiHttpClient.cs b/Nhl.Api.Common/Http/NhlStaticAssetsApiHttpClient.cs index bcff75fe..1e038554 100644 --- a/Nhl.Api.Common/Http/NhlStaticAssetsApiHttpClient.cs +++ b/Nhl.Api.Common/Http/NhlStaticAssetsApiHttpClient.cs @@ -17,7 +17,7 @@ public class NhlStaticAssetsApiHttpClient : NhlApiHttpClient /// /// The dedicated NHL static assets HTTP Client for the Nhl.Api /// - public NhlStaticAssetsApiHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: string.Empty, timeoutInSeconds: 30) + public NhlStaticAssetsApiHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: string.Empty, timeoutInSeconds: 60) { } diff --git a/Nhl.Api.Common/Http/NhlSuggestionApiHttpClient.cs b/Nhl.Api.Common/Http/NhlSuggestionApiHttpClient.cs index 5c249d5d..368f74ab 100644 --- a/Nhl.Api.Common/Http/NhlSuggestionApiHttpClient.cs +++ b/Nhl.Api.Common/Http/NhlSuggestionApiHttpClient.cs @@ -18,7 +18,7 @@ public class NhlSuggestionApiHttpClient : NhlApiHttpClient /// /// The dedicated NHL HTTP Client for the NHL suggestion API /// - public NhlSuggestionApiHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: "v1", timeoutInSeconds: 30) + public NhlSuggestionApiHttpClient() : base(clientApiUri: ClientApiUrl, clientVersion: "v1", timeoutInSeconds: 60) { } diff --git a/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs b/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs index 8966e425..63a725bb 100644 --- a/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs +++ b/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs @@ -368,7 +368,7 @@ public class GameCenterPlay /// The estimated time of the play for the NHL game center play by play, these are not exact times and are close approximations of each game event
/// Example: 2024-01-13T20:12:23Z ///
- public DateTimeOffset EstimatedDateTimeOfPlay { get; set; } + public DateTimeOffset? EstimatedDateTimeOfPlay { get; set; } } /// diff --git a/Nhl.Api.Domain/Services/NhlGameService.cs b/Nhl.Api.Domain/Services/NhlGameService.cs index acd5ec91..21c92f13 100644 --- a/Nhl.Api.Domain/Services/NhlGameService.cs +++ b/Nhl.Api.Domain/Services/NhlGameService.cs @@ -20,7 +20,7 @@ public interface INhlGameService /// /// A game center play by play object /// All of the game center play by play information with the time of play for each play - Task AddDateTimeOfPlayForEachPlay(GameCenterPlayByPlay gameCenterPlayByPlay); + Task AddEstimatedDateTimeOfPlayForEachPlay(GameCenterPlayByPlay gameCenterPlayByPlay); } /// @@ -35,51 +35,67 @@ public class NhlGameService : INhlGameService /// /// A game center play by play object /// All of the game center play by play information with the time of play for each play - public async Task AddDateTimeOfPlayForEachPlay(GameCenterPlayByPlay gameCenterPlayByPlay) + public async Task AddEstimatedDateTimeOfPlayForEachPlay(GameCenterPlayByPlay gameCenterPlayByPlay) { var gameId = gameCenterPlayByPlay.Id.ToString(CultureInfo.InvariantCulture)[4..]; var scoreReport = await this._nhlScoresHtmlReportsApiHttpClient.GetStringAsync($"/{gameCenterPlayByPlay.Season}/PL{gameId}.HTM", default); - var regex = Regex.Matches(scoreReport, @"(?<=)Period(.*?)(?=)", RegexOptions.Compiled, TimeSpan.FromSeconds(5)).ToList(); + var timePeriodMatches = Regex.Matches(scoreReport, @"(?<=)Period(.*?)(?=)", RegexOptions.Compiled | RegexOptions.CultureInvariant, TimeSpan.FromSeconds(5)).ToList(); - if (string.IsNullOrWhiteSpace(scoreReport) || regex.Count == 0) + if (string.IsNullOrWhiteSpace(scoreReport) || timePeriodMatches.Count == 0) { try { + // Parse game start time and adjust for venue UTC offset var gameStart = DateTimeOffset.Parse($"{gameCenterPlayByPlay.StartTimeUTC}", CultureInfo.InvariantCulture); var timeSpanOffset = TimeSpan.Parse(gameCenterPlayByPlay.VenueUTCOffset, CultureInfo.InvariantCulture); - // Set offset - gameStart = gameStart.AddHours(timeSpanOffset.TotalHours); + gameStart = gameStart.AddHours(timeSpanOffset.TotalHours); // Adjust with venue UTC offset - // Set average delay in start time - gameStart = gameStart.Add(TimeSpan.FromMinutes(8.5)); + // Add average delay in start time (assuming game starts on average 8.5 minutes after scheduled time) + gameStart = gameStart.AddMinutes(8.5); - var averageTimeDelayInIntermission = TimeSpan.FromMinutes(18); - - // Average time of a period including stoppage - var timeOfPeriod = TimeSpan.FromMinutes(35); + // Constants based on estimated NHL standards + var averagePeriodDuration = TimeSpan.FromMinutes(42.5); // Average period duration including stoppages + var intermissionDuration = TimeSpan.FromMinutes(20); // Intermission duration + var overtimeIntermissionDuration = TimeSpan.FromMinutes(2.5); // Short break before OT + var maxRegularPeriods = 3; // Number of regular periods foreach (var play in gameCenterPlayByPlay.Plays) { var period = play.Period; var timeElapsed = TimeSpan.Zero; + var timeInPeriod = TimeSpan.ParseExact(play.TimeInPeriod, @"mm\:ss", CultureInfo.InvariantCulture); - if (period > 1) + if (period <= maxRegularPeriods) { - var regularPeriodTime = period <= 3 ? ((period - 1) * timeOfPeriod) : TimeSpan.FromMinutes(105); - var averageDelayInIntermission = period <= 3 ? ((period - 1) * averageTimeDelayInIntermission) : TimeSpan.FromMinutes(60); - timeElapsed += averageDelayInIntermission + regularPeriodTime; - } + // Regular periods + var completedPeriods = period - 1; + + // Total time from completed periods and intermissions + timeElapsed += completedPeriods * (averagePeriodDuration + intermissionDuration); - timeElapsed += TimeOnly.Parse($"00:{play.TimeInPeriod}", CultureInfo.InvariantCulture).ToTimeSpan(); - if (period > 3) + // Time elapsed within the current period + timeElapsed += timeInPeriod; + } + else { - timeElapsed += period * TimeSpan.FromMinutes(10); + // Overtime periods + // Time from regular periods and intermissions + timeElapsed += maxRegularPeriods * (averagePeriodDuration + intermissionDuration); + + // Add short break before overtime + timeElapsed += overtimeIntermissionDuration; + + // Time within overtime period + timeElapsed += timeInPeriod; } - timeElapsed += TimeSpan.FromSeconds(5); - play.EstimatedDateTimeOfPlay = gameStart.Add(timeElapsed); + // Calculate the estimated DateTime of the play + var estimatedDateTime = gameStart.Add(timeElapsed); + + // Assign estimated date time to play + play.EstimatedDateTimeOfPlay = estimatedDateTime; } } catch @@ -99,9 +115,9 @@ public async Task AddDateTimeOfPlayForEachPlay(GameCenterP { 5, [] }, }; - for (var i = 0; i < regex.Count; i++) + for (var i = 0; i < timePeriodMatches.Count; i++) { - var match = regex[i].Value; + var match = timePeriodMatches[i].Value; var value = Regex.Match(match, @"([0-9]{1,2}:[0-9]{2})", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(30)).Groups[0].Value; var time = TimeOnly.Parse($"{value} PM", CultureInfo.InvariantCulture); var dateTime = DateTime.Parse($"{gameCenterPlayByPlay.GameDate} {time} {gameCenterPlayByPlay.EasternUTCOffset}", CultureInfo.InvariantCulture); @@ -134,10 +150,15 @@ public async Task AddDateTimeOfPlayForEachPlay(GameCenterP { var startTime = startTimeOfEachPeriod[playsForPeriod.Key].FirstOrDefault(); var endTime = startTimeOfEachPeriod[playsForPeriod.Key].LastOrDefault(); + if (startTime == default || endTime == default) + { + continue; + } + var distanceBetweenPlays = endTime - startTime; var timeBetweenPlays = distanceBetweenPlays / playsForPeriod.Value.Count; - var multiplier = CalculateMultiplier(startTime, endTime, playsForPeriod.Value.Count); + var multiplier = this.CalculateMultiplier(startTime, endTime, playsForPeriod.Value.Count); for (var i = 0; i < playsForPeriod.Value.Count; i++) { var play = playsForPeriod.Value[i]; diff --git a/Nhl.Api/Src/GameApi/NhlGameApi.cs b/Nhl.Api/Src/GameApi/NhlGameApi.cs index 84503a9c..cfb3ea13 100644 --- a/Nhl.Api/Src/GameApi/NhlGameApi.cs +++ b/Nhl.Api/Src/GameApi/NhlGameApi.cs @@ -147,7 +147,7 @@ public async Task GetGameCenterPlayByPlayByGameIdAsync(int var gameCenterPlayByPlay = await _nhlApiWebHttpClient.GetAsync($"/gamecenter/{gameId}/play-by-play", cancellationToken); if (includeEventDateTime) { - gameCenterPlayByPlay = await _nhlGameService.AddDateTimeOfPlayForEachPlay(gameCenterPlayByPlay); + gameCenterPlayByPlay = await _nhlGameService.AddEstimatedDateTimeOfPlayForEachPlay(gameCenterPlayByPlay); } return gameCenterPlayByPlay; From 5e8c748e371be9fac8b68f55b722089b3a0f5c1b Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 4 Nov 2024 21:25:32 -0500 Subject: [PATCH 05/14] Add draft ranking methods and update team status handling Enhanced the codebase with several key updates: - Added new namespaces across multiple files for better organization. - Introduced `TeamActive` attribute in `TeamEnum` to indicate team status. - Removed the `Ranks` class and its properties. - Updated `GameCenterPlayByPlay` property documentation and default value. - Refactored test methods in `GameTests.cs` and `PlayerTests.cs` for improved validation. - Added `GetPlayerDraftRankingByYearAsync` method in `NhlApi.cs`, `INhlPlayerApi.cs`, and `NhlPlayerApi.cs` to fetch draft rankings. - Excluded `ArizonaCoyotes` from NHL teams for seasons 2024-2025 or later in `NhlStatisticsApi.cs`. - Introduced new classes to represent NHL draft player rankings and categories. --- .../Attributes/TeamActiveAttribute.cs | 19 +++ Nhl.Api.Common/Extensions/EnumExtensions.cs | 2 +- Nhl.Api.Domain/Enumerations/Team/TeamEnum.cs | 35 ++++ Nhl.Api.Domain/Models/Draft/DraftYear.cs | 2 +- .../Models/Draft/PlayerDraftRanking.cs | 160 ++++++++++++++++++ Nhl.Api.Domain/Models/Draft/Ranks.cs | 22 --- .../Models/Game/GameCenterPlayByPlay.cs | 10 +- Nhl.Api.Tests/GameTests.cs | 81 +++++---- Nhl.Api.Tests/PlayerTests.cs | 50 +++++- Nhl.Api/Src/Api/NhlApi.cs | 13 ++ Nhl.Api/Src/PlayerApi/INhlPlayerApi.cs | 13 +- Nhl.Api/Src/PlayerApi/NhlPlayerApi.cs | 27 ++- Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs | 12 +- 13 files changed, 368 insertions(+), 78 deletions(-) create mode 100644 Nhl.Api.Common/Attributes/TeamActiveAttribute.cs create mode 100644 Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs delete mode 100644 Nhl.Api.Domain/Models/Draft/Ranks.cs diff --git a/Nhl.Api.Common/Attributes/TeamActiveAttribute.cs b/Nhl.Api.Common/Attributes/TeamActiveAttribute.cs new file mode 100644 index 00000000..7de59499 --- /dev/null +++ b/Nhl.Api.Common/Attributes/TeamActiveAttribute.cs @@ -0,0 +1,19 @@ +using System; + +namespace Nhl.Api.Common.Attributes; + +/// +/// An enumeration to specifically mark NHL teams active or inactive +/// +/// +/// The constructor +/// +/// Whether an NHL team is active in the leauge +[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] +public class TeamActiveAttribute(bool isActive) : Attribute +{ + /// + /// Determines if the NHL team is currently active + /// + public bool IsActive { get; } = isActive; +} diff --git a/Nhl.Api.Common/Extensions/EnumExtensions.cs b/Nhl.Api.Common/Extensions/EnumExtensions.cs index 25f6e7f7..0743d80a 100644 --- a/Nhl.Api.Common/Extensions/EnumExtensions.cs +++ b/Nhl.Api.Common/Extensions/EnumExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Reflection; using System.Runtime.Serialization; diff --git a/Nhl.Api.Domain/Enumerations/Team/TeamEnum.cs b/Nhl.Api.Domain/Enumerations/Team/TeamEnum.cs index 3185661b..d2fec817 100644 --- a/Nhl.Api.Domain/Enumerations/Team/TeamEnum.cs +++ b/Nhl.Api.Domain/Enumerations/Team/TeamEnum.cs @@ -1,3 +1,5 @@ +using Nhl.Api.Common.Attributes; + namespace Nhl.Api.Models.Enumerations.Team; /// @@ -8,133 +10,166 @@ public enum TeamEnum /// /// New Jersey Devils /// + [TeamActive(true)] NewJerseyDevils = 1, /// /// New York Islanders /// + [TeamActive(true)] NewYorkIslanders = 2, /// /// New York Rangers /// + [TeamActive(true)] NewYorkRangers = 3, /// /// Philadelphia Flyers /// + [TeamActive(true)] PhiladelphiaFlyers = 4, /// /// Pittsburgh Penguins /// + [TeamActive(true)] PittsburghPenguins = 5, /// /// Boston Bruins /// + [TeamActive(true)] BostonBruins = 6, /// /// Buffalo Sabres /// + [TeamActive(true)] BuffaloSabres = 7, /// /// Montreal Canadiens /// + [TeamActive(true)] MontrealCanadiens = 8, /// /// Ottawa Senators /// + [TeamActive(true)] OttawaSenators = 9, /// /// Toronto Maple Leafs /// + [TeamActive(true)] TorontoMapleLeafs = 10, /// /// Carolina Hurricanes /// + [TeamActive(true)] CarolinaHurricanes = 12, /// /// Florida Panthers /// + [TeamActive(true)] FloridaPanthers = 13, /// /// Tampa Bay Lightning /// + [TeamActive(true)] TampaBayLightning = 14, /// /// Washington Capitals /// + [TeamActive(true)] WashingtonCapitals = 15, /// /// Chicago Blackhawks /// + [TeamActive(true)] ChicagoBlackhawks = 16, /// /// Detroit Red Wings /// + [TeamActive(true)] DetroitRedWings = 17, /// /// Nashville Predators /// + [TeamActive(true)] NashvillePredators = 18, /// /// St.Louis Blues /// + [TeamActive(true)] StLouisBlues = 19, /// /// Calgary Flames /// + [TeamActive(true)] CalgaryFlames = 20, /// /// Colorado Avalanche /// + [TeamActive(true)] ColoradoAvalanche = 21, /// /// Edmonton Oilers /// + [TeamActive(true)] EdmontonOilers = 22, /// /// Vancouver Canucks /// + [TeamActive(true)] VancouverCanucks = 23, /// /// Anaheim Ducks /// + [TeamActive(true)] AnaheimDucks = 24, /// /// Dallas Stars /// + [TeamActive(true)] DallasStars = 25, /// /// Los Angeles Kings /// + [TeamActive(true)] LosAngelesKings = 26, /// /// San Jose Sharks /// + [TeamActive(true)] SanJoseSharks = 28, /// /// Columbus Blue Jackets /// + [TeamActive(true)] ColumbusBlueJackets = 29, /// /// Minnesota Wild /// + [TeamActive(true)] MinnesotaWild = 30, /// /// Winnipeg Jets /// + [TeamActive(true)] WinnipegJets = 52, /// /// Arizona Coyotes /// + [TeamActive(false)] ArizonaCoyotes = 53, /// /// Vegas Golden Knights /// + [TeamActive(true)] VegasGoldenKnights = 54, /// /// Seattle Kraken /// + [TeamActive(true)] SeattleKraken = 55, /// /// Utah Hockey Club /// + [TeamActive(true)] UtahHockeyClub = 59 } diff --git a/Nhl.Api.Domain/Models/Draft/DraftYear.cs b/Nhl.Api.Domain/Models/Draft/DraftYear.cs index 24a67fbd..375d14db 100644 --- a/Nhl.Api.Domain/Models/Draft/DraftYear.cs +++ b/Nhl.Api.Domain/Models/Draft/DraftYear.cs @@ -1,4 +1,4 @@ - + namespace Nhl.Api.Models.Draft; /// diff --git a/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs b/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs new file mode 100644 index 00000000..5384ac70 --- /dev/null +++ b/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs @@ -0,0 +1,160 @@ +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace Nhl.Api.Models.Draft; + +/// +/// The NHL draft player category +/// +public class PlayerDraftCategory +{ + /// + /// The ID of the player draft category + /// + [JsonProperty("id")] + public int? Id { get; set; } + + /// + /// The name of the player draft category + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// The consumer key of the player draft category + /// + [JsonProperty("consumerKey")] + public string ConsumerKey { get; set; } +} + +/// +/// The NHL draft player ranking for each prospective player +/// +public class PlayerDraftRanking +{ + /// + /// The last name of the player + /// + [JsonProperty("lastName")] + public string LastName { get; set; } + + /// + /// The first name of the player + /// + [JsonProperty("firstName")] + public string FirstName { get; set; } + + /// + /// The position code of the player + /// + [JsonProperty("positionCode")] + public string PositionCode { get; set; } + + /// + /// The shooting or catching hand of the player + /// + [JsonProperty("shootsCatches")] + public string ShootsCatches { get; set; } + + /// + /// The height of the player in inches + /// + [JsonProperty("heightInInches")] + public int? HeightInInches { get; set; } + + /// + /// The weight of the player in pounds + /// + [JsonProperty("weightInPounds")] + public int? WeightInPounds { get; set; } + + /// + /// The last amateur club of the player + /// + [JsonProperty("lastAmateurClub")] + public string LastAmateurClub { get; set; } + + /// + /// The last amateur league of the player + /// + [JsonProperty("lastAmateurLeague")] + public string LastAmateurLeague { get; set; } + + /// + /// The birth date of the player + /// + [JsonProperty("birthDate")] + public string BirthDate { get; set; } + + /// + /// The birth city of the player + /// + [JsonProperty("birthCity")] + public string BirthCity { get; set; } + + /// + /// The birth state or province of the player + /// + [JsonProperty("birthStateProvince")] + public string BirthStateProvince { get; set; } + + /// + /// The birth country of the player + /// + [JsonProperty("birthCountry")] + public string BirthCountry { get; set; } + + /// + /// The midterm rank of the player + /// + [JsonProperty("midtermRank")] + public int? MidtermRank { get; set; } + + /// + /// The final rank of the player + /// + [JsonProperty("finalRank")] + public int? FinalRank { get; set; } +} + +/// +/// The NHL draft player draft year with all players and their information and rankings +/// +public class PlayerDraftYear +{ + /// + /// The draft year + /// + [JsonProperty("draftYear")] + public int? DraftYear { get; set; } + + /// + /// The category ID + /// + [JsonProperty("categoryId")] + public int? CategoryId { get; set; } + + /// + /// The category key + /// + [JsonProperty("categoryKey")] + public string? CategoryKey { get; set; } + + /// + /// The list of draft years + /// + [JsonProperty("draftYears")] + public List DraftYears { get; set; } = []; + + /// + /// The list of player draft categories + /// + [JsonProperty("categories")] + public List Categories { get; set; } = []; + + /// + /// The list of player draft rankings + /// + [JsonProperty("rankings")] + public List Rankings { get; set; } = []; +} diff --git a/Nhl.Api.Domain/Models/Draft/Ranks.cs b/Nhl.Api.Domain/Models/Draft/Ranks.cs deleted file mode 100644 index ea4bce13..00000000 --- a/Nhl.Api.Domain/Models/Draft/Ranks.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Newtonsoft.Json; - -namespace Nhl.Api.Models.Draft; -/// -/// NHL Prospect Ranks -/// -public class Ranks -{ - /// - /// The final rank for the NHL prospect
- /// Example: 1 - ///
- [JsonProperty("finalRank")] - public int FinalRank { get; set; } - - /// - /// The draft year for the NHL prospect
- /// Example: 2021 - ///
- [JsonProperty("draftYear")] - public int DraftYear { get; set; } -} diff --git a/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs b/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs index 63a725bb..14641d84 100644 --- a/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs +++ b/Nhl.Api.Domain/Models/Game/GameCenterPlayByPlay.cs @@ -365,10 +365,16 @@ public class GameCenterPlay public GameCenterDetails Details { get; set; } /// - /// The estimated time of the play for the NHL game center play by play, these are not exact times and are close approximations of each game event
+ /// The estimated time of the play for the NHL game center play by play, these are not exact times and are close approximations of each game event within 1 (one) hour of the event occurring
+ /// this is due to some factors which include but are not limited to:
+ /// + /// An active NHL game currently in progress + /// No score sheet or report available for correct start and end times of periods + /// No public recordings of the end time of the game/period + /// /// Example: 2024-01-13T20:12:23Z ///
- public DateTimeOffset? EstimatedDateTimeOfPlay { get; set; } + public DateTimeOffset? EstimatedDateTimeOfPlay { get; set; } = null; } /// diff --git a/Nhl.Api.Tests/GameTests.cs b/Nhl.Api.Tests/GameTests.cs index 58c99259..9666b092 100644 --- a/Nhl.Api.Tests/GameTests.cs +++ b/Nhl.Api.Tests/GameTests.cs @@ -208,48 +208,45 @@ public async Task GetGameMetadataByGameIdAsync_Return_Valid_Information(int game } [TestMethodWithRetry(RetryCount = 5)] - public async Task NhlScoresHtmlReportsApiHttpClient_Can_Parse_Html_Report_For_Start_End_Period_Times() + [DataRow(2000020004)] + [DataRow(2001020004)] + [DataRow(2002020004)] + [DataRow(2003020004)] + [DataRow(2005020037)] + [DataRow(2006020046)] + [DataRow(2007020055)] + [DataRow(2008020074)] + [DataRow(2009020090)] + [DataRow(2010020090)] + [DataRow(2011020090)] + [DataRow(2012020090)] + [DataRow(2013020090)] + [DataRow(2014020090)] + [DataRow(2015020090)] + [DataRow(2016020090)] + [DataRow(2017020090)] + [DataRow(2018020090)] + [DataRow(2023010110)] + [DataRow(2019020090)] + [DataRow(2020020090)] + [DataRow(2021020090)] + [DataRow(2022020090)] + [DataRow(2023020090)] + public async Task GetGameCenterPlayByPlayByGameIdAsync_Returns_Valid_Estimated_DateTime_Of_Play_Information(int gameId) { - var dictionary = new Dictionary> - { - { "P1", new List() }, - { "P2", new List() }, - { "P3", new List() }, - { "OT", new List() }, - { "SH", new List() }, - }; - - var httpClient = new NhlScoresHtmlReportsApiHttpClient(); - var gameReport = await httpClient.GetStringAsync("/20232024/PL020206.HTM"); - - var regex = Regex.Matches(gameReport, @"(?<=)Period(.*?)(?=)", RegexOptions.Compiled, TimeSpan.FromSeconds(30)).ToList(); - - for (var i = 0; i < regex.Count; i++) - { - var match = regex[i].Value; - var value = Regex.Match(match, @"([0-9]{1,2}:[0-9]{2})", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(30)).Groups[0].Value; - var time = TimeOnly.Parse($"{value} PM"); - - if (i <= 1) - { - dictionary["P1"].Add(time); - } - else if (i >= 2 && i <= 3) - { - dictionary["P2"].Add(time); - } - else if (i >= 4 && i <= 5) - { - dictionary["P3"].Add(time); - } - else if (i >= 6 && i <= 7) - { - dictionary["OT"].Add(time); - } - else if (i <= 9) - { - dictionary["SH"].Add(time); - } - } + // Arrange + await using var nhlApi = new NhlApi(); + + // Act + var results = await nhlApi.GetGameCenterPlayByPlayByGameIdAsync(gameId, includeEventDateTime: true); + + // Assert + Assert.IsNotNull(results); + Assert.IsNotNull(results.GameDate); + Assert.IsNotNull(results.GameType); + Assert.IsNotNull(results.Id); + Assert.IsNotNull(results.Clock); + Assert.IsNotNull(results.Plays); + Assert.IsTrue(results.Plays.All(p => p.EstimatedDateTimeOfPlay.HasValue)); } } diff --git a/Nhl.Api.Tests/PlayerTests.cs b/Nhl.Api.Tests/PlayerTests.cs index 78db2432..9a1b8156 100644 --- a/Nhl.Api.Tests/PlayerTests.cs +++ b/Nhl.Api.Tests/PlayerTests.cs @@ -31,7 +31,7 @@ public async Task SearchAllPlayersAsync_Returns_Valid_Results(string query, int Assert.AreEqual("Brantford", playerSearchResult.BirthCity); Assert.AreEqual("CAN", playerSearchResult.BirthCountry); Assert.AreEqual("Canada", playerSearchResult.FullBirthCountry); - Assert.AreEqual("Ontario", playerSearchResult.BirthProvinceState); + Assert.AreEqual("ON", playerSearchResult.BirthProvinceState); Assert.AreEqual("Wayne", playerSearchResult.FirstName); Assert.AreEqual("Gretzky", playerSearchResult.LastName); Assert.AreEqual("NYR", playerSearchResult.LastTeamAbbreviation); @@ -57,7 +57,7 @@ public async Task SearchAllPlayersAsync_Returns_Valid_Results(string query, int Assert.AreEqual("Richmond Hill", playerSearchResult.BirthCity); Assert.AreEqual("CAN", playerSearchResult.BirthCountry); Assert.AreEqual("Canada", playerSearchResult.FullBirthCountry); - Assert.AreEqual("Ontario", playerSearchResult.BirthProvinceState); + Assert.AreEqual("ON", playerSearchResult.BirthProvinceState); Assert.AreEqual("Connor", playerSearchResult.FirstName); Assert.AreEqual("McDavid", playerSearchResult.LastName); Assert.AreEqual(true, playerSearchResult.IsActive); @@ -65,6 +65,9 @@ public async Task SearchAllPlayersAsync_Returns_Valid_Results(string query, int Assert.AreEqual("6\u00271\"", playerSearchResult.Height); Assert.AreEqual(97, playerSearchResult.PlayerNumber); break; + + default: + break; } } @@ -121,7 +124,7 @@ public async Task SearchAllActivePlayersAsync_Returns_Valid_Information(string q Assert.AreEqual("Richmond Hill", playerSearchResult.BirthCity); Assert.AreEqual("CAN", playerSearchResult.BirthCountry); Assert.AreEqual("Canada", playerSearchResult.FullBirthCountry); - Assert.AreEqual("Ontario", playerSearchResult.BirthProvinceState); + Assert.AreEqual("ON", playerSearchResult.BirthProvinceState); Assert.AreEqual("Connor", playerSearchResult.FirstName); Assert.AreEqual("McDavid", playerSearchResult.LastName); Assert.AreEqual(true, playerSearchResult.IsActive); @@ -879,6 +882,47 @@ public async Task GetAllPlayersAsync_Returns_All_Players() Assert.IsTrue(players.Count > 22000); } + [TestMethodWithRetry(RetryCount = 5)] + [DataRow("2008")] + [DataRow("2009")] + [DataRow("2010")] + [DataRow("2011")] + [DataRow("2012")] + [DataRow("2013")] + [DataRow("2014")] + [DataRow("2015")] + [DataRow("2016")] + [DataRow("2017")] + [DataRow("2018")] + [DataRow("2019")] + [DataRow("2020")] + [DataRow("2021")] + [DataRow("2022")] + [DataRow("2023")] + [DataRow("2024")] + public async Task GetPlayerDraftRankingByYearAsync_Returns_Correct_Draft_Ranking_Information(string seasonYear) + { + // Arrange + await using var nhlApi = new NhlApi(); + + // Act + var draft = await nhlApi.GetPlayerDraftRankingByYearAsync(seasonYear); + + // Assert + Assert.IsNotNull(draft); + Assert.IsNotNull(draft.Rankings); + Assert.IsTrue(draft.Rankings.Count > 0); + + foreach (var playerDraftRanking in draft.Rankings) + { + Assert.IsNotNull(playerDraftRanking); + Assert.IsNotNull(playerDraftRanking.FirstName); + Assert.IsNotNull(playerDraftRanking.LastName); + Assert.IsNotNull(playerDraftRanking.HeightInInches); + Assert.IsNotNull(playerDraftRanking.WeightInPounds); + } + + } [TestMethodWithRetry(RetryCount = 25)] public async Task PlayerEnumFileGeneratorHelper_Returns_Valid_Content() => diff --git a/Nhl.Api/Src/Api/NhlApi.cs b/Nhl.Api/Src/Api/NhlApi.cs index d2e67043..77dcff57 100644 --- a/Nhl.Api/Src/Api/NhlApi.cs +++ b/Nhl.Api/Src/Api/NhlApi.cs @@ -1,3 +1,5 @@ +using Nhl.Api.Models.Draft; + namespace Nhl.Api; /// @@ -719,6 +721,17 @@ public async Task GetGoalieStatisticsBySeasonAndFi /// Returns the NHL game direct box score including information such as summaries, linescores, shots by period and more public async Task GetBoxscoreByGameIdAsync(int gameId, CancellationToken cancellationToken = default) => await _nhlGameApi.GetBoxscoreByGameIdAsync(gameId, cancellationToken); + + /// + /// Returns the NHL draft ranking by the specified year and starting position for the draft year + /// + /// The NHL draft year + /// The starting position of the NHL draft by the year + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation + /// Returns the NHL draft ranking by the specified year and starting position for the draft year + public async Task GetPlayerDraftRankingByYearAsync(string seasonYear, int startingPosition = 1, CancellationToken cancellationToken = default) => + await _nhlPlayerApi.GetPlayerDraftRankingByYearAsync(seasonYear, startingPosition, cancellationToken); + /// /// Releases and disposes all unused or garbage collected resources for the Nhl.Api /// diff --git a/Nhl.Api/Src/PlayerApi/INhlPlayerApi.cs b/Nhl.Api/Src/PlayerApi/INhlPlayerApi.cs index 61cbc489..2ecccad2 100644 --- a/Nhl.Api/Src/PlayerApi/INhlPlayerApi.cs +++ b/Nhl.Api/Src/PlayerApi/INhlPlayerApi.cs @@ -1,4 +1,6 @@ -namespace Nhl.Api; +using Nhl.Api.Models.Draft; + +namespace Nhl.Api; /// /// The official unofficial NHL Player API providing various NHL information about players, draft prospects, rosters and more @@ -128,4 +130,13 @@ public interface INhlPlayerApi : IDisposable /// Returns all the NHL players to ever play in the NHL public Task> GetAllPlayersAsync(CancellationToken cancellationToken = default); + /// + /// Returns the NHL draft ranking by the specified year and starting position for the draft year + /// + /// The NHL draft year + /// The starting position of the NHL draft by the year + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation + /// Returns the NHL draft ranking by the specified year and starting position for the draft year + public Task GetPlayerDraftRankingByYearAsync(string seasonYear, int startingPosition = 1, CancellationToken cancellationToken = default); + } diff --git a/Nhl.Api/Src/PlayerApi/NhlPlayerApi.cs b/Nhl.Api/Src/PlayerApi/NhlPlayerApi.cs index 6389728a..539516fc 100644 --- a/Nhl.Api/Src/PlayerApi/NhlPlayerApi.cs +++ b/Nhl.Api/Src/PlayerApi/NhlPlayerApi.cs @@ -1,4 +1,5 @@ using Nhl.Api.Common.Services; +using Nhl.Api.Models.Draft; using Nhl.Api.Services; namespace Nhl.Api; @@ -96,7 +97,7 @@ public async Task GetPlayerHeadshotImageAsync(int playerId, string seaso throw new ArgumentException($"The {nameof(seasonYear)} parameter must be in the format of yyyyyyyy, example: 20232024", nameof(seasonYear)); } - var playerInformation = await GetPlayerInformationAsync(playerId, cancellationToken); + var playerInformation = await this.GetPlayerInformationAsync(playerId, cancellationToken); var teamName = playerInformation.SeasonTotals.FirstOrDefault(x => x.Season == int.Parse(seasonYear))?.TeamName?.Default; if (string.IsNullOrWhiteSpace(teamName)) { @@ -282,10 +283,32 @@ public async Task> GetAllPlayersAsync(CancellationT return (await Task.WhenAll(playerSearchResultsTasks)).SelectMany(playerData => playerData.Data).ToList(); } + /// + /// Returns the NHL draft ranking by the specified year and starting position for the draft year + /// + /// The NHL draft year + /// The starting position of the NHL draft by the year + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation + /// Returns the NHL draft ranking by the specified year and starting position for the draft year + public async Task GetPlayerDraftRankingByYearAsync(string seasonYear, int startingPosition = 1, CancellationToken cancellationToken = default) + { + if (string.IsNullOrWhiteSpace(seasonYear)) + { + throw new ArgumentException($"The {nameof(seasonYear)} parameter is required", nameof(seasonYear)); + } + + if (startingPosition < 1) + { + throw new ArgumentException($"The {nameof(startingPosition)} parameter must be greater than 0", nameof(startingPosition)); + } + + return await _nhlApiWebHttpClient.GetAsync($"/draft/rankings/{seasonYear}/{startingPosition}", cancellationToken); + + } + /// /// Disposes and releases all unneeded resources for the NHL player API /// - /// public void Dispose() { _cachingService?.Dispose(); diff --git a/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs b/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs index 47a3cdb0..fee0413c 100644 --- a/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs +++ b/Nhl.Api/Src/StatisticsApi/NhlStatisticsApi.cs @@ -1,3 +1,4 @@ +using System.Globalization; using Nhl.Api.Services; namespace Nhl.Api; @@ -459,13 +460,16 @@ public async Task().ToList(); - var teamRosterTasks = allNhlTeams.Select(async (team) => + // Get all NHL Teams + if (int.Parse(seasonYear, CultureInfo.InvariantCulture) >= int.Parse(SeasonYear.season20242025, CultureInfo.InvariantCulture)) { - return await _nhlLeagueApi.GetTeamRosterBySeasonYearAsync(team, seasonYear, cancellationToken); - }); + // They are no longer in the NHL + allNhlTeams.Remove(TeamEnum.ArizonaCoyotes); + } + + var teamRosterTasks = allNhlTeams.Select(async (team) => await _nhlLeagueApi.GetTeamRosterBySeasonYearAsync(team, seasonYear, cancellationToken)); // Get all team rosters var allRoster = await Task.WhenAll(teamRosterTasks); From bd034fafb105d40f64fd56a608bb5a6b52b6621a Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 4 Nov 2024 21:31:22 -0500 Subject: [PATCH 06/14] Minor refactoring and revisions Refactor and enhance HTTP clients and season generation - Change default timeout in NhlApiHttpClient to 60 seconds. - Add System.Net.Http directive to NhlSuggestionApiHttpClient.cs. - Include System.Linq in SeasonYears.cs for LINQ operations. - Refactor AllSeasons in SeasonYear to use GenerateAllSeasons. - Update NhlGameService to use INhlApiHttpClient for DI. --- Nhl.Api.Common/Http/NhlApiHttpClient.cs | 2 +- .../Http/NhlSuggestionApiHttpClient.cs | 2 +- Nhl.Api.Domain/Models/Season/SeasonYears.cs | 28 ++++--------------- Nhl.Api.Domain/Services/NhlGameService.cs | 2 +- 4 files changed, 8 insertions(+), 26 deletions(-) diff --git a/Nhl.Api.Common/Http/NhlApiHttpClient.cs b/Nhl.Api.Common/Http/NhlApiHttpClient.cs index c5bd4efe..28b60863 100644 --- a/Nhl.Api.Common/Http/NhlApiHttpClient.cs +++ b/Nhl.Api.Common/Http/NhlApiHttpClient.cs @@ -59,7 +59,7 @@ public abstract class NhlApiHttpClient : INhlApiHttpClient /// /// The Nhl.Api HTTP Client /// - public NhlApiHttpClient(string clientApiUri, string clientVersion, int timeoutInSeconds = 30) + public NhlApiHttpClient(string clientApiUri, string clientVersion, int timeoutInSeconds = 60) { ServicePointManager.ReusePort = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12; diff --git a/Nhl.Api.Common/Http/NhlSuggestionApiHttpClient.cs b/Nhl.Api.Common/Http/NhlSuggestionApiHttpClient.cs index 368f74ab..688009ce 100644 --- a/Nhl.Api.Common/Http/NhlSuggestionApiHttpClient.cs +++ b/Nhl.Api.Common/Http/NhlSuggestionApiHttpClient.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Net.Http; namespace Nhl.Api.Common.Http; diff --git a/Nhl.Api.Domain/Models/Season/SeasonYears.cs b/Nhl.Api.Domain/Models/Season/SeasonYears.cs index 1770d9fa..84fcd388 100644 --- a/Nhl.Api.Domain/Models/Season/SeasonYears.cs +++ b/Nhl.Api.Domain/Models/Season/SeasonYears.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; +using System.Linq; namespace Nhl.Api.Models.Season; @@ -11,29 +12,10 @@ public class SeasonYear /// /// A collection of all the NHL seasons /// - public static readonly HashSet AllSeasons = - [ - "19171918", "19181919", "19191920", "19201921", "19211922", "19221923", - "19231924", "19241925", "19251926", "19261927", "19271928", "19281929", - "19291930", "19301931", "19311932", "19321933", "19331934", "19341935", - "19351936", "19361937", "19371938", "19381939", "19391940", "19401941", - "19411942", "19421943", "19431944", "19441945", "19451946", "19461947", - "19471948", "19481949", "19491950", "19501951", "19511952", "19521953", - "19531954", "19541955", "19551956", "19561957", "19571958", "19581959", - "19591960", "19601961", "19611962", "19621963", "19631964", "19641965", - "19651966", "19661967", "19671968", "19681969", "19691970", "19701971", - "19711972", "19721973", "19731974", "19741975", "19751976", "19761977", - "19771978", "19781979", "19791980", "19801981", "19811982", "19821983", - "19831984", "19841985", "19851986", "19861987", "19871988", "19881989", - "19891990", "19901991", "19911992", "19921993", "19931994", "19941995", - "19951996", "19961997", "19971998", "19981999", "19992000", "20002001", - "20012002", "20022003", "20032004", "20052006", "20062007", "20072008", - "20082009", "20092010", "20102011", "20112012", "20122013", "20132014", - "20142015", "20152016", "20162017", "20172018", "20182019", "20192020", - "20202021", "20212022", "20222023", "20232024", "20242025", "20252026", - "20262027", "20272028", "20282029", "20292030", "20302031", "20312032", - "20322033", "20332034", "20342035" - ]; + public static readonly HashSet AllSeasons = GenerateAllSeasons(1917, 2150); + private static HashSet GenerateAllSeasons(int startYear, int endYear) => Enumerable.Range(startYear, endYear - startYear + 1) + .Select(year => $"{year}{year + 1}") + .ToHashSet(); /// /// The NHL season 1917-1918 diff --git a/Nhl.Api.Domain/Services/NhlGameService.cs b/Nhl.Api.Domain/Services/NhlGameService.cs index 21c92f13..8698b6fa 100644 --- a/Nhl.Api.Domain/Services/NhlGameService.cs +++ b/Nhl.Api.Domain/Services/NhlGameService.cs @@ -28,7 +28,7 @@ public interface INhlGameService /// public class NhlGameService : INhlGameService { - private readonly NhlScoresHtmlReportsApiHttpClient _nhlScoresHtmlReportsApiHttpClient = new(); + private readonly INhlApiHttpClient _nhlScoresHtmlReportsApiHttpClient = new NhlScoresHtmlReportsApiHttpClient(); /// /// A method to add the estimated time of play for each play in the game center play by play From 70f1da74d4ad451f842f8b0c1053956a29fdf4ee Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 4 Nov 2024 21:32:51 -0500 Subject: [PATCH 07/14] Update Nhl.Api/Src/Api/NhlApi.cs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Nhl.Api/Src/Api/NhlApi.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Nhl.Api/Src/Api/NhlApi.cs b/Nhl.Api/Src/Api/NhlApi.cs index 77dcff57..6024c731 100644 --- a/Nhl.Api/Src/Api/NhlApi.cs +++ b/Nhl.Api/Src/Api/NhlApi.cs @@ -710,6 +710,7 @@ public async Task GetPlayerStatisticsBySeasonAndFi /// The game type for the NHL season for the player statistics /// A cancellation token to cancel the asynchronous operation /// Returns all the NHL goalie statistics for a specific goalie for a specific season including face off percentage, points per game, overtime goals, short handed points , power play points, shooting percentage, shots, time on ice per game and more + /// Returns all the NHL goalie statistics for goalies matching the filter expression for the specified season, including various performance metrics. public async Task GetGoalieStatisticsBySeasonAndFilterExpressionAsync(string seasonYear, ExpressionGoalieFilter expressionGoalieFilter, GoalieStatisticsFilter goalieStatisticsFilterToSortBy = GoalieStatisticsFilter.Wins, int limit = -1, int offsetStart = 0, GameType gameType = GameType.RegularSeason, CancellationToken cancellationToken = default) => await _nhlStatisticsApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear, expressionGoalieFilter, goalieStatisticsFilterToSortBy, limit, offsetStart, gameType, cancellationToken); From 2b389b6541fc5affc8545407a37a048931b25e09 Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 4 Nov 2024 21:33:15 -0500 Subject: [PATCH 08/14] removed this --- Nhl.Api/Src/PlayerApi/NhlPlayerApi.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nhl.Api/Src/PlayerApi/NhlPlayerApi.cs b/Nhl.Api/Src/PlayerApi/NhlPlayerApi.cs index 539516fc..8fd9f1b5 100644 --- a/Nhl.Api/Src/PlayerApi/NhlPlayerApi.cs +++ b/Nhl.Api/Src/PlayerApi/NhlPlayerApi.cs @@ -97,7 +97,7 @@ public async Task GetPlayerHeadshotImageAsync(int playerId, string seaso throw new ArgumentException($"The {nameof(seasonYear)} parameter must be in the format of yyyyyyyy, example: 20232024", nameof(seasonYear)); } - var playerInformation = await this.GetPlayerInformationAsync(playerId, cancellationToken); + var playerInformation = await GetPlayerInformationAsync(playerId, cancellationToken); var teamName = playerInformation.SeasonTotals.FirstOrDefault(x => x.Season == int.Parse(seasonYear))?.TeamName?.Default; if (string.IsNullOrWhiteSpace(teamName)) { From dd58b0ba0a6a0e4b8bda28ba8088b583536210e2 Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 4 Nov 2024 21:37:09 -0500 Subject: [PATCH 09/14] Updated ReadMe.md --- Nhl.Api/README.md | 156 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 37 deletions(-) diff --git a/Nhl.Api/README.md b/Nhl.Api/README.md index 32186e94..c9c2bbe7 100644 --- a/Nhl.Api/README.md +++ b/Nhl.Api/README.md @@ -128,11 +128,12 @@ Thank you to all the people in the hockey community, especially: - [GetAllSeasonsAsync()](#M-Nhl-Api-NhlApi-GetAllSeasonsAsync-System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetAllSeasonsAsync(System.Threading.CancellationToken)') - [GetAllTotalPlayerStatisticValuesBySeasonAsync(playerId,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetAllTotalPlayerStatisticValuesBySeasonAsync-System-Int32,System-String,System-Nullable{Nhl-Api-Enumerations-Game-GameType},System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetAllTotalPlayerStatisticValuesBySeasonAsync(System.Int32,System.String,System.Nullable{Nhl.Api.Enumerations.Game.GameType},System.Threading.CancellationToken)') - [GetAllTotalPlayerStatisticValuesBySeasonAsync(playerEnum,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetAllTotalPlayerStatisticValuesBySeasonAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,System-String,System-Nullable{Nhl-Api-Enumerations-Game-GameType},System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetAllTotalPlayerStatisticValuesBySeasonAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,System.String,System.Nullable{Nhl.Api.Enumerations.Game.GameType},System.Threading.CancellationToken)') + - [GetBoxscoreByGameIdAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlApi-GetBoxscoreByGameIdAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetBoxscoreByGameIdAsync(System.Int32,System.Threading.CancellationToken)') - [GetCurrentTeamScoreboardAsync(teamId,cancellationToken)](#M-Nhl-Api-NhlApi-GetCurrentTeamScoreboardAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetCurrentTeamScoreboardAsync(System.Int32,System.Threading.CancellationToken)') - [GetCurrentTeamScoreboardAsync(team,cancellationToken)](#M-Nhl-Api-NhlApi-GetCurrentTeamScoreboardAsync-Nhl-Api-Models-Enumerations-Team-TeamEnum,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetCurrentTeamScoreboardAsync(Nhl.Api.Models.Enumerations.Team.TeamEnum,System.Threading.CancellationToken)') - [GetGameCenterBoxScoreByGameIdAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlApi-GetGameCenterBoxScoreByGameIdAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGameCenterBoxScoreByGameIdAsync(System.Int32,System.Threading.CancellationToken)') - [GetGameCenterLandingByGameIdAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlApi-GetGameCenterLandingByGameIdAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGameCenterLandingByGameIdAsync(System.Int32,System.Threading.CancellationToken)') - - [GetGameCenterPlayByPlayByGameIdAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlApi-GetGameCenterPlayByPlayByGameIdAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGameCenterPlayByPlayByGameIdAsync(System.Int32,System.Threading.CancellationToken)') + - [GetGameCenterPlayByPlayByGameIdAsync(gameId,cancellationToken,includeEventDateTime)](#M-Nhl-Api-NhlApi-GetGameCenterPlayByPlayByGameIdAsync-System-Int32,System-Boolean,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGameCenterPlayByPlayByGameIdAsync(System.Int32,System.Boolean,System.Threading.CancellationToken)') - [GetGameMetadataByGameIdAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlApi-GetGameMetadataByGameIdAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGameMetadataByGameIdAsync(System.Int32,System.Threading.CancellationToken)') - [GetGameScoreboardAsync(cancellationToken)](#M-Nhl-Api-NhlApi-GetGameScoreboardAsync-System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGameScoreboardAsync(System.Threading.CancellationToken)') - [GetGameScoresByDateAsync(date,cancellationToken)](#M-Nhl-Api-NhlApi-GetGameScoresByDateAsync-System-DateOnly,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGameScoresByDateAsync(System.DateOnly,System.Threading.CancellationToken)') @@ -140,7 +141,7 @@ Thank you to all the people in the hockey community, especially: - [GetGoalieInformationAsync(player,cancellationToken)](#M-Nhl-Api-NhlApi-GetGoalieInformationAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGoalieInformationAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,System.Threading.CancellationToken)') - [GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync(player,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,System-String,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,System.String,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync(playerId,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync-System-Int32,System-String,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync(System.Int32,System.String,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - - [GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionGoalieFilter,goalieStatisticsFilterToSortBy,limit,offsetStart,cancellationToken)](#M-Nhl-Api-NhlApi-GetGoalieStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionGoalieFilter,Nhl-Api-Models-Player-GoalieStatisticsFilter,System-Int32,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionGoalieFilter,Nhl.Api.Models.Player.GoalieStatisticsFilter,System.Int32,System.Int32,System.Threading.CancellationToken)') + - [GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionGoalieFilter,goalieStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetGoalieStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionGoalieFilter,Nhl-Api-Models-Player-GoalieStatisticsFilter,System-Int32,System-Int32,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionGoalieFilter,Nhl.Api.Models.Player.GoalieStatisticsFilter,System.Int32,System.Int32,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetGoalieStatisticsLeadersAsync(goalieStatisticsType,seasonYear,gameType,limit,cancellationToken)](#M-Nhl-Api-NhlApi-GetGoalieStatisticsLeadersAsync-Nhl-Api-Enumerations-Statistic-GoalieStatisticsType,Nhl-Api-Enumerations-Game-GameType,System-String,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetGoalieStatisticsLeadersAsync(Nhl.Api.Enumerations.Statistic.GoalieStatisticsType,Nhl.Api.Enumerations.Game.GameType,System.String,System.Int32,System.Threading.CancellationToken)') - [GetLeagueGameWeekScheduleByDateAsync(date,cancellationToken)](#M-Nhl-Api-NhlApi-GetLeagueGameWeekScheduleByDateAsync-System-DateOnly,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetLeagueGameWeekScheduleByDateAsync(System.DateOnly,System.Threading.CancellationToken)') - [GetLeagueMetadataInformationAsync(playerIds,teamIds,cancellationToken)](#M-Nhl-Api-NhlApi-GetLeagueMetadataInformationAsync-System-Collections-Generic-List{System-Int32},System-Collections-Generic-List{System-String},System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetLeagueMetadataInformationAsync(System.Collections.Generic.List{System.Int32},System.Collections.Generic.List{System.String},System.Threading.CancellationToken)') @@ -150,6 +151,7 @@ Thank you to all the people in the hockey community, especially: - [GetLeagueStandingsSeasonInformationAsync(cancellationToken)](#M-Nhl-Api-NhlApi-GetLeagueStandingsSeasonInformationAsync-System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetLeagueStandingsSeasonInformationAsync(System.Threading.CancellationToken)') - [GetLeagueWeekScheduleByDateAsync(date,cancellationToken)](#M-Nhl-Api-NhlApi-GetLeagueWeekScheduleByDateAsync-System-DateOnly,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetLeagueWeekScheduleByDateAsync(System.DateOnly,System.Threading.CancellationToken)') - [GetLiveGameFeedPlayerShiftsAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlApi-GetLiveGameFeedPlayerShiftsAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetLiveGameFeedPlayerShiftsAsync(System.Int32,System.Threading.CancellationToken)') + - [GetPlayerDraftRankingByYearAsync(seasonYear,startingPosition,cancellationToken)](#M-Nhl-Api-NhlApi-GetPlayerDraftRankingByYearAsync-System-String,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetPlayerDraftRankingByYearAsync(System.String,System.Int32,System.Threading.CancellationToken)') - [GetPlayerHeadshotImageAsync(player,seasonYear,cancellationToken)](#M-Nhl-Api-NhlApi-GetPlayerHeadshotImageAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,System-String,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetPlayerHeadshotImageAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,System.String,System.Threading.CancellationToken)') - [GetPlayerHeadshotImageAsync(playerId,seasonYear,cancellationToken)](#M-Nhl-Api-NhlApi-GetPlayerHeadshotImageAsync-System-Int32,System-String,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetPlayerHeadshotImageAsync(System.Int32,System.String,System.Threading.CancellationToken)') - [GetPlayerInformationAsync(playerId,cancellationToken)](#M-Nhl-Api-NhlApi-GetPlayerInformationAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetPlayerInformationAsync(System.Int32,System.Threading.CancellationToken)') @@ -157,8 +159,8 @@ Thank you to all the people in the hockey community, especially: - [GetPlayerSeasonGameLogsBySeasonAndGameTypeAsync(player,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetPlayerSeasonGameLogsBySeasonAndGameTypeAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,System-String,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetPlayerSeasonGameLogsBySeasonAndGameTypeAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,System.String,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetPlayerSeasonGameLogsBySeasonAndGameTypeAsync(playerId,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetPlayerSeasonGameLogsBySeasonAndGameTypeAsync-System-Int32,System-String,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetPlayerSeasonGameLogsBySeasonAndGameTypeAsync(System.Int32,System.String,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetPlayerSpotlightAsync(cancellationToken)](#M-Nhl-Api-NhlApi-GetPlayerSpotlightAsync-System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetPlayerSpotlightAsync(System.Threading.CancellationToken)') - - [GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerStatisticsFilterToSortBy,limit,offsetStart,cancellationToken)](#M-Nhl-Api-NhlApi-GetPlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerStatisticsFilter,System-Int32,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerStatisticsFilter,System.Int32,System.Int32,System.Threading.CancellationToken)') - - [GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerRealtimeStatisticsFilterToSortBy,limit,offsetStart,cancellationToken)](#M-Nhl-Api-NhlApi-GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerRealtimeStatisticsFilter,System-Int32,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerRealtimeStatisticsFilter,System.Int32,System.Int32,System.Threading.CancellationToken)') + - [GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetPlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerStatisticsFilter,System-Int32,System-Int32,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerStatisticsFilter,System.Int32,System.Int32,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') + - [GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerRealtimeStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerRealtimeStatisticsFilter,System-Int32,System-Int32,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerRealtimeStatisticsFilter,System.Int32,System.Int32,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetSkaterStatisticsLeadersAsync(playerStatisticsType,seasonYear,gameType,limit,cancellationToken)](#M-Nhl-Api-NhlApi-GetSkaterStatisticsLeadersAsync-Nhl-Api-Enumerations-Statistic-PlayerStatisticsType,Nhl-Api-Enumerations-Game-GameType,System-String,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetSkaterStatisticsLeadersAsync(Nhl.Api.Enumerations.Statistic.PlayerStatisticsType,Nhl.Api.Enumerations.Game.GameType,System.String,System.Int32,System.Threading.CancellationToken)') - [GetSourcesToWatchGamesAsync(cancellationToken)](#M-Nhl-Api-NhlApi-GetSourcesToWatchGamesAsync-System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetSourcesToWatchGamesAsync(System.Threading.CancellationToken)') - [GetTeamColorsAsync(team,cancellationToken)](#M-Nhl-Api-NhlApi-GetTeamColorsAsync-Nhl-Api-Models-Enumerations-Team-TeamEnum,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetTeamColorsAsync(Nhl.Api.Models.Enumerations.Team.TeamEnum,System.Threading.CancellationToken)') @@ -181,7 +183,7 @@ Thank you to all the people in the hockey community, especially: - [GetTeamWeekScheduleByDateAsync(teamAbbreviation,date,cancellationToken)](#M-Nhl-Api-NhlApi-GetTeamWeekScheduleByDateAsync-System-String,System-DateOnly,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetTeamWeekScheduleByDateAsync(System.String,System.DateOnly,System.Threading.CancellationToken)') - [GetTeamWeekScheduleByDateAsync(teamId,date,cancellationToken)](#M-Nhl-Api-NhlApi-GetTeamWeekScheduleByDateAsync-System-Int32,System-DateOnly,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetTeamWeekScheduleByDateAsync(System.Int32,System.DateOnly,System.Threading.CancellationToken)') - [GetTeamWeekScheduleByDateAsync(team,date,cancellationToken)](#M-Nhl-Api-NhlApi-GetTeamWeekScheduleByDateAsync-Nhl-Api-Models-Enumerations-Team-TeamEnum,System-DateOnly,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetTeamWeekScheduleByDateAsync(Nhl.Api.Models.Enumerations.Team.TeamEnum,System.DateOnly,System.Threading.CancellationToken)') - - [GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerTimeOnIceStatisticsFilterToSortBy,limit,offsetStart,cancellationToken)](#M-Nhl-Api-NhlApi-GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerTimeOnIceStatisticsFilter,System-Int32,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerTimeOnIceStatisticsFilter,System.Int32,System.Int32,System.Threading.CancellationToken)') + - [GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerTimeOnIceStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerTimeOnIceStatisticsFilter,System-Int32,System-Int32,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerTimeOnIceStatisticsFilter,System.Int32,System.Int32,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetTotalPlayerStatisticValueByTypeAndSeasonAsync(playerEnum,playerGameCenterStatistic,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetTotalPlayerStatisticValueByTypeAndSeasonAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,Nhl-Api-Enumerations-Statistic-PlayerGameCenterStatistic,System-String,System-Nullable{Nhl-Api-Enumerations-Game-GameType},System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetTotalPlayerStatisticValueByTypeAndSeasonAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,Nhl.Api.Enumerations.Statistic.PlayerGameCenterStatistic,System.String,System.Nullable{Nhl.Api.Enumerations.Game.GameType},System.Threading.CancellationToken)') - [GetTotalPlayerStatisticValueByTypeAndSeasonAsync(playerId,playerGameCenterStatistic,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlApi-GetTotalPlayerStatisticValueByTypeAndSeasonAsync-System-Int32,Nhl-Api-Enumerations-Statistic-PlayerGameCenterStatistic,System-String,System-Nullable{Nhl-Api-Enumerations-Game-GameType},System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetTotalPlayerStatisticValueByTypeAndSeasonAsync(System.Int32,Nhl.Api.Enumerations.Statistic.PlayerGameCenterStatistic,System.String,System.Nullable{Nhl.Api.Enumerations.Game.GameType},System.Threading.CancellationToken)') - [GetTvScheduleBroadcastByDateAsync(date,cancellationToken)](#M-Nhl-Api-NhlApi-GetTvScheduleBroadcastByDateAsync-System-DateOnly,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.GetTvScheduleBroadcastByDateAsync(System.DateOnly,System.Threading.CancellationToken)') @@ -193,11 +195,12 @@ Thank you to all the people in the hockey community, especially: - [SearchAllPlayersAsync(query,limit,cancellationToken)](#M-Nhl-Api-NhlApi-SearchAllPlayersAsync-System-String,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlApi.SearchAllPlayersAsync(System.String,System.Int32,System.Threading.CancellationToken)') - [NhlGameApi](#T-Nhl-Api-NhlGameApi 'Nhl.Api.NhlGameApi') - [#ctor()](#M-Nhl-Api-NhlGameApi-#ctor 'Nhl.Api.NhlGameApi.#ctor') + - [GetBoxscoreByGameIdAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlGameApi-GetBoxscoreByGameIdAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlGameApi.GetBoxscoreByGameIdAsync(System.Int32,System.Threading.CancellationToken)') - [GetCurrentTeamScoreboardAsync(team,cancellationToken)](#M-Nhl-Api-NhlGameApi-GetCurrentTeamScoreboardAsync-Nhl-Api-Models-Enumerations-Team-TeamEnum,System-Threading-CancellationToken- 'Nhl.Api.NhlGameApi.GetCurrentTeamScoreboardAsync(Nhl.Api.Models.Enumerations.Team.TeamEnum,System.Threading.CancellationToken)') - [GetCurrentTeamScoreboardAsync(teamId,cancellationToken)](#M-Nhl-Api-NhlGameApi-GetCurrentTeamScoreboardAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlGameApi.GetCurrentTeamScoreboardAsync(System.Int32,System.Threading.CancellationToken)') - [GetGameCenterBoxScoreByGameIdAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlGameApi-GetGameCenterBoxScoreByGameIdAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlGameApi.GetGameCenterBoxScoreByGameIdAsync(System.Int32,System.Threading.CancellationToken)') - [GetGameCenterLandingByGameIdAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlGameApi-GetGameCenterLandingByGameIdAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlGameApi.GetGameCenterLandingByGameIdAsync(System.Int32,System.Threading.CancellationToken)') - - [GetGameCenterPlayByPlayByGameIdAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlGameApi-GetGameCenterPlayByPlayByGameIdAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(System.Int32,System.Threading.CancellationToken)') + - [GetGameCenterPlayByPlayByGameIdAsync(gameId,includeEventDateTime,cancellationToken)](#M-Nhl-Api-NhlGameApi-GetGameCenterPlayByPlayByGameIdAsync-System-Int32,System-Boolean,System-Threading-CancellationToken- 'Nhl.Api.NhlGameApi.GetGameCenterPlayByPlayByGameIdAsync(System.Int32,System.Boolean,System.Threading.CancellationToken)') - [GetGameMetadataByGameIdAsync(gameId,cancellationToken)](#M-Nhl-Api-NhlGameApi-GetGameMetadataByGameIdAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlGameApi.GetGameMetadataByGameIdAsync(System.Int32,System.Threading.CancellationToken)') - [GetGameScoreboardAsync(cancellationToken)](#M-Nhl-Api-NhlGameApi-GetGameScoreboardAsync-System-Threading-CancellationToken- 'Nhl.Api.NhlGameApi.GetGameScoreboardAsync(System.Threading.CancellationToken)') - [GetGameScoresByDateAsync(date,cancellationToken)](#M-Nhl-Api-NhlGameApi-GetGameScoresByDateAsync-System-DateOnly,System-Threading-CancellationToken- 'Nhl.Api.NhlGameApi.GetGameScoresByDateAsync(System.DateOnly,System.Threading.CancellationToken)') @@ -244,6 +247,7 @@ Thank you to all the people in the hockey community, especially: - [GetGoalieInformationAsync(player,cancellationToken)](#M-Nhl-Api-NhlPlayerApi-GetGoalieInformationAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,System-Threading-CancellationToken- 'Nhl.Api.NhlPlayerApi.GetGoalieInformationAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,System.Threading.CancellationToken)') - [GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync(player,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlPlayerApi-GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,System-String,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlPlayerApi.GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,System.String,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync(playerId,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlPlayerApi-GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync-System-Int32,System-String,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlPlayerApi.GetGoalieSeasonGameLogsBySeasonAndGameTypeAsync(System.Int32,System.String,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') + - [GetPlayerDraftRankingByYearAsync(seasonYear,startingPosition,cancellationToken)](#M-Nhl-Api-NhlPlayerApi-GetPlayerDraftRankingByYearAsync-System-String,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlPlayerApi.GetPlayerDraftRankingByYearAsync(System.String,System.Int32,System.Threading.CancellationToken)') - [GetPlayerHeadshotImageAsync(player,seasonYear,cancellationToken)](#M-Nhl-Api-NhlPlayerApi-GetPlayerHeadshotImageAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,System-String,System-Threading-CancellationToken- 'Nhl.Api.NhlPlayerApi.GetPlayerHeadshotImageAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,System.String,System.Threading.CancellationToken)') - [GetPlayerHeadshotImageAsync(playerId,seasonYear,cancellationToken)](#M-Nhl-Api-NhlPlayerApi-GetPlayerHeadshotImageAsync-System-Int32,System-String,System-Threading-CancellationToken- 'Nhl.Api.NhlPlayerApi.GetPlayerHeadshotImageAsync(System.Int32,System.String,System.Threading.CancellationToken)') - [GetPlayerInformationAsync(playerId,cancellationToken)](#M-Nhl-Api-NhlPlayerApi-GetPlayerInformationAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlPlayerApi.GetPlayerInformationAsync(System.Int32,System.Threading.CancellationToken)') @@ -258,16 +262,16 @@ Thank you to all the people in the hockey community, especially: - [GetAllPlayersStatisticValuesBySeasonAsync(seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetAllPlayersStatisticValuesBySeasonAsync-System-String,System-Nullable{Nhl-Api-Enumerations-Game-GameType},System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetAllPlayersStatisticValuesBySeasonAsync(System.String,System.Nullable{Nhl.Api.Enumerations.Game.GameType},System.Threading.CancellationToken)') - [GetAllTotalPlayerStatisticValuesBySeasonAsync(playerEnum,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetAllTotalPlayerStatisticValuesBySeasonAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,System-String,System-Nullable{Nhl-Api-Enumerations-Game-GameType},System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetAllTotalPlayerStatisticValuesBySeasonAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,System.String,System.Nullable{Nhl.Api.Enumerations.Game.GameType},System.Threading.CancellationToken)') - [GetAllTotalPlayerStatisticValuesBySeasonAsync(playerId,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetAllTotalPlayerStatisticValuesBySeasonAsync-System-Int32,System-String,System-Nullable{Nhl-Api-Enumerations-Game-GameType},System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetAllTotalPlayerStatisticValuesBySeasonAsync(System.Int32,System.String,System.Nullable{Nhl.Api.Enumerations.Game.GameType},System.Threading.CancellationToken)') - - [GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionGoalieFilter,goalieStatisticsFilterToSortBy,limit,offsetStart,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetGoalieStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionGoalieFilter,Nhl-Api-Models-Player-GoalieStatisticsFilter,System-Int32,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionGoalieFilter,Nhl.Api.Models.Player.GoalieStatisticsFilter,System.Int32,System.Int32,System.Threading.CancellationToken)') + - [GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionGoalieFilter,goalieStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetGoalieStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionGoalieFilter,Nhl-Api-Models-Player-GoalieStatisticsFilter,System-Int32,System-Int32,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionGoalieFilter,Nhl.Api.Models.Player.GoalieStatisticsFilter,System.Int32,System.Int32,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetGoalieStatisticsLeadersAsync(goalieStatisticsType,seasonYear,gameType,limit,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetGoalieStatisticsLeadersAsync-Nhl-Api-Enumerations-Statistic-GoalieStatisticsType,Nhl-Api-Enumerations-Game-GameType,System-String,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetGoalieStatisticsLeadersAsync(Nhl.Api.Enumerations.Statistic.GoalieStatisticsType,Nhl.Api.Enumerations.Game.GameType,System.String,System.Int32,System.Threading.CancellationToken)') - - [GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerStatisticsFilterToSortBy,limit,offsetStart,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetPlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerStatisticsFilter,System-Int32,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerStatisticsFilter,System.Int32,System.Int32,System.Threading.CancellationToken)') - - [GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerRealtimeStatisticsFilterToSortBy,limit,offsetStart,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerRealtimeStatisticsFilter,System-Int32,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerRealtimeStatisticsFilter,System.Int32,System.Int32,System.Threading.CancellationToken)') + - [GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetPlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerStatisticsFilter,System-Int32,System-Int32,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerStatisticsFilter,System.Int32,System.Int32,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') + - [GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerRealtimeStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerRealtimeStatisticsFilter,System-Int32,System-Int32,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerRealtimeStatisticsFilter,System.Int32,System.Int32,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetSkaterStatisticsLeadersAsync(playerStatisticsType,seasonYear,gameType,limit,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetSkaterStatisticsLeadersAsync-Nhl-Api-Enumerations-Statistic-PlayerStatisticsType,Nhl-Api-Enumerations-Game-GameType,System-String,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetSkaterStatisticsLeadersAsync(Nhl.Api.Enumerations.Statistic.PlayerStatisticsType,Nhl.Api.Enumerations.Game.GameType,System.String,System.Int32,System.Threading.CancellationToken)') - [GetTeamStatisticsBySeasonAndGameTypeAsync(team,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetTeamStatisticsBySeasonAndGameTypeAsync-Nhl-Api-Models-Enumerations-Team-TeamEnum,System-String,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetTeamStatisticsBySeasonAndGameTypeAsync(Nhl.Api.Models.Enumerations.Team.TeamEnum,System.String,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetTeamStatisticsBySeasonAndGameTypeAsync(teamId,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetTeamStatisticsBySeasonAndGameTypeAsync-System-Int32,System-String,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetTeamStatisticsBySeasonAndGameTypeAsync(System.Int32,System.String,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetTeamStatisticsBySeasonAsync(team,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetTeamStatisticsBySeasonAsync-Nhl-Api-Models-Enumerations-Team-TeamEnum,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetTeamStatisticsBySeasonAsync(Nhl.Api.Models.Enumerations.Team.TeamEnum,System.Threading.CancellationToken)') - [GetTeamStatisticsBySeasonAsync(teamId,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetTeamStatisticsBySeasonAsync-System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetTeamStatisticsBySeasonAsync(System.Int32,System.Threading.CancellationToken)') - - [GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerTimeOnIceStatisticsFilterToSortBy,limit,offsetStart,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerTimeOnIceStatisticsFilter,System-Int32,System-Int32,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerTimeOnIceStatisticsFilter,System.Int32,System.Int32,System.Threading.CancellationToken)') + - [GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerTimeOnIceStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync-System-String,Nhl-Api-Models-Player-ExpressionPlayerFilter,Nhl-Api-Models-Player-PlayerTimeOnIceStatisticsFilter,System-Int32,System-Int32,Nhl-Api-Enumerations-Game-GameType,System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(System.String,Nhl.Api.Models.Player.ExpressionPlayerFilter,Nhl.Api.Models.Player.PlayerTimeOnIceStatisticsFilter,System.Int32,System.Int32,Nhl.Api.Enumerations.Game.GameType,System.Threading.CancellationToken)') - [GetTotalPlayerStatisticValueByTypeAndSeasonAsync(playerEnum,playerGameCenterStatistic,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetTotalPlayerStatisticValueByTypeAndSeasonAsync-Nhl-Api-Models-Enumerations-Player-PlayerEnum,Nhl-Api-Enumerations-Statistic-PlayerGameCenterStatistic,System-String,System-Nullable{Nhl-Api-Enumerations-Game-GameType},System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetTotalPlayerStatisticValueByTypeAndSeasonAsync(Nhl.Api.Models.Enumerations.Player.PlayerEnum,Nhl.Api.Enumerations.Statistic.PlayerGameCenterStatistic,System.String,System.Nullable{Nhl.Api.Enumerations.Game.GameType},System.Threading.CancellationToken)') - [GetTotalPlayerStatisticValueByTypeAndSeasonAsync(playerId,playerGameCenterStatistic,seasonYear,gameType,cancellationToken)](#M-Nhl-Api-NhlStatisticsApi-GetTotalPlayerStatisticValueByTypeAndSeasonAsync-System-Int32,Nhl-Api-Enumerations-Statistic-PlayerGameCenterStatistic,System-String,System-Nullable{Nhl-Api-Enumerations-Game-GameType},System-Threading-CancellationToken- 'Nhl.Api.NhlStatisticsApi.GetTotalPlayerStatisticValueByTypeAndSeasonAsync(System.Int32,Nhl.Api.Enumerations.Statistic.PlayerGameCenterStatistic,System.String,System.Nullable{Nhl.Api.Enumerations.Game.GameType},System.Threading.CancellationToken)') @@ -446,6 +450,24 @@ Returns the all the NHL player game center statistics for a specific player for | gameType | [System.Nullable{Nhl.Api.Enumerations.Game.GameType}](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Nullable 'System.Nullable{Nhl.Api.Enumerations.Game.GameType}') | The NHL game type to retrieve the team statistics, see [GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') for more information on valid game types | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token to cancel the asynchronous operation | + +### GetBoxscoreByGameIdAsync(gameId,cancellationToken) `method` + +##### Summary + +Returns the NHL game direct box score including information such as summaries, linescores, shots by period and more + +##### Returns + +Returns the NHL game direct box score including information such as summaries, linescores, shots by period and more + +##### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| gameId | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The NHL game identifier, Example: 2023020204 | +| cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | + ### GetCurrentTeamScoreboardAsync(teamId,cancellationToken) `method` @@ -518,8 +540,8 @@ Returns the NHL game center feed for the specified game id, including the game i | gameId | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The NHL game identifier, Example: 2023020204 | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | - -### GetGameCenterPlayByPlayByGameIdAsync(gameId,cancellationToken) `method` + +### GetGameCenterPlayByPlayByGameIdAsync(gameId,cancellationToken,includeEventDateTime) `method` ##### Summary @@ -534,7 +556,8 @@ Returns the NHL game center feed for the specified game id, including the game i | Name | Type | Description | | ---- | ---- | ----------- | | gameId | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The NHL game identifier, Example: 2023020204 | -| cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | +| cancellationToken | [System.Boolean](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Boolean 'System.Boolean') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | +| includeEventDateTime | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A flag to include the event date and time for the NHL game center play by play feed | ### GetGameMetadataByGameIdAsync(gameId,cancellationToken) `method` @@ -665,8 +688,8 @@ The collection of player season game logs with each game played including statis | gameType | [Nhl.Api.Enumerations.Game.GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') | The game type parameter for determining the game type for the type of player season logs | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | - -### GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionGoalieFilter,goalieStatisticsFilterToSortBy,limit,offsetStart,cancellationToken) `method` + +### GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionGoalieFilter,goalieStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken) `method` ##### Summary @@ -685,6 +708,7 @@ Returns all the NHL goalie statistics for a specific goalie for a specific seaso | goalieStatisticsFilterToSortBy | [Nhl.Api.Models.Player.GoalieStatisticsFilter](#T-Nhl-Api-Models-Player-GoalieStatisticsFilter 'Nhl.Api.Models.Player.GoalieStatisticsFilter') | The goalie statistics filter to sort the goalie statistics by, see [GoalieStatisticsFilter](#T-Nhl-Api-Models-Player-GoalieStatisticsFilter 'Nhl.Api.Models.Player.GoalieStatisticsFilter') for more information on valid goalie statistics filters | | limit | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results | | offsetStart | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The offset to start the results from when reviewing the NHL goalie statistics | +| gameType | [Nhl.Api.Enumerations.Game.GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') | The game type for the NHL season for the player statistics | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token to cancel the asynchronous operation | @@ -853,6 +877,25 @@ A collection of all the NHL player game shifts for a specific game, including st | gameId | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The game id, Example: 2021020087 | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | + +### GetPlayerDraftRankingByYearAsync(seasonYear,startingPosition,cancellationToken) `method` + +##### Summary + +Returns the NHL draft ranking by the specified year and starting position for the draft year + +##### Returns + +Returns the NHL draft ranking by the specified year and starting position for the draft year + +##### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| seasonYear | [System.String](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.String 'System.String') | The NHL draft year | +| startingPosition | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The starting position of the NHL draft by the year | +| cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | + ### GetPlayerHeadshotImageAsync(player,seasonYear,cancellationToken) `method` @@ -984,8 +1027,8 @@ A collection of players and their information for players in the NHL spotlight | ---- | ---- | ----------- | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | - -### GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerStatisticsFilterToSortBy,limit,offsetStart,cancellationToken) `method` + +### GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken) `method` ##### Summary @@ -1004,10 +1047,11 @@ Returns all the NHL player game center statistics for a specific player for a sp | playerStatisticsFilterToSortBy | [Nhl.Api.Models.Player.PlayerStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerStatisticsFilter 'Nhl.Api.Models.Player.PlayerStatisticsFilter') | The player statistics filter to sort the player statistics by, see [PlayerStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerStatisticsFilter 'Nhl.Api.Models.Player.PlayerStatisticsFilter') for more information on valid player statistics filters | | limit | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results | | offsetStart | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The offset to start the results from when reviewing the NHL player statistics | +| gameType | [Nhl.Api.Enumerations.Game.GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') | The game type for the NHL season for the player statistics | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token to cancel the asynchronous operation | - -### GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerRealtimeStatisticsFilterToSortBy,limit,offsetStart,cancellationToken) `method` + +### GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerRealtimeStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken) `method` ##### Summary @@ -1026,6 +1070,7 @@ Returns all the NHL real-time player game center statistics for players matching | playerRealtimeStatisticsFilterToSortBy | [Nhl.Api.Models.Player.PlayerRealtimeStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerRealtimeStatisticsFilter 'Nhl.Api.Models.Player.PlayerRealtimeStatisticsFilter') | The player real-time statistics filter to sort the player statistics by, see [PlayerRealtimeStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerRealtimeStatisticsFilter 'Nhl.Api.Models.Player.PlayerRealtimeStatisticsFilter') for more information on valid player statistics filters | | limit | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results | | offsetStart | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The offset to start the results from when reviewing the NHL player statistics | +| gameType | [Nhl.Api.Enumerations.Game.GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') | The game type for the NHL season for the player statistics | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token to cancel the asynchronous operation | @@ -1444,8 +1489,8 @@ Returns the NHL team schedule for the specified team and the specified date and | date | [System.DateOnly](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.DateOnly 'System.DateOnly') | The date and time, Example: 2020-10-02 | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | - -### GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerTimeOnIceStatisticsFilterToSortBy,limit,offsetStart,cancellationToken) `method` + +### GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerTimeOnIceStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken) `method` ##### Summary @@ -1464,6 +1509,7 @@ Returns all the NHL time-on-ice player game center statistics for players matchi | playerTimeOnIceStatisticsFilterToSortBy | [Nhl.Api.Models.Player.PlayerTimeOnIceStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerTimeOnIceStatisticsFilter 'Nhl.Api.Models.Player.PlayerTimeOnIceStatisticsFilter') | The player time-on-ice statistics filter to sort the player statistics by, see [PlayerTimeOnIceStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerTimeOnIceStatisticsFilter 'Nhl.Api.Models.Player.PlayerTimeOnIceStatisticsFilter') for more information on valid player statistics filters | | limit | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results | | offsetStart | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The offset to start the results from when reviewing the NHL player statistics | +| gameType | [Nhl.Api.Enumerations.Game.GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') | The game type for the NHL season for the player statistics | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token to cancel the asynchronous operation | @@ -1652,6 +1698,24 @@ The official unofficial NHL Game API providing various NHL information game info This constructor has no parameters. + +### GetBoxscoreByGameIdAsync(gameId,cancellationToken) `method` + +##### Summary + +Returns the NHL game direct box score including information such as summaries, linescores, shots by period and more + +##### Returns + +Returns the NHL game direct box score including information such as summaries, linescores, shots by period and more + +##### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| gameId | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The NHL game identifier, Example: 2023020204 | +| cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | + ### GetCurrentTeamScoreboardAsync(team,cancellationToken) `method` @@ -1724,8 +1788,8 @@ Returns the NHL game center feed for the specified game id, including the game i | gameId | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The NHL game identifier, Example: 2023020204 | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | - -### GetGameCenterPlayByPlayByGameIdAsync(gameId,cancellationToken) `method` + +### GetGameCenterPlayByPlayByGameIdAsync(gameId,includeEventDateTime,cancellationToken) `method` ##### Summary @@ -1740,6 +1804,7 @@ Returns the NHL game center feed for the specified game id, including the game i | Name | Type | Description | | ---- | ---- | ----------- | | gameId | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The NHL game identifier, Example: 2023020204 | +| includeEventDateTime | [System.Boolean](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Boolean 'System.Boolean') | A flag to determine whether the event timestamp for each play by play event is included | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | @@ -2453,12 +2518,6 @@ Disposes and releases all unneeded resources for the NHL player API This method has no parameters. -##### Exceptions - -| Name | Description | -| ---- | ----------- | -| [System.NotImplementedException](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.NotImplementedException 'System.NotImplementedException') | | - ### GetAllPlayersAsync(cancellationToken) `method` @@ -2552,6 +2611,25 @@ The collection of player season game logs with each game played including statis | gameType | [Nhl.Api.Enumerations.Game.GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') | The game type parameter for determining the game type for the type of player season logs | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | + +### GetPlayerDraftRankingByYearAsync(seasonYear,startingPosition,cancellationToken) `method` + +##### Summary + +Returns the NHL draft ranking by the specified year and starting position for the draft year + +##### Returns + +Returns the NHL draft ranking by the specified year and starting position for the draft year + +##### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| seasonYear | [System.String](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.String 'System.String') | The NHL draft year | +| startingPosition | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The starting position of the NHL draft by the year | +| cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | + ### GetPlayerHeadshotImageAsync(player,seasonYear,cancellationToken) `method` @@ -2802,8 +2880,8 @@ Returns the number of total number of a player statistics for a player for a spe | gameType | [System.Nullable{Nhl.Api.Enumerations.Game.GameType}](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Nullable 'System.Nullable{Nhl.Api.Enumerations.Game.GameType}') | The NHL game type to retrieve the team statistics, see [GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') for more information on valid game types | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token to cancel the asynchronous operation | - -### GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionGoalieFilter,goalieStatisticsFilterToSortBy,limit,offsetStart,cancellationToken) `method` + +### GetGoalieStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionGoalieFilter,goalieStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken) `method` ##### Summary @@ -2822,6 +2900,7 @@ Returns all the NHL goalie statistics for a specific goalie for a specific seaso | goalieStatisticsFilterToSortBy | [Nhl.Api.Models.Player.GoalieStatisticsFilter](#T-Nhl-Api-Models-Player-GoalieStatisticsFilter 'Nhl.Api.Models.Player.GoalieStatisticsFilter') | The goalie statistics filter to sort the goalie statistics by, see [GoalieStatisticsFilter](#T-Nhl-Api-Models-Player-GoalieStatisticsFilter 'Nhl.Api.Models.Player.GoalieStatisticsFilter') for more information on valid goalie statistics filters | | limit | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results | | offsetStart | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The offset to start the results from when reviewing the NHL goalie statistics | +| gameType | [Nhl.Api.Enumerations.Game.GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') | The game type for the NHL season for the player statistics | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token to cancel the asynchronous operation | @@ -2845,8 +2924,8 @@ Returns the current NHL player statistics leaders in the NHL for a specific play | limit | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The limit to the number of results returned when reviewing the NHL player statistics | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | - -### GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerStatisticsFilterToSortBy,limit,offsetStart,cancellationToken) `method` + +### GetPlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken) `method` ##### Summary @@ -2865,10 +2944,11 @@ Returns all the NHL player game center statistics for a specific player for a sp | playerStatisticsFilterToSortBy | [Nhl.Api.Models.Player.PlayerStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerStatisticsFilter 'Nhl.Api.Models.Player.PlayerStatisticsFilter') | The player statistics filter to sort the player statistics by, see [PlayerStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerStatisticsFilter 'Nhl.Api.Models.Player.PlayerStatisticsFilter') for more information on valid player statistics filters | | limit | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results | | offsetStart | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The offset to start the results from when reviewing the NHL player statistics | +| gameType | [Nhl.Api.Enumerations.Game.GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') | The game type for the NHL season for the player statistics | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token to cancel the asynchronous operation | - -### GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerRealtimeStatisticsFilterToSortBy,limit,offsetStart,cancellationToken) `method` + +### GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerRealtimeStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken) `method` ##### Summary @@ -2887,6 +2967,7 @@ Returns all the NHL player game center statistics for a specific player for a sp | playerRealtimeStatisticsFilterToSortBy | [Nhl.Api.Models.Player.PlayerRealtimeStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerRealtimeStatisticsFilter 'Nhl.Api.Models.Player.PlayerRealtimeStatisticsFilter') | The player statistics filter to sort the player statistics by, see [PlayerRealtimeStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerRealtimeStatisticsFilter 'Nhl.Api.Models.Player.PlayerRealtimeStatisticsFilter') for more information on valid player statistics filters | | limit | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results | | offsetStart | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The offset to start the results from when reviewing the NHL player statistics | +| gameType | [Nhl.Api.Enumerations.Game.GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') | The game type for the NHL season for the player statistics | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token to cancel the asynchronous operation | @@ -2986,8 +3067,8 @@ Returns all the NHL team valid game types for all valid NHL seasons for the sele | teamId | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The NHL team identifier, specifying which the NHL team, Example: 55 - Seattle Kraken | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token that can be used by other objects or threads to receive notice of cancellation | - -### GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerTimeOnIceStatisticsFilterToSortBy,limit,offsetStart,cancellationToken) `method` + +### GetTimeOnIcePlayerStatisticsBySeasonAndFilterExpressionAsync(seasonYear,expressionPlayerFilter,playerTimeOnIceStatisticsFilterToSortBy,limit,offsetStart,gameType,cancellationToken) `method` ##### Summary @@ -3006,6 +3087,7 @@ Returns all the NHL player game center statistics for a specific player for a sp | playerTimeOnIceStatisticsFilterToSortBy | [Nhl.Api.Models.Player.PlayerTimeOnIceStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerTimeOnIceStatisticsFilter 'Nhl.Api.Models.Player.PlayerTimeOnIceStatisticsFilter') | The player statistics filter to sort the player statistics by, see [PlayerTimeOnIceStatisticsFilter](#T-Nhl-Api-Models-Player-PlayerTimeOnIceStatisticsFilter 'Nhl.Api.Models.Player.PlayerTimeOnIceStatisticsFilter') for more information on valid player statistics filters | | limit | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The limit to the number of results returned when reviewing the NHL player statistics, by default -1 represents no limit applied to results | | offsetStart | [System.Int32](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Int32 'System.Int32') | The offset to start the results from when reviewing the NHL player statistics | +| gameType | [Nhl.Api.Enumerations.Game.GameType](#T-Nhl-Api-Enumerations-Game-GameType 'Nhl.Api.Enumerations.Game.GameType') | The game type for the NHL season for the player statistics | | cancellationToken | [System.Threading.CancellationToken](http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k:System.Threading.CancellationToken 'System.Threading.CancellationToken') | A cancellation token to cancel the asynchronous operation | From 12477070eaf83223e0243234d1009e9cef59dde6 Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 4 Nov 2024 21:38:00 -0500 Subject: [PATCH 10/14] Update version to 3.6.0 and target framework to net8.0 Updated the version number for the projects `Nhl.Api.Common.csproj`, `Nhl.Api.Domain.csproj`, `Nhl.Api.Tests.csproj`, and `Nhl.Api.csproj` from `3.5.0` to `3.6.0`. Additionally, updated the target framework for these projects to `net8.0`. --- Nhl.Api.Common/Nhl.Api.Common.csproj | 2 +- Nhl.Api.Domain/Nhl.Api.Domain.csproj | 2 +- Nhl.Api.Tests/Nhl.Api.Tests.csproj | 2 +- Nhl.Api/Nhl.Api.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Nhl.Api.Common/Nhl.Api.Common.csproj b/Nhl.Api.Common/Nhl.Api.Common.csproj index 0deac4f4..9d6a778f 100644 --- a/Nhl.Api.Common/Nhl.Api.Common.csproj +++ b/Nhl.Api.Common/Nhl.Api.Common.csproj @@ -1,7 +1,7 @@ - 3.5.0 + 3.6.0 net8.0 true enable diff --git a/Nhl.Api.Domain/Nhl.Api.Domain.csproj b/Nhl.Api.Domain/Nhl.Api.Domain.csproj index 58542fca..42599040 100644 --- a/Nhl.Api.Domain/Nhl.Api.Domain.csproj +++ b/Nhl.Api.Domain/Nhl.Api.Domain.csproj @@ -1,7 +1,7 @@ - 3.5.0 + 3.6.0 net8.0 true enable diff --git a/Nhl.Api.Tests/Nhl.Api.Tests.csproj b/Nhl.Api.Tests/Nhl.Api.Tests.csproj index bea10c9a..1d79a8d5 100644 --- a/Nhl.Api.Tests/Nhl.Api.Tests.csproj +++ b/Nhl.Api.Tests/Nhl.Api.Tests.csproj @@ -1,7 +1,7 @@  - 3.5.0 + 3.6.0 net8.0 false true diff --git a/Nhl.Api/Nhl.Api.csproj b/Nhl.Api/Nhl.Api.csproj index 196c7af6..94a6ba37 100644 --- a/Nhl.Api/Nhl.Api.csproj +++ b/Nhl.Api/Nhl.Api.csproj @@ -1,7 +1,7 @@ - 3.5.0 + 3.6.0 net8.0 Nhl.Api Nhl.Api From 7d78e541d8f2bfb0022623b821f9243820d6445c Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 4 Nov 2024 21:42:09 -0500 Subject: [PATCH 11/14] Make DraftYear and SeasonYear sealed; update nullable strings The DraftYear and SeasonYear classes have been changed to sealed classes, preventing inheritance. This is indicated by the addition of the sealed keyword in DraftYear.cs and SeasonYears.cs. In PlayerDraftRanking.cs, several properties in the PlayerDraftRanking class have been updated to allow nullable strings. This is indicated by the addition of the ? after the string type for properties such as LastName, FirstName, PositionCode, ShootsCatches, LastAmateurClub, LastAmateurLeague, BirthDate, BirthCity, BirthStateProvince, and BirthCountry. --- Nhl.Api.Domain/Models/Draft/DraftYear.cs | 2 +- .../Models/Draft/PlayerDraftRanking.cs | 20 +++++++++---------- Nhl.Api.Domain/Models/Season/SeasonYears.cs | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Nhl.Api.Domain/Models/Draft/DraftYear.cs b/Nhl.Api.Domain/Models/Draft/DraftYear.cs index 375d14db..5a38f1e4 100644 --- a/Nhl.Api.Domain/Models/Draft/DraftYear.cs +++ b/Nhl.Api.Domain/Models/Draft/DraftYear.cs @@ -4,7 +4,7 @@ namespace Nhl.Api.Models.Draft; /// /// All of the valid NHL draft years /// -public class DraftYear +public sealed class DraftYear { /// /// NHL Draft Year 1963 diff --git a/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs b/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs index 5384ac70..e5a4dac3 100644 --- a/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs +++ b/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs @@ -36,25 +36,25 @@ public class PlayerDraftRanking /// The last name of the player /// [JsonProperty("lastName")] - public string LastName { get; set; } + public string? LastName { get; set; } /// /// The first name of the player /// [JsonProperty("firstName")] - public string FirstName { get; set; } + public string? FirstName { get; set; } /// /// The position code of the player /// [JsonProperty("positionCode")] - public string PositionCode { get; set; } + public string? PositionCode { get; set; } /// /// The shooting or catching hand of the player /// [JsonProperty("shootsCatches")] - public string ShootsCatches { get; set; } + public string? ShootsCatches { get; set; } /// /// The height of the player in inches @@ -72,37 +72,37 @@ public class PlayerDraftRanking /// The last amateur club of the player /// [JsonProperty("lastAmateurClub")] - public string LastAmateurClub { get; set; } + public string? LastAmateurClub { get; set; } /// /// The last amateur league of the player /// [JsonProperty("lastAmateurLeague")] - public string LastAmateurLeague { get; set; } + public string? LastAmateurLeague { get; set; } /// /// The birth date of the player /// [JsonProperty("birthDate")] - public string BirthDate { get; set; } + public string? BirthDate { get; set; } /// /// The birth city of the player /// [JsonProperty("birthCity")] - public string BirthCity { get; set; } + public string? BirthCity { get; set; } /// /// The birth state or province of the player /// [JsonProperty("birthStateProvince")] - public string BirthStateProvince { get; set; } + public string? BirthStateProvince { get; set; } /// /// The birth country of the player /// [JsonProperty("birthCountry")] - public string BirthCountry { get; set; } + public string? BirthCountry { get; set; } /// /// The midterm rank of the player diff --git a/Nhl.Api.Domain/Models/Season/SeasonYears.cs b/Nhl.Api.Domain/Models/Season/SeasonYears.cs index 84fcd388..250e1614 100644 --- a/Nhl.Api.Domain/Models/Season/SeasonYears.cs +++ b/Nhl.Api.Domain/Models/Season/SeasonYears.cs @@ -7,7 +7,7 @@ namespace Nhl.Api.Models.Season; /// /// All of the NHL season years since the inception of the NHL league /// -public class SeasonYear +public sealed class SeasonYear { /// /// A collection of all the NHL seasons From b2337a77d1e9536058916255dee6fc0ba3172708 Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 4 Nov 2024 21:47:03 -0500 Subject: [PATCH 12/14] Add error handling for HTTP request in AddEstimatedDateTime The method `AddEstimatedDateTimeOfPlayForEachPlay` in the `NhlGameService` class now includes error handling for the HTTP request to fetch the score report. A nullable string variable `scoreReport` is declared at the beginning of the method and initialized within a `try` block. A `catch` block has been added to handle exceptions, returning the `gameCenterPlayByPlay` object without further processing if an error occurs. This change improves the robustness of the method by preventing potential runtime errors due to failed HTTP requests. --- Nhl.Api.Domain/Services/NhlGameService.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Nhl.Api.Domain/Services/NhlGameService.cs b/Nhl.Api.Domain/Services/NhlGameService.cs index 8698b6fa..13a1d754 100644 --- a/Nhl.Api.Domain/Services/NhlGameService.cs +++ b/Nhl.Api.Domain/Services/NhlGameService.cs @@ -37,8 +37,18 @@ public class NhlGameService : INhlGameService /// All of the game center play by play information with the time of play for each play public async Task AddEstimatedDateTimeOfPlayForEachPlay(GameCenterPlayByPlay gameCenterPlayByPlay) { + string? scoreReport = null; + var gameId = gameCenterPlayByPlay.Id.ToString(CultureInfo.InvariantCulture)[4..]; - var scoreReport = await this._nhlScoresHtmlReportsApiHttpClient.GetStringAsync($"/{gameCenterPlayByPlay.Season}/PL{gameId}.HTM", default); + + try + { + scoreReport = await this._nhlScoresHtmlReportsApiHttpClient.GetStringAsync($"/{gameCenterPlayByPlay.Season}/PL{gameId}.HTM", default); + } + catch + { + return gameCenterPlayByPlay; + } var timePeriodMatches = Regex.Matches(scoreReport, @"(?<=)Period(.*?)(?=)", RegexOptions.Compiled | RegexOptions.CultureInvariant, TimeSpan.FromSeconds(5)).ToList(); From 0a851c7fd966a9811ecc969f240e237ba6924a23 Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 4 Nov 2024 21:59:09 -0500 Subject: [PATCH 13/14] Clean up usings and enhance player statistics tests Removed unused `using` directives from multiple files to reduce clutter. Enhanced `GetPlayerStatisticsBySeasonAndFilterExpressionAsync` and `GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync` method calls in `StatisticsTests.cs` by adding parameters for better filtering and sorting: `playerStatisticsFilterToSortBy`, `limit`, `offsetStart`, and `gameType`. --- .../Http/NhlScoresHtmlReportsApiHttpClient.cs | 2 -- .../Models/Draft/PlayerDraftRanking.cs | 2 +- Nhl.Api.Domain/Services/NhlGameService.cs | 5 ++- Nhl.Api.Domain/Services/NhlTeamService.cs | 1 - Nhl.Api.Tests/GameTests.cs | 2 -- Nhl.Api.Tests/StatisticsTests.cs | 34 ++++++++++++------- Nhl.Api/Src/GameApi/NhlGameApi.cs | 4 --- 7 files changed, 24 insertions(+), 26 deletions(-) diff --git a/Nhl.Api.Common/Http/NhlScoresHtmlReportsApiHttpClient.cs b/Nhl.Api.Common/Http/NhlScoresHtmlReportsApiHttpClient.cs index c5ddec6a..fa84d331 100644 --- a/Nhl.Api.Common/Http/NhlScoresHtmlReportsApiHttpClient.cs +++ b/Nhl.Api.Common/Http/NhlScoresHtmlReportsApiHttpClient.cs @@ -1,7 +1,5 @@ using System; using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; namespace Nhl.Api.Common.Http; /// diff --git a/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs b/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs index e5a4dac3..dcc5ead0 100644 --- a/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs +++ b/Nhl.Api.Domain/Models/Draft/PlayerDraftRanking.cs @@ -1,5 +1,5 @@ -using Newtonsoft.Json; using System.Collections.Generic; +using Newtonsoft.Json; namespace Nhl.Api.Models.Draft; diff --git a/Nhl.Api.Domain/Services/NhlGameService.cs b/Nhl.Api.Domain/Services/NhlGameService.cs index 13a1d754..9a163ee3 100644 --- a/Nhl.Api.Domain/Services/NhlGameService.cs +++ b/Nhl.Api.Domain/Services/NhlGameService.cs @@ -1,12 +1,11 @@ +using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Text.RegularExpressions; -using System; using System.Threading.Tasks; using Nhl.Api.Common.Http; using Nhl.Api.Models.Game; -using System.Linq; -using Nhl.Api.Models.Schedule; namespace Nhl.Api.Services; diff --git a/Nhl.Api.Domain/Services/NhlTeamService.cs b/Nhl.Api.Domain/Services/NhlTeamService.cs index 5ff19525..6085e161 100644 --- a/Nhl.Api.Domain/Services/NhlTeamService.cs +++ b/Nhl.Api.Domain/Services/NhlTeamService.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using Nhl.Api.Common.Extensions; diff --git a/Nhl.Api.Tests/GameTests.cs b/Nhl.Api.Tests/GameTests.cs index 9666b092..9a3d23f9 100644 --- a/Nhl.Api.Tests/GameTests.cs +++ b/Nhl.Api.Tests/GameTests.cs @@ -1,6 +1,4 @@ using System.Linq; -using System.Text.RegularExpressions; -using Nhl.Api.Common.Http; namespace Nhl.Api.Tests; diff --git a/Nhl.Api.Tests/StatisticsTests.cs b/Nhl.Api.Tests/StatisticsTests.cs index 4b041ec2..2081c170 100644 --- a/Nhl.Api.Tests/StatisticsTests.cs +++ b/Nhl.Api.Tests/StatisticsTests.cs @@ -1,6 +1,5 @@ using System.Collections.Concurrent; using System.Linq; -using System.Security.AccessControl; using System.Threading; using Newtonsoft.Json; using Nhl.Api.Enumerations.Game; @@ -451,7 +450,8 @@ public async Task GetPlayerStatisticsBySeasonAndFilterAsync_Returns_Valid_Result await using var nhlApi = new NhlApi(); - var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression); + var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression, playerStatisticsFilterToSortBy: PlayerStatisticsFilter.Goals, + limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); @@ -483,7 +483,8 @@ public async Task GetPlayerStatisticsBySeasonAndFilterAsync_Returns_Valid_Result .Build(); - var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season19992000, expression); + var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season19992000, expression, playerStatisticsFilterToSortBy: PlayerStatisticsFilter.Goals, + limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); @@ -507,7 +508,8 @@ public async Task GetPlayerStatisticsBySeasonAndFilterAsync_Returns_Valid_Result // Act var expression = expressionFilter.Build(); - var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20102011, expression); + var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20102011, expression, playerStatisticsFilterToSortBy: PlayerStatisticsFilter.Goals, + limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); @@ -544,7 +546,8 @@ public async Task GetPlayerStatisticsBySeasonAndFilterAsync_Returns_Valid_Result .Build(); - var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression); + var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression, playerStatisticsFilterToSortBy: PlayerStatisticsFilter.Goals, + limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); @@ -598,7 +601,8 @@ public async Task GetPlayerStatisticsBySeasonAndFilterAsync_Returns_Valid_Result .EndGroup() .Build(); - var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression); + var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression, playerStatisticsFilterToSortBy: PlayerStatisticsFilter.Goals, + limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); @@ -637,7 +641,8 @@ public async Task GetRealtimePlayerStatisticsBySeasonAndFilterAsync_Returns_Vali await using var nhlApi = new NhlApi(); - var result = await nhlApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression); + var result = await nhlApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression, playerRealtimeStatisticsFilterToSortBy: PlayerRealtimeStatisticsFilter.MissedShotWideOfNet, + limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); @@ -670,7 +675,8 @@ public async Task GetRealtimePlayerStatisticsBySeasonAndFilterAsync_Returns_Vali .Build(); - var result = await nhlApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20202021, expression); + var result = await nhlApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20202021, expression, playerRealtimeStatisticsFilterToSortBy: PlayerRealtimeStatisticsFilter.EmptyNetAssists, + limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); @@ -694,7 +700,8 @@ public async Task GetRealtimePlayerStatisticsBySeasonAndFilterAsync_Returns_Vali // Act var expression = expressionFilter.Build(); - var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20102011, expression); + var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20102011, expression, playerStatisticsFilterToSortBy: PlayerStatisticsFilter.Goals, + limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); @@ -734,7 +741,8 @@ public async Task GetRealtimePlayerStatisticsBySeasonAndFilterAsync_Returns_Vali .Build(); - var result = await nhlApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression); + var result = await nhlApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression, playerRealtimeStatisticsFilterToSortBy: PlayerRealtimeStatisticsFilter.TakeawaysPer60, + limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); @@ -789,7 +797,7 @@ public async Task GetRealtimePlayerStatisticsBySeasonAndFilterAsync_Returns_Vali .EndGroup() .Build(); - var result = await nhlApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression); + var result = await nhlApi.GetRealtimePlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression, playerRealtimeStatisticsFilterToSortBy: PlayerRealtimeStatisticsFilter.TakeawaysPer60, limit: 50, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); @@ -815,7 +823,7 @@ public async Task GetGoalieStatisticsBySeasonAndFilterAsync_Returns_Valid_Result await using var nhlApi = new NhlApi(); // Act - var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, ExpressionPlayerFilter.Empty); + var result = await nhlApi.GetPlayerStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, ExpressionPlayerFilter.Empty, playerStatisticsFilterToSortBy: PlayerStatisticsFilter.Goals, limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(result); @@ -838,7 +846,7 @@ public async Task GetGoalieStatisticsBySeasonAndFilterAsync_Returns_Valid_Result .LessThanOrEqualTo(3.15) .Build(); - var result = await nhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression); + var result = await nhlApi.GetGoalieStatisticsBySeasonAndFilterExpressionAsync(SeasonYear.season20232024, expression, goalieStatisticsFilterToSortBy: GoalieStatisticsFilter.Wins, limit: 5, offsetStart: 0, gameType: GameType.RegularSeason); // Assert Assert.IsNotNull(expression); diff --git a/Nhl.Api/Src/GameApi/NhlGameApi.cs b/Nhl.Api/Src/GameApi/NhlGameApi.cs index cfb3ea13..e2e7fa6a 100644 --- a/Nhl.Api/Src/GameApi/NhlGameApi.cs +++ b/Nhl.Api/Src/GameApi/NhlGameApi.cs @@ -1,7 +1,3 @@ -using System.Globalization; -using System.Text.RegularExpressions; -using Nhl.Api.Common.Http; -using Nhl.Api.Models.Game; using Nhl.Api.Services; namespace Nhl.Api; From 082c1c9f2adcef01b3f48248beb58c3550c1c640 Mon Sep 17 00:00:00 2001 From: Andre Fischbacher Date: Mon, 4 Nov 2024 22:14:43 -0500 Subject: [PATCH 14/14] Refactor NhlGameService to add CalculateMultiplier method Added a private method `CalculateMultiplier` to the `NhlGameService` class for time estimation based on period duration and event count. Expanded method documentation for clarity. Introduced constants to replace hardcoded values in the multiplier formula, enhancing readability and maintainability. --- Nhl.Api.Domain/Services/NhlGameService.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Nhl.Api.Domain/Services/NhlGameService.cs b/Nhl.Api.Domain/Services/NhlGameService.cs index 9a163ee3..b3684aa1 100644 --- a/Nhl.Api.Domain/Services/NhlGameService.cs +++ b/Nhl.Api.Domain/Services/NhlGameService.cs @@ -185,15 +185,25 @@ public async Task AddEstimatedDateTimeOfPlayForEachPlay(Ga } /// - /// A linear + /// Calculates a multiplier for time estimation based on period duration and number of events. + /// The multiplier is used to adjust the distribution of plays within a period. /// + /// The start time of the period + /// The end time of the period + /// The number of events in the period + /// A multiplier value for time distribution calculations private double CalculateMultiplier(DateTime startTime, DateTime endTime, int events) { + + // Constants for the multiplier formula + var DURATION_COEFFICIENT = 41.0; + var EVENTS_COEFFICIENT = 2.0; + var CONSTANT_TERM = 381.0; + var NORMALIZER = 3000.0; + // Calculate duration in minutes var duration = (endTime - startTime).TotalMinutes; - var multiplier = ((41 * duration) + (2 * events) - 381) / 3000; - - return multiplier; + return ((DURATION_COEFFICIENT * duration) + (EVENTS_COEFFICIENT * events) - CONSTANT_TERM) / NORMALIZER; } }