commit f158619ba834ed186b00232a7bd0800a52a92a01 parent 5e5d218203cc872a4740a95d21ec3c78ad43ca6b Author: Wim Dupont <wim@wimdupont.com> Date: Thu, 21 Mar 2024 18:23:16 +0100 varlamore update Diffstat:
13 files changed, 210 insertions(+), 84 deletions(-)
diff --git a/pom.xml b/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> - <version>3.2.1</version> + <version>3.2.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.wimdupont</groupId> diff --git a/src/main/java/com/wimdupont/sxcybot/client/HiScoreClient.java b/src/main/java/com/wimdupont/sxcybot/client/HiScoreClient.java @@ -4,6 +4,7 @@ import com.wimdupont.sxcybot.exceptions.EntityNotFoundException; import com.wimdupont.sxcybot.model.HiScoreBuilder; import com.wimdupont.sxcybot.model.OsrsBossKc; import com.wimdupont.sxcybot.model.OsrsStat; +import com.wimdupont.sxcybot.repository.osrs.dao.OsrsHiscore; import com.wimdupont.sxcybot.repository.osrs.dao.OsrsHiscoreBoss; import com.wimdupont.sxcybot.repository.osrs.dao.OsrsHiscoreStat; import com.wimdupont.sxcybot.services.osrs.OsrsHiscoreBossService; @@ -14,13 +15,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.List; -import java.util.Optional; @Component public class HiScoreClient { @@ -28,11 +31,6 @@ public class HiScoreClient { private static final String URL = "https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player=%s"; private static final Logger LOGGER = LoggerFactory.getLogger(HiScoreClient.class); - private static final int STATS_START = 0; - private static final int STATS_END = 23; - private static final int BOSS_START = 41; - private static final int BOSS_END = 99; - private final OsrsHiscoreBossService osrsHiscoreBossService; private final OsrsHiscoreStatService osrsHiscoreStatService; @@ -42,53 +40,71 @@ public class HiScoreClient { this.osrsHiscoreStatService = osrsHiscoreStatService; } - public Optional<List<OsrsStat>> getHiScoreStats(String playername, MessageChannel channel) { + public List<OsrsStat> getHiScoreStats(String playername, MessageChannel channel) throws EntityNotFoundException { List<OsrsHiscoreStat> hiscoreStats = osrsHiscoreStatService.findAll(); return getHiScores(playername, channel, (osrsStat, hiScoreStatValues, i) -> OsrsStat.Builder.newBuilder() .name(hiscoreStats.stream().filter(f -> f.getOrderValue() == i).findFirst().orElseThrow(() -> new EntityNotFoundException(String.format("OsrsStatName for order %s not found!", i))) .getName()) - .rank(NumberFormatter.format(hiScoreStatValues.get(0))) + .rank(NumberFormatter.format(hiScoreStatValues.getFirst())) .level(hiScoreStatValues.get(1)) .experience(NumberFormatter.format(hiScoreStatValues.get(2))) - .build(), STATS_START, STATS_END); + .build(), getMinOrder(hiscoreStats), getMaxOrder(hiscoreStats)); } - public Optional<List<OsrsBossKc>> getHiScoreBossKc(String playername, MessageChannel channel) { + public List<OsrsBossKc> getHiScoreBossKc(String playername, MessageChannel channel) throws EntityNotFoundException { List<OsrsHiscoreBoss> hiscoreBosses = osrsHiscoreBossService.findAll(); return getHiScores(playername, channel, (osrsKc, hiScoreKcValues, i) -> OsrsBossKc.Builder.newBuilder() .name(hiscoreBosses.stream().filter(f -> f.getOrderValue() == i).findFirst().orElseThrow(() -> new EntityNotFoundException(String.format("OsrsBoss for order %s not found!", i))) .getName()) - .rank(hiScoreKcValues.get(0)) + .rank(hiScoreKcValues.getFirst()) .kc(hiScoreKcValues.get(1)) - .build(), BOSS_START, BOSS_END); + .build(), getMinOrder(hiscoreBosses), getMaxOrder(hiscoreBosses)); } - private <T> Optional<List<T>> getHiScores(String playername, MessageChannel channel, HiScoreBuilder<T> hiScoreBuilder, int fromIndex, int toIndex) { + private <T> List<T> getHiScores(String playername, MessageChannel channel, HiScoreBuilder<T> hiScoreBuilder, int fromIndex, int toIndex) throws EntityNotFoundException { List<T> hiScoreList = new ArrayList<>(); RestTemplate restTemplate = new RestTemplateBuilder() .errorHandler(new ClientErrorHandler(channel)) .setReadTimeout(Duration.ofSeconds(30)) .build(); - String result = restTemplate.getForObject(String.format(URL, playername), String.class); - if (result != null) { + try { + String result = restTemplate.getForObject(String.format(URL, playername), String.class); + if (result == null) { + throw new Exception(); + } int i = fromIndex; List<String> hiScores = Arrays.stream(result.split("\n")).toList(); - try { - for (String osrsHiScoresStats : hiScores.subList(fromIndex, toIndex + 1)) { - List<String> hiScoreStatValues = Arrays.stream(osrsHiScoresStats.split(",")).toList(); - try { - hiScoreList.add(hiScoreBuilder.accept(osrsHiScoresStats, hiScoreStatValues, i)); - } catch (EntityNotFoundException e) { - LOGGER.error(e.getMessage(), e); - } - i++; - } - } catch (RuntimeException e) { - return Optional.empty(); + for (String osrsHiScoresStats : hiScores.subList(fromIndex, toIndex + 1)) { + List<String> hiScoreStatValues = Arrays.stream(osrsHiScoresStats.split(",")).toList(); + hiScoreList.add(hiScoreBuilder.accept(osrsHiScoresStats, hiScoreStatValues, i)); + i++; + } + if (hiScoreList.isEmpty()) { + throw new Exception(); } + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + throw new EntityNotFoundException(String.format("No hiscores available for %s.", playername)); + } + return hiScoreList; + } + + private <T extends OsrsHiscore> int getMinOrder(List<T> osrsHiscores) { + if (CollectionUtils.isEmpty(osrsHiscores)) { + return 0; } - return Optional.of(hiScoreList); + return Collections.min(osrsHiscores, Comparator.comparing(OsrsHiscore::getOrderValue)) + .getOrderValue(); + } + + private <T extends OsrsHiscore> int getMaxOrder(List<T> osrsHiscores) { + if (CollectionUtils.isEmpty(osrsHiscores)) { + return 0; + } + return Collections.max(osrsHiscores, Comparator.comparing(OsrsHiscore::getOrderValue)) + .getOrderValue(); + } } diff --git a/src/main/java/com/wimdupont/sxcybot/exceptions/OsrsHiscoreOrderValueException.java b/src/main/java/com/wimdupont/sxcybot/exceptions/OsrsHiscoreOrderValueException.java @@ -0,0 +1,9 @@ +package com.wimdupont.sxcybot.exceptions; + +public class OsrsHiscoreOrderValueException extends RuntimeException { + + + public OsrsHiscoreOrderValueException(String msg) { + super(msg); + } +} diff --git a/src/main/java/com/wimdupont/sxcybot/listeners/member/KillCountListener.java b/src/main/java/com/wimdupont/sxcybot/listeners/member/KillCountListener.java @@ -26,8 +26,7 @@ public class KillCountListener implements Listener { String msg = event.getMessage().getContentRaw(); try { String player = msg.substring(msg.indexOf(" ")).trim(); - List<OsrsBossKc> bossKcList = hiScoreClient.getHiScoreBossKc(player, event.getChannel()).orElseThrow(() - -> new EntityNotFoundException(String.format("No HiScores found for %s.", player))); + List<OsrsBossKc> bossKcList = hiScoreClient.getHiScoreBossKc(player, event.getChannel()); event.getChannel().sendTyping().queue(q -> { EmbedBuilder embedBuilder = new EmbedBuilder(); diff --git a/src/main/java/com/wimdupont/sxcybot/repository/osrs/dao/OsrsHiscore.java b/src/main/java/com/wimdupont/sxcybot/repository/osrs/dao/OsrsHiscore.java @@ -0,0 +1,7 @@ +package com.wimdupont.sxcybot.repository.osrs.dao; + +public interface OsrsHiscore { + + int getOrderValue(); + +} diff --git a/src/main/java/com/wimdupont/sxcybot/repository/osrs/dao/OsrsHiscoreBoss.java b/src/main/java/com/wimdupont/sxcybot/repository/osrs/dao/OsrsHiscoreBoss.java @@ -6,7 +6,7 @@ import org.hibernate.annotations.UuidGenerator; @Entity -public class OsrsHiscoreBoss { +public class OsrsHiscoreBoss implements OsrsHiscore { @Id @UuidGenerator diff --git a/src/main/java/com/wimdupont/sxcybot/repository/osrs/dao/OsrsHiscoreStat.java b/src/main/java/com/wimdupont/sxcybot/repository/osrs/dao/OsrsHiscoreStat.java @@ -6,7 +6,7 @@ import org.hibernate.annotations.UuidGenerator; @Entity -public class OsrsHiscoreStat { +public class OsrsHiscoreStat implements OsrsHiscore { @Id @UuidGenerator diff --git a/src/main/java/com/wimdupont/sxcybot/services/OsrsMonitoringService.java b/src/main/java/com/wimdupont/sxcybot/services/OsrsMonitoringService.java @@ -76,7 +76,7 @@ public class OsrsMonitoringService { List<PvmRoleUser> unfound = new ArrayList<>(); for (PvmRoleUser pvmRoleUser : pvmRoleUserService.findAll()) { try { - hiScoreClient.getHiScoreBossKc(pvmRoleUser.getRsn(), null).orElseThrow(); + hiScoreClient.getHiScoreBossKc(pvmRoleUser.getRsn(), null); } catch (Exception e) { unfound.add(pvmRoleUser); } @@ -132,8 +132,7 @@ public class OsrsMonitoringService { } public void monitorHiscores() throws EntityNotFoundException { - List<OsrsBossKc> osrsBossKcs = hiScoreClient.getHiScoreBossKc(monitorUserName, null) - .orElseThrow(() -> new EntityNotFoundException(String.format("No hiscores available for %s.", monitorUserName))); + List<OsrsBossKc> osrsBossKcs = hiScoreClient.getHiScoreBossKc(monitorUserName, null); OsrsBossKc wintertodtBossKc = osrsBossKcs.stream() .filter(f -> f.name().equals(monitorBossName)) .findAny() diff --git a/src/main/java/com/wimdupont/sxcybot/services/guild/pvmrole/PvmRoleSnapshotComparatorService.java b/src/main/java/com/wimdupont/sxcybot/services/guild/pvmrole/PvmRoleSnapshotComparatorService.java @@ -69,9 +69,7 @@ public class PvmRoleSnapshotComparatorService { PvmKcSnapshot pvmKcSnapshot = PvmKcSnapshot.Builder.newBuilder() .pvmRoleUser(pvmRoleUser) .build(); - List<OsrsBossKc> osrsBossKcList = hiScoreClient.getHiScoreBossKc(pvmRoleUser.getRsn(), textChannel).orElseThrow( - () -> new EntityNotFoundException(String.format("No hiScores found for %s", pvmRoleUser.getRsn())) - ); + List<OsrsBossKc> osrsBossKcList = hiScoreClient.getHiScoreBossKc(pvmRoleUser.getRsn(), textChannel); List<PvmUserKc> pvmUserKcList = new ArrayList<>(); for (OsrsBossKc osrsBossKc : osrsBossKcList.stream().filter(r -> Integer.parseInt(r.kc()) > 0).toList()) { try { diff --git a/src/main/java/com/wimdupont/sxcybot/services/osrs/StatMessageSender.java b/src/main/java/com/wimdupont/sxcybot/services/osrs/StatMessageSender.java @@ -32,8 +32,8 @@ public class StatMessageSender { try { embedBuilder.setColor(Color.RED); embedBuilder.setTitle(String.format("Stats of %s", player)); - List<OsrsStat> osrsStatList = hiScoreClient.getHiScoreStats(player, event.getChannel()).orElseThrow(() - -> new EntityNotFoundException(String.format("No HiScores found for %s.", player))); + List<OsrsStat> osrsStatList = hiScoreClient.getHiScoreStats(player, event.getChannel()); + osrsStatList.stream().filter(predicate).forEach(consumer); if (calcCombatLevel != null) { calcCombatLevel.accept(osrsStatList); diff --git a/src/main/resources/db/migration/V1_18__varlamore_update.sql b/src/main/resources/db/migration/V1_18__varlamore_update.sql @@ -0,0 +1,12 @@ +UPDATE osrs_hiscore_boss SET order_value = order_value+1; +UPDATE osrs_hiscore_boss SET order_value = order_value+1 WHERE order_value > 70; + +INSERT INTO osrs_hiscore_boss +VALUES +(UUID(),"Lunar Chests", 1, 71, 1); + +UPDATE osrs_hiscore_boss SET order_value = order_value+1 WHERE order_value > 81; + +INSERT INTO osrs_hiscore_boss +VALUES +(UUID(),"Sol Heredit", 1, 82, 1); diff --git a/src/test/R__hiscores.sql b/src/test/R__hiscores.sql @@ -0,0 +1,94 @@ +--DELETE FROM osrs_hiscore_stat; +-- +--INSERT INTO osrs_hiscore_stat +--VALUES +-- (UUID(), "Overall", 0), +-- (UUID(), "Attack", 1), +-- (UUID(), "Defence", 2), +-- (UUID(), "Strength", 3), +-- (UUID(), "Hitpoints", 4), +-- (UUID(), "Ranged", 5), +-- (UUID(), "Prayer", 6), +-- (UUID(), "Magic", 7), +-- (UUID(), "Cooking", 8), +-- (UUID(), "Woodcutting", 9), +-- (UUID(), "Fletching", 10), +-- (UUID(), "Fishing", 11), +-- (UUID(), "Firemaking", 12), +-- (UUID(), "Crafting", 13), +-- (UUID(), "Smithing", 14), +-- (UUID(), "Mining", 15), +-- (UUID(), "Herblore", 16), +-- (UUID(), "Agility", 17), +-- (UUID(), "Thieving", 18), +-- (UUID(), "Slayer", 19), +-- (UUID(), "Farming", 20), +-- (UUID(), "Runecrafting", 21), +-- (UUID(), "Hunter", 22), +-- (UUID(), "Construction", 23); +-- +--DELETE FROM osrs_hiscore_boss; +-- +--INSERT INTO osrs_hiscore_boss +--VALUES +--(UUID(), 'Abyssal Sire', 1, 42, 1), +--(UUID(), 'Alchemical Hydra', 1, 43, 1), +--(UUID(), 'Artio', 2, 44, 3), +--(UUID(), 'Barrows Chests', 1, 45, 1), +--(UUID(), 'Bryophyta', 1, 46, 1), +--(UUID(), 'Cal\'varion', 2, 47, 3), +--(UUID(), 'Callisto', 3, 48, 3), +--(UUID(), 'Cerberus', 1, 49, 1), +--(UUID(), 'Chambers of Xeric', 1, 50, 2), +--(UUID(), 'Chambers of Xeric: Challenge Mode', 1, 51, 2), +--(UUID(), 'Chaos Elemental', 3, 52, 3), +--(UUID(), 'Chaos Fanatic', 2, 53, 3), +--(UUID(), 'Commander Zilyana', 1, 54, 1), +--(UUID(), 'Corporeal Beast', 1, 55, 1), +--(UUID(), 'Crazy Archaeologist', 2, 56, 3), +--(UUID(), 'Dagannoth Prime', 1, 57, 1), +--(UUID(), 'Dagannoth Rex', 1, 58, 1), +--(UUID(), 'Dagannoth Supreme', 1, 59, 1), +--(UUID(), 'Deranged Archaeologist', 1, 60, 1), +--(UUID(), 'Duke Sucellus', 1, 61, 1), +--(UUID(), 'General Graardor', 1, 62, 1), +--(UUID(), 'Giant Mole', 1, 63, 1), +--(UUID(), 'Grotesque Guardians', 1, 64, 1), +--(UUID(), 'Hespori', 1, 65, 1), +--(UUID(), 'Kalphite Queen', 1, 66, 1), +--(UUID(), 'King Black Dragon', 1, 67, 1), +--(UUID(), 'Kraken', 1, 68, 1), +--(UUID(), 'Kree\' Arra', 1, 69, 1), +--(UUID(), 'K\'ril Tsutsaroth', 1, 70, 1), +--(UUID(), 'Lunar Chests', 1, 71, 1), +--(UUID(), 'Mimic', 1, 72, 1), +--(UUID(), 'Nex', 3, 73, 1), +--(UUID(), 'Nightmare', 1, 74, 1), +--(UUID(), 'Phosani\'s Nightmare', 6, 75, 1), +--(UUID(), 'Obor', 1, 76, 1), +--(UUID(), 'Phantom Muspah', 2, 77, 1), +--(UUID(), 'Sarachnis', 1, 78, 1), +--(UUID(), 'Scorpia', 3, 79, 3), +--(UUID(), 'Scurrius', 1, 80, 1), +--(UUID(), 'Skotizo', 1, 81, 1), +--(UUID(), 'Sol Heredit', 1, 82, 1), +--(UUID(), 'Spindel', 2, 83, 3), +--(UUID(), 'Tempoross', 1, 84, 0), +--(UUID(), 'The Gauntlet', 1, 85, 1), +--(UUID(), 'The Corrupted Gauntlet', 1, 86, 1), +--(UUID(), 'The Leviathan', 1, 87, 1), +--(UUID(), 'The Whisperer', 1, 88, 1), +--(UUID(), 'Theatre of Blood', 1, 89, 2), +--(UUID(), 'Theatre of Blood: Hard Mode', 1, 90, 2), +--(UUID(), 'Thermonuclear Smoke Devil', 1, 91, 1), +--(UUID(), 'Tombs of Amascut', 10, 92, 5), +--(UUID(), 'Tombs of Amascut: Expert Mode', 14, 93, 5), +--(UUID(), 'TzKal-Zuk', 1, 94, 1), +--(UUID(), 'TzTok-Jad', 1, 95, 1), +--(UUID(), 'Vardorvis', 1, 96, 1), +--(UUID(), 'Venenatis', 3, 97, 3), +--(UUID(), 'Vet\'ion', 3, 95, 6), +--(UUID(), 'Vorkath', 1, 96, 4), +--(UUID(), 'Wintertodt', 1, 100, 0), +--(UUID(), 'Zalcano', 1, 101, 0), +--(UUID(), 'Zulrah', 1, 102, 1); diff --git a/src/test/java/com/wimdupont/sxcybot/client/HiScoreClientTest.java b/src/test/java/com/wimdupont/sxcybot/client/HiScoreClientTest.java @@ -1,8 +1,7 @@ package com.wimdupont.sxcybot.client; -import com.wimdupont.sxcybot.model.OsrsBossKc; +import com.wimdupont.sxcybot.exceptions.EntityNotFoundException; import com.wimdupont.sxcybot.model.OsrsStat; -import com.wimdupont.sxcybot.repository.osrs.dao.OsrsHiscoreBoss; import com.wimdupont.sxcybot.repository.osrs.dao.OsrsHiscoreStat; import com.wimdupont.sxcybot.services.osrs.OsrsHiscoreBossService; import com.wimdupont.sxcybot.services.osrs.OsrsHiscoreStatService; @@ -15,10 +14,10 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.util.List; -import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.BDDMockito.given; @@ -42,71 +41,64 @@ class HiScoreClientTest { } @Test - void getHiScoreStatsValid() { + void getHiScoreStatsValid() throws EntityNotFoundException { String playerName = "Zxxy"; List<OsrsHiscoreStat> osrsHiscoreStats = List.of(OsrsHiscoreStat.Builder.newBuilder() .name("Overall") .orderValue(0) .build(), OsrsHiscoreStat.Builder.newBuilder() - .name("Construction") - .orderValue(23) - .build()); + .name("Attack") + .orderValue(1) + .build(), + OsrsHiscoreStat.Builder.newBuilder() + .name("Defence") + .orderValue(2) + .build(), + OsrsHiscoreStat.Builder.newBuilder() + .name("Strength") + .orderValue(3) + .build(), + OsrsHiscoreStat.Builder.newBuilder() + .name("Hitpoints") + .orderValue(4) + .build() + ); given(osrsHiscoreStatService.findAll()).willReturn(osrsHiscoreStats); - Optional<List<OsrsStat>> result = hiScoreClient.getHiScoreStats(playerName, messageChannel); + List<OsrsStat> result = hiScoreClient.getHiScoreStats(playerName, messageChannel); assertFalse(result.isEmpty()); - assertEquals(2, result.get().size()); + assertEquals(5, result.size()); + + assertEquals("Overall", result.get(0).name()); + assertTrue(1939 <= Integer.parseInt(result.get(0).level())); - assertEquals("Overall", result.get().get(0).name()); - assertTrue(1939 <= Integer.parseInt(result.get().get(0).level())); + assertEquals("Strength", result.get(3).name()); + assertTrue(99 == Integer.parseInt(result.get(3).level())); - assertEquals("Construction", result.get().get(1).name()); - assertTrue(90 <= Integer.parseInt(result.get().get(1).level())); + assertEquals("Hitpoints", result.get(4).name()); + assertTrue(99 == Integer.parseInt(result.get(4).level())); } @Test void getHiscoreStatsNonExistingPlayer() { String playerName = "007thisplayershouldneverexist007"; given(messageChannel.sendMessage("No results found. ()")).willReturn(messageAction); - Optional<List<OsrsStat>> result = hiScoreClient.getHiScoreStats(playerName, messageChannel); - - assertTrue(result.isEmpty()); - } + Exception exception = assertThrows(EntityNotFoundException.class, () -> + hiScoreClient.getHiScoreStats(playerName, messageChannel)); - @Test - void getHiscoreBossKcValidKbdKc() { - String playerName = "Zxxy"; - List<OsrsHiscoreBoss> hiscoreBosses = List.of(OsrsHiscoreBoss.Builder.newBuilder() - .name("KBD") - .orderValue(66) - .build(), - OsrsHiscoreBoss.Builder.newBuilder() - .name("Wintertodt") - .orderValue(97) - .build() - ); - - given(osrsHiscoreBossService.findAll()).willReturn(hiscoreBosses); - Optional<List<OsrsBossKc>> result = hiScoreClient.getHiScoreBossKc(playerName, messageChannel); - - assertFalse(result.isEmpty()); - assertEquals(2, result.get().size()); - - assertEquals("KBD", result.get().get(0).name()); - assertTrue(723 <= Integer.parseInt(result.get().get(0).kc())); - - assertEquals("Wintertodt", result.get().get(1).name()); - assertTrue(87 <= Integer.parseInt(result.get().get(1).kc())); + assertEquals(exception.getMessage(), String.format("No hiscores available for %s.", playerName)); } @Test void getHiscoreBossKcNonExistingPlayer() { String playerName = "007thisplayershouldneverexist007"; given(messageChannel.sendMessage("No results found. ()")).willReturn(messageAction); - Optional<List<OsrsBossKc>> result = hiScoreClient.getHiScoreBossKc(playerName, messageChannel); - assertTrue(result.isEmpty()); + Exception exception = assertThrows(EntityNotFoundException.class, () -> + hiScoreClient.getHiScoreBossKc(playerName, messageChannel)); + + assertEquals(exception.getMessage(), String.format("No hiscores available for %s.", playerName)); } }