aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/at/hannibal2')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairDataDisplay.kt291
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt277
3 files changed, 300 insertions, 278 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt
index 25abb16ed..9fcbbad0b 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt
@@ -69,7 +69,7 @@ object ExperimentationTableAPI {
*/
val rewardPattern by patternGroup.pattern(
"rewards",
- "\\d{1,3}k Enchanting Exp|Enchanted Book|(?:Titanic |Grand |\\b)Experience Bottle|Metaphysical Serum|Experiment The Fish",
+ "\\d{1,3}k Enchanting Exp|Enchanted Book|(?:Titanic |Grand |\\b)Experience Bottle|Metaphysical Serum|Experiment the Fish",
)
/**
@@ -132,6 +132,14 @@ object ExperimentationTableAPI {
)
/**
+ * REGEX-TEST: Remaining Clicks: 22
+ */
+ val remainingClicksPattern by patternGroup.pattern(
+ "clicks",
+ "Remaining Clicks: (?<clicks>\\d+)"
+ )
+
+ /**
* REGEX-TEST: ☕ You renewed the experiment table! (1/3)
*/
val experimentRenewPattern by patternGroup.pattern(
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairDataDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairDataDisplay.kt
new file mode 100644
index 000000000..627974e6b
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairDataDisplay.kt
@@ -0,0 +1,291 @@
+package at.hannibal2.skyhanni.features.inventory.experimentationtable
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.events.GuiContainerEvent.SlotClickEvent
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.remainingClicksPattern
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.CollectionUtils.equalsOneOf
+import at.hannibal2.skyhanni.utils.DelayedRun
+import at.hannibal2.skyhanni.utils.InventoryUtils
+import at.hannibal2.skyhanni.utils.ItemUtils.getLore
+import at.hannibal2.skyhanni.utils.LorenzUtils.isAnyOf
+import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
+import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
+import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings
+import at.hannibal2.skyhanni.utils.StringUtils.removeColor
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.milliseconds
+
+// TODO important: all use cases of listOf in combination with string needs to be gone. no caching, constant new list creation, and bad design.
+@SkyHanniModule
+object SuperpairDataDisplay {
+
+ private val config get() = SkyHanniMod.feature.inventory.experimentationTable
+
+ private data class SuperpairItem(val index: Int, val reward: String, val damage: Int)
+ private data class FoundData(val item: SuperpairItem? = null, val first: SuperpairItem? = null, val second: SuperpairItem? = null)
+
+ private enum class FoundType {
+ NORMAL,
+ POWERUP,
+ MATCH,
+ PAIR
+ }
+
+ private val sideSpaces1 = listOf(17, 18, 26, 27, 35, 36)
+ private val sideSpaces2 = listOf(16, 17, 18, 19, 25, 26, 27, 28, 34, 35, 36, 37)
+ private val emptySuperpairItem = SuperpairItem(-1, "", -1)
+
+ private var display = emptyList<String>()
+ private var uncoveredItems = mutableMapOf<Int, SuperpairItem>()
+ private var found = mutableMapOf<FoundType, MutableList<FoundData>>()
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ display = emptyList()
+
+ uncoveredItems = mutableMapOf()
+ found.clear()
+ }
+
+ @SubscribeEvent
+ fun onChestGuiOverlayRendered(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) {
+ if (!isEnabled()) return
+ if (display.isEmpty()) display = drawDisplay()
+
+ config.superpairDisplayPosition.renderStrings(display, posLabel = "Superpair Experiment Information")
+ }
+
+ @SubscribeEvent
+ fun onSlotClick(event: SlotClickEvent) {
+ if (!isEnabled()) return
+ val currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return
+
+ val item = event.item ?: return
+ if (isOutOfBounds(event.slotId, currentExperiment) || item.displayName.removeColor() == "?") return
+
+ val clicksItem = InventoryUtils.getItemAtSlotIndex(4)
+
+ // TODO add variable name to indicate what is going on here
+ if (uncoveredItems.none { it.value.index == event.slotId && it.key == uncoveredItems.keys.max() }) {
+ if (clicksItem != null) {
+ remainingClicksPattern.matchMatcher(clicksItem.displayName.removeColor()) { if (group("clicks").toInt() == 0) return }
+ }
+
+ handleItem(event.slotId)
+ }
+ }
+
+ private fun handleItem(slot: Int) = DelayedRun.runDelayed(200.milliseconds) {
+ val itemNow = InventoryUtils.getItemAtSlotIndex(slot) ?: return@runDelayed
+ val itemName = itemNow.displayName.removeColor()
+ val reward = convertToReward(itemNow)
+ val itemData = SuperpairItem(slot, reward, itemNow.itemDamage)
+ val uncovered = uncoveredItems.keys.maxOrNull() ?: -1
+
+ if (isWaiting(itemName)) return@runDelayed
+
+ if (uncoveredItems.none { it.key == uncovered && it.value.index == slot }) uncoveredItems[uncovered + 1] = itemData
+
+ when {
+ isPowerUp(reward) -> handlePowerUp(itemData, uncovered + 1)
+ isReward(itemName) -> handleReward(itemData, uncovered + 1)
+ }
+
+ val since = clicksSinceSeparator(uncoveredItems)
+
+ val lastReward = uncoveredItems.entries.last().value.reward
+ // TODO use repo patterns for "Instant Find"
+ if ((since >= 2 || (since == -1 && uncoveredItems.size >= 2)) && lastReward != "Instant Find") uncoveredItems[uncovered + 2] =
+ emptySuperpairItem
+
+ display = drawDisplay()
+ }
+
+ private fun handlePowerUp(item: SuperpairItem, uncovered: Int) {
+ // TODO use repo patterns for "Instant Find"
+ if (item.reward != "Instant Find") uncoveredItems.remove(uncovered)
+
+ val itemData = FoundData(item = item)
+ found.getOrPut(FoundType.POWERUP) { mutableListOf(itemData) }.apply { if (!contains(itemData)) add(itemData) }
+ }
+
+ private fun handleReward(item: SuperpairItem, uncovered: Int) {
+ val last = uncoveredItems.getOrDefault(uncovered - 1, item)
+
+ if (isWaiting(last.reward)) return
+
+ when {
+ // TODO use repo patterns for "Instant Find"
+ last.reward == "Instant Find" -> handleInstantFind(item, uncovered)
+ hasFoundPair(item, last) -> handleFoundPair(item, last)
+ hasFoundMatch(item) -> handleFoundMatch(item)
+ else -> handleNormalReward(item)
+ }
+
+ println(found)
+ }
+
+ private fun handleInstantFind(item: SuperpairItem, uncovered: Int) {
+ uncoveredItems[uncovered - 1] = item
+ uncoveredItems[uncovered] = emptySuperpairItem
+
+ handleFoundPair(item, emptySuperpairItem)
+ }
+
+ private fun handleFoundPair(
+ first: SuperpairItem,
+ second: SuperpairItem,
+ ) {
+ found.entries.forEach {
+ when (it.key) {
+ FoundType.MATCH -> it.value.removeIf { data -> data.first?.sameAs(first) ?: false || data.second?.sameAs(first) ?: false }
+ FoundType.NORMAL -> it.value.removeIf { data -> data.item?.sameAs(first) ?: false || data.item?.sameAs(second) ?: false }
+ else -> {}
+ }
+ }
+
+ val pairData = FoundData(first = first, second = second)
+
+ found.getOrPut(FoundType.PAIR) { mutableListOf(pairData) }.apply { if (!contains(pairData)) add(pairData) }
+ }
+
+ private fun handleFoundMatch(item: SuperpairItem) {
+ // TODO better name
+ val match = uncoveredItems.values.find { it.index != item.index && it.sameAs(item) } ?: return
+
+ found.entries.forEach {
+ when {
+ it.key.isAnyOf(FoundType.MATCH, FoundType.PAIR) -> {
+ // TODO extract logic in some way
+ if (it.value.any { data ->
+ (data.first?.index ?: -1).equalsOneOf(item.index, match.index) ||
+ (data.second?.index
+ ?: -1).equalsOneOf(item.index, match.index)
+ }) {
+ return
+ }
+ }
+
+ it.key == FoundType.NORMAL -> it.value.removeIf { data ->
+ (data.item?.index ?: -1).equalsOneOf(item.index, match.index)
+ }
+
+ else -> {}
+ }
+ }
+
+ val pairData = FoundData(first = item, second = match)
+ found.getOrPut(FoundType.MATCH) { mutableListOf(pairData) }.apply { if (!contains(pairData)) add(pairData) }
+ }
+
+ private fun handleNormalReward(item: SuperpairItem) {
+ for ((key, value) in found.entries) {
+ when {
+ key.isAnyOf(FoundType.MATCH, FoundType.PAIR) -> {
+ if (value.any { data ->
+ item.index.equalsOneOf(data.first?.index ?: -1, data.second?.index ?: -1)
+ }) return
+ }
+
+ else -> if (value.any { data ->
+ (data.item?.index ?: -1) == item.index && data.item?.sameAs(item) == true
+ }) return
+ }
+ }
+
+ val itemData = FoundData(item = item)
+ found.getOrPut(FoundType.NORMAL) { mutableListOf(itemData) }.apply { if (!contains(itemData)) add(itemData) }
+ }
+
+ private fun drawDisplay() = buildList {
+ val currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return emptyList<String>()
+
+ add("§6Superpair Experimentation Data")
+ add("")
+
+ val normals = found.entries.firstOrNull { it.key == FoundType.NORMAL }?.value ?: mutableListOf()
+ val powerups = found.entries.firstOrNull { it.key == FoundType.POWERUP }?.value ?: mutableListOf()
+ val matches = found.entries.firstOrNull { it.key == FoundType.MATCH }?.value ?: mutableListOf()
+ val pairs = found.entries.firstOrNull { it.key == FoundType.PAIR }?.value ?: mutableListOf()
+ val possiblePairs = calculatePossiblePairs(currentExperiment)
+
+ if (pairs.isNotEmpty()) add("§2Found")
+ for (pair in pairs) {
+ val prefix = determinePrefix(pairs.indexOf(pair), pairs.lastIndex)
+ add(" $prefix §a${pair.first?.reward ?: ""}")
+ }
+ if (matches.isNotEmpty()) add("§eMatched")
+ for (match in matches) {
+ val prefix = determinePrefix(matches.indexOf(match), matches.lastIndex)
+ add(" $prefix §e${match.first?.reward ?: ""}")
+ }
+ if (powerups.isNotEmpty()) add("§bPowerUp")
+ for (powerup in powerups) {
+ val prefix = determinePrefix(powerups.indexOf(powerup), powerups.size - 1)
+ add(" $prefix §b${powerup.item?.reward ?: ""}")
+ }
+ val toAdd = mutableListOf<String>()
+ if (possiblePairs >= 1) toAdd.add("§ePairs - $possiblePairs")
+ if (2 - powerups.size >= 1) toAdd.add("§bPowerUps - ${2 - powerups.size}")
+ if (normals.isNotEmpty()) toAdd.add("§7Normals - ${normals.size}")
+
+ if (toAdd.isNotEmpty()) {
+ add("")
+ add("§4Not found")
+ }
+ for (string in toAdd) if (string != toAdd.last()) add(" ├ $string") else add(" └ $string")
+ }
+
+ private fun calculatePossiblePairs(currentExperiment: Experiment) =
+ ((currentExperiment.gridSize - 2) / 2) - found.filter { it.key != FoundType.POWERUP }.values.sumOf { it.size }
+
+ private fun convertToReward(item: ItemStack) = if (item.displayName.removeColor() == "Enchanted Book") item.getLore()[2].removeColor()
+ else item.displayName.removeColor()
+
+ private fun determinePrefix(index: Int, lastIndex: Int) = if (index == lastIndex) "└" else "├"
+
+ private fun hasFoundPair(
+ first: SuperpairItem,
+ second: SuperpairItem,
+ ) = first.index != second.index && first.sameAs(second)
+
+ // TODO extract logic greatly
+ private fun hasFoundMatch(firstItem: SuperpairItem) =
+ uncoveredItems.any { it.value.index != firstItem.index && it.value.sameAs(firstItem) } &&
+ found.entries.none {
+ it.key.isAnyOf(FoundType.PAIR, FoundType.MATCH) &&
+ it.value.any { data ->
+ firstItem.index.equalsOneOf(data.first?.index ?: -1, data.second?.index ?: -1)
+ }
+ }
+
+ private fun isPowerUp(reward: String) = ExperimentationTableAPI.powerUpPattern.matches(reward)
+
+ private fun isReward(reward: String) =
+ ExperimentationTableAPI.rewardPattern.matches(reward) || ExperimentationTableAPI.powerUpPattern.matches(reward)
+
+ // TODO use repo patterns instead
+ private fun isWaiting(itemName: String) =
+ listOf("Click any button!", "Click a second button!", "Next button is instantly rewarded!").contains(itemName)
+
+ private fun clicksSinceSeparator(list: MutableMap<Int, SuperpairItem>): Int {
+ val lastIndex = list.entries.indexOfLast { it.value == emptySuperpairItem }
+ return if (lastIndex != -1) list.size - 1 - lastIndex else -1
+ }
+
+ private fun isOutOfBounds(slot: Int, experiment: Experiment): Boolean =
+ slot <= experiment.startSlot ||
+ slot >= experiment.endSlot ||
+ (if (experiment.sideSpace == 1) slot in sideSpaces1 else slot in sideSpaces2)
+
+ private fun SuperpairItem?.sameAs(other: SuperpairItem) = this?.reward == other.reward && this?.damage == other.damage
+
+ private fun isEnabled() =
+ IslandType.PRIVATE_ISLAND.isInIsland() && config.superpairDisplay && ExperimentationTableAPI.getCurrentExperiment() != null
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt
deleted file mode 100644
index cb3102ca8..000000000
--- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt
+++ /dev/null
@@ -1,277 +0,0 @@
-package at.hannibal2.skyhanni.features.inventory.experimentationtable
-
-import at.hannibal2.skyhanni.SkyHanniMod
-import at.hannibal2.skyhanni.events.GuiContainerEvent.SlotClickEvent
-import at.hannibal2.skyhanni.events.GuiRenderEvent
-import at.hannibal2.skyhanni.events.InventoryCloseEvent
-import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
-import at.hannibal2.skyhanni.utils.InventoryUtils
-import at.hannibal2.skyhanni.utils.ItemUtils.getLore
-import at.hannibal2.skyhanni.utils.LorenzUtils
-import at.hannibal2.skyhanni.utils.RegexUtils.matches
-import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings
-import at.hannibal2.skyhanni.utils.SimpleTimeMark
-import at.hannibal2.skyhanni.utils.StringUtils.removeColor
-import net.minecraft.item.ItemStack
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import kotlin.time.Duration.Companion.milliseconds
-
-// TODO important: all use cases of listOf in combination with string needs to be gone. no caching, constant new list creation, and bad design.
-@SkyHanniModule
-object SuperpairExperimentInformationDisplay {
-
- private val config get() = SkyHanniMod.feature.inventory.experimentationTable
-
- private var display = emptyList<String>()
-
- private var uncoveredAt = 0
- private var uncoveredItems = mutableListOf<Pair<Int, String>>()
- private var possiblePairs = 0
-
- data class Item(val index: Int, val name: String)
- data class ItemPair(val first: Item, val second: Item)
-
- // TODO remove string. use enum instead! maybe even create new data type instead of map of pairs
- private var found = mutableMapOf<Pair<Item?, ItemPair?>, String>()
-
- private var toCheck = mutableListOf<Pair<Int, Int>>()
- private var lastClicked = mutableListOf<Pair<Int, Int>>()
- private var lastClick = SimpleTimeMark.farPast()
- private var currentExperiment = Experiment.NONE
- private var instantFind = 0
-
- private val sideSpaces1 = listOf(17, 18, 26, 27, 35, 36)
- private val sideSpaces2 = listOf(16, 17, 18, 19, 25, 26, 27, 28, 34, 35, 36, 37)
-
- @SubscribeEvent
- fun onInventoryClose(event: InventoryCloseEvent) {
- display = emptyList()
-
- uncoveredAt = 0
- uncoveredItems.clear()
- possiblePairs = 0
-
- found.clear()
- toCheck.clear()
- lastClicked.clear()
- lastClick = SimpleTimeMark.farPast()
- currentExperiment = Experiment.NONE
- instantFind = 0
- }
-
- @SubscribeEvent
- fun onChestGuiOverlayRendered(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) {
- if (!isEnabled()) return
- config.superpairDisplayPosition.renderStrings(display, posLabel = "Superpair Experiment Information")
- display = checkItems(toCheck)
- }
-
- @SubscribeEvent
- fun onSlotClick(event: SlotClickEvent) {
- if (!isEnabled()) return
- currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return
-
- if (isOutOfBounds(event.slotId, currentExperiment)) return
- val item = event.item ?: return
- if (item.displayName.removeColor() == "?") return
- val clicksItem = InventoryUtils.getItemAtSlotIndex(4)
-
- if (lastClicked.none { it.first == event.slotId && it.second == uncoveredAt } && lastClick.passedSince() > 100.milliseconds) {
- if (clicksItem != null && clicksItem.displayName.removeColor().split(" ")[1] == "0") return
- lastClicked.add(Pair(event.slotId, uncoveredAt))
- lastClick = SimpleTimeMark.now()
- toCheck.add(event.slotId to uncoveredAt)
- uncoveredAt += 1
- }
- }
-
- private fun checkItems(check: MutableList<Pair<Int, Int>>): List<String> {
- currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return listOf()
- if (check.isEmpty()) return drawDisplay()
-
- for ((slot, uncovered) in check) {
- val itemNow = InventoryUtils.getItemAtSlotIndex(slot) ?: return drawDisplay()
- val itemName = itemNow.displayName.removeColor()
-
- if (isWaiting(itemName) || isOutOfBounds(slot, currentExperiment)) return drawDisplay()
-
- val reward = convertToReward(itemNow)
- if (uncoveredItems.none { it.first == slot }) uncoveredItems.add(Pair(slot, reward))
-
- when {
- isPowerUp(reward) -> handlePowerUp(slot, reward)
- isReward(itemName) -> handleReward(slot, uncovered, reward)
- }
-
- possiblePairs = calculatePossiblePairs()
-
- val since = clicksSinceSeparator(lastClicked)
-
- if ((since >= 2 || (since == -1 && lastClicked.size >= 2)) && instantFind == 0) {
- lastClicked.add(-1 to uncoveredAt)
- uncoveredAt += 1
- }
- toCheck.removeIf { it.first == slot }
-
- return drawDisplay()
- }
- possiblePairs = calculatePossiblePairs()
- return drawDisplay()
- }
-
- private fun handlePowerUp(slot: Int, reward: String) {
- val item = toEither(Item(slot, reward))
-
- found[item] = "Powerup"
- possiblePairs--
- lastClicked.removeIf { it.first == slot }
- uncoveredAt -= 1
- if (reward == "Instant Find") instantFind += 1
- }
-
- private fun handleReward(slot: Int, uncovered: Int, reward: String) {
- val lastSlotClicked =
- if (instantFind == 0 && lastClicked.none { it.first == -1 && it.second == uncovered - 1 } && lastClicked.size != 1) lastClicked.find { it.second == uncovered - 1 }
- ?: return else lastClicked.find { it.second == uncovered } ?: return
-
- val lastItem = InventoryUtils.getItemAtSlotIndex(lastSlotClicked.first) ?: return
- val itemClicked = InventoryUtils.getItemAtSlotIndex(slot) ?: return
-
- val lastItemName = convertToReward(lastItem)
-
- if (isWaiting(lastItemName)) return
-
- when {
- instantFind >= 1 -> {
- handleFoundPair(slot, reward, lastSlotClicked.first)
- instantFind -= 1
- lastClicked.add(-1 to uncoveredAt)
- uncoveredAt += 1
- }
-
- hasFoundPair(slot, lastSlotClicked.first, reward, lastItemName) && lastItem.itemDamage == itemClicked.itemDamage -> handleFoundPair(
- slot,
- reward,
- lastSlotClicked.first,
- )
-
- hasFoundMatch(slot, reward) -> handleFoundMatch(slot, reward)
- else -> handleNormalReward(slot, reward)
- }
-
- }
-
- private fun handleFoundPair(
- slot: Int,
- reward: String,
- lastSlotClicked: Int,
- ) {
- val pair = toEither(ItemPair(Item(slot, reward), Item(lastSlotClicked, reward)))
-
- found[pair] = "Pair"
- found.entries.removeIf {
- it.value == "Match" && right(it.key).first.index == slot
- }
- found.entries.removeIf {
- it.value == "Normal" && (left(it.key).index == slot || left(it.key).index == lastSlotClicked)
- }
- }
-
- private fun handleFoundMatch(slot: Int, reward: String) {
- val match = uncoveredItems.find { it.second == reward }?.first ?: return
- val pair = toEither(ItemPair(Item(slot, reward), Item(match, reward)))
-
- if (found.none {
- listOf("Pair", "Match").contains(it.value) && (right(it.key).first.index == slot)
- }) found[pair] = "Match"
- found.entries.removeIf { it.value == "Normal" && (left(it.key).index == slot || left(it.key).index == match) }
- }
-
- private fun handleNormalReward(slot: Int, reward: String) {
- val item = toEither(Item(slot, reward))
-
- if (found.none {
- listOf("Match", "Pair").contains(it.value) && (right(it.key).first.index == slot || right(it.key).second.index == slot)
- } && found.none { it.value == "Normal" && left(it.key).index == slot }) found[item] = "Normal"
- }
-
- private fun calculatePossiblePairs() =
- ((currentExperiment.gridSize - 2) / 2) - found.filter { listOf("Pair", "Match", "Normal").contains(it.value) }.size
-
- private fun drawDisplay() = buildList {
- add("§6Superpair Experimentation Data")
- add("")
-
- val pairs = found.entries.filter { it.value == "Pair" }
- val matches = found.entries.filter { it.value == "Match" }
- val powerups = found.entries.filter { it.value == "Powerup" }
- val normals = found.entries.filter { it.value == "Normal" }
-
- if (pairs.isNotEmpty()) add("§2Found")
- for (pair in pairs) {
- val prefix = determinePrefix(pairs.indexOf(pair), pairs.lastIndex)
- add(" $prefix §a${right(pair.key).first.name}")
- }
- if (matches.isNotEmpty()) add("§eMatched")
- for (match in matches) {
- val prefix = determinePrefix(matches.indexOf(match), matches.lastIndex)
- add(" $prefix §e${right(match.key).first.name}")
- }
- if (powerups.isNotEmpty()) add("§bPowerUp")
- for (powerup in powerups) {
- val prefix = determinePrefix(powerups.indexOf(powerup), powerups.size - 1)
- add(" $prefix §b${left(powerup.key).name}")
- }
- val toAdd = mutableListOf<String>()
- if (possiblePairs >= 1) toAdd.add("§ePairs - $possiblePairs")
- if (2 - powerups.size >= 1) toAdd.add("§bPowerUps - ${2 - powerups.size}")
- if (normals.isNotEmpty()) toAdd.add("§7Normals - ${normals.size}")
-
- if (toAdd.isNotEmpty()) {
- add("")
- add("§4Not found")
- }
- for (string in toAdd) if (string != toAdd.last()) add(" ├ $string") else add(" └ $string")
- }
-
- private fun convertToReward(item: ItemStack) = if (item.displayName.removeColor() == "Enchanted Book") item.getLore()[2].removeColor()
- else item.displayName.removeColor()
-
- private fun determinePrefix(index: Int, lastIndex: Int) = if (index == lastIndex) "└" else "├"
-
- private fun hasFoundPair(
- firstSlot: Int,
- secondSlot: Int,
- firstName: String,
- secondName: String,
- ) = firstSlot != secondSlot && firstName == secondName
-
- private fun hasFoundMatch(itemSlot: Int, reward: String) =
- uncoveredItems.any { (slot, name) -> slot != itemSlot && name == reward } && found.none {
- listOf("Pair", "Match").contains(it.value) && (right(it.key).first.index == itemSlot || right(it.key).second.index == itemSlot)
- }
-
- private fun isPowerUp(reward: String) = ExperimentationTableAPI.powerUpPattern.matches(reward)
-
- private fun isReward(reward: String) = ExperimentationTableAPI.rewardPattern.matches(reward)
-
- private fun isWaiting(itemName: String) =
- listOf("Click any button!", "Click a second button!", "Next button is instantly rewarded!").contains(itemName)
-
- private fun clicksSinceSeparator(list: MutableList<Pair<Int, Int>>): Int {
- val lastIndex = list.indexOfLast { it.first == -1 }
- return if (lastIndex != -1) list.size - 1 - lastIndex else -1
- }
-
- private fun isOutOfBounds(slot: Int, experiment: Experiment): Boolean =
- slot <= experiment.startSlot || slot >= experiment.endSlot || (if (experiment.sideSpace == 1) slot in sideSpaces1 else slot in sideSpaces2)
-
- // TODO remove left and right, use custom data type instead
- private fun left(it: Pair<Item?, ItemPair?>): Item = it.first ?: Item(-1, "")
-
- private fun right(it: Pair<Item?, ItemPair?>): ItemPair = it.second ?: ItemPair(Item(-1, ""), Item(-1, ""))
-
- private fun toEither(it: Any): Pair<Item?, ItemPair?> = if (it is Item) it to null else null to it as ItemPair
-
- private fun isEnabled() = LorenzUtils.inSkyBlock && config.superpairDisplay && ExperimentationTableAPI.getCurrentExperiment() != null
-}