Adds blinds + straddle rows

hh
Laurent 6 years ago
parent 08012fc88e
commit cc2a7fbbec
  1. 22
      app/src/main/java/net/pokeranalytics/android/model/handhistory/HandSetup.kt
  2. 7
      app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt
  3. 7
      app/src/main/java/net/pokeranalytics/android/model/realm/Player.kt
  4. 7
      app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt
  5. 7
      app/src/main/java/net/pokeranalytics/android/model/realm/TournamentName.kt
  6. 8
      app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt
  7. 23
      app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt
  8. 4
      app/src/main/java/net/pokeranalytics/android/ui/adapter/RowRepresentableDataSource.kt
  9. 5
      app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt
  10. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/FilterDetailsFragment.kt
  11. 5
      app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt
  12. 5
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt
  13. 5
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetTableSizeGridFragment.kt
  14. 7
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt
  15. 7
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/CustomFieldDataFragment.kt
  16. 7
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/LocationDataFragment.kt
  17. 7
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/PlayerDataFragment.kt
  18. 7
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/TransactionDataFragment.kt
  19. 7
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/TransactionTypeDataFragment.kt
  20. 51
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryAdapter.kt
  21. 21
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryFragment.kt
  22. 4
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt
  23. 6
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt
  24. 9
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/HandHistorySettings.kt
  25. 107
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/HandHistoryViewModel.kt
  26. 2
      app/src/main/res/layout/row_hand_action.xml
  27. 2
      app/src/main/res/layout/row_hhsettings_blinds.xml
  28. 3
      app/src/main/res/layout/row_hhsettings_player_setup.xml
  29. 58
      app/src/main/res/layout/row_hhsettings_straddle.xml

@ -1,6 +1,7 @@
package net.pokeranalytics.android.model.handhistory package net.pokeranalytics.android.model.handhistory
import net.pokeranalytics.android.model.realm.Game import net.pokeranalytics.android.model.realm.Game
import java.util.*
class HandSetup { class HandSetup {
@ -16,4 +17,25 @@ class HandSetup {
var game: Game? = null var game: Game? = null
var straddlePositions: SortedSet<Position> = sortedSetOf()
fun clearStraddles() {
this.straddlePositions.clear()
}
/***
* This method sorts the straddle positions in their natural order
* If the straddle position contains the button, we're usually in a Mississipi straddle,
* meaning the BUT straddles, then CO, then HJ...
* Except if it goes to UTG, in which case we don't know if we're in standard straddle, or Mississipi
* We use the first straddled position to sort out this case
*/
fun setStraddlePositions(firstStraddlePosition: Position, positions: LinkedHashSet<Position>) {
var sortedPosition = positions.sortedBy { it.ordinal }
if (positions.contains(Position.BUT) && firstStraddlePosition != Position.UTG) {
sortedPosition = sortedPosition.reversed()
}
this.straddlePositions = sortedPosition.toSortedSet()
}
} }

@ -64,11 +64,14 @@ open class Game : RealmObject(), NameManageable, StaticRowRepresentableDataSourc
return rowRepresentation return rowRepresentation
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
SimpleRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT SimpleRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT
GameRow.SHORT_NAME -> this.shortName ?: NULL_TEXT GameRow.SHORT_NAME -> this.shortName ?: NULL_TEXT
else -> return super.stringForRow(row) else -> return super.stringForRow(row, 0)
} }
} }

@ -75,10 +75,13 @@ open class Player : RealmObject(), NameManageable, Deletable, StaticRowRepresent
return this.name return this.name
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
PlayerRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT PlayerRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT
else -> return super.stringForRow(row) else -> return super.stringForRow(row, 0)
} }
} }

@ -56,10 +56,13 @@ open class TournamentFeature : RealmObject(), NameManageable, StaticRowRepresent
return TournamentFeature.rowRepresentation return TournamentFeature.rowRepresentation
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
SimpleRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT SimpleRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT
else -> return super.stringForRow(row) else -> return super.stringForRow(row, 0)
} }
} }

@ -53,10 +53,13 @@ open class TournamentName : RealmObject(), NameManageable, StaticRowRepresentabl
return TournamentName.rowRepresentation return TournamentName.rowRepresentation
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
SimpleRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT SimpleRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT
else -> return super.stringForRow(row) else -> return super.stringForRow(row, 0)
} }
} }

@ -1,7 +1,6 @@
package net.pokeranalytics.android.model.realm package net.pokeranalytics.android.model.realm
import android.content.Context import android.content.Context
import com.crashlytics.android.Crashlytics
import io.realm.Realm import io.realm.Realm
import io.realm.RealmModel import io.realm.RealmModel
import io.realm.RealmObject import io.realm.RealmObject
@ -107,10 +106,13 @@ open class TransactionType : RealmObject(), NameManageable, StaticRowRepresentab
return rowRepresentation return rowRepresentation
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
SimpleRow.NAME -> this.name SimpleRow.NAME -> this.name
else -> return super.stringForRow(row) else -> return super.stringForRow(row, 0)
} }
} }

@ -6,15 +6,16 @@ import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.Filterable
import net.pokeranalytics.android.model.handhistory.HandSetup import net.pokeranalytics.android.model.handhistory.HandSetup
import net.pokeranalytics.android.model.handhistory.Position
import net.pokeranalytics.android.model.handhistory.Street import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.interfaces.TimeFilterable import net.pokeranalytics.android.model.interfaces.TimeFilterable
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.modules.handhistory.views.CardHolder import net.pokeranalytics.android.ui.modules.handhistory.views.CardHolder
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import timber.log.Timber
import java.util.* import java.util.*
open class HandHistory : RealmObject(), RowRepresentable, Identifiable, Filterable, TimeFilterable, CardHolder { open class HandHistory : RealmObject(), RowRepresentable, Identifiable, Filterable, TimeFilterable, CardHolder {
@PrimaryKey @PrimaryKey
@ -101,6 +102,8 @@ open class HandHistory : RealmObject(), RowRepresentable, Identifiable, Filterab
// Card.valueOf(10, Card.Suit.DIAMOND), // Card.valueOf(10, Card.Suit.DIAMOND),
// Card.valueOf(12, Card.Suit.SPADES))) // Card.valueOf(12, Card.Suit.SPADES)))
this.actions.clear()
handSetup.tableSize?.let { this.numberOfPlayers = it } handSetup.tableSize?.let { this.numberOfPlayers = it }
handSetup.smallBlind?.let { this.smallBlind = it } handSetup.smallBlind?.let { this.smallBlind = it }
handSetup.bigBlind?.let { this.bigBlind = it } handSetup.bigBlind?.let { this.bigBlind = it }
@ -108,11 +111,25 @@ open class HandHistory : RealmObject(), RowRepresentable, Identifiable, Filterab
this.addAction(0, Action.Type.POST_SB, this.smallBlind) this.addAction(0, Action.Type.POST_SB, this.smallBlind)
this.addAction(1, Action.Type.POST_BB, this.bigBlind) this.addAction(1, Action.Type.POST_BB, this.bigBlind)
val positions = Position.positionsPerPlayers(this.numberOfPlayers)
Timber.d("noa 1 = ${this.actions.size}")
var lastStraddler: Int? = null
handSetup.straddlePositions.forEach { position -> // position are sorted here
val positionIndex = positions.indexOf(position)
this.addAction(positionIndex, Action.Type.STRADDLE)
lastStraddler = positionIndex
}
Timber.d("noa 2 = ${this.actions.size}")
val totalActions = this.actions.size val totalActions = this.actions.size
val startingPosition = lastStraddler?.let { it + 1 } ?: totalActions
for (i in totalActions until this.numberOfPlayers + totalActions) { for (i in 0 until this.numberOfPlayers) {
this.addAction(i % this.numberOfPlayers) this.addAction((startingPosition + i) % this.numberOfPlayers)
} }
Timber.d("noa 3 = ${this.actions.size}")
} }

@ -122,13 +122,13 @@ interface DisplayableDataSource {
* Returns a localized string for a specific row * Returns a localized string for a specific row
*/ */
fun stringForRow(row: RowRepresentable, context: Context): String { fun stringForRow(row: RowRepresentable, context: Context): String {
return stringForRow(row) return stringForRow(row, 0)
} }
/** /**
* Returns a string for a specific row * Returns a string for a specific row
*/ */
fun stringForRow(row: RowRepresentable): String { fun stringForRow(row: RowRepresentable, tag: Int = 0): String {
return "" return ""
} }

@ -90,7 +90,10 @@ class CurrenciesFragment : BaseFragment(), StaticRowRepresentableDataSource, Row
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return (row as CurrencyRow).currencyCodeAndSymbol return (row as CurrencyRow).currencyCodeAndSymbol
} }

@ -99,7 +99,7 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSo
override fun stringForRow(row: RowRepresentable, context: Context): String { override fun stringForRow(row: RowRepresentable, context: Context): String {
return when (row) { return when (row) {
is QueryCondition.ListOfValues<*> -> row.firstValue(context) is QueryCondition.ListOfValues<*> -> row.firstValue(context)
else -> super.stringForRow(row) else -> super.stringForRow(row, 0)
} ?: NULL_TEXT } ?: NULL_TEXT
} }

@ -131,7 +131,10 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource,
return rows return rows
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
// Return the number of selected filters for this category // Return the number of selected filters for this category
var selectedFilters = "" var selectedFilters = ""
if (row is FilterCategoryRow) { if (row is FilterCategoryRow) {

@ -103,7 +103,10 @@ class SettingsFragment : BaseFragment(), RowRepresentableDelegate, StaticRowRepr
return rowRepresentation return rowRepresentation
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
SettingRow.SUBSCRIPTION -> AppGuard.subscriptionStatus(requireContext()) SettingRow.SUBSCRIPTION -> AppGuard.subscriptionStatus(requireContext())
SettingRow.VERSION -> BuildConfig.VERSION_NAME + if (BuildConfig.DEBUG) " (${BuildConfig.VERSION_CODE}) DEBUG" else "" SettingRow.VERSION -> BuildConfig.VERSION_NAME + if (BuildConfig.DEBUG) " (${BuildConfig.VERSION_CODE}) DEBUG" else ""

@ -63,7 +63,10 @@ class BottomSheetTableSizeGridFragment : BottomSheetFragment(), StaticRowReprese
dismiss() dismiss()
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
this.context?.let { this.context?.let {
return row.localizedTitle(it) return row.localizedTitle(it)
} }

@ -83,7 +83,10 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
return rows return rows
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
SimpleRow.NAME -> if (bankroll.name.isNotEmpty()) bankroll.name else NULL_TEXT SimpleRow.NAME -> if (bankroll.name.isNotEmpty()) bankroll.name else NULL_TEXT
BankrollRow.CURRENCY -> { BankrollRow.CURRENCY -> {
@ -104,7 +107,7 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
val rate = this.bankroll.currency?.rate ?: 1.0 val rate = this.bankroll.currency?.rate ?: 1.0
rate.toRate() rate.toRate()
} }
else -> super.stringForRow(row) else -> super.stringForRow(row, 0)
} }
} }

@ -120,10 +120,13 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
return customField.adapterRows() return customField.adapterRows()
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
SimpleRow.NAME -> if (customField.name.isNotEmpty()) customField.name else NULL_TEXT SimpleRow.NAME -> if (customField.name.isNotEmpty()) customField.name else NULL_TEXT
else -> super.stringForRow(row) else -> super.stringForRow(row, 0)
} }
} }

@ -64,10 +64,13 @@ class LocationDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
return rows return rows
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
SimpleRow.NAME -> if (location.name.isNotEmpty())location.name else NULL_TEXT SimpleRow.NAME -> if (location.name.isNotEmpty())location.name else NULL_TEXT
else -> return super.stringForRow(row) else -> return super.stringForRow(row, 0)
} }
} }

@ -116,11 +116,14 @@ class PlayerDataFragment : EditableDataFragment(), StaticRowRepresentableDataSou
} }
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
PlayerRow.NAME -> if (player.name.isNotEmpty()) player.name else NULL_TEXT PlayerRow.NAME -> if (player.name.isNotEmpty()) player.name else NULL_TEXT
PlayerRow.SUMMARY -> if (player.summary.isNotEmpty()) player.summary else NULL_TEXT PlayerRow.SUMMARY -> if (player.summary.isNotEmpty()) player.summary else NULL_TEXT
else -> super.stringForRow(row) else -> super.stringForRow(row, 0)
} }
} }

@ -46,14 +46,17 @@ class TransactionDataFragment : EditableDataFragment(), StaticRowRepresentableDa
return transaction.adapterRows() return transaction.adapterRows()
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
TransactionRow.BANKROLL -> this.transaction.bankroll?.name ?: NULL_TEXT TransactionRow.BANKROLL -> this.transaction.bankroll?.name ?: NULL_TEXT
TransactionRow.TYPE -> this.transaction.type?.name ?: NULL_TEXT TransactionRow.TYPE -> this.transaction.type?.name ?: NULL_TEXT
TransactionRow.AMOUNT -> if (this.transaction.amount != 0.0) this.transaction.amount.round() else NULL_TEXT TransactionRow.AMOUNT -> if (this.transaction.amount != 0.0) this.transaction.amount.round() else NULL_TEXT
TransactionRow.COMMENT -> if (this.transaction.comment.isNotEmpty()) this.transaction.comment else NULL_TEXT TransactionRow.COMMENT -> if (this.transaction.comment.isNotEmpty()) this.transaction.comment else NULL_TEXT
TransactionRow.DATE -> this.transaction.date.shortDate() TransactionRow.DATE -> this.transaction.date.shortDate()
else -> super.stringForRow(row) else -> super.stringForRow(row, 0)
} }
} }

@ -33,10 +33,13 @@ class TransactionTypeDataFragment : EditableDataFragment(), RowRepresentableData
return this.transactionType.viewTypeForPosition(position) return this.transactionType.viewTypeForPosition(position)
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(
row: RowRepresentable,
tag: Int
): String {
return when (row) { return when (row) {
SimpleRow.NAME -> this.transactionType.name SimpleRow.NAME -> this.transactionType.name
else -> return super.stringForRow(row) else -> return super.stringForRow(row, 0)
} }
} }

@ -10,9 +10,9 @@ import android.widget.Button
import android.widget.EditText import android.widget.EditText
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.row_hhsettings_blinds.view.* import kotlinx.android.synthetic.main.row_hhsettings_blinds.view.*
import kotlinx.android.synthetic.main.row_hhsettings_player_setup.view.* import kotlinx.android.synthetic.main.row_hhsettings_player_setup.view.*
import kotlinx.android.synthetic.main.row_hhsettings_straddle.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.handhistory.Street import net.pokeranalytics.android.model.handhistory.Street
@ -21,8 +21,10 @@ import net.pokeranalytics.android.ui.adapter.BindableHolder
import net.pokeranalytics.android.ui.adapter.RecyclerAdapter import net.pokeranalytics.android.ui.adapter.RecyclerAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource 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.px
import net.pokeranalytics.android.ui.modules.handhistory.model.ComputedAction import net.pokeranalytics.android.ui.modules.handhistory.model.ComputedAction
import net.pokeranalytics.android.ui.modules.handhistory.model.HHKeyboard import net.pokeranalytics.android.ui.modules.handhistory.model.HHKeyboard
import net.pokeranalytics.android.ui.modules.handhistory.model.StraddleRowRepresentable
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.StreetCardsRow import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardsRow
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
@ -31,7 +33,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.ViewIdentifier
import timber.log.Timber import timber.log.Timber
enum class HandRowType(var layoutRes: Int) : ViewIdentifier { enum class HandRowType(var layoutRes: Int) : ViewIdentifier, RowRepresentable {
HEADER(R.layout.row_header_value), HEADER(R.layout.row_header_value),
ACTION(R.layout.row_hand_action), ACTION(R.layout.row_hand_action),
PLAYER_SUMMARY(R.layout.row_hand_player_summary), PLAYER_SUMMARY(R.layout.row_hand_player_summary),
@ -42,6 +44,8 @@ enum class HandRowType(var layoutRes: Int) : ViewIdentifier {
PLAYER_SETUP(R.layout.row_hhsettings_player_setup) PLAYER_SETUP(R.layout.row_hhsettings_player_setup)
; ;
override val viewType: Int = this.ordinal
override val identifier: Int override val identifier: Int
get() { return this.ordinal } get() { return this.ordinal }
} }
@ -368,9 +372,9 @@ class HandHistoryAdapter(
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
super.onBind(position, row, adapter) super.onBind(position, row, adapter)
itemView.smallBlindEditText.setText(adapter.dataSource.stringForRow(row)) itemView.smallBlindEditText.setText(adapter.dataSource.stringForRow(row, 0))
itemView.bigBlindEditText.setText(adapter.dataSource.stringForRow(row)) itemView.bigBlindEditText.setText(adapter.dataSource.stringForRow(row, 1))
itemView.anteEditText.setText(adapter.dataSource.stringForRow(row)) itemView.anteEditText.setText(adapter.dataSource.stringForRow(row, 2))
itemView.bbAnteSwitch.isChecked = adapter.dataSource.isSelected(position, row, 0) itemView.bbAnteSwitch.isChecked = adapter.dataSource.isSelected(position, row, 0)
} }
@ -381,27 +385,36 @@ class HandHistoryAdapter(
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
super.onBind(position, row, adapter) super.onBind(position, row, adapter)
// itemView.typeChipGroup.clearCheck() val straddleRow = row as StraddleRowRepresentable
itemView.typeChipGroup.setOnCheckedChangeListener { chipGroup, i ->
} itemView.positionsChipGroup.removeAllViews()
straddleRow.positions.forEach { pos ->
val hadStraddle = adapter.dataSource.isSelectable(row) val chip = Chip(itemView.context)
val countVisibility = if (hadStraddle) View.VISIBLE else View.GONE chip.id = View.generateViewId()
// chip.tag = filter.id
chip.text = pos.value
chip.chipStartPadding = 8f.px
chip.chipEndPadding = 8f.px
itemView.countTextView.visibility = countVisibility chip.isChecked = straddleRow.selectedPositions.contains(pos)
itemView.minusButton.visibility = countVisibility chip.setOnClickListener {
itemView.plusButton.visibility = countVisibility if (chip.isChecked) {
straddleRow.selectedPositions.add(pos)
} else {
straddleRow.selectedPositions.remove(pos)
}
adapter.delegate?.onRowValueChanged(straddleRow.selectedPositions, row)
}
itemView.positionsChipGroup.addView(chip)
itemView.countTextView.text = adapter.dataSource.stringForRow(row) }
} }
// type: none, std, mississipi
// number
} }
inner class RowHandPlayerSetup(itemView: View) : RowHandHolder(itemView) { inner class RowHandPlayerSetup(itemView: View) : RowHandHolder(itemView) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
@ -409,8 +422,8 @@ class HandHistoryAdapter(
// itemView.positionsChipGroup // itemView.positionsChipGroup
itemView.handEditText.setText(adapter.dataSource.stringForRow(row)) itemView.handEditText.setText(adapter.dataSource.stringForRow(row, 0))
itemView.stackEditText.setText(adapter.dataSource.stringForRow(row)) itemView.stackEditText.setText(adapter.dataSource.stringForRow(row, 1))
} }

@ -18,10 +18,7 @@ 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.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.model.ComputedAction import net.pokeranalytics.android.ui.modules.handhistory.model.*
import net.pokeranalytics.android.ui.modules.handhistory.model.HHKeyboard
import net.pokeranalytics.android.ui.modules.handhistory.model.HHSelection
import net.pokeranalytics.android.ui.modules.handhistory.model.HandHistoryViewModel
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.PlayerCardsRow import net.pokeranalytics.android.ui.modules.handhistory.views.PlayerCardsRow
import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardsRow import net.pokeranalytics.android.ui.modules.handhistory.views.StreetCardsRow
@ -81,7 +78,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
?: throw PAIllegalStateException("HandHistory not found") ?: throw PAIllegalStateException("HandHistory not found")
this.model.setHandHistory(handHistory) this.model.setHandHistory(handHistory)
} ?: run { } ?: run {
this.model.configure(HandSetup()) this.model.createNewHandHistory(HandSetup())
} }
} }
@ -176,7 +173,11 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
} ?: run { } ?: run {
this.keyboard.hide() this.keyboard.hide()
} }
// The whole data set is refreshed because of a weird EditText bug where
// the EditText wasn't displayed when the previous + current rows were refreshed separately
this.handHistoryAdapter.notifyDataSetChanged() this.handHistoryAdapter.notifyDataSetChanged()
// this.refreshCells(startIndex) // this.refreshCells(startIndex)
} }
@ -234,7 +235,15 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDelegate, KeyboardL
} }
override fun onRowValueChanged(value: Any?, row: RowRepresentable) { override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
this.model.currentAmount = value as String when (row) {
is ComputedAction -> {
this.model.currentAmount = value as String
}
is StraddleRowRepresentable -> {
this.model.changeStraddleSelection(value as LinkedHashSet<Position>)
}
}
} }
// Keyboard Listener // Keyboard Listener

@ -37,6 +37,8 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>()
this.positions = Position.positionsPerPlayers(handHistory.numberOfPlayers) this.positions = Position.positionsPerPlayers(handHistory.numberOfPlayers)
this.clear()
var totalPotSize = 0.0 var totalPotSize = 0.0
// sorted actions // sorted actions
@ -150,7 +152,7 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>()
if (position == lastSignificantAction.position) { if (position == lastSignificantAction.position) {
setOf(Action.Type.FOLD, Action.Type.CHECK, Action.Type.BET, Action.Type.UNDEFINED_ALLIN) setOf(Action.Type.FOLD, Action.Type.CHECK, Action.Type.BET, Action.Type.UNDEFINED_ALLIN)
} else { } else {
setOf(Action.Type.STRADDLE, Action.Type.FOLD, Action.Type.CALL, Action.Type.BET, Action.Type.UNDEFINED_ALLIN) setOf(Action.Type.FOLD, Action.Type.CALL, Action.Type.BET, Action.Type.UNDEFINED_ALLIN)
} }
} }
Action.Type.BET, Action.Type.RAISE -> { Action.Type.BET, Action.Type.RAISE -> {

@ -34,7 +34,7 @@ class ComputedAction(var manager: ActionManager,
private val requiresAmount: Boolean private val requiresAmount: Boolean
get() { get() {
return when(this.action.type) { return when(this.action.type) {
Action.Type.POST_SB, Action.Type.POST_BB, Action.Type.POST_SB, Action.Type.POST_BB, Action.Type.STRADDLE,
Action.Type.BET, Action.Type.RAISE -> (this.action.amount == null) 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) Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN -> (this.playerRemainingStack == null && this.action.amount == null)
else -> false else -> false
@ -178,6 +178,10 @@ class ComputedAction(var manager: ActionManager,
*/ */
private fun updateEffectiveAmount() { private fun updateEffectiveAmount() {
if (this.action.type == null) {
return
}
val significantAction = getStreetLastSignificantAction() val significantAction = getStreetLastSignificantAction()
?: 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")
val significantAmount = significantAction.action.amount val significantAmount = significantAction.action.amount

@ -1,5 +1,7 @@
package net.pokeranalytics.android.ui.modules.handhistory.model package net.pokeranalytics.android.ui.modules.handhistory.model
import net.pokeranalytics.android.model.handhistory.Position
import net.pokeranalytics.android.ui.modules.handhistory.HandRowType
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
enum class HandHistorySettings : RowRepresentable { enum class HandHistorySettings : RowRepresentable {
@ -8,5 +10,12 @@ enum class HandHistorySettings : RowRepresentable {
COMMENT, COMMENT,
PLAYER_SETUP; PLAYER_SETUP;
}
class StraddleRowRepresentable(
var positions: LinkedHashSet<Position>,
var selectedPositions: LinkedHashSet<Position>) : RowRepresentable {
override val viewType: Int = HandRowType.STRADDLE.ordinal
} }

@ -31,6 +31,16 @@ class HHSelection(var index: Int, var keyboard: HHKeyboard)
class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer, ActionListListener { class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer, ActionListListener {
/***
* The hand history
*/
private lateinit var handHistory: HandHistory
/***
*
*/
private var isNew: Boolean = true
/*** /***
* Indicates whether the hand history is being edited or not * Indicates whether the hand history is being edited or not
*/ */
@ -72,14 +82,19 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentra
var rowsLiveData: MutableLiveData<MutableList<RowRepresentable>> = MutableLiveData() var rowsLiveData: MutableLiveData<MutableList<RowRepresentable>> = MutableLiveData()
/*** /***
* The hand history * All actions sorted by index
*/ */
private lateinit var handHistory: HandHistory private var sortedActions: ActionList = ActionList(this)
/*** /***
* All actions sorted by index * First Straddle selected
*/ */
private var sortedActions: ActionList = ActionList(this) private var firstStraddlePosition: Position? = null
/***
* The hand setup
*/
private var handSetup: HandSetup = HandSetup()
/*** /***
* The board cards sorted by position * The board cards sorted by position
@ -98,22 +113,35 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentra
} }
/*** /***
* Configures a new HandHistory object using a [handSetup] * Straddle selected positions
*/
private var straddlePositions: LinkedHashSet<Position> = linkedSetOf()
/***
* Creates and configures a new HandHistory object using a [handSetup]
*/ */
fun configure(handSetup: HandSetup) { fun createNewHandHistory(handSetup: HandSetup) {
this.handSetup = handSetup
val handHistory = HandHistory() val handHistory = HandHistory()
handHistory.configure(handSetup) handHistory.configure(handSetup)
this.playerHandMaxCards = handSetup.game?.playerHandMaxCards this.playerHandMaxCards = handSetup.game?.playerHandMaxCards
this.setHandHistory(handHistory) this.loadHandHistory(handHistory)
} }
/*** /***
* Sets the hand history and loads it * Sets the hand history and loads it
*/ */
fun setHandHistory(handHistory: HandHistory) { fun setHandHistory(handHistory: HandHistory) {
this.isNew = false
loadHandHistory(handHistory)
}
private fun loadHandHistory(handHistory: HandHistory) {
this.handHistory = handHistory this.handHistory = handHistory
setNumberOfPlayers(handHistory.numberOfPlayers)
load() load()
} }
@ -122,6 +150,7 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentra
* Pre-computes the potsizes for the video export * Pre-computes the potsizes for the video export
*/ */
private fun load() { private fun load() {
this.setNumberOfPlayers(handHistory.numberOfPlayers)
this.sortedActions.load(this.handHistory) this.sortedActions.load(this.handHistory)
this.createRowRepresentation() this.createRowRepresentation()
} }
@ -134,10 +163,15 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentra
rows.add(CustomizableRowRepresentable(customViewType = HandRowType.HEADER, resId = R.string.settings, value = "")) rows.add(CustomizableRowRepresentable(customViewType = HandRowType.HEADER, resId = R.string.settings, value = ""))
rows.add(HandRowType.BLINDS)
if (this.isNew) { // don't allow any straddle changes if not new
val positions = Position.positionsPerPlayers(this.handHistory.numberOfPlayers)
positions.remove(Position.SB)
positions.remove(Position.BB)
rows.add(StraddleRowRepresentable(positions, this.straddlePositions))
}
Street.values().forEach { street -> Street.values().forEach { street ->
@ -415,7 +449,6 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentra
this.createRowRepresentation() this.createRowRepresentation()
} }
fun amountChanged(amount: String?) { fun amountChanged(amount: String?) {
this.currentAmount = amount this.currentAmount = amount
} }
@ -439,10 +472,19 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentra
} }
override fun isSelected(position: Int, row: RowRepresentable, tag: Int): Boolean { override fun isSelected(position: Int, row: RowRepresentable, tag: Int): Boolean {
val currentSelection = this.selectionLiveData
val isSelectedIndex = (position == currentSelection.value?.index) return when (row) {
val isSelectedAction = (tag == currentSelection.value?.keyboard?.ordinal) HandRowType.BLINDS -> {
return isSelectedIndex && isSelectedAction this.handHistory.bigBlindAnte
}
is ComputedAction -> {
val currentSelection = this.selectionLiveData
val isSelectedIndex = (position == currentSelection.value?.index)
val isSelectedAction = (tag == currentSelection.value?.keyboard?.ordinal)
isSelectedIndex && isSelectedAction
}
else -> false
}
} }
fun cardSelectionEnded() { fun cardSelectionEnded() {
@ -453,4 +495,39 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentra
// this.builder.setBuilderListener(builderListener) // this.builder.setBuilderListener(builderListener)
// } // }
override fun stringForRow(row: RowRepresentable, tag: Int): String {
return when (row) {
HandRowType.BLINDS -> {
when (tag) {
0 -> this.handHistory.smallBlind?.formatted() ?: ""
1 -> this.handHistory.bigBlind?.formatted() ?: ""
2 -> this.handHistory.ante.formatted()
else -> throw PAIllegalStateException("Unmanaged case with $row, tag = $tag")
}
}
else -> throw PAIllegalStateException("Unmanaged case with $row, tag = $tag")
}
}
fun changeStraddleSelection(positions: LinkedHashSet<Position>) {
if (positions.isEmpty()) {
this.firstStraddlePosition = null
this.handSetup.clearStraddles()
} else {
if (this.firstStraddlePosition == null) {
this.firstStraddlePosition = positions.firstOrNull()
}
this.handSetup.setStraddlePositions(this.firstStraddlePosition!!, positions)
}
this.handHistory.configure(this.handSetup) // restart initial setup
this.sortedActions.load(this.handHistory) // recreate the sorted Actions
this.createRowRepresentation() // make the table rows
}
} }

@ -21,7 +21,7 @@
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/actionButton" android:id="@+id/actionButton"
style="@style/PokerAnalyticsTheme.HHButton" style="@style/PokerAnalyticsTheme.HHButton"
android:layout_width="64dp" android:layout_width="84dp"
android:layout_height="44dp" android:layout_height="44dp"
android:layout_marginStart="8dp"/> android:layout_marginStart="8dp"/>

@ -2,7 +2,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatEditText <androidx.appcompat.widget.AppCompatEditText
android:id="@+id/smallBlindEditText" android:id="@+id/smallBlindEditText"

@ -9,8 +9,7 @@
android:id="@+id/positionsChipGroup" android:id="@+id/positionsChipGroup"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="44dp" android:layout_height="44dp"
app:chipSpacing="8dp" app:chipSpacing="8dp" />
app:singleSelection="true" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

@ -3,69 +3,15 @@
android:orientation="vertical" android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="wrap_content">
<com.google.android.material.chip.ChipGroup <com.google.android.material.chip.ChipGroup
android:id="@+id/typeChipGroup" android:id="@+id/positionsChipGroup"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="44dp" android:layout_height="44dp"
app:chipSpacing="8dp" app:chipSpacing="8dp"
app:singleSelection="true"> app:singleSelection="true">
<com.google.android.material.chip.Chip
android:id="@+id/noneChip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/none" />
<com.google.android.material.chip.Chip
android:id="@+id/standardChip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/standard" />
<com.google.android.material.chip.Chip
android:id="@+id/mississipiChip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mississipi" />
</com.google.android.material.chip.ChipGroup> </com.google.android.material.chip.ChipGroup>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="80dp"
android:layout_marginEnd="80dp"
>
<com.google.android.material.button.MaterialButton
android:id="@+id/minusButton"
android:text="-"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
style="@style/PokerAnalyticsTheme.SingleCharacterButton"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/countTextView"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
style="@style/PokerAnalyticsTheme.TextView.RowTitle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/guidelineStart"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/plusButton"
android:text="+"
style="@style/PokerAnalyticsTheme.SingleCharacterButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout> </LinearLayout>
Loading…
Cancel
Save