Adds basic UI for hand history

hh
Laurent 6 years ago
parent 62c24590f0
commit 15db3c4d3a
  1. 5
      app/src/main/AndroidManifest.xml
  2. 19
      app/src/main/java/net/pokeranalytics/android/model/handhistory/ComputedAction.kt
  3. 18
      app/src/main/java/net/pokeranalytics/android/model/handhistory/HHBuilder.kt
  4. 12
      app/src/main/java/net/pokeranalytics/android/model/handhistory/Street.kt
  5. 1
      app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt
  6. 5
      app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Card.kt
  7. 18
      app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt
  8. 48
      app/src/main/java/net/pokeranalytics/android/ui/activity/HandHistoryActivity.kt
  9. 1
      app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt
  10. 112
      app/src/main/java/net/pokeranalytics/android/ui/fragment/HandHistoryFragment.kt
  11. 24
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt
  12. 9
      app/src/main/java/net/pokeranalytics/android/ui/view/handhistory/StreetHeader.kt
  13. 19
      app/src/main/java/net/pokeranalytics/android/ui/viewmodel/HandHistoryViewModel.kt
  14. 7
      app/src/main/res/layout/activity_hand_history.xml
  15. 27
      app/src/main/res/layout/fragment_hand_history.xml
  16. 6
      app/src/main/res/layout/row_hand_action.xml
  17. 6
      app/src/main/res/layout/row_hand_street.xml

@ -71,6 +71,11 @@
android:launchMode="singleTop" android:launchMode="singleTop"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name="net.pokeranalytics.android.ui.activity.HandHistoryActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait" />
<activity <activity
android:name="net.pokeranalytics.android.ui.activity.BankrollDetailsActivity" android:name="net.pokeranalytics.android.ui.activity.BankrollDetailsActivity"
android:launchMode="singleTop" android:launchMode="singleTop"

@ -1,21 +1,16 @@
package net.pokeranalytics.android.model.handhistory package net.pokeranalytics.android.model.handhistory
import net.pokeranalytics.android.model.realm.handhistory.Action import net.pokeranalytics.android.model.realm.handhistory.Action
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
class ComputedAction(var action: Action, class ComputedAction(var action: Action,
var totalPotSize: Double = 0.0, var totalPotSize: Double = 0.0,
var playerRemainingStack: Double? = null) { var playerRemainingStack: Double? = null) : RowRepresentable {
/*** /***
* The potsize is used: * Returns whether the action requires the user to enter an amount for the selected action
* - in the replayer / video
* - in the list of actions by street
*/ */
// var potSize = 0.0
//
// var playerRemainingStack = 0.0
val requireAmount: Boolean val requireAmount: Boolean
get() { get() {
return when(this.action.type) { return when(this.action.type) {
@ -25,6 +20,10 @@ class ComputedAction(var action: Action,
} }
} }
/***
* Sets the effective amount of the action
* Also calculates the player remaining stack if possible
*/
fun setEffectiveAmount(amount: Double) { fun setEffectiveAmount(amount: Double) {
this.action.effectiveAmount = amount this.action.effectiveAmount = amount
this.playerRemainingStack?.let { this.playerRemainingStack?.let {
@ -32,4 +31,6 @@ class ComputedAction(var action: Action,
} }
} }
override val viewType: Int = RowViewType.ROW_HAND_ACTION.ordinal
} }

@ -3,9 +3,11 @@ package net.pokeranalytics.android.model.handhistory
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.realm.handhistory.Action import net.pokeranalytics.android.model.realm.handhistory.Action
import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.handhistory.StreetHeader
import kotlin.math.min import kotlin.math.min
class Builder { class HHBuilder {
/*** /***
* The hand history * The hand history
@ -260,4 +262,18 @@ class Builder {
} }
fun rowRepresentables() : List<RowRepresentable> {
val rows: MutableList<RowRepresentable> = mutableListOf()
var potSize = 0.0
Street.values().forEach { street ->
rows.add(StreetHeader(street, this.handHistory.cardsForStreet(street), potSize))
val actions = this.sortedActions.filter { it.action.street == street.ordinal }
rows.addAll(actions)
potSize = actions.last().totalPotSize
}
return rows
}
} }

@ -4,6 +4,16 @@ enum class Street {
PREFLOP, PREFLOP,
FLOP, FLOP,
TURN, TURN,
RIVER RIVER;
val totalBoardCards: Int
get() {
return when (this) {
PREFLOP -> 0
FLOP -> 3
TURN -> 4
RIVER -> 5
}
}
} }

@ -191,6 +191,7 @@ class PokerAnalyticsMigration : RealmMigration {
val cardSchema = schema.create("Card") val cardSchema = schema.create("Card")
cardSchema.addField("value", Int::class.java) cardSchema.addField("value", Int::class.java)
cardSchema.addField("suit", Int::class.java) cardSchema.addField("suit", Int::class.java)
cardSchema.addField("index", Int::class.java)
hhSchema.addRealmListField("board", cardSchema) hhSchema.addRealmListField("board", cardSchema)
val actionSchema = schema.create("Action") val actionSchema = schema.create("Action")

@ -22,4 +22,9 @@ open class Card : RealmObject() {
*/ */
var suit: Int = 0 var suit: Int = 0
/***
* The card index in a list
*/
var index: Int = 0
} }

@ -2,16 +2,22 @@ package net.pokeranalytics.android.model.realm.handhistory
import io.realm.RealmList import io.realm.RealmList
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.model.handhistory.HandSetup import net.pokeranalytics.android.model.handhistory.HandSetup
import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import java.util.* import java.util.*
open class HandHistory : RealmObject() { open class HandHistory : RealmObject(), Identifiable {
@PrimaryKey @PrimaryKey
var id = UUID.randomUUID().toString() override var id = UUID.randomUUID().toString()
@Ignore
override val realmObjectClass: Class<out Identifiable> = HandHistory::class.java
/*** /***
* The date of the hand history * The date of the hand history
@ -92,13 +98,15 @@ open class HandHistory : RealmObject() {
action.type = Action.Type.POST_BB action.type = Action.Type.POST_BB
action.amount = this.bigBlind action.amount = this.bigBlind
} }
else -> { else -> {}
}
} }
this.actions.add(action) this.actions.add(action)
} }
} }
fun cardsForStreet(street: Street): List<Card> {
return this.board.sortedBy { it.index }.drop(street.totalBoardCards)
}
} }

@ -0,0 +1,48 @@
package net.pokeranalytics.android.ui.activity
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.activity.components.BaseActivity
import net.pokeranalytics.android.ui.activity.components.RequestCode
import net.pokeranalytics.android.ui.fragment.HandHistoryFragment
class HandHistoryActivity : BaseActivity() {
enum class IntentKey(val keyName: String) {
IDENTIFIER("identifier")
}
companion object {
fun newInstance(fragment: Fragment, id: String?) {
val intent = Intent(fragment.requireContext(), DataListActivity::class.java)
id?.let { intent.putExtra(IntentKey.IDENTIFIER.keyName, it) }
fragment.startActivityForResult(intent, RequestCode.NEW_HAND_HISTORY.value)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_hand_history)
initUI()
}
/**
* Init UI
*/
private fun initUI() {
val fragmentTransaction = supportFragmentManager.beginTransaction()
val handHistoryId = intent.getStringExtra(IntentKey.IDENTIFIER.keyName)
val fragment = HandHistoryFragment.newInstance(handHistoryId)
fragmentTransaction.add(R.id.container, fragment)
fragmentTransaction.commit()
}
}

@ -10,6 +10,7 @@ enum class RequestCode(var value: Int) {
NEW_SESSION(800), NEW_SESSION(800),
NEW_TRANSACTION(801), NEW_TRANSACTION(801),
NEW_REPORT(802), NEW_REPORT(802),
NEW_HAND_HISTORY(803),
IMPORT(900), IMPORT(900),
SUBSCRIPTION(901), SUBSCRIPTION(901),
CURRENCY(902), CURRENCY(902),

@ -0,0 +1,112 @@
package net.pokeranalytics.android.ui.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_settings.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.handhistory.HHBuilder
import net.pokeranalytics.android.model.handhistory.HandSetup
import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.viewmodel.HandHistoryViewModel
import net.pokeranalytics.android.util.extensions.findById
class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepresentableDelegate {
private lateinit var model: HandHistoryViewModel
private lateinit var handHistoryAdapter: RowRepresentableAdapter
private var rows: List<RowRepresentable> = listOf()
companion object {
fun newInstance(id: String? = null): HandHistoryFragment {
val fragment = HandHistoryFragment()
val bundle = Bundle()
bundle.putSerializable(BundleKey.PRIMARY_KEY.value, id)
fragment.arguments = bundle
return fragment
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this)[HandHistoryViewModel::class.java]
} ?: throw Exception("Invalid Activity")
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_hand_history, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initData()
initUI()
}
private fun initData() {
val handHistoryId = this.arguments?.getString(BundleKey.PRIMARY_KEY.value)
val builder = handHistoryId?.let {
val handHistory = getRealm().findById<HandHistory>(it) ?: throw PAIllegalStateException("HandHistory not found")
HHBuilder(handHistory)
} ?: run {
HHBuilder(HandSetup())
}
this.model.setBuilder(builder)
}
private fun initUI() {
setToolbarTitle(getString(R.string.hand_history))
setDisplayHomeAsUpEnabled(true)
val viewManager = LinearLayoutManager(requireContext())
handHistoryAdapter = RowRepresentableAdapter(this, this)
recyclerView.apply {
setHasFixedSize(true)
layoutManager = viewManager
adapter = handHistoryAdapter
}
this.rows = this.model.builder.value?.rowRepresentables() ?: listOf()
}
// RowRepresentableDataSource
override fun adapterRows(): List<RowRepresentable>? {
return this.rows
}
override fun rowRepresentableForPosition(position: Int): RowRepresentable? {
return this.rows[position]
}
override fun numberOfRows(): Int {
return this.rows.size
}
override fun viewTypeForPosition(position: Int): Int {
return this.rows[position].viewType
}
}

@ -94,6 +94,8 @@ enum class RowViewType(private var layoutRes: Int) {
LIST(R.layout.row_list), LIST(R.layout.row_list),
ROW_PLAYER(R.layout.row_player), ROW_PLAYER(R.layout.row_player),
ROW_PLAYER_IMAGE(R.layout.row_player_image), ROW_PLAYER_IMAGE(R.layout.row_player_image),
ROW_HAND_ACTION(R.layout.row_hand_action),
ROW_HAND_STREET(R.layout.row_hand_street),
// Separator // Separator
SEPARATOR(R.layout.row_separator); SEPARATOR(R.layout.row_separator);
@ -142,6 +144,10 @@ enum class RowViewType(private var layoutRes: Int) {
GRAPH -> GraphViewHolder(layout) GRAPH -> GraphViewHolder(layout)
LEGEND_DEFAULT -> LegendDefaultViewHolder(layout) LEGEND_DEFAULT -> LegendDefaultViewHolder(layout)
// Hand History
ROW_HAND_ACTION -> RowHandAction(layout)
ROW_HAND_STREET -> RowHandStreet(layout)
// Separator // Separator
SEPARATOR -> SeparatorViewHolder(layout) SEPARATOR -> SeparatorViewHolder(layout)
@ -675,6 +681,24 @@ enum class RowViewType(private var layoutRes: Int) {
} }
} }
/**
* Display a hand action
*/
inner class RowHandAction(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
}
}
/**
* Display a hand street
*/
inner class RowHandStreet(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
}
}
/** /**
* Display a separator * Display a separator
*/ */

@ -0,0 +1,9 @@
package net.pokeranalytics.android.ui.view.handhistory
import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.model.realm.handhistory.Card
import net.pokeranalytics.android.ui.view.RowRepresentable
class StreetHeader(var street: Street, var cards: List<Card>, var potSize: Double) : RowRepresentable {
}

@ -0,0 +1,19 @@
package net.pokeranalytics.android.ui.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import net.pokeranalytics.android.model.handhistory.HHBuilder
class HandHistoryViewModel : ViewModel() {
var builder = MutableLiveData<HHBuilder>()
fun setBuilder(builder: HHBuilder) {
this.builder.value = builder
}
fun test() {
// this.builder.
}
}

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false" />
</FrameLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
Loading…
Cancel
Save