diff --git a/src/main/kotlin/net/taehui/twilight/Component.kt b/src/main/kotlin/net/taehui/twilight/Component.kt index bbf9f27..9884e19 100644 --- a/src/main/kotlin/net/taehui/twilight/Component.kt +++ b/src/main/kotlin/net/taehui/twilight/Component.kt @@ -32,6 +32,34 @@ DEFAULT, LONG_NOTE_UP } + enum class Handled(@JvmField val value: Int) { + NOT(0), + CLEAR(1), + BAND1(2), + F(4), + HIGHER_CLEAR(5), + HIGHEST_CLEAR(6); + + @JsonValue + fun getValue(): Int { + return value + } + + companion object { + fun getHandled(value: Int): Handled { + return when (value) { + 0 -> NOT + 1 -> CLEAR + 2 -> BAND1 + 4 -> F + 5 -> HIGHER_CLEAR + 6 -> HIGHEST_CLEAR + else -> throw IllegalArgumentException(value.toString()) + } + } + } + } + enum class InputMode(@JvmField val value: Int) { INPUT_MODE_4(4), INPUT_MODE_5(5), @@ -80,6 +108,29 @@ } companion object { + const val DEFAULT_JUDGMENT_MODE = 1 + const val HIGHER_JUDGMENT_MODE = 2 + const val HIGHEST_JUDGMENT_MODE = 4 + const val FAVOR_JUDGMENT_MODE = 5 + + const val DEFAULT_HIT_POINTS_MODE = 1 + const val HIGHER_HIT_POINTS_MODE = 2 + const val FAILED_HIT_POINTS_MODE = 3 + const val HIGHEST_HIT_POINTS_MODE = 5 + const val FAVOR_HIT_POINTS_MODE = 6 + const val TEST_HIT_POINTS_MODE = 7 + + const val DEFAULT_LONG_NOTE_MODE = 0 + + const val DEFAULT_INPUT_FAVOR_MODE = 0 + const val MODE_5_INPUT_FAVOR_MODE = 5 + const val MODE_5_1_INPUT_FAVOR_MODE = 10 + const val MODE_7_INPUT_FAVOR_MODE = 7 + const val MODE_7_1_INPUT_FAVOR_MODE = 11 + const val MODE_9_INPUT_FAVOR_MODE = 9 + + const val DEFAULT_NOTE_MODIFY_MODE = 0 + const val STANDARD_HEIGHT = 720.0 const val STANDARD_BPM = 130.0 const val STANDARD_METER = 192 diff --git a/src/main/kotlin/net/taehui/twilight/JSON.kt b/src/main/kotlin/net/taehui/twilight/JSON.kt index e06a6a1..bdc35cc 100644 --- a/src/main/kotlin/net/taehui/twilight/JSON.kt +++ b/src/main/kotlin/net/taehui/twilight/JSON.kt @@ -626,9 +626,8 @@ var lowestJudgmentConditionMode = 0 } - class TwilightWwwAvatarAbility(rs: ResultSet, i: Double) { + class TwilightWwwAvatarAbility(rs: ResultSet, rate: Double, val handled: Component.Handled) { val noteID: String - val noteVariety: Int val artist: String val title: String val genre: String @@ -639,14 +638,13 @@ init { noteID = rs.getString("Note_ID") - noteVariety = rs.getInt("Note_Variety") artist = rs.getString("Artist") title = rs.getString("Title") genre = rs.getString("Genre") levelText = rs.getString("Level_Text") level = rs.getInt("Level") stand = rs.getInt("Stand") - ability = rs.getDouble("Value") * i + ability = rs.getDouble("Value") * rate } } } \ No newline at end of file diff --git a/src/main/kotlin/net/taehui/twilight/qwilight/QwilightAvatar.kt b/src/main/kotlin/net/taehui/twilight/qwilight/QwilightAvatar.kt index d6db2fb..8e60c5c 100644 --- a/src/main/kotlin/net/taehui/twilight/qwilight/QwilightAvatar.kt +++ b/src/main/kotlin/net/taehui/twilight/qwilight/QwilightAvatar.kt @@ -794,7 +794,7 @@ val isPaused = text.isPaused val inputFlags = text.inputFlags val commentFileContents = eventData[1] - if (longNoteMode != INPUT_LONG_NOTE_MODE && judgmentMode != FAVOR_JUDGMENT_MODE && hitPointsMode != FAVOR_HIT_POINTS_MODE && hitPointsMode != TEST_HIT_POINTS_MODE && noteModifyMode != LONG_NOTE_NOTE_MODIFY_MODE) { + if (longNoteMode != INPUT_LONG_NOTE_MODE && judgmentMode != Component.FAVOR_JUDGMENT_MODE && hitPointsMode != Component.FAVOR_HIT_POINTS_MODE && hitPointsMode != Component.TEST_HIT_POINTS_MODE && noteModifyMode != LONG_NOTE_NOTE_MODIFY_MODE) { val noteFileData = eventData[0].toByteArray() val targetComputing = BaseCompiler.handleCompile(noteFileData, dataID).single() val noteID512 = Utility.getID512(noteFileData) @@ -821,6 +821,9 @@ val comment = CommentOuterClass.Comment.parseFrom(commentFileContents) val commentFileData = commentFileContents.toByteArray() val commentIDNew = Utility.getID512(commentFileData) + val isP = comment.lowestJudgment == 0 + val lowestAudioMultiplier = comment.audioMultipliersList.map { it.audioMultiplier } + .plus(audioMultiplier).min() val commentID = DB.saveComment( multiplier, autoMode, @@ -836,7 +839,7 @@ lowestJudgmentConditionMode, stand, band, - comment.lowestJudgment == 0, + isP, point, salt, commentIDNew, @@ -844,8 +847,7 @@ targetComputing.noteID, isPaused, inputFlags, - comment.audioMultipliersList.map { it.audioMultiplier } - .plus(audioMultiplier).min(), + lowestAudioMultiplier, comment.audioMultipliersList.map { it.audioMultiplier } .plus(audioMultiplier).max(), ) @@ -861,6 +863,9 @@ } } } + if ((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) && longNoteMode == Component.DEFAULT_LONG_NOTE_MODE && inputFavorMode == Component.DEFAULT_INPUT_FAVOR_MODE && noteModifyMode == Component.DEFAULT_NOTE_MODIFY_MODE && lowestAudioMultiplier >= 1.0) { + DB.saveHandled(avatarID, targetComputing.noteID, isP, hitPointsMode) + } if (SiteHandler.hasAvatar(this, SiteHandler.commentSiteID)) { SiteHandler.putSiteYell( SiteHandler.commentSiteID, @@ -1513,9 +1518,6 @@ const val IO_COMPUTING = 8 const val BUNDLE_AVAILABLE_COUNT = 1 const val INPUT_LONG_NOTE_MODE = 2 - const val FAVOR_JUDGMENT_MODE = 5 - const val FAVOR_HIT_POINTS_MODE = 6 - const val TEST_HIT_POINTS_MODE = 7 const val LONG_NOTE_NOTE_MODIFY_MODE = 2 } } \ No newline at end of file diff --git a/src/main/kotlin/net/taehui/twilight/system/AbilitySystem.kt b/src/main/kotlin/net/taehui/twilight/system/AbilitySystem.kt index 120baca..96b73fd 100644 --- a/src/main/kotlin/net/taehui/twilight/system/AbilitySystem.kt +++ b/src/main/kotlin/net/taehui/twilight/system/AbilitySystem.kt @@ -141,7 +141,7 @@ val noteIDAbilityMap = noteIDAbilityMap[abilityClassVariety] val abilityTable = jm.readValue(abilityFilePath.toFile(), JSON.BMSTable::class.java) val levels = - abilityTable.level_order.map { "${abilityTable.symbol}$it" }.toTypedArray(); + abilityTable.level_order.map { "${abilityTable.symbol}$it" }.toTypedArray() jm.readValue( TwilightComponent.ABILITY_ENTRY_PATH.resolve("$abilityName.json") .toFile(), diff --git a/src/main/kotlin/net/taehui/twilight/system/Configure.kt b/src/main/kotlin/net/taehui/twilight/system/Configure.kt index acc565e..c76c7a0 100644 --- a/src/main/kotlin/net/taehui/twilight/system/Configure.kt +++ b/src/main/kotlin/net/taehui/twilight/system/Configure.kt @@ -11,7 +11,6 @@ import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths -import java.util.concurrent.CompletableFuture import java.util.concurrent.TimeUnit object Configure : Logger { diff --git a/src/main/kotlin/net/taehui/twilight/system/DB.kt b/src/main/kotlin/net/taehui/twilight/system/DB.kt index ac56f64..2aa7461 100644 --- a/src/main/kotlin/net/taehui/twilight/system/DB.kt +++ b/src/main/kotlin/net/taehui/twilight/system/DB.kt @@ -1,6 +1,5 @@ package net.taehui.twilight.system -import CommentKt import CommentOuterClass import com.fasterxml.jackson.annotation.JsonIgnore import net.taehui.twilight.* @@ -11,7 +10,6 @@ import org.apache.commons.dbcp2.BasicDataSource import org.apache.commons.io.FileUtils import org.apache.commons.io.FilenameUtils -import org.apache.commons.io.IOUtils import java.io.IOException import java.nio.file.Files import java.nio.file.Path @@ -26,7 +24,6 @@ import java.util.stream.Stream import java.util.stream.StreamSupport import kotlin.collections.ArrayList -import kotlin.io.path.inputStream import kotlin.math.pow object DB : Logger { @@ -113,6 +110,17 @@ ) dbStatement.executeUpdate( """ + CREATE TABLE IF NOT EXISTS tw_handled ( + Avatar VARCHAR(20) NOT NULL, + Note_ID VARCHAR(139) NOT NULL, + Handled INTEGER NOT NULL, + PRIMARY KEY (Avatar, Note_ID), + FOREIGN KEY (Avatar) REFERENCES tn_avatar(Avatar_ID) ON UPDATE CASCADE ON DELETE CASCADE + ) COLLATE=utf8mb4_general_ci ENGINE=InnoDB + """.trimIndent() + ) + dbStatement.executeUpdate( + """ CREATE TABLE IF NOT EXISTS tw_bundle ( Avatar VARCHAR(20) NOT NULL, Date DATETIME NOT NULL, @@ -645,10 +653,10 @@ val commentID = FilenameUtils.removeExtension(commentFilePath.fileName.toString()) it.prepareStatement( """ - SELECT Audio_Multiplier - FROM tw_comment - WHERE Comment_ID = ? - """.trimIndent() + SELECT Audio_Multiplier + FROM tw_comment + WHERE Comment_ID = ? + """.trimIndent() ).use { dbStatement -> dbStatement.setString(1, commentID) dbStatement.executeQuery().use { rows -> @@ -663,10 +671,10 @@ if (comment.audioMultipliersCount > 0) { it.prepareStatement( """ - UPDATE tw_comment - SET Lowest_Audio_Multiplier = ?, Highest_Audio_Multiplier = ? - WHERE Comment_ID = ? - """.trimIndent() + UPDATE tw_comment + SET Lowest_Audio_Multiplier = ?, Highest_Audio_Multiplier = ? + WHERE Comment_ID = ? + """.trimIndent() ).use { dbStatement -> dbStatement.setDouble( 1, @@ -684,10 +692,10 @@ } else { it.prepareStatement( """ - UPDATE tw_comment - SET Lowest_Audio_Multiplier = Audio_Multiplier, Highest_Audio_Multiplier = Audio_Multiplier - WHERE Comment_ID = ? - """.trimIndent() + UPDATE tw_comment + SET Lowest_Audio_Multiplier = Audio_Multiplier, Highest_Audio_Multiplier = Audio_Multiplier + WHERE Comment_ID = ? + """.trimIndent() ).use { dbStatement -> dbStatement.setString(1, commentID) dbStatement.executeUpdate() @@ -706,6 +714,71 @@ } } + fun learnHandled(futureLearnHandledStatus: AtomicInteger): CompletableFuture { + data class Comment(val avatar: String, val noteID: String, val hitPointsMode: Int, val isP: Boolean) + + return logFuture { + val comments = mutableListOf() + pool.connection.use { + it.prepareStatement( + """ + SELECT Avatar, Note_ID, Hit_Points_Mode, Is_P + FROM tw_comment + WHERE Lowest_Audio_Multiplier >= 1.0 AND (Hit_Points_Mode = ${Component.DEFAULT_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHER_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHEST_HIT_POINTS_MODE}) AND (Judgment_Mode = ${Component.DEFAULT_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHER_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHEST_JUDGMENT_MODE}) AND Long_Note_Mode = ${Component.DEFAULT_LONG_NOTE_MODE} AND Input_Favor_Mode = ${Component.DEFAULT_INPUT_FAVOR_MODE} AND Note_Modify_Mode = ${Component.DEFAULT_NOTE_MODIFY_MODE} + """.trimIndent() + ).use { dbStatement -> + dbStatement.executeQuery().use { rows -> + while (rows.next()) { + comments.add( + Comment( + rows.getString("Avatar"), + rows.getString("Note_ID"), + rows.getInt("Hit_Points_Mode"), + rows.getBoolean("Is_P") + ) + ) + } + } + } + } + StreamSupport.stream(comments.groupBy { Pair(it.avatar, it.noteID) }.toList().spliterator(), true) + .use { parallel -> + parallel.forEach { (avatarNoteID, comments) -> + val isP = comments.any { it.isP } + val hitPointsMode = comments.maxBy { + when (it.hitPointsMode) { + Component.HIGHEST_HIT_POINTS_MODE, Component.FAILED_HIT_POINTS_MODE -> 2 + Component.HIGHER_HIT_POINTS_MODE -> 1 + else -> 0 + } + }.hitPointsMode + pool.connection.use { + it.prepareStatement( + """ + REPLACE INTO tw_handled + VALUES(?, ?, ?) + """.trimIndent() + ).use { dbStatement -> + dbStatement.setString(1, avatarNoteID.first) + dbStatement.setString(2, avatarNoteID.second) + dbStatement.setInt( + 3, (if (isP) Component.Handled.BAND1 else { + when (hitPointsMode) { + Component.HIGHEST_HIT_POINTS_MODE, Component.FAILED_HIT_POINTS_MODE -> Component.Handled.HIGHEST_CLEAR + Component.HIGHER_HIT_POINTS_MODE -> Component.Handled.HIGHER_CLEAR + else -> Component.Handled.CLEAR + } + }).value + ) + dbStatement.execute() + } + } + futureLearnHandledStatus.incrementAndGet() + } + } + } + } + fun getWipeBundles(): CompletableFuture> { return logValueFuture { data class BundleID(val avatarID: String, val bundleName: String) @@ -872,6 +945,7 @@ val isPaused = rows.getBoolean("Is_Paused") val inputFlags = rows.getInt("Input_Flags") + val handled = getHandled(this.avatarID, noteID) }) } } @@ -1824,6 +1898,36 @@ return commentID } + fun saveHandled(avatarID: String, noteID: String, isP: Boolean, hitPointsMode: Int) { + var handled = getHandled(avatarID, noteID) + if (handled != Component.Handled.BAND1) { + if (isP) { + handled = Component.Handled.BAND1 + } else { + if (hitPointsMode == Component.HIGHEST_HIT_POINTS_MODE) { + handled = Component.Handled.HIGHEST_CLEAR + } else if (hitPointsMode == Component.HIGHER_HIT_POINTS_MODE && handled != Component.Handled.HIGHEST_CLEAR) { + handled = Component.Handled.HIGHER_CLEAR + } else if (handled != Component.Handled.HIGHER_CLEAR && handled != Component.Handled.HIGHEST_CLEAR) { + handled = Component.Handled.CLEAR + } + } + pool.connection.use { + it.prepareStatement( + """ + REPLACE INTO tw_handled + VALUES(?, ?, ?) + """.trimIndent() + ).use { dbStatement -> + dbStatement.setString(1, avatarID) + dbStatement.setString(2, noteID) + dbStatement.setInt(3, handled.value) + dbStatement.execute() + } + } + } + } + fun getTitle(qm: Map): CompletableFuture { return logValueFuture { val avatarID = Utility.getDefaultAvatarID(qm.getOrDefault("avatarID", "")) @@ -2539,6 +2643,24 @@ } } + fun getHandled(avatarID: String, noteID: String): Component.Handled { + return pool.connection.use { db -> + db.prepareStatement( + """ + SELECT Handled + FROM tw_handled + WHERE Avatar = ? AND Note_ID = ? + """.trimIndent() + ).use { dbStatement -> + dbStatement.setString(1, avatarID) + dbStatement.setString(2, noteID) + dbStatement.executeQuery().use { rows -> + if (rows.next()) Component.Handled.getHandled(rows.getInt("Handled")) else Component.Handled.NOT + } + } + } + } + fun getAvatarFavorites(inputMode: Component.InputMode, avatarID: String): CompletableFuture { return logValueFuture { pool.connection.use { db -> @@ -2557,13 +2679,15 @@ dbStatement.executeQuery().use { val data = mutableListOf() while (it.next()) { + val noteID = it.getString("Note_ID") data.add(object { - val noteID = it.getString("Note_ID") + val noteID = noteID val artist = it.getString("Artist") val title = it.getString("Title") val genre = it.getString("Genre") val levelText = it.getString("Level_Text") val level = it.getInt("Level") + val handled = getHandled(avatarID, noteID) val totalCount = it.getInt("Count") }) } @@ -2592,13 +2716,15 @@ dbStatement.executeQuery().use { val data = mutableListOf() while (it.next()) { + val noteID = it.getString("Note_ID") data.add(object { - val noteID = it.getString("Note_ID") + val noteID = noteID val artist = it.getString("Artist") val title = it.getString("Title") val genre = it.getString("Genre") val levelText = it.getString("Level_Text") val level = it.getInt("Level") + val handled = getHandled(avatarID, noteID) val date = it.getTimestamp("Date") }) } @@ -2641,12 +2767,12 @@ } } - fun getAvatarAbilityNoteFiles(inputMode: Component.InputMode, avatarID: String): CompletableFuture { + fun getAvatarAbility(inputMode: Component.InputMode, avatarID: String): CompletableFuture { return logValueFuture { (when (inputMode) { - Component.InputMode.INPUT_MODE_5_1 -> getAbilities5K() - Component.InputMode.INPUT_MODE_7_1 -> getAbilities7K() - Component.InputMode.INPUT_MODE_9 -> getAbilities9K() + Component.InputMode.INPUT_MODE_5_1 -> getAbilities5K(true) + Component.InputMode.INPUT_MODE_7_1 -> getAbilities7K(true) + Component.InputMode.INPUT_MODE_9 -> getAbilities9K(true) else -> emptyMap() }.entries.singleOrNull { it.key.first == avatarID } ?: AbstractMap.SimpleEntry( Pair(avatarID, ""), @@ -2665,6 +2791,7 @@ val noteID256: String val stand: Int var levelVSStand: Int + val handled: Component.Handled } fun getAvatarLevelVS(avatarID: String, targetID: String, levelName: String): CompletableFuture { @@ -2678,7 +2805,7 @@ """ SELECT tw_note.Note_ID, Note_ID_128, Note_ID_256, Title, Artist, Genre, Level_Text, Level, Stand FROM tw_note, tw_comment - WHERE tw_note.Note_ID = tw_comment.Note_ID AND Avatar = ? AND Is_Max = true + WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = ? AND Is_Max = true """.trimIndent() ).use { dbStatement -> dbStatement.setString(1, avatarID) @@ -2696,6 +2823,7 @@ val level = it.getInt("Level") override val stand = it.getInt("Stand") override var levelVSStand = 0 + override val handled = getHandled(avatarID, noteID) } } } @@ -2758,24 +2886,32 @@ } } - private fun getAbilities5K(): Map, MutableCollection> { + private fun getAbilities5K(getHandled: Boolean = false): Map, MutableCollection> { val abilities5K = mutableMapOf, MutableCollection>() pool.connection.use { it.prepareStatement( """ SELECT tw_note.Note_ID, Note_Variety, Artist, Title, Genre, Level_Text, tw_note.Level, Stand, Avatar_ID, Avatar_Name, Ability_5K * (POWER(Stand / 1000000, 3) - 0.5 * POWER(Stand / 1000000, 2) + 0.5 * (Stand / 1000000)) AS Value FROM tw_note, tw_comment, tn_avatar - WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Ability_5K > 0.0 AND (Input_Favor_Mode = 0 OR Input_Favor_Mode = 5 OR Input_Favor_Mode = 10) AND (Hit_Points_Mode = 1 OR Hit_Points_Mode = 2 OR Hit_Points_Mode = 5) AND (Judgment_Mode = 1 OR Judgment_Mode = 2 OR Judgment_Mode = 4) AND Is_Max = true + WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Ability_5K > 0.0 AND (Input_Favor_Mode = ${Component.DEFAULT_INPUT_FAVOR_MODE} OR Input_Favor_Mode = ${Component.MODE_5_INPUT_FAVOR_MODE} OR Input_Favor_Mode = ${Component.MODE_5_1_INPUT_FAVOR_MODE}) AND (Hit_Points_Mode = ${Component.DEFAULT_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHER_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHEST_HIT_POINTS_MODE}) AND (Judgment_Mode = ${Component.DEFAULT_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHER_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHEST_JUDGMENT_MODE}) AND Is_Max = true ORDER BY Value DESC """.trimIndent() ).use { dbStatement -> dbStatement.executeQuery().use { rows -> while (rows.next()) { + val avatarID = rows.getString("Avatar_ID") + val noteID = rows.getString("Note_ID") val abilities = abilities5K.computeIfAbsent( - Pair(rows.getString("Avatar_ID"), rows.getString("Avatar_Name")) + Pair(avatarID, rows.getString("Avatar_Name")) ) { ArrayList() } if (abilities.size < 50) { - abilities.add(JSON.TwilightWwwAvatarAbility(rows, 0.95.pow(abilities.size.toDouble()))) + abilities.add( + JSON.TwilightWwwAvatarAbility( + rows, + 0.95.pow(abilities.size.toDouble()), + if (getHandled) getHandled(avatarID, noteID) else Component.Handled.NOT + ) + ) } } } @@ -2790,7 +2926,7 @@ """ SELECT Ability_5K * (POWER(Stand / 1000000, 3) - 0.5 * POWER(Stand / 1000000, 2) + 0.5 * (Stand / 1000000)) AS Value FROM tw_note, tw_comment, tn_avatar - WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Avatar_ID = ? AND Ability_5K > 0.0 AND (Input_Favor_Mode = 0 OR Input_Favor_Mode = 5 OR Input_Favor_Mode = 10) AND (Hit_Points_Mode = 1 OR Hit_Points_Mode = 2 OR Hit_Points_Mode = 5) AND (Judgment_Mode = 1 OR Judgment_Mode = 2 OR Judgment_Mode = 4) AND Is_Max = true + WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Avatar_ID = ? AND Ability_5K > 0.0 AND (Input_Favor_Mode = ${Component.DEFAULT_INPUT_FAVOR_MODE} OR Input_Favor_Mode = ${Component.MODE_5_INPUT_FAVOR_MODE} OR Input_Favor_Mode = ${Component.MODE_5_1_INPUT_FAVOR_MODE}) AND (Hit_Points_Mode = ${Component.DEFAULT_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHER_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHEST_HIT_POINTS_MODE}) AND (Judgment_Mode = ${Component.DEFAULT_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHER_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHEST_JUDGMENT_MODE}) AND Is_Max = true ORDER BY Value DESC LIMIT 50 """.trimIndent() @@ -2807,24 +2943,32 @@ } } - private fun getAbilities7K(): Map, MutableCollection> { + private fun getAbilities7K(getHandled: Boolean = false): Map, MutableCollection> { val abilities7K = mutableMapOf, MutableCollection>() pool.connection.use { it.prepareStatement( """ SELECT tw_note.Note_ID, Note_Variety, Artist, Title, Genre, Level_Text, tw_note.Level, Stand, Avatar_ID, Avatar_Name, Ability_7K * (POWER(Stand / 1000000, 3) - 0.5 * POWER(Stand / 1000000, 2) + 0.5 * (Stand / 1000000)) AS Value FROM tw_note, tw_comment, tn_avatar - WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Ability_7K > 0.0 AND (Input_Favor_Mode = 0 OR Input_Favor_Mode = 7 OR Input_Favor_Mode = 11) AND (Hit_Points_Mode = 1 OR Hit_Points_Mode = 2 OR Hit_Points_Mode = 5) AND (Judgment_Mode = 1 OR Judgment_Mode = 2 OR Judgment_Mode = 4) AND Is_Max = true + WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Ability_7K > 0.0 AND (Input_Favor_Mode = ${Component.DEFAULT_INPUT_FAVOR_MODE} OR Input_Favor_Mode = ${Component.MODE_7_INPUT_FAVOR_MODE} OR Input_Favor_Mode = ${Component.MODE_7_1_INPUT_FAVOR_MODE}) AND (Hit_Points_Mode = ${Component.DEFAULT_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHER_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHEST_HIT_POINTS_MODE}) AND (Judgment_Mode = ${Component.DEFAULT_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHER_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHEST_JUDGMENT_MODE}) AND Is_Max = true ORDER BY Value DESC """.trimIndent() ).use { dbStatement -> dbStatement.executeQuery().use { rows -> while (rows.next()) { + val avatarID = rows.getString("Avatar_ID") + val noteID = rows.getString("Note_ID") val abilities = abilities7K.computeIfAbsent( - Pair(rows.getString("Avatar_ID"), rows.getString("Avatar_Name")) + Pair(avatarID, rows.getString("Avatar_Name")) ) { ArrayList() } if (abilities.size < 50) { - abilities.add(JSON.TwilightWwwAvatarAbility(rows, 0.95.pow(abilities.size.toDouble()))) + abilities.add( + JSON.TwilightWwwAvatarAbility( + rows, + 0.95.pow(abilities.size.toDouble()), + if (getHandled) getHandled(avatarID, noteID) else Component.Handled.NOT + ) + ) } } } @@ -2839,7 +2983,7 @@ """ SELECT Ability_7K * (POWER(Stand / 1000000, 3) - 0.5 * POWER(Stand / 1000000, 2) + 0.5 * (Stand / 1000000)) AS Value FROM tw_note, tw_comment, tn_avatar - WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Avatar_ID = ? AND Ability_7K > 0.0 AND (Input_Favor_Mode = 0 OR Input_Favor_Mode = 7 OR Input_Favor_Mode = 11) AND (Hit_Points_Mode = 1 OR Hit_Points_Mode = 2 OR Hit_Points_Mode = 5) AND (Judgment_Mode = 1 OR Judgment_Mode = 2 OR Judgment_Mode = 4) AND Is_Max = true + WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Avatar_ID = ? AND Ability_7K > 0.0 AND (Input_Favor_Mode = ${Component.DEFAULT_INPUT_FAVOR_MODE} OR Input_Favor_Mode = ${Component.MODE_7_INPUT_FAVOR_MODE} OR Input_Favor_Mode = ${Component.MODE_7_1_INPUT_FAVOR_MODE}) AND (Hit_Points_Mode = ${Component.DEFAULT_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHER_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHEST_HIT_POINTS_MODE}) AND (Judgment_Mode = ${Component.DEFAULT_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHER_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHEST_JUDGMENT_MODE}) AND Is_Max = true ORDER BY Value DESC LIMIT 50 """.trimIndent() @@ -2856,30 +3000,38 @@ } } - private fun getAbilities9K(): Map, MutableCollection> { - val abilities5K = mutableMapOf, MutableCollection>() + private fun getAbilities9K(getHandled: Boolean = false): Map, MutableCollection> { + val abilities9K = mutableMapOf, MutableCollection>() pool.connection.use { it.prepareStatement( """ SELECT tw_note.Note_ID, Note_Variety, Artist, Title, Genre, Level_Text, tw_note.Level, Stand, Avatar_ID, Avatar_Name, Ability_9K * (POWER(Stand / 1000000, 3) - 0.5 * POWER(Stand / 1000000, 2) + 0.5 * (Stand / 1000000)) AS Value FROM tw_note, tw_comment, tn_avatar - WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Ability_9K > 0.0 AND (Input_Favor_Mode = 0 OR Input_Favor_Mode = 9) AND (Hit_Points_Mode = 1 OR Hit_Points_Mode = 2 OR Hit_Points_Mode = 5) AND (Judgment_Mode = 1 OR Judgment_Mode = 2 OR Judgment_Mode = 4) AND Is_Max = true + WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Ability_9K > 0.0 AND (Input_Favor_Mode = ${Component.DEFAULT_INPUT_FAVOR_MODE} OR Input_Favor_Mode = ${Component.MODE_9_INPUT_FAVOR_MODE}) AND (Hit_Points_Mode = ${Component.DEFAULT_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHER_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHEST_HIT_POINTS_MODE}) AND (Judgment_Mode = ${Component.DEFAULT_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHER_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHEST_JUDGMENT_MODE}) AND Is_Max = true ORDER BY Value DESC """.trimIndent() ).use { dbStatement -> dbStatement.executeQuery().use { rows -> while (rows.next()) { - val abilities = abilities5K.computeIfAbsent( - Pair(rows.getString("Avatar_ID"), rows.getString("Avatar_Name")) + val avatarID = rows.getString("Avatar_ID") + val noteID = rows.getString("Note_ID") + val abilities = abilities9K.computeIfAbsent( + Pair(avatarID, rows.getString("Avatar_Name")) ) { ArrayList() } if (abilities.size < 50) { - abilities.add(JSON.TwilightWwwAvatarAbility(rows, 0.95.pow(abilities.size.toDouble()))) + abilities.add( + JSON.TwilightWwwAvatarAbility( + rows, + 0.95.pow(abilities.size.toDouble()), + if (getHandled) getHandled(avatarID, noteID) else Component.Handled.NOT + ) + ) } } } } } - return abilities5K + return abilities9K } fun getAvatarAbility9K(avatarID: String): Double { @@ -2888,7 +3040,7 @@ """ SELECT Ability_9K * (POWER(Stand / 1000000, 3) - 0.5 * POWER(Stand / 1000000, 2) + 0.5 * (Stand / 1000000)) AS Value FROM tw_note, tw_comment, tn_avatar - WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Avatar_ID = ? AND Ability_9K > 0.0 AND (Input_Favor_Mode = 0 OR Input_Favor_Mode = 9) AND (Hit_Points_Mode = 1 OR Hit_Points_Mode = 2 OR Hit_Points_Mode = 5) AND (Judgment_Mode = 1 OR Judgment_Mode = 2 OR Judgment_Mode = 4) AND Is_Max = true + WHERE tw_note.Note_ID = tw_comment.Note_ID AND tw_comment.Avatar = tn_avatar.Avatar_ID AND Avatar_ID = ? AND Ability_9K > 0.0 AND (Input_Favor_Mode = ${Component.DEFAULT_INPUT_FAVOR_MODE} OR Input_Favor_Mode = ${Component.MODE_9_INPUT_FAVOR_MODE}) AND (Hit_Points_Mode = ${Component.DEFAULT_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHER_HIT_POINTS_MODE} OR Hit_Points_Mode = ${Component.HIGHEST_HIT_POINTS_MODE}) AND (Judgment_Mode = ${Component.DEFAULT_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHER_JUDGMENT_MODE} OR Judgment_Mode = ${Component.HIGHEST_JUDGMENT_MODE}) AND Is_Max = true ORDER BY Value DESC LIMIT 50 """.trimIndent() diff --git a/src/main/kotlin/net/taehui/twilight/system/IO.kt b/src/main/kotlin/net/taehui/twilight/system/IO.kt index 90ff77c..cccbeb2 100644 --- a/src/main/kotlin/net/taehui/twilight/system/IO.kt +++ b/src/main/kotlin/net/taehui/twilight/system/IO.kt @@ -18,6 +18,8 @@ private var futureLearnNotes: CompletableFuture? = null private val futureLearnCommentsStatus = AtomicInteger() private var futureLearnComments: CompletableFuture? = null + private val futureLearnHandledStatus = AtomicInteger() + private var futureLearnHandled: CompletableFuture? = null private var futureWipeNotes: Collection? = null private var futurePMSNotes: Collection? = null private var futureWipeComments: Collection? = null @@ -218,6 +220,30 @@ logInfo("comment [wipe] Clean Comment Files") } + "handled" -> { + if (w.size > 1) { + when (w[1]) { + "learn" -> { + if (futureLearnHandled?.isDone != false) { + futureLearnHandled = + DB.learnHandled(futureLearnHandledStatus).thenAccept { + logInfo( + "Learned ${futureLearnHandledStatus.get()} Handled" + ) + } + } else { + logInfo( + "Learning ${futureLearnHandledStatus.get()} Handled" + ) + } + continue + } + } + } + + logInfo("handled [learn] Learn Handled") + } + "note" -> { if (w.size > 1) { when (w[1]) { diff --git a/src/main/kotlin/net/taehui/twilight/system/QwilightNamesSystem.kt b/src/main/kotlin/net/taehui/twilight/system/QwilightNamesSystem.kt index 2997f4d..64e1582 100644 --- a/src/main/kotlin/net/taehui/twilight/system/QwilightNamesSystem.kt +++ b/src/main/kotlin/net/taehui/twilight/system/QwilightNamesSystem.kt @@ -1,9 +1,7 @@ package net.taehui.twilight.system import net.taehui.twilight.Logger -import net.taehui.twilight.Utility import java.util.LinkedList -import java.util.concurrent.ConcurrentLinkedQueue object QwilightNamesSystem : Logger { private val qwilightNames = LinkedList() diff --git a/src/main/kotlin/net/taehui/twilight/www/WwwAvatar.kt b/src/main/kotlin/net/taehui/twilight/www/WwwAvatar.kt index 3833079..c7040a8 100644 --- a/src/main/kotlin/net/taehui/twilight/www/WwwAvatar.kt +++ b/src/main/kotlin/net/taehui/twilight/www/WwwAvatar.kt @@ -270,21 +270,21 @@ send(ctx, it) } - "/qwilight/www/avatar/ability/5K" -> DB.getAvatarAbilityNoteFiles( + "/qwilight/www/avatar/ability/5K" -> DB.getAvatarAbility( Component.InputMode.INPUT_MODE_5_1, avatarID ).thenAccept { send(ctx, it) } - "/qwilight/www/avatar/ability/7K" -> DB.getAvatarAbilityNoteFiles( + "/qwilight/www/avatar/ability/7K" -> DB.getAvatarAbility( Component.InputMode.INPUT_MODE_7_1, avatarID ).thenAccept { send(ctx, it) } - "/qwilight/www/avatar/ability/9K" -> DB.getAvatarAbilityNoteFiles( + "/qwilight/www/avatar/ability/9K" -> DB.getAvatarAbility( Component.InputMode.INPUT_MODE_9, avatarID ).thenAccept {