diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java index 38bd105709..a34c6a72f9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/OverviewTabPanel.java @@ -114,25 +114,39 @@ class OverviewTabPanel extends TabContentPanel stopwatchOverview.updateStatus(stopwatches + " active stopwatch" + (stopwatches == 1 ? "" : "es"), ColorScheme.PROGRESS_COMPLETE_COLOR); } - farmingOverviews.forEach((patchType, panel) -> updateItemPanel(panel, farmingTracker.getCompletionTime(patchType))); - updateItemPanel(birdHouseOverview, birdHouseTracker.getCompletionTime()); + farmingOverviews.forEach((patchType, panel) -> + updateItemPanel(panel, farmingTracker.getSummary(patchType), farmingTracker.getCompletionTime(patchType))); + + updateItemPanel(birdHouseOverview, birdHouseTracker.getSummary(), birdHouseTracker.getCompletionTime()); } - private void updateItemPanel(OverviewItemPanel panel, long completionTime) + private void updateItemPanel(OverviewItemPanel panel, SummaryState summary, long completionTime) { - long duration = completionTime - Instant.now().getEpochSecond(); + switch (summary) + { + case COMPLETED: + case IN_PROGRESS: + { + long duration = completionTime - Instant.now().getEpochSecond(); - if (completionTime < 0) - { - panel.updateStatus("Unknown", Color.GRAY); - } - else if (duration <= 0) - { - panel.updateStatus("Ready", ColorScheme.PROGRESS_COMPLETE_COLOR); - } - else - { - panel.updateStatus("Ready " + getFormattedEstimate(duration, config.estimateRelative()), Color.GRAY); + if (duration <= 0) + { + panel.updateStatus("Ready", ColorScheme.PROGRESS_COMPLETE_COLOR); + } + else + { + panel.updateStatus("Ready " + getFormattedEstimate(duration, config.estimateRelative()), Color.GRAY); + } + + break; + } + case EMPTY: + panel.updateStatus("Empty", Color.GRAY); + break; + case UNKNOWN: + default: + panel.updateStatus("Unknown", Color.GRAY); + break; } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/SummaryState.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/SummaryState.java new file mode 100644 index 0000000000..3dc659f53e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/SummaryState.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, Daniel Teo + * 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.timetracking; + +public enum SummaryState +{ + COMPLETED, + IN_PROGRESS, + EMPTY, + UNKNOWN +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java index d88357c180..f49f5088bd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java @@ -34,6 +34,7 @@ import net.runelite.api.Varbits; import net.runelite.api.coords.WorldPoint; import net.runelite.client.config.ConfigManager; import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.timetracking.SummaryState; import net.runelite.client.plugins.timetracking.Tab; import net.runelite.client.plugins.timetracking.TimeTrackingConfig; @@ -49,6 +50,14 @@ public class FarmingTracker private final TimeTrackingConfig config; private final FarmingWorld farmingWorld; + private final Map summaries = new EnumMap<>(PatchImplementation.class); + + /** + * The time at which all patches of a particular type will be ready to be harvested, + * or {@code -1} if we have no data about any patch of the given type. + */ + private final Map completionTimes = new EnumMap<>(PatchImplementation.class); + @Inject private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager, TimeTrackingConfig config, FarmingWorld farmingWorld) @@ -61,15 +70,6 @@ public class FarmingTracker } - /** - * The time at which all patches of a particular type will be ready to be harvested, - * or {@code -1} if we have no data about any patch of the given type. - * - * Each value is set to {@code 0} if all patches of that type have already completed - * when updating the value. - */ - private Map completionTimes = new EnumMap<>(PatchImplementation.class); - public FarmingTabPanel createTabPanel(Tab tab) { return new FarmingTabPanel(client, itemManager, configManager, config, farmingWorld.getTabs().get(tab)); @@ -140,6 +140,7 @@ public class FarmingTracker public void loadCompletionTimes() { + summaries.clear(); completionTimes.clear(); for (PatchImplementation patchType : PatchImplementation.values()) @@ -148,6 +149,12 @@ public class FarmingTracker } } + public SummaryState getSummary(PatchImplementation patchType) + { + SummaryState summary = summaries.get(patchType); + return summary == null ? SummaryState.UNKNOWN : summary; + } + /** * Gets the overall completion time for the given patch type. * @see #completionTimes @@ -166,6 +173,7 @@ public class FarmingTracker { long maxCompletionTime = 0; boolean allUnknown = true; + boolean allEmpty = true; for (FarmingPatch patch : farmingWorld.getPatchTypes().get(patchType)) { @@ -204,6 +212,8 @@ public class FarmingTracker if (state.getProduce() != Produce.WEEDS && state.getProduce() != Produce.SCARECROW) { + allEmpty = false; + // update max duration if this patch takes longer to grow if (tickrate > 0) { @@ -222,11 +232,24 @@ public class FarmingTracker if (allUnknown) { + summaries.put(patchType, SummaryState.UNKNOWN); completionTimes.put(patchType, -1L); - return; } - - completionTimes.put(patchType, (maxCompletionTime <= Instant.now().getEpochSecond()) ? 0 : maxCompletionTime); + else if (allEmpty) + { + summaries.put(patchType, SummaryState.EMPTY); + completionTimes.put(patchType, -1L); + } + else if (maxCompletionTime <= Instant.now().getEpochSecond()) + { + summaries.put(patchType, SummaryState.COMPLETED); + completionTimes.put(patchType, 0L); + } + else + { + summaries.put(patchType, SummaryState.IN_PROGRESS); + completionTimes.put(patchType, maxCompletionTime); + } } /** diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java index f48afef8c7..c61b952cee 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/hunter/BirdHouseTracker.java @@ -41,6 +41,7 @@ import net.runelite.api.coords.WorldPoint; import net.runelite.client.Notifier; import net.runelite.client.config.ConfigManager; import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.timetracking.SummaryState; import net.runelite.client.plugins.timetracking.TimeTrackingConfig; @Singleton @@ -60,6 +61,16 @@ public class BirdHouseTracker @Getter(AccessLevel.PACKAGE) private final ConcurrentMap birdHouseData = new ConcurrentHashMap<>(); + @Getter + private SummaryState summary = SummaryState.UNKNOWN; + + /** + * The time at which all the bird houses will be ready to be dismantled, + * or {@code -1} if we have no data about any of the bird house spaces. + */ + @Getter + private long completionTime = -1; + @Inject private BirdHouseTracker(Client client, ItemManager itemManager, ConfigManager configManager, TimeTrackingConfig config, Notifier notifier) @@ -71,16 +82,6 @@ public class BirdHouseTracker this.notifier = notifier; } - /** - * The time at which all the bird houses will be ready to be dismantled, - * or {@code -1} if we have no data about any of the bird house spaces. - * - * This is set to {@code 0} if the bird houses have already completed - * when updating it. - */ - @Getter - private long completionTime = -1; - public BirdHouseTabPanel createBirdHouseTabPanel() { return new BirdHouseTabPanel(itemManager, this, config); @@ -176,8 +177,9 @@ public class BirdHouseTracker */ public boolean checkCompletion() { - if (completionTime > 0 && completionTime < Instant.now().getEpochSecond()) + if (summary == SummaryState.IN_PROGRESS && completionTime < Instant.now().getEpochSecond()) { + summary = SummaryState.COMPLETED; completionTime = 0; if (config.birdHouseNotification()) @@ -199,20 +201,43 @@ public class BirdHouseTracker { if (birdHouseData.isEmpty()) { + summary = SummaryState.UNKNOWN; completionTime = -1; return; } + boolean allEmpty = true; long maxCompletionTime = 0; for (BirdHouseData data : birdHouseData.values()) { - if (BirdHouseState.fromVarpValue(data.getVarp()) == BirdHouseState.SEEDED) + final BirdHouseState state = BirdHouseState.fromVarpValue(data.getVarp()); + + if (state != BirdHouseState.EMPTY) + { + allEmpty = false; + } + + if (state == BirdHouseState.SEEDED) { maxCompletionTime = Math.max(maxCompletionTime, data.getTimestamp() + BIRD_HOUSE_DURATION); } } - completionTime = (maxCompletionTime <= Instant.now().getEpochSecond()) ? 0 : maxCompletionTime; + if (allEmpty) + { + summary = SummaryState.EMPTY; + completionTime = 0; + } + else if (maxCompletionTime <= Instant.now().getEpochSecond()) + { + summary = SummaryState.COMPLETED; + completionTime = 0; + } + else + { + summary = SummaryState.IN_PROGRESS; + completionTime = maxCompletionTime; + } } private void saveToConfig(Map updatedData)