/* * Copyright (C) 2023 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * * NotEnoughUpdates is free software: you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * NotEnoughUpdates is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with NotEnoughUpdates. If not, see . */ package io.github.moulberry.notenoughupdates.util.hypixelapi import com.google.gson.JsonArray import com.google.gson.JsonObject import io.github.moulberry.notenoughupdates.NotEnoughUpdates import java.math.BigInteger import java.util.concurrent.CompletableFuture import kotlin.collections.List import kotlin.collections.Map import kotlin.collections.component1 import kotlin.collections.component2 import kotlin.collections.filter import kotlin.collections.flatMap import kotlin.collections.groupBy import kotlin.collections.mapNotNull import kotlin.collections.mapValues import kotlin.collections.maxOf import kotlin.collections.sumOf import kotlin.collections.toList import kotlin.collections.toMap import kotlin.collections.toSet data class ProfileCollectionInfo( val collections: Map, val craftedGenerators: Map, ) { data class CollectionInfo( val collection: Collection, val totalCollectionCount: BigInteger, val personalCollectionCount: BigInteger, val unlockedTiers: List, ) class CollectionMetadata internal constructor() { lateinit var collections: Map private set val allCollections by lazy { collections.values.flatMap { it.items.toList() }.toMap() } } class CollectionCategory internal constructor() { lateinit var items: Map private set } class Collection internal constructor() { lateinit var name: String private set var maxTiers: Int = -1 private set lateinit var tiers: List private set override fun toString(): String { return "Collection(name=$name, maxTiers=$maxTiers, tiers=$tiers)" } } class CollectionTier internal constructor() { var tier: Int = -1 private set var amountRequired: Int = -1 private set lateinit var unlocks: List private set override fun toString(): String { return "CollectionTier(tier=$tier, amountRequired=$amountRequired, unlocks=$unlocks)" } } companion object { val generatorPattern = "^([^0-9]+)_([0-9]+)$".toRegex() val hypixelCollectionInfo: CompletableFuture by lazy { NotEnoughUpdates.INSTANCE.manager.apiUtils .newAnonymousHypixelApiRequest("resources/skyblock/collections") .requestJson() .thenApply { NotEnoughUpdates.INSTANCE.manager.gson.fromJson(it, CollectionMetadata::class.java) } } fun getCollectionData( profileData: JsonObject, mainPlayer: String, collectionData: CollectionMetadata ): ProfileCollectionInfo? { val mainPlayerUUID = mainPlayer.replace("-", "") val members = profileData["members"] as? JsonObject ?: return null val mainPlayerData = (members[mainPlayerUUID] as? JsonObject ?: return null) val mainPlayerCollection = mainPlayerData["collection"] as? JsonObject ?: return null val memberCollections = members.entrySet().mapNotNull { (uuid, data) -> if (data !is JsonObject) return null data["collection"] as? JsonObject } val generators = members.entrySet().mapNotNull { (uuid, data) -> if (data !is JsonObject) return null data.getAsJsonObject("player_data")?.get("crafted_generators") as? JsonArray }.flatMap { it.toList() } return ProfileCollectionInfo( collectionData.allCollections.mapValues { (name, collection) -> val totalCollection = memberCollections.sumOf { it[name]?.asBigInteger ?: BigInteger.ZERO } val personalCollection = mainPlayerCollection[name]?.asBigInteger ?: BigInteger.ZERO CollectionInfo( collection, totalCollection, personalCollection, collection.tiers.filter { BigInteger.valueOf(it.amountRequired.toLong()) <= totalCollection } ) }, generators.toSet() .mapNotNull { val pattern = generatorPattern.matchEntire(it.asString) ?: return@mapNotNull null pattern.groupValues[1] to pattern.groupValues[2].toInt() } .groupBy { it.first } .mapValues { it.value.maxOf { it.second } } .toMap() ) } /** * This should be the json object returned by /skyblock/profiles at profiles.. (aka the root tag * should contain profile_id, members, cute_name, etc.) */ @JvmStatic fun getCollectionData(profileData: JsonObject, mainPlayer: String): CompletableFuture { return hypixelCollectionInfo.thenApply { getCollectionData(profileData, mainPlayer, it) } } } }