diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 90f7c4fd..f304e967 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -64,6 +64,11 @@ android:launchMode="singleTop" android:screenOrientation="portrait" /> + + diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt index bb24beb3..03fb0152 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -1,5 +1,8 @@ package net.pokeranalytics.android.calculus +import android.os.Parcel +import android.os.Parcelable +import io.realm.Realm import net.pokeranalytics.android.calculus.Stat.* import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.model.realm.Filter @@ -7,6 +10,31 @@ import net.pokeranalytics.android.model.realm.SessionSet import timber.log.Timber import java.util.* +class ParcelableString(var string: String) : Parcelable { + constructor(parcel: Parcel) : this(parcel.readString()) { + } + + override fun writeToParcel(parcel: Parcel, flags: Int) { + parcel.writeString(string) + } + + override fun describeContents(): Int { + return 0 + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): ParcelableString { + return ParcelableString(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + +} + + /** * The class performing stats computation */ @@ -59,35 +87,39 @@ class Calculator { companion object { - fun computeStatsWithFilters(filters: List, options: Options): List { + fun computeStatsWithFilters(realm: Realm, filters: List, options: Options): List { var computableGroups: MutableList = mutableListOf() filters.forEach { filter -> val results = filter.results() val sets = filter.results() - val group = ComputableGroup(filter.name, results, sets) + val group = ComputableGroup(filter.name, filter.filterConditions.map { it.queryCondition }) computableGroups.add(group) } - return Calculator.computeGroups(computableGroups, options) + return Calculator.computeGroups(realm, computableGroups, options) } /** * Computes all stats for list of Session sessionGroup */ - fun computeGroups(groups: List, options: Options): List { + fun computeGroups(realm: Realm, groups: List, options: Options): List { val computedResults = mutableListOf() groups.forEach { group -> val s = Date() + + // Clean existing computables / sessionSets if group is reused + group.cleanup() + // Computes actual sessionGroup stats - val results: ComputedResults = Calculator.compute(group, options = options) + val results: ComputedResults = Calculator.compute(realm, group, options = options) // Computes the compared sessionGroup if existing val comparedGroup = group.comparedComputables if (comparedGroup != null) { - val comparedResults = Calculator.compute(comparedGroup, options = options) + val comparedResults = Calculator.compute(realm, comparedGroup, options = options) group.comparedComputedResults = comparedResults results.computeStatVariations(comparedResults) } @@ -107,11 +139,10 @@ class Calculator { /** * Computes stats for a SessionSet */ - fun compute(computableGroup: ComputableGroup, options: Options): ComputedResults { - - Timber.d(">>>> Start computing group ${computableGroup.name}, ${computableGroup.computables.size} computables") + fun compute(realm: Realm, computableGroup: ComputableGroup, options: Options): ComputedResults { - val computables = computableGroup.computables + val computables = computableGroup.computables(realm) + Timber.d(">>>> Start computing group ${computableGroup.name}, ${computables.size} computables") val results: ComputedResults = ComputedResults(computableGroup) @@ -135,30 +166,29 @@ class Calculator { var tBuyinSum = 0.0 var tHands = 0.0 - computables.forEach { s -> + computables.forEach { computable -> index++ - tSum += s.ratedNet - tBBSum += s.bbNet - tBBSessionCount += s.hasBigBlind - tWinningSessionCount += s.isPositive - tBuyinSum += s.ratedBuyin - tHands += s.estimatedHands - - results.addEvolutionValue(tSum, NETRESULT, s) - results.addEvolutionValue(tSum / index, AVERAGE, s) - results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES, s) - results.addEvolutionValue(tBBSum / tBBSessionCount, AVERAGE_NET_BB, s) - results.addEvolutionValue((tWinningSessionCount / index).toDouble(), WIN_RATIO, s) - results.addEvolutionValue(tBuyinSum / index, AVERAGE_BUYIN, s) - - val netBB100 = Stat.netBBPer100Hands(tBBSum, tHands) - if (netBB100 != null) { - results.addEvolutionValue(netBB100, NET_BB_PER_100_HANDS, s) + tSum += computable.ratedNet + tBBSum += computable.bbNet + tBBSessionCount += computable.hasBigBlind + tWinningSessionCount += computable.isPositive + tBuyinSum += computable.ratedBuyin + tHands += computable.estimatedHands + + val sessionId = ParcelableString(computable.session?.id ?: throw IllegalStateException("Computing lone ComputableResult")) + results.addEvolutionValue(tSum, NETRESULT, sessionId) + results.addEvolutionValue(tSum / index, AVERAGE, sessionId) + results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES, sessionId) + results.addEvolutionValue(tBBSum / tBBSessionCount, AVERAGE_NET_BB, sessionId) + results.addEvolutionValue((tWinningSessionCount / index).toDouble(), WIN_RATIO, sessionId) + results.addEvolutionValue(tBuyinSum / index, AVERAGE_BUYIN, sessionId) + + Stat.netBBPer100Hands(tBBSum, tHands)?.let { netBB100 -> + results.addEvolutionValue(netBB100, NET_BB_PER_100_HANDS, sessionId) } - val roi = Stat.returnOnInvestment(tSum, tBuyinSum) - if (roi != null) { - results.addEvolutionValue(roi, ROI, s) + Stat.returnOnInvestment(tSum, tBuyinSum)?.let { roi -> + results.addEvolutionValue(roi, ROI, sessionId) } } @@ -168,7 +198,7 @@ class Calculator { } } - val sessionSets = computableGroup.sets + val sessionSets = computableGroup.sessionSets(realm) // Compute for each serie val gHourlyDuration = @@ -201,20 +231,19 @@ class Calculator { tHourlyRate = gSum / tHourlyDuration tHourlyRateBB = gBBSum / tHourlyDuration - results.addEvolutionValue(tSum, tHourlyDuration, NETRESULT, sessionSet) - results.addEvolutionValue(tSum / tHourlyDuration, tHourlyDuration, HOURLY_RATE, sessionSet) - results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, sessionSet) - results.addEvolutionValue(tIndex.toDouble(), tHourlyDuration, NUMBER_OF_SETS, sessionSet) - results.addEvolutionValue(sessionSet.netDuration.toDouble(), tHourlyDuration, DURATION, sessionSet) - results.addEvolutionValue(tHourlyDuration / tIndex, tHourlyDuration, AVERAGE_DURATION, sessionSet) - results.addEvolutionValue(tHourlyRateBB, tHourlyDuration, HOURLY_RATE_BB, sessionSet) - - val netBB100 = Stat.netBBPer100Hands(gBBSum, gTotalHands) - if (netBB100 != null) { - results.addEvolutionValue(netBB100, tHourlyDuration, NET_BB_PER_100_HANDS, sessionSet) - } else { //@todo maybe not - results.addEvolutionValue(0.0, tHourlyDuration, NET_BB_PER_100_HANDS, sessionSet) + val id = ParcelableString(sessionSet.id) + results.addEvolutionValue(tSum, tHourlyDuration, NETRESULT, id) + results.addEvolutionValue(tSum / tHourlyDuration, tHourlyDuration, HOURLY_RATE, id) + results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, id) + results.addEvolutionValue(tIndex.toDouble(), tHourlyDuration, NUMBER_OF_SETS, id) + results.addEvolutionValue(sessionSet.netDuration.toDouble(), tHourlyDuration, DURATION, id) + results.addEvolutionValue(tHourlyDuration / tIndex, tHourlyDuration, AVERAGE_DURATION, id) + results.addEvolutionValue(tHourlyRateBB, tHourlyDuration, HOURLY_RATE_BB, id) + + Stat.netBBPer100Hands(gBBSum, gTotalHands)?.let { netBB100 -> + results.addEvolutionValue(netBB100, tHourlyDuration, NET_BB_PER_100_HANDS, id) } + } } else -> { @@ -261,13 +290,10 @@ class Calculator { ) ) - val roi = Stat.returnOnInvestment(sum, totalBuyin) - val netBB100 = Stat.netBBPer100Hands(bbSum, totalHands) - - if (roi != null) { + Stat.returnOnInvestment(sum, totalBuyin)?.let { roi -> results.addStats(setOf(ComputedStat(ROI, roi))) } - if (netBB100 != null) { + Stat.netBBPer100Hands(bbSum, totalHands)?.let { netBB100 -> results.addStats(setOf(ComputedStat(NET_BB_PER_100_HANDS, netBB100))) } diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt b/app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt index 6899353c..57b50c37 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt @@ -2,161 +2,207 @@ package net.pokeranalytics.android.calculus import com.github.mikephil.charting.data.BarEntry import com.github.mikephil.charting.data.Entry +import io.realm.Realm import io.realm.RealmResults +import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.realm.ComputableResult +import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.model.realm.SessionSet /** * A sessionGroup of computable items identified by a name */ -class ComputableGroup(name: String, computables: RealmResults, sets: RealmResults, stats: List? = null) { - - /** - * The display name of the group - */ - var name: String = name - - /** - * The list of endedSessions to compute - */ - var computables: RealmResults = computables - - /** - * The list of endedSessions to compute - */ - var sets: RealmResults = sets - - /** - * The list of stats to display - */ - var stats: List? = stats - - /** - * A subgroup used to compute stat variation - */ - var comparedComputables: ComputableGroup? = null - - /** - * The computed stats of the comparable sessionGroup - */ - var comparedComputedResults: ComputedResults? = null +class ComputableGroup(name: String, conditions: List, stats: List? = null) { + + /** + * The display name of the group + */ + var name: String = name + + /** + * A list of conditions to get + */ + var conditions: List = conditions + + /** + * The list of endedSessions to compute + */ + private var _computables: RealmResults? = null + + /** + * Retrieves the computables on the relative [realm] filtered with the provided [conditions] + */ + fun computables(realm: Realm): RealmResults { + + // if computables exists and is valid (previous realm not closed) + this._computables?.let { + if (it.isValid) { + return it + } + } + + val computables: RealmResults = Filter.queryOn(realm, this.conditions) + this._computables = computables + return computables + } + + /** + * The list of sets to compute + */ + private var _sessionSets: RealmResults? = null + + /** + * Retrieves the session sets on the relative [realm] filtered with the provided [conditions] + */ + fun sessionSets(realm: Realm): RealmResults { + // if computables exists and is valid (previous realm not closed) + this._sessionSets?.let { + if (it.isValid) { + return it + } + } + + val sets: RealmResults = Filter.queryOn(realm, this.conditions) + this._sessionSets = sets + return sets + } + + /** + * The list of stats to display + */ + var stats: List? = stats + + /** + * A subgroup used to compute stat variation + */ + var comparedComputables: ComputableGroup? = null + + /** + * The computed stats of the comparable sessionGroup + */ + var comparedComputedResults: ComputedResults? = null + + fun cleanup() { + this._computables = null + this._sessionSets = null + } } class ComputedResults(group: ComputableGroup) { - /** - * The session group used to computed the stats - */ - var group: ComputableGroup = group - - // The computed stats of the sessionGroup - private var _computedStats: MutableMap = mutableMapOf() - - // The map containing all evolution numericValues for all stats - private var _evolutionValues: MutableMap> = mutableMapOf() - - fun allStats() : Collection { - return this._computedStats.values - } - - /** - * 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, data: Any) { - this._addEvolutionValue(Point(value, y = duration, data = data), stat = stat) - } - - private fun _addEvolutionValue(point: Point, stat: Stat) { - val evolutionValues = this._evolutionValues[stat] - if (evolutionValues != null) { - evolutionValues.add(point) - } else { - val values: MutableList = mutableListOf(point) - this._evolutionValues[stat] = values - } - } - - fun addStats(computedStats: Set) { - computedStats.forEach { - this._computedStats[it.stat] = it - } - } - - fun computedStat(stat: Stat) : ComputedStat? { - return this._computedStats[stat] - } - - fun computeStatVariations(resultsToCompare: ComputedResults) { - this._computedStats.keys.forEach { stat -> - val computedStat = this.computedStat(stat) - val comparedStat = resultsToCompare.computedStat(stat) - if (computedStat != null && comparedStat != null) { - computedStat.variation = (computedStat.value - comparedStat.value) / comparedStat.value - } - } - } - - fun finalize(options: Calculator.Options) { - if (options.evolutionValues != Calculator.Options.EvolutionValues.NONE) { - - // Sort points as a distribution - this._computedStats.keys.filter { it.hasDistributionSorting() }.forEach { _ -> - // @todo sort + /** + * The session group used to computed the stats + */ + var group: ComputableGroup = group + + // The computed stats of the sessionGroup + private var _computedStats: MutableMap = mutableMapOf() + + // The map containing all evolution numericValues for all stats + private var _evolutionValues: MutableMap> = mutableMapOf() + + fun allStats(): Collection { + return this._computedStats.values + } + + /** + * 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, data: Any) { + this._addEvolutionValue(Point(value, y = duration, data = data), stat = stat) + } + + private fun _addEvolutionValue(point: Point, stat: Stat) { + val evolutionValues = this._evolutionValues[stat] + if (evolutionValues != null) { + evolutionValues.add(point) + } else { + val values: MutableList = mutableListOf(point) + this._evolutionValues[stat] = values + } + } + + fun addStats(computedStats: Set) { + computedStats.forEach { + this._computedStats[it.stat] = it + } + } + + fun computedStat(stat: Stat): ComputedStat? { + return this._computedStats[stat] + } + + fun computeStatVariations(resultsToCompare: ComputedResults) { + this._computedStats.keys.forEach { stat -> + val computedStat = this.computedStat(stat) + val comparedStat = resultsToCompare.computedStat(stat) + if (computedStat != null && comparedStat != null) { + computedStat.variation = (computedStat.value - comparedStat.value) / comparedStat.value + } + } + } + + fun finalize(options: Calculator.Options) { + if (options.evolutionValues != Calculator.Options.EvolutionValues.NONE) { + + // Sort points as a distribution + this._computedStats.keys.filter { it.hasDistributionSorting() }.forEach { _ -> + // @todo sort // var evolutionValues = this._evolutionValues[stat] // evolutionValues.so - } + } - } - } + } + } - /** - * Returns the number of computed stats - */ - fun numberOfStats() : Int { - return this._computedStats.size - } + /** + * Returns the number of computed stats + */ + fun numberOfStats(): Int { + return this._computedStats.size + } // MPAndroidChart - fun defaultStatEntries(stat: Stat) : Array { + fun defaultStatEntries(stat: Stat): List { return when (stat) { Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES -> this.barEntries(stat) else -> this.singleLineEntries(stat) } } - fun singleLineEntries(stat: Stat) : Array { + fun singleLineEntries(stat: Stat): List { var entries = mutableListOf() this._evolutionValues[stat]?.let { points -> points.forEachIndexed { index, p -> entries.add(Entry(index.toFloat(), p.y.toFloat(), p.data)) } } - return entries.toTypedArray() + return entries } - fun durationEntries(stat: Stat) : Array { + fun durationEntries(stat: Stat): List { var entries = mutableListOf() this._evolutionValues[stat]?.let { points -> points.forEach { p -> entries.add(Entry(p.x.toFloat(), p.y.toFloat(), p.data)) } } - return entries.toTypedArray() + return entries } - fun barEntries(stat: Stat) : Array { + fun barEntries(stat: Stat): List { - var entries = arrayOf() + var entries = mutableListOf() this._evolutionValues[stat]?.let { points -> points.forEach { p -> - entries[0] = BarEntry(p.x.toFloat(), p.y.toFloat(), p.data) + entries.add(BarEntry(p.x.toFloat(), p.y.toFloat(), p.data)) } } return entries diff --git a/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt b/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt index 77d26c60..d27daf72 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt @@ -40,6 +40,10 @@ class PokerAnalyticsMigration : RealmMigration { schema.get("Filter")?.let { it.renameField("filterElements", "filterConditions") } + schema.get("SessionSet")?.let { + it.addPrimaryKey("id") + } + currentVersion++ } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt index 427621d8..e0786847 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt @@ -1,13 +1,11 @@ package net.pokeranalytics.android.model.realm -import android.os.Parcel -import android.os.Parcelable import io.realm.RealmObject import net.pokeranalytics.android.calculus.interfaces.Computable import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.QueryCondition -open class ComputableResult() : RealmObject(), Computable, Filterable, Parcelable { +open class ComputableResult() : RealmObject(), Computable, Filterable { override var ratedNet: Double = 0.0 @@ -27,16 +25,6 @@ open class ComputableResult() : RealmObject(), Computable, Filterable, Parcelabl 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) { this.sessionSet = session.sessionSet @@ -66,28 +54,7 @@ open class ComputableResult() : RealmObject(), Computable, Filterable, Parcelabl BB_PER100HANDS("bbPer100Hands") } - 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, Filterable { - override fun createFromParcel(parcel: Parcel): ComputableResult { - return ComputableResult(parcel) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } + companion object : Filterable { fun fieldNameForQueryType(queryCondition: QueryCondition): String? { return "session." + Session.fieldNameForQueryType(queryCondition) diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt index 9ccaa0a0..c962b609 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt @@ -10,6 +10,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow import org.jetbrains.annotations.TestOnly +import timber.log.Timber import java.util.* /** @@ -43,8 +44,9 @@ open class Filter : RealmObject() { inline fun queryOn(realm: Realm, queries: List): RealmResults { var realmQuery = realm.where() queries.forEach { - realmQuery = it.filter(realmQuery) + realmQuery = it.filter(realmQuery) } + Timber.d(">>> Filter query: ${realmQuery.description}") return realmQuery.findAll() } } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt index eee014a1..6a3ae55d 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt @@ -1,19 +1,21 @@ package net.pokeranalytics.android.model.realm -import android.os.Parcel -import android.os.Parcelable import io.realm.Realm import io.realm.RealmObject import io.realm.RealmResults import io.realm.annotations.Ignore import io.realm.annotations.LinkingObjects +import io.realm.annotations.PrimaryKey import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.interfaces.Timed import java.util.* -open class SessionSet() : RealmObject(), Timed, Filterable, Parcelable { +open class SessionSet() : RealmObject(), Timed, Filterable { + + @PrimaryKey + var id = UUID.randomUUID().toString() var startDate: Date = Date() set(value) { @@ -72,13 +74,6 @@ open class SessionSet() : RealmObject(), Timed, Filterable, Parcelable { 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) { RATED_NET("ratedNet"), HOURLY_RATE("hourlyRate"), @@ -87,31 +82,10 @@ open class SessionSet() : RealmObject(), Timed, Filterable, Parcelable { 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, Filterable { - - override fun createFromParcel(parcel: Parcel): SessionSet { - return SessionSet(parcel) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - - // Filterable + companion object : Filterable { fun newInstance(realm: Realm) : SessionSet { - val sessionSet: SessionSet = realm.createObject(SessionSet::class.java) + val sessionSet = SessionSet() return realm.copyToRealm(sessionSet) } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/GraphActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/GraphActivity.kt index 4de9e896..4140b81a 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/GraphActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/GraphActivity.kt @@ -9,6 +9,11 @@ import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.fragment.GraphFragment +class GraphParameters(stat: Stat, entries: List) { + var stat: Stat = stat + var entries: List = entries +} + class GraphActivity : PokerAnalyticsActivity() { private enum class IntentKey(val keyName: String) { @@ -18,13 +23,17 @@ class GraphActivity : PokerAnalyticsActivity() { companion object { + // Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects + var parameters: GraphParameters? = null + /** * Default constructor */ - fun newInstance(context: Context, stat: Stat, entries: Array) { + fun newInstance(context: Context, stat: Stat, entries: List) { + + GraphActivity.parameters = GraphParameters(stat, entries) + val intent = Intent(context, GraphActivity::class.java) - intent.putExtra(IntentKey.STAT.keyName, stat.name) - intent.putExtra(IntentKey.ENTRIES.keyName, entries) context.startActivity(intent) } @@ -41,16 +50,19 @@ class GraphActivity : PokerAnalyticsActivity() { */ 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) + + GraphActivity.parameters?.let { + fragment.setData(it.stat, it.entries) + GraphActivity.parameters = null + } ?: run { + throw Exception("Missing graph parameters") + } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt index fc2bd3c8..4f713c6e 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt @@ -1,7 +1,6 @@ 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 @@ -21,16 +20,16 @@ interface GraphDataSource { class GraphFragment : PokerAnalyticsFragment() { lateinit var dataSource: GraphDataSource - lateinit var entries: Array + lateinit var stat: Stat + lateinit var entries: List companion object { - } - fun setData(stat: Stat, entries: Array) { + fun setData(stat: Stat, entries: List) { this.stat = stat this.entries = entries } @@ -46,13 +45,9 @@ class GraphFragment : PokerAnalyticsFragment() { private fun initUI() { - (this.entries.toList() as MutableList).let { entries -> - - val dataSet = LineDataSet(entries, stat.name) - val lineData = LineData(listOf(dataSet)) - this.chart.data = lineData - - } + val dataSet = LineDataSet(this.entries, this.stat.name) + val lineData = LineData(listOf(dataSet)) + this.chart.data = lineData } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt index afb7845e..000e43de 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt @@ -11,9 +11,7 @@ import kotlinx.coroutines.* import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.* import net.pokeranalytics.android.model.StatRepresentable -import net.pokeranalytics.android.model.realm.ComputableResult -import net.pokeranalytics.android.model.realm.Session -import net.pokeranalytics.android.model.realm.SessionSet +import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.ui.activity.GraphActivity import net.pokeranalytics.android.ui.adapter.DisplayDescriptor import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter @@ -165,32 +163,16 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc private fun createSessionGroupsAndStartCompute(realm: Realm) : List { - val s = Date() - - val allSessions = realm.where(ComputableResult::class.java).findAll() - val allSessionSets = realm.where(SessionSet::class.java).findAll() - Timber.d(">>>>> number of computables to compute = ${allSessions.size}") - - val cgSessions = allSessions.where().equalTo("session.type", Session.Type.CASH_GAME.ordinal).findAll() - val cgSessionSets = realm.where(SessionSet::class.java).equalTo("sessions.type", Session.Type.CASH_GAME.ordinal).findAll() - - val tSessions = allSessions.where().equalTo("session.type", Session.Type.TOURNAMENT.ordinal).findAll() - val tSessionSets = realm.where(SessionSet::class.java).equalTo("sessions.type", Session.Type.TOURNAMENT.ordinal).findAll() - - val e = Date() - val duration = (e.time - s.time) / 1000.0 - Timber.d(">>> filtering in ${duration} seconds") - val allStats: List = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE, Stat.NUMBER_OF_SETS, Stat.AVERAGE_DURATION, Stat.DURATION) - val allSessionGroup = ComputableGroup(stringAll, allSessions, allSessionSets, allStats) + val allSessionGroup = ComputableGroup(stringAll, listOf(), allStats) val cgStats: List = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.NET_BB_PER_100_HANDS, Stat.HOURLY_RATE_BB, Stat.AVERAGE, Stat.STANDARD_DEVIATION_HOURLY, Stat.WIN_RATIO, Stat.NUMBER_OF_GAMES, Stat.AVERAGE_BUYIN) - val cgSessionGroup = ComputableGroup(stringCashGame, cgSessions, cgSessionSets, cgStats) + val cgSessionGroup = ComputableGroup(stringCashGame, listOf(QueryCondition.CASH), cgStats) val tStats: List = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.ROI, Stat.WIN_RATIO, Stat.NUMBER_OF_GAMES, Stat.AVERAGE_BUYIN) - val tSessionGroup = ComputableGroup(stringTournament, tSessions, tSessionSets, tStats) + val tSessionGroup = ComputableGroup(stringTournament, listOf(QueryCondition.TOURNAMENT), tStats) Timber.d(">>>>> Start computations...") - return Calculator.computeGroups(listOf(allSessionGroup, cgSessionGroup, tSessionGroup), Calculator.Options()) + return Calculator.computeGroups(realm, listOf(allSessionGroup, cgSessionGroup, tSessionGroup), Calculator.Options()) } @@ -217,8 +199,6 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { - return - if (row is StatRepresentable) { // filter groups @@ -245,7 +225,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc val realm = Realm.getDefaultInstance() val options = Calculator.Options() options.evolutionValues = Calculator.Options.EvolutionValues.STANDARD - results = Calculator.computeGroups(listOf(computableGroup), options) + results = Calculator.computeGroups(realm, listOf(computableGroup), options) realm.close() val e = Date()