Skip to content

Commit

Permalink
refactor player class
Browse files Browse the repository at this point in the history
  • Loading branch information
wow890209 committed Oct 29, 2023
1 parent 31d3f27 commit 433b515
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 182 deletions.
5 changes: 5 additions & 0 deletions utopia-gamification/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,10 @@
<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>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,33 +1,39 @@
package tw.waterballsa.utopia.utopiagamification.quest.domain

import tw.waterballsa.utopia.utopiagamification.quest.extensions.LevelSheet
import tw.waterballsa.utopia.utopiagamification.quest.extensions.LevelSheet.Companion.calculateLevel
import tw.waterballsa.utopia.utopiagamification.quest.extensions.LevelSheet.Companion.toLevel
import java.time.OffsetDateTime
import java.time.OffsetDateTime.now
import kotlin.ULong.Companion.MIN_VALUE

class Player(
val id: String,
var name: String,
var exp: ULong = MIN_VALUE,
var level: UInt = 1u,
exp: ULong = 0uL,
level: UInt = 1u,
val joinDate: OffsetDateTime = now(),
var latestActivateDate: OffsetDateTime = now(),
var levelUpgradeDate: OffsetDateTime = now(),
// TODO achievement-system 這邊應該要改成 Role 陣列
val jdaRoles: MutableList<String> = mutableListOf(),
latestActivateDate: OffsetDateTime = now(),
levelUpgradeDate: OffsetDateTime? = null,
val jdaRoles: MutableList<String> = mutableListOf()
) {

init {
calculateLevel()
}
var exp = exp
private set

var level = level
private set

var levelUpgradeDate = levelUpgradeDate
private set

val currentLevelExpLimit
get() = LevelSheet.getLevelRange(level.toInt()).expLimit
var latestActivateDate = latestActivateDate
private set

fun gainExp(rewardExp: ULong) {
exp += rewardExp
calculateLevel()
val newLevel = exp.toLevel()
if (newLevel != level) {
level = newLevel
levelUpgradeDate = now()
}
activate()
}

Expand All @@ -39,14 +45,6 @@ class Player(
jdaRoles.add(role)
}

private fun calculateLevel() {
val newLevel = calculateLevel(exp)
if (newLevel > level) {
level = newLevel
levelUpgradeDate = now()
}
}

private fun activate() {
latestActivateDate = now()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
package tw.waterballsa.utopia.utopiagamification.quest.extensions

import tw.waterballsa.utopia.utopiagamification.quest.extensions.LevelSheet.Range.Companion.LEVEL_ONE
import kotlin.ULong.Companion.MIN_VALUE
import tw.waterballsa.utopia.utopiagamification.quest.extensions.LevelSheet.LevelRange.Companion.LEVEL_ONE
import java.lang.String.format


class LevelSheet private constructor() {

companion object {
const val EXP_PER_MINUTES = 10u
private const val EXP_PER_MINUTES = 10u
private const val MAX_LEVEL = 100
private val COEFFICIENTS = arrayOf(1u, 2u, 4u, 8u, 12u, 16u, 32u, 52u, 64u, 84u)
private val LEVEL_TO_RANGE = generateSequence(LEVEL_ONE) { it.next() }.take(MAX_LEVEL).associateBy { it.level }
private val LEVEL_TO_LEVEL_RANGE = generateSequence(LEVEL_ONE) { it.next() }.take(MAX_LEVEL).associateBy { it.level }

fun calculateLevel(exp: ULong) = (LEVEL_TO_RANGE.values.find { it.isExpGreaterThan(exp) } ?: LEVEL_ONE).level.toUInt()
// exp to level
fun ULong.toLevel() = (LEVEL_TO_LEVEL_RANGE.values.find { it.isMatchLevel(this) } ?: LEVEL_ONE).level.toUInt()

fun getLevelRange(level: Int): Range = when {
level <= 0 -> LEVEL_ONE
level > MAX_LEVEL -> LEVEL_TO_RANGE.values.last()
else -> LEVEL_TO_RANGE[level] ?: throw IllegalArgumentException("The level ($level) is incorrect.")
}
// level to level range
fun UInt.toLevelRange(): LevelRange = LEVEL_TO_LEVEL_RANGE[toInt()] ?: throw IllegalArgumentException("The given level ($this) not found.")
}

class Range private constructor(val level: Int = 1, previousLevelRange: Range? = null) {
class LevelRange private constructor(val level: Int = 1, val previous: LevelRange? = null) {

// 升級時間
val upgradeTime: ULong
Expand All @@ -32,29 +31,22 @@ class LevelSheet private constructor() {
val expLimit: ULong

companion object {
val LEVEL_ONE = Range()
val LEVEL_ONE = LevelRange(level = 1)
}

init {
// 經驗值係數
val coefficient = COEFFICIENTS[level.coerceAtLeast(1).div(10).coerceAtMost(COEFFICIENTS.size.minus(1))]
upgradeTime = (previousLevelRange?.upgradeTime ?: MIN_VALUE).plus(EXP_PER_MINUTES.times(coefficient))
accExp = (previousLevelRange?.accExp ?: MIN_VALUE).plus(EXP_PER_MINUTES.times(upgradeTime))
expLimit = accExp.minus(previousLevelRange?.accExp ?: MIN_VALUE)
upgradeTime = (previous?.upgradeTime ?: 0u).plus(EXP_PER_MINUTES.times(coefficient))
accExp = (previous?.accExp ?: 0u).plus(EXP_PER_MINUTES.times(upgradeTime))
expLimit = accExp.minus(previous?.accExp ?: 0u)
}

fun next() = Range(level.plus(1), this)
fun next() = LevelRange(level.plus(1), this)

fun isExpGreaterThan(exp: ULong) = accExp > exp
fun isMatchLevel(exp: ULong) = accExp > exp

override fun toString(): String {
return String.format(
"level: %3d, upgrade time: %5d, exp limit: %6d, acc exp: %7d",
level,
upgradeTime.toLong(),
expLimit.toLong(),
accExp.toLong()
)
}
override fun toString(): String = format("| level: %3d | upgrade time: %5d | exp limit: %6d | acc exp: %7d | %n${"-".repeat(75)}",
level, upgradeTime.toLong(), expLimit.toLong(), accExp.toLong())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent
import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle
import org.springframework.stereotype.Component
import tw.waterballsa.utopia.utopiagamification.quest.domain.Mission
import tw.waterballsa.utopia.utopiagamification.quest.domain.Player
import tw.waterballsa.utopia.utopiagamification.quest.extensions.LevelSheet.Companion.toLevelRange
import tw.waterballsa.utopia.utopiagamification.quest.extensions.LevelSheet.LevelRange.Companion.LEVEL_ONE
import tw.waterballsa.utopia.utopiagamification.quest.extensions.publishToUser
import tw.waterballsa.utopia.utopiagamification.quest.usecase.ClaimMissionRewardUsecase
import tw.waterballsa.utopia.utopiagamification.repositories.PlayerRepository
Expand Down Expand Up @@ -45,11 +48,12 @@ class UtopiaGamificationQuestListener(
val request = ClaimMissionRewardUsecase.Request(player, questId)
val presenter = object : ClaimMissionRewardUsecase.Presenter {
override fun presentPlayerExpNotification(mission: Mission) {

publishMessage(
"""
${player.name} 已獲得 ${mission.quest.reward.exp} exp!!
目前等級:${player.level}
目前經驗值:${player.exp} / ${player.currentLevelExpLimit}
${mission.player.name} 已獲得 ${mission.quest.reward.exp} exp!!
目前等級:${mission.player.level}
目前經驗值:${mission.player.currentExp()}/${mission.player.level.toLevelRange().expLimit}
""".trimIndent()
)
}
Expand All @@ -67,6 +71,9 @@ class UtopiaGamificationQuestListener(
}
}

private fun Player.currentExp(): ULong =
if (level == LEVEL_ONE.level.toUInt()) exp else exp - level.toLevelRange().previous!!.accExp

private fun ButtonInteractionEvent.splitButtonId(delimiters: String): List<String> {
val result = button.id?.split(delimiters) ?: return emptyList()
if (result.size != 3) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ interface PlayerRepository {

fun findPlayerById(id: String): Player?
fun savePlayer(player: Player): Player

}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ data class PlayerDocument(
val level: Int,
val joinDate: OffsetDateTime,
val latestActivateDate: OffsetDateTime,
val levelUpgradeDate: OffsetDateTime,
val levelUpgradeDate: OffsetDateTime?,
val jdaRoles: MutableList<String>? = mutableListOf()
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tw.waterballsa.utopia.utopiagmification.quest

import org.assertj.core.api.Assertions.*
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
Expand Down Expand Up @@ -74,5 +75,15 @@ class UtopiaGamificationQuestTest {
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)
}

0 comments on commit 433b515

Please sign in to comment.