Start of Graphs

feature/top10
Laurent 7 years ago
parent 9845193db3
commit 5e2959e883
  1. 5
      app/build.gradle
  2. 34
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  3. 66
      app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt
  4. 3
      app/src/main/java/net/pokeranalytics/android/model/StatRepresentable.kt
  5. 38
      app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt
  6. 58
      app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt
  7. 1
      app/src/main/java/net/pokeranalytics/android/ui/activity/DataListActivity.kt
  8. 1
      app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt
  9. 57
      app/src/main/java/net/pokeranalytics/android/ui/activity/GraphActivity.kt
  10. 59
      app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt
  11. 63
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt
  12. 7
      app/src/main/res/layout/activity_graph.xml
  13. 14
      app/src/main/res/layout/fragment_graph.xml

@ -7,6 +7,7 @@ apply plugin: 'io.fabric'
repositories { repositories {
maven { url 'https://maven.fabric.io/public' } maven { url 'https://maven.fabric.io/public' }
maven { url 'https://jitpack.io' }
} }
android { android {
@ -95,6 +96,10 @@ dependencies {
// Logs // Logs
implementation 'com.jakewharton.timber:timber:4.7.1' implementation 'com.jakewharton.timber:timber:4.7.1'
// MPAndroidChart
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
// Instrumented Tests
androidTestImplementation 'androidx.test:core:1.1.0' androidTestImplementation 'androidx.test:core:1.1.0'
androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test:rules:1.1.1' androidTestImplementation 'androidx.test:rules:1.1.1'

@ -144,21 +144,21 @@ class Calculator {
tBuyinSum += s.ratedBuyin tBuyinSum += s.ratedBuyin
tHands += s.estimatedHands tHands += s.estimatedHands
results.addEvolutionValue(tSum, NETRESULT) results.addEvolutionValue(tSum, NETRESULT, s)
results.addEvolutionValue(tSum / index, AVERAGE) results.addEvolutionValue(tSum / index, AVERAGE, s)
results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES) results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES, s)
results.addEvolutionValue(tBBSum / tBBSessionCount, AVERAGE_NET_BB) results.addEvolutionValue(tBBSum / tBBSessionCount, AVERAGE_NET_BB, s)
results.addEvolutionValue((tWinningSessionCount / index).toDouble(), WIN_RATIO) results.addEvolutionValue((tWinningSessionCount / index).toDouble(), WIN_RATIO, s)
results.addEvolutionValue(tBuyinSum / index, AVERAGE_BUYIN) results.addEvolutionValue(tBuyinSum / index, AVERAGE_BUYIN, s)
val netBB100 = Stat.netBBPer100Hands(tBBSum, tHands) val netBB100 = Stat.netBBPer100Hands(tBBSum, tHands)
if (netBB100 != null) { if (netBB100 != null) {
results.addEvolutionValue(netBB100, NET_BB_PER_100_HANDS) results.addEvolutionValue(netBB100, NET_BB_PER_100_HANDS, s)
} }
val roi = Stat.returnOnInvestment(tSum, tBuyinSum) val roi = Stat.returnOnInvestment(tSum, tBuyinSum)
if (roi != null) { if (roi != null) {
results.addEvolutionValue(roi, ROI) results.addEvolutionValue(roi, ROI, s)
} }
} }
@ -201,19 +201,19 @@ class Calculator {
tHourlyRate = gSum / tHourlyDuration tHourlyRate = gSum / tHourlyDuration
tHourlyRateBB = gBBSum / tHourlyDuration tHourlyRateBB = gBBSum / tHourlyDuration
results.addEvolutionValue(tSum, tHourlyDuration, NETRESULT) results.addEvolutionValue(tSum, tHourlyDuration, NETRESULT, sessionSet)
results.addEvolutionValue(tSum / tHourlyDuration, tHourlyDuration, HOURLY_RATE) results.addEvolutionValue(tSum / tHourlyDuration, tHourlyDuration, HOURLY_RATE, sessionSet)
results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE) results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, sessionSet)
results.addEvolutionValue(tIndex.toDouble(), tHourlyDuration, NUMBER_OF_SETS) results.addEvolutionValue(tIndex.toDouble(), tHourlyDuration, NUMBER_OF_SETS, sessionSet)
results.addEvolutionValue(sessionSet.netDuration.toDouble(), tHourlyDuration, DURATION) results.addEvolutionValue(sessionSet.netDuration.toDouble(), tHourlyDuration, DURATION, sessionSet)
results.addEvolutionValue(tHourlyDuration / tIndex, tHourlyDuration, AVERAGE_DURATION) results.addEvolutionValue(tHourlyDuration / tIndex, tHourlyDuration, AVERAGE_DURATION, sessionSet)
results.addEvolutionValue(tHourlyRateBB, tHourlyDuration, HOURLY_RATE_BB) results.addEvolutionValue(tHourlyRateBB, tHourlyDuration, HOURLY_RATE_BB, sessionSet)
val netBB100 = Stat.netBBPer100Hands(gBBSum, gTotalHands) val netBB100 = Stat.netBBPer100Hands(gBBSum, gTotalHands)
if (netBB100 != null) { if (netBB100 != null) {
results.addEvolutionValue(netBB100, tHourlyDuration, NET_BB_PER_100_HANDS) results.addEvolutionValue(netBB100, tHourlyDuration, NET_BB_PER_100_HANDS, sessionSet)
} else { //@todo maybe not } else { //@todo maybe not
results.addEvolutionValue(0.0, tHourlyDuration, NET_BB_PER_100_HANDS) results.addEvolutionValue(0.0, tHourlyDuration, NET_BB_PER_100_HANDS, sessionSet)
} }
} }
} }

@ -1,5 +1,7 @@
package net.pokeranalytics.android.calculus package net.pokeranalytics.android.calculus
import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.data.Entry
import io.realm.RealmResults import io.realm.RealmResults
import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.SessionSet import net.pokeranalytics.android.model.realm.SessionSet
@ -58,20 +60,23 @@ class ComputedResults(group: ComputableGroup) {
return this._computedStats.values return this._computedStats.values
} }
fun addEvolutionValue(value: Double, stat: Stat) { /**
this._addEvolutionValue(Point(value), stat = stat) * Adds a value to the evolution values
*/
fun addEvolutionValue(value: Double, stat: Stat, data: Any) {
this._addEvolutionValue(Point(value, data), stat = stat)
} }
fun addEvolutionValue(value: Double, duration: Double, stat: Stat) { fun addEvolutionValue(value: Double, duration: Double, stat: Stat, data: Any) {
this._addEvolutionValue(Point(value, y = duration), stat = stat) this._addEvolutionValue(Point(value, y = duration, data = data), stat = stat)
} }
private fun _addEvolutionValue(point: Point, stat: Stat) { private fun _addEvolutionValue(point: Point, stat: Stat) {
var evolutionValues = this._evolutionValues[stat] val evolutionValues = this._evolutionValues[stat]
if (evolutionValues != null) { if (evolutionValues != null) {
evolutionValues.add(point) evolutionValues.add(point)
} else { } else {
var values: MutableList<Point> = mutableListOf(point) val values: MutableList<Point> = mutableListOf(point)
this._evolutionValues[stat] = values this._evolutionValues[stat] = values
} }
} }
@ -88,7 +93,7 @@ class ComputedResults(group: ComputableGroup) {
fun computeStatVariations(resultsToCompare: ComputedResults) { fun computeStatVariations(resultsToCompare: ComputedResults) {
this._computedStats.keys.forEach { stat -> this._computedStats.keys.forEach { stat ->
var computedStat = this.computedStat(stat) val computedStat = this.computedStat(stat)
val comparedStat = resultsToCompare.computedStat(stat) val comparedStat = resultsToCompare.computedStat(stat)
if (computedStat != null && comparedStat != null) { if (computedStat != null && comparedStat != null) {
computedStat.variation = (computedStat.value - comparedStat.value) / comparedStat.value computedStat.variation = (computedStat.value - comparedStat.value) / comparedStat.value
@ -116,12 +121,51 @@ class ComputedResults(group: ComputableGroup) {
return this._computedStats.size return this._computedStats.size
} }
// MPAndroidChart
fun defaultStatEntries(stat: Stat) : Array<out Entry> {
return when (stat) {
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES -> this.barEntries(stat)
else -> this.singleLineEntries(stat)
}
}
fun singleLineEntries(stat: Stat) : Array<Entry> {
var entries = mutableListOf<Entry>()
this._evolutionValues[stat]?.let { points ->
points.forEachIndexed { index, p ->
entries.add(Entry(index.toFloat(), p.y.toFloat(), p.data))
}
}
return entries.toTypedArray()
}
fun durationEntries(stat: Stat) : Array<Entry> {
var entries = mutableListOf<Entry>()
this._evolutionValues[stat]?.let { points ->
points.forEach { p ->
entries.add(Entry(p.x.toFloat(), p.y.toFloat(), p.data))
}
}
return entries.toTypedArray()
}
fun barEntries(stat: Stat) : Array<BarEntry> {
var entries = arrayOf<BarEntry>()
this._evolutionValues[stat]?.let { points ->
points.forEach { p ->
entries[0] = BarEntry(p.x.toFloat(), p.y.toFloat(), p.data)
}
}
return entries
}
} }
class Point(x: Double, y: Double) { class Point(val x: Double, val y: Double, val data: Any) {
val x: Double = x
val y: Double = y
constructor(x: Double) : this(x, 1.0) constructor(y: Double, data: Any) : this(0.0, y, data)
} }

@ -6,10 +6,11 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
class StatRepresentable(stat: Stat, computedStat: ComputedStat?) : RowRepresentable { class StatRepresentable(stat: Stat, computedStat: ComputedStat?, groupName: String = "") : RowRepresentable {
var stat: Stat = stat var stat: Stat = stat
var computedStat: ComputedStat? = computedStat var computedStat: ComputedStat? = computedStat
var groupName: String = groupName
override val viewType: Int override val viewType: Int
get() = RowViewType.STAT.ordinal get() = RowViewType.STAT.ordinal

@ -1,11 +1,13 @@
package net.pokeranalytics.android.model.realm package net.pokeranalytics.android.model.realm
import android.os.Parcel
import android.os.Parcelable
import io.realm.RealmObject import io.realm.RealmObject
import net.pokeranalytics.android.calculus.interfaces.Computable import net.pokeranalytics.android.calculus.interfaces.Computable
import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.Filterable
import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.filter.QueryCondition
open class ComputableResult : RealmObject(), Computable, Filterable { open class ComputableResult() : RealmObject(), Computable, Filterable, Parcelable {
override var ratedNet: Double = 0.0 override var ratedNet: Double = 0.0
@ -25,6 +27,16 @@ open class ComputableResult : RealmObject(), Computable, Filterable {
var session: Session? = null var session: Session? = null
constructor(parcel: Parcel) : this() {
ratedNet = parcel.readDouble()
bbNet = parcel.readDouble()
hasBigBlind = parcel.readInt()
isPositive = parcel.readInt()
ratedBuyin = parcel.readDouble()
estimatedHands = parcel.readDouble()
bbPer100Hands = parcel.readDouble()
}
fun updateWith(session: Session) { fun updateWith(session: Session) {
this.sessionSet = session.sessionSet this.sessionSet = session.sessionSet
@ -54,7 +66,28 @@ open class ComputableResult : RealmObject(), Computable, Filterable {
BB_PER100HANDS("bbPer100Hands") BB_PER100HANDS("bbPer100Hands")
} }
companion object : Filterable { override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeDouble(ratedNet)
parcel.writeDouble(bbNet)
parcel.writeInt(hasBigBlind)
parcel.writeInt(isPositive)
parcel.writeDouble(ratedBuyin)
parcel.writeDouble(estimatedHands)
parcel.writeDouble(bbPer100Hands)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<ComputableResult>, Filterable {
override fun createFromParcel(parcel: Parcel): ComputableResult {
return ComputableResult(parcel)
}
override fun newArray(size: Int): Array<ComputableResult?> {
return arrayOfNulls(size)
}
fun fieldNameForQueryType(queryCondition: QueryCondition): String? { fun fieldNameForQueryType(queryCondition: QueryCondition): String? {
return "session." + Session.fieldNameForQueryType(queryCondition) return "session." + Session.fieldNameForQueryType(queryCondition)
@ -62,5 +95,4 @@ open class ComputableResult : RealmObject(), Computable, Filterable {
} }
} }

@ -1,5 +1,7 @@
package net.pokeranalytics.android.model.realm package net.pokeranalytics.android.model.realm
import android.os.Parcel
import android.os.Parcelable
import io.realm.Realm import io.realm.Realm
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.RealmResults import io.realm.RealmResults
@ -11,7 +13,7 @@ import net.pokeranalytics.android.model.interfaces.Timed
import java.util.* import java.util.*
open class SessionSet : RealmObject(), Timed, Filterable { open class SessionSet() : RealmObject(), Timed, Filterable, Parcelable {
var startDate: Date = Date() var startDate: Date = Date()
set(value) { set(value) {
@ -49,19 +51,6 @@ open class SessionSet : RealmObject(), Timed, Filterable {
*/ */
override var netDuration: Long = 0L override var netDuration: Long = 0L
companion object : Filterable {
fun newInstance(realm: Realm) : SessionSet {
val sessionSet: SessionSet = realm.createObject(SessionSet::class.java)
return realm.copyToRealm(sessionSet)
}
fun fieldNameForQueryType(queryCondition: QueryCondition): String? {
return "sessions." + Session.fieldNameForQueryType(queryCondition)
}
}
fun computeStats() { fun computeStats() {
this.ratedNet = this.sessions?.sumByDouble { it.computableResult?.ratedNet ?: 0.0 } ?: 0.0 this.ratedNet = this.sessions?.sumByDouble { it.computableResult?.ratedNet ?: 0.0 } ?: 0.0
this.estimatedHands = this.sessions?.sumByDouble { it.estimatedHands } ?: 0.0 this.estimatedHands = this.sessions?.sumByDouble { it.estimatedHands } ?: 0.0
@ -83,6 +72,13 @@ open class SessionSet : RealmObject(), Timed, Filterable {
var bbNet: Double = 0.0 var bbNet: Double = 0.0
constructor(parcel: Parcel) : this() {
netDuration = parcel.readLong()
ratedNet = parcel.readDouble()
estimatedHands = parcel.readDouble()
bbNet = parcel.readDouble()
}
enum class Field(val identifier: String) { enum class Field(val identifier: String) {
RATED_NET("ratedNet"), RATED_NET("ratedNet"),
HOURLY_RATE("hourlyRate"), HOURLY_RATE("hourlyRate"),
@ -91,5 +87,39 @@ open class SessionSet : RealmObject(), Timed, Filterable {
NET_DURATION("netDuration") NET_DURATION("netDuration")
} }
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeLong(netDuration)
parcel.writeDouble(ratedNet)
parcel.writeDouble(estimatedHands)
parcel.writeDouble(bbNet)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<SessionSet>, Filterable {
override fun createFromParcel(parcel: Parcel): SessionSet {
return SessionSet(parcel)
}
override fun newArray(size: Int): Array<SessionSet?> {
return arrayOfNulls(size)
}
// Filterable
fun newInstance(realm: Realm) : SessionSet {
val sessionSet: SessionSet = realm.createObject(SessionSet::class.java)
return realm.copyToRealm(sessionSet)
}
fun fieldNameForQueryType(queryCondition: QueryCondition): String? {
return "sessions." + Session.fieldNameForQueryType(queryCondition)
}
}
} }

@ -9,6 +9,7 @@ import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.fragment.DataListFragment import net.pokeranalytics.android.ui.fragment.DataListFragment
class DataListActivity : PokerAnalyticsActivity() { class DataListActivity : PokerAnalyticsActivity() {
enum class IntentKey(val keyName: String) { enum class IntentKey(val keyName: String) {
DATA_TYPE("DATA_TYPE"), DATA_TYPE("DATA_TYPE"),
ITEM_DELETED("ITEM_DELETED") ITEM_DELETED("ITEM_DELETED")

@ -72,4 +72,5 @@ class EditableDataActivity : PokerAnalyticsActivity() {
fragmentTransaction.commit() fragmentTransaction.commit()
fragment.setData(dataType, primaryKey) fragment.setData(dataType, primaryKey)
} }
} }

@ -0,0 +1,57 @@
package net.pokeranalytics.android.ui.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.github.mikephil.charting.data.Entry
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.fragment.GraphFragment
class GraphActivity : PokerAnalyticsActivity() {
private enum class IntentKey(val keyName: String) {
STAT("STAT"),
ENTRIES("ENTRIES"),
}
companion object {
/**
* Default constructor
*/
fun newInstance(context: Context, stat: Stat, entries: Array<out Entry>) {
val intent = Intent(context, GraphActivity::class.java)
intent.putExtra(IntentKey.STAT.keyName, stat.name)
intent.putExtra(IntentKey.ENTRIES.keyName, entries)
context.startActivity(intent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_editable_data)
initUI()
}
/**
* Init UI
*/
private fun initUI() {
val stat = Stat.valueOf(intent.getStringExtra(IntentKey.STAT.keyName))
val entries = intent.getParcelableArrayExtra(IntentKey.ENTRIES.keyName)
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
val fragment = GraphFragment()
fragmentTransaction.add(R.id.container, fragment)
fragmentTransaction.commit()
fragment.setData(stat, entries)
}
}

@ -0,0 +1,59 @@
package net.pokeranalytics.android.ui.fragment
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import kotlinx.android.synthetic.main.fragment_graph.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
interface GraphDataSource {
}
class GraphFragment : PokerAnalyticsFragment() {
lateinit var dataSource: GraphDataSource
lateinit var entries: Array<Parcelable>
lateinit var stat: Stat
companion object {
}
fun setData(stat: Stat, entries: Array<Parcelable>) {
this.stat = stat
this.entries = entries
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_graph, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initUI()
}
private fun initUI() {
(this.entries.toList() as MutableList<Entry>).let { entries ->
val dataSet = LineDataSet(entries, stat.name)
val lineData = LineData(listOf(dataSet))
this.chart.data = lineData
}
}
}

@ -14,8 +14,10 @@ import net.pokeranalytics.android.model.StatRepresentable
import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet import net.pokeranalytics.android.model.realm.SessionSet
import net.pokeranalytics.android.ui.activity.GraphActivity
import net.pokeranalytics.android.ui.adapter.DisplayDescriptor import net.pokeranalytics.android.ui.adapter.DisplayDescriptor
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.SessionObserverFragment import net.pokeranalytics.android.ui.fragment.components.SessionObserverFragment
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
@ -25,7 +27,8 @@ import timber.log.Timber
import java.util.* import java.util.*
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSource, CoroutineScope { class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSource, CoroutineScope,
RowRepresentableDelegate {
override val coroutineContext: CoroutineContext override val coroutineContext: CoroutineContext
get() = Dispatchers.Main get() = Dispatchers.Main
@ -36,6 +39,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
private var stringTournament = "" private var stringTournament = ""
private lateinit var statsAdapter: RowRepresentableAdapter private lateinit var statsAdapter: RowRepresentableAdapter
private var computedResults : List<ComputedResults>? = null
companion object { companion object {
@ -114,7 +118,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
this.stringCashGame = getString(R.string.cash_game) this.stringCashGame = getString(R.string.cash_game)
this.stringTournament = getString(R.string.tournament) this.stringTournament = getString(R.string.tournament)
this.statsAdapter = RowRepresentableAdapter(this) this.statsAdapter = RowRepresentableAdapter(this, this)
} }
/** /**
@ -131,7 +135,6 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
} }
} }
private fun launchStatComputation() { private fun launchStatComputation() {
GlobalScope.launch(coroutineContext) { GlobalScope.launch(coroutineContext) {
@ -143,6 +146,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
results = createSessionGroupsAndStartCompute(realm) results = createSessionGroupsAndStartCompute(realm)
computedResults = results
realm.close() realm.close()
val e = Date() val e = Date()
@ -202,11 +206,62 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
results.forEach { result -> results.forEach { result ->
rows.add(CustomizableRowRepresentable(title = result.group.name)) rows.add(CustomizableRowRepresentable(title = result.group.name))
result.group.stats?.forEach { stat -> result.group.stats?.forEach { stat ->
rows.add(StatRepresentable(stat, result.computedStat(stat))) rows.add(StatRepresentable(stat, result.computedStat(stat), result.group.name))
} }
} }
return rows return rows
} }
// RowRepresentableDelegate
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
return
if (row is StatRepresentable) {
// filter groups
val groupResults = this.computedResults?.filter {
it.group.name == row.groupName
}
groupResults?.firstOrNull()?.let {
this.launchStatComputationWithEvolution(row.stat, it.group)
}
}
}
private fun launchStatComputationWithEvolution(stat: Stat, computableGroup: ComputableGroup) {
GlobalScope.launch(coroutineContext) {
var results = listOf<ComputedResults>()
val test = GlobalScope.async {
val s = Date()
Timber.d(">>> start...")
val realm = Realm.getDefaultInstance()
val options = Calculator.Options()
options.evolutionValues = Calculator.Options.EvolutionValues.STANDARD
results = Calculator.computeGroups(listOf(computableGroup), options)
realm.close()
val e = Date()
val duration = (e.time - s.time) / 1000.0
Timber.d(">>> ended in ${duration} seconds")
}
test.await()
if (!isDetached) {
results.firstOrNull()?.defaultStatEntries(stat)?.let { entries ->
GraphActivity.newInstance(requireContext(), stat, entries)
}
}
}
}
} }

@ -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,14 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Loading…
Cancel
Save