aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorRime <81419447+Emirlol@users.noreply.github.com>2024-05-14 10:08:16 +0300
committerRime <81419447+Emirlol@users.noreply.github.com>2024-05-23 13:31:48 +0300
commit5ea7ccf01559a12f79bb06f4cf8f762895620038 (patch)
treef5e769e08414fcaf18253f6556f8592d23eb6faf /src/main
parent87c382b7ea32467d99f919ed8bdcbd2e7355e437 (diff)
downloadSkyblocker-5ea7ccf01559a12f79bb06f4cf8f762895620038.tar.gz
Skyblocker-5ea7ccf01559a12f79bb06f4cf8f762895620038.tar.bz2
Skyblocker-5ea7ccf01559a12f79bb06f4cf8f762895620038.zip
Refactor code, fix coach calculation and attempt to highlight the best affordable pick
I tried to make the best pick still have yellow highlight while keeping the best affordable pick green but it's not working for some reason and I have no idea what's causing it'.
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java120
1 files changed, 61 insertions, 59 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java
index 5c809a98..ed4d0f5e 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java
@@ -5,23 +5,25 @@ import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.render.gui.ColorHighlight;
import de.hysky.skyblocker.utils.render.gui.ContainerSolver;
import it.unimi.dsi.fastutil.ints.*;
-import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
+import net.minecraft.client.MinecraftClient;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.text.Text;
+import org.apache.commons.math3.analysis.function.Min;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
public class ChocolateFactorySolver extends ContainerSolver {
private static final Pattern CPS_PATTERN = Pattern.compile("([\\d,.]+) Chocolate per second");
private static final Pattern CPS_INCREASE_PATTERN = Pattern.compile("\\+([\\d,]+) Chocolate per second");
private static final Pattern COST_PATTERN = Pattern.compile("Cost ([\\d,]+) Chocolate");
- private static final Pattern HIRE_PATTERN = Pattern.compile("(HIRE|PROMOTE) ➜ \\[\\d+] \\S+ *");
private static final Pattern TOTAL_MULTIPLIER_PATTERN = Pattern.compile("Total Multiplier: ([\\d.]+)x");
private static final Pattern MULTIPLIER_INCREASE_PATTERN = Pattern.compile("\\+([\\d.]+)x Chocolate per second");
+ private static final Pattern TOTAL_CHOCOLATE_PATTERN = Pattern.compile("([\\d,]+) Chocolate");
public ChocolateFactorySolver() {
super("^Chocolate Factory$");
@@ -33,31 +35,36 @@ public class ChocolateFactorySolver extends ContainerSolver {
}
@Override
- protected void start(GenericContainerScreen screen) {
- markHighlightsDirty(); //Recalculate highlights when the screen is opened, which happens when upgrading rabbits
- }
-
- @Override
protected List<ColorHighlight> getColors(String[] groups, Int2ObjectMap<ItemStack> slots) {
- final Int2DoubleMap cpsIncreaseFactors = new Int2DoubleLinkedOpenHashMap(6); //There are only 5 rabbits on the screen + 1 for the coach
+ final Int2ObjectMap<Rabbit> cpsIncreaseFactors = new Int2ObjectLinkedOpenHashMap<>(6);
for (int i = 29; i <= 33; i++) { // The 5 rabbits slots are in 29, 30, 31, 32 and 33.
ItemStack item = slots.get(i);
if (item.getItem() != Items.PLAYER_HEAD || item.isEmpty()) continue;
- String lore = getConcattedLore(item);
- if (lore.isBlank()) continue;
-
- OptionalDouble cpsIncreaseFactor = getRabbitCPSIncreaseFactor(lore); // The 5 usual rabbits
- if (cpsIncreaseFactor.isEmpty()) continue; //Something went wrong, skip this item
- cpsIncreaseFactors.put(i, cpsIncreaseFactor.getAsDouble());
+ int finalI = i; //Java, pfft.
+ getRabbit(item).ifPresent(rabbit -> cpsIncreaseFactors.put(finalI, rabbit));
}
- OptionalDouble coachCpsIncreaseFactor = getCoachCPSIncreaseFactor(slots.get(45), slots.get(42)); // The coach
- if (!coachCpsIncreaseFactor.isEmpty()) cpsIncreaseFactors.put(42, coachCpsIncreaseFactor.getAsDouble());
+ //Coach is in slot 42 while the factory info item is in slot 45.
+ getCoach(slots.get(45), slots.get(42)).ifPresent(coach -> cpsIncreaseFactors.put(42, coach));
+ if (cpsIncreaseFactors.isEmpty()) return List.of(); //Something went wrong.
+
+ OptionalLong totalChocolate = getTotalChocolate(slots.get(13));
- Optional<Int2DoubleMap.Entry> bestSlot = cpsIncreaseFactors.int2DoubleEntrySet().stream().max(Map.Entry.comparingByValue());
- if (bestSlot.isEmpty()) return List.of(); //No valid slots found, somehow. This means something went wrong, despite all the checks thus far.
- return List.of(ColorHighlight.green(bestSlot.get().getIntKey()));
+ List<Int2ObjectMap.Entry<Rabbit>> sorted = cpsIncreaseFactors.int2ObjectEntrySet()
+ .stream() //Compare cost/cpsIncrease rather than cpsIncrease/cost to avoid getting close to 0 and losing precision.
+ .sorted(Comparator.comparingDouble(entry -> entry.getValue().cost() / entry.getValue().cpsIncrease())) //Ascending order, lower = better
+ .dropWhile(entry -> entry.getValue().cost == 0)
+ .collect(Collectors.toCollection(LinkedList::new));
+
+ Int2ObjectMap.Entry<Rabbit> bestEntry = sorted.removeFirst();
+ if (totalChocolate.isEmpty() || bestEntry.getValue().cost < totalChocolate.getAsLong()) return List.of(ColorHighlight.green(bestEntry.getIntKey()));
+
+ for (Int2ObjectMap.Entry<Rabbit> entry : sorted) {
+ if (entry.getValue().cost > totalChocolate.getAsLong()) continue;
+ return List.of(ColorHighlight.green(entry.getIntKey()), ColorHighlight.yellow(bestEntry.getIntKey()));
+ }
+ return List.of(ColorHighlight.green(bestEntry.getIntKey()));
}
/**
@@ -80,67 +87,59 @@ public class ChocolateFactorySolver extends ContainerSolver {
return stringBuilder.toString();
}
- private OptionalDouble getCoachCPSIncreaseFactor(ItemStack cpsItem, ItemStack coachItem) {
+ private Optional<Rabbit> getCoach(ItemStack cpsItem, ItemStack coachItem) {
+ if (coachItem.isEmpty() || cpsItem.isEmpty() || coachItem.getItem() != Items.PLAYER_HEAD || cpsItem.getItem() != Items.COCOA_BEANS) return Optional.empty();
String cpsItemLore = getConcattedLore(cpsItem);
Matcher cpsMatcher = CPS_PATTERN.matcher(cpsItemLore);
OptionalDouble currentCps = getDoubleFromMatcher(cpsMatcher);
- if (currentCps.isEmpty()) return OptionalDouble.empty();
+ if (currentCps.isEmpty()) return Optional.empty();
Matcher multiplierMatcher = TOTAL_MULTIPLIER_PATTERN.matcher(cpsItemLore);
OptionalDouble totalMultiplier = getDoubleFromMatcher(multiplierMatcher, cpsMatcher.end());
- if (totalMultiplier.isEmpty()) return OptionalDouble.empty();
+ if (totalMultiplier.isEmpty()) return Optional.empty();
String coachLore = getConcattedLore(coachItem);
Matcher multiplierIncreaseMatcher = MULTIPLIER_INCREASE_PATTERN.matcher(coachLore);
OptionalDouble currentCpsMultiplier = getDoubleFromMatcher(multiplierIncreaseMatcher);
- if (currentCpsMultiplier.isEmpty()) return OptionalDouble.empty();
+ if (currentCpsMultiplier.isEmpty()) return Optional.empty();
+
OptionalDouble nextCpsMultiplier = getDoubleFromMatcher(multiplierIncreaseMatcher);
if (nextCpsMultiplier.isEmpty()) { //This means that the coach isn't hired yet.
nextCpsMultiplier = currentCpsMultiplier; //So the first instance of the multiplier is actually the amount we'll get upon upgrading.
currentCpsMultiplier = OptionalDouble.of(0.0); //And so, we can re-assign values to the variables to make the calculation more readable.
}
- return OptionalDouble.of((currentCps.getAsDouble()/totalMultiplier.getAsDouble()) * (nextCpsMultiplier.getAsDouble() - currentCpsMultiplier.getAsDouble()));
+ Matcher costMatcher = COST_PATTERN.matcher(coachLore);
+ OptionalInt cost = getIntFromMatcher(costMatcher, multiplierIncreaseMatcher.end()); //Cost comes after the multiplier line
+ if (cost.isEmpty()) return Optional.empty();
+
+ return Optional.of(new Rabbit(currentCps.getAsDouble() / totalMultiplier.getAsDouble() * (nextCpsMultiplier.getAsDouble() - currentCpsMultiplier.getAsDouble()), cost.getAsInt()));
}
- /**
- * The "CPS increase factor" here is the increase in CPS per chocolate spent.
- * The highest value among the choices is the best one to pick.
- *
- * @param lore The lore of the item
- * @return The CPS increase factor of the item, or an empty optional if it couldn't be found
- */
- private OptionalDouble getRabbitCPSIncreaseFactor(String lore) {
- Matcher hireMatcher = HIRE_PATTERN.matcher(lore);
- if (!hireMatcher.find()) return OptionalDouble.empty(); //Not a hireable/promotable rabbit. Could be a locked or maxed rabbit.
-
- switch (hireMatcher.group(1)) {
- case "HIRE" -> {
- Matcher cpsMatcher = CPS_INCREASE_PATTERN.matcher(lore);
- OptionalInt cps = getIntFromMatcher(cpsMatcher, hireMatcher.end()); //Cps line is right after the hire line
- if (cps.isEmpty()) return OptionalDouble.empty();
-
- Matcher costMatcher = COST_PATTERN.matcher(lore);
- OptionalInt cost = getIntFromMatcher(costMatcher, cpsMatcher.end()); //Cost comes after the cps line
- if (cost.isEmpty()) return OptionalDouble.empty();
- return OptionalDouble.of(cps.getAsInt() / (double) cost.getAsInt());
- }
- case "PROMOTE" -> {
- Matcher cpsMatcher = CPS_INCREASE_PATTERN.matcher(lore);
- OptionalInt currentCps = getIntFromMatcher(cpsMatcher); //Current cps is before the hire line
- if (currentCps.isEmpty()) return OptionalDouble.empty();
- OptionalInt nextCps = getIntFromMatcher(cpsMatcher, hireMatcher.end()); //Next cps is right after the hire line
- if (nextCps.isEmpty()) return OptionalDouble.empty();
-
- Matcher costMatcher = COST_PATTERN.matcher(lore);
- OptionalInt cost = getIntFromMatcher(costMatcher, cpsMatcher.end()); //Cost comes after the cps line
- if (cost.isEmpty()) return OptionalDouble.empty();
- return OptionalDouble.of((nextCps.getAsInt() - currentCps.getAsInt()) / (double) cost.getAsInt());
- }
- default -> { return OptionalDouble.empty(); }
+ private Optional<Rabbit> getRabbit(ItemStack item) {
+ String lore = getConcattedLore(item);
+ Matcher cpsMatcher = CPS_INCREASE_PATTERN.matcher(lore);
+ OptionalInt currentCps = getIntFromMatcher(cpsMatcher);
+ if (currentCps.isEmpty()) return Optional.empty();
+ OptionalInt nextCps = getIntFromMatcher(cpsMatcher);
+ if (nextCps.isEmpty()) {
+ nextCps = currentCps; //This means that the rabbit isn't hired yet.
+ currentCps = OptionalInt.of(0); //So the first instance of the cps is actually the amount we'll get upon hiring.
}
+
+ Matcher costMatcher = COST_PATTERN.matcher(lore);
+ OptionalInt cost = getIntFromMatcher(costMatcher, cpsMatcher.end()); //Cost comes after the cps line
+ if (cost.isEmpty()) return Optional.empty();
+ return Optional.of(new Rabbit(nextCps.getAsInt() - currentCps.getAsInt(), cost.getAsInt()));
+ }
+
+ private OptionalLong getTotalChocolate(ItemStack item) {
+ if (item.isEmpty() || item.getItem() != Items.PLAYER_HEAD) return OptionalLong.empty();
+ Matcher matcher = TOTAL_CHOCOLATE_PATTERN.matcher(item.getName().getString());
+ if (!matcher.find()) return OptionalLong.empty();
+ return OptionalLong.of(Long.parseLong(matcher.group(1).replace(",", "")));
}
private OptionalInt getIntFromMatcher(Matcher matcher) {
@@ -160,4 +159,7 @@ public class ChocolateFactorySolver extends ContainerSolver {
if (!matcher.find(startingIndex)) return OptionalDouble.empty();
return OptionalDouble.of(Double.parseDouble(matcher.group(1).replace(",", "")));
}
+
+ private record Rabbit(double cpsIncrease, int cost) {
+ }
}