diff --git a/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/FirstPage.scala b/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/FirstPage.scala index e3fb9eb5c4..88d3ddd579 100644 --- a/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/FirstPage.scala +++ b/src/main/scala/com/github/unchama/seichiassist/menus/stickmenu/FirstPage.scala @@ -8,7 +8,8 @@ import com.github.unchama.menuinventory.router.CanOpen import com.github.unchama.menuinventory.slot.button.action.{ ClickEventFilter, FilteredButtonEffect, - LeftClickButtonEffect + LeftClickButtonEffect, + RightClickButtonEffect } import com.github.unchama.menuinventory.slot.button.{Button, RecomputedButton, action} import com.github.unchama.seichiassist.data.descrptions.PlayerStatsLoreGenerator @@ -519,8 +520,11 @@ object FirstPage extends Menu { } val computeGachaTicketButton: IO[Button] = { - val effect: FilteredButtonEffect = LeftClickButtonEffect( - environment.gachaPointApi.receiveBatch + val leftClickEffect: FilteredButtonEffect = LeftClickButtonEffect( + environment.gachaPointApi.receiveLargeBatch + ) + val rightClickEffect: FilteredButtonEffect = RightClickButtonEffect( + environment.gachaPointApi.receiveSmallBatch ) val computeItemStack: IO[ItemStack] = @@ -534,8 +538,10 @@ object FirstPage extends Menu { val requiredToNextTicket = s"$RESET${AQUA}次のガチャ券まで:${point.amountUntilNextGachaTicket.amount}ブロック" + val receiveGachaTicketDescription = + s"$RESET${GRAY}左クリックで最大9st、右クリックで最大1stのガチャ券を受け取ります" - List(gachaTicketStatus, requiredToNextTicket) + List(gachaTicketStatus, requiredToNextTicket, receiveGachaTicketDescription) } new SkullItemStackBuilder(SkullOwners.unchama) @@ -545,7 +551,7 @@ object FirstPage extends Menu { } val computeButton: IO[Button] = computeItemStack.map { itemStack => - Button(itemStack, effect) + Button(itemStack, leftClickEffect, rightClickEffect) } RecomputedButton(computeButton) diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/GachaPointApi.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/GachaPointApi.scala index 3549b054c7..e7153e2692 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/GachaPointApi.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/GachaPointApi.scala @@ -15,7 +15,12 @@ trait GachaPointApi[F[_], G[_], Player] { /** * プレーヤーのガチャポイントをガチャ券に変換して一括で受け取る作用。 */ - val receiveBatch: Kleisli[F, Player, Unit] + val receiveLargeBatch: Kleisli[F, Player, Unit] + + /** + * プレーヤーのガチャポイントをガチャ券に変換して一括で受け取る作用。 + */ + val receiveSmallBatch: Kleisli[F, Player, Unit] /** * プレーヤーのガチャポイントを増やす作用。 diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/System.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/System.scala index dd0ff9f74b..7138ed0d5a 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/System.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/System.scala @@ -83,11 +83,18 @@ object System { ReadOnlyRef.fromRef(value.pointRef) ) - override val receiveBatch: Kleisli[F, Player, Unit] = Kleisli { player => + override val receiveLargeBatch: Kleisli[F, Player, Unit] = Kleisli { player => gachaPointRepositoryControlsRepository .lift(player) - .traverse { value => value.semaphore.tryBatchTransaction } - .as(()) + .traverse { _.semaphore.tryLargeBatchTransaction } + .void + } + + override val receiveSmallBatch: Kleisli[F, Player, Unit] = Kleisli { player => + gachaPointRepositoryControlsRepository + .lift(player) + .traverse { _.semaphore.trySmallBatchTransaction } + .void } override def addGachaPoint(point: GachaPoint): Kleisli[F, Player, Unit] = diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/domain/BatchUsageSemaphore.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/domain/BatchUsageSemaphore.scala index b34aba3816..35f2575a3d 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/domain/BatchUsageSemaphore.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/domain/BatchUsageSemaphore.scala @@ -18,15 +18,24 @@ class BatchUsageSemaphore[F[_]: FlatMap, G[_]: ContextCoercion[*[_], F]]( import cats.implicits._ /** - * バッチでのガチャポイント変換を行い、 [[BatchUsageSemaphore.usageInterval]]の間使用不可にする作用。 + * 576個(= 64 * 9スタック)のバッチでガチャポイント変換を行い、 [[BatchUsageSemaphore.usageInterval]]の間使用不可にする作用。 */ - def tryBatchTransaction: F[Unit] = + def tryLargeBatchTransaction: F[Unit] = recoveringSemaphore.tryUse { ContextCoercion { - gachaPointRef.modify { point => point.useInBatch.asTuple } + gachaPointRef.modify { _.useInLargeBatch.asTuple } + }.flatTap(grantAction.give) + }(BatchUsageSemaphore.usageInterval) + + /** + * 64個(= 64 * 1スタック)のバッチでガチャポイント変換を行い、 [[BatchUsageSemaphore.usageInterval]]の間使用不可にする作用。 + */ + def trySmallBatchTransaction: F[Unit] = + recoveringSemaphore.tryUse { + ContextCoercion { + gachaPointRef.modify { _.useInSmallBatch.asTuple } }.flatTap(grantAction.give) }(BatchUsageSemaphore.usageInterval) - } object BatchUsageSemaphore { diff --git a/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/domain/gachapoint/GachaPoint.scala b/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/domain/gachapoint/GachaPoint.scala index 06f7c62021..a3c14036d0 100644 --- a/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/domain/gachapoint/GachaPoint.scala +++ b/src/main/scala/com/github/unchama/seichiassist/subsystems/gachapoint/domain/gachapoint/GachaPoint.scala @@ -5,7 +5,7 @@ import com.github.unchama.seichiassist.subsystems.breakcount.domain.level.Seichi /** * ガチャポイントとはプレーヤーが持つ「消費可能な整地経験量」である。 * - * プレーヤーは576個(= 64 * 9スタック)のバッチにてガチャポイントをガチャ券に交換できる。 + * プレーヤーは576個(= 64 * 9スタック)のバッチもしくは、64個(1スタック)のバッチにてガチャポイントをガチャ券に交換できる。 */ case class GachaPoint(exp: SeichiExpAmount) { @@ -18,8 +18,8 @@ case class GachaPoint(exp: SeichiExpAmount) { /** * ガチャポイントをバッチでガチャ券に変換した際のポイントの変化を計算する。 */ - lazy val useInBatch: GachaPoint.Usage = { - val ticketCount = availableTickets.min(GachaPoint.batchSize).toInt + private def useInBatch(batchSize: BatchSize): GachaPoint.Usage = { + val ticketCount = availableTickets.min(batchSize.value).toInt val expToUse = GachaPoint.perGachaTicket.exp.amount * ticketCount val remaining = GachaPoint.ofNonNegative(exp.amount - expToUse) @@ -27,6 +27,16 @@ case class GachaPoint(exp: SeichiExpAmount) { GachaPoint.Usage(remaining, ticketCount) } + /** + * ガチャポイントを576個(= 64 * 9スタック)のバッチでガチャ券に変換した際のポイントの変化を計算する。 + */ + lazy val useInLargeBatch: GachaPoint.Usage = useInBatch(GachaPoint.largeBatchSize) + + /** + * ガチャポイントを64個(= 64 * 1スタック)のバッチでガチャ券に変換した際のポイントの変化を計算する。 + */ + lazy val useInSmallBatch: GachaPoint.Usage = useInBatch(GachaPoint.smallBatchSize) + /** * 次にガチャ券を利用できるようになるまでに必要な整地経験値量 */ @@ -42,6 +52,10 @@ case class GachaPoint(exp: SeichiExpAmount) { def subtract(point: GachaPoint): GachaPoint = GachaPoint(exp.subtract(point.exp)) } +case class BatchSize(value: Int) { + require(value > 0, "batch size must be positive") +} + object GachaPoint { def ofNonNegative(x: BigDecimal): GachaPoint = GachaPoint(SeichiExpAmount.ofNonNegative(x)) @@ -54,15 +68,25 @@ object GachaPoint { * 変換にて得られるガチャ券の総数 */ case class Usage(remainingGachaPoint: GachaPoint, gachaTicketCount: Int) { - require(gachaTicketCount <= GachaPoint.batchSize, "usage must not exceed batch size") + require(gachaTicketCount <= GachaPoint.maxBatchSize.value, "usage must not exceed max batch size") def asTuple: (GachaPoint, Int) = (remainingGachaPoint, gachaTicketCount) } + /** + * ガチャ券を576個(= 64 * 9スタック)のバッチでガチャポイントに変換する際のバッチサイズ + */ + final val largeBatchSize = BatchSize(9 * 64) + + /** + * ガチャ券を64個(= 64 * 1スタック)のバッチでガチャポイントに変換する際のバッチサイズ + */ + final val smallBatchSize = BatchSize(64) + /** * ガチャ券へのポイント交換にて一度に得られるガチャ券の上限 */ - final val batchSize = 9 * 64 + final val maxBatchSize = largeBatchSize /** * ガチャポイントの初期値 @@ -86,3 +110,4 @@ object GachaPoint { ofNonNegative(perGachaTicketPoint * gachaTicketAmount) } +