Skip to content

Commit ea0462d

Browse files
authored
Extract transportLoader (#249)
* Add comprehensive unit tests for Transport class - Implement tests for parsing transport data from contents, including various scenarios such as empty lines, comments, multiple transports from the same origin, teleport duration adjustments, skill and item requirements, quest and varbit requirements, and more. - Validate behavior for malformed data and ensure default values are used appropriately. - Test filtering based on radius thresholds and ensure no transports are created for invalid origins or destinations. - Cover edge cases such as permutations, missing fields, and specific transport types like agility shortcuts and teleportation. * Refactor transport loading and add comprehensive tests - Updated import paths for Transport and TransportLoader classes. - Changed the method of loading transports from resources to use TransportLoader. - Introduced a new test class TransportLoaderTest with extensive unit tests for the TransportLoader functionality. - Added tests for various scenarios including basic transport parsing, handling of empty and comment lines, multiple transports from the same origin, skill and item requirements, quest requirements, varbit and varplayer requirements, and more. - Ensured that malformed data is handled gracefully and that transports are not created for undefined origins or destinations. - Implemented tests for filtering based on radius thresholds and ensuring that only valid transports are created. * Add back comments to clarify transport handling logic in addTransportsFromContents method * Add comments to clarify transport logic in TransportLoader class * Add unit tests for TransportItems, TransportType, TransportVarCheck, TransportVarPlayer, and TransportVarbit classes
1 parent a9f964e commit ea0462d

22 files changed

Lines changed: 1382 additions & 169 deletions

src/main/java/shortestpath/PathMapOverlay.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import net.runelite.client.ui.overlay.OverlayLayer;
1717
import net.runelite.client.ui.overlay.OverlayPosition;
1818
import shortestpath.pathfinder.CollisionMap;
19+
import shortestpath.transport.Transport;
20+
import shortestpath.transport.TransportType;
1921

2022
public class PathMapOverlay extends Overlay {
2123
private final Client client;

src/main/java/shortestpath/PathMapTooltipOverlay.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import net.runelite.client.ui.overlay.Overlay;
1919
import net.runelite.client.ui.overlay.OverlayLayer;
2020
import net.runelite.client.ui.overlay.OverlayPosition;
21+
import shortestpath.transport.Transport;
2122

2223
public class PathMapTooltipOverlay extends Overlay {
2324
private static final int TOOLTIP_OFFSET_HEIGHT = 25;

src/main/java/shortestpath/PathTileOverlay.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import net.runelite.client.ui.overlay.OverlayLayer;
1919
import net.runelite.client.ui.overlay.OverlayPosition;
2020
import shortestpath.pathfinder.CollisionMap;
21+
import shortestpath.transport.Transport;
22+
import shortestpath.transport.TransportType;
2123

2224
public class PathTileOverlay extends Overlay {
2325
private final Client client;

src/main/java/shortestpath/ShortestPathPlugin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@
6464
import shortestpath.pathfinder.CollisionMap;
6565
import shortestpath.pathfinder.Pathfinder;
6666
import shortestpath.pathfinder.PathfinderConfig;
67+
import shortestpath.transport.Transport;
68+
import shortestpath.transport.TransportType;
6769

6870
@PluginDescriptor(
6971
name = "Shortest Path",

src/main/java/shortestpath/pathfinder/CollisionMap.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
import java.util.Collections;
55
import java.util.List;
66
import java.util.Set;
7-
import shortestpath.Transport;
7+
88
import shortestpath.WorldPointUtil;
9+
import shortestpath.transport.Transport;
910

1011
public class CollisionMap {
1112

src/main/java/shortestpath/pathfinder/PathfinderConfig.java

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,30 @@
44
import java.util.HashSet;
55
import java.util.List;
66
import java.util.Map;
7+
8+
import static shortestpath.transport.TransportType.AGILITY_SHORTCUT;
9+
import static shortestpath.transport.TransportType.BOAT;
10+
import static shortestpath.transport.TransportType.CANOE;
11+
import static shortestpath.transport.TransportType.CHARTER_SHIP;
12+
import static shortestpath.transport.TransportType.FAIRY_RING;
13+
import static shortestpath.transport.TransportType.GNOME_GLIDER;
14+
import static shortestpath.transport.TransportType.GRAPPLE_SHORTCUT;
15+
import static shortestpath.transport.TransportType.HOT_AIR_BALLOON;
16+
import static shortestpath.transport.TransportType.MAGIC_CARPET;
17+
import static shortestpath.transport.TransportType.MAGIC_MUSHTREE;
18+
import static shortestpath.transport.TransportType.MINECART;
19+
import static shortestpath.transport.TransportType.QUETZAL;
20+
import static shortestpath.transport.TransportType.SEASONAL_TRANSPORTS;
21+
import static shortestpath.transport.TransportType.SHIP;
22+
import static shortestpath.transport.TransportType.SPIRIT_TREE;
23+
import static shortestpath.transport.TransportType.TELEPORTATION_BOX;
24+
import static shortestpath.transport.TransportType.TELEPORTATION_ITEM;
25+
import static shortestpath.transport.TransportType.TELEPORTATION_LEVER;
26+
import static shortestpath.transport.TransportType.TELEPORTATION_MINIGAME;
27+
import static shortestpath.transport.TransportType.TELEPORTATION_PORTAL;
28+
import static shortestpath.transport.TransportType.TELEPORTATION_SPELL;
29+
import static shortestpath.transport.TransportType.WILDERNESS_OBELISK;
30+
731
import java.util.ArrayList;
832
import java.util.Arrays;
933
import java.util.Set;
@@ -28,34 +52,13 @@
2852
import shortestpath.Destination;
2953
import shortestpath.ItemVariations;
3054
import shortestpath.PrimitiveIntHashMap;
31-
import shortestpath.Transport;
32-
import shortestpath.TransportItems;
33-
import shortestpath.TransportType;
34-
import shortestpath.TransportVarbit;
35-
import shortestpath.TransportVarPlayer;
3655
import shortestpath.WorldPointUtil;
37-
import static shortestpath.TransportType.AGILITY_SHORTCUT;
38-
import static shortestpath.TransportType.GRAPPLE_SHORTCUT;
39-
import static shortestpath.TransportType.BOAT;
40-
import static shortestpath.TransportType.CANOE;
41-
import static shortestpath.TransportType.CHARTER_SHIP;
42-
import static shortestpath.TransportType.SHIP;
43-
import static shortestpath.TransportType.FAIRY_RING;
44-
import static shortestpath.TransportType.GNOME_GLIDER;
45-
import static shortestpath.TransportType.HOT_AIR_BALLOON;
46-
import static shortestpath.TransportType.MAGIC_CARPET;
47-
import static shortestpath.TransportType.MAGIC_MUSHTREE;
48-
import static shortestpath.TransportType.MINECART;
49-
import static shortestpath.TransportType.QUETZAL;
50-
import static shortestpath.TransportType.SEASONAL_TRANSPORTS;
51-
import static shortestpath.TransportType.SPIRIT_TREE;
52-
import static shortestpath.TransportType.TELEPORTATION_BOX;
53-
import static shortestpath.TransportType.TELEPORTATION_LEVER;
54-
import static shortestpath.TransportType.TELEPORTATION_MINIGAME;
55-
import static shortestpath.TransportType.TELEPORTATION_PORTAL;
56-
import static shortestpath.TransportType.TELEPORTATION_ITEM;
57-
import static shortestpath.TransportType.TELEPORTATION_SPELL;
58-
import static shortestpath.TransportType.WILDERNESS_OBELISK;
56+
import shortestpath.transport.Transport;
57+
import shortestpath.transport.TransportItems;
58+
import shortestpath.transport.TransportLoader;
59+
import shortestpath.transport.TransportType;
60+
import shortestpath.transport.TransportVarPlayer;
61+
import shortestpath.transport.TransportVarbit;
5962

6063
public class PathfinderConfig {
6164
private static final List<Integer> RUNE_POUCHES = Arrays.asList(
@@ -138,7 +141,7 @@ public PathfinderConfig(Client client, ShortestPathConfig config) {
138141
this.config = config;
139142
this.mapData = SplitFlagMap.fromResources();
140143
this.map = ThreadLocal.withInitial(() -> new CollisionMap(mapData));
141-
this.allTransports = Transport.loadAllFromResources();
144+
this.allTransports = TransportLoader.loadAllFromResources();
142145
this.usableTeleports = new HashSet<>(allTransports.size() / 20);
143146
this.transports = new HashMap<>(allTransports.size() / 2);
144147
this.transportsPacked = new PrimitiveIntHashMap<>(allTransports.size() / 2);

src/main/java/shortestpath/Transport.java renamed to src/main/java/shortestpath/transport/Transport.java

Lines changed: 5 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
package shortestpath;
1+
package shortestpath.transport;
22

3-
import java.io.IOException;
4-
import java.nio.charset.StandardCharsets;
53
import java.util.HashMap;
64
import java.util.HashSet;
75
import java.util.Map;
8-
import java.util.Scanner;
96
import java.util.Set;
107
import lombok.Getter;
118
import net.runelite.api.Quest;
129
import net.runelite.api.Skill;
10+
import shortestpath.ItemVariations;
11+
import shortestpath.Util;
12+
import shortestpath.WorldPointUtil;
1313
import lombok.extern.slf4j.Slf4j;
1414

1515
/**
@@ -20,7 +20,7 @@ public class Transport {
2020
public static final int UNDEFINED_ORIGIN = WorldPointUtil.UNDEFINED;
2121
public static final int UNDEFINED_DESTINATION = WorldPointUtil.UNDEFINED;
2222
/** A location placeholder different from null to use for permutation transports */
23-
private static final int LOCATION_PERMUTATION = WorldPointUtil.packWorldPoint(-1, -1, 1);
23+
public static final int LOCATION_PERMUTATION = WorldPointUtil.packWorldPoint(-1, -1, 1);
2424
private static final String DELIM_SPACE = " ";
2525
private static final String DELIM_MULTI = ";";
2626
private static final String DELIM_STATE = "=";
@@ -346,126 +346,4 @@ private static Set<Quest> findQuests(String questNamesCombined) {
346346
}
347347
return quests;
348348
}
349-
350-
private static void addTransports(Map<Integer, Set<Transport>> transports, String path, TransportType transportType) {
351-
addTransports(transports, path, transportType, 0);
352-
}
353-
354-
private static void addTransports(Map<Integer, Set<Transport>> transports, String path, TransportType transportType, int radiusThreshold) {
355-
final String DELIM_COLUMN = "\t";
356-
final String PREFIX_COMMENT = "#";
357-
358-
try {
359-
String s = new String(Util.readAllBytes(ShortestPathPlugin.class.getResourceAsStream(path)), StandardCharsets.UTF_8);
360-
Scanner scanner = new Scanner(s);
361-
362-
// Header line is the first line in the file and will start with either '#' or '# '
363-
String headerLine = scanner.nextLine();
364-
headerLine = headerLine.startsWith(PREFIX_COMMENT + " ") ? headerLine.replace(PREFIX_COMMENT + " ", PREFIX_COMMENT) : headerLine;
365-
headerLine = headerLine.startsWith(PREFIX_COMMENT) ? headerLine.replace(PREFIX_COMMENT, "") : headerLine;
366-
String[] headers = headerLine.split(DELIM_COLUMN);
367-
368-
Set<Transport> newTransports = new HashSet<>();
369-
370-
while (scanner.hasNextLine()) {
371-
String line = scanner.nextLine();
372-
373-
if (line.startsWith(PREFIX_COMMENT) || line.isBlank()) {
374-
continue;
375-
}
376-
377-
String[] fields = line.split(DELIM_COLUMN);
378-
Map<String, String> fieldMap = new HashMap<>();
379-
for (int i = 0; i < headers.length; i++) {
380-
if (i < fields.length) {
381-
fieldMap.put(headers[i], fields[i]);
382-
}
383-
}
384-
385-
Transport transport = new Transport(fieldMap, transportType);
386-
newTransports.add(transport);
387-
388-
}
389-
scanner.close();
390-
391-
/*
392-
* A transport with origin A and destination B is one-way and must
393-
* be duplicated as origin B and destination A to become two-way.
394-
* Example: key-locked doors
395-
*
396-
* A transport with origin A and a missing destination is one-way,
397-
* but can go from origin A to all destinations with a missing origin.
398-
* Example: fairy ring AIQ -> <blank>
399-
*
400-
* A transport with a missing origin and destination B is one-way,
401-
* but can go from all origins with a missing destination to destination B.
402-
* Example: fairy ring <blank> -> AIQ
403-
*
404-
* Identical transports from origin A to destination A are skipped, and
405-
* non-identical transports from origin A to destination A can be skipped
406-
* by specifying a radius threshold to ignore almost identical coordinates.
407-
* Example: fairy ring AIQ -> AIQ
408-
*/
409-
Set<Transport> transportOrigins = new HashSet<>();
410-
Set<Transport> transportDestinations = new HashSet<>();
411-
for (Transport transport : newTransports) {
412-
int origin = transport.getOrigin();
413-
int destination = transport.getDestination();
414-
// Logic to determine ordinary transport vs teleport vs permutation (e.g. fairy ring)
415-
if ((origin == UNDEFINED_ORIGIN && destination == UNDEFINED_DESTINATION)
416-
|| (origin == LOCATION_PERMUTATION && destination == LOCATION_PERMUTATION)) {
417-
continue;
418-
} else if (origin != LOCATION_PERMUTATION && origin != UNDEFINED_ORIGIN
419-
&& destination == LOCATION_PERMUTATION) {
420-
transportOrigins.add(transport);
421-
} else if (origin == LOCATION_PERMUTATION
422-
&& destination != LOCATION_PERMUTATION && destination != UNDEFINED_DESTINATION) {
423-
transportDestinations.add(transport);
424-
}
425-
if (origin != LOCATION_PERMUTATION
426-
&& destination != UNDEFINED_DESTINATION && destination != LOCATION_PERMUTATION
427-
&& (origin == UNDEFINED_ORIGIN || origin != destination)) {
428-
transports.computeIfAbsent(origin, k -> new HashSet<>()).add(transport);
429-
}
430-
}
431-
for (Transport origin : transportOrigins) {
432-
for (Transport destination : transportDestinations) {
433-
// The radius threshold prevents transport permutations from including (almost) same origin and destination
434-
if (WorldPointUtil.distanceBetween2D(origin.getOrigin(), destination.getDestination()) > radiusThreshold) {
435-
transports.computeIfAbsent(origin.getOrigin(), k -> new HashSet<>())
436-
.add(new Transport(origin, destination));
437-
}
438-
}
439-
}
440-
} catch (IOException e) {
441-
throw new RuntimeException(e);
442-
}
443-
}
444-
445-
public static HashMap<Integer, Set<Transport>> loadAllFromResources() {
446-
HashMap<Integer, Set<Transport>> transports = new HashMap<>();
447-
addTransports(transports, "/transports/transports.tsv", TransportType.TRANSPORT);
448-
addTransports(transports, "/transports/agility_shortcuts.tsv", TransportType.AGILITY_SHORTCUT);
449-
addTransports(transports, "/transports/boats.tsv", TransportType.BOAT);
450-
addTransports(transports, "/transports/canoes.tsv", TransportType.CANOE);
451-
addTransports(transports, "/transports/charter_ships.tsv", TransportType.CHARTER_SHIP);
452-
addTransports(transports, "/transports/ships.tsv", TransportType.SHIP);
453-
addTransports(transports, "/transports/fairy_rings.tsv", TransportType.FAIRY_RING);
454-
addTransports(transports, "/transports/gnome_gliders.tsv", TransportType.GNOME_GLIDER, 6);
455-
addTransports(transports, "/transports/hot_air_balloons.tsv", TransportType.HOT_AIR_BALLOON, 7);
456-
addTransports(transports, "/transports/magic_carpets.tsv", TransportType.MAGIC_CARPET);
457-
addTransports(transports, "/transports/magic_mushtrees.tsv", TransportType.MAGIC_MUSHTREE, 5);
458-
addTransports(transports, "/transports/minecarts.tsv", TransportType.MINECART);
459-
addTransports(transports, "/transports/quetzals.tsv", TransportType.QUETZAL);
460-
addTransports(transports, "/transports/seasonal_transports.tsv", TransportType.SEASONAL_TRANSPORTS);
461-
addTransports(transports, "/transports/spirit_trees.tsv", TransportType.SPIRIT_TREE, 5);
462-
addTransports(transports, "/transports/teleportation_items.tsv", TransportType.TELEPORTATION_ITEM);
463-
addTransports(transports, "/transports/teleportation_boxes.tsv", TransportType.TELEPORTATION_BOX);
464-
addTransports(transports, "/transports/teleportation_levers.tsv", TransportType.TELEPORTATION_LEVER);
465-
addTransports(transports, "/transports/teleportation_minigames.tsv", TransportType.TELEPORTATION_MINIGAME);
466-
addTransports(transports, "/transports/teleportation_portals.tsv", TransportType.TELEPORTATION_PORTAL);
467-
addTransports(transports, "/transports/teleportation_spells.tsv", TransportType.TELEPORTATION_SPELL);
468-
addTransports(transports, "/transports/wilderness_obelisks.tsv", TransportType.WILDERNESS_OBELISK);
469-
return transports;
470-
}
471349
}

src/main/java/shortestpath/TransportItems.java renamed to src/main/java/shortestpath/transport/TransportItems.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package shortestpath;
1+
package shortestpath.transport;
22

33
import java.util.Arrays;
44

0 commit comments

Comments
 (0)