Stats display in the tab pre-alpha

feature/top10
Laurent 7 years ago
parent 096c39a59f
commit bf1babad67
  1. 2
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  2. 11
      app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt
  3. 6
      app/src/main/java/net/pokeranalytics/android/calculus/Format.kt
  4. 4
      app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt
  5. 6
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  6. 45
      app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt
  7. 25
      app/src/main/java/net/pokeranalytics/android/ui/datasource/StatsDataSource.kt
  8. 3
      app/src/main/java/net/pokeranalytics/android/ui/fragment/HistoryFragment.kt
  9. 49
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt
  10. 12
      app/src/main/java/net/pokeranalytics/android/ui/view/RowRepresentable.kt
  11. 164
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt

@ -92,7 +92,7 @@ class Calculator {
val sessions: List<SessionInterface> = sessionGroup.sessions val sessions: List<SessionInterface> = sessionGroup.sessions
var sessionSets = sessionGroup.sessions.mapNotNull { it.sessionSet }.toHashSet() var sessionSets = sessionGroup.sessions.mapNotNull { it.sessionSet }.toHashSet()
var results: ComputedResults = ComputedResults() var results: ComputedResults = ComputedResults(sessionGroup)
if (sessions.size == 0) { if (sessions.size == 0) {
return results return results

@ -38,7 +38,12 @@ class SessionGroup(name: String, sessions: List<SessionInterface>) {
} }
class ComputedResults() { class ComputedResults(group: SessionGroup) {
/**
* The session group used to computed the stats
*/
var group: SessionGroup = group
// The computed stats of the sessionGroup // The computed stats of the sessionGroup
private var _computedStats: MutableMap<Stat, ComputedStat> = mutableMapOf() private var _computedStats: MutableMap<Stat, ComputedStat> = mutableMapOf()
@ -46,6 +51,10 @@ class ComputedResults() {
// The map containing all evolution values for all stats // The map containing all evolution values for all stats
private var _evolutionValues: MutableMap<Stat, MutableList<Point>> = mutableMapOf() private var _evolutionValues: MutableMap<Stat, MutableList<Point>> = mutableMapOf()
fun allStats() : Collection<ComputedStat> {
return this._computedStats.values
}
fun addEvolutionValue(value: Double, stat: Stat) { fun addEvolutionValue(value: Double, stat: Stat) {
this._addEvolutionValue(Point(value), stat = stat) this._addEvolutionValue(Point(value), stat = stat)
} }

@ -2,7 +2,7 @@ package net.pokeranalytics.android.calculus
import android.graphics.Color import android.graphics.Color
class StatFormat { class StatFormat(text: String, color: Int = Color.WHITE) {
var text: String = "" var text: String = text
var color: Int = Color.BLUE var color: Int = color
} }

@ -107,14 +107,14 @@ class ComputedStat(stat: Stat, value: Double) {
* Formats the value of the stat to be suitable for display * Formats the value of the stat to be suitable for display
*/ */
fun format() : StatFormat { fun format() : StatFormat {
return StatFormat() return StatFormat("${value}".toUpperCase())
} }
/** /**
* Returns a StatFormat instance for an evolution value located at the specified [index] * Returns a StatFormat instance for an evolution value located at the specified [index]
*/ */
fun evolutionValueFormat(index: Int) : StatFormat { fun evolutionValueFormat(index: Int) : StatFormat {
return StatFormat() return StatFormat("undef")
} }
} }

@ -50,6 +50,10 @@ open class Session : RealmObject(), SessionInterface, Savable,
// The time frame of the Session, i.e. the start & end date // The time frame of the Session, i.e. the start & end date
var timeFrame: TimeFrame? = null var timeFrame: TimeFrame? = null
set(value) {
field = value
value?.let { it.notifySessionDateChange(this) }
}
// The time frame sessionGroup, which can contain multiple sessions // The time frame sessionGroup, which can contain multiple sessions
override var sessionSet: SessionSet? = null override var sessionSet: SessionSet? = null
@ -237,7 +241,7 @@ open class Session : RealmObject(), SessionInterface, Savable,
// make sessions recreate/find their session set // make sessions recreate/find their session set
sessionsFromSet?.let { sessions -> sessionsFromSet?.let { sessions ->
sessions.forEach { session -> sessions.forEach { session ->
session.timeFrame?.notifySessionDateChange() session.timeFrame?.notifySessionDateChange(session)
} }
} }
} }

@ -83,18 +83,26 @@ open class TimeFrame : RealmObject() {
this.computeDuration() this.computeDuration()
if (this.session != null) { this.session?.let {
this.notifySessionDateChange() this.notifySessionDateChange(it)
} }
} }
/**
* Computes the net duration of the session
*/
private fun computeDuration() { private fun computeDuration() {
var endDate: Date = this.endDate ?: Date() var endDate: Date = this.endDate ?: Date()
val netDuration = endDate.time - this.startDate.time - this.breakDuration val netDuration = endDate.time - this.startDate.time - this.breakDuration
this.duration = netDuration this.duration = netDuration
} }
fun notifySessionDateChange() { /**
* Queries all time frames that might be impacted by the date change
* Makes all necessary changes to keep sequential time frames
*/
fun notifySessionDateChange(owner: Session) {
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
var query: RealmQuery<SessionSet> = realm.where(SessionSet::class.java) var query: RealmQuery<SessionSet> = realm.where(SessionSet::class.java)
query.isNotNull("timeFrame") query.isNotNull("timeFrame")
@ -118,20 +126,19 @@ open class TimeFrame : RealmObject() {
val sessionGroups = query.findAll() val sessionGroups = query.findAll()
this.updateTimeFrames(sessionGroups) this.updateTimeFrames(sessionGroups, owner)
// realm.close()
} }
/** /**
* Update Time frames from sets * Update Time frames from sets
*/ */
private fun updateTimeFrames(sessionSets: RealmResults<SessionSet>) { private fun updateTimeFrames(sessionSets: RealmResults<SessionSet>, owner: Session) {
when (sessionSets.size) { when (sessionSets.size) {
0 -> this.createSessionGroup() 0 -> this.createSessionGroup(owner)
1 -> this.updateSingleSessionGroup(sessionSets.first()!!) 1 -> this.updateSingleSessionGroup(owner, sessionSets.first()!!)
else -> this.mergeSessionGroups(sessionSets) else -> this.mergeSessionGroups(owner, sessionSets)
} }
} }
@ -139,7 +146,7 @@ open class TimeFrame : RealmObject() {
/** /**
* Creates the session sessionGroup when the session has none * Creates the session sessionGroup when the session has none
*/ */
private fun createSessionGroup() { private fun createSessionGroup(owner: Session) {
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
@ -151,11 +158,7 @@ open class TimeFrame : RealmObject() {
throw ModelException("TimeFrame should never be null here") throw ModelException("TimeFrame should never be null here")
} }
this.session?.let { owner.sessionSet = set
it.sessionSet = set
} ?: run {
throw ModelException("Session should never be null here")
}
Timber.d("sd = : ${set.timeFrame?.startDate}, ed = ${set.timeFrame?.endDate}") Timber.d("sd = : ${set.timeFrame?.startDate}, ed = ${set.timeFrame?.endDate}")
@ -165,7 +168,7 @@ open class TimeFrame : RealmObject() {
* Single session sessionGroup update * Single session sessionGroup update
* Changes the sessionGroup timeframe using the current timeframe dates * Changes the sessionGroup timeframe using the current timeframe dates
*/ */
private fun updateSingleSessionGroup(sessionSet: SessionSet) { private fun updateSingleSessionGroup(owner: Session, sessionSet: SessionSet) {
var groupTimeFrame: TimeFrame = sessionSet.timeFrame!! // tested in the query var groupTimeFrame: TimeFrame = sessionSet.timeFrame!! // tested in the query
@ -179,7 +182,7 @@ open class TimeFrame : RealmObject() {
groupTimeFrame.endDate = null groupTimeFrame.endDate = null
} }
this.session?.sessionSet = sessionSet owner.sessionSet = sessionSet
} }
@ -187,7 +190,7 @@ open class TimeFrame : RealmObject() {
* Multiple session sets update: * Multiple session sets update:
* Merges all sets into one (delete all then create a new one) * Merges all sets into one (delete all then create a new one)
*/ */
private fun mergeSessionGroups(sessionSets: RealmResults<SessionSet>) { private fun mergeSessionGroups(owner: Session, sessionSets: RealmResults<SessionSet>) {
var startDate: Date = this.startDate var startDate: Date = this.startDate
var endDate: Date? = this.endDate var endDate: Date? = this.endDate
@ -228,11 +231,7 @@ open class TimeFrame : RealmObject() {
} }
// Add the session linked to this timeframe to the new sessionGroup // Add the session linked to this timeframe to the new sessionGroup
this.sessions?.first()?.let { owner.sessionSet = set
it.sessionSet = set
} ?: run {
throw ModelException("TimeFrame should never be null here")
}
// Add all orphan sessions // Add all orphan sessions
sessions.forEach { it.sessionSet = set } sessions.forEach { it.sessionSet = set }

@ -1,18 +1,33 @@
package net.pokeranalytics.android.ui.datasource package net.pokeranalytics.android.ui.datasource
import net.pokeranalytics.android.calculus.ComputedResults import net.pokeranalytics.android.calculus.ComputedResults
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
class StatsDataSource(results: List<ComputedResults>) : RowRepresentableDataSource {
class StatRepresentable(stat: ComputedStat) : RowRepresentable {
var computedStat: ComputedStat = stat
override val viewType: Int
get() = RowViewType.STAT.ordinal
override val resId: Int?
get() = this.computedStat.stat.resId
}
class StatsDataSource(results: List<ComputedResults>) {
var results: List<ComputedResults> = results var results: List<ComputedResults> = results
var rows: List<RowRepresentable> = listOf()
init {
override fun adapterRows(): ArrayList<RowRepresentable> {
return ArrayList<RowRepresentable>()
} }
override fun numberOfRows(): Int { fun numberOfRows(): Int {
return 0 return 0
// return this.results.fold(0) { acc, computedResults -> // return this.results.fold(0) { acc, computedResults ->
// return acc + computedResults.numberOfStats() // return acc + computedResults.numberOfStats()

@ -25,8 +25,7 @@ import net.pokeranalytics.android.util.isSameMonth
import net.pokeranalytics.android.util.longDate import net.pokeranalytics.android.util.longDate
import java.util.* import java.util.*
class HistoryFragment : PokerAnalyticsFragment(), RowRepresentableDataSource, class HistoryFragment : PokerAnalyticsFragment(), RowRepresentableDataSource, RowRepresentableDelegate {
RowRepresentableDelegate {
companion object { companion object {
fun newInstance(): HistoryFragment { fun newInstance(): HistoryFragment {

@ -15,10 +15,18 @@ import net.pokeranalytics.android.calculus.SessionGroup
import net.pokeranalytics.android.model.extensions.SessionType import net.pokeranalytics.android.model.extensions.SessionType
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.datasource.StatsDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.datasource.StatRepresentable
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.view.HeaderRowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
class StatsFragment : PokerAnalyticsFragment() { class StatsFragment : PokerAnalyticsFragment(), RowRepresentableDataSource {
private var rowRepresentables: ArrayList<RowRepresentable> = ArrayList<RowRepresentable>()
private lateinit var statsAdapterRow: RowRepresentableAdapter
companion object { companion object {
@ -33,7 +41,6 @@ class StatsFragment : PokerAnalyticsFragment() {
} }
} }
private lateinit var statsAdapterRow: RowRepresentableAdapter
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -45,6 +52,21 @@ class StatsFragment : PokerAnalyticsFragment() {
initData() initData()
} }
// Row Representable DS
override fun adapterRows(): ArrayList<RowRepresentable> {
return this.rowRepresentables
}
override fun stringForRow(row: RowRepresentable): String {
if (row is StatRepresentable) {
val stat = row as StatRepresentable
val format = stat.computedStat.format()
return format.text
}
return "nope"
}
/** /**
* Init data * Init data
*/ */
@ -76,9 +98,14 @@ class StatsFragment : PokerAnalyticsFragment() {
val tSessionGroup = SessionGroup(getString(R.string.tournament), tSessions) val tSessionGroup = SessionGroup(getString(R.string.tournament), tSessions)
results = Calculator.computeGroups(listOf(allSessionGroup, cgSessionGroup, tSessionGroup), Calculator.Options()) results = Calculator.computeGroups(listOf(allSessionGroup, cgSessionGroup, tSessionGroup), Calculator.Options())
} }
this.statsAdapterRow = RowRepresentableAdapter(StatsDataSource(results))
this.rowRepresentables = this.convertResultsIntoRepresentables(results)
this.statsAdapterRow = RowRepresentableAdapter(this) // StatsAdapter(this, null)
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
@ -90,4 +117,18 @@ class StatsFragment : PokerAnalyticsFragment() {
} }
fun convertResultsIntoRepresentables(results: List<ComputedResults>) : ArrayList<RowRepresentable> {
val rows: ArrayList<RowRepresentable> = ArrayList<RowRepresentable>()
results.forEach {
rows.add(HeaderRowRepresentable(RowViewType.HEADER_TITLE_VALUE, title = it.group.name))
it.allStats().forEach {
rows.add(StatRepresentable(it))
}
}
return rows
}
} }

@ -71,8 +71,16 @@ interface Displayable : Localizable {
return false return false
} }
var displayHeader: Boolean val displayHeader: Boolean
var headerValues: ArrayList<String> get() {
return false
}
val headerValues: ArrayList<String>
get() {
return ArrayList<String>()
}
} }

@ -42,11 +42,91 @@ enum class RowViewType {
DATA, DATA,
BOTTOM_SHEET_DATA, BOTTOM_SHEET_DATA,
TITLE_GRID, TITLE_GRID,
ROW_SESSION; ROW_SESSION,
STAT;
inner class FakeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), /**
BindableHolder { * View holder
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { */
fun viewHolder(parent: ViewGroup): RecyclerView.ViewHolder {
return when (this) {
HEADER_TITLE_VALUE -> HeaderTitleValueViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_header_title_value,
parent,
false
)
)
HEADER_TITLE_AMOUNT -> HeaderTitleAmountViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_header_title_amount,
parent,
false
)
)
TITLE -> TitleViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title,
parent,
false
)
)
TITLE_VALUE -> TitleValueViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title_value,
parent,
false
)
)
TITLE_GRID -> TitleGridSessionViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_bottom_sheet_grid_title,
parent,
false)
)
TITLE_SWITCH -> TitleSwitchViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title_switch,
parent,
false
)
)
TITLE_VALUE_ACTION -> TitleValueActionViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title_value_action,
parent,
false
)
)
DATA -> DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title,
parent,
false
)
)
BOTTOM_SHEET_DATA -> BottomSheetDataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_bottom_sheet_title,
parent,
false
)
)
ROW_SESSION -> RowSessionViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_history_session,
parent,
false)
)
STAT -> TitleValueViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title_value,
parent,
false
)
)
else -> throw Exception("Undefined rowViewType's holder")
} }
} }
@ -209,81 +289,5 @@ enum class RowViewType {
} }
} }
/**
* View holder
*/
fun viewHolder(parent: ViewGroup): RecyclerView.ViewHolder {
return when (this) {
HEADER_TITLE_VALUE -> HeaderTitleValueViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_header_title_value,
parent,
false
)
)
HEADER_TITLE_AMOUNT -> HeaderTitleAmountViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_header_title_amount,
parent,
false
)
)
TITLE -> TitleViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title,
parent,
false
)
)
TITLE_VALUE -> TitleValueViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title_value,
parent,
false
)
)
TITLE_GRID -> TitleGridSessionViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_bottom_sheet_grid_title,
parent,
false)
)
TITLE_SWITCH -> TitleSwitchViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title_switch,
parent,
false
)
)
TITLE_VALUE_ACTION -> TitleValueActionViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title_value_action,
parent,
false
)
)
DATA -> DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title,
parent,
false
)
)
BOTTOM_SHEET_DATA -> BottomSheetDataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_bottom_sheet_title,
parent,
false
)
)
ROW_SESSION -> RowSessionViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_history_session,
parent,
false)
)
else -> throw Exception("Undefined RowViewType's holder")
}
}
} }
Loading…
Cancel
Save