More and more progress

hh
Laurent 6 years ago
parent 9ba73dc7c1
commit 7082ef7c23
  1. 309
      app/src/main/java/net/pokeranalytics/android/model/handhistory/HHBuilder.kt
  2. 4
      app/src/main/java/net/pokeranalytics/android/model/handhistory/HandSetup.kt
  3. 29
      app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt
  4. 14
      app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Action.kt
  5. 14
      app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt
  6. 8
      app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/PlayerSetup.kt
  7. 14
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryAdapter.kt
  8. 12
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryFragment.kt
  9. 6
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryViewModel.kt
  10. 129
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/CardsRow.kt
  11. 12
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/PlayerCardsRow.kt
  12. 23
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/StreetCardView.kt
  13. 3
      app/src/main/res/values/strings.xml

@ -6,8 +6,9 @@ import net.pokeranalytics.android.model.realm.handhistory.Action
import net.pokeranalytics.android.model.realm.handhistory.Card import net.pokeranalytics.android.model.realm.handhistory.Card
import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.modules.handhistory.HandRowType import net.pokeranalytics.android.ui.modules.handhistory.HandRowType
import net.pokeranalytics.android.ui.modules.handhistory.views.CardsRow
import net.pokeranalytics.android.ui.modules.handhistory.views.PlayerCardsRow import net.pokeranalytics.android.ui.modules.handhistory.views.PlayerCardsRow
import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardView import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardsRow
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.util.extensions.formatted import net.pokeranalytics.android.util.extensions.formatted
@ -22,7 +23,7 @@ enum class HHKeyboard {
class HHSelection(var index: Int, var keyboard: HHKeyboard) class HHSelection(var index: Int, var keyboard: HHKeyboard)
class HHBuilder : BoardChangedListener { class HHBuilder {
/*** /***
* The hand history * The hand history
@ -42,13 +43,24 @@ class HHBuilder : BoardChangedListener {
/*** /***
* The board cards sorted by position * The board cards sorted by position
*/ */
private lateinit var boardManager: BoardManager // private lateinit var boardManager: BoardManager
/*** /***
* A LinkedHashSet containing the sorted positions at the table * A LinkedHashSet containing the sorted positions at the table
*/ */
var positions: LinkedHashSet<Position> = linkedSetOf() var positions: LinkedHashSet<Position> = linkedSetOf()
/***
* The maximum number of cards in a player's hand
*/
private var playerHandMaxCards: Int? = null
set(value) {
field = value
this.rowRepresentables.filterIsInstance<PlayerCardsRow>().forEach {
it.maxCards = value
}
}
/*** /***
* Creates a builder using a [handSetup] * Creates a builder using a [handSetup]
* Also creates a new Hand History and configures it according to the [handSetup] * Also creates a new Hand History and configures it according to the [handSetup]
@ -56,6 +68,7 @@ class HHBuilder : BoardChangedListener {
constructor(handSetup: HandSetup) { constructor(handSetup: HandSetup) {
val handHistory = HandHistory() val handHistory = HandHistory()
handHistory.configure(handSetup) handHistory.configure(handSetup)
this.playerHandMaxCards = handSetup.game?.playerHandMaxCards
this.handHistory = handHistory this.handHistory = handHistory
} }
@ -92,7 +105,7 @@ class HHBuilder : BoardChangedListener {
} }
this.sortedActions = computedActions this.sortedActions = computedActions
this.boardManager = BoardManager(this.handHistory.board, this) // this.boardManager = BoardManager(this.handHistory.board, this)
this.createRowRepresentation() this.createRowRepresentation()
} }
@ -143,6 +156,7 @@ class HHBuilder : BoardChangedListener {
/*** /***
* Selects an action type for the action at the provided [index] * Selects an action type for the action at the provided [index]
* In case of UNDEFINED_ALLIN, we define which type of allin it is.
* If the user changes the current action, * If the user changes the current action,
* for convenience we remove all the following actions to avoid managing complex cases * for convenience we remove all the following actions to avoid managing complex cases
* Also calculates the player effective amounts in proper cases * Also calculates the player effective amounts in proper cases
@ -152,15 +166,43 @@ class HHBuilder : BoardChangedListener {
*/ */
fun selectAction(index: Int, actionType: Action.Type) : List<Int>? { fun selectAction(index: Int, actionType: Action.Type) : List<Int>? {
Timber.d(">>> Sets $actionType at index: $index") var type = actionType
val computedAction = this.actionForIndex(index) val computedAction = this.actionForIndex(index)
if (computedAction.action.type != actionType) {
computedAction.action.type = actionType // define allin type
if (type == Action.Type.UNDEFINED_ALLIN) {
val significant = getStreetLastSignificantAction(index)
if (significant != null) {
val betAmount = significant.action.amount
val remainingStack = computedAction.playerRemainingStack
if (remainingStack != null && betAmount != null && remainingStack < betAmount) {
type = Action.Type.CALL_ALLIN
} else {
type = Action.Type.RAISE_ALLIN
}
} else {
type = Action.Type.BET_ALLIN
}
}
Timber.d(">>> Sets $type at index: $index")
var structureModified = false
val actionPreviouslySet = (computedAction.action.type != null)
// set type + reset amount if type change
if (computedAction.action.type != type) {
computedAction.action.type = type
computedAction.action.amount = null computedAction.action.amount = null
if (actionPreviouslySet) {
structureModified = dropNextActionsIfNecessary(index)
}
} }
when (actionType) { // define action amounts if possible
when (type) {
Action.Type.CALL -> { Action.Type.CALL -> {
val significantAction = getStreetLastSignificantAction(index) val significantAction = getStreetLastSignificantAction(index)
?: throw PAIllegalStateException("There must be a previously set significant action for a call to be set") ?: throw PAIllegalStateException("There must be a previously set significant action for a call to be set")
@ -175,26 +217,28 @@ class HHBuilder : BoardChangedListener {
Action.Type.STRADDLE -> { Action.Type.STRADDLE -> {
// TODO // TODO
} }
Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN, Action.Type.UNDEFINED_ALLIN -> {
computedAction.action.amount = computedAction.playerRemainingStack
}
else -> {} else -> {}
} }
val dropedIndex = dropNextActionsIfNecessary(index)
val structureModified = this.updateFollowupActions(index) structureModified = this.updateFollowupActions(index) || structureModified
// Automatically sets action for the previous empty actions // Automatically sets action for the previous empty actions
val modifiedActions = mutableListOf<ComputedAction>() val modifiedActions = mutableListOf<ComputedAction>()
getPreviousEmptyActions(index).forEach { getPreviousEmptyActions(index).forEach {
modifiedActions.add(it) modifiedActions.add(it)
val lastSignificant = getStreetLastSignificantAction(index) val lastSignificant = getStreetLastSignificantAction(index)
if (lastSignificant != null) { it.action.type = if (lastSignificant != null) {
it.action.type = Action.Type.FOLD Action.Type.FOLD
} else { } else {
it.action.type = Action.Type.CHECK Action.Type.CHECK
} }
} }
if (dropedIndex != null || structureModified) return null if (structureModified) return null
return modifiedActions.map { this.rowRepresentables.indexOf(it) } return modifiedActions.map { this.rowRepresentables.indexOf(it) }
} }
@ -212,11 +256,21 @@ class HHBuilder : BoardChangedListener {
addsFollowupActionsIfNecessary(index) addsFollowupActionsIfNecessary(index)
} }
false -> { // closes the action, pass to next street if necessary false -> { // closes the action, pass to next street if necessary
if (type == Action.Type.CALL_ALLIN) { // sometimes we can go from RAISE_ALLIN to CALL_IN, changing the actions required
removeActionsIfNecessary(index)
}
createNextStreetIfNecessary(index) createNextStreetIfNecessary(index)
} }
else -> false else -> false
} }
}
/***
* Recreates the actions after [index]
*/
private fun removeActionsIfNecessary(index: Int) {
this.sortedActions = this.sortedActions.take(index + 1).toMutableList()
addsFollowupActionsIfNecessary(index)
} }
/*** /***
@ -269,7 +323,7 @@ class HHBuilder : BoardChangedListener {
/*** /***
* Returns the list of position still in play before the given [index] * Returns the list of position still in play before the given [index]
*/ */
private fun activePositions(index: Int) : MutableList<Position> { private fun activePositions(index: Int): MutableList<Position> {
val oustedPositions = this.sortedActions.take(index + 1) val oustedPositions = this.sortedActions.take(index + 1)
.filter { it.action.type?.isPullOut ?: false } .filter { it.action.type?.isPullOut ?: false }
.map { it.position } .map { it.position }
@ -284,56 +338,12 @@ class HHBuilder : BoardChangedListener {
* Returns true if a street has been created * Returns true if a street has been created
*/ */
private fun createNextStreetIfNecessary(index: Int) : Boolean { private fun createNextStreetIfNecessary(index: Int) : Boolean {
val nextStreet = isStreetActionClosed(index) val nextStreet = isStreetActionClosed(index)
if (nextStreet != null) { if (nextStreet != null) {
createStreet(nextStreet) createStreet(nextStreet)
return true return true
} }
return false 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
} }
/*** /***
@ -377,15 +387,25 @@ class HHBuilder : BoardChangedListener {
* following an action change. * following an action change.
* We want drop all non-auto added rows after the index * We want drop all non-auto added rows after the index
*/ */
private fun dropNextActionsIfNecessary(index: Int) : Int? { private fun dropNextActionsIfNecessary(index: Int) : Boolean {
// val dropIndex = index + 1 // TODO determine dropIndex
// this.sortedActions = this.sortedActions.take(dropIndex) val street = this.actionForIndex(index).action.street
return null val firstIndexOfStreet = this.sortedActions.first { it.action.street == street }.action.index
val activePositions = activePositions(firstIndexOfStreet)
val defaultRowsCount = when (street) {
Street.PREFLOP -> activePositions.size + 2
else -> activePositions.size
}
val sizeBefore = this.sortedActions.size
this.sortedActions = this.sortedActions.take(index + defaultRowsCount).toMutableList()
val sizeAfter = this.sortedActions.size
return sizeAfter != sizeBefore
} }
/*** /***
* Sets the amount for the action at the provided [index] * Sets the amount for the action at the provided [index]
* In the case of an UNDEFINED_ALLIN, define if it's a RAISE_ALLIN or a CALL_ALLIN * In the case of a RAISE_ALLIN, check if it's a CALL_ALLIN
*/ */
fun setAmount(index: Int, amount: Double) { fun setAmount(index: Int, amount: Double) {
@ -397,36 +417,27 @@ class HHBuilder : BoardChangedListener {
when (computedAction.action.type) { when (computedAction.action.type) {
Action.Type.BET, Action.Type.RAISE, Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN -> { Action.Type.BET, Action.Type.RAISE, Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN -> {
getNextCalls(index).forEach { getStreetNextCalls(index).forEach {
it.setEffectiveAmount(amount) it.setEffectiveAmount(amount)
} }
} // verify if the raise is not a call after all
Action.Type.UNDEFINED_ALLIN -> { if (computedAction.action.type == Action.Type.RAISE_ALLIN) {
getStreetLastSignificantAction(index)?.action?.amount?.let { significantActionAmount ->
getStreetLastSignificantAction(index)?.action?.amount?.let { significantActionAmount ->
val committedAmount = getPreviousCommittedAmount(index) ?: 0.0 val committedAmount = getPreviousCommittedAmount(index) ?: 0.0
val askedAmount = significantActionAmount - committedAmount val askedAmount = significantActionAmount - committedAmount
computedAction.playerRemainingStack?.let { remainingStack -> computedAction.playerRemainingStack?.let { remainingStack ->
if (remainingStack < askedAmount) {
if (remainingStack > askedAmount) {
selectAction(index, Action.Type.RAISE_ALLIN)
} else {
selectAction(index, Action.Type.CALL_ALLIN) selectAction(index, Action.Type.CALL_ALLIN)
} }
} ?: run {
selectAction(index, Action.Type.RAISE_ALLIN)
} }
}
} ?: run {
selectAction(index, Action.Type.RAISE_ALLIN)
} }
} }
else -> {} else -> {}
} }
} }
/*** /***
@ -467,11 +478,11 @@ class HHBuilder : BoardChangedListener {
/*** /***
* Returns all "CALL" ComputedAction between the [index] and the next significant action * Returns all "CALL" ComputedAction between the [index] and the next significant action
*/ */
private fun getNextCalls(index: Int) : List<ComputedAction> { private fun getStreetNextCalls(index: Int) : List<ComputedAction> {
val nextSignificantIndex = getNextSignificantAction(index)?.action?.index ?: lastIndexOfStreet(index) val streetNextSignificantIndex = getStreetNextSignificantAction(index)?.action?.index ?: lastIndexOfStreet(index)
return this.sortedActions.filter { return this.sortedActions.filter {
it.action.index in (index + 1) until nextSignificantIndex && it.action.index in ((index + 1) until streetNextSignificantIndex)
(it.action.type == Action.Type.CALL || it.action.type == Action.Type.CALL_ALLIN) && (it.action.type?.isCall ?: false)
} }
} }
@ -508,7 +519,7 @@ class HHBuilder : BoardChangedListener {
/*** /***
* Returns the next significant player action in the street, if any, for the action at the provided [index] * Returns the next significant player action in the street, if any, for the action at the provided [index]
*/ */
private fun getNextSignificantAction(index: Int): ComputedAction? { private fun getStreetNextSignificantAction(index: Int): ComputedAction? {
val street = this.actionForIndex(index).action.street val street = this.actionForIndex(index).action.street
val nextActions = this.sortedActions.drop(index + 1).filter { it.action.street == street } val nextActions = this.sortedActions.drop(index + 1).filter { it.action.street == street }
return nextActions.firstOrNull { it.action.isActionSignificant } return nextActions.firstOrNull { it.action.isActionSignificant }
@ -544,7 +555,7 @@ class HHBuilder : BoardChangedListener {
* Finds the index of the first incomplete action, if existing * Finds the index of the first incomplete action, if existing
* If the same selection is the same than current, pass to the next row * If the same selection is the same than current, pass to the next row
*/ */
fun findIndexForEdition(startIndex: Int, keyboard: HHKeyboard? = null): HHSelection? { fun findIndexForEdition(startIndex: Int): HHSelection? {
this.rowRepresentables.forEachIndexed { index, rowRepresentable -> this.rowRepresentables.forEachIndexed { index, rowRepresentable ->
@ -579,12 +590,21 @@ class HHBuilder : BoardChangedListener {
* Adds a card with the selected [value] * Adds a card with the selected [value]
*/ */
fun cardValueSelected(value: Card.Value, currentSelection: HHSelection) { fun cardValueSelected(value: Card.Value, currentSelection: HHSelection) {
when (this.rowRepresentables[currentSelection.index]) {
is StreetCardView -> { val row = this.rowRepresentables[currentSelection.index] as CardsRow
val card = Card.newInstance(value.value) row.valueSelected(value)
this.boardManager.add(card)
} // when (val row = this.rowRepresentables[currentSelection.index]) {
} // is CardsRow -> {
// val card = Card.newInstance(value.value)
// row.add(card)
// }
// is PlayerCardsRow -> {
// val positionIndex = this.positions.indexOf(row.position)
// val playerSetup = this.handHistory.playerSetupForPosition(positionIndex)
// playerSetup.cardValueSelected(value)
// }
// }
} }
/*** /***
@ -593,36 +613,49 @@ class HHBuilder : BoardChangedListener {
*/ */
fun cardSuitSelected(suit: Card.Suit, currentSelection: HHSelection) { fun cardSuitSelected(suit: Card.Suit, currentSelection: HHSelection) {
when (val row = this.rowRepresentables[currentSelection.index]) { val row = this.rowRepresentables[currentSelection.index] as CardsRow
is StreetCardView -> { row.suitSelected(suit)
val addNewCard = this.boardManager.lastCard(row.street)?.let {
if (it.suit != null) {
true
} else {
it.suit = suit
false
}
} ?: true
if (addNewCard) { // TODO do we want to store the information right now ?
val card = Card.newInstance(suit = suit)
this.boardManager.add(card)
}
} // when (val row = this.rowRepresentables[currentSelection.index]) {
} // is StreetCardsRow -> {
//
// 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)
// }
// }
// is PlayerCardsRow -> {
// val positionIndex = this.positions.indexOf(row.position)
// val playerSetup = this.handHistory.playerSetupForPosition(positionIndex)
// playerSetup.cardSuitSelected(suit)
// }
// }
} }
/*** /***
* Deletes all the card of the selected street * Deletes all the card of the selected street
*/ */
fun clearCards(currentSelection: HHSelection) { fun clearCards(currentSelection: HHSelection) {
when (val row = this.rowRepresentables[currentSelection.index]) {
is StreetCardView -> { val row = this.rowRepresentables[currentSelection.index] as CardsRow
this.boardManager.clearStreet(row.street) row.clear()
}
} // when (val row = this.rowRepresentables[currentSelection.index]) {
// is StreetCardsRow -> {
// this.boardManager.clearStreet(row.street)
// }
// }
} }
@ -633,22 +666,41 @@ class HHBuilder : BoardChangedListener {
*/ */
fun deleteLastCardProperty(currentSelection: HHSelection) { fun deleteLastCardProperty(currentSelection: HHSelection) {
when (val row = this.rowRepresentables[currentSelection.index]) { val row = this.rowRepresentables[currentSelection.index] as CardsRow
is StreetCardView -> { row.deleteLastCardProperty()
this.boardManager.lastCard(row.street)?.let { card ->
if (card.value != null && card.suit != null) { // when (val row = this.rowRepresentables[currentSelection.index]) {
card.suit = null // is StreetCardsRow -> {
} else { // this.boardManager.lastCard(row.street)?.let { card ->
this.boardManager.remove(card) // if (card.value != null && card.suit != null) {
} // card.suit = null
} // } else {
// this.boardManager.remove(card)
// }
// }
// }
// }
} }
/***
* When a card selection is ended,
* sets the playerHandMaxCards with the number of cards set to the player
*/
fun cardSelectionEnded(index: Int) {
val cardsRow = this.rowRepresentables[index] as CardsRow
if (cardsRow is PlayerCardsRow) {
this.playerHandMaxCards = cardsRow.cards.size
} }
} }
override fun boardChanged() { // BoardChangedListener
this.rowRepresentables.filterIsInstance<StreetCardView>().forEach {
it.cards = this.boardManager.allCards /***
* Called when the board has changed
*/
fun boardChanged(cards: List<Card>) {
this.rowRepresentables.filterIsInstance<StreetCardsRow>().forEach {
// it.cards = cards
} }
} }
@ -684,7 +736,7 @@ class HHBuilder : BoardChangedListener {
activePositions(lastActionIndex).forEach { activePositions(lastActionIndex).forEach {
val positionIndex = this.positions.indexOf(it) val positionIndex = this.positions.indexOf(it)
val playerCardsRow = PlayerCardsRow(it, this.handHistory.cardsForPosition(positionIndex)) val playerCardsRow = PlayerCardsRow(it, this.handHistory.cardsForPosition(positionIndex), this.playerHandMaxCards)
this.rowRepresentables.add(playerCardsRow) this.rowRepresentables.add(playerCardsRow)
} }
} }
@ -758,11 +810,12 @@ class HHBuilder : BoardChangedListener {
* Adds a [street] header to a [rowRepresentables] list with a given [potSize] * Adds a [street] header to a [rowRepresentables] list with a given [potSize]
*/ */
private fun addStreetHeader(rowRepresentables: MutableList<RowRepresentable>, street: Street, potSize: Double) { private fun addStreetHeader(rowRepresentables: MutableList<RowRepresentable>, street: Street, potSize: Double) {
val headerView = CustomizableRowRepresentable(customViewType = HandRowType.HEADER, resId = street.resId, value = potSize.formatted()) val potString = if (potSize > 0) potSize.formatted() else null
val headerView = CustomizableRowRepresentable(customViewType = HandRowType.HEADER, resId = street.resId, value = potString)
rowRepresentables.add(headerView) rowRepresentables.add(headerView)
if (street.totalBoardCards > 0) { if (street.totalBoardCards > 0) {
val boardView = StreetCardView(street, this.handHistory.cardsForStreet(street)) val boardView = StreetCardsRow(street, this.handHistory.cardsForStreet(street))
rowRepresentables.add(boardView) rowRepresentables.add(boardView)
} }

@ -1,5 +1,7 @@
package net.pokeranalytics.android.model.handhistory package net.pokeranalytics.android.model.handhistory
import net.pokeranalytics.android.model.realm.Game
class HandSetup { class HandSetup {
var smallBlind: Double? = null var smallBlind: Double? = null
@ -12,4 +14,6 @@ class HandSetup {
var bigBlindAnte: Boolean = false var bigBlindAnte: Boolean = false
var game: Game? = null
} }

@ -30,7 +30,6 @@ open class Game : RealmObject(), NameManageable, StaticRowRepresentableDataSourc
val rowRepresentation : List<RowRepresentable> by lazy { val rowRepresentation : List<RowRepresentable> by lazy {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()
rows.add(SimpleRow.NAME) rows.add(SimpleRow.NAME)
// rows.addAll(GameRow.values())
rows rows
} }
} }
@ -62,7 +61,7 @@ open class Game : RealmObject(), NameManageable, StaticRowRepresentableDataSourc
} }
override fun adapterRows(): List<RowRepresentable>? { override fun adapterRows(): List<RowRepresentable>? {
return Game.rowRepresentation return rowRepresentation
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(row: RowRepresentable): String {
@ -103,4 +102,30 @@ open class Game : RealmObject(), NameManageable, StaticRowRepresentableDataSourc
override fun isValidForDelete(realm: Realm): Boolean { override fun isValidForDelete(realm: Realm): Boolean {
return realm.where<Session>().equalTo("game.id", id).findAll().isEmpty() return realm.where<Session>().equalTo("game.id", id).findAll().isEmpty()
} }
val playerHandMaxCards: Int?
get() {
return when {
isHoldem -> 2
isOmaha5 -> 5
isOmaha4 -> 4
else -> null
}
}
private val isHoldem: Boolean
get() {
return name.contains("texas", ignoreCase = true) || name.contains("holdem", ignoreCase = true) || name.contains("hold'em", ignoreCase = true) || name.contains("HE")
}
private val isOmaha4: Boolean
get() {
return name.contains("omaha", ignoreCase = true) || name.contains("PLO", ignoreCase = true)
}
private val isOmaha5: Boolean
get() {
return name.contains("5")
}
} }

@ -21,9 +21,9 @@ open class Action : RealmObject() {
BET(R.string.bet), BET(R.string.bet),
RAISE(R.string.raise), RAISE(R.string.raise),
UNDEFINED_ALLIN(R.string.allin), UNDEFINED_ALLIN(R.string.allin),
CALL_ALLIN(R.string.allin), CALL_ALLIN(R.string.callin),
BET_ALLIN(R.string.allin), BET_ALLIN(R.string.ballin),
RAISE_ALLIN(R.string.allin); RAISE_ALLIN(R.string.rallin);
val isSignificant: Boolean val isSignificant: Boolean
get() { get() {
@ -53,6 +53,14 @@ open class Action : RealmObject() {
} }
} }
val isCall: Boolean
get() {
return when (this) {
CALL, CALL_ALLIN -> true
else -> false
}
}
val requiresOpponentDecision: Boolean val requiresOpponentDecision: Boolean
get() { get() {
return when(this) { return when(this) {

@ -105,7 +105,7 @@ open class HandHistory : RealmObject(), RowRepresentable, Identifiable, Filterab
handSetup.bigBlind?.let { this.bigBlind = it } handSetup.bigBlind?.let { this.bigBlind = it }
this.addAction(0, 0, Action.Type.POST_SB, this.smallBlind) this.addAction(0, 0, Action.Type.POST_SB, this.smallBlind)
// this.addAction(1, 1, Action.Type.POST_BB, this.bigBlind) this.addAction(1, 1, Action.Type.POST_BB, this.bigBlind)
val totalActions = this.actions.size val totalActions = this.actions.size
@ -128,8 +128,18 @@ open class HandHistory : RealmObject(), RowRepresentable, Identifiable, Filterab
return this.board.sortedBy { it.index }.take(street.totalBoardCards).toMutableList() return this.board.sortedBy { it.index }.take(street.totalBoardCards).toMutableList()
} }
fun playerSetupForPosition(position: Int) : PlayerSetup {
this.playerSetups.firstOrNull { it.position == position }?.let {
return it
}
val ps = PlayerSetup()
ps.position = position
return ps
}
fun cardsForPosition(position: Int): List<Card> { fun cardsForPosition(position: Int): List<Card> {
return this.playerSetups.first { it.position == position }.cards return this.playerSetups.firstOrNull { it.position == position }?.cards ?: listOf()
} }
} }

@ -26,4 +26,12 @@ open class PlayerSetup : RealmObject() {
*/ */
var cards: RealmList<Card> = RealmList() var cards: RealmList<Card> = RealmList()
fun cardValueSelected(value: Card.Value) {
}
fun cardSuitSelected(suit: Card.Suit) {
}
} }

@ -23,7 +23,7 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.extensions.hideKeyboard import net.pokeranalytics.android.ui.extensions.hideKeyboard
import net.pokeranalytics.android.ui.modules.handhistory.views.PlayerCardsRow import net.pokeranalytics.android.ui.modules.handhistory.views.PlayerCardsRow
import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardView import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardsRow
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.holder.RowViewHolder import net.pokeranalytics.android.ui.view.holder.RowViewHolder
import net.pokeranalytics.android.ui.view.rowrepresentable.ViewIdentifier import net.pokeranalytics.android.ui.view.rowrepresentable.ViewIdentifier
@ -258,7 +258,7 @@ class HandHistoryAdapter(
this.currentPosition = position this.currentPosition = position
val streetCardView = row as StreetCardView val streetCardView = row as StreetCardsRow
val street = streetCardView.street val street = streetCardView.street
itemView.findViewById<EditText>(R.id.flopEditText)?.let { flopEditText -> itemView.findViewById<EditText>(R.id.flopEditText)?.let { flopEditText ->
@ -269,6 +269,10 @@ class HandHistoryAdapter(
val flop = streetCardView.cards.take(3) val flop = streetCardView.cards.take(3)
val text = flop.formatted(itemView.context) val text = flop.formatted(itemView.context)
flopEditText.setText(text) flopEditText.setText(text)
val selected = adapter.dataSource.isSelected(position, row, Street.FLOP.ordinal)
if (!selected) flopEditText.clearFocus()
} }
itemView.findViewById<EditText>(R.id.turnEditText)?.let { turnEditText -> itemView.findViewById<EditText>(R.id.turnEditText)?.let { turnEditText ->
@ -281,6 +285,9 @@ class HandHistoryAdapter(
} else { } else {
turnEditText.text = null turnEditText.text = null
} }
val selected = adapter.dataSource.isSelected(position, row, Street.FLOP.ordinal)
if (!selected) turnEditText.clearFocus()
} }
itemView.findViewById<EditText>(R.id.riverEditText)?.let { riverEditText -> itemView.findViewById<EditText>(R.id.riverEditText)?.let { riverEditText ->
@ -293,6 +300,9 @@ class HandHistoryAdapter(
} else { } else {
riverEditText.text = null riverEditText.text = null
} }
val selected = adapter.dataSource.isSelected(position, row, Street.FLOP.ordinal)
if (!selected) riverEditText.clearFocus()
} }
} }

@ -17,7 +17,8 @@ import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.modules.handhistory.views.KeyboardListener import net.pokeranalytics.android.ui.modules.handhistory.views.KeyboardListener
import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardView import net.pokeranalytics.android.ui.modules.handhistory.views.PlayerCardsRow
import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardsRow
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager
import net.pokeranalytics.android.util.extensions.findById import net.pokeranalytics.android.util.extensions.findById
@ -199,7 +200,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
else -> throw PAIllegalStateException("Unmanaged tag value: $tag") else -> throw PAIllegalStateException("Unmanaged tag value: $tag")
} }
} }
is StreetCardView -> { is StreetCardsRow, is PlayerCardsRow -> {
HHKeyboard.CARD HHKeyboard.CARD
} }
else -> throw PAIllegalStateException("unmanaged row type: $row") else -> throw PAIllegalStateException("unmanaged row type: $row")
@ -240,16 +241,12 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
override fun cardValueSelected(value: Card.Value) { override fun cardValueSelected(value: Card.Value) {
this.model.cardValueSelected(value) this.model.cardValueSelected(value)
this.handHistoryAdapter.notifyItemChanged(this.model.currentSelection.index) this.handHistoryAdapter.notifyItemChanged(this.model.currentSelection.index)
// TODO add test about number of cards before selecting next action?
this.findNextActionToEdit() this.findNextActionToEdit()
} }
override fun cardSuitSelected(suit: Card.Suit) { override fun cardSuitSelected(suit: Card.Suit) {
this.model.cardSuitSelected(suit) this.model.cardSuitSelected(suit)
this.handHistoryAdapter.notifyItemChanged(this.model.currentSelection.index) this.handHistoryAdapter.notifyItemChanged(this.model.currentSelection.index)
// TODO add test about number of cards?
this.findNextActionToEdit() this.findNextActionToEdit()
} }
@ -259,7 +256,8 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
} }
override fun cardSelectionEnded() { override fun cardSelectionEnded() {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates. this.model.cardSelectionEnded()
this.findNextActionToEdit()
} }
override fun cardBackSpaceSelected() { override fun cardBackSpaceSelected() {

@ -83,7 +83,7 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource {
} }
fun findIndexForEdition(index: Int): HHKeyboard? { fun findIndexForEdition(index: Int): HHKeyboard? {
val selection = this.builder.findIndexForEdition(index, this.selectionLiveData.value?.keyboard) val selection = this.builder.findIndexForEdition(index)
this.selectionLiveData.value = selection this.selectionLiveData.value = selection
return selection?.keyboard return selection?.keyboard
} }
@ -125,4 +125,8 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource {
return isSelectedIndex && isSelectedAction return isSelectedIndex && isSelectedAction
} }
fun cardSelectionEnded() {
this.builder.cardSelectionEnded(this.currentSelection.index)
}
} }

@ -0,0 +1,129 @@
package net.pokeranalytics.android.ui.modules.handhistory.views
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.handhistory.HHKeyboard
import net.pokeranalytics.android.model.handhistory.HandHistoryRow
import net.pokeranalytics.android.model.handhistory.Position
import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.model.realm.handhistory.Card
import net.pokeranalytics.android.ui.modules.handhistory.HandRowType
abstract class CardsRow(cards: List<Card>) : HandHistoryRow {
var cards: MutableList<Card> = cards.toMutableList()
private set
private val MAX_CARDS: Int = 7
abstract fun cardLimit() : Int?
override fun keyboardForCompletion(): HHKeyboard? {
return if (cards.size < cardLimit() ?: MAX_CARDS) {
HHKeyboard.CARD
} else if (cards.last().suit == null) {
HHKeyboard.CARD
} else {
null
}
}
fun valueSelected(value: Card.Value) {
val card = Card.newInstance(value.value)
this.add(card)
}
fun suitSelected(suit: Card.Suit) {
val addNewCard = this.lastCard()?.let {
if (it.suit != null) {
true
} else {
it.suit = suit
false
}
} ?: true
if (addNewCard) {
val card = Card.newInstance(suit = suit)
this.add(card)
}
}
protected open fun lastCard() : Card? {
return this.cards.lastOrNull()
}
/***
* Adds a card to the board, notifies the listener
*/
private fun add(card: Card) {
this.cards.lastOrNull()?.let {
if (it.suit == null) {
it.suit = Card.Suit.UNDEFINED
}
}
if (this.cards.size == 5) {
throw PAIllegalStateException("Can't add anymore cards")
}
card.index = this.cards.size
this.cards.add(card)
}
open fun clear() {
this.cards.clear()
}
/***
* Remove the given [card], notifies the listener
*/
private fun remove(card: Card) {
this.cards.remove(card)
}
/***
* Delete the last card property
*/
fun deleteLastCardProperty() {
this.lastCard()?.let { card ->
if (card.value != null && card.suit != null) {
card.suit = null
} else {
this.remove(card)
}
}
}
}
class StreetCardsRow(var street: Street, cards: List<Card>) : CardsRow(cards) {
override val viewType: Int = HandRowType.STREET.ordinal
override fun cardLimit() : Int {
return this.street.totalBoardCards
}
override fun lastCard(): Card? {
return this.cards.lastOrNull { it.street == this.street }
}
override fun clear() {
this.cards.removeAll { it.street == this.street }
}
}
class PlayerCardsRow(var position: Position, cards: List<Card> = listOf(), var maxCards: Int? = null) : CardsRow(cards) {
override val viewType: Int = HandRowType.PLAYER_SUMMARY.ordinal
override fun cardLimit() : Int? {
return this.maxCards
}
}

@ -1,12 +0,0 @@
package net.pokeranalytics.android.ui.modules.handhistory.views
import net.pokeranalytics.android.model.handhistory.Position
import net.pokeranalytics.android.model.realm.handhistory.Card
import net.pokeranalytics.android.ui.modules.handhistory.HandRowType
import net.pokeranalytics.android.ui.view.RowRepresentable
class PlayerCardsRow(var position: Position, var cards: List<Card> = listOf()) : RowRepresentable {
override val viewType: Int = HandRowType.PLAYER_SUMMARY.ordinal
}

@ -1,23 +0,0 @@
package net.pokeranalytics.android.ui.modules.handhistory.views
import net.pokeranalytics.android.model.handhistory.HHKeyboard
import net.pokeranalytics.android.model.handhistory.HandHistoryRow
import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.model.realm.handhistory.Card
import net.pokeranalytics.android.ui.modules.handhistory.HandRowType
class StreetCardView(var street: Street, var cards: List<Card>) : HandHistoryRow {
override val viewType: Int = HandRowType.STREET.ordinal
override fun keyboardForCompletion(): HHKeyboard? {
return if (cards.size < street.totalBoardCards) {
HHKeyboard.CARD
} else if (cards.last().suit == null) {
HHKeyboard.CARD
} else {
null
}
}
}

@ -787,6 +787,9 @@
<string name="bet">bet</string> <string name="bet">bet</string>
<string name="raise">raise</string> <string name="raise">raise</string>
<string name="allin">allin</string> <string name="allin">allin</string>
<string name="ballin">b_allin</string>
<string name="callin">c_allin</string>
<string name="rallin">r_allin</string>
<string name="backspace"></string> <string name="backspace"></string>
</resources> </resources>

Loading…
Cancel
Save