Hiscore feature expansion (#152)

* Add remaining Hiscore parameters to HiscoreSkill

* Add remaining Hiscore parameters to HiscoreResult

* Add remaining Hiscore parameters to HiscoreResultBuilder

* Add new Hiscore panel icons (from offical Hiscore website, so they don't match very well) and subpanel for Clue Scrolls, Bounty Hunter - Hunter, Bounty Hunter - Rogue, and Last Man Standing

* Add logic to catch unranked hiscores and display them properly. Not currently checking for combat level calculations, but other cases should be covered.

* Make HiscoreService and HiscoreClient aware of different hiscore endpoints

* Add Spring Editor to convert path variable String to enum, add pretty versions of HiscoreEndpoint names, add new icons for endpoint selection

* Fix HiscoreEndpoint.valueof failing silently and preventing lookup, update HiscoreService tests, add Hiscore endpoint selection buttons to HiscorePanel

* Replace HiscorePanel skill icons with smaller versions from the official hiscore website

* Fix details listing rank instead of experience

* Fix details listing rank instead of experience, fix skill panels not being cleared when selecting a different hiscore category, make HiscoreService respond 404  when a Hiscore entry is not found instead of 500.

* Fix skill panels not being cleared when selecting a different hiscore category, make HiscoreService respond 404  when a Hiscore entry is not found instead of 500.

* Revert changing RuneliteAPI base URL, those changes should not have been committed (local testing only)

* Add ClueScrollAll and ClueScrollMaster to HiscoreService tests.

* Style cleanup and relocate NotFoundException to http-service package

* Use relative path for small skill icons

* Move Jagex Hiscore urls from HiscoreService to HiscoreEndpoint

* Create new util package in http-service for common exceptions and Spring converters, clean up HiscoreService by streamlining error handling and removing methods for old unit test

* Change HiscoreService unit test to use new HiscoreTestService subclass which handles setting the test URL

* Change HiscoreEndpoint hiscoreUrls to HttpUrl instead of String

* Cleanup formatting, remove unused http-service exception

* http-api: cleanup HiscoreEndpoint
This commit is contained in:
Julian Nowaczek
2017-09-16 15:28:42 -05:00
committed by Adam
parent 10afba7017
commit b12bd04764
59 changed files with 692 additions and 207 deletions

View File

@@ -25,38 +25,27 @@
package net.runelite.client.plugins.hiscore;
import com.google.common.base.Strings;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.MouseInputAdapter;
import net.runelite.api.Experience;
import net.runelite.client.RuneLite;
import net.runelite.client.ui.IconTextField;
import net.runelite.client.ui.PluginPanel;
import net.runelite.http.api.hiscore.HiscoreClient;
import net.runelite.http.api.hiscore.HiscoreResult;
import net.runelite.http.api.hiscore.HiscoreSkill;
import net.runelite.http.api.hiscore.*;
import static net.runelite.http.api.hiscore.HiscoreSkill.*;
import net.runelite.http.api.hiscore.Skill;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -83,9 +72,10 @@ public class HiscorePanel extends PluginPanel
private final IconTextField input;
private final List<JLabel> skillLabels = new LinkedList<>();
private final List<JLabel> skillLabels = new ArrayList<>();
private final JPanel statsPanel = new JPanel();
private final ButtonGroup endpointButtonGroup = new ButtonGroup();
private final JTextArea details = new JTextArea();
private final HiscoreClient client = new HiscoreClient();
@@ -134,6 +124,7 @@ public class HiscorePanel extends PluginPanel
input = new IconTextField();
input.setIcon(search);
input.setFont(labelFont.deriveFont(Font.BOLD));
input.addActionListener(e ->
{
ScheduledExecutorService executor = runelite.getExecutor();
@@ -178,6 +169,22 @@ public class HiscorePanel extends PluginPanel
gridBag.setConstraints(totalPanel, c);
add(totalPanel);
JPanel minigamePanel = new JPanel();
minigamePanel.setBorder(subPanelBorder);
// These aren't all on one row because when there's a label with four or more digits it causes the details
// panel to change its size for some reason...
minigamePanel.setLayout(new GridLayout(2, 3));
minigamePanel.add(makeSkillPanel(CLUE_SCROLL_ALL.getName(), CLUE_SCROLL_ALL));
minigamePanel.add(makeSkillPanel(LAST_MAN_STANDING.getName(), LAST_MAN_STANDING));
minigamePanel.add(makeSkillPanel(BOUNTY_HUNTER_ROGUE.getName(), BOUNTY_HUNTER_ROGUE));
minigamePanel.add(makeSkillPanel(BOUNTY_HUNTER_HUNTER.getName(), BOUNTY_HUNTER_HUNTER));
c.gridx = 0;
c.gridy = 3;
gridBag.setConstraints(minigamePanel, c);
add(minigamePanel);
JPanel detailsPanel = new JPanel();
detailsPanel.setBorder(subPanelBorder);
detailsPanel.setLayout(new BorderLayout());
@@ -197,16 +204,57 @@ public class HiscorePanel extends PluginPanel
detailsPanel.add(details, BorderLayout.CENTER);
c.gridx = 0;
c.gridy = 3;
// Last item has a nonzero weighty so it will expand to fill vertical space
c.weighty = 1;
c.gridy = 4;
gridBag.setConstraints(detailsPanel, c);
add(detailsPanel);
JPanel endpointPanel = new JPanel();
endpointPanel.setBorder(subPanelBorder);
List<JToggleButton> endpointButtons = new ArrayList<>();
for (HiscoreEndpoint endpoint : HiscoreEndpoint.values())
{
try
{
Icon icon = new ImageIcon(ImageIO.read(HiscorePanel.class.getResourceAsStream(endpoint.name() + ".png")));
Icon selected = new ImageIcon(ImageIO.read(HiscorePanel.class.getResourceAsStream(endpoint.name() + "_selected.png")));
JToggleButton button = new JToggleButton();
button.setIcon(icon);
button.setSelectedIcon(selected);
button.setPreferredSize(new Dimension(24,24));
button.setBackground(Color.WHITE);
button.setFocusPainted(false);
button.setActionCommand(endpoint.name());
button.setToolTipText(endpoint.getName() + " Hiscores");
button.addActionListener((e ->
{
ScheduledExecutorService executor = runelite.getExecutor();
executor.execute(this::lookup);
}));
endpointButtons.add(button);
endpointButtonGroup.add(button);
endpointPanel.add(button);
}
catch (IOException ex)
{
logger.warn(null, ex);
}
}
endpointButtons.get(0).setSelected(true);
c.gridx = 0;
c.gridy = 5;
// Last item has a nonzero weighty so it will expand to fill vertical space
c.weighty = 1;
gridBag.setConstraints(endpointPanel, c);
add(endpointPanel);
}
private void changeDetail(String skillName, HiscoreSkill skill)
{
if (result == null)
if (result == null || result.getPlayer() == null)
{
return;
}
@@ -216,14 +264,6 @@ public class HiscorePanel extends PluginPanel
String text;
switch (skillName)
{
case "Overall":
{
Skill requestedSkill = result.getOverall();
text = "Total Level" + System.lineSeparator()
+ "Rank: " + formatter.format(requestedSkill.getRank()) + System.lineSeparator()
+ "Total Experience: " + formatter.format(requestedSkill.getExperience());
break;
}
case "Combat":
{
double combatLevel = Experience.getCombatLevelPrecise(
@@ -235,19 +275,50 @@ public class HiscorePanel extends PluginPanel
result.getRanged().getLevel(),
result.getPrayer().getLevel()
);
text = "Exact Combat Level: " + formatter.format(combatLevel) + System.lineSeparator()
text = "Skill: Combat" + System.lineSeparator()
+ "Exact Combat Level: " + formatter.format(combatLevel) + System.lineSeparator()
+ "Experience: " + formatter.format(result.getAttack().getExperience()
+ result.getStrength().getExperience() + result.getDefence().getExperience()
+ result.getHitpoints().getExperience() + result.getMagic().getExperience()
+ result.getRanged().getExperience() + result.getPrayer().getExperience());
+ result.getStrength().getExperience() + result.getDefence().getExperience()
+ result.getHitpoints().getExperience() + result.getMagic().getExperience()
+ result.getRanged().getExperience() + result.getPrayer().getExperience());
break;
}
case "Clue Scrolls (all)":
{
String rank = (result.getClueScrollAll().getRank() == -1) ? "Unranked" : formatter.format(result.getClueScrollAll().getRank());
text = "Total Clue Scrolls Completed" + System.lineSeparator()
+ "Rank: " + rank;
break;
}
case "Bounty Hunter - Rogue":
{
String rank = (result.getBountyHunterRogue().getRank() == -1) ? "Unranked" : formatter.format(result.getBountyHunterRogue().getRank());
text = "Bounty Hunter - Rogue Kills" + System.lineSeparator()
+ "Rank: " + rank;
break;
}
case "Bounty Hunter - Hunter":
{
String rank = (result.getBountyHunterHunter().getRank() == -1) ? "Unranked" : formatter.format(result.getBountyHunterHunter().getRank());
text = "Bounty Hunter - Hunter Kills" + System.lineSeparator()
+ "Rank: " + rank;
break;
}
case "Last Man Standing":
{
String rank = (result.getLastManStanding().getRank() == -1) ? "Unranked" : formatter.format(result.getLastManStanding().getRank());
text = "Last Man Standing" + System.lineSeparator()
+ "Rank: " + rank;
break;
}
default:
{
Skill requestedSkill = result.getSkill(skill);
String rank = (requestedSkill.getRank() == -1) ? "Unranked" : formatter.format(requestedSkill.getRank());
String exp = (requestedSkill.getRank() == -1) ? "Unranked" : formatter.format(requestedSkill.getExperience());
text = "Skill: " + skillName + System.lineSeparator()
+ "Rank: " + formatter.format(requestedSkill.getRank()) + System.lineSeparator()
+ "Experience: " + formatter.format(requestedSkill.getExperience());
+ "Rank: " + rank + System.lineSeparator()
+ "Experience: " + exp;
break;
}
}
@@ -265,7 +336,7 @@ public class HiscorePanel extends PluginPanel
label.putClientProperty(SKILL_NAME, skillName);
label.putClientProperty(SKILL, skill);
String skillIcon = "/skill_icons/" + skillName.toLowerCase() + ".png";
String skillIcon = "skill_icons_small/" + skillName.toLowerCase() + ".png";
logger.debug("Loading skill icon from {}", skillIcon);
try
@@ -316,11 +387,14 @@ public class HiscorePanel extends PluginPanel
try
{
result = client.lookup(lookup);
HiscoreEndpoint endpoint = HiscoreEndpoint.valueOf(endpointButtonGroup.getSelection().getActionCommand());
logger.debug("Hiscore endpoint " + endpoint.name() + " selected");
result = client.lookup(lookup, endpoint);
}
catch (IOException ex)
{
logger.warn(null, ex);
logger.warn("Error fetching Hiscore data " + ex.getMessage());
return;
}
@@ -331,18 +405,29 @@ public class HiscorePanel extends PluginPanel
if (skillName.equals("Combat"))
{
int combatLevel = Experience.getCombatLevel(
result.getAttack().getLevel(),
result.getStrength().getLevel(),
result.getDefence().getLevel(),
result.getHitpoints().getLevel(),
result.getMagic().getLevel(),
result.getRanged().getLevel(),
result.getPrayer().getLevel()
);
label.setText(Integer.toString(combatLevel));
if (result.getPlayer() != null)
{
int combatLevel = Experience.getCombatLevel(
result.getAttack().getLevel(),
result.getStrength().getLevel(),
result.getDefence().getLevel(),
result.getHitpoints().getLevel(),
result.getMagic().getLevel(),
result.getRanged().getLevel(),
result.getPrayer().getLevel()
);
label.setText(Integer.toString(combatLevel));
}
else
{
label.setText("--");
}
}
else if (skill != null)
else if (result.getSkill(skill) == null)
{
label.setText("--");
}
else if (result.getSkill(skill) != null && result.getSkill(skill).getRank() != -1)
{
label.setText(Integer.toString(result.getSkill(skill).getLevel()));
}