From 363bb0400ce8bf81ee7d97095f3f8b17771db45c Mon Sep 17 00:00:00 2001 From: hwanvely <990706leo@gmail.com> Date: Mon, 25 Aug 2025 06:09:35 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=ED=94=BC=EB=B2=84=ED=83=80=EC=9E=84?= =?UTF-8?q?=20=EA=B2=80=EC=A6=9D=20=EC=8B=9C=20=EC=A0=90=EC=88=98=EA=B0=80?= =?UTF-8?q?=20=EB=91=90=EB=B0=B0=EA=B0=80=20=EB=90=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../game/snackgame/core/domain/Snackgame.kt | 17 +++++++++++++ .../core/service/dto/StreaksRequest.kt | 25 ++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) 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 73be78c..f786cbe 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 51671ec..f9ff013 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 From a76212d10fc29f1e0b413320325e8167669c3108 Mon Sep 17 00:00:00 2001 From: hwanvely <990706leo@gmail.com> Date: Mon, 25 Aug 2025 06:19:20 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=20refactor:=20=EB=B0=94=EB=80=90=20dto?= =?UTF-8?q?=EC=97=90=20=EB=A7=9E=EA=B2=8C=20BIZ=20=EB=B0=8F=20test=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../game/snackgame/biz/domain/SnackgameBiz.kt | 30 +++++++++++++++++++ .../snackgame/biz/domain/SnackgameBizV2.kt | 29 ++++++++++++++++++ .../core/service/SnackgameServiceTest.kt | 30 +++++++++++++++++-- 3 files changed, 86 insertions(+), 3 deletions(-) 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 3ff312d..89ac2fa 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 0401262..146368a 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/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 2d2c0d1..ea02c2c 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)