summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoffrey Bion <joffrey.bion@booking.com>2020-05-23 01:28:04 +0200
committerJoffrey Bion <joffrey.bion@booking.com>2020-05-23 01:40:39 +0200
commit0249e3f8b6d32ffb8c0370261d22084221aba1ca (patch)
treef04fea6453fae5f50b265345f95aa5eb73cae2b5
parentPlay default cheapest transactions (diff)
downloadseven-wonders-0249e3f8b6d32ffb8c0370261d22084221aba1ca.tar.gz
seven-wonders-0249e3f8b6d32ffb8c0370261d22084221aba1ca.tar.bz2
seven-wonders-0249e3f8b6d32ffb8c0370261d22084221aba1ca.zip
Add score board UI at end of game
-rw-r--r--sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/score/Score.kt16
-rw-r--r--sw-ui/src/main/kotlin/com/palantir/blueprintjs/BpHtmlTable.kt26
-rw-r--r--sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt24
-rw-r--r--sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt11
-rw-r--r--sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt11
-rw-r--r--sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ScoreTable.kt142
-rw-r--r--sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt12
-rw-r--r--sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/ApiActions.kt2
8 files changed, 221 insertions, 23 deletions
diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/score/Score.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/score/Score.kt
index 3f9dbe41..1896ecd3 100644
--- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/score/Score.kt
+++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/score/Score.kt
@@ -17,12 +17,12 @@ data class PlayerScore(
override fun compareTo(other: PlayerScore) = compareValuesBy(this, other, { it.totalPoints }, { it.boardGold })
}
-enum class ScoreCategory {
- CIVIL,
- SCIENCE,
- MILITARY,
- TRADE,
- GUILD,
- WONDER,
- GOLD
+enum class ScoreCategory(val title: String) {
+ CIVIL("Civil"),
+ SCIENCE("Science"),
+ MILITARY("War"),
+ TRADE("Trade"),
+ GUILD("Guild"),
+ WONDER("Wonder"),
+ GOLD("Gold")
}
diff --git a/sw-ui/src/main/kotlin/com/palantir/blueprintjs/BpHtmlTable.kt b/sw-ui/src/main/kotlin/com/palantir/blueprintjs/BpHtmlTable.kt
new file mode 100644
index 00000000..1a602882
--- /dev/null
+++ b/sw-ui/src/main/kotlin/com/palantir/blueprintjs/BpHtmlTable.kt
@@ -0,0 +1,26 @@
+@file:JsModule("@blueprintjs/core")
+package com.palantir.blueprintjs
+
+import react.PureComponent
+import react.RProps
+import react.RState
+import react.ReactElement
+
+external interface IHTMLTableProps : RProps {
+ var bordered: Boolean?
+ get() = definedExternally
+ set(value) = definedExternally
+ var condensed: Boolean?
+ get() = definedExternally
+ set(value) = definedExternally
+ var interactive: Boolean?
+ get() = definedExternally
+ set(value) = definedExternally
+ var striped: Boolean?
+ get() = definedExternally
+ set(value) = definedExternally
+}
+
+open external class HTMLTable : PureComponent<IHTMLTableProps, RState> {
+ override fun render(): ReactElement
+}
diff --git a/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt b/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt
index a366c446..1a7638dc 100644
--- a/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt
+++ b/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt
@@ -85,12 +85,20 @@ fun RBuilder.bpInputGroup(
fun RBuilder.bpTag(
intent: Intent? = null,
minimal: Boolean? = null,
+ large: Boolean? = null,
+ round: Boolean? = null,
+ fill: Boolean? = null,
active: Boolean? = null,
+ icon: String? = null,
block: RHandler<ITagProps> = {}
): ReactElement = child(Tag::class) {
attrs {
this.intent = intent
this.minimal = minimal
+ this.large = large
+ this.round = round
+ this.fill = fill
+ this.icon = icon
this.active = active
}
block()
@@ -176,3 +184,19 @@ fun RBuilder.bpCard(
}
block()
}
+
+fun RBuilder.bpHtmlTable(
+ bordered: Boolean = false,
+ interactive: Boolean = false,
+ condensed: Boolean = false,
+ striped: Boolean = false,
+ block: RHandler<IHTMLTableProps> = {}
+): ReactElement = child(HTMLTable::class) {
+ attrs {
+ this.bordered = bordered
+ this.interactive = interactive
+ this.condensed = condensed
+ this.striped = striped
+ }
+ block()
+}
diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt
index ce32e8b9..dcd80b6f 100644
--- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt
+++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt
@@ -11,11 +11,7 @@ import org.luxons.sevenwonders.model.PlayerTurnInfo
import org.luxons.sevenwonders.model.api.PlayerDTO
import org.luxons.sevenwonders.model.cards.HandCard
import org.luxons.sevenwonders.ui.components.GlobalStyles
-import org.luxons.sevenwonders.ui.redux.GameState
-import org.luxons.sevenwonders.ui.redux.RequestPrepareMove
-import org.luxons.sevenwonders.ui.redux.RequestSayReady
-import org.luxons.sevenwonders.ui.redux.RequestUnprepareMove
-import org.luxons.sevenwonders.ui.redux.connectStateAndDispatch
+import org.luxons.sevenwonders.ui.redux.*
import react.*
import react.dom.*
import styled.*
@@ -32,6 +28,7 @@ interface GameSceneDispatchProps : RProps {
var sayReady: () -> Unit
var prepareMove: (move: PlayerMove) -> Unit
var unprepareMove: () -> Unit
+ var leaveGame: () -> Unit
}
interface GameSceneProps : GameSceneStateProps, GameSceneDispatchProps
@@ -57,6 +54,9 @@ private class GameScene(props: GameSceneProps) : RComponent<GameSceneProps, RSta
private fun RBuilder.turnInfoScene(turnInfo: PlayerTurnInfo) {
val board = turnInfo.table.boards[turnInfo.playerIndex]
div {
+ turnInfo.scoreBoard?.let {
+ scoreTableOverlay(it, props.players, props.leaveGame)
+ }
actionInfo(turnInfo.message)
boardComponent(board = board)
val hand = turnInfo.hand
@@ -206,6 +206,7 @@ private val gameScene: RClass<GameSceneProps> =
prepareMove = { move -> dispatch(RequestPrepareMove(move)) }
unprepareMove = { dispatch(RequestUnprepareMove()) }
sayReady = { dispatch(RequestSayReady()) }
+ leaveGame = { dispatch(RequestLeaveGame()) }
},
mapStateToProps = { state, _ ->
playerIsReady = state.currentPlayer?.isReady == true
diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt
new file mode 100644
index 00000000..dc52a83a
--- /dev/null
+++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt
@@ -0,0 +1,11 @@
+package org.luxons.sevenwonders.ui.components.game
+
+import kotlinx.css.*
+import styled.StyleSheet
+
+object GameStyles : StyleSheet("GameStyles", isStatic = true) {
+
+ val scoreBoard by css {
+ backgroundColor = Color.paleGoldenrod
+ }
+}
diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ScoreTable.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ScoreTable.kt
new file mode 100644
index 00000000..149fd3c9
--- /dev/null
+++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ScoreTable.kt
@@ -0,0 +1,142 @@
+package org.luxons.sevenwonders.ui.components.game
+
+import com.palantir.blueprintjs.*
+import kotlinx.css.*
+import kotlinx.html.TD
+import kotlinx.html.TH
+import org.luxons.sevenwonders.model.api.PlayerDTO
+import org.luxons.sevenwonders.model.score.ScoreBoard
+import org.luxons.sevenwonders.model.score.ScoreCategory
+import org.luxons.sevenwonders.ui.components.GlobalStyles
+import react.RBuilder
+import react.dom.*
+import styled.*
+
+fun RBuilder.scoreTableOverlay(scoreBoard: ScoreBoard, players: List<PlayerDTO>, leaveGame: () -> Unit) {
+ bpOverlay(isOpen = true) {
+ bpCard {
+ attrs {
+ val fixedCenterClass = GlobalStyles.getClassName { it::fixedCenter }
+ val scoreBoardClass = GameStyles.getClassName { it::scoreBoard }
+ className = "$fixedCenterClass $scoreBoardClass"
+ }
+ styledDiv {
+ css {
+ display = Display.flex
+ flexDirection = FlexDirection.column
+ alignItems = Align.center
+ }
+ styledH1 {
+ css {
+ marginTop = 0.px
+ }
+ +"Score Board"
+ }
+ scoreTable(scoreBoard, players)
+ styledDiv {
+ css {
+ marginTop = 1.rem
+ }
+ bpButton(intent = Intent.WARNING, rightIcon = "log-out", large = true, onClick = { leaveGame() }) {
+ +"LEAVE"
+ }
+ }
+ }
+ }
+ }
+}
+
+private fun RBuilder.scoreTable(scoreBoard: ScoreBoard, players: List<PlayerDTO>) {
+ bpHtmlTable(bordered = false, interactive = true) {
+ thead {
+ tr {
+ centeredTh { +"Rank" }
+ centeredTh {
+ attrs { colSpan = "2" }
+ +"Player"
+ }
+ centeredTh { +"Score" }
+ ScoreCategory.values().forEach {
+ centeredTh { +it.title }
+ }
+ }
+ }
+ tbody {
+ scoreBoard.scores.forEachIndexed { index, score ->
+ val player = players[score.playerIndex]
+ tr {
+ centeredTd { +"${index + 1}" }
+ centeredTd { bpIcon(player.icon?.name ?: "user", size = 25) }
+ styledTd {
+ inlineStyles {
+ verticalAlign = VerticalAlign.middle
+ }
+ +player.displayName
+ }
+ centeredTd {
+ bpTag(large = true, round = true, minimal = true) {
+ +"${score.totalPoints}"
+ }
+ }
+ ScoreCategory.values().forEach { cat ->
+ centeredTd {
+ bpTag(intent = cat.intent, large = true, round = true, icon = cat.icon, fill = true) {
+ +"${score.pointsByCategory[cat]}"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+private fun RBuilder.centeredTh(block: RDOMBuilder<TH>.() -> Unit) {
+ th {
+ // inline styles necessary to overcome blueprintJS overrides
+ inlineStyles {
+ textAlign = TextAlign.center
+ verticalAlign = VerticalAlign.middle
+ }
+ block()
+ }
+}
+
+private fun RBuilder.centeredTd(block: RDOMBuilder<TD>.() -> Unit) {
+ td {
+ // inline styles necessary to overcome blueprintJS overrides
+ inlineStyles {
+ textAlign = TextAlign.center
+ verticalAlign = VerticalAlign.middle
+ }
+ block()
+ }
+}
+
+private val ScoreCategory.intent: Intent
+ get() = when(this) {
+ ScoreCategory.CIVIL -> Intent.PRIMARY
+ ScoreCategory.SCIENCE -> Intent.SUCCESS
+ ScoreCategory.MILITARY -> Intent.DANGER
+ ScoreCategory.TRADE -> Intent.WARNING
+ ScoreCategory.GUILD -> Intent.NONE
+ ScoreCategory.WONDER -> Intent.NONE
+ ScoreCategory.GOLD -> Intent.WARNING
+ }
+
+private val ScoreCategory.icon: String
+ get() = when(this) {
+ ScoreCategory.CIVIL -> "office"
+ ScoreCategory.SCIENCE -> "lab-test"
+ ScoreCategory.MILITARY -> "cut"
+ ScoreCategory.TRADE -> "swap-horizontal"
+ ScoreCategory.GUILD -> "clean" // stars
+ ScoreCategory.WONDER -> "symbol-triangle-up"
+ ScoreCategory.GOLD -> "dollar"
+ }
+
+// Potentially useful emojis:
+// Greek temple: 🏛
+// Cog (science): ⚙️
+// Swords (war): ⚔️
+// Gold bag: 💰
diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
index 1e591f87..4d23974f 100644
--- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
+++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
@@ -1,12 +1,7 @@
package org.luxons.sevenwonders.ui.components.gameBrowser
-import com.palantir.blueprintjs.Classes
-import com.palantir.blueprintjs.Intent
-import com.palantir.blueprintjs.bpButton
-import com.palantir.blueprintjs.bpIcon
-import com.palantir.blueprintjs.bpTag
+import com.palantir.blueprintjs.*
import kotlinx.css.*
-import kotlinx.html.classes
import kotlinx.html.title
import org.luxons.sevenwonders.model.api.ConnectedPlayer
import org.luxons.sevenwonders.model.api.LobbyDTO
@@ -37,10 +32,7 @@ interface GameListProps : GameListStateProps, GameListDispatchProps
class GameListPresenter(props: GameListProps) : RComponent<GameListProps, RState>(props) {
override fun RBuilder.render() {
- table {
- attrs {
- classes = setOf(Classes.HTML_TABLE)
- }
+ bpHtmlTable {
thead {
gameListHeaderRow()
}
diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/ApiActions.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/ApiActions.kt
index 300693a3..6fbaadb9 100644
--- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/ApiActions.kt
+++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/ApiActions.kt
@@ -20,6 +20,8 @@ class RequestStartGame : RAction
class RequestLeaveLobby : RAction
+class RequestLeaveGame : RAction
+
class RequestSayReady : RAction
data class RequestPrepareMove(val move: PlayerMove) : RAction
bgstack15