Closed mlynarp closed 4 months ago
Hey @mlynarp
Thanks for giving me this great suggestion! I will try and put it in the back-log for myself and work on this when I have a chance
Hey @mlynarp
After releasing v3.0.0
, there is a way to enable you to have the ability to retrieve the face off winning percentage statistic per player.
Within the C# class model PlayerCareerTotals
there is the ability to give you access to the players regular season and playoff season face off winning percentage.
You can access this endpoint via Task<PlayerProfile>GetPlayerInformationAsync(PlayerEnum player)
method, here is the documentation, https://github.com/Afischbacher/Nhl.Api?tab=readme-ov-file#getplayerinformationasyncplayer-method
Here is a small sample of the JSON returned with the specific information you are looking for with Connor McDavid's profile
"careerTotals": {
"regularSeason": {
"faceoffWinningPctg": 0.4744
},
"playoffs": {
"faceoffWinningPctg": 0.4635
}
},
Let me know if this helps, I can then close this issue :)
Thanks
Hey @Afischbacher ,
actually my goal was to collect statistics about the faceoffs won not the percentage. So for example I need to know that McDavid has collected throughout the 2023/2024 season 187 faceoffs he won as this category is used in Yahoo Fantasy league.
Thanks for future improvements.
Hey @mlynarp
Now I understand what you mean, and I have built something to accommodate this and other types of events (blocked shots, hits) so you can effectively count by the player and season, this should be live in 3.1.0
Thanks :)
Hei @Afischbacher,
I checked the source code and it seems you will have to integrate https://api.nhle.com/stats/rest/en endpoint for statistics data which is not part of the source code.
Do you need help with these or when do you think you will have API which will return statistics data per player per season?
Just to describe you in more detail what I need:
I have an app which loads all active players within active season (info about season and season dates would be great as well) and then loads statistics per each player. For skater it is GP, G, A, P, +-, PIM, Shots, FOW (int number), Hits, Blocks, and for goalies its GP, W, GAA, SV, SV%. Then I do some analysis and data visualization.
Therefore I can help you with the code if its too big for now. Currently I didn't find the way how to achieve it with current version.
Btw. I studied the API reference here https://github.com/Zmalski/NHL-API-Reference and not sure whether all data are available in API :-(
Thanks for you valuable work!
Hey @mlynarp
So, I have just released the 3.1.0
version of the Nhl.Api
and think it will help you towards your goal of creating this app, I hope. It may require you to do API calls within the NuGet with minor LINQ manipulation, but it could work.
If I understand exactly what you're looking for. Take a look at the GetPlayerInformationAsync
method to get all the statistics such as Goals, Assists and Points and call the GetTotalPlayerStatisticValueByTypeAndSeasonAsync
for the Face offs Won and any other statistics you may need or want. Now I understand this might not give you the full picture of what you are looking for, but I think it's a step in the right direction and a welcome improvement for individuals looking for different statistics.
Here is an example of the Player Landing Endpoint for Connor McDavid
"featuredStats": {
"season": 20232024,
"regularSeason": {
"subSeason": {
"gamesPlayed": 33,
"goals": 14,
"assists": 39,
"points": 53,
"plusMinus": 9,
"pim": 16,
"gameWinningGoals": 0,
"otGoals": 0,
"shots": 96,
"shootingPctg": 0.145833,
"powerPlayGoals": 4,
"powerPlayPoints": 19,
"shorthandedPoints": 0,
"shorthandedGoals": 0
},
Again, it does not have all the pieces of the puzzle, but I think it's close once you include the new endpoints I have added.
Let's keep this issue open and find a full solution for you, but please let me know what you think about the new changes.
Thanks
P.S. Please share this app, I would love to see it!!!
Hey @Afischbacher thanks for new version. It looks good and I think I will be able to get all the data I need.
Just one note, I noticed the implementation of the total player statistics. This is perfectly fine for one player, however I need to collect it for all NHL players and the above mentioned fields. It looks to me that it would cause a performance issue so I will rather iterate over all games boxscores and extract the particular fields for players.
Maybe it would be good to do it in API at least per team to avoid plenty of API calls and iterations. Something like GetTotalPlayersStatistiscByTeamAndSeasonAsync which would return a collections of players and its full statistic values within a POCO object.
P.S. My app is currently in very rough state, its like alpha alpha version :-) I can share later on when it is really in a good shape.
I started with the implementation but found that I had no way to collect information about the team. There is a list of team enums, but I can't map it to a team abbreviation. This function is private through the NhlTeamService class. The only way to collect information such as team name, conference name, division name, team abbreviation is through GetLeagueStandingsByDateAsync. This function includes team stats, which is great, but unfortunately it doesn't include the team ID, so I don't have a way to connect to the team enum programmatically.
Can you improve it and include this information to LeagueStanding object or make NhlTeamService interface available to use?
Thanks.
Hey @mlynarp
Thank you for the feedback. Let me see if I can open up the functionality of the service to be public and also see if I can get the statistics per player for all categories. I'll see if I can find time tonight to unblock you.
Hi @Afischbacher
any news regarding API extension?
Thanks
Hey @mlynarp
Let me try and release something for this weekend, apologies on the delays
Thanks
Hi @Afischbacher,
do you have time to release something? Or what is your expected time frame to provide above mentioned features.
Thanks for info.
Hey @mlynarp
I have local changes done. Just need to write tests and deploy.
My goal is to have this done for end of week. Other projects and priorities have been taking my time, sadly...
I'll keep you posted. But please keep bugging me.
Thanks
Andre
Hey @mlynarp
Check out the latest release of v3.2.0 and let's see if this does the trick for your app, I think it's what you're looking for!.
The method is GetAllTotalPlayerStatisticValueBySeasonAsync
If it does, I can close the issue, apologies for this taking longer than expected!
Thanks for your patience!
Andre
Hey @Afischbacher,
thanks for you update. I checked the API and I think I should be able to fulfill my task. Nevertheless I started to work on it and found out that NHL API (the official one, not your nuget) is extremely slow. Hope its temporarily. Do you experience same issue?
One simple request (https://api-web.nhle.com/v1/schedule/2023-10-29) takes up to 40 seconds. So the nuget API calls timed out.
It looks like to be working normally again.
So during my implementation I discovered couple of troubles:
All above mentioned will be valid for more players, I just mentioned the reproducible cases.
To fix 3: I think the condition for the team should be x.Season == int.Parse(seasonYear) && x.LeagueAbbrev == "NHL" on the line 385 (NhlStatisticsApi.cs) or make leagueAbbrev parameterized.
Hey @mlynarp,
Let me peek at these cases and see if I can get these bugs fixed soon.
Thanks, Andre
Hey @mlynarp ,
I have fixed most of the issues quickly, I think I can have a release out tonight.
Thanks
Hey @Afischbacher
do you plan to release your quick fixes or do you plan something bigger? :-)
Thanks for feedback.
Hey @mlynarp
Haha, if I were planning something bigger, I would tell you ๐งโ๐ณ๐๐
Let me try and get it out in the next 24 hours, otherwise it will be a couple of days.
Thanks again, Andre
@mlynarp
Take a read here https://github.com/Afischbacher/Nhl.Api/pull/48/files
Make comments if you want!
If I have time I can merge and release the NuGet tonight ๐
@mlynarp
v3.2.1 is live, take a peak!
Great,
first test results:
Thanks for your work!
Number of blocks still not fit, e,g. Elias Pettersson
@mlynarp
Thanks, Andre
Montreal issue is fixed, great.
I am loading all NHL players, so I call GetAllTotalPlayerStatisticValuesBySeasonAsync roughly 1200 times. I run it in parallel but still it takes aprox. 120 seconds and sometimes when running in parallel it fails. Running in sequence would be a death.
The number of blocked shots returned by GetAllTotalPlayerStatisticValuesBySeasonAsync is not correct and doesn't fit the official numbers from NHL. The Faceoff won and hits seem to be correct.
Hey @mlynarp
Happy to see this works with the new fix
Yes well, you're making about 84 * 1200 =100,800 requests in the span in ~2 minutes, I am not surprised, I would consider looking into a caching/storing this data in a persisted state to reduce your dependency on the API and run this on an event based or timer-based model. Doing this on request is not the best idea because this data does not update until any game is live or active.
As for the blocked shots, I took a deep dive into Elias Pettersson blocks for this season, and it has 41 registered events for him blocking versus the 38, so I am not sure if it's a data issue, but go through each game and look to see if he blocks the puck (joking of course)
See my data below, there are 41 instances of him "blocking a shot" sample.json
I am ready to close this issue,
Thanks
Hey @Afischbacher
current version is pretty good and I can start to use software again and save my fall in Fantasy League :-)
Anyway I checked the json and you are right there are 41 blocked shots for Elias. This is really strange. Only thing that come to my mind is that they do a stats correction after the game and maybe its not fixed in the play by play data.
Performance: You do for every player a call for profile information (that must be done), then call for team schedule and then for every game (84) you call GetGameCenter and then the iterative math. This means 1200x team schedule, 1200x84 game center.
I believe you can call once per team its schedule and then for every game(84) call game center. Then iterate and fill all team players. This would mean 32x team schedule, 32x84 game center. Iteration for team members will be more complicated but much faster. In the end you end up with 2688 API calls.
I will appreciate if you can try this as it would be then complete. I do some caching but irrespectively of this I believe it deserves this improvement ;-)
Thanks for your support.
Hey @mlynarp
I think I can create an entire endpoint dedicated to this, I think the difference here is instead of the entity being around a player, we can just focus it on the entire league and build a Dictionary of Dictionary<PlayerProfile, Stats>
and I think it can be done.
Let me see what I can do, I won't close this just yet.
Thanks, Andre
Hey @Afischbacher,
I redesigned my application and as a part of it I collect stats in different way. See the pseudo code:
As a result all of this takes aprox 10 seconds and all the statistics are correct and fits to what is shown on Yahoo. I think that this is much better attitude to collect stats.
Petr
Hey @mlynarp
I do have a new release coming out that might still give you what you're looking for. I will try and push something out this week.
Thanks
@mlynarp
Hey!
Look at v3.3.0
I have added an endpoint that is much more performant and gives all the statistics I believe you need!
The method is
GetAllPlayersStatisticValuesBySeasonAsync
Let me know what you think and if this works, we can finally close this!
Thanks, Andre
Hey @Afischbacher
I checked new version and it is really a good progress, however I measured 21 seconds for whole league which is still worse than my iteration over boxscore (8seconds) and it still suffers from unprecise data. The hits given and blocked shots doesn't match the real statistics.
I think that game play by play is not the correct statistics. Rather use the boxscore where it seems to fit.
P.S. Do you think you might provide an API to get player ID from player name? The problem is that getting the team roster will return just the active players on the roster. It means when a player is sent to AHL or being long term injured he's not part of roster and then this player is missing in overall stats. Alternatively you might return all player IDs who played within current season that would be the best.
Thanks for your work!
Hey @mlynarp
Interesting, during my testing I saw it return me results within ~10 seconds, which is not bad for me, but it could be due to caching or latency from the NHL endpoint? Not sure why all the endpoints you call are quite slow? It is odd.
As for this question:
Do you think you might provide an API to get player ID from player name?
There are two endpoints that come to mind:
public async Task<List<PlayerSearchResult>> SearchAllPlayersAsync(string query, int limit = 25, CancellationToken cancellationToken = default)
public async Task<List<PlayerSearchResult>> SearchAllActivePlayersAsync(string query, int limit = 25, CancellationToken cancellationToken = default)
With these endpoints you can just search for any name and have information returned including the PlayerId
Also remember the PlayerEnum
is a direct dynamic mapping of all player names to their identifiers. Look for it, it may help you!
Let me know if this is any help, if it is, I can close this issue!
P.S. Please send a link to this app when you get a chance!
Thanks
Hey @Afischbacher
thanks for the API, I think that should do the job for me.
From my perspective the API offers what I really need, I will keep my own implementation but your API is fine.
Feel free to close the issue but I would consider to replace play by play statistics by boxscore as it delivers precise data.
Hey @mlynarp
Going to close this issue as it is resolved!
Thanks
P.S. Please do share the app you build!!
It would be cool to enhance player statistics to include faceoffs won (FOW) as it is used quite often in Yahoo Fantasy Leagues.
Currently as a workaround I need to iterate over all games and check the boxscore and calculate on my own.