Toolbar improvement + buttons logic

hh
Laurent 5 years ago
parent c32d0cf402
commit d62285a16e
  1. 5
      app/src/main/java/net/pokeranalytics/android/model/handhistory/Street.kt
  2. 8
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt
  3. 4
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt
  4. 4
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/HandHistoryViewModel.kt
  5. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/HandStep.kt
  6. 10
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerConfiguration.kt
  7. 90
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerFragment.kt
  8. 51
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerModel.kt
  9. 38
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerView.kt
  10. 15
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt
  11. 9
      app/src/main/res/drawable/ic_fast_forward_white.xml
  12. 9
      app/src/main/res/drawable/ic_fast_rewind_white.xml
  13. 9
      app/src/main/res/drawable/ic_play_arrow.xml
  14. 9
      app/src/main/res/drawable/ic_skip_next_white.xml
  15. 9
      app/src/main/res/drawable/ic_skip_previous_white.xml
  16. 113
      app/src/main/res/layout/fragment_replayer.xml
  17. 35
      app/src/main/res/menu/toolbar_replayer.xml
  18. 2
      app/src/main/res/values/strings.xml

@ -2,6 +2,7 @@ package net.pokeranalytics.android.model.handhistory
import android.content.Context import android.content.Context
import android.graphics.Canvas import android.graphics.Canvas
import io.realm.internal.Table
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.modules.handhistory.replayer.HandStep 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.ReplayerConfiguration
@ -44,6 +45,10 @@ enum class Street : HandStep {
TableDrawer.drawStreet(this, configuration, canvas, context) TableDrawer.drawStreet(this, configuration, canvas, context)
} }
override fun undo(configuration: ReplayerConfiguration, canvas: Canvas, context: Context) {
TableDrawer.undoStreet(this, configuration, canvas, context)
}
override fun frames( override fun frames(
configuration: ReplayerConfiguration, configuration: ReplayerConfiguration,
canvas: Canvas, canvas: Canvas,

@ -681,4 +681,12 @@ class ActionList(var listener: ActionListListener? = null) : ArrayList<ComputedA
return firstStreetAction?.stackBeforeActing return firstStreetAction?.stackBeforeActing
} }
/***
* Removes blinds for the list,
* used for the replayer/video export
*/
fun removeBlinds() {
this.dropLastWhile { this.firstOrNull()?.action?.type?.isBlind == true }
}
} }

@ -312,6 +312,10 @@ class ComputedAction(var manager: ActionManager,
TableDrawer.drawAction(this, true, configuration, canvas, context) TableDrawer.drawAction(this, true, configuration, canvas, context)
} }
override fun undo(configuration: ReplayerConfiguration, canvas: Canvas, context: Context) {
TableDrawer.undoAction(this, true, configuration, canvas, context)
}
override fun frames( override fun frames(
configuration: ReplayerConfiguration, configuration: ReplayerConfiguration,
canvas: Canvas, canvas: Canvas,

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

@ -11,6 +11,7 @@ interface HandStep {
fun frames(configuration: ReplayerConfiguration, canvas: Canvas, context: Context, update: () -> (Unit)) 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)
fun undo(configuration: ReplayerConfiguration, canvas: Canvas, context: Context)
companion object { companion object {
@ -18,6 +19,7 @@ interface HandStep {
val actionList = ActionList() val actionList = ActionList()
actionList.load(handHistory) actionList.load(handHistory)
actionList.removeBlinds()
val steps = mutableListOf<HandStep>() val steps = mutableListOf<HandStep>()
Street.values().forEach { street -> Street.values().forEach { street ->

@ -4,15 +4,25 @@ import android.graphics.RectF
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
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
import net.pokeranalytics.android.ui.modules.handhistory.model.ComputedAction
import timber.log.Timber import timber.log.Timber
class ReplayerConfiguration(var handHistory: HandHistory) { class ReplayerConfiguration(var handHistory: HandHistory) {
var initialActions: List<ComputedAction>
var actionList: ActionList = ActionList(null) var actionList: ActionList = ActionList(null)
private set private set
var steps: List<HandStep>
init { init {
this.actionList.load(this.handHistory) this.actionList.load(this.handHistory)
this.initialActions = actionList.filter { it.action.type?.isBlind == true }
this.steps = HandStep.createSteps(this.handHistory)
} }
data class Size(var width: Float, var height: Float) data class Size(var width: Float, var height: Float)

@ -10,21 +10,15 @@ import androidx.lifecycle.ViewModelProviders
import kotlinx.android.synthetic.main.fragment_replayer.* import kotlinx.android.synthetic.main.fragment_replayer.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.fragment.components.BaseFragment
import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.modules.handhistory.model.HandHistoryViewModel import net.pokeranalytics.android.ui.modules.handhistory.model.HandHistoryViewModel
import timber.log.Timber
class ReplayerFragment : RealmFragment() { class ReplayerFragment : RealmFragment() {
/*** /***
* The fragment's ViewModel * The fragment's ViewModel
*/ */
private lateinit var model: HandHistoryViewModel private lateinit var model: ReplayerModel
private var steps: List<HandStep> = listOf()
// private lateinit var configuration: ReplayerConfiguration
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
@ -41,7 +35,7 @@ class ReplayerFragment : RealmFragment() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
this.model = activity?.run { this.model = activity?.run {
ViewModelProviders.of(this)[HandHistoryViewModel::class.java] ViewModelProviders.of(this)[ReplayerModel::class.java]
} ?: throw Exception("Invalid Activity") } ?: throw Exception("Invalid Activity")
} }
@ -50,73 +44,91 @@ class ReplayerFragment : RealmFragment() {
// TODO change // TODO change
val hh = getRealm().where(HandHistory::class.java).findFirst()!! val hh = getRealm().where(HandHistory::class.java).findFirst()!!
Timber.d(">>> Load HH with player count = ${hh.numberOfPlayers}") // Timber.d(">>> Load HH with player count = ${hh.numberOfPlayers}")
this.model.setHandHistory(hh) // this.model.setHandHistory(hh)
loadHand(this.model.handHistory) val hhm = ViewModelProviders.of(this)[HandHistoryViewModel::class.java]
loadHand(hh)
} }
private fun initUI() { private fun initUI() {
this.next_action.setOnClickListener {
nextAction()
}
this.previous_action.setOnClickListener {
previousAction()
}
this.next_hand.setOnClickListener {
nextHand()
}
this.previous_hand.setOnClickListener {
previousHand()
}
this.play_pause.setOnClickListener {
playOrPause()
}
this.speed.setOnClickListener {
changeSpeed()
}
updateSpeedButtonText()
} }
private fun loadHand(handHistory: HandHistory) { private fun updateSpeedButtonText() {
this.steps = HandStep.createSteps(handHistory) this.speed.text = "${this.model.speedMultiplier}x"
this.replayer.configuration = ReplayerConfiguration(handHistory)
} }
var isPlaying: Boolean = false private fun loadHand(handHistory: HandHistory) {
val config = ReplayerConfiguration(handHistory)
val mainHandler = Handler(Looper.getMainLooper()) this.replayer.configuration = config
this.model.configuration = config
}
val actionSpeed = 1000L private val mainHandler = Handler(Looper.getMainLooper())
var speedMultiplier = 1
private val timerRunnable: Runnable = Runnable { private val timerRunnable: Runnable = Runnable {
nextAction() nextAction()
} }
fun playOrPause() { private fun playOrPause() {
if (this.isPlaying) { if (this.model.isPlaying) {
mainHandler.removeCallbacks(timerRunnable) mainHandler.removeCallbacks(timerRunnable)
} else { } else {
mainHandler.postDelayed(timerRunnable, 0L) mainHandler.postDelayed(timerRunnable, 0L)
} }
this.isPlaying = !this.isPlaying this.model.isPlaying = !this.model.isPlaying
} }
private var stepIndex: Int = 0 private fun nextAction() {
fun nextAction() { this.model.next?.let {
if (this.stepIndex < this.steps.size - 1) { this.replayer.next(it)
this.stepIndex += 1
playAction()
} }
if (this.isPlaying) {
mainHandler.postDelayed(timerRunnable, speedMultiplier * actionSpeed) if (this.model.isPlaying) {
mainHandler.postDelayed(timerRunnable, this.model.actionDelay)
} }
} }
fun previousAction() { private fun previousAction() {
if (this.stepIndex > 0) { this.model.previous?.let {
this.stepIndex -= 1 this.replayer.previous(it)
playAction()
} }
} }
fun playAction() {
this.replayer.step = this.steps[this.stepIndex]
this.replayer.invalidate() // force redraw
}
fun nextHand() { private fun nextHand() {
} }
fun previousHand() { private fun previousHand() {
} }
private fun changeSpeed() {
this.model.changeSpeed()
updateSpeedButtonText()
}
} }

@ -0,0 +1,51 @@
package net.pokeranalytics.android.ui.modules.handhistory.replayer
import androidx.lifecycle.ViewModel
class ReplayerModel : ViewModel() {
var configuration: ReplayerConfiguration? = null
var isPlaying: Boolean = false
val actionSpeed = 1000L
var speedMultiplier = 1.0
private set
private var stepIndex: Int = 0
val previous: HandStep?
get() {
this.configuration?.steps?.let { steps ->
if (this.stepIndex > 1) {
this.stepIndex -= 1
return steps[this.stepIndex]
}
}
return null
}
val next: HandStep?
get() {
this.configuration?.steps?.let { steps ->
if (steps.size > this.stepIndex + 1) {
this.stepIndex += 1
return steps[this.stepIndex]
}
}
return null
}
val actionDelay: Long
get() { return (speedMultiplier * actionSpeed).toLong() }
fun changeSpeed() {
this.speedMultiplier = when (speedMultiplier) {
1.0 -> 1.5
1.5 -> 2.0
else -> 1.0
}
}
}

@ -2,17 +2,16 @@ 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 android.graphics.RectF
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.View
import timber.log.Timber
private data class ReplayerAction(val step: HandStep, val draw: Boolean)
class ReplayerView(context: Context, attrs: AttributeSet) : View(context, attrs) { class ReplayerView(context: Context, attrs: AttributeSet) : View(context, attrs) {
var step: HandStep? = null private var actionsToDraw = mutableListOf<ReplayerAction>()
lateinit var configuration: ReplayerConfiguration
var rect = RectF() lateinit var configuration: ReplayerConfiguration
init { init {
@ -22,20 +21,35 @@ class ReplayerView(context: Context, attrs: AttributeSet) : View(context, attrs)
} }
} }
override fun onDraw(canvas: Canvas?) { fun previous(handStep: HandStep) {
super.onDraw(canvas) val action = ReplayerAction(handStep, false)
Timber.d("ReplayerView > onDraw, rect = $rect") this.addAction(action)
}
fun next(handStep: HandStep) {
val action = ReplayerAction(handStep, true)
this.addAction(action)
}
// canvas?.drawCircle(100f, 100f, 50f, paint) private fun addAction(action: ReplayerAction) {
this.actionsToDraw.add(action)
this.invalidate()
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas?.let { canvas?.let {
this.actionsToDraw.dropWhile { action ->
// Timber.d("ReplayerView > onDraw with canvas: ${canvas.width}, ${canvas.height}") if (action.draw) {
TableDrawer.initializeTable(this.configuration, canvas, context) action.step.draw(this.configuration, canvas, context)
} else {
action.step.undo(this.configuration, canvas, context)
}
this.step?.draw(this.configuration, canvas, context) this.actionsToDraw.isNotEmpty()
}
} }
} }

@ -93,14 +93,14 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
// val chipText = config.chipText(i) // val chipText = config.chipText(i)
// drawChip(2000.0, chipText, chipCircle, canvas, context) // drawChip(2000.0, chipText, chipCircle, canvas, context)
drawStreet(Street.RIVER, config, canvas, context) // drawStreet(Street.RIVER, config, canvas, context)
// drawPot(100.0, 200.0, config, canvas, context) // drawPot(100.0, 200.0, config, canvas, context)
} }
val blinds = config.actionList.filter { it.action.type?.isBlind ?: false } // val blinds = config.actionList.filter { it.action.type?.isBlind ?: false }
blinds.forEach { action -> config.initialActions.forEach { action ->
action.action.amount?.let { amount -> action.action.amount?.let { amount ->
drawChip(amount, action.positionIndex, config, canvas, context) drawChip(amount, action.positionIndex, config, canvas, context)
} }
@ -110,7 +110,6 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
drawPot(pot, totalPot, config, canvas, context) drawPot(pot, totalPot, config, canvas, context)
// drawAction(action, false, config, canvas, context) // drawAction(action, false, config, canvas, context)
} }
@ -311,6 +310,14 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) {
} }
fun undoAction(computedAction: ComputedAction, highlighted: Boolean, configuration: ReplayerConfiguration, canvas: Canvas, context: Context) {
// TODO
}
fun undoStreet(street: Street, configuration: ReplayerConfiguration, canvas: Canvas, context: Context) {
// TODO
}
} }
} }

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"
android:fillColor="#ffffff"/>
</vector>

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"
android:fillColor="#ffffff"/>
</vector>

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M8,5v14l11,-7z"
android:fillColor="#ffffff"/>
</vector>

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"
android:fillColor="#ffffff"/>
</vector>

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z"
android:fillColor="#ffffff"/>
</vector>

@ -28,64 +28,91 @@
android:id="@+id/replayer" android:id="@+id/replayer"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/controls" app:layout_constraintBottom_toTopOf="@+id/bottomBar"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/appBar" /> app:layout_constraintTop_toBottomOf="@+id/appBar" />
<LinearLayout <androidx.appcompat.widget.Toolbar
android:id="@+id/controls" android:id="@+id/bottomBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="50dp" android:layout_height="?attr/actionBarSize"
android:background="@color/kaki_medium" android:layout_alignParentBottom="true"
android:gravity="center" android:layout_gravity="center"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"> app:layout_constraintStart_toStartOf="parent">
<Button <LinearLayout
android:id="@+id/previous_hand" android:id="@+id/controls"
android:layout_width="50dp" android:layout_width="match_parent"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_marginStart="4dp" android:gravity="center"
android:layout_marginEnd="4dp" app:layout_constraintBottom_toBottomOf="parent"
/> app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button <ImageButton
android:id="@+id/next_hand" android:id="@+id/previous_hand"
android:layout_width="50dp" android:src="@drawable/ic_skip_previous_white"
android:layout_height="50dp" style="@style/PokerAnalyticsTheme.TransparentButton"
android:layout_marginStart="4dp" android:layout_width="50dp"
android:layout_marginEnd="4dp"/> android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
/>
<Button <ImageButton
android:id="@+id/previous_action" android:id="@+id/next_hand"
android:layout_width="50dp" style="@style/PokerAnalyticsTheme.TransparentButton"
android:layout_height="50dp" android:src="@drawable/ic_skip_next_white"
android:layout_marginStart="4dp" android:layout_width="50dp"
android:layout_marginEnd="4dp"/> android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
<Button <ImageButton
android:id="@+id/next_action" android:id="@+id/play_pause"
android:layout_width="50dp" style="@style/PokerAnalyticsTheme.TransparentButton"
android:layout_height="50dp" android:src="@drawable/ic_play_arrow"
android:layout_marginStart="4dp" android:layout_width="50dp"
android:layout_marginEnd="4dp"/> android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
<Button
android:id="@+id/speed"
style="@style/PokerAnalyticsTheme.TransparentButton"
android:layout_width="64dp"
android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
<ImageButton
android:id="@+id/previous_action"
style="@style/PokerAnalyticsTheme.TransparentButton"
android:src="@drawable/ic_fast_rewind_white"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
<ImageButton
android:id="@+id/next_action"
style="@style/PokerAnalyticsTheme.TransparentButton"
android:src="@drawable/ic_fast_forward_white"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
<Button
android:id="@+id/play_pause"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
<Button
android:id="@+id/speed"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/previous_hand"
android:title="@string/previous"
android:icon="@drawable/ic_skip_previous_white"
app:showAsAction="ifRoom" />
<item
android:id="@+id/next_hand"
android:title="@string/next"
android:icon="@drawable/ic_skip_next_white"
app:showAsAction="ifRoom" />
<item
android:id="@+id/play_pause"
android:title="@string/pause"
android:icon="@drawable/ic_play_arrow"
app:showAsAction="ifRoom" />
<item
android:id="@+id/speed"
android:title="1x"
app:showAsAction="ifRoom" />
<item
android:id="@+id/previous_action"
android:title="@string/previous"
android:icon="@drawable/ic_fast_rewind_white"
app:showAsAction="ifRoom" />
<item
android:id="@+id/next_action"
android:title="@string/next"
android:icon="@drawable/ic_fast_forward_white"
app:showAsAction="ifRoom" />
</menu>

@ -1,6 +1,8 @@
<resources> <resources>
<string name="app_name">Poker Analytics</string> <string name="app_name">Poker Analytics</string>
<string name="previous">Previous</string>
<string name="street_preflop">Preflop</string> <string name="street_preflop">Preflop</string>
<string name="street_flop">Flop</string> <string name="street_flop">Flop</string>
<string name="street_turn">Turn</string> <string name="street_turn">Turn</string>

Loading…
Cancel
Save