diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/Raid.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/Raid.java index 574dcebb2a..66f303a8ed 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/Raid.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/Raid.java @@ -30,7 +30,7 @@ import lombok.Getter; import net.runelite.client.plugins.raids.solver.Layout; import net.runelite.client.plugins.raids.solver.Room; -public class Raid +class Raid { @Getter private final RaidRoom[] rooms = new RaidRoom[16]; @@ -38,7 +38,7 @@ public class Raid @Getter private Layout layout; - public void updateLayout(Layout layout) + void updateLayout(Layout layout) { if (layout == null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java index f92e483eae..10612e483d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java @@ -123,7 +123,7 @@ public interface RaidsConfig extends Config position = 8, keyName = "whitelistedRotations", name = "Whitelisted rotations", - description = "Warn when boss rotation doesn't match a whitelisted one. Add rotations like [tekton, muttadile, guardians]" + description = "Warn when boss rotation doesn't match a whitelisted one. Add rotations like: tekton, muttadiles, guardians - each rotation on its own line" ) default String whitelistedRotations() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java index 3f572adf2a..d9fd379f5c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsOverlay.java @@ -101,14 +101,6 @@ public class RaidsOverlay extends Overlay .color(color) .build()); - int bossMatches = 0; - int bossCount = 0; - - if (config.enableRotationWhitelist()) - { - bossMatches = plugin.getRotationMatches(); - } - for (Room layoutRoom : plugin.getRaid().getLayout().getRooms()) { int position = layoutRoom.getPosition(); @@ -124,13 +116,12 @@ public class RaidsOverlay extends Overlay switch (room.getType()) { case COMBAT: - bossCount++; if (plugin.getRoomWhitelist().contains(room.getName().toLowerCase())) { color = Color.GREEN; } else if (plugin.getRoomBlacklist().contains(room.getName().toLowerCase()) - || config.enableRotationWhitelist() && bossCount > bossMatches) + || config.enableRotationWhitelist() && !plugin.getRotationMatches()) { color = Color.RED; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java index f96f9c0a9d..12ded3525a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java @@ -24,21 +24,24 @@ */ package net.runelite.client.plugins.raids; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; import com.google.inject.Binder; import com.google.inject.Provides; import java.io.IOException; import java.text.DecimalFormat; import java.time.Instant; -import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.ScheduledExecutorService; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.Collectors; import javax.inject.Inject; +import lombok.AccessLevel; import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; @@ -96,7 +99,6 @@ public class RaidsPlugin extends Plugin private static final String RAID_COMPLETE_MESSAGE = "Congratulations - your raid is complete!"; private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###.##"); private static final DecimalFormat POINTS_FORMAT = new DecimalFormat("#,###"); - private static final Pattern ROTATION_REGEX = Pattern.compile("\\[(.*?)]"); private static final String LAYOUT_COMMAND = "!layout"; @Inject @@ -142,17 +144,18 @@ public class RaidsPlugin extends Plugin private ScheduledExecutorService scheduledExecutorService; @Getter - private final ArrayList roomWhitelist = new ArrayList<>(); + private final Set roomWhitelist = new HashSet(); @Getter - private final ArrayList roomBlacklist = new ArrayList<>(); + private final Set roomBlacklist = new HashSet(); @Getter - private final ArrayList rotationWhitelist = new ArrayList<>(); + private final Set rotationWhitelist = new HashSet(); @Getter - private final ArrayList layoutWhitelist = new ArrayList<>(); + private final Set layoutWhitelist = new HashSet(); + @Setter(AccessLevel.PACKAGE) // for the test @Getter private Raid raid; @@ -399,38 +402,28 @@ public class RaidsPlugin extends Plugin } } - private void updateLists() + @VisibleForTesting + void updateLists() { updateList(roomWhitelist, config.whitelistedRooms()); updateList(roomBlacklist, config.blacklistedRooms()); - updateList(rotationWhitelist, config.whitelistedRotations()); updateList(layoutWhitelist, config.whitelistedLayouts()); + + // Update rotation whitelist + rotationWhitelist.clear(); + for (String line : config.whitelistedRotations().split("\\n")) + { + rotationWhitelist.add(line.toLowerCase().replace(" ", "")); + } } - private void updateList(ArrayList list, String input) + private void updateList(Collection list, String input) { list.clear(); - - if (list == rotationWhitelist) - { - Matcher m = ROTATION_REGEX.matcher(input); - while (m.find()) - { - String rotation = m.group(1).toLowerCase(); - - if (!list.contains(rotation)) - { - list.add(rotation); - } - } - } - else - { - list.addAll(Text.fromCSV(input.toLowerCase())); - } + list.addAll(Text.fromCSV(input.toLowerCase())); } - int getRotationMatches() + boolean getRotationMatches() { RaidRoom[] combatRooms = raid.getCombatRooms(); String rotation = Arrays.stream(combatRooms) @@ -438,7 +431,7 @@ public class RaidsPlugin extends Plugin .map(String::toLowerCase) .collect(Collectors.joining(",")); - return rotationWhitelist.contains(rotation) ? combatRooms.length : 0; + return rotationWhitelist.contains(rotation); } private Point findLobbyBase() diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/raids/RaidsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/raids/RaidsPluginTest.java new file mode 100644 index 0000000000..09c432f7bd --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/raids/RaidsPluginTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2019, Alexsuperfly + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.raids; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.util.concurrent.ScheduledExecutorService; +import net.runelite.api.Client; +import net.runelite.client.config.ChatColorConfig; +import net.runelite.client.config.RuneLiteConfig; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class RaidsPluginTest +{ + @Mock + @Bind + Client client; + + @Mock + @Bind + ScheduledExecutorService executor; + + @Mock + @Bind + ChatColorConfig chatColorConfig; + + @Mock + @Bind + RuneLiteConfig runeliteConfig; + + @Mock + @Bind + RaidsConfig raidsConfig; + + @Inject + RaidsPlugin raidsPlugin; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + when(raidsConfig.whitelistedRooms()).thenReturn(""); + when(raidsConfig.blacklistedRooms()).thenReturn(""); + when(raidsConfig.whitelistedRotations()).thenReturn(""); + when(raidsConfig.whitelistedLayouts()).thenReturn(""); + } + + @Test + public void testRotationWhitelist() + { + when(raidsConfig.whitelistedRotations()).thenReturn("Muttadiles, Tekton, Mystics"); + raidsPlugin.updateLists(); + + final RaidRoom[] raidRooms = new RaidRoom[]{RaidRoom.MUTTADILES, RaidRoom.TEKTON, RaidRoom.MYSTICS}; + Raid raid = mock(Raid.class); + when(raid.getCombatRooms()).thenReturn(raidRooms); + raidsPlugin.setRaid(raid); + + assertTrue(raidsPlugin.getRotationMatches()); + } + + @Test + public void testRotationWhitelistMultiple() + { + when(raidsConfig.whitelistedRotations()).thenReturn("Vanguards, Vespula, Vasa \nMuttadiles, Tekton, Mystics"); + raidsPlugin.updateLists(); + + final RaidRoom[] raidRooms = new RaidRoom[]{RaidRoom.MUTTADILES, RaidRoom.TEKTON, RaidRoom.MYSTICS}; + Raid raid = mock(Raid.class); + when(raid.getCombatRooms()).thenReturn(raidRooms); + raidsPlugin.setRaid(raid); + + assertTrue(raidsPlugin.getRotationMatches()); + } + + @Test + public void testRotationWhitelistBackwards() + { + when(raidsConfig.whitelistedRotations()).thenReturn("muttadiles, tekton, mystics"); + raidsPlugin.updateLists(); + + final RaidRoom[] raidRooms = new RaidRoom[]{RaidRoom.MYSTICS, RaidRoom.TEKTON, RaidRoom.MUTTADILES}; + Raid raid = mock(Raid.class); + when(raid.getCombatRooms()).thenReturn(raidRooms); + raidsPlugin.setRaid(raid); + + assertFalse(raidsPlugin.getRotationMatches()); + } +}