Fixes various export and reading issues

hh
Laurent 5 years ago
parent 91b17e6897
commit 8c4e297164
  1. 30
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/FrameManager.kt
  2. 8
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/HandStep.kt
  3. 122
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerAnimator.kt
  4. 12
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerFragment.kt
  5. 54
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt
  6. 13
      app/src/test/java/net/pokeranalytics/android/BasicUnitTest.kt

@ -1,17 +1,16 @@
package net.pokeranalytics.android.ui.modules.handhistory.replayer package net.pokeranalytics.android.ui.modules.handhistory.replayer
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import timber.log.Timber
enum class FrameType(val visualOccurences: Int) { enum class FrameType(val visualOccurences: Int) {
STATE(150), STATE(150),
GATHER_ANIMATION(4), GATHER_ANIMATION(2),
DISTRIBUTION_ANIMATION(4) DISTRIBUTION_ANIMATION(2)
} }
class FrameManager { class FrameManager {
data class FrameDescriptor(val type: FrameType, val count: Int, private val frameStart: Int) { data class FrameDescriptor(val type: FrameType, val count: Int, val frameStart: Int) {
var range: IntRange = frameStart until frameStart + count var range: IntRange = frameStart until frameStart + count
} }
@ -28,6 +27,8 @@ class FrameManager {
val totalFrames: Int val totalFrames: Int
get() { return this.totalAddedFrames } get() { return this.totalAddedFrames }
lateinit var currentDescriptor: FrameDescriptor
/*** /***
* Adds a frame descriptor with a frame [type] and a frame [count] * Adds a frame descriptor with a frame [type] and a frame [count]
*/ */
@ -40,18 +41,25 @@ class FrameManager {
/*** /***
* *
*/ */
fun frameType(frame: Int): FrameType { val currentFrameType: FrameType
this.descriptors.forEach { descriptor -> get() {
if (frame in descriptor.range) { return this.currentDescriptor.type
return descriptor.type
}
} }
throw PAIllegalStateException("frame $frame asked out of $totalAddedFrames defined frames, descriptor count = ${this.descriptors.size}")
}
fun reset() { fun reset() {
this.descriptors.clear() this.descriptors.clear()
this.totalAddedFrames = 0 this.totalAddedFrames = 0
} }
fun defineFrameDescriptor(frame: Int) {
for (descriptor in this.descriptors) {
if (frame in descriptor.range) {
this.currentDescriptor = descriptor
return
}
}
throw PAIllegalStateException("frame $frame asked out of $totalAddedFrames defined frames, descriptor count = ${this.descriptors.size}")
}
} }

@ -3,6 +3,7 @@ package net.pokeranalytics.android.ui.modules.handhistory.replayer
import android.content.Context import android.content.Context
import android.graphics.Canvas import android.graphics.Canvas
import net.pokeranalytics.android.model.handhistory.Street import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.model.realm.handhistory.Action
import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.modules.handhistory.model.ActionList import net.pokeranalytics.android.ui.modules.handhistory.model.ActionList
@ -33,9 +34,12 @@ interface HandStep {
val steps = mutableListOf<HandStep>() val steps = mutableListOf<HandStep>()
Street.values().forEach { street -> Street.values().forEach { street ->
steps.add(street) if (street != Street.PREFLOP) {
steps.add(street)
}
val streetActions = actionList.filter { it.street == street } // add the non-blind street actions
val streetActions = actionList.filter { it.street == street && it.action.type != Action.Type.POST_SB }
for (action in streetActions) { for (action in streetActions) {
steps.add(action) steps.add(action)
} }

@ -11,7 +11,6 @@ import net.pokeranalytics.android.ui.modules.handhistory.model.ActionList
import net.pokeranalytics.android.ui.modules.handhistory.model.ComputedAction import net.pokeranalytics.android.ui.modules.handhistory.model.ComputedAction
import net.pokeranalytics.android.util.MathUtils import net.pokeranalytics.android.util.MathUtils
import timber.log.Timber import timber.log.Timber
import kotlin.math.max
class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) { class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
@ -44,7 +43,8 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
is ComputedAction -> this.frameManager.add(FrameType.STATE, 1) is ComputedAction -> this.frameManager.add(FrameType.STATE, 1)
is Street -> { is Street -> {
// gather animation if chips have been committed in the street // gather animation if chips have been committed in the street
if (this.actionList.streetHasSignificantAction(step)) { val previousStreet = step.previous
if (previousStreet != null && this.actionList.streetHasSignificantAction(previousStreet)) {
this.frameManager.add(FrameType.GATHER_ANIMATION, framesForChipsAnimation) this.frameManager.add(FrameType.GATHER_ANIMATION, framesForChipsAnimation)
} }
// Chip distribution animation on the Summary // Chip distribution animation on the Summary
@ -64,57 +64,23 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
private val numberOfFramesForCurrentStep: Int private val numberOfFramesForCurrentStep: Int
get() { get() {
return this.frameManager.totalFrames return this.frameManager.totalFrames
// return when (val step = this.currentStep) {
// is ComputedAction -> 1
// is Street -> {
// var frames = 1
// // gather animation if chips have been committed in the street
// if (this.actionList.streetHasSignificantAction(step)) {
// frames += framesForChipsAnimation
// }
// // Chip distribution animation on the Summary
// if (step == Street.SUMMARY) {
// frames += framesForChipsAnimation
// }
// frames
// }
//
//
//// Street.SUMMARY -> 1 + 2 * framesForChipsAnimation // 2 animations
//// is Street -> 1 + framesForChipsAnimation
// else -> throw PAIllegalStateException("unmanaged step: $step")
// }
} }
/*** /***
* The index of the current frame * The index of the current frame
*/ */
private var currentFrame = 0 private var currentFrameIndex = 0
set(value) {
field = value
this.frameManager.defineFrameDescriptor(value)
}
/*** /***
* The frame type for the current combination of step + frame index * The frame type for the current combination of step + frame index
*/ */
val frameType: FrameType val frameType: FrameType
get() { get() {
return this.frameManager.frameType(this.currentFrame) return this.frameManager.currentFrameType
// return when (val step = this.currentStep) {
// is ComputedAction -> FrameType.STATE
// Street.SUMMARY -> {
// when (this.currentFrame) {
// in (0 until framesForChipsAnimation) -> FrameType.GATHER_ANIMATION
// in (framesForChipsAnimation until 2 * framesForChipsAnimation) -> FrameType.DISTRIBUTION_ANIMATION
// else -> FrameType.STATE
// }
// }
// is Street -> {
// when (this.currentFrame) {
// in (0 until framesForChipsAnimation) -> FrameType.GATHER_ANIMATION
// else -> FrameType.STATE
// }
// }
// else -> throw PAIllegalStateException("unmanaged step: $step")
// }
} }
/*** /***
@ -124,8 +90,8 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
*/ */
private val visualOccurences: Int private val visualOccurences: Int
get() { get() {
return if (this.currentStepIndex == this.steps.size - 1 && this.currentFrame == this.numberOfFramesForCurrentStep - 1) { return if (this.currentStepIndex == this.steps.size - 1 && this.currentFrameIndex == this.numberOfFramesForCurrentStep - 1) {
FrameType.STATE.visualOccurences * 5 FrameType.STATE.visualOccurences * 3
} else { } else {
this.frameType.visualOccurences this.frameType.visualOccurences
} }
@ -144,13 +110,13 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
*/ */
val shouldShowAdditionalFrame: Boolean val shouldShowAdditionalFrame: Boolean
get() { get() {
return this.currentFrame < this.numberOfFramesForCurrentStep - 1 return this.currentFrameIndex < this.numberOfFramesForCurrentStep
} }
/*** /***
* The list of actions associated with the hand history * The list of actions associated with the hand history
*/ */
var actionList: ActionList = ActionList(null) var actionList: ActionList = ActionList()
private set private set
/*** /***
@ -161,7 +127,7 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
/*** /***
* The index of the last blind in the action list * The index of the last blind in the action list
*/ */
private var lastBlindIndex: Int = 0 // private var lastBlindIndex: Int = 0
private var currentStepIndex: Int = 0 private var currentStepIndex: Int = 0
set(value) { set(value) {
@ -169,8 +135,8 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
field = value field = value
defineFramesForCurrentStep() defineFramesForCurrentStep()
// if we go backwards we don't want to perform an animation, otherwise we want // if we go backwards we don't want to perform an animation, otherwise we do want it
this.currentFrame = if (backwards) this.numberOfFramesForCurrentStep - 1 else 0 this.currentFrameIndex = if (backwards) this.numberOfFramesForCurrentStep - 1 else 0
} }
val currentStep: HandStep val currentStep: HandStep
@ -182,31 +148,31 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
loadHandHistory(this.handHistory) loadHandHistory(this.handHistory)
} }
fun loadHandHistory(handHistory: HandHistory) { private fun loadHandHistory(handHistory: HandHistory) {
this.actionList.load(handHistory) this.actionList.load(handHistory)
this.steps = HandStep.createSteps(handHistory) this.steps = HandStep.createSteps(handHistory)
defineFramesForCurrentStep()
val bi = this.steps.indexOfLast { it is ComputedAction && it.action.type?.isBlind == true }
this.lastBlindIndex = max(bi, 0) // in case indexOfLast returns -1
this.currentStepIndex = this.lastBlindIndex // initialize at big blind
} }
/*** /***
* Let the animator know when a frame has been drawn * Let the animator know when a frame has been drawn
*/ */
fun frameDrawn() { fun frameDrawn() {
if (this.currentFrame < this.numberOfFramesForCurrentStep - 1) { // Timber.d("a>frameDrawn: ${this.currentFrameIndex}, total: ${this.numberOfFramesForCurrentStep}")
this.currentFrame += 1 if (this.currentFrameIndex < this.numberOfFramesForCurrentStep - 1) {
this.currentFrameIndex += 1
} }
// Timber.d("b>frameDrawn: ${this.currentFrameIndex}")
} }
/*** /***
* Reset the step and the frame to the start of the hand * Reset the step and the frame to the start of the hand
*/ */
fun restart() { fun restart() {
this.currentStepIndex = this.lastBlindIndex this.currentStepIndex = 0
this.currentFrame = 0 this.currentFrameIndex = 0
} }
// Dimensions // Dimensions
@ -355,7 +321,7 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
val prp = line.intersects(pRect) ?: throw PAIllegalStateException("should not happen") val prp = line.intersects(pRect) ?: throw PAIllegalStateException("should not happen")
val boxToCenterLine = MathUtils.Line(prp.x, prp.y, tableRect.centerX(), tableRect.centerY()) val boxToCenterLine = MathUtils.Line(prp.x, prp.y, tableRect.centerX(), tableRect.centerY())
val boxToChipDistance = if (bottomOriented) 3 * chipRadius else 2 * chipRadius // because the chip text needs space val boxToChipDistance = if (bottomOriented) 3.3f * chipRadius else 2 * chipRadius // because the chip text needs space
val chipPoint = boxToCenterLine.pointForDistance(boxToChipDistance) val chipPoint = boxToCenterLine.pointForDistance(boxToChipDistance)
this.chipCircles.add(Circle(chipPoint.x, chipPoint.y, chipRadius)) this.chipCircles.add(Circle(chipPoint.x, chipPoint.y, chipRadius))
@ -584,7 +550,7 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
} }
fun previousStep() { fun previousStep() {
if (this.currentStepIndex > this.lastBlindIndex + 1) { if (this.currentStepIndex > 1) {
this.currentStepIndex -= 1 this.currentStepIndex -= 1
} }
} }
@ -636,7 +602,9 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
} }
private fun animatedChipCircle(origin: Circle, destination: Circle): Circle { private fun animatedChipCircle(origin: Circle, destination: Circle): Circle {
val completion = (this.currentFrame + 1).toFloat() / this.numberOfFramesForCurrentStep.toFloat() val fd = this.frameManager.currentDescriptor
val currentAnimationFrameIndex = this.currentFrameIndex - fd.frameStart + 1
val completion = currentAnimationFrameIndex.toFloat() / fd.count.toFloat()
val x = origin.x + (destination.x - origin.x) * completion val x = origin.x + (destination.x - origin.x) * completion
val y = origin.y + (destination.y - origin.y) * completion val y = origin.y + (destination.y - origin.y) * completion
@ -659,23 +627,45 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
*/ */
fun frames(context: Context, frameHandler: (Bitmap, Int) -> Unit) { fun frames(context: Context, frameHandler: (Bitmap, Int) -> Unit) {
while (this.hasMoreSteps) { Timber.d("Step count = ${this.steps.size}")
// The first steps are blinds and we don't animate them
(this.currentStepIndex until this.steps.size).forEach {
while (this.shouldShowAdditionalFrame) { // Timber.d("STEP [$index] >> ($handStep): Frame count = ${this.frameManager.totalFrames}")
(0 until this.frameManager.totalFrames).forEach { f ->
Timber.d("FRAME [$f] >> step: $currentStepIndex, frame: $currentFrameIndex")
val bitmap = Bitmap.createBitmap(this.width.toInt(), this.height.toInt(), Bitmap.Config.ARGB_8888) val bitmap = Bitmap.createBitmap(this.width.toInt(), this.height.toInt(), Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap) val canvas = Canvas(bitmap)
TableDrawer.drawTable(this, canvas, context) TableDrawer.drawTable(this, canvas, context)
Timber.d("frame drawn at step: $currentStepIndex, frame: $currentFrame")
frameHandler(bitmap, this.visualOccurences) frameHandler(bitmap, this.visualOccurences)
// frameDrawn()
} }
nextStep() nextStep()
} }
// do {
//
// do {
//
// val bitmap = Bitmap.createBitmap(this.width.toInt(), this.height.toInt(), Bitmap.Config.ARGB_8888)
// val canvas = Canvas(bitmap)
// TableDrawer.drawTable(this, canvas, context)
//
// Timber.d("frame drawn at step: $currentStepIndex, frame: $currentFrame")
// frameHandler(bitmap, this.visualOccurences)
//
// } while (this.shouldShowAdditionalFrame)
//
// nextStep()
//
// } while (this.hasMoreSteps)
} }
/*** /***
@ -683,7 +673,7 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
*/ */
val isReplayFinished: Boolean val isReplayFinished: Boolean
get() { get() {
return this.currentStepIndex >= this.steps.size - 1 && this.currentFrame >= this.numberOfFramesForCurrentStep - 1 return this.currentStepIndex >= this.steps.size - 1 && this.currentFrameIndex >= this.numberOfFramesForCurrentStep - 1
} }
} }

@ -169,6 +169,12 @@ class ReplayerFragment : RealmFragment() {
refreshPlayButtonIfNecessary() refreshPlayButtonIfNecessary()
} }
private fun previousAction() {
this.model.previousStep()
this.replayer.refresh()
refreshPlayButtonIfNecessary()
}
private fun refreshPlayButtonIfNecessary() { private fun refreshPlayButtonIfNecessary() {
val isFinished = this.model.animator?.isReplayFinished ?: true val isFinished = this.model.animator?.isReplayFinished ?: true
@ -178,12 +184,6 @@ class ReplayerFragment : RealmFragment() {
} }
private fun previousAction() {
this.model.previousStep()
this.replayer.refresh()
refreshPlayButtonIfNecessary()
}
private fun nextHand() { private fun nextHand() {
val hands = getRealm().where(HandHistory::class.java).sort("date", Sort.DESCENDING).findAll() val hands = getRealm().where(HandHistory::class.java).sort("date", Sort.DESCENDING).findAll()
val index = hands.indexOfFirst { it.id == this.model.animator?.handHistory?.id } val index = hands.indexOfFirst { it.id == this.model.animator?.handHistory?.id }

@ -12,32 +12,6 @@ import net.pokeranalytics.android.ui.modules.handhistory.model.ComputedAction
import net.pokeranalytics.android.util.RANDOM_PLAYER import net.pokeranalytics.android.util.RANDOM_PLAYER
import net.pokeranalytics.android.util.extensions.formatted import net.pokeranalytics.android.util.extensions.formatted
data class ChipColor(val fillColor: Int, val borderColor: Int) {
companion object {
val all: List<ChipColor> by lazy {
listOf(
ChipColor(R.color.white, R.color.grey),
ChipColor(R.color.kaki_light, R.color.white_dark),
ChipColor(R.color.green, R.color.white),
ChipColor(R.color.player_color_2, R.color.chip_dash_color_2),
ChipColor(R.color.player_color_3, R.color.chip_dash_color_3),
ChipColor(R.color.player_color_9, R.color.chip_dash_color_9),
ChipColor(R.color.player_color_5, R.color.chip_dash_color_5),
ChipColor(R.color.player_color_7, R.color.chip_dash_color_7),
ChipColor(R.color.player_color_6, R.color.chip_dash_color_6),
ChipColor(R.color.player_color_8, R.color.chip_dash_color_8),
ChipColor(R.color.player_color_4, R.color.chip_dash_color_4),
ChipColor(R.color.chip_dash_color_7, R.color.player_color_2),
ChipColor(R.color.chip_dash_color_4, R.color.player_color_3),
ChipColor(R.color.player_color_6, R.color.player_color_9),
ChipColor(R.color.player_color_8, R.color.player_color_2),
ChipColor(R.color.chip_dash_color_7, R.color.player_color_4)
)
}
}
}
class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) { class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
companion object { companion object {
@ -478,4 +452,30 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
} }
} }
private data class ChipColor(val fillColor: Int, val borderColor: Int) {
companion object {
val all: List<ChipColor> by lazy {
listOf(
ChipColor(R.color.white, R.color.grey),
ChipColor(R.color.kaki_light, R.color.white_dark),
ChipColor(R.color.green, R.color.white),
ChipColor(R.color.player_color_2, R.color.chip_dash_color_2),
ChipColor(R.color.player_color_3, R.color.chip_dash_color_3),
ChipColor(R.color.player_color_9, R.color.chip_dash_color_9),
ChipColor(R.color.player_color_5, R.color.chip_dash_color_5),
ChipColor(R.color.player_color_7, R.color.chip_dash_color_7),
ChipColor(R.color.player_color_6, R.color.chip_dash_color_6),
ChipColor(R.color.player_color_8, R.color.chip_dash_color_8),
ChipColor(R.color.player_color_4, R.color.chip_dash_color_4),
ChipColor(R.color.chip_dash_color_7, R.color.player_color_2),
ChipColor(R.color.chip_dash_color_4, R.color.player_color_3),
ChipColor(R.color.player_color_6, R.color.player_color_9),
ChipColor(R.color.player_color_8, R.color.player_color_2),
ChipColor(R.color.chip_dash_color_7, R.color.player_color_4)
)
}
}
}

@ -79,4 +79,17 @@ class BasicUnitTest : RealmUnitTest() {
Assert.assertEquals(42, v) Assert.assertEquals(42, v)
} }
@Test
fun testDoWhile() {
var h = 0
var i = 0
do {
h++
} while (i < 0)
Assert.assertEquals(1, h)
}
} }

Loading…
Cancel
Save