diff --git a/nise-backend/src/main/kotlin/com/nisemoe/nise/scheduler/Agent.kt b/nise-backend/src/main/kotlin/com/nisemoe/nise/scheduler/Agent.kt new file mode 100644 index 0000000..fff0d10 --- /dev/null +++ b/nise-backend/src/main/kotlin/com/nisemoe/nise/scheduler/Agent.kt @@ -0,0 +1,96 @@ +package com.nisemoe.nise.scheduler + +import com.nisemoe.generated.tables.records.ScoresRecord +import com.nisemoe.generated.tables.references.SCORES +import com.nisemoe.generated.tables.references.USERS +import org.jooq.DSLContext +import org.springframework.context.annotation.Profile +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.stereotype.Service + +data class UserReport( + val username: String, + val susScore: Double, + val userId: Long, + val userScores: List +) + +@Service +@Profile("agent") +class Agent( + private val dslContext: DSLContext +) { + + // 20 minutes to ms = 1200000 + @Scheduled(fixedDelay = 1200000, initialDelay = 0) + fun buildReports() { + + // Select sus scores + val susUsers = dslContext.select( + SCORES.USER_ID, + SCORES.ADJUSTED_UR, + SCORES.SLIDEREND_RELEASE_STANDARD_DEVIATION_ADJUSTED, + SCORES.PP, + SCORES.EDGE_HITS, + SCORES.SNAPS, + SCORES.KEYPRESSES_MEDIAN_ADJUSTED, + SCORES.ERROR_KURTOSIS + ) + .from(SCORES) + .where(SCORES.ADJUSTED_UR.lessOrEqual(10.0)) + .and(SCORES.SLIDEREND_RELEASE_STANDARD_DEVIATION_ADJUSTED.lessOrEqual(8.0)) + .and(SCORES.IS_BANNED.isFalse) + .and(SCORES.VERSION.greaterOrEqual(4)) + .fetchInto(ScoresRecord::class.java) + + val reports = mutableListOf() + + for(user in susUsers.groupBy { it.userId }) { + val userId = user.key!! + val username = dslContext.select(USERS.USERNAME) + .from(USERS) + .where(USERS.USER_ID.eq(userId)) + .fetchOne(USERS.USERNAME) ?: continue + + val userScores = user.value + val susScore = calculateSuspiciousnessScore(userScores) + + reports.add(UserReport(userId = userId, username = username, userScores = userScores, susScore = susScore)) + } + + reports.sortByDescending { it.susScore } + + println(reports) + } + + fun calculateSuspiciousnessScore(scores: List): Double { + if (scores.isEmpty()) return 0.0 + + return scores.sumOf { score -> + var suspiciousnessScore = 0.0 + + suspiciousnessScore += score.pp!! * 1.0 + + suspiciousnessScore += if (score.adjustedUr!! < 6.0) 5.0 else 0.0 + + suspiciousnessScore += if (score.sliderendReleaseStandardDeviationAdjusted!! < 6) 5.0 else 0.0 + + suspiciousnessScore += when { + score.edgeHits!! > 4 -> (score.edgeHits!! - 4) * 2.0 + else -> 0.0 + } + + suspiciousnessScore += when { + score.snaps!! > 4 -> (score.snaps!! - 4) * 2.0 + else -> 0.0 + } + + suspiciousnessScore += if (score.keypressesMedianAdjusted!! < 6) 5.0 else 0.0 + + suspiciousnessScore += if (score.errorKurtosis!! < 6) 5.0 else 0.0 + + suspiciousnessScore + } + } + +} \ No newline at end of file