package net.taehui.twilight import io.netty.handler.codec.DecoderException import net.taehui.twilight.system.PlatformIDSystem import org.apache.commons.codec.binary.Hex import java.io.InputStream import java.net.MalformedURLException import java.net.SocketException import java.net.URI import java.security.MessageDigest import java.util.* import kotlin.math.pow import kotlin.math.sqrt object Utility { fun isEtcNetBundle(etc: String): Boolean { return etc.isNotEmpty() && "Qwilight" != etc && "MD5" != etc && !etc.contains(":") } fun getDistance( value: Component, waitBPMMap: Queue<Map.Entry<Double, Double>>, loopingCounter: Double, targetLoopingCounter: Double ): Double { var tmpLoopingCounter = loopingCounter var distance = 0.0 while (!waitBPMMap.isEmpty()) { val (wait, bpm) = waitBPMMap.peek() if (wait < targetLoopingCounter) { distance += value.logicalYMillis * (wait - tmpLoopingCounter) tmpLoopingCounter = wait value.setBPM(bpm) waitBPMMap.poll() } else { break } } return distance + value.logicalYMillis * (targetLoopingCounter - tmpLoopingCounter) } fun getDefaultAvatarID(avatarID: String): String { val siteWipedID = avatarID.substring(avatarID.indexOf('@') + 1) val platformWipedID = siteWipedID.substring(siteWipedID.indexOf('$') + 1) return PlatformIDSystem.getAvatarID(platformWipedID) ?: siteWipedID } fun getFaultText(e: Throwable): String { return StringBuilder(e.localizedMessage ?: "").apply { e.stackTrace.forEach { append(System.lineSeparator()) append(it) } }.toString() } fun getQuitStatusValue(point: Double, stand: Int): Int { return if (point < 0.8) { 6 } else if (point < 0.85) { 5 } else if (point < 0.9) { 4 } else if (point < 0.95) { 3 } else if (stand < 900000) { 2 } else if (point < 1.0) { 1 } else { 0 } } fun isValidWww(www: String): Boolean { return try { return URI(www).isAbsolute } catch (e: MalformedURLException) { false } } fun getID512(noteFileData: ByteArray): String { val hashComputer = MessageDigest.getInstance("SHA-512") hashComputer.update(noteFileData) return Hex.encodeHexString(hashComputer.digest()) } fun getID256(noteFileData: ByteArray): String { val hashComputer = MessageDigest.getInstance("SHA-256") hashComputer.update(noteFileData) return Hex.encodeHexString(hashComputer.digest()) } fun getID128(noteFileData: ByteArray): String { val hashComputer = MessageDigest.getInstance("MD5") hashComputer.update(noteFileData) return Hex.encodeHexString(hashComputer.digest()) } fun getNoteID512(noteID: String): String { return noteID.split(':')[0] } fun getDataID(noteID: String): Int { return noteID.split(':')[1].toInt() } fun isStandardHandled( autoMode: Int, judgmentMode: Int, hitPointsMode: Int, longNoteMode: Int, inputFavorMode: Int, noteModifyMode: Int, lowestAudioMultiplier: Double ): Boolean { return autoMode == Component.DEFAULT_AUTO_MODE && (judgmentMode == Component.DEFAULT_JUDGMENT_MODE || judgmentMode == Component.HIGHER_JUDGMENT_MODE || judgmentMode == Component.HIGHEST_JUDGMENT_MODE) && (hitPointsMode == Component.DEFAULT_HIT_POINTS_MODE || hitPointsMode == Component.HIGHER_HIT_POINTS_MODE || hitPointsMode == Component.HIGHEST_HIT_POINTS_MODE || hitPointsMode == Component.FAILED_HIT_POINTS_MODE || hitPointsMode == Component.YELL_HIT_POINTS_MODE) && longNoteMode == Component.DEFAULT_LONG_NOTE_MODE && inputFavorMode == Component.DEFAULT_INPUT_FAVOR_MODE && noteModifyMode == Component.DEFAULT_NOTE_MODIFY_MODE && lowestAudioMultiplier >= 1.0 } fun getAvatarLevel(avatarXP: Double): Int { return (1.0 + if (avatarXP < 40000) { avatarXP / 400.0 } else { sqrt(avatarXP) / 3 }).toInt() } fun getAvatarXP(avatarLevel: Int): Double { return if (avatarLevel < 100) { avatarLevel * 400.0 } else { (3.0 * avatarLevel).pow(2) } } }