diff options
-rw-r--r-- | sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/cards/Cards.kt | 22 | ||||
-rw-r--r-- | sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt | 157 |
2 files changed, 110 insertions, 69 deletions
diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/cards/Cards.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/cards/Cards.kt index 6b7e1fe0..fdb4d11b 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/cards/Cards.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/cards/Cards.kt @@ -52,17 +52,17 @@ data class PreparedCard( @Serializable data class CardBack(val image: String) -enum class PlayabilityLevel { - CHAINABLE, - NO_REQUIREMENTS, - ENOUGH_RESOURCES, - ENOUGH_GOLD, - ENOUGH_GOLD_AND_RES, - REQUIRES_HELP, - MISSING_REQUIRED_GOLD, - MISSING_GOLD_FOR_RES, - UNAVAILABLE_RESOURCES, - INCOMPATIBLE_WITH_BOARD +enum class PlayabilityLevel(val message: String) { + CHAINABLE("free because of a card on the board"), + NO_REQUIREMENTS("free"), + ENOUGH_RESOURCES("free"), + ENOUGH_GOLD("enough gold"), + ENOUGH_GOLD_AND_RES("enough gold and resources"), + REQUIRES_HELP("requires buying resources"), + MISSING_REQUIRED_GOLD("not enough gold"), + MISSING_GOLD_FOR_RES("not enough gold to buy resources"), + UNAVAILABLE_RESOURCES("neighbours don't have the missing resources"), + INCOMPATIBLE_WITH_BOARD("card already on the board") } enum class Color(val isResource: Boolean) { diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt index 1db3e0b0..6831d6e0 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt @@ -1,42 +1,17 @@ package org.luxons.sevenwonders.ui.components.game -import com.palantir.blueprintjs.Intent -import com.palantir.blueprintjs.bpButton -import com.palantir.blueprintjs.bpButtonGroup -import kotlinx.css.Align -import kotlinx.css.CSSBuilder -import kotlinx.css.Color -import kotlinx.css.Display -import kotlinx.css.GridColumn -import kotlinx.css.GridRow -import kotlinx.css.Position -import kotlinx.css.alignItems -import kotlinx.css.bottom -import kotlinx.css.display -import kotlinx.css.filter -import kotlinx.css.gridColumn -import kotlinx.css.gridRow -import kotlinx.css.height -import kotlinx.css.left -import kotlinx.css.margin -import kotlinx.css.maxHeight -import kotlinx.css.maxWidth -import kotlinx.css.pct -import kotlinx.css.position +import com.palantir.blueprintjs.* +import kotlinx.css.* import kotlinx.css.properties.* -import kotlinx.css.px -import kotlinx.css.rem -import kotlinx.css.vh -import kotlinx.css.vw -import kotlinx.css.width -import kotlinx.css.zIndex import kotlinx.html.DIV import org.luxons.sevenwonders.model.MoveType import org.luxons.sevenwonders.model.PlayerMove +import org.luxons.sevenwonders.model.cards.CardPlayability import org.luxons.sevenwonders.model.cards.HandCard import org.luxons.sevenwonders.model.resources.noTransactions import org.luxons.sevenwonders.model.wonders.WonderBuildability import react.RBuilder +import react.RElementBuilder import styled.StyledDOMBuilder import styled.css import styled.styledDiv @@ -87,7 +62,6 @@ private fun RBuilder.handCard( } private fun RBuilder.actionButtons(card: HandCard, wonderBuildability: WonderBuildability, prepareMove: (PlayerMove) -> Unit) { - // class: action-buttons styledDiv { css { alignItems = Align.flexEnd @@ -100,40 +74,107 @@ private fun RBuilder.actionButtons(card: HandCard, wonderBuildability: WonderBui } } bpButtonGroup { - bpButton(title = "PLAY (${priceText(-card.playability.minPrice)})", - large = true, - intent = Intent.SUCCESS, - icon = "play", - disabled = !card.playability.isPlayable, - onClick = { - val transactions = card.playability.cheapestTransactions.firstOrNull() ?: noTransactions() - prepareMove(PlayerMove(MoveType.PLAY, card.name, transactions)) - } - ) - bpButton(title = "UPGRADE WONDER (${priceText(-wonderBuildability.minPrice)})", - large = true, - intent = Intent.PRIMARY, - icon = "key-shift", - disabled = !wonderBuildability.isBuildable, - onClick = { - val wonderTransactions = wonderBuildability.cheapestTransactions.firstOrNull() ?: noTransactions() - prepareMove(PlayerMove(MoveType.UPGRADE_WONDER, card.name, wonderTransactions)) - } - ) - bpButton(title = "DISCARD (+3 coins)", // TODO remove hardcoded value - large = true, - intent = Intent.DANGER, - icon = "cross", - onClick = { prepareMove(PlayerMove(MoveType.DISCARD, card.name)) } - ) + playCardButton(card, prepareMove) + upgradeWonderButton(wonderBuildability, prepareMove, card) + discardButton(prepareMove, card) + } + } +} + +private fun RElementBuilder<IButtonGroupProps>.playCardButton( + card: HandCard, + prepareMove: (PlayerMove) -> Unit +) { + bpButton( + title = "PLAY (${cardPlayabilityInfo(card.playability)})", + large = true, + intent = Intent.SUCCESS, + disabled = !card.playability.isPlayable, + onClick = { + val transactions = card.playability.cheapestTransactions.firstOrNull() ?: noTransactions() + prepareMove(PlayerMove(MoveType.PLAY, card.name, transactions)) + } + ) { + bpIcon("play") + if (card.playability.isPlayable && !card.playability.isFree) { + priceInfo(card.playability.minPrice) + } + } +} + +private fun RElementBuilder<IButtonGroupProps>.upgradeWonderButton( + wonderBuildability: WonderBuildability, + prepareMove: (PlayerMove) -> Unit, + card: HandCard +) { + bpButton( + title = "UPGRADE WONDER (${wonderBuildabilityInfo(wonderBuildability)})", + large = true, + intent = Intent.PRIMARY, + disabled = !wonderBuildability.isBuildable, + onClick = { + val transactions = wonderBuildability.cheapestTransactions.firstOrNull() ?: noTransactions() + prepareMove(PlayerMove(MoveType.UPGRADE_WONDER, card.name, transactions)) + } + ) { + bpIcon("key-shift") + if (wonderBuildability.isBuildable && !wonderBuildability.isFree) { + priceInfo(wonderBuildability.minPrice) } } } +private fun RElementBuilder<IButtonGroupProps>.discardButton( + prepareMove: (PlayerMove) -> Unit, + card: HandCard +) { + bpButton( + title = "DISCARD (+3 coins)", // TODO remove hardcoded value + large = true, + intent = Intent.DANGER, + icon = "cross", + onClick = { prepareMove(PlayerMove(MoveType.DISCARD, card.name)) } + ) +} + +private fun cardPlayabilityInfo(playability: CardPlayability) = when(playability.isPlayable) { + true -> priceText(-playability.minPrice) + false -> playability.playabilityLevel.message +} + +private fun wonderBuildabilityInfo(buildability: WonderBuildability) = when(buildability.isBuildable) { + true -> priceText(-buildability.minPrice) + false -> buildability.playabilityLevel.message +} + private fun priceText(amount: Int) = when (amount.absoluteValue) { 0 -> "free" - 1 -> "$amount coin" - else -> "$amount coins" + 1 -> "${pricePrefix(amount)}$amount coin" + else -> "${pricePrefix(amount)}$amount coins" +} + +private fun pricePrefix(amount: Int) = when { + amount > 0 -> "+" + else -> "" +} + +private fun RElementBuilder<IButtonProps>.priceInfo(amount: Int) { + styledDiv { + val size = 1.rem + css { + position = Position.absolute + top = (-0.2).rem + left = (-0.2).rem + backgroundColor = Color.goldenrod + width = size + height = size + borderRadius = size + fontSize = size * 0.8 + textAlign = TextAlign.center + zIndex = 5 // above all 3 buttons + } + +"$amount" + } } private fun CSSBuilder.handStyle() { |