From f775b60f887766875f0858a5df796f4cb327bf59 Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 29 Jan 2020 16:30:43 +0100 Subject: [PATCH] Adds Player rows at SUMMARY + fixes --- .../model/handhistory/ComputedAction.kt | 16 +- .../android/model/handhistory/HHBuilder.kt | 195 +++++++++++++----- .../android/model/realm/handhistory/Action.kt | 11 + .../model/realm/handhistory/HandHistory.kt | 4 + .../modules/handhistory/HandHistoryAdapter.kt | 108 +++++++--- .../handhistory/views/PlayerCardsRow.kt | 12 ++ app/src/main/res/layout/row_hand_action.xml | 10 - .../res/layout/row_hand_player_summary.xml | 33 +++ 8 files changed, 287 insertions(+), 102 deletions(-) create mode 100644 app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/PlayerCardsRow.kt create mode 100644 app/src/main/res/layout/row_hand_player_summary.xml diff --git a/app/src/main/java/net/pokeranalytics/android/model/handhistory/ComputedAction.kt b/app/src/main/java/net/pokeranalytics/android/model/handhistory/ComputedAction.kt index dcf858f3..07347a87 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/handhistory/ComputedAction.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/handhistory/ComputedAction.kt @@ -22,15 +22,15 @@ class ComputedAction(var action: Action, /*** * Returns whether the action requires the user to enter an amount for the selected action */ - val requiresAmount: Boolean - get() { - return when(this.action.type) { - Action.Type.POST_SB, Action.Type.POST_BB, - Action.Type.BET, Action.Type.RAISE -> (this.action.amount == null) - Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN -> (this.playerRemainingStack == null && this.action.amount == null) - else -> false + private val requiresAmount: Boolean + get() { + return when(this.action.type) { + Action.Type.POST_SB, Action.Type.POST_BB, + Action.Type.BET, Action.Type.RAISE -> (this.action.amount == null) + Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN -> (this.playerRemainingStack == null && this.action.amount == null) + else -> false + } } - } /*** * Sets the effective amount of the action diff --git a/app/src/main/java/net/pokeranalytics/android/model/handhistory/HHBuilder.kt b/app/src/main/java/net/pokeranalytics/android/model/handhistory/HHBuilder.kt index c1ad9256..6cbe7c3e 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/handhistory/HHBuilder.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/handhistory/HHBuilder.kt @@ -6,6 +6,7 @@ import net.pokeranalytics.android.model.realm.handhistory.Action import net.pokeranalytics.android.model.realm.handhistory.Card import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.ui.modules.handhistory.HandRowType +import net.pokeranalytics.android.ui.modules.handhistory.views.PlayerCardsRow import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardView import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable @@ -100,7 +101,7 @@ class HHBuilder : BoardChangedListener { */ private fun availableActions(index: Int) : Set { - val lastSignificantAction: ComputedAction? = getLastSignificantAction(index) + val lastSignificantAction: ComputedAction? = getStreetLastSignificantAction(index) val lastUserAction: ComputedAction? = getLastUserAction(index) return if (lastSignificantAction != null) { @@ -122,7 +123,7 @@ class HHBuilder : BoardChangedListener { Action.Type.RAISE_ALLIN, Action.Type.BET_ALLIN -> { if (remainingStack != null && actionAmount != null && remainingStack <= actionAmount) { setOf(Action.Type.FOLD, Action.Type.CALL_ALLIN) - } else if (unfoldedPositions(index).size == 2 && remainingStack != null && actionAmount != null && remainingStack > actionAmount) { + } else if (activePositions(index).size == 2 && remainingStack != null && actionAmount != null && remainingStack > actionAmount) { setOf(Action.Type.FOLD, Action.Type.CALL) } else { setOf(Action.Type.FOLD, Action.Type.CALL, Action.Type.RAISE, Action.Type.UNDEFINED_ALLIN) @@ -160,7 +161,7 @@ class HHBuilder : BoardChangedListener { when (actionType) { Action.Type.CALL -> { - val significantAction = getLastSignificantAction(index) + val significantAction = getStreetLastSignificantAction(index) ?: throw PAIllegalStateException("There must be a previously set significant action for a call to be set") val significantAmount = significantAction.action.amount ?: throw PAIllegalStateException("There must be a set amount on the action for the call to be set") @@ -184,7 +185,7 @@ class HHBuilder : BoardChangedListener { val modifiedActions = mutableListOf() getPreviousEmptyActions(index).forEach { modifiedActions.add(it) - val lastSignificant = getLastSignificantAction(index) + val lastSignificant = getStreetLastSignificantAction(index) if (lastSignificant != null) { it.action.type = Action.Type.FOLD } else { @@ -226,7 +227,7 @@ class HHBuilder : BoardChangedListener { val computedAction = this.actionForIndex(index) val indexPosition = computedAction.position - val activePositions = unfoldedPositions(index) + val activePositions = activePositions(index) activePositions.remove(indexPosition) // We want to remove positions that already have an action after [index] @@ -264,14 +265,16 @@ class HHBuilder : BoardChangedListener { this.rowRepresentables.add(computedAction) } - /*** - * Returns the list of position still in play before the given[index] - */ - private fun unfoldedPositions(index: Int) : MutableList { - val folds = this.sortedActions.take(index).filter { it.action.type == Action.Type.FOLD } - .map { it.position } - val allPositions = this.positions - allPositions.removeAll(folds) + /*** + * Returns the list of position still in play before the given [index] + */ + private fun activePositions(index: Int) : MutableList { + val oustedPositions = this.sortedActions.take(index + 1) + .filter { it.action.type?.isPullOut ?: false } + .map { it.position } + + val allPositions = this.positions + allPositions.removeAll(oustedPositions) return allPositions.toMutableList() } @@ -280,37 +283,56 @@ class HHBuilder : BoardChangedListener { * Returns true if a street has been created */ private fun createNextStreetIfNecessary(index: Int) : Boolean { - val computedAction = this.actionForIndex(index) - val currentStreet = this.actionForIndex(index).action.street // TODO is it useful? - - getLastSignificantAction(index)?.let { significantAction -> - - val activePositions = unfoldedPositions(index) - val activePlayerCount = activePositions.size // don't move this line because of removes - - activePositions.remove(significantAction.position) - - val significantIndex = significantAction.action.index - for (i in significantIndex + 1 until this.sortedActions.size) { - val ca = this.sortedActions[i] - val type = ca.action.type - if (type != null && !type.isSignificant) { // Calls and folds - activePositions.remove(ca.position) - } - } - - if (activePositions.isEmpty()) { - - if (activePlayerCount >= 2) { - createStreet(currentStreet.next) - } else { - createStreet(Street.SUMMARY) - } - return true - } + val nextStreet = isStreetActionClosed(index) + if (nextStreet != null) { + createStreet(nextStreet) + return true } return false + +// val computedAction = this.actionForIndex(index) +// val currentStreet = this.actionForIndex(index).action.street +// +// getStreetLastSignificantAction(index)?.let { significantAction -> +// +// val activePositions = activePositions(index) +// val activePlayerCount = activePositions.size // don't move this line because of removes +// +// activePositions.remove(significantAction.position) +// +// val significantIndex = significantAction.action.index +// for (i in significantIndex + 1 until this.sortedActions.size) { +// val ca = this.sortedActions[i] +// val type = ca.action.type +// if (type != null && !type.isSignificant) { // Calls and folds +// activePositions.remove(ca.position) +// } +// } +// +// if (activePositions.isEmpty()) { +// +// if (activePlayerCount >= 2 && currentStreet != Street.RIVER) { +// createStreet(currentStreet.next) +// } else { +// createStreet(Street.SUMMARY) +// } +// return true +// } +// +// } +// +// val allCheck = this.sortedActions.filter { it.action.street == currentStreet }.all { it.action.type == Action.Type.CHECK } +// if (allCheck) { +// if (currentStreet != Street.RIVER) { +// createStreet(currentStreet.next) +// } else { +// createStreet(Street.SUMMARY) +// } +// return true +// } +// +// return false } /*** @@ -322,14 +344,22 @@ class HHBuilder : BoardChangedListener { private fun createStreet(street: Street) { val lastComputedAction = this.sortedActions.last() - val lastActionIndex = lastComputedAction.action.index - val totalPotSize = lastComputedAction.totalPotSize addStreetHeader(this.rowRepresentables, street, totalPotSize) - unfoldedPositions(lastActionIndex).sortedBy { it.ordinal }.forEach { - addNewEmptyAction(it, street, totalPotSize, lastRemainingStack(it, lastActionIndex)) + val lastActionIndex = lastComputedAction.action.index + activePositions(lastActionIndex).sortedBy { it.ordinal }.forEach { + + when (street) { + Street.SUMMARY -> { + this.rowRepresentables.add(PlayerCardsRow(it)) + } + else -> { + addNewEmptyAction(it, street, totalPotSize, lastRemainingStack(it, lastActionIndex)) + } + } + } } @@ -372,7 +402,7 @@ class HHBuilder : BoardChangedListener { } Action.Type.UNDEFINED_ALLIN -> { - getLastSignificantAction(index)?.action?.amount?.let { significantActionAmount -> + getStreetLastSignificantAction(index)?.action?.amount?.let { significantActionAmount -> val committedAmount = getPreviousCommittedAmount(index) ?: 0.0 val askedAmount = significantActionAmount - committedAmount @@ -425,7 +455,7 @@ class HHBuilder : BoardChangedListener { return when (previousAction.type) { Action.Type.POST_BB, Action.Type.POST_SB, Action.Type.STRADDLE, Action.Type.BET, Action.Type.RAISE -> previousAction.amount - Action.Type.CALL -> getLastSignificantAction(previousAction.index)?.action?.amount + Action.Type.CALL -> getStreetLastSignificantAction(previousAction.index)?.action?.amount else -> null } } @@ -466,7 +496,7 @@ class HHBuilder : BoardChangedListener { /*** * Returns the last significant player action, if any, for the action at the provided [index] */ - private fun getLastSignificantAction(index: Int): ComputedAction? { + private fun getStreetLastSignificantAction(index: Int): ComputedAction? { val street = this.actionForIndex(index).action.street Timber.d("**** this.sortedActions.size = ${this.sortedActions.size}") val previousActions = this.sortedActions.take(index).filter { it.action.street == street } @@ -648,22 +678,79 @@ class HHBuilder : BoardChangedListener { val actions = this.sortedActions.filter { it.action.street == street } - if (actions.isNotEmpty()) { + when (street) { + Street.SUMMARY -> { + val lastActionIndex = this.sortedActions.size - 1 - addStreetHeader(rows, street, potSize) + if (activePositions(lastActionIndex).size < 2 || isStreetActionClosed(lastActionIndex) == Street.SUMMARY) { + addStreetHeader(rows, street, potSize) - // Actions - rows.addAll(actions) - - potSize = actions.last().totalPotSize + activePositions(lastActionIndex).forEach { + val positionIndex = this.positions.indexOf(it) + val playerCardsRow = PlayerCardsRow(it, this.handHistory.cardsForPosition(positionIndex)) + this.rowRepresentables.add(playerCardsRow) + } + } + } + else -> { + if (actions.isNotEmpty()) { + addStreetHeader(rows, street, potSize) + rows.addAll(actions) + potSize = actions.last().totalPotSize + } + } } + } this.rowRepresentables = rows // return rows } + private fun isStreetActionClosed(index: Int) : Street? { + + val currentStreet = this.actionForIndex(index).action.street + + getStreetLastSignificantAction(index)?.let { significantAction -> + + val activePositions = activePositions(index) + val activePlayerCount = activePositions.size // don't move this line because of removes + + activePositions.remove(significantAction.position) + + val significantIndex = significantAction.action.index + for (i in significantIndex + 1 until this.sortedActions.size) { + val ca = this.sortedActions[i] + val type = ca.action.type + if (type != null && !type.isSignificant) { // Calls and folds + activePositions.remove(ca.position) + } + } + + if (activePositions.isEmpty()) { + + return if (activePlayerCount >= 2 && currentStreet != Street.RIVER) { + currentStreet.next + } else { + Street.SUMMARY + } + } + + } + + val allCheck = this.sortedActions.filter { it.action.street == currentStreet }.all { it.action.type == Action.Type.CHECK } + if (allCheck) { + return if (currentStreet != Street.RIVER) { + currentStreet.next + } else { + Street.SUMMARY + } + } + + return null + } + private fun addStreetHeader(rowRepresentables: MutableList, street: Street, potSize: Double) { val headerView = CustomizableRowRepresentable(customViewType = HandRowType.HEADER, resId = street.resId) rowRepresentables.add(headerView) diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Action.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Action.kt index 137c22cd..1ee89ab7 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Action.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Action.kt @@ -34,6 +34,17 @@ open class Action : RealmObject() { } } + /*** + * Tells if the action pulls the player out from any new decision + */ + val isPullOut: Boolean + get() { + return when (this) { + FOLD, BET_ALLIN, RAISE_ALLIN, CALL_ALLIN, UNDEFINED_ALLIN -> true + else -> false + } + } + val requiresOpponentDecision: Boolean get() { return when(this) { diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt index 6942e108..96939d7d 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt @@ -128,4 +128,8 @@ open class HandHistory : RealmObject(), RowRepresentable, Identifiable, Filterab return this.board.sortedBy { it.index }.take(street.totalBoardCards).toMutableList() } + fun cardsForPosition(position: Int): List { + return this.playerSetups.first { it.position == position }.cards + } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryAdapter.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryAdapter.kt index 5fc3b9ef..15fea871 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryAdapter.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryAdapter.kt @@ -22,6 +22,7 @@ import net.pokeranalytics.android.ui.adapter.RecyclerAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.extensions.hideKeyboard +import net.pokeranalytics.android.ui.modules.handhistory.views.PlayerCardsRow import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardView import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.holder.RowViewHolder @@ -32,6 +33,7 @@ import timber.log.Timber enum class HandRowType(var layoutRes: Int) : ViewIdentifier { HEADER(R.layout.row_header_title), ACTION(R.layout.row_hand_action), + PLAYER_SUMMARY(R.layout.row_hand_player_summary), STREET(R.layout.row_hand_cards); override val identifier: Int @@ -55,6 +57,7 @@ class HandHistoryAdapter( HandRowType.HEADER -> RowViewHolder(layout) HandRowType.ACTION -> RowHandAction(layout) HandRowType.STREET -> RowHandStreet(layout) + HandRowType.PLAYER_SUMMARY -> RowHandPlayerSummary(layout) } } @@ -79,22 +82,6 @@ class HandHistoryAdapter( } } -// inner class TextListener : TextWatcher { -// -// var position: Int = 0 -// -// override fun afterTextChanged(s: Editable?) {} -// -// override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} -// -// override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { -// val row = dataSource.rowRepresentableForPosition(position) -// ?: throw PAIllegalStateException("Row Representable not found at index: $position") -// delegate?.onRowValueChanged(s.toString(), row) -// } -// -// } - abstract inner class RowHandHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { var currentPosition = 0 @@ -236,25 +223,12 @@ class HandHistoryAdapter( } -// private fun requestFocusAndShowKeyboard(editText: EditText) { -// -// if (editText.requestFocus()) { -// val imm = itemView.context.getSystemService(InputMethodManager::class.java) -// imm.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY) - -// val imm = itemView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager -// imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0) -// imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT) -// } -// -// } } /** * Display a hand street */ - inner class RowHandStreet(itemView: View) : RowHandHolder(itemView), - BindableHolder { + inner class RowHandStreet(itemView: View) : RowHandHolder(itemView), BindableHolder { init { @@ -325,4 +299,78 @@ class HandHistoryAdapter( } + + /** + * Display a hand action + */ + inner class RowHandPlayerSummary(itemView: View) : RowHandHolder(itemView), + BindableHolder { + +// private var actionCanBeEdited = true +// private var amountCanBeEdited = true + + init { + + // Cards + itemView.findViewById(R.id.cardsEditText)?.let { amountEditText -> + + amountEditText.isFocusableInTouchMode = true + + amountEditText.setOnTouchListener { _, event -> + + if (event.action == MotionEvent.ACTION_UP) { + // Both are required, otherwise requestFocus() fails + amountEditText.isFocusable = true + amountEditText.isFocusableInTouchMode = true + + amountEditText.requestFocus() + + editTextSelected(amountEditText, true, HHKeyboard.AMOUNT.ordinal) + } + return@setOnTouchListener true + } + + } + } + + override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { + + Timber.d("onbind @position = $position") + + this.currentPosition = position + + val playerCardView = row as PlayerCardsRow + + // Position + itemView.findViewById