diff --git a/src/main/java/com/snackgame/server/game/snackgame/core/domain/Snackgame.kt b/src/main/java/com/snackgame/server/game/snackgame/core/domain/Snackgame.kt index f786cbe..612ab3c 100644 --- a/src/main/java/com/snackgame/server/game/snackgame/core/domain/Snackgame.kt +++ b/src/main/java/com/snackgame/server/game/snackgame/core/domain/Snackgame.kt @@ -45,13 +45,9 @@ open class Snackgame( fun remove(streakWithFever: StreakWithFever) { val streak = streakWithFever.streak - val removedSnacks = board.removeSnacksIn(streak) + val removedSnacks = board.removeSnacksIn(streakWithFever.streak) - val serverIsFever = feverTime?.isActive(streakWithFever.occurredAt) == true - val isValid = streakWithFever.clientIsFever && serverIsFever - - val multiplier = if (isValid) FEVER_MULTIPLIER else NORMAL_MULTIPLIER - increaseScore(streak.length * multiplier) + increaseScore(streak.length * isFever(streakWithFever)) if (removedSnacks.any(Snack::isGolden)) { this.board = board.reset() @@ -67,13 +63,19 @@ open class Snackgame( } } - fun startFeverTime() { - this.feverTime = FeverTime.start() + private fun isFever(streakWithFever: StreakWithFever): Int { + val serverIsFever = feverTime?.isActive(streakWithFever.occurredAt) == true + val isValid = streakWithFever.clientIsFever && serverIsFever + val multiplier = if (isValid) FEVER_MULTIPLIER else NORMAL_MULTIPLIER + return multiplier } private fun increaseScore(earn: Int) { - val multiplier = if (feverTime?.isActive() == true) FEVER_MULTIPLIER else NORMAL_MULTIPLIER - this.score += earn * multiplier + this.score += earn + } + + fun startFeverTime() { + this.feverTime = FeverTime.start() } override val metadata = SNACK_GAME diff --git a/src/main/java/com/snackgame/server/game/snackgame/core/domain/item/FeverTime.kt b/src/main/java/com/snackgame/server/game/snackgame/core/domain/item/FeverTime.kt index ead7eaf..fabd527 100644 --- a/src/main/java/com/snackgame/server/game/snackgame/core/domain/item/FeverTime.kt +++ b/src/main/java/com/snackgame/server/game/snackgame/core/domain/item/FeverTime.kt @@ -12,7 +12,7 @@ class FeverTime( fun isActive(now: LocalDateTime = LocalDateTime.now()): Boolean { if (feverStartedAt == null) return false val effectiveStart = feverPausedAt?.let { feverStartedAt!!.plus(Duration.between(it, now)) } ?: feverStartedAt - return Duration.between(effectiveStart, now) < DURATION + return Duration.between(effectiveStart, now) < FEVER_TIME_PERIOD } fun pause() { @@ -31,7 +31,7 @@ class FeverTime( } companion object { - private val DURATION: Duration = Duration.ofSeconds(30) + private val FEVER_TIME_PERIOD: Duration = Duration.ofSeconds(30) fun start(now: LocalDateTime = LocalDateTime.now()): FeverTime { return FeverTime(now) diff --git a/src/main/java/com/snackgame/server/game/snackgame/core/service/dto/StreaksRequest.kt b/src/main/java/com/snackgame/server/game/snackgame/core/service/dto/StreaksRequest.kt index f9ff013..26eed98 100644 --- a/src/main/java/com/snackgame/server/game/snackgame/core/service/dto/StreaksRequest.kt +++ b/src/main/java/com/snackgame/server/game/snackgame/core/service/dto/StreaksRequest.kt @@ -3,6 +3,8 @@ package com.snackgame.server.game.snackgame.core.service.dto import com.fasterxml.jackson.annotation.JsonCreator import com.snackgame.server.game.snackgame.core.domain.Coordinate import com.snackgame.server.game.snackgame.core.domain.Streak +import com.snackgame.server.game.snackgame.exception.InvalidStreakTimeException +import java.time.Duration import java.time.LocalDateTime data class StreaksRequest @JsonCreator constructor( @@ -14,14 +16,24 @@ data class StreaksRequest @JsonCreator constructor( data class StreakWithMeta( val coordinates: List, - val isFever: Boolean + val isFever: Boolean, + val occurredAt: LocalDateTime, ) { - fun toDomain(now: LocalDateTime): StreakWithFever = - StreakWithFever( + fun toDomain(now: LocalDateTime): StreakWithFever { + if (Duration.between(occurredAt, now).abs() > REQUEST_TIME_TOLERANCE) { + throw InvalidStreakTimeException() + } + + return StreakWithFever( streak = Streak.of(coordinates.map { Coordinate(it.y, it.x) }), clientIsFever = isFever, - occurredAt = now + occurredAt = occurredAt ) + } + + companion object { + private val REQUEST_TIME_TOLERANCE: Duration = Duration.ofSeconds(2) + } } data class StreakWithFever( diff --git a/src/main/java/com/snackgame/server/game/snackgame/exception/InvalidStreakTimeException.kt b/src/main/java/com/snackgame/server/game/snackgame/exception/InvalidStreakTimeException.kt new file mode 100644 index 0000000..df23b33 --- /dev/null +++ b/src/main/java/com/snackgame/server/game/snackgame/exception/InvalidStreakTimeException.kt @@ -0,0 +1,4 @@ +package com.snackgame.server.game.snackgame.exception + +class InvalidStreakTimeException : SnackgameException("허용된 시간차를 초과하였습니다.") { +} \ No newline at end of file diff --git a/src/test/java/com/snackgame/server/game/snackgame/core/service/SnackgameServiceTest.kt b/src/test/java/com/snackgame/server/game/snackgame/core/service/SnackgameServiceTest.kt index 0384d49..4f73191 100644 --- a/src/test/java/com/snackgame/server/game/snackgame/core/service/SnackgameServiceTest.kt +++ b/src/test/java/com/snackgame/server/game/snackgame/core/service/SnackgameServiceTest.kt @@ -48,7 +48,8 @@ class SnackgameServiceTest { listOf( StreakWithMeta( coordinates = coordinates, - isFever = false + isFever = false, + LocalDateTime.now() ) ) ) @@ -85,7 +86,8 @@ class SnackgameServiceTest { listOf( StreakWithMeta( coordinates = coordinates, - isFever = false + isFever = true, + LocalDateTime.now() ) ) )