diff --git a/src/main/java/com/snackgame/server/game/snackgame/biz/domain/SnackgameBiz.kt b/src/main/java/com/snackgame/server/game/snackgame/biz/domain/SnackgameBiz.kt index 3ff312d7..89ac2fad 100644 --- a/src/main/java/com/snackgame/server/game/snackgame/biz/domain/SnackgameBiz.kt +++ b/src/main/java/com/snackgame/server/game/snackgame/biz/domain/SnackgameBiz.kt @@ -6,12 +6,17 @@ import com.snackgame.server.game.snackgame.core.domain.Board import com.snackgame.server.game.snackgame.core.domain.BoardConverter import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.DEFAULT_HEIGHT import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.DEFAULT_WIDTH +import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.FEVER_MULTIPLIER +import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.NORMAL_MULTIPLIER import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.SESSION_TIME import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.SPARE_TIME import com.snackgame.server.game.snackgame.core.domain.Streak +import com.snackgame.server.game.snackgame.core.domain.item.FeverTime import com.snackgame.server.game.snackgame.core.domain.snack.Snack +import com.snackgame.server.game.snackgame.core.service.dto.StreakWithFever import java.time.Duration import javax.persistence.Convert +import javax.persistence.Embedded import javax.persistence.Entity import javax.persistence.Lob @@ -33,6 +38,11 @@ open class SnackgameBiz( this.score = score } + @Embedded + var feverTime: FeverTime? = null + private set + + fun remove(streak: Streak) { val removedSnacks = board.removeSnacksIn(streak) this.score += removedSnacks.size @@ -41,5 +51,25 @@ open class SnackgameBiz( } } + fun remove(streakWithFever: StreakWithFever) { + val streak = streakWithFever.streak + val removedSnacks = board.removeSnacksIn(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) + + if (removedSnacks.any(Snack::isGolden)) { + this.board = board.reset() + } + } + + private fun increaseScore(earn: Int) { + val multiplier = if (feverTime?.isActive() == true) FEVER_MULTIPLIER else NORMAL_MULTIPLIER + this.score += earn * multiplier + } + override val metadata = SNACK_GAME_BIZ } diff --git a/src/main/java/com/snackgame/server/game/snackgame/biz/domain/SnackgameBizV2.kt b/src/main/java/com/snackgame/server/game/snackgame/biz/domain/SnackgameBizV2.kt index 04012629..146368ab 100644 --- a/src/main/java/com/snackgame/server/game/snackgame/biz/domain/SnackgameBizV2.kt +++ b/src/main/java/com/snackgame/server/game/snackgame/biz/domain/SnackgameBizV2.kt @@ -6,12 +6,17 @@ import com.snackgame.server.game.snackgame.core.domain.Board import com.snackgame.server.game.snackgame.core.domain.BoardConverter import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.DEFAULT_HEIGHT import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.DEFAULT_WIDTH +import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.FEVER_MULTIPLIER +import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.NORMAL_MULTIPLIER import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.SESSION_TIME import com.snackgame.server.game.snackgame.core.domain.Snackgame.Companion.SPARE_TIME import com.snackgame.server.game.snackgame.core.domain.Streak +import com.snackgame.server.game.snackgame.core.domain.item.FeverTime import com.snackgame.server.game.snackgame.core.domain.snack.Snack +import com.snackgame.server.game.snackgame.core.service.dto.StreakWithFever import java.time.Duration import javax.persistence.Convert +import javax.persistence.Embedded import javax.persistence.Entity import javax.persistence.Lob @@ -28,6 +33,10 @@ open class SnackgameBizV2( var board = board private set + @Embedded + var feverTime: FeverTime? = null + private set + fun remove(streak: Streak) { val removedSnacks = board.removeSnacksIn(streak) this.score += removedSnacks.size @@ -36,5 +45,25 @@ open class SnackgameBizV2( } } + fun remove(streakWithFever: StreakWithFever) { + val streak = streakWithFever.streak + val removedSnacks = board.removeSnacksIn(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) + + if (removedSnacks.any(Snack::isGolden)) { + this.board = board.reset() + } + } + + private fun increaseScore(earn: Int) { + val multiplier = if (feverTime?.isActive() == true) FEVER_MULTIPLIER else NORMAL_MULTIPLIER + this.score += earn * multiplier + } + override val metadata = SNACK_GAME_BIZ_V2 } 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 73be78cb..f786cbe4 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 @@ -4,6 +4,7 @@ import com.snackgame.server.game.metadata.Metadata.SNACK_GAME import com.snackgame.server.game.session.domain.Session import com.snackgame.server.game.snackgame.core.domain.item.FeverTime import com.snackgame.server.game.snackgame.core.domain.snack.Snack +import com.snackgame.server.game.snackgame.core.service.dto.StreakWithFever import java.time.Duration import javax.persistence.Convert import javax.persistence.Embedded @@ -32,6 +33,7 @@ open class Snackgame( this.score = score } + //todo : 제거 예정 fun remove(streak: Streak) { val removedSnacks = board.removeSnacksIn(streak) increaseScore(streak.length) @@ -41,6 +43,21 @@ open class Snackgame( } } + fun remove(streakWithFever: StreakWithFever) { + val streak = streakWithFever.streak + val removedSnacks = board.removeSnacksIn(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) + + if (removedSnacks.any(Snack::isGolden)) { + this.board = board.reset() + } + } + fun removeBomb(streak: Streak) { val removedSnacks = board.bombSnacksIn(streak) increaseScore(removedSnacks.size) 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 51671ece..f9ff0133 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,12 +3,29 @@ 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 java.time.LocalDateTime data class StreaksRequest @JsonCreator constructor( - val streaks: List> + val streaks: List ) { + fun toStreaks(now: LocalDateTime = LocalDateTime.now()): List = + streaks.map { it.toDomain(now) } +} - fun toStreaks(): List = streaks.map { streak -> - Streak.of(streak.map { Coordinate(it.y, it.x) }) - } +data class StreakWithMeta( + val coordinates: List, + val isFever: Boolean +) { + fun toDomain(now: LocalDateTime): StreakWithFever = + StreakWithFever( + streak = Streak.of(coordinates.map { Coordinate(it.y, it.x) }), + clientIsFever = isFever, + occurredAt = now + ) } + +data class StreakWithFever( + val streak: Streak, + val clientIsFever: Boolean, + val occurredAt: LocalDateTime +) \ 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 2d2c0d1b..ea02c2c8 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 @@ -2,10 +2,10 @@ package com.snackgame.server.game.snackgame.core.service -import com.snackgame.server.fixture.SeasonFixture import com.snackgame.server.game.snackgame.core.domain.Snackgame import com.snackgame.server.game.snackgame.core.domain.SnackgameRepository import com.snackgame.server.game.snackgame.core.service.dto.CoordinateRequest +import com.snackgame.server.game.snackgame.core.service.dto.StreakWithMeta import com.snackgame.server.game.snackgame.core.service.dto.StreaksRequest import com.snackgame.server.game.snackgame.fixture.BoardFixture import com.snackgame.server.game.snackgame.fixture.ItemFixture @@ -39,7 +39,19 @@ class SnackgameServiceTest { CoordinateRequest(0, 0) ) - snackgameService.removeStreaks(땡칠().id, game.sessionId, StreaksRequest(listOf(coordinates))) + + snackgameService.removeStreaks( + 땡칠().id, + game.sessionId, + StreaksRequest( + listOf( + StreakWithMeta( + coordinates = coordinates, + isFever = false + ) + ) + ) + ) val found = snackgameRepository.findByOwnerIdAndSessionId(땡칠().id, game.sessionId)!! assertThat(found.score).isEqualTo(2) @@ -64,7 +76,19 @@ class SnackgameServiceTest { ) snackgameService.useFeverTime(땡칠().id, game.sessionId) - snackgameService.removeStreaks(땡칠().id, game.sessionId, StreaksRequest(listOf(coordinates))) + + snackgameService.removeStreaks( + 땡칠().id, + game.sessionId, + StreaksRequest( + listOf( + StreakWithMeta( + coordinates = coordinates, + isFever = false + ) + ) + ) + ) val found = snackgameRepository.findByOwnerIdAndSessionId(땡칠().id, game.sessionId)!! assertThat(found.score).isEqualTo(4)