From 99cf2d465ab863ea74c6d598ae6061fe18e17c46 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 25 Nov 2022 15:51:12 +0100 Subject: [PATCH] Fixes missing ComputableResults in sessions --- .../android/PokerAnalyticsApplication.kt | 4 +- .../android/calculus/Calculator.kt | 2 +- .../android/calculus/ReportWhistleBlower.kt | 6 ++ .../migrations/PokerAnalyticsMigration.kt | 9 +++ .../android/model/realm/ComputableResult.kt | 5 ++ .../android/model/realm/Session.kt | 76 ++++++++----------- .../android/model/realm/SessionSet.kt | 2 +- .../android/ui/fragment/StatisticsFragment.kt | 7 +- .../android/ui/fragment/Top10Fragment.kt | 4 +- .../ui/fragment/components/RealmFragment.kt | 5 +- .../ui/modules/calendar/CalendarFragment.kt | 7 +- .../ui/modules/session/SessionFragment.kt | 5 ++ .../util/extensions/RealmExtensions.kt | 14 ++++ 13 files changed, 85 insertions(+), 61 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt index 8c5d62ba..6d4f240f 100644 --- a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt +++ b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt @@ -54,7 +54,7 @@ class PokerAnalyticsApplication : Application() { Realm.init(this) val realmConfiguration = RealmConfiguration.Builder() .name(Realm.DEFAULT_REALM_NAME) - .schemaVersion(14) + .schemaVersion(15) // .allowWritesOnUiThread(true) .migration(PokerAnalyticsMigration()) .initialData(Seed(this)) @@ -84,7 +84,7 @@ class PokerAnalyticsApplication : Application() { // Report this.reportWhistleBlower = ReportWhistleBlower(this.applicationContext) -// SessionSetManager.configure() + SessionSetManager.configure() // Infos val locale = Locale.getDefault() 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 ec880fbb..bd5f0617 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -618,7 +618,7 @@ class SSStats(sessionSet: SessionSet, query: Query) { // Session Set Stats if (setSessions.size == filteredSessions.size) { this.initStatsWithSet(sessionSet) } else { - ratedNet = filteredSessions.sumOf { it.computableResult?.ratedNet ?: 0.0 } + ratedNet = filteredSessions.sumOf { it.managedComputableResult?.ratedNet ?: 0.0 } bbSum = filteredSessions.sumOf { it.bbNet } hourlyDuration = filteredSessions.hourlyDuration estimatedHands = filteredSessions.sumOf { it.estimatedHands } diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt b/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt index d87b8020..598583e1 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt @@ -22,6 +22,7 @@ class ReportWhistleBlower(var context: Context) { private var sessions: RealmResults? = null private var results: RealmResults? = null + private var sessionSets: RealmResults? = null private var currentTask: ReportTask? = null @@ -47,6 +48,11 @@ class ReportWhistleBlower(var context: Context) { requestReportLaunch() } + this.sessionSets = realm.where(SessionSet::class.java).findAll() + this.sessionSets?.addChangeListener { _ -> + requestReportLaunch() + } + realm.close() } 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 93f7d03c..6070ea18 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 @@ -335,6 +335,15 @@ class PokerAnalyticsMigration : RealmMigration { currentVersion++ } + // Migrate to version 15 + if (currentVersion == 14) { + schema.get("ComputableResult")?.let { crs -> + crs.addField("id", String::class.java).setRequired("id", true) + crs.addPrimaryKey("id") + } + currentVersion++ + } + } override fun equals(other: Any?): Boolean { 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 28a6be15..9e8a3313 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,11 +1,16 @@ package net.pokeranalytics.android.model.realm import io.realm.RealmObject +import io.realm.annotations.PrimaryKey import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.QueryCondition +import java.util.* open class ComputableResult : RealmObject(), Filterable { + @PrimaryKey + var id = UUID.randomUUID().toString() + var ratedNet: Double = 0.0 var bbNet: BB = 0.0 diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt index 5eea0a05..2a85c0a1 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt @@ -33,10 +33,7 @@ import net.pokeranalytics.android.ui.graph.Graph import net.pokeranalytics.android.ui.view.* import net.pokeranalytics.android.ui.view.rows.SessionPropertiesRow import net.pokeranalytics.android.util.* -import net.pokeranalytics.android.util.extensions.hourMinute -import net.pokeranalytics.android.util.extensions.shortDateTime -import net.pokeranalytics.android.util.extensions.toCurrency -import net.pokeranalytics.android.util.extensions.toMinutes +import net.pokeranalytics.android.util.extensions.* import java.lang.ref.WeakReference import java.text.DateFormat import java.text.NumberFormat @@ -163,10 +160,19 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim var result: Result? = null @LinkingObjects("session") - private val computableResults: RealmResults? = null + private val managedComputableResults: RealmResults? = null @Ignore - val computableResult: ComputableResult? = this.computableResults?.firstOrNull() + val managedComputableResult: ComputableResult? = this.managedComputableResults?.firstOrNull() + + @Ignore + var inverseComputableResult: WeakReference? = null + + // @Ignore + fun computableResult() : ComputableResult? { + return this.inverseComputableResult?.get() + } + // Timed interface @@ -488,22 +494,29 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim */ fun computeStats() { + val realm = Realm.getDefaultInstance() + val currentComputableResult = realm.computableResult(this) + // ComputableResult are created only when a session is over - if (this.startDate != null && this.endDate != null && this.computableResults?.size == 0) { - val computableResult = realm.createObject(ComputableResult::class.java) + if (this.startDate != null && this.endDate != null && currentComputableResult == null && this.inverseComputableResult?.get() == null) { + val computableResult = ComputableResult() computableResult.session = this + this.inverseComputableResult = WeakReference(computableResult) } // if a ComputableResult exists and the session is not completed, delete it - else if ((this.startDate == null || this.endDate == null) && this.computableResult != null && this.computableResult.isValid) { - this.computableResult.deleteFromRealm() + else if ((this.startDate == null || this.endDate == null) && currentComputableResult != null && currentComputableResult.isValid) { + currentComputableResult.deleteFromRealm() } + realm.close() + + this.computableResult()?.updateWith(this) // Update the ComputableResult - this.computableResults?.forEachIndexed { index, computableResult -> - computableResult.updateWith(this) - if (index > 0) { - throw PAIllegalStateException("Session cannot have more than one computable result") - } - } +// this.computableResult()?.forEachIndexed { index, computableResult -> +// computableResult.updateWith(this) +// if (index > 0) { +// throw PAIllegalStateException("Session cannot have more than one computable result") +// } +// } this.sessionSet?.computeStats() } @@ -759,7 +772,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim } // cleanup unnecessary related objects this.result?.deleteFromRealm() - this.computableResults?.deleteAllFromRealm() + this.computableResult()?.deleteFromRealm() } @@ -1017,7 +1030,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim var right: TextFormat? = null if (!hasMainCurrencyCode) { - this.computableResult?.ratedNet?.let { ratedNet -> + this.managedComputableResult?.ratedNet?.let { ratedNet -> right = Stat.NET_RESULT.textFormat(ratedNet) } } @@ -1105,33 +1118,6 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim this.result?.netResult = null } - /// Stakes - -// fun generateStakes() { -// -// if (this.cgAnte == null && this.cgAnte == null) { -// this.cgStakes = null -// return -// } -// -// val components = arrayListOf() -// -// this.cgBlinds?.let { components.add("${cbBlinds}${it}") } -// this.cgAnte?.let { components.add("${cbAnte}${it.formatted}") } -// -// val code = this.bankroll?.currency?.code ?: UserDefaults.currency.currencyCode -// components.add("${cbCode}${code}") -// -// this.cgStakes = components.joinToString(cbSeparator) -// } -// -// fun defineHighestBet() { -// val bets = arrayListOf() -// this.cgAnte?.let { bets.add(it) } -// bets.addAll(this.blindValues) -// this.cgBiggestBet = bets.maxOrNull() -// } - private fun cleanupBlinds(blinds: String?): String? { if (blinds == null) { 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 20025072..5729e399 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 @@ -61,7 +61,7 @@ open class SessionSet() : RealmObject(), Timed, Filterable { override var netDuration: Long = 0L fun computeStats() { - this.ratedNet = this.sessions?.sumOf { it.computableResult?.ratedNet ?: 0.0 } ?: 0.0 + this.ratedNet = this.sessions?.sumOf { it.managedComputableResult?.ratedNet ?: 0.0 } ?: 0.0 this.estimatedHands = this.sessions?.sumOf { it.estimatedHands } ?: 0.0 this.bbNet = this.sessions?.sumOf { it.bbNet } ?: 0.0 this.breakDuration = this.sessions?.max("breakDuration")?.toLong() ?: 0L diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt index 7055fe43..e164b283 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt @@ -8,7 +8,10 @@ import android.os.Bundle import android.view.* import androidx.appcompat.widget.Toolbar import io.realm.Realm -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.launch import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.ComputableGroup @@ -27,7 +30,6 @@ import net.pokeranalytics.android.ui.modules.filter.FilterableType import net.pokeranalytics.android.ui.modules.filter.FiltersActivity import net.pokeranalytics.android.ui.modules.settings.TransactionFilterActivity import timber.log.Timber -import java.util.* class StatisticsFragment : FilterableFragment(), RealmAsyncListener { @@ -73,6 +75,7 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener { addRealmChangeListener(this, UserConfig::class.java) addRealmChangeListener(this, ComputableResult::class.java) addRealmChangeListener(this, Transaction::class.java) + addRealmChangeListener(this, SessionSet::class.java) } private fun initUI() { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt index 47934d3a..a0ed866a 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt @@ -141,10 +141,10 @@ class Top10Fragment : RealmFragment(), RowRepresentableDataSource, RowRepresenta // Sort by rated net val sortedCashGames = cashGames.sortedByDescending { - it.computableResult?.ratedNet + it.managedComputableResult?.ratedNet }.toMutableList() val sortedTournaments = tournaments.sortedByDescending { - it.computableResult?.ratedNet + it.managedComputableResult?.ratedNet }.toMutableList() // Keep 10 items diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt index 3c3a3e84..a4522964 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt @@ -7,10 +7,7 @@ import android.view.ViewGroup import io.realm.Realm import io.realm.RealmModel import io.realm.RealmResults -import kotlinx.coroutines.Dispatchers import net.pokeranalytics.android.exceptions.PAIllegalStateException -import timber.log.Timber -import kotlin.coroutines.CoroutineContext interface RealmAsyncListener { fun asyncListenedEntityChange(realm: Realm) @@ -67,7 +64,7 @@ open class RealmFragment : BaseFragment() { this.changeListener = listener val results = this.realm.where(clazz).findAllAsync() results.addChangeListener { t, _ -> - Timber.d("Realm changes: ${realmResults?.size}, $this") +// Timber.d("Realm changes: ${realmResults?.size}, $this") this.changeListener?.asyncListenedEntityChange(t.realm) } this.observedRealmResults.add(results) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarFragment.kt index 642661b2..c6da4f5c 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarFragment.kt @@ -22,10 +22,7 @@ import net.pokeranalytics.android.model.Criteria import net.pokeranalytics.android.model.combined import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.QueryCondition -import net.pokeranalytics.android.model.realm.ComputableResult -import net.pokeranalytics.android.model.realm.Transaction -import net.pokeranalytics.android.model.realm.TransactionType -import net.pokeranalytics.android.model.realm.UserConfig +import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource @@ -106,7 +103,9 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource, addRealmChangeListener(this, UserConfig::class.java) addRealmChangeListener(this, ComputableResult::class.java) addRealmChangeListener(this, Transaction::class.java) + addRealmChangeListener(this, SessionSet::class.java) } + private var transactionFilterMenuItem: MenuItem? = null override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt index c5d9b3d8..7633994d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt @@ -309,6 +309,11 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr } getRealm().executeTransactionAsync { realm -> realm.copyToRealmOrUpdate(this.currentSession) + + this.currentSession.inverseComputableResult?.get()?.let { computableResult -> + realm.copyToRealmOrUpdate(computableResult) + } + } } diff --git a/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt b/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt index 3ca760d1..dc0d225c 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt @@ -1,6 +1,8 @@ package net.pokeranalytics.android.util.extensions import io.realm.* +import io.realm.kotlin.where +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.interfaces.Identifiable @@ -149,8 +151,20 @@ fun Realm.lookupForNameInAllTablesById(id: String): String? { return null } +fun Realm.computableResult(session: Session): ComputableResult? { + val crs = this.where().equalTo("session.id", session.id).findAll() + if (crs.size > 1) { + throw PAIllegalStateException("Session has multiple computable results") + } + return crs.firstOrNull() +} + fun Realm.copySessionFromRealm(session: Session): Session { val copy = this.copyFromRealm(session) copy.result?.inverseSession = WeakReference(copy) + this.computableResult(session)?.let { + val computableResult = this.copyFromRealm(it) + copy.inverseComputableResult = WeakReference(computableResult) + } return copy } \ No newline at end of file