postie Posted April 21, 2014 Share Posted April 21, 2014 I've been trying to make a world hopper with a timer that i can use for buying items or mining. I have been using hashmaps to keep the world and system time but my problem is that as of right now i can't seem seem to find a way to instantly return a world once it goes over "X" amount of time, the only method i have checks if the key i give it is in the hashmap and then checks to see if its been longer than "X" amount of time. generating the worlds using a RNG means if it doesn't generate the world then it never revisits it or at least not soon enough to buy when items re-spawn. Does anyone have an ideas to another method of storing keys and values together that would let me check by value and return a key, or a work around for the hashmap. //postie Link to comment Share on other sites More sharing options...
Ziy Posted April 22, 2014 Share Posted April 22, 2014 Hashmap is a slight overkill if you are using world numbers as a key (why not an array using the world number as index?) you could also look into cyclic buffer or just a queue and just randomly pick from the 5 at the front as long as it satisfy your conditions 1 Link to comment Share on other sites More sharing options...
postie Posted April 22, 2014 Author Share Posted April 22, 2014 Okay thanks for the post ill have a look into that and let you know how it gets on. postie Link to comment Share on other sites More sharing options...
Ziy Posted April 22, 2014 Share Posted April 22, 2014 Cool :-) keep us updated Link to comment Share on other sites More sharing options...
postie Posted April 22, 2014 Author Share Posted April 22, 2014 I've decided to opt for the Queue (delayQueue) as i think it will be the most light weight, but i'm struggling with how to set different timeouts in 1 delayQueue. First time using delay queues and it all seems abit confusing. Link to comment Share on other sites More sharing options...
Swizzbeat Posted April 22, 2014 Share Posted April 22, 2014 I'm not sure why either you're attempting to over complicate things on purpose or without knowing it, but literally creating an array of worlds to hop to and then passing the hopWorld() method a random index will do exactly what you want. worldHopper.hopWorld(WORLD_ARRAY[Math.random() * WORLD_ARRAY.length]); Link to comment Share on other sites More sharing options...
Mr def nerd Posted April 22, 2014 Share Posted April 22, 2014 I'm not sure why either you're attempting to over complicate things on purpose or without knowing it, but literally creating an array of worlds to hop to and then passing the hopWorld() method a random index will do exactly what you want. worldHopper.hopWorld(WORLD_ARRAY[Math.random() * WORLD_ARRAY.length]); Well, in that case you won't be able to save the respawn time of the certain item/object you want. I guess HashMap with a class that stores the respawn time and uses the world as a key would work. You could use a simple for loop to go through every value in the hashmap and then if one of them has reached the respawn time you simply hop to the world with the id of that key 1 Link to comment Share on other sites More sharing options...
Ziy Posted April 23, 2014 Share Posted April 23, 2014 Hey I wrote a class to help you with the problem The pool introduces a random element without having to randomly iterate through the list each time (prioritising worlds we haven't visited for longer). import java.util.LinkedList; import java.util.Random; /** * * @author Ziy */ public class WorldManager { private int[] worlds = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // Example worlds private final int POOLSIZE = 5; // Size of pool (must be <= number of worlds) private final int ACCEPTABLE_TIME = 10; // in seconds private final LinkedList<Integer> queue = new LinkedList<>(); private final int[] pool = new int[POOLSIZE]; private final Random random = new Random(); private final long startTime; public WorldManager() { // Start by shuffling the worlds shuffleArray(worlds); // Add all the worlds to the queue for (int world : worlds) { queue.add(world); } // Move the first n (where n is the pool size) into the pool for (int i = 0; i < pool.length; i++) { pool[i] = queue.remove(); } // Repurpose the world array so we can now use it to house the times // We will index it using the world number worlds = new int[100]; // Set the start time startTime = System.currentTimeMillis(); } public int getNext() // returns world or -1 if no world satisfies { int startingRandom = random.nextInt(pool.length); // Pick a random world from the pool and iterate through the rest // to look for a valid world for (int i = 0; i < pool.length; i++) { int startingIndex = (startingRandom + i) % pool.length; int nextWorld = pool[startingIndex]; if (getTime() - worlds[nextWorld] >= ACCEPTABLE_TIME - 1 || worlds[nextWorld] == 0) { // Update world time worlds[nextWorld] = getTime() + 1; // Add world back to the queue queue.add(nextWorld); // Add the head of the queue to the pool pool[startingIndex] = queue.remove(); return 300 + nextWorld; // 300 added for OS } } // No world satisfies the time required return -1; } private int getTime() { return (int) ((System.currentTimeMillis() - startTime) / 1000); } private void shuffleArray(int[] array) { for (int i = array.length - 1; i > 0; i--) { int index = random.nextInt(i + 1); // Simple swap int a = array[index]; array[index] = array[i]; array[i] = a; } } // Test main - remove if unwanted public static void main(String[] args) { long startTime = System.currentTimeMillis(); WorldManager wm = new WorldManager(); while (System.currentTimeMillis() < startTime + 30000) // crudely run for 30 secs { int world = wm.getNext(); long time = (System.currentTimeMillis() - startTime) / 1000; if (world != -1) { System.out.println("World: " + world + " Time: " + time + "s"); } } } } Here is what it looks like when we run the main run: World: 307 Time: 0s World: 301 Time: 0s World: 305 Time: 0s World: 310 Time: 0s World: 308 Time: 0s World: 304 Time: 0s World: 309 Time: 0s World: 302 Time: 0s World: 306 Time: 0s World: 303 Time: 0s World: 308 Time: 10s World: 301 Time: 10s World: 304 Time: 10s World: 305 Time: 10s World: 306 Time: 10s World: 303 Time: 10s World: 307 Time: 10s World: 310 Time: 10s World: 302 Time: 10s World: 309 Time: 10s World: 304 Time: 20s World: 305 Time: 20s World: 307 Time: 20s World: 308 Time: 20s World: 306 Time: 20s World: 303 Time: 20s World: 310 Time: 20s World: 309 Time: 20s World: 302 Time: 20s World: 301 Time: 20s BUILD SUCCESSFUL (total time: 30 seconds) Quickly drawn diagram to explain the process 1 Link to comment Share on other sites More sharing options...
harrynoob Posted April 24, 2014 Share Posted April 24, 2014 you're all overcomplicating this guys :| you can keep using a HashMap<Integer, Integer> (or HashMap<Integer, Long>, whatever you prefer) just iterate over map.entrySet() and find the entry with the lowest value property; then return that entry and grab the key from it (aka your world) Link to comment Share on other sites More sharing options...
Ziy Posted April 24, 2014 Share Posted April 24, 2014 you're all overcomplicating this guys :| you can keep using a HashMap<Integer, Integer> (or HashMap<Integer, Long>, whatever you prefer) just iterate over map.entrySet() and find the entry with the lowest value property; then return that entry and grab the key from it (aka your world) Your approach will work, but.. Why not have worst case O(1) lookup each time if you can? You are iterating over the entire set of worlds each time which is unnecessary and can prove to be inefficient if you polling for available worlds continually This will repeat the same sequence of worlds every time You haven't mentioned the time constraint Link to comment Share on other sites More sharing options...
mattyo Posted April 24, 2014 Share Posted April 24, 2014 as others have said youve over complicated it, just keep it basic and it'll work fine Link to comment Share on other sites More sharing options...
harrynoob Posted April 24, 2014 Share Posted April 24, 2014 Your approach will work, but.. Why not have worst case O(1) lookup each time if you can? You are iterating over the entire set of worlds each time which is unnecessary and can prove to be inefficient if you polling for available worlds continually This will repeat the same sequence of worlds every time You haven't mentioned the time constraint Except... Having constant-time lookups is not necessary in this case. RS scripting should not care about lookup efficiency in most cases, since all delay comes from the game itself. Also, I seriously doubt the OP will continually poll for available worlds; once he finds an available one, he will hop there. In the meantime, either OP won't poll or he will be waiting for a world to become available. HashMaps will keep his code simple and clean, too. Also, the HashMap won't contain thousands of elements; at most 50-ish. tl;dr rs isn't performance sensitive, writing new class is useless Link to comment Share on other sites More sharing options...
Ziy Posted April 24, 2014 Share Posted April 24, 2014 Except... Having constant-time lookups is not necessary in this case. RS scripting should not care about lookup efficiency in most cases, since all delay comes from the game itself. Also, I seriously doubt the OP will continually poll for available worlds; once he finds an available one, he will hop there. In the meantime, either OP won't poll or he will be waiting for a world to become available. HashMaps will keep his code simple and clean, too. Also, the HashMap won't contain thousands of elements; at most 50-ish. tl;dr rs isn't performance sensitive, writing new class is useless I think my understanding of "useless" is different from yours I really can't be bothered discussing this further. It is all subjective after all. I prefer to spend a little bit of time and thought and produce reusable resources with minimal overheads Link to comment Share on other sites More sharing options...
harrynoob Posted April 24, 2014 Share Posted April 24, 2014 I think my understanding of "useless" is different from yours I really can't be bothered discussing this further. It is all subjective after all. I prefer to spend a little bit of time and thought and produce reusable resources with minimal overheads Your reasoning is understandable but it's pretty irrelevant in this case. It's never wrong to care about performance though, haha. Link to comment Share on other sites More sharing options...
Botre Posted April 24, 2014 Share Posted April 24, 2014 Your reasoning is understandable but it's pretty irrelevant in this case. It's never wrong to care about performance though, haha. Link to comment Share on other sites More sharing options...