taycaldwell / riot-api-java

Riot Games API Java Library
http://taycaldwell.github.io/riot-api-java/
Apache License 2.0
192 stars 73 forks source link

Get current Solo Queue 5v5 rank - JAVA Riot API #97

Closed Vodkamir closed 5 years ago

Vodkamir commented 7 years ago

Hello, I have been using taycaldwell Riot-Api Code of getting the current solo Q 5v5 rank with the following code

ApiConfig config = new ApiConfig().setKey("Key");
RiotApi api = new RiotApi(config);
    String username = JOptionPane.showInputDialog("Enter Summoner 
name").toLowerCase().replace(" ", "");

net.rithms.riot.api.endpoints.summoner.dto.Summoner summoner = 
api.getSummonerByName(Platform.EUW, username);

List<League> leagues = api.getLeagueEntryBySummoner(summoner.getId());

for(League league : leagues) {

    if(league.getQueue().equals(QueueType.RANKED_SOLO_5x5.name())) {
        System.out.println("League Name: " + league.getName());
        System.out.println("Tier: " + league.getTier());

        LeagueEntry entry = league.getEntries().get(0);
        System.out.println("Division: " + entry.getDivision());
        System.out.println("LP: " + entry.getLeaguePoints());
        System.out.println("Wins: " + entry.getWins());
        System.out.println("Losses: " + entry.getLosses());

However when do I run it gives me an error :Exception in thread "main" java.lang.NullPointerException indicating the line : for(League league : leagues) {

taycaldwell commented 7 years ago

Can you provide the stack trace?

Vodkamir commented 7 years ago

Not sure how to for this one, Im quite new to this (really sorry)

dschow commented 7 years ago

Should should check to see if leagues is null before trying to iterate over it.

Vodkamir commented 7 years ago
Thread [main] (Suspended (e xception NullPointerException)) 
Test2.main(String[]) line: 59 ---->(for(League league : leagues) {) statement   
taycaldwell commented 7 years ago

What @dschow said. Check that the collection isn't null before you iterate over it.

I'm wondering if we should utilize Optionals for return values to enforce devs to check if data #isPresent before they handle it. Thoughts @Linnun?

Optional<List<League>> seems nasty, but if the API is going to return empty data rather than a 404, we should probably handle it more elegantly (Would prefer an empty collection). Other option is to explicitly handle these kind of endpoint quirks (i.e. throw a 404 for this case.).

Also need to look into this more and see why GSON wouldn't just convert it to an empty list, since I'm pretty sure the API is returning an empty JSON array as a response.

Basically, what I'm getting at is that method return values should never be null. This should be part of the contract.

Vodkamir commented 7 years ago

Tried to check if the leagues is null gave me a response that Can only iterate over an array or an instance of java.lang.Iterable

taycaldwell commented 7 years ago

Can you provide your imports?

Vodkamir commented 7 years ago

Some of them I have used for other requests that had the similar issue

import java.awt.BorderLayout; import java.awt.FlowLayout; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map;

import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.border.EmptyBorder;

import net.rithms.riot.api.ApiConfig; import net.rithms.riot.api.RiotApi; import net.rithms.riot.api.RiotApiException; import net.rithms.riot.api.endpoints.champion.dto.Champion; import net.rithms.riot.api.endpoints.stats.dto.AggregatedStats; import net.rithms.riot.api.endpoints.stats.dto.PlayerStatsSummaryList; import net.rithms.riot.api.endpoints.stats.dto.RankedStats; import net.rithms.riot.constant.Platform; import net.rithms.riot.constant.QueueType; import net.rithms.riot.constant.Region; import net.rithms.riot.constant.Season; import net.rithms.riot.dto.Champion.ChampionList; import net.rithms.riot.dto.League.League; import net.rithms.riot.dto.League.LeagueEntry; import net.rithms.riot.dto.Stats.ChampionStats; import net.rithms.riot.dto.Stats.PlayerStatsSummary; import net.rithms.riot.dto.Summoner.Summoner; import net.rithms.riot.api.endpoints.stats.dto.AggregatedStats;

taycaldwell commented 7 years ago

Okay... Looks fine so far - Can you provide your updated code?

Vodkamir commented 7 years ago

I left it as it is

net.rithms.riot.api.endpoints.summoner.dto.Summoner summoner = api.getSummonerByName(Platform.EUW, username); List leagues = api.getLeagueEntryBySummoner(summoner.getId());

for(League league : leagues) {

    if(league.getQueue().equals(QueueType.RANKED_SOLO_5x5.name())) {

        System.out.println("League Name: " + league.getName());
        System.out.println("Tier: " + league.getTier());
        LeagueEntry entry = league.getEntries().get(0);
        System.out.println("Division: " + entry.getDivision());
        System.out.println("LP: " + entry.getLeaguePoints());
        System.out.println("Wins: " + entry.getWins());
        System.out.println("Losses: " + entry.getLosses());
taycaldwell commented 7 years ago

and doing this gives you the compiler error? 🤔 :

net.rithms.riot.api.endpoints.summoner.dto.Summoner summoner =
    api.getSummonerByName(Platform.EUW, username);
List<League> leagues = api.getLeagueEntryBySummoner(summoner.getId());

if (leagues != null) {
    for (League league : leagues) {
        if (league.getQueue().equals(QueueType.RANKED_SOLO_5x5.name())) {
            System.out.println("League Name: " + league.getName());
            System.out.println("Tier: " + league.getTier());
            LeagueEntry entry = league.getEntries().get(0);
            System.out.println("Division: " + entry.getDivision());
            System.out.println("LP: " + entry.getLeaguePoints());
            System.out.println("Wins: " + entry.getWins());
            System.out.println("Losses: " + entry.getLosses());
        }
    }
}
Vodkamir commented 7 years ago

oh for the null code it gives me nothing, a empty console

 if (leagues != null) {

for(League league : leagues ) {

    if(league.getQueue().equals(QueueType.RANKED_SOLO_5x5.name())) {

        System.out.println("League Name: " + league.getName());
        System.out.println("Tier: " + league.getTier());

        // Get the league entry for the given player of this que
        // and print out the division, lp, and wins and losses
        LeagueEntry entry = league.getEntries().get(0);
        System.out.println("Division: " + entry.getDivision());
        System.out.println("LP: " + entry.getLeaguePoints());
        System.out.println("Wins: " + entry.getWins());
        System.out.println("Losses: " + entry.getLosses());
taycaldwell commented 7 years ago

Okay good, no errors.

So the reason you are getting an empty console is because the leagues list is null, so the print statements are never executed and printed to the console.

Why is the list of leagues null? I believe the API isn't returning league entry data for this summoner, because this summoner isn't ranked.

Can you provide the summoner name you are using so I can verify this for you?

taycaldwell commented 7 years ago

What version of the library are you using? >.>

Vodkamir commented 7 years ago

I believe the most recent one I believe, 3.9.0 (For riot api Java)

taycaldwell commented 7 years ago

It looks like there is data being returned for that summoner and queue type by the API for the version of the library you are using, which leads me to believe there is a bug with the library.

I will investigate this further and get back to you.

Sorry for the inconvenience.

Vodkamir commented 7 years ago

Thank you very much for the help, much appriciated

Linnun commented 7 years ago

It is generally advised that you do not use the QueueType enum to check against a league's queueType. The reason is that leagues are not mapped to Queues 1:1. There might be multiple queues that count towards the same league. For example the queues RANKED_SOLO_5x5 and TEAM_BUILDER_RANKED_SOLO both had their games count towards the RANKED_SOLO_5x5 league. Also the name of a league does not have to match the name of any queue at all -- note that theoretically Riot could change this in future on short notice.

That being said, you should always check the result from an api call for null, at least when getting a non-Collection. For Collections, it is admittingly bad practice to have them return as null -- they should return empty Collcetions instead. That is something I will look into for the upcoming version 4.0.0 of this api wrapper.

As for your code, other than missing the null check it looks fine. My guess would be that the summoner you are looking up is not ranked in any league of the queueType RANKED_SOLO_5x5.

Vodkamir commented 7 years ago

Thank you for the help

But the Summoner is ranked, I've tried different names that are ranked for Ranked solo 5x5

This is a one time project that I am using to hand it this week and as general API practice