Advances on card keyboard and automatic action creation

hh
Laurent 6 years ago
parent 66730eb43e
commit 2d2a7aa446
  1. 49
      app/src/main/java/net/pokeranalytics/android/model/handhistory/BoardManager.kt
  2. 204
      app/src/main/java/net/pokeranalytics/android/model/handhistory/HHBuilder.kt
  3. 8
      app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Action.kt
  4. 85
      app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Card.kt
  5. 4
      app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt
  6. 5
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryAdapter.kt
  7. 53
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryFragment.kt
  8. 76
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryViewModel.kt
  9. 62
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/CardSuitAdapter.kt
  10. 60
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/CardValueAdapter.kt
  11. 60
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/KeyboardCardView.kt
  12. 22
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/KeyboardContainer.kt
  13. 15
      app/src/main/res/layout/view_hand_keyboard_card.xml
  14. 1
      app/src/main/res/values/strings.xml

@ -0,0 +1,49 @@
package net.pokeranalytics.android.model.handhistory
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.realm.handhistory.Card
interface BoardChangedListener {
fun boardChanged()
}
class BoardManager(cards: List<Card>, var listener: BoardChangedListener) {
private var sortedBoardCards: MutableList<Card> = mutableListOf()
val allCards: List<Card>
get() {
return this.sortedBoardCards
}
init {
this.sortedBoardCards = cards.sortedBy { it.index }.toMutableList()
}
fun add(card: Card) {
if (this.sortedBoardCards.size == 5) {
throw PAIllegalStateException("Can't add anymore cards")
}
card.index = this.sortedBoardCards.size
this.sortedBoardCards.add(card)
this.listener.boardChanged()
}
fun clearStreet(street: Street) {
this.sortedBoardCards.removeAll { it.street == street }
this.listener.boardChanged()
}
fun lastCard(street: Street) : Card? {
return this.sortedBoardCards.lastOrNull { it.street == street }
}
fun remove(card: Card) {
this.sortedBoardCards.remove(card)
this.listener.boardChanged()
}
}

@ -3,12 +3,14 @@ package net.pokeranalytics.android.model.handhistory
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException
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.StreetCardView
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import timber.log.Timber
import kotlin.math.max
enum class HHKeyboard {
ACTION,
@ -19,7 +21,7 @@ enum class HHKeyboard {
class HHSelection(var index: Int, var keyboard: HHKeyboard)
class HHBuilder {
class HHBuilder : BoardChangedListener {
/***
* The hand history
@ -34,7 +36,13 @@ class HHBuilder {
/***
* All actions sorted by index
*/
private var sortedActions: List<ComputedAction> = mutableListOf()
private var sortedActions: MutableList<ComputedAction> = mutableListOf()
/***
* The board cards sorted by position
*/
private lateinit var boardManager: BoardManager
// private var sortedBoardCards: MutableList<Card> = mutableListOf()
var positions: LinkedHashSet<Position> = linkedSetOf()
@ -82,6 +90,8 @@ class HHBuilder {
}
this.sortedActions = computedActions
// this.sortedBoardCards = this.handHistory.board.sortedBy { it.index }.toMutableList()
this.boardManager = BoardManager(this.handHistory.board, this)
}
/***
@ -174,7 +184,7 @@ class HHBuilder {
val dropedIndex = dropNextActionsIfNecessary(index)
this.updateFollowupActions()
this.updateFollowupActions(index)
// Automatically sets action for the previous empty actions
val modifiedActions = mutableListOf<ComputedAction>()
@ -196,10 +206,98 @@ class HHBuilder {
* Adds, if necessary, new ComputedAction for players that needs to act
* Also adds, if necessary, the Street separators and board selectors
*/
private fun updateFollowupActions() {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
private fun updateFollowupActions(index: Int) {
val computedAction = this.actionForIndex(index)
val type = computedAction.action.type
when (type?.isSignificant) {
true -> { // opens the action and requires action from other
addsFollowupActionsIfNecessary(index)
}
false -> { // closes the action, pass to next street if necessary
createNextStreetIfNecessary(index)
}
else -> { }
}
}
private fun addsFollowupActionsIfNecessary(index: Int) {
val computedAction = this.actionForIndex(index)
val indexPosition = computedAction.position
val activePositions = unfoldedPositions(index)
activePositions.remove(indexPosition)
// We want to remove positions that already have an action after [index]
for (i in index + 1 until this.sortedActions.size) {
val ca = this.actionForIndex(i)
activePositions.remove(ca.position)
}
// Circularly adds an action for missing positions
val firstPositionAfterCurrent = max(0, activePositions.indexOfFirst { it.ordinal > indexPosition.ordinal })
for (i in 0 until activePositions.size) {
val position = activePositions[(firstPositionAfterCurrent + i) % activePositions.size]
this.addNewEmptyAction(position, computedAction.totalPotSize, lastRemainingStack(position, index))
}
}
private fun lastRemainingStack(position: Position, index: Int): Double? {
return this.sortedActions.take(index).lastOrNull { it.position == position }?.playerRemainingStack
}
private fun addNewEmptyAction(position: Position, currentPotSize: Double, remainingStack: Double?) {
val action = Action()
action.index = this.sortedActions.size
action.position = position.ordinal
val computedAction = ComputedAction(action, currentPotSize, remainingStack, position)
this.sortedActions.add(computedAction)
}
private fun unfoldedPositions(index: Int) : MutableList<Position> {
val folds = this.sortedActions.take(index).filter { it.action.type == Action.Type.FOLD }
.map { it.position }
val allPositions = this.positions
allPositions.removeAll(folds)
return allPositions.toMutableList()
}
private fun createNextStreetIfNecessary(index: Int) {
val computedAction = this.actionForIndex(index)
val currentStreet = this.actionForIndex(index).action.street // TODO is it useful?
getLastSignificantAction(index)?.action?.index?.let { significantIndex ->
val indexPosition = computedAction.position
val activePositions = unfoldedPositions(index)
activePositions.remove(indexPosition)
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()) {
createNextStreet(index)
}
}
}
private fun createNextStreet(index: Int) {
// TODO
}
/***
* Returns the list of empty actions before the action at the given [index]
*/
private fun getPreviousEmptyActions(index: Int) : List<ComputedAction> {
val street = this.actionForIndex(index).action.street
return this.sortedActions.take(index).filter { it.action.street == street && it.action.type == null }
@ -216,6 +314,9 @@ class HHBuilder {
return null
}
/***
* Returns the number of active players at the beginning of the street
*/
private fun remainingActivePlayerCountAtStreetStart(index: Int) : Int {
return 0
}
@ -301,6 +402,9 @@ class HHBuilder {
return null
}
/***
* Returns all "CALL" ComputedAction between the [index] and the next significant action
*/
private fun getNextCalls(index: Int) : List<ComputedAction> {
val nextSignificantIndex = getNextSignificantAction(index)?.action?.index ?: lastIndexOfStreet(index)
return this.sortedActions.filter {
@ -357,6 +461,10 @@ class HHBuilder {
return streetActions.drop(index + 1).map { it.position }
}
/***
* Sets the number of players playing the hand
* Defines the appropriate positions for this player count
*/
fun setNumberOfPlayers(playerCount: Int) {
this.handHistory.numberOfPlayers = playerCount
this.positions = Position.positionsPerPlayers(playerCount)
@ -405,6 +513,9 @@ class HHBuilder {
return rows
}
/***
* Returns the [index] of a ComputedAction given its [rowRepresentableIndex]
*/
fun indexOfComputedAction(rowRepresentableIndex: Int) : Int {
val computedAction = this.currentRowRepresentables[rowRepresentableIndex] as ComputedAction
return computedAction.action.index
@ -432,6 +543,10 @@ class HHBuilder {
return null
}
/***
* Returns the index, strictly superior to [actionIndexForSelection],
* of the next action of the given [position]
*/
fun nextActionIndex(actionIndexForSelection: Int, position: Position): Int {
var i = actionIndexForSelection + 1
@ -445,5 +560,84 @@ class HHBuilder {
}
}
/***
* Adds a card with the selected [value]
*/
fun cardValueSelected(value: Card.Value, currentSelection: HHSelection) {
when (this.currentRowRepresentables[currentSelection.index]) {
is StreetCardView -> {
val card = Card.newInstance(value.value)
this.boardManager.add(card)
}
}
}
/***
* Either affect the [suit] to the current card,
* or create a Card with an empty value and the [suit]
*/
fun cardSuitSelected(suit: Card.Suit, currentSelection: HHSelection) {
when (val row = this.currentRowRepresentables[currentSelection.index]) {
is StreetCardView -> {
val addNewCard = this.boardManager.lastCard(row.street)?.let {
if (it.suit != null) {
true
} else {
it.suit = suit
false
}
} ?: true
if (addNewCard) {
val card = Card.newInstance(suit = suit)
this.boardManager.add(card)
}
}
}
}
/***
* Deletes all the card of the selected street
*/
fun clearCards(currentSelection: HHSelection) {
val row = this.currentRowRepresentables[currentSelection.index]
when (row) {
is StreetCardView -> {
this.boardManager.clearStreet(row.street)
}
}
}
/***
* Delete the last property of the last Card of the selected street
* We don't want empty Card (value + suit),
* so we delete the whole card if both information are null
*/
fun deleteLastCardProperty(currentSelection: HHSelection) {
val row = this.currentRowRepresentables[currentSelection.index]
when (row) {
is StreetCardView -> {
this.boardManager.lastCard(row.street)?.let { card ->
if (card.value != null && card.suit != null) {
card.suit = null
} else {
this.boardManager.remove(card)
}
}
}
}
}
override fun boardChanged() {
this.currentRowRepresentables.filterIsInstance<StreetCardView>().forEach {
it.cards = this.boardManager.allCards
}
}
}

@ -34,6 +34,14 @@ open class Action : RealmObject() {
}
}
val requiresOpponentDecision: Boolean
get() {
return when(this) {
CALL, CALL_ALLIN, FOLD -> false
else -> true
}
}
override val viewType: Int = RowViewType.TITLE_GRID.ordinal
companion object {

@ -7,7 +7,9 @@ import android.text.style.ForegroundColorSpan
import io.realm.RealmObject
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import timber.log.Timber
import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
interface CardProperty
@ -28,79 +30,109 @@ fun List<Card>.formatted(context: Context) : CharSequence? {
open class Card : RealmObject() {
companion object {
fun valueOf(value: Int, suit: Suit) : Card {
fun newInstance(value: Int? = null, suit: Suit? = null, index: Int = 0) : Card {
val card = Card()
card.value = value
card.suit = suit
Timber.d("suit = ${card.suitIdentifier}")
value?.let { card.value = it }
suit?.let { card.suit = it}
card.index = index
return card
}
}
class Value(var value: Int) : CardProperty {
class Value(var value: Int?) : CardProperty, RowRepresentable {
companion object {
fun format(value: Int) : String {
val values: List<Value> by lazy {
val v = mutableListOf(Value(null)) // null for x
(2..14).forEach { v.add(Value(it)) }
v
}
fun format(value: Int?) : String {
return when(value) {
0 -> "x"
in 2..9 -> "$value"
10 -> "T"
11 -> "J"
12 -> "Q"
13 -> "K"
14 -> "A"
else -> throw PAIllegalStateException("card value '$value' not handled")
else -> "X"
}
}
}
override fun getDisplayName(context: Context): String {
return this.formatted
}
val formatted: String
get() { return format(this.value) }
override val viewType: Int = RowViewType.TITLE_GRID.ordinal
}
enum class Suit(val value: String) : CardProperty {
UNDEFINED("x"),
enum class Suit(val value: String) : CardProperty, RowRepresentable {
SPADES(""),
HEART(""),
DIAMOND(""),
CLOVER("");
companion object {
fun format(suit: Suit?) : String {
return suit?.value ?: "x"
}
fun color(suit: Suit?) : Int {
return suit?.color ?: R.color.white
}
}
val color: Int
get() {
return when (this) {
UNDEFINED -> R.color.white
SPADES -> R.color.white_dark
HEART -> R.color.red
DIAMOND -> R.color.diamond
CLOVER -> R.color.clover
}
}
override fun getDisplayName(context: Context): String {
return this.value
}
override val viewType: Int = RowViewType.TITLE_GRID.ordinal
}
/***
* The card value: 2..A
* 0: undefined
*/
var value: Int = 0
var value: Int? = null
/***
* Returns the formatted value of the card
*/
val formattedValue: String
get() { return Value.format(this.value) }
/***
* The card suit: heart, spades...
* The card suit identifier: heart, spades...
*/
var suitIdentifier: Int = 0
var suitIdentifier: Int? = null
var suit: Suit
/***
* Returns the suit of the card
*/
var suit: Suit?
get() {
return Suit.values()[this.suitIdentifier]
return this.suitIdentifier?.let { Suit.values()[it] }
}
set(value) {
this.suitIdentifier = value.ordinal
this.suitIdentifier = value?.ordinal
}
/***
@ -108,11 +140,24 @@ open class Card : RealmObject() {
*/
var index: Int = 0
val street: Street
get() {
return when (index) {
in 0..2 -> Street.FLOP
3 -> Street.TURN
4 -> Street.RIVER
else -> throw PAIllegalStateException("Card doesn't belong to any street")
}
}
/***
* Formats the Card into a Spannable String with the appropriate color
*/
fun formatted(context: Context) : SpannableString {
val spannable = SpannableString(this.formattedValue + this.suit.value)
val spannable = SpannableString(this.formattedValue + Suit.format(this.suit))
spannable.setSpan(
ForegroundColorSpan(context.getColor(this.suit.color)),
ForegroundColorSpan(context.getColor(Suit.color(this.suit))),
0,
spannable.length,
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE

@ -124,8 +124,8 @@ open class HandHistory : RealmObject(), RowRepresentable, Identifiable, Filterab
}
fun cardsForStreet(street: Street): List<Card> {
return this.board.sortedBy { it.index }.drop(street.totalBoardCards)
fun cardsForStreet(street: Street): MutableList<Card> {
return this.board.sortedBy { it.index }.take(street.totalBoardCards).toMutableList()
}
}

@ -282,6 +282,8 @@ class HandHistoryAdapter(
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
this.currentPosition = position
val streetCardView = row as StreetCardView
val street = streetCardView.street
@ -290,7 +292,8 @@ class HandHistoryAdapter(
flopEditText.isFocusable = (street == Street.FLOP)
flopEditText.isVisible = true
val text = streetCardView.cards.take(3).formatted(itemView.context)
val flop = streetCardView.cards.take(3)
val text = flop.formatted(itemView.context)
flopEditText.setText(text)
}

@ -66,7 +66,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
initUI()
this.edit()
this.model.currentSelection.value?.index?.let {
this.model.selectionLiveData.value?.index?.let {
Timber.d(">>>> attempt to retrieveEditTextInputConnection")
this.retrieveEditTextInputConnection(it)
}
@ -84,7 +84,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
}
this.model.setBuilder(builder)
this.rows = this.model.builder.value?.rowRepresentables() ?: listOf()
this.rows = this.model.builderLiveData.value?.rowRepresentables() ?: listOf()
}
@ -108,7 +108,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
adapter = handHistoryAdapter
}
this.model.currentSelection.observeForever { selection ->
this.model.selectionLiveData.observeForever { selection ->
selection?.let {
Timber.d("Current selection is ${selection.index} / ${selection.keyboard}")
retrieveEditTextInputConnection(selection.index)
@ -129,7 +129,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
// At first, the selection is defined before the holder is bound,
// so we retrieve the editText inputConnection once the recycler view has been rendered
this.recyclerView.viewTreeObserver.addOnGlobalLayoutListener {
this.model.currentSelection.value?.index?.let {
this.model.selectionLiveData.value?.index?.let {
retrieveEditTextInputConnection(it)
}
}
@ -162,7 +162,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
}
private fun findNextActionToEdit() {
val selection = this.model.currentSelection.value
val selection = this.model.selectionLiveData.value
val index = selection?.index ?: throw PAIllegalStateException("Request next with no selection")
this.findNextActionToEdit(index, selection.keyboard)
}
@ -201,16 +201,14 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
return
}
this.model.currentSelection.value?.index?.let { oldIndex ->
this.model.selectionLiveData.value?.index?.let { oldIndex ->
refreshCells(oldIndex)
}
this.model.currentSelection.value = HHSelection(position, HHKeyboard.values()[tag])
// scrolls to selected position
this.recyclerView.smoothScrollToPosition(position)
val keyboard = when (row) {
val keyboard: HHKeyboard = when (row) {
is ComputedAction -> {
when (tag) {
HHKeyboard.ACTION.ordinal -> HHKeyboard.ACTION
@ -225,15 +223,18 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
is StreetCardView -> {
HHKeyboard.CARD
}
else -> null
else -> throw PAIllegalStateException("unmanaged row type: $row")
}
this.model.selectionLiveData.value = HHSelection(position, keyboard)
Timber.d("row $position selected, show keyboard = $keyboard")
keyboard?.let { this.keyboard.show(keyboard) }
this.keyboard.show(keyboard)
}
override fun onRowDeselected(position: Int, row: RowRepresentable) {
this.model.currentSelection.value = null
this.model.selectionLiveData.value = null
this.model.currentAmount = null
}
@ -242,7 +243,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
}
override fun isSelected(position: Int, row: RowRepresentable, tag: Int): Boolean {
val currentSelection = this.model.currentSelection
val currentSelection = this.model.selectionLiveData
val isSelectedIndex = (position == currentSelection.value?.index)
val isSelectedAction = (tag == currentSelection.value?.keyboard?.ordinal)
// Timber.d("position = $position, tag = $tag, current index = ${currentSelection?.index}, kb = ${currentSelection?.keyboard}")
@ -264,9 +265,9 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
this.findNextActionToEdit()
}
override fun cardValueSelected(value: Int) {
override fun cardValueSelected(value: Card.Value) {
this.model.cardValueSelected(value)
this.handHistoryAdapter.notifyDataSetChanged()
this.handHistoryAdapter.notifyItemChanged(this.model.currentSelection.index)
// TODO add test about number of cards before selecting next action?
// this.findNextActionToEdit()
@ -274,12 +275,26 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
override fun cardSuitSelected(suit: Card.Suit) {
this.model.cardSuitSelected(suit)
this.handHistoryAdapter.notifyDataSetChanged()
this.handHistoryAdapter.notifyItemChanged(this.model.currentSelection.index)
// TODO add test about number of cards?
// this.findNextActionToEdit()
}
override fun clearCards() {
this.model.clearCards()
this.handHistoryAdapter.notifyItemChanged(this.model.currentSelection.index)
}
override fun cardSelectionEnded() {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun cardBackSpaceSelected() {
this.model.deleteLastCardProperty()
this.handHistoryAdapter.notifyItemChanged(this.model.currentSelection.index)
}
override fun amountValidated() {
Timber.d(">>> amount validated")
this.model.amountValidated()
@ -293,9 +308,9 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
}
override fun closeKeyboard() {
this.model.currentSelection.value?.index?.let {
this.model.selectionLiveData.value?.index?.let {
this.handHistoryAdapter.notifyItemChanged(it)
this.model.currentSelection.value = null
this.model.selectionLiveData.value = null
}
this.keyboard?.hide()
}
@ -320,7 +335,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
}
private fun refreshCurrentRow() {
this.model.currentSelection.value?.index?.let {
this.model.selectionLiveData.value?.index?.let {
Timber.d("refreshes row at index = $it")
this.handHistoryAdapter.notifyItemChanged(it)
}

@ -14,51 +14,45 @@ import timber.log.Timber
class HandHistoryViewModel : ViewModel() {
var builderLiveData = MutableLiveData<HHBuilder>()
val builder: HHBuilder
get() {
return this.builderLiveData.value ?: throw PAIllegalStateException("Builder not found")
}
var isEdited = true
var currentSelection: MutableLiveData<HHSelection> = MutableLiveData()
var selectionLiveData: MutableLiveData<HHSelection> = MutableLiveData()
// var currentSelection: HHSelection? = null
// set(value) {
// field = value
// value?.let {
// Timber.d("Current selection is ${it.index} / ${it.keyboard}")
// } ?: run {
// Timber.d("No selection")
// }
// }
val currentSelection: HHSelection
get() { return selectionLiveData.value ?: throw PAIllegalStateException("No selection") }
var currentAmount: String? = null
var lastCardPropertySelection: CardProperty? = null
var builder = MutableLiveData<HHBuilder>()
fun setBuilder(builder: HHBuilder) {
this.builder.value = builder
}
fun test() {
// this.builder.
this.builderLiveData.value = builder
}
private val actionIndexForSelection: Int
get() {
this.currentSelection.value?.let { selection ->
return builder.value?.indexOfComputedAction(selection.index) ?: throw PAIllegalStateException("No builder")
} ?: throw PAIllegalStateException("No selection")
return this.builder.indexOfComputedAction(currentSelection.index)
}
// Action
fun actionSelected(action: Action.Type): List<Int>? {
builder.value?.let {
return it.selectAction(this.actionIndexForSelection, action)
} ?: throw PAIllegalStateException("Builder not found")
return this.builder.selectAction(this.actionIndexForSelection, action)
}
// Amount
fun amountValidated() {
try {
this.currentAmount?.toDouble()?.let { amount ->
builder.value?.setAmount(this.actionIndexForSelection, amount)
builderLiveData.value?.setAmount(this.actionIndexForSelection, amount)
this.currentAmount = null
}
} catch (e: NumberFormatException) {
@ -67,29 +61,31 @@ class HandHistoryViewModel : ViewModel() {
}
fun clearAmount() {
builder.value?.clearAmount(this.actionIndexForSelection)
builderLiveData.value?.clearAmount(this.actionIndexForSelection)
this.currentAmount = null
}
fun cardValueSelected(value: Int) {
// Cards
fun cardValueSelected(value: Card.Value) {
this.builder.cardValueSelected(value, this.currentSelection)
}
this.currentSelection.value?.let { selection ->
selection.index
// get the appropriate card list, board or player's hand and give the information
fun cardSuitSelected(suit: Card.Suit) {
this.builder.cardSuitSelected(suit, this.currentSelection)
}
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
fun clearCards() {
this.builder.clearCards(this.currentSelection)
}
fun cardSuitSelected(suit: Card.Suit) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
fun deleteLastCardProperty() {
this.builder.deleteLastCardProperty(this.currentSelection)
}
fun findIndexForEdition(startIndex: Int, keyboard: HHKeyboard? = null): HHKeyboard? {
builder.value?.let { builder ->
this.currentSelection.value = builder.findIndexForEdition(startIndex, keyboard)
return currentSelection.value?.keyboard
} ?: throw PAIllegalStateException("Builder not defined")
this.selectionLiveData.value = this.builder.findIndexForEdition(startIndex, keyboard)
return selectionLiveData.value?.keyboard
}
fun amountChanged(amount: String?) {
@ -97,15 +93,11 @@ class HandHistoryViewModel : ViewModel() {
}
fun positionsForSelection(): List<Position> {
this.builder.value?.let {
return it.positionsAtIndex(this.actionIndexForSelection)
} ?: throw PAIllegalStateException("Builder not defined")
return this.builder.positionsAtIndex(this.actionIndexForSelection)
}
fun nextActionIndexForPosition(position: Position): Int {
this.builder.value?.let {
return it.nextActionIndex(this.actionIndexForSelection, position)
} ?: throw PAIllegalStateException("Builder not defined")
return this.builder.nextActionIndex(this.actionIndexForSelection, position)
}
}

@ -0,0 +1,62 @@
package net.pokeranalytics.android.ui.modules.handhistory.views
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.handhistory.Card
import net.pokeranalytics.android.ui.adapter.BindableHolder
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.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.holder.RowViewHolder
import timber.log.Timber
class CardSuitAdapter(var keyboardListener: KeyboardListener) :
RecyclerView.Adapter<RecyclerView.ViewHolder>(),
RowRepresentableDataSource, RowRepresentableDelegate, RecyclerAdapter {
override var dataSource: RowRepresentableDataSource = this
override var delegate: RowRepresentableDelegate? = this
private val suits = Card.Suit.values().toList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_cell, parent, false)
return RowViewHolder(layout)
}
override fun getItemCount(): Int {
return this.suits.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
this.rowRepresentableForPosition(position)?.let {
(holder as BindableHolder).onBind(position, it, this)
}
}
override fun adapterRows(): List<RowRepresentable>? {
return this.suits
}
override fun rowRepresentableForPosition(position: Int): RowRepresentable? {
return this.suits[position]
}
override fun numberOfRows(): Int {
return this.suits.size
}
override fun viewTypeForPosition(position: Int): Int {
return RowViewType.TITLE_GRID.ordinal
}
override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) {
Timber.d("/////onRowSelected")
keyboardListener.cardSuitSelected(this.suits[position])
}
}

@ -0,0 +1,60 @@
package net.pokeranalytics.android.ui.modules.handhistory.views
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.handhistory.Card
import net.pokeranalytics.android.ui.adapter.BindableHolder
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.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.holder.RowViewHolder
import timber.log.Timber
class CardValueAdapter(var keyboardListener: KeyboardListener) :
RecyclerView.Adapter<RecyclerView.ViewHolder>(),
RowRepresentableDataSource, RowRepresentableDelegate, RecyclerAdapter {
override var dataSource: RowRepresentableDataSource = this
override var delegate: RowRepresentableDelegate? = this
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_cell, parent, false)
return RowViewHolder(layout)
}
override fun getItemCount(): Int {
return Card.Value.values.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
this.rowRepresentableForPosition(position)?.let {
(holder as BindableHolder).onBind(position, it, this)
}
}
override fun adapterRows(): List<RowRepresentable>? {
return Card.Value.values
}
override fun rowRepresentableForPosition(position: Int): RowRepresentable? {
return Card.Value.values[position]
}
override fun numberOfRows(): Int {
return Card.Value.values.size
}
override fun viewTypeForPosition(position: Int): Int {
return RowViewType.TITLE_GRID.ordinal
}
override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) {
Timber.d("/////onRowSelected")
keyboardListener.cardValueSelected(Card.Value.values[position])
}
}

@ -1,7 +1,67 @@
package net.pokeranalytics.android.ui.modules.handhistory.views
import android.content.Context
import android.view.LayoutInflater
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.view_hand_keyboard_action.view.closeButton
import kotlinx.android.synthetic.main.view_hand_keyboard_card.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException
class KeyboardCardView(context: Context) : AbstractKeyboardView(context) {
private lateinit var cardValueAdapter: CardValueAdapter
private lateinit var cardSuitAdapter: CardSuitAdapter
init {
LayoutInflater.from(context)
.inflate(R.layout.view_hand_keyboard_card, this, true)
this.nextButton.setOnClickListener {
this.keyboardListener?.cardSelectionEnded()
}
this.clearButton.setOnClickListener {
this.keyboardListener?.clearCards()
}
this.closeButton.setOnClickListener {
this.keyboardListener?.closeKeyboard()
}
this.backSpaceButton.setOnClickListener {
this.keyboardListener?.cardBackSpaceSelected()
}
}
override fun onListenerSet(listener: KeyboardListener) {
// Position Recycler
this.keyboardListener?.let {
this.cardValueAdapter = CardValueAdapter(it)
this.cardSuitAdapter = CardSuitAdapter(it)
} ?: throw PAIllegalStateException("keyboard listener not set")
val cardValueViewManager = GridLayoutManager(this.context, 7)
this.valueRecyclerView.apply {
setHasFixedSize(true)
layoutManager = cardValueViewManager
adapter = cardValueAdapter
// addItemDecoration(GridSpacingItemDecoration(spanCount, spacing, includeEdge))
}
val cardSuitViewManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
this.suitRecyclerView.apply {
setHasFixedSize(true)
layoutManager = cardSuitViewManager
adapter = cardSuitAdapter
// addItemDecoration(GridSpacingItemDecoration(spanCount, spacing, includeEdge))
}
}
}

@ -17,10 +17,13 @@ import net.pokeranalytics.android.model.realm.handhistory.Card
interface KeyboardListener {
fun actionSelected(action: Action.Type)
fun amountChanged(amount: String?)
fun cardValueSelected(value: Int)
fun cardSuitSelected(suit: Card.Suit)
fun amountValidated()
fun clearAmount()
fun cardValueSelected(value: Card.Value)
fun cardSuitSelected(suit: Card.Suit)
fun clearCards()
fun cardBackSpaceSelected()
fun cardSelectionEnded()
fun closeKeyboard()
fun positionSelected(position: Position)
}
@ -66,7 +69,7 @@ class KeyboardContainer(context: Context, attrs: AttributeSet?) : FrameLayout(co
val height = this.height.toFloat()
this.translationY = height
this.visibility = View.VISIBLE
this.animate().translationY(0.0f).setDuration(250).start();
this.animate().translationY(0.0f).setDuration(250).start()
}
}
@ -80,19 +83,6 @@ class KeyboardContainer(context: Context, attrs: AttributeSet?) : FrameLayout(co
show()
// var view = this.keyboards[type]
//
// if (view == null) {
// view = when(type) {
// HHKeyboard.ACTION -> { KeyboardActionView(context) }
// HHKeyboard.AMOUNT -> { KeyboardAmountView(context) }
// HHKeyboard.CARD -> { KeyboardCardView(context) }
// }
// view.keyboardListener = this.keyboardListener
// this.keyboards[type] = view
// addView(view)
// }
this.keyboards[type]?.let {
show(it)
} ?: run {

@ -41,7 +41,7 @@
android:layout_weight="2"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/doneButton"
android:id="@+id/nextButton"
style="@style/PokerAnalyticsTheme.Button"
android:text="@string/done"
android:layout_weight="1"
@ -65,8 +65,19 @@
android:layout_width="match_parent"
android:layout_height="50dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toStartOf="@id/backSpaceButton"
app:layout_constraintBottom_toBottomOf="parent"
/>
<com.google.android.material.button.MaterialButton
android:id="@+id/backSpaceButton"
style="@style/PokerAnalyticsTheme.Button"
android:text="@string/backspace"
android:layout_width="50dp"
android:layout_height="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -787,5 +787,6 @@
<string name="bet">bet</string>
<string name="raise">raise</string>
<string name="allin">allin</string>
<string name="backspace"></string>
</resources>

Loading…
Cancel
Save