From f13896051bcd0fa031b244f70fc3dde0f0c18666 Mon Sep 17 00:00:00 2001 From: mikeblunts <293524454+mikeblunts@users.noreply.github.com> Date: Sun, 14 Jun 2026 18:10:12 +1000 Subject: [PATCH] Show expected flip duration on Grand Exchange offer tooltips Cache the expectedDuration from each suggestion per item name in SuggestionManager and surface it as an "Est. time" line on the GE offer-slot tooltip, beneath the existing Profit line, reusing UIUtilities.formatSuggestionDuration. Co-authored-by: Claude Opus 4.8 --- .../controller/TooltipController.java | 16 ++++++++++++++-- .../flippingcopilot/model/SuggestionManager.java | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/flippingcopilot/controller/TooltipController.java b/src/main/java/com/flippingcopilot/controller/TooltipController.java index c34b8599..1da20dd8 100644 --- a/src/main/java/com/flippingcopilot/controller/TooltipController.java +++ b/src/main/java/com/flippingcopilot/controller/TooltipController.java @@ -1,5 +1,6 @@ package com.flippingcopilot.controller; +import com.flippingcopilot.model.SuggestionManager; import com.flippingcopilot.ui.UIUtilities; import com.flippingcopilot.util.ProfitCalculator; import lombok.RequiredArgsConstructor; @@ -22,11 +23,13 @@ public class TooltipController { private static final int SCRIPT_TOOLTIP_GE = 526; private static final int TOOLTIP_HEIGHT_WITH_PROFIT = 45; + private static final int TOOLTIP_LINE_HEIGHT = 13; private static final int WIDTH_PADDING = 4; private final Client client; private final ProfitCalculator profitCalculator; + private final SuggestionManager suggestionManager; public void tooltip(ScriptPostFired e) { if(e.getScriptId() != SCRIPT_TOOLTIP_GE) { @@ -58,8 +61,17 @@ public void tooltip(ScriptPostFired e) { if(name != null) { long profit = profitCalculator.getProfitByItemName(name); - text.setText(text.getText() + "
Profit: " + UIUtilities.quantityToRSDecimalStack(profit, false) + " gp"); - tooltip.setOriginalHeight(TOOLTIP_HEIGHT_WITH_PROFIT); + String updatedText = text.getText() + "
Profit: " + UIUtilities.quantityToRSDecimalStack(profit, false) + " gp"; + int height = TOOLTIP_HEIGHT_WITH_PROFIT; + + Double expectedSeconds = suggestionManager.getExpectedDurationForItem(name); + if (expectedSeconds != null) { + updatedText += "
Est. time: " + UIUtilities.formatSuggestionDuration(expectedSeconds); + height += TOOLTIP_LINE_HEIGHT; + } + + text.setText(updatedText); + tooltip.setOriginalHeight(height); int width = calculateTooltipWidth(text.getFont(), text.getText()); tooltip.setOriginalWidth(width); diff --git a/src/main/java/com/flippingcopilot/model/SuggestionManager.java b/src/main/java/com/flippingcopilot/model/SuggestionManager.java index 4ab4b9e7..4e043fa3 100644 --- a/src/main/java/com/flippingcopilot/model/SuggestionManager.java +++ b/src/main/java/com/flippingcopilot/model/SuggestionManager.java @@ -5,6 +5,8 @@ import javax.inject.Singleton; import java.time.Instant; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; @Singleton @Getter @@ -28,13 +30,24 @@ public class SuggestionManager { private int suggestionItemIdOnOfferSubmitted = -1; private OfferStatus suggestionOfferStatusOnOfferSubmitted = null; + // Most recent expected duration (seconds) Copilot predicted for each item, captured from each + // suggestion as it arrives. expectedDuration only lives on the live suggestion, so caching it by + // item lets the GE offer tooltip show an expected time for any item that has been suggested. + private final Map itemNameToExpectedDuration = new ConcurrentHashMap<>(); + public volatile int suggestionsDelayedUntil = 0; public void setSuggestion(Suggestion suggestion) { this.suggestion = suggestion; suggestionReceivedAt = Instant.now(); + if (suggestion != null && suggestion.getExpectedDuration() != null && suggestion.getName() != null) { + itemNameToExpectedDuration.put(suggestion.getName(), suggestion.getExpectedDuration()); + } + } + public Double getExpectedDurationForItem(String itemName) { + return itemNameToExpectedDuration.get(itemName); } public void setSuggestionError(HttpResponseException error) { @@ -52,6 +65,7 @@ public void reset() { suggestionError = null; suggestionItemIdOnOfferSubmitted = -1; suggestionOfferStatusOnOfferSubmitted = null; + itemNameToExpectedDuration.clear(); } public boolean suggestionOutOfDate() {