Frame and animation refactoring

hh
Laurent 5 years ago
parent 1e9d726f23
commit c3f930e339
  1. 8
      app/src/main/java/net/pokeranalytics/android/model/handhistory/Street.kt
  2. 14
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt
  3. 59
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/FrameManager.kt
  4. 101
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerAnimator.kt
  5. 8
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt

@ -41,6 +41,14 @@ enum class Street : HandStep {
return values()[this.ordinal + 1] return values()[this.ordinal + 1]
} }
val previous: Street?
get() {
return when (this) {
PREFLOP -> null
else -> values()[this.ordinal - 1]
}
}
// override fun draw(configuration: ReplayerConfiguration, canvas: Canvas, context: Context) { // override fun draw(configuration: ReplayerConfiguration, canvas: Canvas, context: Context) {
// TableDrawer.drawStreet(this, configuration, canvas, context) // TableDrawer.drawStreet(this, configuration, canvas, context)
// } // }

@ -309,13 +309,6 @@ class ActionList(var listener: ActionListListener? = null) : ArrayList<ComputedA
return this.last { it.street == street }.action.index return this.last { it.street == street }.action.index
} }
/***
* Returns the last action index of the [street]
*/
fun lastActionIndexBeforeStreet(street: Street): Int {
return this.last { it.street == street }.action.index
}
/*** /***
* Returns the list of empty actions before the action at the given [index] * Returns the list of empty actions before the action at the given [index]
*/ */
@ -332,6 +325,13 @@ class ActionList(var listener: ActionListListener? = null) : ArrayList<ComputedA
return previousActions.lastOrNull { it.action.isActionSignificant } return previousActions.lastOrNull { it.action.isActionSignificant }
} }
/***
* Returns true if the [street] contains a significant action
*/
fun streetHasSignificantAction(street: Street): Boolean {
return this.filter { it.street == street }.any { it.action.isActionSignificant }
}
/*** /***
* Check if some positions are still required to play, * Check if some positions are still required to play,
* and adds new actions if none exists after [index] * and adds new actions if none exists after [index]

@ -0,0 +1,59 @@
package net.pokeranalytics.android.ui.modules.handhistory.replayer
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import timber.log.Timber
enum class FrameType(val visualOccurences: Int) {
STATE(150),
GATHER_ANIMATION(4),
DISTRIBUTION_ANIMATION(4)
}
class FrameManager {
data class FrameDescriptor(val type: FrameType, val count: Int, private val frameStart: Int) {
var range: IntRange = frameStart until frameStart + count
}
/***
* The list of frame descriptors
*/
private val descriptors = mutableListOf<FrameDescriptor>()
/***
* The total number of added frames in the descriptors
*/
private var totalAddedFrames: Int = 0
val totalFrames: Int
get() { return this.totalAddedFrames }
/***
* Adds a frame descriptor with a frame [type] and a frame [count]
*/
fun add(type: FrameType, count: Int) {
val fd = FrameDescriptor(type, count, this.totalAddedFrames)
this.descriptors.add(fd)
this.totalAddedFrames += count
}
/***
*
*/
fun frameType(frame: Int): FrameType {
this.descriptors.forEach { descriptor ->
if (frame in descriptor.range) {
return descriptor.type
}
}
throw PAIllegalStateException("frame $frame asked out of $totalAddedFrames defined frames, descriptor count = ${this.descriptors.size}")
}
fun reset() {
this.descriptors.clear()
this.totalAddedFrames = 0
}
}

@ -12,18 +12,11 @@ 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 import kotlin.math.max
import kotlin.math.min
class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) { class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
// Steps & Frames // Steps & Frames
enum class FrameType(val visualOccurences: Int) {
STATE(150),
GATHER_ANIMATION(4),
DISTRIBUTION_ANIMATION(4)
}
/*** /***
* The number of frames per second * The number of frames per second
*/ */
@ -42,17 +35,55 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
private val framesForChipsAnimation: Int private val framesForChipsAnimation: Int
get() { return (chipAnimationDuration / animationRate).toInt() } get() { return (chipAnimationDuration / animationRate).toInt() }
private var frameManager = FrameManager()
private fun defineFramesForCurrentStep() {
this.frameManager.reset()
when (val step = this.currentStep) {
is ComputedAction -> this.frameManager.add(FrameType.STATE, 1)
is Street -> {
// gather animation if chips have been committed in the street
if (this.actionList.streetHasSignificantAction(step)) {
this.frameManager.add(FrameType.GATHER_ANIMATION, framesForChipsAnimation)
}
// Chip distribution animation on the Summary
if (step == Street.SUMMARY) {
this.frameManager.add(FrameType.DISTRIBUTION_ANIMATION, framesForChipsAnimation)
}
this.frameManager.add(FrameType.STATE, 1)
}
else -> throw PAIllegalStateException("unmanaged step: $step")
}
}
/*** /***
* The total number of frames for each kind of step * The total number of frames for each kind of step
*/ */
private val numberOfFramesForCurrentStep: Int private val numberOfFramesForCurrentStep: Int
get() { get() {
return when (val step = this.currentStep) { return this.frameManager.totalFrames
is ComputedAction -> 1 // return when (val step = this.currentStep) {
Street.SUMMARY -> 1 + 2 * framesForChipsAnimation // 2 animations // is ComputedAction -> 1
is Street -> 1 + framesForChipsAnimation // is Street -> {
else -> throw PAIllegalStateException("unmanaged step: $step") // 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")
// }
} }
/*** /***
@ -65,29 +96,36 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
*/ */
val frameType: FrameType val frameType: FrameType
get() { get() {
return when (val step = this.currentStep) { return this.frameManager.frameType(this.currentFrame)
is ComputedAction -> FrameType.STATE
Street.SUMMARY -> { // return when (val step = this.currentStep) {
when (this.currentFrame) { // is ComputedAction -> FrameType.STATE
in (0 until framesForChipsAnimation) -> FrameType.GATHER_ANIMATION // Street.SUMMARY -> {
in (framesForChipsAnimation until 2 * framesForChipsAnimation) -> FrameType.DISTRIBUTION_ANIMATION // when (this.currentFrame) {
else -> FrameType.STATE // 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 // is Street -> {
else -> FrameType.STATE // when (this.currentFrame) {
} // in (0 until framesForChipsAnimation) -> FrameType.GATHER_ANIMATION
} // else -> FrameType.STATE
else -> throw PAIllegalStateException("unmanaged step: $step") // }
} // }
// else -> throw PAIllegalStateException("unmanaged step: $step")
// }
} }
/***
* Returns the number of visual occurrences for the current frame
* This function returns a longer value for the last frame of the last step
* because some player auto-replay videos because we want the viewer to have a pause.
*/
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.currentFrame == this.numberOfFramesForCurrentStep - 1) {
FrameType.STATE.visualOccurences * 4 FrameType.STATE.visualOccurences * 5
} else { } else {
this.frameType.visualOccurences this.frameType.visualOccurences
} }
@ -122,6 +160,7 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) {
val backwards = value < field val backwards = value < field
field = value field = value
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 want
this.currentFrame = if (backwards) this.numberOfFramesForCurrentStep - 1 else 0 this.currentFrame = if (backwards) this.numberOfFramesForCurrentStep - 1 else 0
} }

@ -159,7 +159,7 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
when (animator.currentStep) { when (animator.currentStep) {
is Street -> { is Street -> {
when (animator.frameType) { when (animator.frameType) {
ReplayerAnimator.FrameType.STATE -> { FrameType.STATE -> {
if (animator.currentStep == Street.SUMMARY) { if (animator.currentStep == Street.SUMMARY) {
val winnerPots = animator.handHistory.winnerPots.firstOrNull { it.position == i } val winnerPots = animator.handHistory.winnerPots.firstOrNull { it.position == i }
@ -172,14 +172,14 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
} }
} }
ReplayerAnimator.FrameType.GATHER_ANIMATION -> { FrameType.GATHER_ANIMATION -> {
lastCommittedAmount(i, animator)?.let { amount -> lastCommittedAmount(i, animator)?.let { amount ->
val color = colorForAmount(amount) val color = colorForAmount(amount)
val circle = animator.animatedChipCircleToPot(i) val circle = animator.animatedChipCircleToPot(i)
drawChipCircle(circle, color, canvas, context) drawChipCircle(circle, color, canvas, context)
} }
} }
ReplayerAnimator.FrameType.DISTRIBUTION_ANIMATION -> { FrameType.DISTRIBUTION_ANIMATION -> {
val winnerPots = animator.handHistory.winnerPots.firstOrNull { it.position == i } val winnerPots = animator.handHistory.winnerPots.firstOrNull { it.position == i }
winnerPots?.let { pot -> winnerPots?.let { pot ->
@ -454,7 +454,7 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
private fun drawPot(street: Street, computedAction: ComputedAction?, animator: ReplayerAnimator, canvas: Canvas, context: Context) { private fun drawPot(street: Street, computedAction: ComputedAction?, animator: ReplayerAnimator, canvas: Canvas, context: Context) {
if (street == Street.SUMMARY && animator.frameType != ReplayerAnimator.FrameType.GATHER_ANIMATION) { if (street == Street.SUMMARY && animator.frameType != FrameType.GATHER_ANIMATION) {
return return
} }

Loading…
Cancel
Save