From edb851deac83669d3272bf036d4b4189d8a1ee99 Mon Sep 17 00:00:00 2001 From: wow890209 Date: Sun, 12 Nov 2023 15:59:25 +0800 Subject: [PATCH] refactoryFulfillMissionsUsecase --- .../activity/domain/Activity.kt | 8 +- .../listeners/JoinActivityListener.kt | 10 +- .../utopiagamification/quest/domain/Action.kt | 2 +- .../domain/actions/JoinActivityAction.kt | 6 +- .../domain/actions/MessageReactionAction.kt | 3 +- .../quest/domain/actions/MessageSentAction.kt | 5 +- .../quest/domain/actions/PostAction.kt | 5 +- .../quest/domain/actions/QuizAction.kt | 5 +- .../UtopiagamificationExtensions.kt | 17 ++- .../listeners/ButtonInteractionListener.kt | 3 + .../listeners/MessageReactionListener.kt | 11 +- .../quest/listeners/MessageSentListener.kt | 19 ++- .../quest/listeners/PostListener.kt | 13 +- .../quest/listeners/QuizListener.kt | 10 +- .../quest/listeners/SlashCommandListener.kt | 5 +- .../listeners/UtopiaGamificationListener.kt | 24 ---- .../PlayerFulfillMissionPresenter.kt | 20 +++ .../usecase/PlayerFulfillMissionsUsecase.kt | 6 +- .../it/PlayerFulfillMissionUsecaseTest.kt | 60 ++++++++ .../MissionTestInvocationContextProvider.kt | 73 +++++++--- .../utopiagamification/quest/ut/PlayerTest.kt | 18 +++ .../quest/ut/TestQuestRepository.kt | 136 ++++++++++++++++++ .../quest/ut/UtopiaGamificationQuestTest.kt | 16 +-- 23 files changed, 379 insertions(+), 96 deletions(-) create mode 100644 utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/presenters/PlayerFulfillMissionPresenter.kt create mode 100644 utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/it/PlayerFulfillMissionUsecaseTest.kt create mode 100644 utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/PlayerTest.kt create mode 100644 utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/TestQuestRepository.kt diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/activity/domain/Activity.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/activity/domain/Activity.kt index 4b598280..abb2ac7a 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/activity/domain/Activity.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/activity/domain/Activity.kt @@ -32,14 +32,14 @@ class Activity( private fun Player.toAudience(): Audience = Audience(id) - fun leave(player: Player): JoinActivityAction? { - val audience = audiences[player.id] ?: return null + fun leave(playerId: String): JoinActivityAction? { + val audience = audiences[playerId] ?: return null val stayDuration = audience.leave() - log.info(""" [leave activity] { "userId" = "${player.id}", "activityName" = $eventName, "stayDuration" = "$stayDuration"} """) + log.info(""" [leave activity] { "userId" = "$playerId", "activityName" = $eventName, "stayDuration" = "$stayDuration"} """) return JoinActivityAction( - player, + playerId, eventName, audiences.size, stayDuration.toMinutes().toInt() diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/activity/listeners/JoinActivityListener.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/activity/listeners/JoinActivityListener.kt index 4c38e649..eccdfaa0 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/activity/listeners/JoinActivityListener.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/activity/listeners/JoinActivityListener.kt @@ -11,11 +11,13 @@ import org.springframework.stereotype.Component import tw.waterballsa.utopia.utopiagamification.activity.domain.Activity import tw.waterballsa.utopia.utopiagamification.activity.domain.Activity.State.* import tw.waterballsa.utopia.utopiagamification.activity.extensions.DateTimeRange +import tw.waterballsa.utopia.utopiagamification.quest.extensions.publishToUser import tw.waterballsa.utopia.utopiagamification.quest.extensions.toTaipeiLocalDateTime import tw.waterballsa.utopia.utopiagamification.quest.listeners.UtopiaGamificationListener +import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.PlayerFulfillMissionPresenter +import tw.waterballsa.utopia.utopiagamification.quest.usecase.PlayerFulfillMissionsUsecase import tw.waterballsa.utopia.utopiagamification.repositories.ActivityRepository import tw.waterballsa.utopia.utopiagamification.repositories.PlayerRepository -import tw.waterballsa.utopia.utopiagamification.quest.usecase.PlayerFulfillMissionsUsecase import java.time.LocalDateTime.now private val log = KotlinLogging.logger {} @@ -41,9 +43,11 @@ class EventJoiningListener( channelLeft?.let { val stayActivity = activityRepository.findAudienceStayActivity(it.id, player.id) ?: return@let - val action = stayActivity.leave(player) ?: return - playerFulfillMissionsUsecase.execute(action, user.claimMissionRewardPresenter) + val action = stayActivity.leave(user.id) ?: return + val presenter = PlayerFulfillMissionPresenter() + playerFulfillMissionsUsecase.execute(action, presenter) activityRepository.save(stayActivity) + presenter.viewModel?.publishToUser(user) } } } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/Action.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/Action.kt index 47c817c5..7a8637c4 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/Action.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/Action.kt @@ -1,7 +1,7 @@ package tw.waterballsa.utopia.utopiagamification.quest.domain abstract class Action( - val player: Player + val playerId: String ) { abstract fun match(criteria: Criteria): Boolean diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/JoinActivityAction.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/JoinActivityAction.kt index fd910431..d5197893 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/JoinActivityAction.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/JoinActivityAction.kt @@ -1,14 +1,14 @@ package tw.waterballsa.utopia.utopiagamification.quest.domain.actions import tw.waterballsa.utopia.utopiagamification.quest.domain.Action -import tw.waterballsa.utopia.utopiagamification.quest.domain.Player +// TODO join是參加的意思,不是家入的意思,join 容易被誤會成加入的意思,應該要換成其他英文字 class JoinActivityAction( - player: Player, + playerId: String, val eventName: String, val maxMemberCount: Int, val stayDuration: Int, -) : Action(player) { +) : Action(playerId) { override fun match(criteria: Criteria): Boolean = criteria is JoinActivityCriteria } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/MessageReactionAction.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/MessageReactionAction.kt index 49dfc33e..bcb31021 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/MessageReactionAction.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/MessageReactionAction.kt @@ -1,10 +1,9 @@ package tw.waterballsa.utopia.utopiagamification.quest.domain.actions import tw.waterballsa.utopia.utopiagamification.quest.domain.Action -import tw.waterballsa.utopia.utopiagamification.quest.domain.Player class MessageReactionAction( - player: Player, + player: String, val messageId: String, val emoji: String ) : Action(player) { diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/MessageSentAction.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/MessageSentAction.kt index 3633b90f..a38d617b 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/MessageSentAction.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/MessageSentAction.kt @@ -1,17 +1,16 @@ package tw.waterballsa.utopia.utopiagamification.quest.domain.actions import tw.waterballsa.utopia.utopiagamification.quest.domain.Action -import tw.waterballsa.utopia.utopiagamification.quest.domain.Player class MessageSentAction( - player: Player, + playerId: String, val channelId: String, val context: String, val hasReplied: Boolean, val hasImage: Boolean, val numberOfVoiceChannelMembers: Int, -) : Action(player) { +) : Action(playerId) { override fun match(criteria: Criteria): Boolean = criteria is MessageSentCriteria } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/PostAction.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/PostAction.kt index 4bec30a7..3b540b06 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/PostAction.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/PostAction.kt @@ -1,12 +1,11 @@ package tw.waterballsa.utopia.utopiagamification.quest.domain.actions import tw.waterballsa.utopia.utopiagamification.quest.domain.Action -import tw.waterballsa.utopia.utopiagamification.quest.domain.Player class PostAction( - player: Player, + playerId: String, val channelId: String -) : Action(player) { +) : Action(playerId) { override fun match(criteria: Criteria): Boolean = criteria is PostCriteria } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/QuizAction.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/QuizAction.kt index f32617a5..b8004d6b 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/QuizAction.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/domain/actions/QuizAction.kt @@ -2,15 +2,14 @@ package tw.waterballsa.utopia.utopiagamification.quest.domain.actions import mu.KotlinLogging import tw.waterballsa.utopia.utopiagamification.quest.domain.Action -import tw.waterballsa.utopia.utopiagamification.quest.domain.Player private val log = KotlinLogging.logger {} class QuizAction( - player: Player, + playerId: String, val quizName: String, val correctCount: Int -) : Action(player) { +) : Action(playerId) { override fun match(criteria: Criteria): Boolean = criteria is QuizCriteria } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/extensions/UtopiagamificationExtensions.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/extensions/UtopiagamificationExtensions.kt index 657473a6..9ba80e14 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/extensions/UtopiagamificationExtensions.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/extensions/UtopiagamificationExtensions.kt @@ -2,7 +2,9 @@ package tw.waterballsa.utopia.utopiagamification.quest.extensions import dev.minn.jda.ktx.messages.Embed import net.dv8tion.jda.api.entities.User +import tw.waterballsa.utopia.utopiagamification.quest.listeners.RewardButton import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.AssignPlayerQuestPresenter +import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.PlayerFulfillMissionPresenter import java.time.LocalDateTime import java.time.OffsetDateTime import java.time.ZoneId @@ -12,6 +14,12 @@ fun String.toDate(): LocalDateTime = LocalDateTime.parse(this) fun OffsetDateTime.toTaipeiLocalDateTime(): LocalDateTime = atZoneSameInstant(ZoneId.of("Asia/Taipei")).toLocalDateTime() +class Color { + companion object { + const val GREEN = 706146 + } +} + fun AssignPlayerQuestPresenter.ViewModel.publishToUser(user: User) { user.openPrivateChannel().queue { it.sendMessageEmbeds( @@ -35,9 +43,10 @@ fun AssignPlayerQuestPresenter.ViewModel.publishToUser(user: User) { } } - -class Color { - companion object { - const val GREEN = 706146 +fun PlayerFulfillMissionPresenter.ViewModel.publishToUser(user: User) { + user.openPrivateChannel().queue { + it.sendMessage(postMessage) + .addActionRow(RewardButton.toJdaButton(questId)) + .queue() } } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/ButtonInteractionListener.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/ButtonInteractionListener.kt index 6bda7e5d..2542d336 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/ButtonInteractionListener.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/ButtonInteractionListener.kt @@ -3,6 +3,7 @@ package tw.waterballsa.utopia.utopiagamification.quest.listeners import dev.minn.jda.ktx.interactions.components.button import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent +import net.dv8tion.jda.api.interactions.components.buttons.Button import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle import org.springframework.stereotype.Component import tw.waterballsa.utopia.utopiagamification.quest.extensions.publishToUser @@ -20,6 +21,8 @@ class RewardButton { const val LABEL: String = "領取獎勵" fun id(questId: Int): String = "$BUTTON_QUEST_TAG-$NAME-$questId" + + fun toJdaButton(questId: Int): Button = button(id(questId), LABEL) } } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/MessageReactionListener.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/MessageReactionListener.kt index a5e646b6..3f9db767 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/MessageReactionListener.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/MessageReactionListener.kt @@ -4,6 +4,8 @@ import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent import org.springframework.stereotype.Component import tw.waterballsa.utopia.utopiagamification.quest.domain.actions.MessageReactionAction +import tw.waterballsa.utopia.utopiagamification.quest.extensions.publishToUser +import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.PlayerFulfillMissionPresenter import tw.waterballsa.utopia.utopiagamification.quest.usecase.PlayerFulfillMissionsUsecase import tw.waterballsa.utopia.utopiagamification.repositories.PlayerRepository @@ -16,16 +18,21 @@ class MessageReactionListener( override fun onMessageReactionAdd(event: MessageReactionAddEvent) { with(event) { + //TODO 這個 toPlayer 會有副作用,會註冊玩家,之後會發 pr 解決這個問題 val user = user ?: return val player = user.toPlayer() ?: return val action = MessageReactionAction( - player, + user.id, messageId, emoji.name ) - playerFulfillMissionsUsecase.execute(action, user.claimMissionRewardPresenter) + val presenter = PlayerFulfillMissionPresenter() + + playerFulfillMissionsUsecase.execute(action, presenter) + + presenter.viewModel?.publishToUser(user) } } } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/MessageSentListener.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/MessageSentListener.kt index 6d5a9c82..188b8c12 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/MessageSentListener.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/MessageSentListener.kt @@ -7,6 +7,8 @@ import net.dv8tion.jda.api.events.message.MessageReceivedEvent import net.dv8tion.jda.api.events.message.MessageUpdateEvent import org.springframework.stereotype.Component import tw.waterballsa.utopia.utopiagamification.quest.domain.actions.MessageSentAction +import tw.waterballsa.utopia.utopiagamification.quest.extensions.publishToUser +import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.PlayerFulfillMissionPresenter import tw.waterballsa.utopia.utopiagamification.quest.usecase.PlayerFulfillMissionsUsecase import tw.waterballsa.utopia.utopiagamification.repositories.PlayerRepository @@ -23,19 +25,23 @@ class MessageSentListener( return } + //TODO 這個 toPlayer 會有副作用,會註冊玩家,之後會發 pr 解決這個問題 val user = author val player = user.toPlayer() ?: return val action = MessageSentAction( - player, + user.id, (channel as? ThreadChannel)?.parentChannel?.id ?: channel.id, message.contentDisplay, message.referencedMessage != null, message.attachments.any { it.isImage }, (channel as? VoiceChannel)?.members?.size ?: 0 ) + val presenter = PlayerFulfillMissionPresenter() - playerFulfillMissionsUsecase.execute(action, user.claimMissionRewardPresenter) + playerFulfillMissionsUsecase.execute(action, presenter) + + presenter.viewModel?.publishToUser(user) } } @@ -45,11 +51,12 @@ class MessageSentListener( return } + //TODO 這個 toPlayer 會有副作用,會註冊玩家,之後會發 pr 解決這個問題 val user = author val player = user.toPlayer() ?: return val action = MessageSentAction( - player, + user.id, (channel as? ThreadChannel)?.parentChannel?.id ?: channel.id, message.contentDisplay, message.referencedMessage != null, @@ -57,7 +64,11 @@ class MessageSentListener( (channel as? VoiceChannel)?.members?.size ?: 0 ) - playerFulfillMissionsUsecase.execute(action, user.claimMissionRewardPresenter) + val presenter = PlayerFulfillMissionPresenter() + + playerFulfillMissionsUsecase.execute(action, presenter) + + presenter.viewModel?.publishToUser(user) } } } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/PostListener.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/PostListener.kt index 2ab52fcd..ff15baab 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/PostListener.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/PostListener.kt @@ -4,6 +4,8 @@ import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent import org.springframework.stereotype.Component import tw.waterballsa.utopia.utopiagamification.quest.domain.actions.PostAction +import tw.waterballsa.utopia.utopiagamification.quest.extensions.publishToUser +import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.PlayerFulfillMissionPresenter import tw.waterballsa.utopia.utopiagamification.quest.usecase.PlayerFulfillMissionsUsecase import tw.waterballsa.utopia.utopiagamification.repositories.PlayerRepository @@ -16,16 +18,21 @@ class PostListener( override fun onGuildAuditLogEntryCreate(event: GuildAuditLogEntryCreateEvent) { with(event) { + //TODO 這個 toPlayer 會有副作用,會註冊玩家,之後會發 pr 解決這個問題 val user = user ?: return - val channel = guild.getThreadChannelById(entry.targetId)?.parentChannel ?: return val player = user.toPlayer() ?: return + val channel = guild.getThreadChannelById(entry.targetId)?.parentChannel ?: return val action = PostAction( - player, + user.id, channel.id ) - playerFulfillMissionsUsecase.execute(action, user.claimMissionRewardPresenter) + val presenter = PlayerFulfillMissionPresenter() + + playerFulfillMissionsUsecase.execute(action, presenter) + + presenter.viewModel?.publishToUser(user) } } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/QuizListener.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/QuizListener.kt index 3d4d60b8..36bea0ff 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/QuizListener.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/QuizListener.kt @@ -9,6 +9,8 @@ import tw.waterballsa.utopia.jda.domains.QuizPreparationStartEvent import tw.waterballsa.utopia.jda.domains.UtopiaEvent import tw.waterballsa.utopia.utopiagamification.quest.domain.Quest import tw.waterballsa.utopia.utopiagamification.quest.domain.actions.QuizAction +import tw.waterballsa.utopia.utopiagamification.quest.extensions.publishToUser +import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.PlayerFulfillMissionPresenter import tw.waterballsa.utopia.utopiagamification.quest.usecase.PlayerFulfillMissionsUsecase import tw.waterballsa.utopia.utopiagamification.repositories.MissionRepository import tw.waterballsa.utopia.utopiagamification.repositories.PlayerRepository @@ -60,18 +62,22 @@ class QuizListener( private fun onQuizEnd(event: QuizEndEvent) { with(event) { + //TODO 這個 toPlayer 會有副作用,會註冊玩家,之後會發 pr 解決這個問題 val user = jda.retrieveUserById(quizTakerId).complete() ?: return val player = user.toPlayer() ?: return val action = QuizAction( - player, + user.id, quizName, correctCount ) + val presenter = PlayerFulfillMissionPresenter() log.info { """[quiz end] { quizTakerId : "$quizTakerId", quizName : "$quizName", correctCount : "$correctCount" } """ } - playerFulfillMissionsUsecase.execute(action, user.claimMissionRewardPresenter) + playerFulfillMissionsUsecase.execute(action, presenter) + + presenter.viewModel?.publishToUser(user) } } } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/SlashCommandListener.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/SlashCommandListener.kt index 3ee2b98c..201dae55 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/SlashCommandListener.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/SlashCommandListener.kt @@ -9,6 +9,7 @@ import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Com import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.unlockAcademyQuestId import tw.waterballsa.utopia.utopiagamification.quest.extensions.publishToUser import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.AssignPlayerQuestPresenter +import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.PlayerFulfillMissionPresenter import tw.waterballsa.utopia.utopiagamification.quest.usecase.AssignPlayerQuestUsecase import tw.waterballsa.utopia.utopiagamification.repositories.MissionRepository import tw.waterballsa.utopia.utopiagamification.repositories.PlayerRepository @@ -68,7 +69,9 @@ class SlashCommandListener( with(mission) { if (state == COMPLETED) { - user.claimMissionRewardPresenter.presentClaimMissionReward(mission) + val presenter = PlayerFulfillMissionPresenter() + presenter.present(mission) + presenter.viewModel?.publishToUser(user) } if (state == IN_PROGRESS) { diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/UtopiaGamificationListener.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/UtopiaGamificationListener.kt index 6a1d2f34..1736195d 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/UtopiaGamificationListener.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/UtopiaGamificationListener.kt @@ -1,14 +1,10 @@ package tw.waterballsa.utopia.utopiagamification.quest.listeners -import dev.minn.jda.ktx.interactions.components.button import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.entities.Member import net.dv8tion.jda.api.entities.User -import net.dv8tion.jda.api.interactions.components.buttons.Button import tw.waterballsa.utopia.jda.UtopiaListener -import tw.waterballsa.utopia.utopiagamification.quest.domain.Mission import tw.waterballsa.utopia.utopiagamification.quest.domain.Player -import tw.waterballsa.utopia.utopiagamification.quest.usecase.PlayerFulfillMissionsUsecase import tw.waterballsa.utopia.utopiagamification.repositories.PlayerRepository open class UtopiaGamificationListener( @@ -37,24 +33,4 @@ open class UtopiaGamificationListener( jdaRoles.addAll(member.roles.map { it.id }.toMutableList()) return this } - - protected val User.claimMissionRewardPresenter - get() = object : PlayerFulfillMissionsUsecase.Presenter { - override fun presentClaimMissionReward(mission: Mission) { - openPrivateChannel().queue { - it.sendMessage(mission.postMessage) - .addActionRow(mission.rewardButton) - .queue() - } - } - } - - private val Mission.postMessage - get() = quest.postMessage - - val Mission.rewardButton: Button - get() = button( - RewardButton.id(quest.id), - RewardButton.LABEL - ) } diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/presenters/PlayerFulfillMissionPresenter.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/presenters/PlayerFulfillMissionPresenter.kt new file mode 100644 index 00000000..0ad99cce --- /dev/null +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/listeners/presenters/PlayerFulfillMissionPresenter.kt @@ -0,0 +1,20 @@ +package tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters + +import tw.waterballsa.utopia.utopiagamification.quest.domain.Mission +import tw.waterballsa.utopia.utopiagamification.quest.usecase.PlayerFulfillMissionsUsecase + + +class PlayerFulfillMissionPresenter : PlayerFulfillMissionsUsecase.Presenter { + + var viewModel: ViewModel? = null + private set + + override fun present(mission: Mission) { + viewModel = ViewModel(mission.quest.postMessage, mission.quest.id) + } + + class ViewModel( + val postMessage: String, + val questId: Int + ) +} diff --git a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/usecase/PlayerFulfillMissionsUsecase.kt b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/usecase/PlayerFulfillMissionsUsecase.kt index f34f8b0a..73b5068f 100644 --- a/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/usecase/PlayerFulfillMissionsUsecase.kt +++ b/utopia-gamification/src/main/kotlin/tw/waterballsa/utopia/utopiagamification/quest/usecase/PlayerFulfillMissionsUsecase.kt @@ -12,7 +12,7 @@ class PlayerFulfillMissionsUsecase( fun execute(action: Action, presenter: Presenter) { with(action) { - val missions = missionRepository.findInProgressMissionsByPlayerId(player.id) + val missions = missionRepository.findInProgressMissionsByPlayerId(playerId) fulfillMissions(missions, presenter) } @@ -24,11 +24,11 @@ class PlayerFulfillMissionsUsecase( .filter { mission -> mission.isCompleted() } .onEach { mission -> missionRepository.saveMission(mission) - presenter.presentClaimMissionReward(mission) + presenter.present(mission) } } interface Presenter { - fun presentClaimMissionReward(mission: Mission) + fun present(mission: Mission) } } diff --git a/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/it/PlayerFulfillMissionUsecaseTest.kt b/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/it/PlayerFulfillMissionUsecaseTest.kt new file mode 100644 index 00000000..fcbeaff7 --- /dev/null +++ b/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/it/PlayerFulfillMissionUsecaseTest.kt @@ -0,0 +1,60 @@ +package tw.waterballsa.utopia.utopiagamification.quest.it + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.TestTemplate +import org.junit.jupiter.api.extension.ExtendWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Primary +import tw.waterballsa.utopia.utopiagamification.quest.domain.Mission +import tw.waterballsa.utopia.utopiagamification.quest.domain.Player +import tw.waterballsa.utopia.utopiagamification.quest.domain.Quest +import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.PlayerFulfillMissionPresenter +import tw.waterballsa.utopia.utopiagamification.quest.usecase.PlayerFulfillMissionsUsecase +import tw.waterballsa.utopia.utopiagamification.quest.ut.MissionTestCase +import tw.waterballsa.utopia.utopiagamification.quest.ut.MissionTestInvocationContextProvider +import tw.waterballsa.utopia.utopiagamification.quest.ut.TestQuestRepository +import tw.waterballsa.utopia.utopiagamification.repositories.MissionRepository +import tw.waterballsa.utopia.utopiagamification.repositories.PlayerRepository +import tw.waterballsa.utopia.utopiagamification.repositories.QuestRepository +import tw.waterballsa.utopia.utopiatestkit.annotations.UtopiaTest + +@Configuration +open class MockBeanConfig { + + @Primary + @Bean + open fun questRepository(): QuestRepository { + return TestQuestRepository() + } +} + +@UtopiaTest +class PlayerFulfillMissionUsecaseTest @Autowired constructor( + private val missionRepository: MissionRepository, + private val playerFulfillMissionsUsecase: PlayerFulfillMissionsUsecase, + private val playerRepository: PlayerRepository +) { + + @TestTemplate + @ExtendWith(MissionTestInvocationContextProvider::class) + fun `test player fulfill mission`(missionTestCase: MissionTestCase) { + with(missionTestCase) { + player.acceptQuest(quest) + val presenter = PlayerFulfillMissionPresenter() + + playerFulfillMissionsUsecase.execute(action, presenter) + + val mission = missionRepository.findPlayerMissionByQuestId(player.id, quest.id) + + Assertions.assertThat(mission).isNotNull + Assertions.assertThat(mission?.isCompleted()).isEqualTo(isMissionCompleted) + } + } + + private fun Player.acceptQuest(quest: Quest) { + playerRepository.savePlayer(this) + missionRepository.saveMission(Mission(this, quest)) + } +} diff --git a/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/MissionTestInvocationContextProvider.kt b/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/MissionTestInvocationContextProvider.kt index 0a8c21aa..a61e0ff3 100644 --- a/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/MissionTestInvocationContextProvider.kt +++ b/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/MissionTestInvocationContextProvider.kt @@ -37,7 +37,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid reward = Reward(100u, 100u, 1.0f), criteria = QuizCriteria("紳士考題", 4, 5) ), - QuizAction(player, "紳士考題", 5), + QuizAction(player.id, "紳士考題", 5), isMatchAction = true, isMissionCompleted = true ), @@ -55,7 +55,43 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid reward = Reward(100u, 100u, 1.0f), criteria = QuizCriteria("紳士考題", 4, 5), ), - QuizAction(player, "紳士考題", 0), + QuizAction(player.id, "紳士考題", 0), + isMatchAction = true, + isMissionCompleted = false + ), + + MissionTestCase( + """ + given player accept mission '參與院長主持的學院節目', + when player was stay ten min, + then mission should be completed""".trimIndent(), + player, + quest = Quest( + id = 9, + title = "參與院長主持的學院節目", + description = "", + reward = Reward(100u, 100u, 1.0f), + criteria = JoinActivityCriteria("遊戲微服務計畫:水球實況", 1, 5) + ), + JoinActivityAction(player.id, "遊戲微服務計畫:水球實況", 1, 10), + isMatchAction = true, + isMissionCompleted = true + ), + + MissionTestCase( + """ + given player accept mission '參與院長主持的學院節目', + when player was stay two min, + then mission should be failed""".trimIndent(), + player, + quest = Quest( + id = 9, + title = "參與院長主持的學院節目", + description = "", + reward = Reward(100u, 100u, 1.0f), + criteria = JoinActivityCriteria("遊戲微服務計畫:水球實況", 1, 5) + ), + JoinActivityAction(player.id, "遊戲微服務計畫:水球實況", 1, 2), isMatchAction = true, isMissionCompleted = false ), @@ -77,7 +113,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid ) ), MessageSentAction( - player, + player.id, "eatWatermelonEveryWhere", "hello watermelon", hasReplied = false, @@ -105,7 +141,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid ) ), MessageSentAction( - player, + player.id, "test", "", hasReplied = false, @@ -130,7 +166,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid criteria = PostCriteria(ChannelIdRule("flagPostChannelId")) ), PostAction( - player, + player.id, "flagPostChannelId", ), isMatchAction = true, @@ -151,7 +187,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid criteria = PostCriteria(ChannelIdRule("flagPostChannelId")) ), PostAction( - player, + player.id, "featuredVideosChannelId", ), isMatchAction = true, @@ -172,7 +208,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid criteria = MessageSentCriteria(ChannelIdRule("featuredVideosChannelId")) ), MessageSentAction( - player, + player.id, "featuredVideosChannelId", "good video", hasReplied = false, @@ -197,7 +233,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid criteria = MessageSentCriteria(ChannelIdRule("featuredVideosChannelId")) ), MessageSentAction( - player, + player.id, "flagPostChannelId", "good video", hasReplied = false, @@ -225,7 +261,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid ) ), MessageSentAction( - player, + player.id, "careerAdvancementTopicChannelId", "I want to go to good company", hasReplied = true, @@ -254,7 +290,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid ) ), MessageSentAction( - player, + player.id, "careerAdvancementTopicChannelId", "I want to go to good company", hasReplied = false, @@ -283,7 +319,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid ) ), MessageSentAction( - player, + player.id, "engineerLifeChannelId", "I believe I can fly", hasReplied = false, @@ -311,7 +347,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid ) ), MessageSentAction( - player, + player.id, "engineerLifeChannelId", "I believe I can fly", hasReplied = false, @@ -336,7 +372,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid criteria = MessageSentCriteria(ChannelIdRule("discussionAreaChannelId")) ), MessageSentAction( - player, + player.id, "discussionAreaChannelId", "I am waterBall bot", hasReplied = false, @@ -361,7 +397,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid criteria = MessageSentCriteria(ChannelIdRule("discussionAreaChannelId")) ), MessageSentAction( - player, + player.id, "careerAdvancementTopicChannelId", "I am waterBall bot", hasReplied = true, @@ -388,7 +424,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid regexRule = """【(.|\n)*】(.|\n)*工作職位:?(.|\n)*((公司產業:?(:)?(.|\n)*))?專長:?(.|\n)*興趣:?(.|\n)*簡介:?.(.|\n)*((三件關於我的事,猜猜哪一件是假的:?(:)?(.|\n)*))?""".toRegexRule() ) ), MessageSentAction( - player, + player.id, "selfIntroChannelId", """三件關於我的事,猜猜哪一件是假的:""", hasReplied = false, @@ -415,7 +451,8 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid regexRule = """【(.|\n)*】(.|\n)*工作職位:?(.|\n)*((公司產業:?(:)?(.|\n)*))?專長:?(.|\n)*興趣:?(.|\n)*簡介:?.(.|\n)*((三件關於我的事,猜猜哪一件是假的:?(:)?(.|\n)*))?""".toRegexRule() ) ), MessageSentAction( - player, "selfIntroChannelId", """ + player.id, + "selfIntroChannelId", """ 【 playerA 】 工作職位: <工作職位> 公司產業: <工作所在公司的產業類型> @@ -453,7 +490,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid ) ), MessageReactionAction( - player, + player.id, "unlockEntryMessageId", "🍒" ), @@ -479,7 +516,7 @@ class MissionTestInvocationContextProvider : TestTemplateInvocationContextProvid ) ), MessageReactionAction( - player, + player.id, "unlockEntryMessageId", "🔑" ), diff --git a/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/PlayerTest.kt b/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/PlayerTest.kt new file mode 100644 index 00000000..2efbba6b --- /dev/null +++ b/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/PlayerTest.kt @@ -0,0 +1,18 @@ +package tw.waterballsa.utopia.utopiagamification.quest.ut + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import tw.waterballsa.utopia.utopiagamification.quest.domain.Player + +class PlayerTest { + + @Test + fun `given playerA level 3 and exp 650, when player gain 6000 exp, then level is 11 and exp is 6650`() { + val player = Player("A", "A", 650u, 3u) + val rewardExp = 6000uL + player.gainExp(rewardExp) + + Assertions.assertThat(player.exp).isEqualTo(6650uL) + Assertions.assertThat(player.level).isEqualTo(11u) + } +} diff --git a/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/TestQuestRepository.kt b/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/TestQuestRepository.kt new file mode 100644 index 00000000..deadb62e --- /dev/null +++ b/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/TestQuestRepository.kt @@ -0,0 +1,136 @@ +package tw.waterballsa.utopia.utopiagamification.quest.ut + +import tw.waterballsa.utopia.utopiagamification.quest.domain.* +import tw.waterballsa.utopia.utopiagamification.quest.domain.actions.* +import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.toRegexRule +import tw.waterballsa.utopia.utopiagamification.repositories.QuestRepository + +class TestQuestRepository : QuestRepository { + private val quests = mutableListOf( + Quest( + id = 1, + title = "解鎖學院", + description = "", + preCondition = EmptyPreCondition(), + roleType = RoleType.EVERYONE, + periodType = PeriodType.MAIN_QUEST, + reward = Reward(100u, 100u, 1.0f, RoleType.WSA_MEMBER), + criteria = MessageReactionCriteria( + ChannelIdRule("unlockEntryChannelId"), + "unlockEntryMessageId", + "🔑" + ) + ), + Quest( + id = 2, + title = "自我介紹", + description = "", + reward = Reward(100u, 100u, 1.0f), + preCondition = QuestIdPreCondition(1), + roleType = RoleType.WSA_MEMBER, + periodType = PeriodType.MAIN_QUEST, + criteria = MessageSentCriteria( + ChannelIdRule("selfIntroChannelId"), + regexRule = """【(.|\n)*】(.|\n)*工作職位:?(.|\n)*((公司產業:?(:)?(.|\n)*))?專長:?(.|\n)*興趣:?(.|\n)*簡介:?.(.|\n)*((三件關於我的事,猜猜哪一件是假的:?(:)?(.|\n)*))?""".toRegexRule() + ) + ), + Quest( + id = 3, + title = "新生降落", + description = "", + preCondition = QuestIdPreCondition(2), + roleType = RoleType.WSA_MEMBER, + periodType = PeriodType.MAIN_QUEST, + reward = Reward(100u, 100u, 1.0f), + criteria = MessageSentCriteria(ChannelIdRule("discussionAreaChannelId")) + ), + Quest( + id = 4, + title = "融入大家", + description = "這是一個PO照片任務", + preCondition = QuestIdPreCondition(3), + roleType = RoleType.WSA_MEMBER, + periodType = PeriodType.MAIN_QUEST, + reward = Reward(100u, 100u, 1.0f), + criteria = MessageSentCriteria( + ChannelIdRule("engineerLifeChannelId"), + hasImageRule = BooleanRule.TRUE + ) + ), + Quest( + id = 5, + title = "職涯攻略", + description = "", + preCondition = QuestIdPreCondition(4), + roleType = RoleType.WSA_MEMBER, + periodType = PeriodType.MAIN_QUEST, + reward = Reward(100u, 100u, 1.0f), + criteria = + MessageSentCriteria( + ChannelIdRule("careerAdvancementTopicChannelId"), + hasRepliedRule = BooleanRule.TRUE + ) + ), + Quest( + id = 6, + title = "學院精華影片", + description = "", + preCondition = QuestIdPreCondition(5), + roleType = RoleType.WSA_MEMBER, + periodType = PeriodType.MAIN_QUEST, + reward = Reward(100u, 100u, 1.0f), + criteria = MessageSentCriteria(ChannelIdRule("featuredVideosChannelId")) + ), + Quest( + id = 7, + title = "全民插旗:把學院當成自己的家", + description = "", + preCondition = QuestIdPreCondition(6), + roleType = RoleType.WSA_MEMBER, + periodType = PeriodType.MAIN_QUEST, + reward = Reward(100u, 100u, 1.0f), + criteria = PostCriteria(ChannelIdRule("flagPostChannelId")) + ), + Quest( + id = 8, + title = "到處吃瓜", + description = "", + reward = Reward(100u, 100u, 1.0f), + preCondition = QuestIdPreCondition(7), + roleType = RoleType.WSA_MEMBER, + periodType = PeriodType.MAIN_QUEST, + criteria = MessageSentCriteria( + ChannelIdRule.ANY_CHANNEL, + numberOfVoiceChannelMembersRule = AtLeastRule(2) + ) + ), + Quest( + id = 9, + title = "參與院長主持的學院節目", + description = "", + reward = Reward(100u, 100u, 1.0f), + criteria = JoinActivityCriteria("遊戲微服務計畫:水球實況", 1, 5) + ), + Quest( + id = 10, + title = "考試", + description = "", + preCondition = QuestIdPreCondition(8), + roleType = RoleType.WSA_MEMBER, + periodType = PeriodType.MAIN_QUEST, + reward = Reward(100u, 100u, 1.0f), + criteria = QuizCriteria("紳士考題", 4, 5), + ), + ) + + override fun findById(id: Int): Quest? { + return quests.find { it.id == id } + } + + override fun save(quest: Quest): Quest { + quests.add(quest) + return quest + } +} + + diff --git a/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/UtopiaGamificationQuestTest.kt b/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/UtopiaGamificationQuestTest.kt index d90ce5bd..f9a9a055 100644 --- a/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/UtopiaGamificationQuestTest.kt +++ b/utopia-gamification/src/test/kotlin/tw/waterballsa/utopia/utopiagamification/quest/ut/UtopiaGamificationQuestTest.kt @@ -56,10 +56,10 @@ class UtopiaGamificationQuestTest { val activityMission = playerA.acceptQuest(quest) activity.join(playerA) - val leaveActivityAction = activity.leave(playerA)!! + val leaveActivityAction = activity.leave(playerA.id)!! activityMission.carryOut(leaveActivityAction) - assertEquals(playerA.id, leaveActivityAction.player.id) + assertEquals(playerA.id, leaveActivityAction.playerId) assertEquals(activity.eventName, leaveActivityAction.eventName) assertTrue(activityMission.isCompleted()) } @@ -69,21 +69,11 @@ class UtopiaGamificationQuestTest { fun `given player accept mission, when player didn't join activity, then mission should be failed`() { val activityMission = playerA.acceptQuest(quest) - val leaveActivityAction = activity.leave(playerA) + val leaveActivityAction = activity.leave(playerA.id) assertNull(leaveActivityAction) assertFalse(activityMission.isCompleted()) } - @Test - fun `given playerA level 3 and exp 650, when player gain 6000 exp, then level is 11 and exp is 6650`() { - val player = Player("A", "A", 650u, 3u) - val rewardExp = 6000uL - player.gainExp(rewardExp) - - assertThat(player.exp).isEqualTo(6650uL) - assertThat(player.level).isEqualTo(11u) - } - private fun Player.acceptQuest(quest: Quest) = Mission(this, quest) }