Skip to content

Commit

Permalink
refactor assignPlayerQuestUsecase and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
wow890209 committed Nov 3, 2023
1 parent 515607d commit dc79d3b
Show file tree
Hide file tree
Showing 18 changed files with 276 additions and 142 deletions.
5 changes: 0 additions & 5 deletions utopia-gamification/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,5 @@
<artifactId>utopia-test-kit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>tw.waterballsa.utopia</groupId>
<artifactId>utopia-test-kit</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package tw.waterballsa.utopia.utopiagamification.quest.domain.exception

class AssignedQuestException(playerId: String, questId: Int) :
RuntimeException("Player already owns this quest. {playerId:$playerId, questId:$questId}")
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,41 @@ package tw.waterballsa.utopia.utopiagamification.quest.domain.quests

import tw.waterballsa.utopia.utopiagamification.quest.domain.*
import tw.waterballsa.utopia.utopiagamification.quest.domain.actions.*
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.firstMessageActionQuestId
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.flagPostQuestId
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.joinActivityQuestId
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.quizQuestId
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.replyToAnyoneInCareerAdvancementTopicChannelQuestId
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.selfIntroductionQuestId
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.sendContainsImageMessageInEngineerLifeChannelQuestId
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.sendMessageInVoiceChannelQuestId
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.unlockAcademyQuestId
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.watchVideoQuestId
import tw.waterballsa.utopia.utopiagamification.repositories.inmemory.repositoryimpl.InMemoryQuestRepository

private const val unlockEmoji = "🔑"
private const val missionTips = "> (要是你怕自己的訊息太突兀,只要在訊息的開頭加上 `#任務`,保證自在。)"

class QuestIds {
companion object {
const val unlockAcademyQuestId = 1
const val selfIntroductionQuestId = 2
const val firstMessageActionQuestId = 3
const val sendContainsImageMessageInEngineerLifeChannelQuestId = 4
const val replyToAnyoneInCareerAdvancementTopicChannelQuestId = 5
const val watchVideoQuestId = 6
const val flagPostQuestId = 7
const val sendMessageInVoiceChannelQuestId = 8
const val joinActivityQuestId = 9
const val quizQuestId = 10
}
}


val InMemoryQuestRepository.unlockAcademyQuest: Quest
get() = findById(1) ?: save(
get() = findById(unlockAcademyQuestId) ?: save(
Quest(
id = 1,
id = unlockAcademyQuestId,
title = "解鎖學院",
description =
"""
Expand Down Expand Up @@ -39,15 +65,15 @@ val InMemoryQuestRepository.unlockAcademyQuest: Quest
RoleType.WSA_MEMBER
),

nextQuestId = 2
nextQuestId = selfIntroductionQuestId
)
)


val InMemoryQuestRepository.selfIntroductionQuest: Quest
get() = findById(2) ?: save(
get() = findById(selfIntroductionQuestId) ?: save(
Quest(
id = 2,
id = selfIntroductionQuestId,
title = "自我介紹",
description =
"""
Expand Down Expand Up @@ -91,7 +117,7 @@ val InMemoryQuestRepository.selfIntroductionQuest: Quest
regexRule = getSelfIntroductionRegex()
),

nextQuestId = 3
nextQuestId = firstMessageActionQuestId
)
)

Expand All @@ -101,9 +127,9 @@ private fun getSelfIntroductionRegex(): RegexRule =
"""【(.|\n)*】(.|\n)*工作職位:?(.|\n)*((公司產業:?(:)?(.|\n)*))?專長:?(.|\n)*興趣:?(.|\n)*簡介:?.(.|\n)*((三件關於我的事,猜猜哪一件是假的:?(:)?(.|\n)*))?""".toRegexRule()

val InMemoryQuestRepository.firstMessageActionQuest: Quest
get() = findById(3) ?: save(
get() = findById(firstMessageActionQuestId) ?: save(
Quest(
id = 3,
id = firstMessageActionQuestId,
title = "新生降落",
description =
"""
Expand Down Expand Up @@ -135,14 +161,14 @@ val InMemoryQuestRepository.firstMessageActionQuest: Quest
ChannelIdRule(wsa.discussionAreaChannelId)
),

nextQuestId = 4
nextQuestId = sendContainsImageMessageInEngineerLifeChannelQuestId
)
)

val InMemoryQuestRepository.sendContainsImageMessageInEngineerLifeChannelQuest: Quest
get() = findById(4) ?: save(
get() = findById(sendContainsImageMessageInEngineerLifeChannelQuestId) ?: save(
Quest(
id = 4,
id = sendContainsImageMessageInEngineerLifeChannelQuestId,
title = "融入大家",
description =
"""
Expand Down Expand Up @@ -173,14 +199,14 @@ val InMemoryQuestRepository.sendContainsImageMessageInEngineerLifeChannelQuest:
hasImageRule = BooleanRule.TRUE
),

nextQuestId = 5
nextQuestId = replyToAnyoneInCareerAdvancementTopicChannelQuestId
)
)

val InMemoryQuestRepository.replyToAnyoneInCareerAdvancementTopicChannelQuest: Quest
get() = findById(5) ?: save(
get() = findById(replyToAnyoneInCareerAdvancementTopicChannelQuestId) ?: save(
Quest(
id = 5,
id = replyToAnyoneInCareerAdvancementTopicChannelQuestId,
title = "職涯攻略",
description =
"""
Expand Down Expand Up @@ -214,14 +240,14 @@ val InMemoryQuestRepository.replyToAnyoneInCareerAdvancementTopicChannelQuest: Q
hasRepliedRule = BooleanRule.TRUE
),

nextQuestId = 6
nextQuestId = watchVideoQuestId
)
)

val InMemoryQuestRepository.watchVideoQuest: Quest
get() = findById(6) ?: save(
get() = findById(watchVideoQuestId) ?: save(
Quest(
id = 6,
id = watchVideoQuestId,
title = "學院精華影片",
description = """
在學會如何自在地和大家聊天交流和參與話題之後,接下來要來帶你好好逛一下這個學院。
Expand Down Expand Up @@ -250,14 +276,14 @@ val InMemoryQuestRepository.watchVideoQuest: Quest
ChannelIdRule(wsa.featuredVideosChannelId),
),

nextQuestId = 7
nextQuestId = flagPostQuestId
)
)

val InMemoryQuestRepository.flagPostQuest: Quest
get() = findById(7) ?: save(
get() = findById(flagPostQuestId) ?: save(
Quest(
id = 7,
id = flagPostQuestId,
title = "全民插旗:把學院當成自己的家",
description =
"""
Expand Down Expand Up @@ -289,14 +315,14 @@ val InMemoryQuestRepository.flagPostQuest: Quest
ChannelIdRule(wsa.flagPostChannelId)
),

nextQuestId = 8
nextQuestId = sendMessageInVoiceChannelQuestId
)
)

val InMemoryQuestRepository.sendMessageInVoiceChannelQuest: Quest
get() = findById(8) ?: save(
get() = findById(sendMessageInVoiceChannelQuestId) ?: save(
Quest(
id = 8,
id = sendMessageInVoiceChannelQuestId,
title = "到處吃瓜",
description =
"""
Expand Down Expand Up @@ -329,14 +355,14 @@ val InMemoryQuestRepository.sendMessageInVoiceChannelQuest: Quest
numberOfVoiceChannelMembersRule = AtLeastRule(2)
),

nextQuestId = 9
nextQuestId = joinActivityQuestId
)
)

val InMemoryQuestRepository.joinActivityQuest: Quest
get() = findById(9) ?: save(
get() = findById(joinActivityQuestId) ?: save(
Quest(
id = 9,
id = joinActivityQuestId,
title = "參與院長主持的學院節目",
description =
"""
Expand All @@ -353,14 +379,14 @@ val InMemoryQuestRepository.joinActivityQuest: Quest
),

criteria = JoinActivityCriteria("遊戲微服務計畫:水球實況", 60, 40),
nextQuestId = 10
nextQuestId = quizQuestId
)
)

val InMemoryQuestRepository.quizQuest: Quest
get() = findById(10) ?: save(
get() = findById(quizQuestId) ?: save(
Quest(
id = 10,
id = quizQuestId,
title = "考試",
description =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ fun String.toDate(): LocalDateTime = LocalDateTime.parse(this)
fun OffsetDateTime.toTaipeiLocalDateTime(): LocalDateTime =
atZoneSameInstant(ZoneId.of("Asia/Taipei")).toLocalDateTime()


fun Mission.publishToUser(user: User) {
user.openPrivateChannel().queue {
it.sendMessageEmbeds(
Expand All @@ -39,6 +38,6 @@ fun Mission.publishToUser(user: User) {

class Color {
companion object {
val GREEN = 706146
const val GREEN = 706146
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,27 @@ package tw.waterballsa.utopia.utopiagamification.quest.listeners
import net.dv8tion.jda.api.entities.Guild
import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent
import org.springframework.stereotype.Component
import tw.waterballsa.utopia.utopiagamification.quest.domain.Mission
import tw.waterballsa.utopia.utopiagamification.quest.domain.Quest
import tw.waterballsa.utopia.utopiagamification.quest.extensions.publishToUser
import tw.waterballsa.utopia.utopiagamification.quest.usecase.PlayerAcceptQuestUsecase
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.unlockAcademyQuestId
import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.AssignPlayerQuestPresenter
import tw.waterballsa.utopia.utopiagamification.quest.usecase.AssignPlayerQuestUsecase
import tw.waterballsa.utopia.utopiagamification.repositories.PlayerRepository
import tw.waterballsa.utopia.utopiagamification.repositories.QuestRepository
import tw.waterballsa.utopia.utopiagamification.repositories.exceptions.NotFoundException.Companion.notFound

private const val unlockAcademyQuestId = 1

@Component
class MemberJoinListener(
guild: Guild,
playerRepository: PlayerRepository,
private val questRepository: QuestRepository,
private val playerAcceptQuestUsecase: PlayerAcceptQuestUsecase,
private val assignPlayerQuestUsecase: AssignPlayerQuestUsecase,
) : UtopiaGamificationListener(guild, playerRepository) {

override fun onGuildMemberJoin(event: GuildMemberJoinEvent) {
with(event) {

//TODO 這個 toPlayer 會有副作用,會註冊玩家,之後會發 pr 解決這個問題
val player = user.toPlayer() ?: return
val unlockAcademyQuest = questRepository.findById(unlockAcademyQuestId)
?: throw notFound(Quest::class)
.id(unlockAcademyQuestId)
.message("assign new member first quest")
.build()

val request = PlayerAcceptQuestUsecase.Request(player, unlockAcademyQuest)

val presenter = object : PlayerAcceptQuestUsecase.Presenter {
override fun presentPlayerHasAcquiredMission() {
sendMessageToUserPrivateChannel("已獲得新手任務,無法再次獲得!")
}
val request = AssignPlayerQuestUsecase.Request(user.id, unlockAcademyQuestId)
val presenter = AssignPlayerQuestPresenter(user)

override fun presentPlayerAcquiresMission(mission: Mission) {
mission.publishToUser(user)
}
}

playerAcceptQuestUsecase.execute(request, presenter)
assignPlayerQuestUsecase.execute(request, presenter)
}
}

private fun GuildMemberJoinEvent.sendMessageToUserPrivateChannel(message: String) =
user.openPrivateChannel().queue { it.sendMessage(message).queue() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,25 @@ import net.dv8tion.jda.api.interactions.commands.build.CommandData
import net.dv8tion.jda.api.interactions.commands.build.Commands
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData
import org.springframework.stereotype.Component
import tw.waterballsa.utopia.utopiagamification.quest.domain.Mission
import tw.waterballsa.utopia.utopiagamification.quest.domain.Quest
import tw.waterballsa.utopia.utopiagamification.quest.domain.State.*
import tw.waterballsa.utopia.utopiagamification.quest.domain.exception.AssignedQuestException
import tw.waterballsa.utopia.utopiagamification.quest.domain.quests.QuestIds.Companion.quizQuestId
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.usecase.PlayerAcceptQuestUsecase
import tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters.AssignPlayerQuestPresenter
import tw.waterballsa.utopia.utopiagamification.quest.usecase.AssignPlayerQuestUsecase
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.utopiagamification.repositories.exceptions.NotFoundException.Companion.notFound

const val UTOPIA_COMMAND_NAME = "utopia"
const val FIRST_QUEST_COMMAND_NAME = "first-quest"
const val REVIEW_COMMAND_NAME = "re-render"

private const val unlockAcademyQuestId = 1
private const val quizQuestId = 10

@Component
class SlashCommandListener(
guild: Guild,
playerRepository: PlayerRepository,
private val questRepository: QuestRepository,
private val playerAcceptQuestUsecase: PlayerAcceptQuestUsecase,
private val assignPlayerQuestUsecase: AssignPlayerQuestUsecase,
private val missionRepository: MissionRepository
) : UtopiaGamificationListener(guild, playerRepository) {

Expand Down Expand Up @@ -57,28 +53,17 @@ class SlashCommandListener(
}

private fun SlashCommandInteractionEvent.handleFirstQuestCommand() {
//TODO 這個 toPlayer 會有副作用,會註冊玩家,之後會發 pr 解決這個問題
val player = user.toPlayer() ?: return

val unlockAcademyQuest = questRepository.findById(unlockAcademyQuestId)
?: throw notFound(Quest::class)
.id(unlockAcademyQuestId)
.message("assign old member first quest")
.build()

val request = PlayerAcceptQuestUsecase.Request(player, unlockAcademyQuest)

val presenter = object : PlayerAcceptQuestUsecase.Presenter {
override fun presentPlayerHasAcquiredMission() {
hook.editOriginal("已獲得新手任務,無法再次獲得。").queue()
}
val request = AssignPlayerQuestUsecase.Request(user.id, unlockAcademyQuestId)
val presenter = AssignPlayerQuestPresenter(user, hook)

override fun presentPlayerAcquiresMission(mission: Mission) {
mission.publishToUser(user)
hook.editOriginal("已經接取第一個任務,去私訊查看任務內容。").queue()
}
try {
assignPlayerQuestUsecase.execute(request, presenter)
} catch (e: AssignedQuestException) {
hook.editOriginal("已獲得新手任務,無法再次獲得!").queue()
}

playerAcceptQuestUsecase.execute(request, presenter)
}

private fun SlashCommandInteractionEvent.handleReviewCommand() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package tw.waterballsa.utopia.utopiagamification.quest.listeners.presenters

import net.dv8tion.jda.api.entities.User
import net.dv8tion.jda.api.interactions.InteractionHook
import tw.waterballsa.utopia.utopiagamification.quest.domain.Mission
import tw.waterballsa.utopia.utopiagamification.quest.extensions.publishToUser
import tw.waterballsa.utopia.utopiagamification.quest.usecase.AssignPlayerQuestUsecase

class AssignPlayerQuestPresenter(
private val user: User,
private val hook: InteractionHook? = null
) : AssignPlayerQuestUsecase.Presenter {
override fun presentMission(mission: Mission) {
hook?.editOriginal("你已接取第一個任務,到私訊查看內容吧!")?.queue()
mission.publishToUser(user)
}
}
Loading

0 comments on commit dc79d3b

Please sign in to comment.