Search by user ban_date, refactor of search
This commit is contained in:
parent
947f8cac02
commit
2b5ab1c054
@ -3,6 +3,7 @@ package com.nisemoe.nise
|
||||
import com.nisemoe.generated.enums.JudgementType
|
||||
import org.nisemoe.mari.judgements.Judgement
|
||||
import java.time.LocalDateTime
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
@ -20,6 +21,11 @@ class Format {
|
||||
.format(targetFormatter)
|
||||
}
|
||||
|
||||
fun formatOffsetDateTime(dateTime: OffsetDateTime): String {
|
||||
return LocalDateTime.ofInstant(dateTime.toInstant(), ZoneOffset.UTC)
|
||||
.format(targetFormatter)
|
||||
}
|
||||
|
||||
fun parseStringToDate(dateTimeStr: String): Date {
|
||||
val localDateTime = LocalDateTime.parse(dateTimeStr, targetFormatter)
|
||||
return Date.from(localDateTime.atZone(ZoneOffset.UTC).toInstant())
|
||||
|
||||
@ -0,0 +1,87 @@
|
||||
package com.nisemoe.nise.search
|
||||
|
||||
import org.jooq.Condition
|
||||
import org.jooq.Field
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
class PredicateBuilder {
|
||||
|
||||
companion object {
|
||||
|
||||
fun buildBooleanCondition(field: Field<Boolean>, operator: String, value: Boolean): Condition {
|
||||
return when (operator) {
|
||||
"=" -> field.eq(value)
|
||||
"!=" -> field.ne(value)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
fun buildGradeCondition(field: Field<String>, operator: String, value: String): Condition {
|
||||
return when (value) {
|
||||
"SS", "S", "A", "B", "C", "D" -> {
|
||||
val valuesToMatch = when (value) {
|
||||
"SS" -> listOf("Grade.SS", "Grade.SSH")
|
||||
"S" -> listOf("Grade.S", "Grade.SH")
|
||||
else -> listOf("Grade.$value")
|
||||
}
|
||||
when (operator) {
|
||||
"=" -> field.`in`(valuesToMatch)
|
||||
"!=" -> field.notIn(valuesToMatch)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
else -> throw IllegalArgumentException("Invalid grade value")
|
||||
}
|
||||
}
|
||||
|
||||
fun buildNumberCondition(field: Field<Double>, operator: String, value: Double): Condition {
|
||||
return when (operator) {
|
||||
"=" -> field.eq(value)
|
||||
">" -> field.gt(value)
|
||||
"<" -> field.lt(value)
|
||||
">=" -> field.ge(value)
|
||||
"<=" -> field.le(value)
|
||||
"!=" -> field.ne(value)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
fun buildStringCondition(field: Field<String>, operator: String, value: String): Condition {
|
||||
return when (operator.lowercase()) {
|
||||
"=" -> field.eq(value)
|
||||
"contains" -> field.containsIgnoreCase(value)
|
||||
"like" -> field.likeIgnoreCase(
|
||||
// Escape special characters for LIKE if needed
|
||||
value.replace("%", "\\%").replace("_", "\\_")
|
||||
)
|
||||
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
fun buildDatetimeCondition(field: Field<String>, operator: String, value: String): Condition {
|
||||
|
||||
if(field.type == OffsetDateTime::class.java) {
|
||||
val fieldOffset = field as Field<OffsetDateTime>
|
||||
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm")
|
||||
val parsedDate = OffsetDateTime.parse(value, formatter.withZone(ZoneOffset.UTC))
|
||||
|
||||
return when (operator.lowercase()) {
|
||||
"before" -> fieldOffset.lessThan(parsedDate)
|
||||
"after" -> fieldOffset.greaterThan(parsedDate)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
return when (operator.lowercase()) {
|
||||
"before" -> field.lessThan(value)
|
||||
"after" -> field.greaterThan(value)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -63,6 +63,7 @@ class ScoreSearchController(
|
||||
val user_count_50: Long?,
|
||||
val user_count_miss: Long?,
|
||||
val user_is_banned: Boolean?,
|
||||
val user_approx_ban_date: String?,
|
||||
|
||||
// Score fields
|
||||
val id: Int?,
|
||||
|
||||
@ -35,6 +35,7 @@ class ScoreSearchSchemaController(
|
||||
InternalSchemaField("user_count_50", "50s", Category.user, Type.number, false, "number of 50 hits", databaseField = USERS.COUNT_50),
|
||||
InternalSchemaField("user_count_miss", "Misses", Category.user, Type.number, false, "missed hits", databaseField = USERS.COUNT_MISS),
|
||||
InternalSchemaField("user_is_banned", "Is Banned", Category.user, Type.boolean, false, "is the user banned?", databaseField = USERS.IS_BANNED),
|
||||
InternalSchemaField("user_approx_ban_date", "Approx. ban date", Category.user, Type.datetime, false, "approximate date the user was banned at.", databaseField = USERS.APPROX_BAN_DATE),
|
||||
|
||||
// Score fields
|
||||
InternalSchemaField("is_banned", "Banned", Category.score, Type.boolean, false, "has to score been deleted?", databaseField = SCORES.IS_BANNED),
|
||||
|
||||
@ -5,6 +5,11 @@ import com.nisemoe.generated.tables.references.SCORES
|
||||
import com.nisemoe.generated.tables.references.USERS
|
||||
import com.nisemoe.nise.Format
|
||||
import com.nisemoe.nise.osu.Mod
|
||||
import com.nisemoe.nise.search.PredicateBuilder.Companion.buildBooleanCondition
|
||||
import com.nisemoe.nise.search.PredicateBuilder.Companion.buildDatetimeCondition
|
||||
import com.nisemoe.nise.search.PredicateBuilder.Companion.buildGradeCondition
|
||||
import com.nisemoe.nise.search.PredicateBuilder.Companion.buildNumberCondition
|
||||
import com.nisemoe.nise.search.PredicateBuilder.Companion.buildStringCondition
|
||||
import com.nisemoe.nise.service.AuthService
|
||||
import org.jooq.*
|
||||
import org.jooq.impl.DSL
|
||||
@ -47,6 +52,7 @@ class ScoreSearchService(
|
||||
USERS.COUNT_50,
|
||||
USERS.COUNT_MISS,
|
||||
USERS.IS_BANNED,
|
||||
USERS.APPROX_BAN_DATE,
|
||||
|
||||
// Scores fields
|
||||
SCORES.ID,
|
||||
@ -155,6 +161,7 @@ class ScoreSearchService(
|
||||
user_count_50 = it.get(USERS.COUNT_50),
|
||||
user_count_miss = it.get(USERS.COUNT_MISS),
|
||||
user_is_banned = it.get(USERS.IS_BANNED),
|
||||
user_approx_ban_date = it.get(USERS.APPROX_BAN_DATE)?.let { it1 -> Format.formatOffsetDateTime(it1) },
|
||||
|
||||
// Score fields
|
||||
id = it.get(SCORES.ID),
|
||||
@ -260,64 +267,4 @@ class ScoreSearchService(
|
||||
}
|
||||
return databaseField.databaseField!!
|
||||
}
|
||||
|
||||
private fun buildBooleanCondition(field: Field<Boolean>, operator: String, value: Boolean): Condition {
|
||||
return when (operator) {
|
||||
"=" -> field.eq(value)
|
||||
"!=" -> field.ne(value)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildGradeCondition(field: Field<String>, operator: String, value: String): Condition {
|
||||
return when (value) {
|
||||
"SS", "S", "A", "B", "C", "D" -> {
|
||||
val valuesToMatch = when (value) {
|
||||
"SS" -> listOf("Grade.SS", "Grade.SSH")
|
||||
"S" -> listOf("Grade.S", "Grade.SH")
|
||||
else -> listOf("Grade.$value")
|
||||
}
|
||||
when (operator) {
|
||||
"=" -> field.`in`(valuesToMatch)
|
||||
"!=" -> field.notIn(valuesToMatch)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
else -> throw IllegalArgumentException("Invalid grade value")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildNumberCondition(field: Field<Double>, operator: String, value: Double): Condition {
|
||||
return when (operator) {
|
||||
"=" -> field.eq(value)
|
||||
">" -> field.gt(value)
|
||||
"<" -> field.lt(value)
|
||||
">=" -> field.ge(value)
|
||||
"<=" -> field.le(value)
|
||||
"!=" -> field.ne(value)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildStringCondition(field: Field<String>, operator: String, value: String): Condition {
|
||||
return when (operator.lowercase()) {
|
||||
"=" -> field.eq(value)
|
||||
"contains" -> field.containsIgnoreCase(value)
|
||||
"like" -> field.likeIgnoreCase(
|
||||
// Escape special characters for LIKE if needed
|
||||
value.replace("%", "\\%").replace("_", "\\_")
|
||||
)
|
||||
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatetimeCondition(field: Field<String>, operator: String, value: String): Condition {
|
||||
return when (operator.lowercase()) {
|
||||
"before" -> field.lessThan(value)
|
||||
"after" -> field.greaterThan(value)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -61,7 +61,8 @@ class UserSearchController(
|
||||
val count_100: Long?,
|
||||
val count_50: Long?,
|
||||
val count_miss: Long?,
|
||||
val is_banned: Boolean?
|
||||
val is_banned: Boolean?,
|
||||
val approx_ban_date: String?,
|
||||
)
|
||||
|
||||
data class SearchRequest(
|
||||
|
||||
@ -33,6 +33,7 @@ class UserSearchSchemaController(
|
||||
InternalSchemaField("count_50", "50s", Category.user, Type.number, false, "number of 50 hits", databaseField = USERS.COUNT_50),
|
||||
InternalSchemaField("count_miss", "Misses", Category.user, Type.number, false, "missed hits", databaseField = USERS.COUNT_MISS),
|
||||
InternalSchemaField("is_banned", "Is Banned", Category.user, Type.boolean, false, "is the user banned?", databaseField = USERS.IS_BANNED),
|
||||
InternalSchemaField("approx_ban_date", "Approx. ban date", Category.user, Type.datetime, false, "approximate date the user was banned at.", databaseField = USERS.APPROX_BAN_DATE),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@ -3,11 +3,17 @@ package com.nisemoe.nise.search.user
|
||||
import com.nisemoe.generated.tables.references.SCORES
|
||||
import com.nisemoe.generated.tables.references.USERS
|
||||
import com.nisemoe.nise.Format
|
||||
import com.nisemoe.nise.search.PredicateBuilder.Companion.buildBooleanCondition
|
||||
import com.nisemoe.nise.search.PredicateBuilder.Companion.buildDatetimeCondition
|
||||
import com.nisemoe.nise.search.PredicateBuilder.Companion.buildGradeCondition
|
||||
import com.nisemoe.nise.search.PredicateBuilder.Companion.buildNumberCondition
|
||||
import com.nisemoe.nise.search.PredicateBuilder.Companion.buildStringCondition
|
||||
import org.jooq.*
|
||||
import org.jooq.impl.DSL
|
||||
import org.springframework.stereotype.Service
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
@Service
|
||||
class UserSearchService(
|
||||
private val dslContext: DSLContext
|
||||
@ -41,7 +47,8 @@ class UserSearchService(
|
||||
USERS.COUNT_100,
|
||||
USERS.COUNT_50,
|
||||
USERS.COUNT_MISS,
|
||||
USERS.IS_BANNED
|
||||
USERS.IS_BANNED,
|
||||
USERS.APPROX_BAN_DATE
|
||||
)
|
||||
|
||||
val query = dslContext
|
||||
@ -93,7 +100,8 @@ class UserSearchService(
|
||||
count_100 = it.get(USERS.COUNT_100),
|
||||
count_50 = it.get(USERS.COUNT_50),
|
||||
count_miss = it.get(USERS.COUNT_MISS),
|
||||
is_banned = it.get(USERS.IS_BANNED)
|
||||
is_banned = it.get(USERS.IS_BANNED),
|
||||
approx_ban_date = it.get(USERS.APPROX_BAN_DATE)?.let { it1 -> Format.formatOffsetDateTime(it1) }
|
||||
)
|
||||
}
|
||||
|
||||
@ -154,63 +162,4 @@ class UserSearchService(
|
||||
return databaseField.databaseField!!
|
||||
}
|
||||
|
||||
private fun buildBooleanCondition(field: Field<Boolean>, operator: String, value: Boolean): Condition {
|
||||
return when (operator) {
|
||||
"=" -> field.eq(value)
|
||||
"!=" -> field.ne(value)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildGradeCondition(field: Field<String>, operator: String, value: String): Condition {
|
||||
return when (value) {
|
||||
"SS", "S", "A", "B", "C", "D" -> {
|
||||
val valuesToMatch = when (value) {
|
||||
"SS" -> listOf("Grade.SS", "Grade.SSH")
|
||||
"S" -> listOf("Grade.S", "Grade.SH")
|
||||
else -> listOf("Grade.$value")
|
||||
}
|
||||
when (operator) {
|
||||
"=" -> field.`in`(valuesToMatch)
|
||||
"!=" -> field.notIn(valuesToMatch)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
else -> throw IllegalArgumentException("Invalid grade value")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildNumberCondition(field: Field<Double>, operator: String, value: Double): Condition {
|
||||
return when (operator) {
|
||||
"=" -> field.eq(value)
|
||||
">" -> field.gt(value)
|
||||
"<" -> field.lt(value)
|
||||
">=" -> field.ge(value)
|
||||
"<=" -> field.le(value)
|
||||
"!=" -> field.ne(value)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildStringCondition(field: Field<String>, operator: String, value: String): Condition {
|
||||
return when (operator.lowercase()) {
|
||||
"=" -> field.eq(value)
|
||||
"contains" -> field.containsIgnoreCase(value)
|
||||
"like" -> field.likeIgnoreCase(
|
||||
// Escape special characters for LIKE if needed
|
||||
value.replace("%", "\\%").replace("_", "\\_")
|
||||
)
|
||||
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatetimeCondition(field: Field<String>, operator: String, value: String): Condition {
|
||||
return when (operator.lowercase()) {
|
||||
"before" -> field.lessThan(value)
|
||||
"after" -> field.greaterThan(value)
|
||||
else -> throw IllegalArgumentException("Invalid operator")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user