Change replayer drawing algo to draw only what is necessary

hh
Laurent 5 years ago
parent b19fa6823d
commit cb4206ea3a
  1. 9
      app/src/main/java/net/pokeranalytics/android/model/handhistory/Street.kt
  2. 3
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryFragment.kt
  3. 18
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt
  4. 6
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt
  5. 4
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/HandHistoryViewModel.kt
  6. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/HandStep.kt
  7. 62
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerConfiguration.kt
  8. 32
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerView.kt
  9. 131
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt

@ -5,7 +5,6 @@ import android.graphics.Canvas
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.modules.handhistory.replayer.HandStep
import net.pokeranalytics.android.ui.modules.handhistory.replayer.ReplayerConfiguration
import net.pokeranalytics.android.ui.modules.handhistory.replayer.TableDrawer
enum class Street : HandStep {
PREFLOP,
@ -40,9 +39,9 @@ enum class Street : HandStep {
return values()[this.ordinal + 1]
}
override fun draw(configuration: ReplayerConfiguration, canvas: Canvas, context: Context) {
TableDrawer.drawStreet(this, configuration, canvas, context)
}
// override fun draw(configuration: ReplayerConfiguration, canvas: Canvas, context: Context) {
// TableDrawer.drawStreet(this, configuration, canvas, context)
// }
override fun frames(
configuration: ReplayerConfiguration,
@ -50,7 +49,7 @@ enum class Street : HandStep {
context: Context,
update: () -> Unit
) {
TableDrawer.drawStreet(this, configuration, canvas, context)
// TableDrawer.drawStreet(this, configuration, canvas, context)
}
}

@ -728,7 +728,8 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
val tc = TableDrawer(bitmap)
// draw initial table
TableDrawer.initializeTable(config, tc, requireContext())
// TableDrawer.initializeTable(config, tc, requireContext())
// TODO
val muxer = MMediaMuxer()
muxer.Init(requireActivity(), bitmap.width, bitmap.height, "hhVideo", "YES!")

@ -711,6 +711,9 @@ class ActionList(var listener: ActionListListener? = null) : ArrayList<ComputedA
this.removeAll { it.action.type?.isBlind == true }
}
/***
* Returns the ComputedAction just before the passed [action]
*/
override fun previousAction(action: ComputedAction): ComputedAction? {
val index = this.indexOf(action)
return if (index > 0) {
@ -720,5 +723,20 @@ class ActionList(var listener: ActionListListener? = null) : ArrayList<ComputedA
}
}
/***
* Returns the player stack, located at the given [position], at the action [index]
*/
fun playerRemainingStack(position: Int, index: Int): Double? {
return this.take(index + 1).lastOrNull { it.positionIndex == position }?.stackAfterActing
}
/***
* Returns the last action where the player put chips on the table for the street
*/
fun lastChipCommittingActionOfPlayer(position: Int, stepIndex: Int): ComputedAction? {
val street = this[stepIndex].street
return this.take(stepIndex + 1).filter { it.street == street }
.lastOrNull { it.positionIndex == position && it.action.type?.isPassive == false }
}
}

@ -313,9 +313,9 @@ class ComputedAction(var manager: ActionManager,
return this.manager.previousAction(this)
}
override fun draw(configuration: ReplayerConfiguration, canvas: Canvas, context: Context) {
TableDrawer.drawAction(this, true, configuration, canvas, context)
}
// override fun draw(configuration: ReplayerConfiguration, canvas: Canvas, context: Context) {
// TableDrawer.drawAction(this, true, configuration, canvas, context)
// }
override fun frames(
configuration: ReplayerConfiguration,

@ -1032,8 +1032,4 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentra
this.createRowRepresentation()
}
fun changeSpeed() {
TODO("Not yet implemented")
}
}

@ -10,7 +10,7 @@ interface HandStep {
fun frames(configuration: ReplayerConfiguration, canvas: Canvas, context: Context, update: () -> (Unit))
fun draw(configuration: ReplayerConfiguration, canvas: Canvas, context: Context)
// fun draw(configuration: ReplayerConfiguration, canvas: Canvas, context: Context)
companion object {

@ -18,29 +18,20 @@ class ReplayerConfiguration(var handHistory: HandHistory) {
private var lastBlindIndex: Int = 0
private var currentStep: Int = 0
private var stepIndex: Int = 0
init {
this.actionList.load(this.handHistory)
this.lastBlindIndex = max(this.actionList.indexOfLast { it.action.type?.isBlind == true }, 0)
this.currentStep = this.lastBlindIndex + 1 // initialize at big blind
this.stepIndex = this.lastBlindIndex + 1 // initialize at big blind
this.steps = HandStep.createSteps(this.handHistory)
}
data class Size(var width: Float, var height: Float)
data class Circle(var x: Float, var y: Float, var radius: Float) {
fun toRect(): RectF {
return RectF(x - radius, y - radius, x + radius, y + radius)
}
}
data class TextPoint(var x: Float, var y: Float, var fontSize: Float) {
fun toRect(): RectF {
val wRatio = 1.5f
return RectF(x - wRatio * fontSize, y - fontSize, x + wRatio * fontSize, y + fontSize * 0.1f)
}
}
data class Circle(var x: Float, var y: Float, var radius: Float)
data class TextPoint(var x: Float, var y: Float, var fontSize: Float)
private val maxCards = 5
@ -309,41 +300,64 @@ class ReplayerConfiguration(var handHistory: HandHistory) {
}
fun next() {
if (this.steps.size > this.currentStep + 1) {
this.currentStep += 1
if (this.steps.size > this.stepIndex + 1) {
this.stepIndex += 1
}
}
fun previous() {
if (this.currentStep > this.lastBlindIndex + 1) {
this.currentStep -= 1
if (this.stepIndex > this.lastBlindIndex + 1) {
this.stepIndex -= 1
}
}
val stepsToDraw: List<HandStep>
val currentStep: HandStep
get() {
return this.steps.take(this.currentStep + 1)
return this.steps[this.stepIndex]
}
val activePositions: List<Int>
// val stepsToDraw: List<HandStep>
// get() {
// return this.steps.take(this.stepIndex + 1)
// }
private val lastActionAtStep: ComputedAction?
get() {
val action = when (val step = this.steps[currentStep]) {
return when (val step = this.steps[stepIndex]) {
is ComputedAction -> {
step
}
is Street -> {
if (currentStep > 0) {
this.steps[currentStep - 1] as ComputedAction?
if (stepIndex > 0) {
this.steps[stepIndex - 1] as ComputedAction?
} else {
null
}
}
else -> throw PAIllegalStateException("unmanaged step: $step")
}
val index = action?.action?.index ?: 0
}
val activePositions: List<Int>
get() {
val index = this.lastActionAtStep?.action?.index ?: 0
return this.actionList.activePositionIndexes(index)
}
fun playerRemainingStack(i: Int): Double? {
this.lastActionAtStep?.action?.index?.let { index ->
return this.actionList.playerRemainingStack(i, index)
}
return null
}
fun lastSignificantActionOfPlayer(i: Int): ComputedAction? {
this.lastActionAtStep?.action?.index?.let { index ->
return this.actionList.lastChipCommittingActionOfPlayer(i, index)
}
return null
}
}

@ -4,10 +4,11 @@ import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.view.View
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.ui.modules.handhistory.model.ComputedAction
import timber.log.Timber
private data class ReplayerAction(val step: HandStep, val draw: Boolean)
class ReplayerView(context: Context, attrs: AttributeSet) : View(context, attrs) {
lateinit var configuration: ReplayerConfiguration
@ -24,21 +25,6 @@ class ReplayerView(context: Context, attrs: AttributeSet) : View(context, attrs)
this.invalidate()
}
// fun previous(handStep: HandStep) {
// val action = ReplayerAction(handStep, false)
// this.addAction(action)
// }
//
// fun next(handStep: HandStep) {
// val action = ReplayerAction(handStep, true)
// this.addAction(action)
// }
//
// private fun addAction(action: ReplayerAction) {
// this.actionsToDraw.add(action)
// this.invalidate()
// }
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
@ -46,17 +32,7 @@ class ReplayerView(context: Context, attrs: AttributeSet) : View(context, attrs)
canvas?.let {
TableDrawer.initializeTable(configuration, canvas, context)
// show cards
configuration.activePositions.forEach {
TableDrawer.drawCards(it, configuration, canvas, context)
}
// action
this.configuration.stepsToDraw.forEach { step ->
step.draw(this.configuration, canvas, context)
}
TableDrawer.drawTable(configuration, canvas, context)
}

@ -5,6 +5,7 @@ import android.graphics.*
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.handhistory.Position
import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.model.realm.handhistory.Action
@ -66,10 +67,78 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
cardTextPaint.isAntiAlias = true
}
fun drawTable(config: ReplayerConfiguration, canvas: Canvas, context: Context) {
// base
initializeTable(config, canvas, context)
val step = config.currentStep
val street: Street
var computedAction: ComputedAction? = null
when (step) {
is Street -> {
street = step
config.lastActionBeforeStreet(street)?.let {
drawPot(it, config, canvas, context)
}
}
is ComputedAction -> {
street = step.street
computedAction = step
drawPot(step, config, canvas, context)
}
else -> throw PAIllegalStateException("Step unmanaged: $step")
}
drawBoardCards(street, config, canvas, context)
val hh = config.handHistory
for (i in 0 until hh.numberOfPlayers) {
Timber.d("Getting player $i setup ")
// draw player rectangles with action or name + stack
val actionType = computedAction?.action?.type
if (computedAction?.positionIndex == i && actionType != null) {
drawPlayerRectangle(i, true, config, canvas, context)
drawAction(i, actionType, config, canvas, context)
} else {
val remainingStack = config.playerRemainingStack(i)
drawPlayerRectangle(i, false, config, canvas, context)
drawPositionAndStack(i, remainingStack, config, canvas, context)
}
// draw chips
// when does a chip appears ?
// when the player has put some money during the current street
config.lastSignificantActionOfPlayer(i)?.let { action ->
when {
action.action.type?.isSignificant == true -> {
action.action.amount?.let { amount ->
drawChip(amount, action.positionIndex, config, canvas, context)
}
}
action.action.type?.isCall == true -> {
action.getStreetLastSignificantAction()?.action?.amount?.let { amount ->
drawChip(amount, action.positionIndex, config, canvas, context)
}
}
else -> {}
}
}
}
// show player cards
config.activePositions.forEach {
drawCards(it, config, canvas, context)
}
}
/***
* WARNING: Avoid instancing objects here, as it's called from onDraw method
*/
fun initializeTable(config: ReplayerConfiguration, canvas: Canvas, context: Context) {
private fun initializeTable(config: ReplayerConfiguration, canvas: Canvas, context: Context) {
canvas.drawColor(context.getColor(backgroundColor))
@ -83,7 +152,7 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
// drawCards(i, config, canvas, context)
drawPlayerRectangle(i,false, config, canvas, context)
drawPositionAndStack(i, playerSetup?.stack, config, canvas, context)
// drawPositionAndStack(i, playerSetup?.stack, config, canvas, context)
drawPlayerCircle(i, config, canvas, context)
@ -121,8 +190,8 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
private fun drawChip(amount: Double, chipText: ReplayerConfiguration.TextPoint, chipCircle: ReplayerConfiguration.Circle, canvas: Canvas, context: Context) {
clearText(chipText, canvas)
clearCircle(chipCircle, canvas)
// clearText(chipText, canvas)
// clearCircle(chipCircle, canvas)
this.fillPaint.color = context.getColor(R.color.green)
canvas.drawCircle(chipCircle.x, chipCircle.y, chipCircle.radius, this.fillPaint)
@ -139,19 +208,19 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
}
private fun clearText(textPoint: ReplayerConfiguration.TextPoint, canvas: Canvas) {
this.clearRect(textPoint.toRect(), canvas)
}
private fun clearCircle(circle: ReplayerConfiguration.Circle, canvas: Canvas) {
this.clearRect(circle.toRect(), canvas)
}
private fun clearRect(rect: RectF, canvas: Canvas) {
canvas.drawRect(rect, this.backgroundPaint)
}
// private fun clearText(textPoint: ReplayerConfiguration.TextPoint, canvas: Canvas) {
// this.clearRect(textPoint.toRect(), canvas)
// }
//
// private fun clearCircle(circle: ReplayerConfiguration.Circle, canvas: Canvas) {
// this.clearRect(circle.toRect(), canvas)
// }
//
// private fun clearRect(rect: RectF, canvas: Canvas) {
// canvas.drawRect(rect, this.backgroundPaint)
// }
fun drawCards(playerIndex: Int, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
private fun drawCards(playerIndex: Int, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
val playerSetup = config.handHistory.playerSetupForPosition(playerIndex)
val cardRects = config.cardRects(playerIndex)
@ -195,12 +264,12 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
}
fun drawPlayerPositionAndStack(action: ComputedAction, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
private fun drawPlayerPositionAndStack(action: ComputedAction, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
drawPlayerRectangle(action.positionIndex,false, config, canvas, context)
drawPositionAndStack(action.positionIndex, action.stackAfterActing, config, canvas, context)
}
fun drawAction(action: ComputedAction, highlighted: Boolean = true, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
private fun drawAction(action: ComputedAction, highlighted: Boolean = true, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
// show that action is on the player by highlighting
drawPlayerRectangle(action.positionIndex, highlighted, config, canvas, context)
@ -265,7 +334,7 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
/***
* [i] is the player position in the hand
*/
private fun drawPlayerRectangle(i: Int, highlighted: Boolean, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
private fun drawPlayerRectangle(i: Int, highlighted: Boolean, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
val rect = config.stackRectForPlayer(i)
val rectRadius = (rect.bottom - rect.top) / 4
@ -306,7 +375,7 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
canvas.drawText(actionName, pnPoint.x, pnPoint.y, this.textPaint)
}
fun drawStreet(street: Street, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
private fun drawBoardCards(street: Street, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
val cards = config.handHistory.cardsForStreet(street)
config.boardCardRects.take(street.totalBoardCards).forEachIndexed { index, rectF ->
@ -314,18 +383,18 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
}
// Clear all chips
val hh = config.handHistory
for (i in 0 until hh.numberOfPlayers) {
val pc = config.chipCircle(i)
clearCircle(pc, canvas)
val pct = config.chipText(i)
clearText(pct, canvas)
}
// val hh = config.handHistory
// for (i in 0 until hh.numberOfPlayers) {
// val pc = config.chipCircle(i)
// clearCircle(pc, canvas)
// val pct = config.chipText(i)
// clearText(pct, canvas)
// }
// Clear last action before street
config.lastActionBeforeStreet(street)?.let { action ->
drawPlayerPositionAndStack(action, config, canvas, context)
}
// config.lastActionBeforeStreet(street)?.let { action ->
// drawPlayerPositionAndStack(action, config, canvas, context)
// }
}
@ -339,7 +408,7 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
this.textPaint.textSize = tpTextPoint.fontSize
this.textPaint.color = context.getColor(R.color.white)
clearText(config.totalPotTextPoint, canvas)
// clearText(config.totalPotTextPoint, canvas)
canvas.drawText(totalPot.formatted, config.totalPotTextPoint.x, config.totalPotTextPoint.y, this.textPaint)
}

Loading…
Cancel
Save