From b371cca725a67036554787f4fc733865ecabdcd6 Mon Sep 17 00:00:00 2001 From: Ayush Chadha Date: Sun, 4 Feb 2024 10:08:51 +0530 Subject: [PATCH] fix: daily stats --- docs/spec/CodeCharacter-API.yml | 16 ---- .../codecharacter/dtos/UserMatchStatDto.kt | 16 ---- .../dtos/UserMatchStatsInnerDto.kt | 16 ---- .../server/match/MatchService.kt | 2 +- .../server/schedulers/SchedulingService.kt | 94 +++++++++---------- .../server/stats/PublicStatEntity.kt | 3 +- .../codecharacter/server/stats/StatEntity.kt | 10 +- .../server/stats/StatsController.kt | 2 - .../server/stats/StatsService.kt | 70 ++++++++------ 9 files changed, 97 insertions(+), 132 deletions(-) diff --git a/docs/spec/CodeCharacter-API.yml b/docs/spec/CodeCharacter-API.yml index c565528..e516dfb 100644 --- a/docs/spec/CodeCharacter-API.yml +++ b/docs/spec/CodeCharacter-API.yml @@ -1970,34 +1970,18 @@ components: type: object description: User Match Stat model properties: - maxAtk: - type: number - default: 0 - minAtk: - type: number - default: 0 avgAtk: type: number default: 0 dc_wins: type: number default: 0 - dc_losses: - type: number - default: 0 - dc_destruction: - type: number - default: 0 coins: type: number default: 0 required: - - maxAtk - - minAtk - avgAtk - dc_wins - - dc_losses - - dc_destruction - coins DailyChallengeGetRequest: diff --git a/library/src/main/kotlin/delta/codecharacter/dtos/UserMatchStatDto.kt b/library/src/main/kotlin/delta/codecharacter/dtos/UserMatchStatDto.kt index 15e3c17..4e3c1bf 100644 --- a/library/src/main/kotlin/delta/codecharacter/dtos/UserMatchStatDto.kt +++ b/library/src/main/kotlin/delta/codecharacter/dtos/UserMatchStatDto.kt @@ -16,34 +16,18 @@ import java.math.BigDecimal /** * User Match Stat model - * @param maxAtk - * @param minAtk * @param avgAtk * @param dcWins - * @param dcLosses - * @param dcDestruction * @param coins */ data class UserMatchStatDto( - @Schema(example = "null", required = true, description = "") - @get:JsonProperty("maxAtk", required = true) val maxAtk: java.math.BigDecimal = BigDecimal.ZERO, - - @Schema(example = "null", required = true, description = "") - @get:JsonProperty("minAtk", required = true) val minAtk: java.math.BigDecimal = BigDecimal.ZERO, - @Schema(example = "null", required = true, description = "") @get:JsonProperty("avgAtk", required = true) val avgAtk: java.math.BigDecimal = BigDecimal.ZERO, @Schema(example = "null", required = true, description = "") @get:JsonProperty("dc_wins", required = true) val dcWins: java.math.BigDecimal = BigDecimal.ZERO, - @Schema(example = "null", required = true, description = "") - @get:JsonProperty("dc_losses", required = true) val dcLosses: java.math.BigDecimal = BigDecimal.ZERO, - - @Schema(example = "null", required = true, description = "") - @get:JsonProperty("dc_destruction", required = true) val dcDestruction: java.math.BigDecimal = BigDecimal.ZERO, - @Schema(example = "null", required = true, description = "") @get:JsonProperty("coins", required = true) val coins: java.math.BigDecimal = BigDecimal.ZERO ) { diff --git a/library/src/main/kotlin/delta/codecharacter/dtos/UserMatchStatsInnerDto.kt b/library/src/main/kotlin/delta/codecharacter/dtos/UserMatchStatsInnerDto.kt index e34c0a9..f49aa72 100644 --- a/library/src/main/kotlin/delta/codecharacter/dtos/UserMatchStatsInnerDto.kt +++ b/library/src/main/kotlin/delta/codecharacter/dtos/UserMatchStatsInnerDto.kt @@ -17,34 +17,18 @@ import java.math.BigDecimal /** * - * @param maxAtk - * @param minAtk * @param avgAtk * @param dcWins - * @param dcLosses - * @param dcDestruction * @param coins */ data class UserMatchStatsInnerDto( - @Schema(example = "null", required = true, description = "") - @get:JsonProperty("maxAtk", required = true) val maxAtk: java.math.BigDecimal = BigDecimal.ZERO, - - @Schema(example = "null", required = true, description = "") - @get:JsonProperty("minAtk", required = true) val minAtk: java.math.BigDecimal = BigDecimal.ZERO, - @Schema(example = "null", required = true, description = "") @get:JsonProperty("avgAtk", required = true) val avgAtk: java.math.BigDecimal = BigDecimal.ZERO, @Schema(example = "null", required = true, description = "") @get:JsonProperty("dc_wins", required = true) val dcWins: java.math.BigDecimal = BigDecimal.ZERO, - @Schema(example = "null", required = true, description = "") - @get:JsonProperty("dc_losses", required = true) val dcLosses: java.math.BigDecimal = BigDecimal.ZERO, - - @Schema(example = "null", required = true, description = "") - @get:JsonProperty("dc_destruction", required = true) val dcDestruction: java.math.BigDecimal = BigDecimal.ZERO, - @Schema(example = "null", required = true, description = "") @get:JsonProperty("coins", required = true) val coins: java.math.BigDecimal = BigDecimal.ZERO ) { diff --git a/server/src/main/kotlin/delta/codecharacter/server/match/MatchService.kt b/server/src/main/kotlin/delta/codecharacter/server/match/MatchService.kt index 86ac067..ff78ef0 100644 --- a/server/src/main/kotlin/delta/codecharacter/server/match/MatchService.kt +++ b/server/src/main/kotlin/delta/codecharacter/server/match/MatchService.kt @@ -485,7 +485,7 @@ class MatchService( statsService.updateStats( userId = match.user.userId, verdict = verdict, - atkDmg = updatedGame.destruction, + atkDmg = 0.0, dcAttempts = 1, coins = updatedGame.coinsUsed ) diff --git a/server/src/main/kotlin/delta/codecharacter/server/schedulers/SchedulingService.kt b/server/src/main/kotlin/delta/codecharacter/server/schedulers/SchedulingService.kt index 3fde6d8..f813228 100644 --- a/server/src/main/kotlin/delta/codecharacter/server/schedulers/SchedulingService.kt +++ b/server/src/main/kotlin/delta/codecharacter/server/schedulers/SchedulingService.kt @@ -1,47 +1,47 @@ - package delta.codecharacter.server.schedulers - - import delta.codecharacter.server.code.code_revision.CodeRevisionService - import delta.codecharacter.server.code.latest_code.LatestCodeService - import delta.codecharacter.server.code.locked_code.LockedCodeService - import delta.codecharacter.server.game_map.latest_map.LatestMapService - import delta.codecharacter.server.game_map.locked_map.LockedMapService - import delta.codecharacter.server.game_map.map_revision.MapRevisionService - import delta.codecharacter.server.match.MatchService - import delta.codecharacter.server.user.public_user.PublicUserService - import org.slf4j.Logger - import org.slf4j.LoggerFactory - import org.springframework.beans.factory.annotation.Autowired - import org.springframework.scheduling.annotation.Scheduled - import org.springframework.stereotype.Service - - @Service - class SchedulingService( - @Autowired private val publicUserService: PublicUserService, - @Autowired private val matchService: MatchService, - @Autowired private val codeRevisionService: CodeRevisionService, - @Autowired private val latestCodeService: LatestCodeService, - @Autowired private val lockedCodeService: LockedCodeService, - @Autowired private val latestMapService: LatestMapService, - @Autowired private val lockedMapService: LockedMapService, - @Autowired private val mapRevisionService: MapRevisionService - ) { - private val logger: Logger = LoggerFactory.getLogger(SchedulingService::class.java) - - @Scheduled(cron = "\${environment.registration-time}", zone = "GMT+5:30") - fun updateTempLeaderboard() { - logger.info("Practice phase ended!!") - publicUserService.resetRatingsAfterPracticePhase() - codeRevisionService.resetCodeRevisionAfterPracticePhase() - latestCodeService.resetLatestCodeAfterPracticePhase() - lockedCodeService.resetLockedCodeAfterPracticePhase() - latestMapService.resetLatestMapAfterPracticePhase() - lockedMapService.resetLockedMapAfterPracticePhase() - mapRevisionService.resetMapRevisionAfterPracticePhase() - publicUserService.updateLeaderboardAfterPracticePhase() - } - - @Scheduled(cron = "\${environment.promote-demote-time}", zone = "GMT+5:30") - fun createAutoMatch() { - matchService.createAutoMatch() - } - } +// package delta.codecharacter.server.schedulers +// +// import delta.codecharacter.server.code.code_revision.CodeRevisionService +// import delta.codecharacter.server.code.latest_code.LatestCodeService +// import delta.codecharacter.server.code.locked_code.LockedCodeService +// import delta.codecharacter.server.game_map.latest_map.LatestMapService +// import delta.codecharacter.server.game_map.locked_map.LockedMapService +// import delta.codecharacter.server.game_map.map_revision.MapRevisionService +// import delta.codecharacter.server.match.MatchService +// import delta.codecharacter.server.user.public_user.PublicUserService +// import org.slf4j.Logger +// import org.slf4j.LoggerFactory +// import org.springframework.beans.factory.annotation.Autowired +// import org.springframework.scheduling.annotation.Scheduled +// import org.springframework.stereotype.Service +// +// @Service +// class SchedulingService( +// @Autowired private val publicUserService: PublicUserService, +// @Autowired private val matchService: MatchService, +// @Autowired private val codeRevisionService: CodeRevisionService, +// @Autowired private val latestCodeService: LatestCodeService, +// @Autowired private val lockedCodeService: LockedCodeService, +// @Autowired private val latestMapService: LatestMapService, +// @Autowired private val lockedMapService: LockedMapService, +// @Autowired private val mapRevisionService: MapRevisionService +// ) { +// private val logger: Logger = LoggerFactory.getLogger(SchedulingService::class.java) +// +// @Scheduled(cron = "\${environment.registration-time}", zone = "GMT+5:30") +// fun updateTempLeaderboard() { +// logger.info("Practice phase ended!!") +// publicUserService.resetRatingsAfterPracticePhase() +// codeRevisionService.resetCodeRevisionAfterPracticePhase() +// latestCodeService.resetLatestCodeAfterPracticePhase() +// lockedCodeService.resetLockedCodeAfterPracticePhase() +// latestMapService.resetLatestMapAfterPracticePhase() +// lockedMapService.resetLockedMapAfterPracticePhase() +// mapRevisionService.resetMapRevisionAfterPracticePhase() +// publicUserService.updateLeaderboardAfterPracticePhase() +// } +// +// @Scheduled(cron = "\${environment.promote-demote-time}", zone = "GMT+5:30") +// fun createAutoMatch() { +// matchService.createAutoMatch() +// } +// } diff --git a/server/src/main/kotlin/delta/codecharacter/server/stats/PublicStatEntity.kt b/server/src/main/kotlin/delta/codecharacter/server/stats/PublicStatEntity.kt index 7c540d0..af6797d 100644 --- a/server/src/main/kotlin/delta/codecharacter/server/stats/PublicStatEntity.kt +++ b/server/src/main/kotlin/delta/codecharacter/server/stats/PublicStatEntity.kt @@ -1,5 +1,6 @@ package delta.codecharacter.server.stats +import delta.codecharacter.server.user.public_user.DailyChallengeHistory import org.springframework.data.annotation.Id import org.springframework.data.mongodb.core.mapping.Document import java.util.* @@ -7,5 +8,5 @@ import java.util.* @Document(collection="stats") data class PublicStatEntity( @Id val userId: UUID, - val stats : List + var stats: HashMap ) diff --git a/server/src/main/kotlin/delta/codecharacter/server/stats/StatEntity.kt b/server/src/main/kotlin/delta/codecharacter/server/stats/StatEntity.kt index dc246a4..735e63c 100644 --- a/server/src/main/kotlin/delta/codecharacter/server/stats/StatEntity.kt +++ b/server/src/main/kotlin/delta/codecharacter/server/stats/StatEntity.kt @@ -1,11 +1,11 @@ package delta.codecharacter.server.stats +import delta.codecharacter.server.match.MatchModeEnum +import java.time.Instant + data class StatEntity ( - val maxAtk :Double, - val minAtk : Double, val avgAtk : Double, val dc_wins : Int, - val dc_losses : Int, - val dc_destruction: Int, - val coins : Int + val coins : Int, + val createdAt: Instant, ) diff --git a/server/src/main/kotlin/delta/codecharacter/server/stats/StatsController.kt b/server/src/main/kotlin/delta/codecharacter/server/stats/StatsController.kt index ee2aec4..9f9ffe4 100644 --- a/server/src/main/kotlin/delta/codecharacter/server/stats/StatsController.kt +++ b/server/src/main/kotlin/delta/codecharacter/server/stats/StatsController.kt @@ -20,6 +20,4 @@ class StatsController(@Autowired private val statsService: StatsService) : Stats val user = SecurityContextHolder.getContext().authentication.principal as UserEntity return ResponseEntity.ok(statsService.getInfo(user.id)) } - - } diff --git a/server/src/main/kotlin/delta/codecharacter/server/stats/StatsService.kt b/server/src/main/kotlin/delta/codecharacter/server/stats/StatsService.kt index b0a9898..2b4786d 100644 --- a/server/src/main/kotlin/delta/codecharacter/server/stats/StatsService.kt +++ b/server/src/main/kotlin/delta/codecharacter/server/stats/StatsService.kt @@ -1,24 +1,33 @@ package delta.codecharacter.server.stats import delta.codecharacter.dtos.UserMatchStatsInnerDto +import delta.codecharacter.server.daily_challenge.DailyChallengeService import delta.codecharacter.server.daily_challenge.match.DailyChallengeMatchVerdictEnum -import delta.codecharacter.server.schedulers.SchedulingService import delta.codecharacter.server.user.public_user.PublicUserRepository -import org.slf4j.Logger -import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value import org.springframework.data.domain.PageRequest import org.springframework.data.domain.Sort import org.springframework.stereotype.Service import java.math.BigDecimal +import java.time.Duration +import java.time.Instant import java.util.* import kotlin.collections.ArrayList -import kotlin.math.max +import kotlin.collections.HashMap import kotlin.math.min @Service class StatsService(@Autowired private val statsRepository:StatsRepository, @Autowired private val publicUserRepository: PublicUserRepository){ + + @Value("\${environment.event-start-date}") private lateinit var startDate: String + fun findNumberOfDays(): Int { + val givenDateTime = Instant.parse(startDate) + val nowDateTime = Instant.now() + val period: Duration = Duration.between(givenDateTime, nowDateTime) + return period.toDays().toInt() + } fun updateStats( userId: UUID, atkDmg: Double, @@ -26,30 +35,39 @@ class StatsService(@Autowired private val statsRepository:StatsRepository, dcAttempts: Int, verdict: DailyChallengeMatchVerdictEnum?, ) { + val currentDay = findNumberOfDays() if(statsRepository.existsById(userId)) { - val userList = statsRepository.findById(userId).get() - val user = userList.stats.last() + val user = (statsRepository.findById(userId).get()) + val userStats:StatEntity; + if(user.stats.containsKey(currentDay)){ + userStats = user.stats[currentDay]!! + } else { + var win = 0 + if(dcAttempts!=0){ + win = if(verdict == DailyChallengeMatchVerdictEnum.SUCCESS) 1 else 0 + } + user.stats[currentDay] = StatEntity(atkDmg,win,coins, Instant.now()); + userStats = user.stats[currentDay]!! + } val updatedUserStat = - user.copy( - maxAtk = max(user.maxAtk, atkDmg), - minAtk = min(user.minAtk, atkDmg), - avgAtk = (user.avgAtk * userList.stats.size + atkDmg) / (1+userList.stats.size), - coins = (user.coins * userList.stats.size + coins) / (1+userList.stats.size), - dc_losses = - if (dcAttempts != 0 && verdict == DailyChallengeMatchVerdictEnum.FAILURE) - user.dc_losses + 1 - else user.dc_losses, + userStats.copy( + avgAtk = (userStats.avgAtk * user.stats.size + atkDmg) / (1+user.stats.size), + coins = (userStats.coins * user.stats.size + coins) / (1+user.stats.size), dc_wins = if (dcAttempts != 0 && verdict == DailyChallengeMatchVerdictEnum.SUCCESS) - user.dc_wins + 1 - else user.dc_wins, + userStats.dc_wins + 1 + else userStats.dc_wins, ) - val updatedUserList = (userList.stats.toMutableList()) - updatedUserList.add(updatedUserStat) - val updatedUser = userList.copy(stats = updatedUserList) - statsRepository.save(updatedUser) + user.stats[currentDay] = updatedUserStat; + statsRepository.save(user) } else { - statsRepository.insert((PublicStatEntity(userId,listOf(StatEntity(atkDmg,atkDmg,atkDmg,0,0,0,coins))))) + val initialMap = HashMap(); + var win = 0 + if(dcAttempts!=0){ + win = if(verdict == DailyChallengeMatchVerdictEnum.SUCCESS) 1 else 0 + } + initialMap[currentDay] = StatEntity(atkDmg,win,coins,Instant.now()) + statsRepository.insert(PublicStatEntity(userId,initialMap)) } } fun getInfo(userId: UUID): List> { @@ -68,7 +86,7 @@ class StatsService(@Autowired private val statsRepository:StatsRepository, l.add(lTop) return l } - val currentUserStats = statsRepository.findById(userId).get(); + val currentUserStats = statsRepository.findById(userId).get() var lUser = convertToDTO(currentUserStats) val minEle = min(lUser.size,lTop.size) @@ -83,14 +101,10 @@ class StatsService(@Autowired private val statsRepository:StatsRepository, } private fun convertToDTO(currentUserStatsArr: PublicStatEntity): List { - return currentUserStatsArr.stats.map {it -> + return currentUserStatsArr.stats.values.map {it -> UserMatchStatsInnerDto( - maxAtk = BigDecimal(it.maxAtk), - minAtk = BigDecimal(it.minAtk), avgAtk = BigDecimal(it.avgAtk), dcWins = BigDecimal(it.dc_wins), - dcLosses = BigDecimal(it.dc_losses), - dcDestruction = BigDecimal(it.dc_destruction), coins = BigDecimal(it.coins) ) }