more archi + first drawn rectangle

hh
Laurent 6 years ago
parent 982ded7e66
commit f7315defe4
  1. 9
      app/src/main/java/net/pokeranalytics/android/model/handhistory/Street.kt
  2. 101
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryFragment.kt
  3. 9
      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/replayer/HandStep.kt
  5. 16
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerConfiguration.kt
  6. 71
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerFragment.kt
  7. 29
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerView.kt
  8. 33
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableCanvas.kt
  9. 20
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TestActivity.kt
  10. 67
      app/src/main/res/layout/fragment_replayer.xml

@ -44,5 +44,14 @@ enum class Street : HandStep {
TableCanvas.drawStreet(this, configuration, canvas, context)
}
override fun frames(
configuration: ReplayerConfiguration,
canvas: Canvas,
context: Context,
update: () -> Unit
) {
TableCanvas.drawStreet(this, configuration, canvas, context)
}
}

@ -18,7 +18,6 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.handhistory.Position
import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.model.realm.Player
import net.pokeranalytics.android.model.realm.handhistory.Action
import net.pokeranalytics.android.model.realm.handhistory.Card
@ -26,6 +25,7 @@ import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.activity.components.RequestCode
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.extensions.px
import net.pokeranalytics.android.ui.extensions.toByteArray
import net.pokeranalytics.android.ui.fragment.components.BaseFragment
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment
@ -39,6 +39,7 @@ import net.pokeranalytics.android.ui.modules.handhistory.views.KeyboardListener
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager
import net.pokeranalytics.android.util.extensions.findById
import net.pokeranalytics.android.util.video.MMediaMuxer
import timber.log.Timber
@ -72,7 +73,11 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
companion object {
fun newInstance(id: String? = null, configurationId: String? = null, attached: Boolean = false): HandHistoryFragment {
fun newInstance(
id: String? = null,
configurationId: String? = null,
attached: Boolean = false
): HandHistoryFragment {
val fragment = HandHistoryFragment()
val bundle = Bundle()
bundle.putSerializable(BundleKey.HAND_HISTORY_ID.value, id)
@ -93,7 +98,11 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
}
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)
return inflater.inflate(R.layout.fragment_hand_history, container, false)
}
@ -115,8 +124,8 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
this.model.setHandHistory(hhCopy)
this.setEditing(false)
} ?: run {
val configurationId= this.arguments?.getString(BundleKey.CONFIGURATION_ID.value)
val attached= this.arguments?.getBoolean(BundleKey.ATTACHED.value) ?: false
val configurationId = this.arguments?.getString(BundleKey.CONFIGURATION_ID.value)
val attached = this.arguments?.getBoolean(BundleKey.ATTACHED.value) ?: false
this.model.createNewHandHistory(getRealm(), configurationId, attached)
this.setEditing(true)
@ -130,7 +139,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
setDisplayHomeAsUpEnabled(true)
this.handHistoryAdapter = HandHistoryAdapter(this.model,this)
this.handHistoryAdapter = HandHistoryAdapter(this.model, this)
// val swipeToDelete = SwipeToDeleteCallback { position ->
// this.model.deleteIfPossible(position)
@ -162,7 +171,8 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
val selection = this.model.currentSelection
retrieveEditTextInputConnection(selection)
}
else -> {}
else -> {
}
}
}
@ -185,7 +195,8 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
RequestCode.PLAYER_SELECTION.ordinal -> {
if (resultCode == Activity.RESULT_OK) {
val playerId = data?.getStringExtra(BaseFragment.BundleKey.PRIMARY_KEY.value) ?: throw PAIllegalStateException("Primary key not set where as activity has finished")
val playerId = data?.getStringExtra(BaseFragment.BundleKey.PRIMARY_KEY.value)
?: throw PAIllegalStateException("Primary key not set where as activity has finished")
getRealm().findById<Player>(playerId)?.let { player ->
this.model.playerSelected(player)
} ?: throw PAIllegalStateException("Player (id=$playerId) not found")
@ -238,7 +249,8 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
HHKeyboard.AMOUNT -> {
retrieveEditTextInputConnection(selection)
}
else -> {}
else -> {
}
}
this.showKeyboard(kb) {
@ -270,10 +282,14 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
val handRow = this.model.rowRepresentableForPosition(selection.index) as? HandHistoryRow
val holder = recyclerView.findViewHolderForAdapterPosition(selection.index) as? HandHistoryAdapter.RowHandHolder
val holder =
recyclerView.findViewHolderForAdapterPosition(selection.index) as? HandHistoryAdapter.RowHandHolder
holder?.let {
val amountEditText = it.editTextForTag(selection.tag)
this.keyboard.setAmountEditText(amountEditText, handRow?.amountForTag(this.model.handHistory, selection.tag))
this.keyboard.setAmountEditText(
amountEditText,
handRow?.amountForTag(this.model.handHistory, selection.tag)
)
} ?: run {
Timber.d("no holder, or not RowHandAction")
}
@ -337,17 +353,31 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
}
when (row.bottomSheetType) { // Comment, number of players...
BottomSheetType.NONE -> {}
BottomSheetType.NONE -> {
}
else -> {
val editDescriptors = this.model.editDescriptors(row)
when (row) {
HandRowType.PLAYER_NUMBER -> {
BottomSheetFragment.create(requireFragmentManager(), row, this, editDescriptors, isClearable = false, alternativeLabels = true)
BottomSheetFragment.create(
requireFragmentManager(),
row,
this,
editDescriptors,
isClearable = false,
alternativeLabels = true
)
}
else -> {
BottomSheetFragment.create(requireFragmentManager(), row, this, editDescriptors, alternativeLabels = true)
BottomSheetFragment.create(
requireFragmentManager(),
row,
this,
editDescriptors,
alternativeLabels = true
)
}
}
@ -527,7 +557,8 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
onRowSelected(rowRepresentableIndex, it, ComputedAction.Tag.ACTION.ordinal)
this.handHistoryAdapter.notifyItemChanged(rowRepresentableIndex)
this.scrollToPosition(rowRepresentableIndex)
} ?: throw PAIllegalStateException("Rowrepresentable not fouind at index $rowRepresentableIndex")
}
?: throw PAIllegalStateException("Rowrepresentable not fouind at index $rowRepresentableIndex")
}
// Table
@ -642,9 +673,11 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder.setTitle(R.string.position)
builder.setItems(arrayOf<CharSequence>(
getString(R.string.remove)
)) { _, index ->
builder.setItems(
arrayOf<CharSequence>(
getString(R.string.remove)
)
) { _, index ->
// The 'which' argument contains the index position
// of the selected item
when (index) {
@ -666,11 +699,13 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder.setTitle(R.string.export)
builder.setItems(arrayOf<CharSequence>(
getString(R.string.text)
builder.setItems(
arrayOf<CharSequence>(
getString(R.string.text)
// getString(R.string.video),
// "GIF"
)) { _, index ->
)
) { _, index ->
// The 'which' argument contains the index position
// of the selected item
when (index) {
@ -687,17 +722,33 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
val config = ReplayerConfiguration(this.model.handHistory)
val bitmap = Bitmap.createBitmap(480, 480, Bitmap.Config.ARGB_8888)
val width = 480
val height = 480
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val tc = TableCanvas(bitmap)
// draw initial table
TableCanvas.initializeTable(config, tc, requireContext())
HandStep.build(this.model.handHistory).forEach {
it.draw(config, tc, requireContext())
}
val muxer = MMediaMuxer()
muxer.Init(requireActivity(), bitmap.width, bitmap.height, "hhVideo", "YES!")
HandStep.createSteps(this.model.handHistory).forEach { step ->
step.frames(config, tc, requireContext()) {
try {
val byteArray = bitmap.toByteArray()
muxer.AddFrame(byteArray)
} catch (e: Exception) {
Timber.e("error = ${e.message}")
}
}
}
muxer.CreateVideo()
val path = muxer.GetPath()
Timber.d("**** Video path = $path")
// Timber.d("**** Start video test")
//

@ -312,4 +312,13 @@ class ComputedAction(var manager: ActionManager,
TableCanvas.drawAction(this, configuration, canvas, context)
}
override fun frames(
configuration: ReplayerConfiguration,
canvas: Canvas,
context: Context,
update: () -> Unit
) {
// TODO("Not yet implemented")
}
}

@ -8,11 +8,13 @@ import net.pokeranalytics.android.ui.modules.handhistory.model.ActionList
interface HandStep {
fun frames(configuration: ReplayerConfiguration, canvas: Canvas, context: Context, update: () -> (Unit))
fun draw(configuration: ReplayerConfiguration, canvas: Canvas, context: Context)
companion object {
fun build(handHistory: HandHistory): List<HandStep> {
fun createSteps(handHistory: HandHistory): List<HandStep> {
val actionList = ActionList()
actionList.load(handHistory)

@ -1,13 +1,27 @@
package net.pokeranalytics.android.ui.modules.handhistory.replayer
import android.graphics.RectF
import net.pokeranalytics.android.model.realm.handhistory.HandHistory
class ReplayerConfiguration(var handHistory: HandHistory) {
val speed: Double = 1.0
var width = 100f
var height = 100f
var rect = RectF()
val speed: Double = 1.0
val showVillainHands: Boolean = true
fun setDimension(width: Float, height: Float) {
this.width = width
this.height = height
val tp = TableCanvas.tablePadding
this.rect = RectF(tp, tp, width - tp, height - tp)
}
}

@ -1,13 +1,29 @@
package net.pokeranalytics.android.ui.modules.handhistory.replayer
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProviders
import kotlinx.android.synthetic.main.fragment_replayer.*
import net.pokeranalytics.android.R
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.modules.handhistory.model.HandHistoryViewModel
class ReplayerFragment : BaseFragment() {
class ReplayerFragment : RealmFragment() {
/***
* The fragment's ViewModel
*/
private lateinit var model: HandHistoryViewModel
private var steps: List<HandStep> = listOf()
// private lateinit var configuration: ReplayerConfiguration
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
@ -20,28 +36,75 @@ class ReplayerFragment : BaseFragment() {
initUI()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.model = activity?.run {
ViewModelProviders.of(this)[HandHistoryViewModel::class.java]
} ?: throw Exception("Invalid Activity")
}
private fun initData() {
// TODO change
this.model.setHandHistory(getRealm().where(HandHistory::class.java).findFirst()!!)
loadHand(this.model.handHistory)
}
private fun initUI() {
}
fun play() {
private fun loadHand(handHistory: HandHistory) {
this.steps = HandStep.createSteps(handHistory)
this.replayer.configuration = ReplayerConfiguration(handHistory)
}
var isPlaying: Boolean = false
val mainHandler = Handler(Looper.getMainLooper())
val actionSpeed = 1000L
var speedMultiplier = 1
private val timerRunnable: Runnable = Runnable {
nextAction()
}
fun resume() {
fun playOrPause() {
if (this.isPlaying) {
mainHandler.removeCallbacks(timerRunnable)
} else {
mainHandler.postDelayed(timerRunnable, 0L)
}
this.isPlaying = !this.isPlaying
}
fun nextAction() {
private var stepIndex: Int = 0
fun nextAction() {
if (this.stepIndex < this.steps.size - 1) {
this.stepIndex += 1
playAction()
}
if (this.isPlaying) {
mainHandler.postDelayed(timerRunnable, speedMultiplier * actionSpeed)
}
}
fun previousAction() {
if (this.stepIndex > 0) {
this.stepIndex -= 1
playAction()
}
}
fun playAction() {
this.replayer.step = this.steps[this.stepIndex]
this.replayer.invalidate() // force redraw
}
fun nextHand() {

@ -2,23 +2,42 @@ package net.pokeranalytics.android.ui.modules.handhistory.replayer
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
import net.pokeranalytics.android.R
import timber.log.Timber
class ReplayerView(context: Context, attrs: AttributeSet) : View(context, attrs) {
lateinit var replayerConfiguration: ReplayerConfiguration
var step: HandStep? = null
lateinit var configuration: ReplayerConfiguration
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
Timber.d("ReplayerView > onMeasure")
var rect = RectF()
init {
TableCanvas.configurePaints(context)
this.viewTreeObserver.addOnGlobalLayoutListener {
this.configuration.setDimension(width.toFloat(), height.toFloat())
}
}
override fun onDraw(canvas: Canvas?) {
Timber.d("ReplayerView > onDraw")
super.onDraw(canvas)
Timber.d("ReplayerView > onDraw, rect = $rect")
// canvas?.drawCircle(100f, 100f, 50f, paint)
canvas?.let {
// TableCanvas.draw(this.replayerConfiguration, it, context)
// Timber.d("ReplayerView > onDraw with canvas: ${canvas.width}, ${canvas.height}")
TableCanvas.initializeTable(this.configuration, canvas, context)
this.step?.draw(this.configuration, canvas, context)
}
}

@ -13,10 +13,27 @@ import net.pokeranalytics.android.ui.modules.handhistory.model.ComputedAction
class TableCanvas(bitmap: Bitmap) : Canvas(bitmap) {
companion object {
const val STROKE_WIDTH = 20.0f
const val strokeWidth = 20f
const val tablePadding = 200f
const val tableCornerRadius = 100f
private val paint = Paint()
fun configurePaints(context: Context) {
paint.isAntiAlias = true
paint.style = Paint.Style.STROKE
paint.strokeWidth = strokeWidth
paint.color = context.getColor(R.color.green)
}
/***
* WARNING: Avoid instancing objects here, as it's called from onDraw method
*/
fun initializeTable(config: ReplayerConfiguration, canvas: Canvas, context: Context) {
canvas.drawRoundRect(config.rect, this.tableCornerRadius, this.tableCornerRadius, this.paint)
}
fun drawStreet(street: Street, config: ReplayerConfiguration, canvas: Canvas, context: Context) {
@ -34,18 +51,4 @@ class TableCanvas(bitmap: Bitmap) : Canvas(bitmap) {
}
fun load(context: Context) {
// create canvasses
val paint = Paint()
paint.color = context.getColor(R.color.green)
paint.style = Paint.Style.STROKE
paint.strokeWidth = STROKE_WIDTH
paint.isAntiAlias = true
val rect = RectF(10f, 10f, 10f, 10.0f)
drawRoundRect(rect, 8f, 8f, paint)
}
}

@ -16,20 +16,20 @@ class TestActivity : BaseActivity() {
}
fun initUI() {
showFragment(ReplayerFragment(), R.id.container)
}
override fun onStart() {
super.onStart()
val bm = Bitmap.createBitmap(
this.container.width,
this.container.height,
Bitmap.Config.ARGB_8888)
val tc = TableCanvas(bm)
tc.load(this)
this.image_view.setImageBitmap(bm)
// val bm = Bitmap.createBitmap(
// this.container.width,
// this.container.height,
// Bitmap.Config.ARGB_8888)
//
// val tc = TableCanvas(bm)
// tc.load(this)
//
// this.image_view.setImageBitmap(bm)
}
}

@ -9,28 +9,83 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:theme="@style/PokerAnalyticsTheme.Toolbar.Session"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:title="@string/more" />
app:title="@string/hand_history" />
</com.google.android.material.appbar.AppBarLayout>
<net.pokeranalytics.android.ui.modules.handhistory.replayer.ReplayerView
android:id="@+id/replayer"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/controls"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/appBar" />
<LinearLayout
android:id="@+id/controls"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/kaki_medium"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/previous_hand"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
/>
<Button
android:id="@+id/next_hand"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
<Button
android:id="@+id/previous_action"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
<Button
android:id="@+id/next_action"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
<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>
Loading…
Cancel
Save