From 0961a74c15f69465cf31bdc7dafb0afd2977fbc7 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 8 Jun 2020 17:10:45 +0200 Subject: [PATCH] Add chips --- .../handhistory/model/ComputedAction.kt | 2 +- .../replayer/ReplayerConfiguration.kt | 60 +++++- .../handhistory/replayer/TableDrawer.kt | 174 ++++++++++++------ 3 files changed, 178 insertions(+), 58 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt index a71d81d0..a6acbd15 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt @@ -309,7 +309,7 @@ class ComputedAction(var manager: ActionManager, get() { return this.action.position } override fun draw(configuration: ReplayerConfiguration, canvas: Canvas, context: Context) { - TableDrawer.drawAction(this, configuration, canvas, context) + TableDrawer.drawAction(this.positionIndex, this, configuration, canvas, context) } override fun frames( diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerConfiguration.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerConfiguration.kt index 7bfc03db..85ac64bf 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerConfiguration.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerConfiguration.kt @@ -3,10 +3,18 @@ package net.pokeranalytics.android.ui.modules.handhistory.replayer import android.graphics.RectF import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.realm.handhistory.HandHistory +import net.pokeranalytics.android.ui.modules.handhistory.model.ActionList import timber.log.Timber class ReplayerConfiguration(var handHistory: HandHistory) { + var actionList: ActionList = ActionList(null) + private set + + init { + this.actionList.load(this.handHistory) + } + data class Size(var width: Float, var height: Float) data class Circle(var x: Float, var y: Float, var radius: Float) data class TextPoint(var x: Float, var y: Float, var fontSize: Float) @@ -25,8 +33,12 @@ class ReplayerConfiguration(var handHistory: HandHistory) { private var playerCircles = mutableListOf() private var playerNamePoints = mutableListOf() private var playerStackPoints = mutableListOf() + private var playerActionPoints = mutableListOf() private var playerCardRects = mutableListOf>() + private var chipCircles = mutableListOf() + private var chipTextPoints = mutableListOf() + val dealerCircle: Circle get() { val rect = this.playerStackRects.last() @@ -59,7 +71,7 @@ class ReplayerConfiguration(var handHistory: HandHistory) { val playerPerColumn = if (portrait) 4 else 3 val playerPerRow = 12 / playerPerColumn // 3 or 4 - this.tableHPadding = width / playerPerRow / 2 + this.tableHPadding = width / playerPerRow / 2 * 0.9f this.tableVPadding = height / playerPerColumn * 0.8f this.tableRect = RectF(tableHPadding, tableVPadding, width - tableHPadding, height - tableVPadding) @@ -69,7 +81,7 @@ class ReplayerConfiguration(var handHistory: HandHistory) { val pzWidth = width / playerPerRow this.playerItemsHeight = pzHeight / 3 - this.playerItemsWidth = pzWidth * this.paddingPercentage + this.playerItemsWidth = this.tableHPadding * 2 * this.paddingPercentage val cardWidth = pzWidth * this.cardsPaddingPercentage / this.maxCards this.cardSpecs = Size(cardWidth, cardWidth * 1.75f) @@ -94,37 +106,59 @@ class ReplayerConfiguration(var handHistory: HandHistory) { } if (portrait && playerCount > 4) { repartition.reverse() } // adjustment for portrait vs landscape + val chipsVerticalOffsetFromStackCenter = this.playerItemsHeight * 0.9f + val chipsHorizontalOffsetFromStackCenter = pzWidth / 2f + var pIndex = -1 repartition.forEachIndexed { index, count -> val x = width / (count + 1) val y = height / (count + 1) - var rectCenterX = x - var rectCenterY = y + var rectCenterX: Float + var rectCenterY: Float + var chipXOffset: Float + var chipYOffset: Float var circleOffset = playerItemsHeight * 1.75f + for (i in 1..count) { pIndex += 1 Timber.d("Creating dimensions for player $pIndex") + // when the position is in a corner, because we have 3/4 players + // we need an additional offset direction to display the chips + val cornerDirection = when { + count > 2 && i == 1 -> { 1 } + count > 2 && i == count -> { - 1 } + else -> { 0 } + } + when (index) { 0 -> { // bottom rectCenterX = x * i rectCenterY = height - this.tableVPadding circleOffset *= -1 + chipXOffset = cornerDirection * chipsHorizontalOffsetFromStackCenter + chipYOffset = -1.25f * chipsVerticalOffsetFromStackCenter } 1 -> { // left rectCenterX = this.tableHPadding rectCenterY = height - y * i + chipXOffset = 1 * chipsHorizontalOffsetFromStackCenter + chipYOffset = cornerDirection * -1 * chipsVerticalOffsetFromStackCenter } 2 -> { // top rectCenterX = x * i rectCenterY = this.tableVPadding + chipXOffset = cornerDirection * -1 * chipsHorizontalOffsetFromStackCenter + chipYOffset = 1 * chipsVerticalOffsetFromStackCenter } 3 -> { // right rectCenterX = width - this.tableHPadding rectCenterY = y * i + chipXOffset = -1 * chipsHorizontalOffsetFromStackCenter + chipYOffset = cornerDirection * chipsVerticalOffsetFromStackCenter } else -> throw PAIllegalStateException("can't happen") } @@ -135,6 +169,11 @@ class ReplayerConfiguration(var handHistory: HandHistory) { val bottom = rectCenterY + this.playerItemsHeight / 2 this.playerStackRects.add(RectF(left, top, right, bottom)) + val chipRadius = this.playerItemsHeight / 4 + this.chipCircles.add(Circle(rectCenterX + chipXOffset, rectCenterY + chipYOffset, chipRadius)) + val chipTextSize = chipRadius + this.chipTextPoints.add(TextPoint(rectCenterX + chipXOffset, rectCenterY + chipYOffset + 2 * chipTextSize, chipTextSize)) + // we give each text zone 1/3rd of the box height, leaving 1/3 for space // the y given is the bottom of the text rect, giving 1/18th as the offset // 1 / (3_total_space * 3_each_space * 2_center) @@ -143,6 +182,7 @@ class ReplayerConfiguration(var handHistory: HandHistory) { val fontSize = this.playerItemsHeight / 3 this.playerNamePoints.add(TextPoint(rectCenterX, rectCenterY - bottomOffset, fontSize)) this.playerStackPoints.add(TextPoint(rectCenterX, rectCenterY + this.playerItemsHeight / 3, fontSize)) + this.playerActionPoints.add(TextPoint(rectCenterX, rectCenterY + this.playerItemsHeight / 6, fontSize)) this.playerCircles.add(Circle(rectCenterX, rectCenterY - circleOffset, this.playerItemsHeight / 2)) @@ -179,6 +219,14 @@ class ReplayerConfiguration(var handHistory: HandHistory) { return this.playerCircles[i] } + fun chipCircle(i: Int): Circle { + return this.chipCircles[i] + } + + fun chipText(i: Int): TextPoint { + return this.chipTextPoints[i] + } + fun pointForPlayerName(i: Int): TextPoint { return this.playerNamePoints[i] } @@ -187,6 +235,10 @@ class ReplayerConfiguration(var handHistory: HandHistory) { return this.playerStackPoints[i] } + fun pointForPlayerAction(i: Int): TextPoint { + return this.playerActionPoints[i] + } + fun cardRects(i: Int): List { return this.playerCardRects[i] } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt index 566ecc26..56d1ba94 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt @@ -4,10 +4,13 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Paint +import android.graphics.RectF import androidx.core.content.res.ResourcesCompat +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory import net.pokeranalytics.android.R import net.pokeranalytics.android.model.handhistory.Position import net.pokeranalytics.android.model.handhistory.Street +import net.pokeranalytics.android.model.realm.handhistory.Action import net.pokeranalytics.android.model.realm.handhistory.Card import net.pokeranalytics.android.ui.modules.handhistory.model.ComputedAction import net.pokeranalytics.android.util.RANDOM_PLAYER @@ -65,40 +68,30 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) { cardTextPaint.textSize = config.cardSpecs.height * .38f val hh = config.handHistory - val positions = Position.positionsPerPlayers(hh.numberOfPlayers) for (i in 0 until hh.numberOfPlayers) { - val isHero = (hh.heroIndex == i) Timber.d("Getting player $i setup ") val playerSetup = hh.playerSetupForPosition(i) - // Stack zone - val rect = config.stackRectForPlayer(i) - val radius = (rect.bottom - rect.top) / 4 - - fillPaint.color = context.getColor(R.color.green_darker) - canvas.drawRoundRect(config.stackRectForPlayer(i), radius, radius, this.fillPaint) - strokePaint.color = context.getColor(R.color.green) - canvas.drawRoundRect(config.stackRectForPlayer(i), radius, radius, this.strokePaint) + drawPlayerRectangle(i, playerSetup?.stack, false, config, canvas, context) // Player portrait zone val circle = config.circleForPlayer(i) - canvas.drawCircle(circle.x, circle.y, circle.radius, this.fillPaint) - canvas.drawCircle(circle.x, circle.y, circle.radius, this.strokePaint) + val radius = circle.radius + canvas.drawCircle(circle.x, circle.y, radius, this.fillPaint) + canvas.drawCircle(circle.x, circle.y, radius, this.strokePaint) val playerInitials = playerSetup?.player?.initials ?: RANDOM_PLAYER - this.textPaint.textSize = circle.radius - canvas.drawText(playerInitials, circle.x, circle.y + circle.radius * 0.4f, this.textPaint) - - // Player name - val name = playerSetup?.player?.name ?: positions.elementAt(i).value - val pnPoint = config.pointForPlayerName(i) - this.textPaint.textSize = pnPoint.fontSize - canvas.drawText(name, pnPoint.x, pnPoint.y, this.textPaint) - - // Player stack - playerSetup?.stack?.formatted?.let { stack -> - val psPoint = config.pointForPlayerStack(i) - this.textPaint.textSize = psPoint.fontSize - canvas.drawText(stack, psPoint.x, psPoint.y, this.textPaint) + this.textPaint.textSize = radius + canvas.drawText(playerInitials, circle.x, circle.y + radius * 0.4f, this.textPaint) + + // Player picture + playerSetup?.player?.picture?.let { picturePath -> + val pictureBitmap = RoundedBitmapDrawableFactory.create(context.resources, picturePath) + pictureBitmap.setAntiAlias(true) + pictureBitmap.cornerRadius = circle.radius + pictureBitmap.bitmap?.let { bitmap -> + val pictureRect = RectF(circle.x - radius, circle.y - radius, circle.x + radius, circle.y + radius) + canvas.drawBitmap(bitmap, null, pictureRect, null) + } } // Dealer button @@ -107,48 +100,123 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) { canvas.drawCircle(dealerCircle.x, dealerCircle.y, dealerCircle.radius, fillPaint) this.strokePaint.color = context.getColor(R.color.white) canvas.drawCircle(dealerCircle.x, dealerCircle.y, dealerCircle.radius, strokePaint) + this.textPaint.textSize = dealerCircle.radius canvas.drawText("D", dealerCircle.x, dealerCircle.y + this.textPaint.textSize / 3, this.textPaint) - val cardRects = config.cardRects(i) - val cards = playerSetup?.cards - cardRects.forEachIndexed { j, cardRect -> - - if (j < cards?.size ?: 0 && (config.showVillainHands || isHero)) { // show card - val card = cards?.get(j)!! // tested line before - fillPaint.color = context.getColor(R.color.white) - canvas.drawRoundRect(cardRect, config.cardRadius, config.cardRadius, fillPaint) - - cardTextPaint.color = context.getColor(R.color.black) - val valueY = cardRect.top + config.cardSpecs.height * 0.44f - canvas.drawText(card.formattedValue, cardRect.centerX(), valueY, cardTextPaint) - - val suit = card.suit ?: Card.Suit.UNDEFINED - cardTextPaint.color = context.getColor(suit.color) - val suitY = cardRect.top + config.cardSpecs.height * 0.88f - canvas.drawText(suit.value, cardRect.centerX(), suitY, cardTextPaint) - - } else { // show hidden cards - fillPaint.color = context.getColor(R.color.card_fill) - canvas.drawRoundRect(cardRect, config.cardRadius, config.cardRadius, fillPaint) - cardStrokePaint.color = context.getColor(R.color.card_border) - canvas.drawRoundRect(cardRect, config.cardRadius, config.cardRadius, cardStrokePaint) - } + drawCards(i, config, canvas, context) + +// val blinds = config.actionList.filter { it.action.type?.isBlind ?: false } +// blinds.forEach { action -> +// drawAction(i, action, config, canvas, context) +// } + + val chipCircle = config.chipCircle(i) + this.fillPaint.color = context.getColor(R.color.green) + canvas.drawCircle(chipCircle.x, chipCircle.y, chipCircle.radius, this.fillPaint) + + val chipText = config.chipText(i) + this.textPaint.textSize = chipText.fontSize + this.textPaint.color = context.getColor(R.color.white) + canvas.drawText("2000", chipText.x, chipText.y, this.textPaint) + + } + } + + private fun drawCards(playerIndex: Int, config: ReplayerConfiguration, canvas: Canvas, context: Context) { + + val playerSetup = config.handHistory.playerSetupForPosition(playerIndex) + val cardRects = config.cardRects(playerIndex) + val cards = playerSetup?.cards + val isHero = (config.handHistory.heroIndex == playerIndex) + cardRects.forEachIndexed { j, cardRect -> + + if (j < cards?.size ?: 0 && (config.showVillainHands || isHero)) { // show card + val card = cards?.get(j)!! // tested line before + fillPaint.color = context.getColor(R.color.white) + canvas.drawRoundRect(cardRect, config.cardRadius, config.cardRadius, fillPaint) + + cardTextPaint.color = context.getColor(R.color.black) + val valueY = cardRect.top + config.cardSpecs.height * 0.44f + canvas.drawText(card.formattedValue, cardRect.centerX(), valueY, cardTextPaint) + + val suit = card.suit ?: Card.Suit.UNDEFINED + cardTextPaint.color = context.getColor(suit.color) + val suitY = cardRect.top + config.cardSpecs.height * 0.88f + canvas.drawText(suit.value, cardRect.centerX(), suitY, cardTextPaint) + + } else { // show hidden cards + fillPaint.color = context.getColor(R.color.card_fill) + canvas.drawRoundRect(cardRect, config.cardRadius, config.cardRadius, fillPaint) + cardStrokePaint.color = context.getColor(R.color.card_border) + canvas.drawRoundRect(cardRect, config.cardRadius, config.cardRadius, cardStrokePaint) } } } - fun drawStreet(street: Street, config: ReplayerConfiguration, canvas: Canvas, context: Context) { + fun drawAction(i: Int, action: ComputedAction, config: ReplayerConfiguration, canvas: Canvas, context: Context) { + + // show that action is on the player by highlighting + drawPlayerRectangle(i, null, true, config, canvas, context) + + // show action name : call, bet, check... + drawAction(i, action.action.type!!, config, canvas, context) + + // show chips image + text, if applicable + + // show pot updates, if applicable + + } + + /*** + * [i] is the player position in the hand + */ + private fun drawPlayerRectangle(i: Int, stack: Double?, highlighted: Boolean, config: ReplayerConfiguration, canvas: Canvas, context: Context) { + + val rect = config.stackRectForPlayer(i) + val rectRadius = (rect.bottom - rect.top) / 4 + + val color = if (highlighted) R.color.green_diamond_dark else R.color.green_darker + fillPaint.color = context.getColor(color) + canvas.drawRoundRect(config.stackRectForPlayer(i), rectRadius, rectRadius, this.fillPaint) + strokePaint.color = context.getColor(R.color.green) + canvas.drawRoundRect(config.stackRectForPlayer(i), rectRadius, rectRadius, this.strokePaint) + + drawPositionAndStack(i, stack, config, canvas, context) } - fun drawAction(action: ComputedAction, config: ReplayerConfiguration, canvas: Canvas, context: Context) { + private fun drawPositionAndStack(i: Int, stack: Double?, config: ReplayerConfiguration, canvas: Canvas, context: Context) { + + val hh = config.handHistory + // Player position + val positions = Position.positionsPerPlayers(hh.numberOfPlayers) + val name = positions.elementAt(i).value + val pnPoint = config.pointForPlayerName(i) + this.textPaint.textSize = pnPoint.fontSize + canvas.drawText(name, pnPoint.x, pnPoint.y, this.textPaint) + + // Player stack + val psPoint = config.pointForPlayerStack(i) + this.textPaint.textSize = psPoint.fontSize + val stackFormatted = stack?.formatted ?: "" + canvas.drawText(stackFormatted, psPoint.x, psPoint.y, this.textPaint) + + } + + private fun drawAction(i: Int, type: Action.Type, config: ReplayerConfiguration, canvas: Canvas, context: Context) { + val pnPoint = config.pointForPlayerAction(i) + this.textPaint.textSize = pnPoint.fontSize + canvas.drawText(type.name, pnPoint.x, pnPoint.y, this.textPaint) + } + + fun drawStreet(street: Street, config: ReplayerConfiguration, canvas: Canvas, context: Context) { } - //////// + //////// fun setPot(pot: Double, totalPot: Double) { }