Fixes missing ComputableResults in sessions

perftest
Laurent 3 years ago
parent 0aac37b288
commit 99cf2d465a
  1. 4
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  2. 2
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  3. 6
      app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt
  4. 9
      app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt
  5. 5
      app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt
  6. 76
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  7. 2
      app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt
  8. 7
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt
  9. 4
      app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt
  10. 5
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt
  11. 7
      app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarFragment.kt
  12. 5
      app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt
  13. 14
      app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt

@ -54,7 +54,7 @@ class PokerAnalyticsApplication : Application() {
Realm.init(this) Realm.init(this)
val realmConfiguration = RealmConfiguration.Builder() val realmConfiguration = RealmConfiguration.Builder()
.name(Realm.DEFAULT_REALM_NAME) .name(Realm.DEFAULT_REALM_NAME)
.schemaVersion(14) .schemaVersion(15)
// .allowWritesOnUiThread(true) // .allowWritesOnUiThread(true)
.migration(PokerAnalyticsMigration()) .migration(PokerAnalyticsMigration())
.initialData(Seed(this)) .initialData(Seed(this))
@ -84,7 +84,7 @@ class PokerAnalyticsApplication : Application() {
// Report // Report
this.reportWhistleBlower = ReportWhistleBlower(this.applicationContext) this.reportWhistleBlower = ReportWhistleBlower(this.applicationContext)
// SessionSetManager.configure() SessionSetManager.configure()
// Infos // Infos
val locale = Locale.getDefault() val locale = Locale.getDefault()

@ -618,7 +618,7 @@ class SSStats(sessionSet: SessionSet, query: Query) { // Session Set Stats
if (setSessions.size == filteredSessions.size) { if (setSessions.size == filteredSessions.size) {
this.initStatsWithSet(sessionSet) this.initStatsWithSet(sessionSet)
} else { } else {
ratedNet = filteredSessions.sumOf { it.computableResult?.ratedNet ?: 0.0 } ratedNet = filteredSessions.sumOf { it.managedComputableResult?.ratedNet ?: 0.0 }
bbSum = filteredSessions.sumOf { it.bbNet } bbSum = filteredSessions.sumOf { it.bbNet }
hourlyDuration = filteredSessions.hourlyDuration hourlyDuration = filteredSessions.hourlyDuration
estimatedHands = filteredSessions.sumOf { it.estimatedHands } estimatedHands = filteredSessions.sumOf { it.estimatedHands }

@ -22,6 +22,7 @@ class ReportWhistleBlower(var context: Context) {
private var sessions: RealmResults<Session>? = null private var sessions: RealmResults<Session>? = null
private var results: RealmResults<Result>? = null private var results: RealmResults<Result>? = null
private var sessionSets: RealmResults<SessionSet>? = null
private var currentTask: ReportTask? = null private var currentTask: ReportTask? = null
@ -47,6 +48,11 @@ class ReportWhistleBlower(var context: Context) {
requestReportLaunch() requestReportLaunch()
} }
this.sessionSets = realm.where(SessionSet::class.java).findAll()
this.sessionSets?.addChangeListener { _ ->
requestReportLaunch()
}
realm.close() realm.close()
} }

@ -335,6 +335,15 @@ class PokerAnalyticsMigration : RealmMigration {
currentVersion++ 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 { override fun equals(other: Any?): Boolean {

@ -1,11 +1,16 @@
package net.pokeranalytics.android.model.realm package net.pokeranalytics.android.model.realm
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
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
import java.util.*
open class ComputableResult : RealmObject(), Filterable { open class ComputableResult : RealmObject(), Filterable {
@PrimaryKey
var id = UUID.randomUUID().toString()
var ratedNet: Double = 0.0 var ratedNet: Double = 0.0
var bbNet: BB = 0.0 var bbNet: BB = 0.0

@ -33,10 +33,7 @@ import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.view.* import net.pokeranalytics.android.ui.view.*
import net.pokeranalytics.android.ui.view.rows.SessionPropertiesRow import net.pokeranalytics.android.ui.view.rows.SessionPropertiesRow
import net.pokeranalytics.android.util.* import net.pokeranalytics.android.util.*
import net.pokeranalytics.android.util.extensions.hourMinute import net.pokeranalytics.android.util.extensions.*
import net.pokeranalytics.android.util.extensions.shortDateTime
import net.pokeranalytics.android.util.extensions.toCurrency
import net.pokeranalytics.android.util.extensions.toMinutes
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.text.DateFormat import java.text.DateFormat
import java.text.NumberFormat import java.text.NumberFormat
@ -163,10 +160,19 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
var result: Result? = null var result: Result? = null
@LinkingObjects("session") @LinkingObjects("session")
private val computableResults: RealmResults<ComputableResult>? = null private val managedComputableResults: RealmResults<ComputableResult>? = null
@Ignore @Ignore
val computableResult: ComputableResult? = this.computableResults?.firstOrNull() val managedComputableResult: ComputableResult? = this.managedComputableResults?.firstOrNull()
@Ignore
var inverseComputableResult: WeakReference<ComputableResult>? = null
// @Ignore
fun computableResult() : ComputableResult? {
return this.inverseComputableResult?.get()
}
// Timed interface // Timed interface
@ -488,22 +494,29 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
*/ */
fun computeStats() { fun computeStats() {
val realm = Realm.getDefaultInstance()
val currentComputableResult = realm.computableResult(this)
// ComputableResult are created only when a session is over // ComputableResult are created only when a session is over
if (this.startDate != null && this.endDate != null && this.computableResults?.size == 0) { if (this.startDate != null && this.endDate != null && currentComputableResult == null && this.inverseComputableResult?.get() == null) {
val computableResult = realm.createObject(ComputableResult::class.java) val computableResult = ComputableResult()
computableResult.session = this computableResult.session = this
this.inverseComputableResult = WeakReference(computableResult)
} // if a ComputableResult exists and the session is not completed, delete it } // 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) { else if ((this.startDate == null || this.endDate == null) && currentComputableResult != null && currentComputableResult.isValid) {
this.computableResult.deleteFromRealm() currentComputableResult.deleteFromRealm()
} }
realm.close()
this.computableResult()?.updateWith(this)
// Update the ComputableResult // Update the ComputableResult
this.computableResults?.forEachIndexed { index, computableResult -> // this.computableResult()?.forEachIndexed { index, computableResult ->
computableResult.updateWith(this) // computableResult.updateWith(this)
if (index > 0) { // if (index > 0) {
throw PAIllegalStateException("Session cannot have more than one computable result") // throw PAIllegalStateException("Session cannot have more than one computable result")
} // }
} // }
this.sessionSet?.computeStats() this.sessionSet?.computeStats()
} }
@ -759,7 +772,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
} }
// cleanup unnecessary related objects // cleanup unnecessary related objects
this.result?.deleteFromRealm() 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 var right: TextFormat? = null
if (!hasMainCurrencyCode) { if (!hasMainCurrencyCode) {
this.computableResult?.ratedNet?.let { ratedNet -> this.managedComputableResult?.ratedNet?.let { ratedNet ->
right = Stat.NET_RESULT.textFormat(ratedNet) right = Stat.NET_RESULT.textFormat(ratedNet)
} }
} }
@ -1105,33 +1118,6 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
this.result?.netResult = null this.result?.netResult = null
} }
/// Stakes
// fun generateStakes() {
//
// if (this.cgAnte == null && this.cgAnte == null) {
// this.cgStakes = null
// return
// }
//
// val components = arrayListOf<String>()
//
// 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<Double>()
// this.cgAnte?.let { bets.add(it) }
// bets.addAll(this.blindValues)
// this.cgBiggestBet = bets.maxOrNull()
// }
private fun cleanupBlinds(blinds: String?): String? { private fun cleanupBlinds(blinds: String?): String? {
if (blinds == null) { if (blinds == null) {

@ -61,7 +61,7 @@ open class SessionSet() : RealmObject(), Timed, Filterable {
override var netDuration: Long = 0L override var netDuration: Long = 0L
fun computeStats() { 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.estimatedHands = this.sessions?.sumOf { it.estimatedHands } ?: 0.0
this.bbNet = this.sessions?.sumOf { it.bbNet } ?: 0.0 this.bbNet = this.sessions?.sumOf { it.bbNet } ?: 0.0
this.breakDuration = this.sessions?.max("breakDuration")?.toLong() ?: 0L this.breakDuration = this.sessions?.max("breakDuration")?.toLong() ?: 0L

@ -8,7 +8,10 @@ import android.os.Bundle
import android.view.* import android.view.*
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import io.realm.Realm 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.R
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.ComputableGroup 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.filter.FiltersActivity
import net.pokeranalytics.android.ui.modules.settings.TransactionFilterActivity import net.pokeranalytics.android.ui.modules.settings.TransactionFilterActivity
import timber.log.Timber import timber.log.Timber
import java.util.*
class StatisticsFragment : FilterableFragment(), RealmAsyncListener { class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
@ -73,6 +75,7 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
addRealmChangeListener(this, UserConfig::class.java) addRealmChangeListener(this, UserConfig::class.java)
addRealmChangeListener(this, ComputableResult::class.java) addRealmChangeListener(this, ComputableResult::class.java)
addRealmChangeListener(this, Transaction::class.java) addRealmChangeListener(this, Transaction::class.java)
addRealmChangeListener(this, SessionSet::class.java)
} }
private fun initUI() { private fun initUI() {

@ -141,10 +141,10 @@ class Top10Fragment : RealmFragment(), RowRepresentableDataSource, RowRepresenta
// Sort by rated net // Sort by rated net
val sortedCashGames = cashGames.sortedByDescending { val sortedCashGames = cashGames.sortedByDescending {
it.computableResult?.ratedNet it.managedComputableResult?.ratedNet
}.toMutableList() }.toMutableList()
val sortedTournaments = tournaments.sortedByDescending { val sortedTournaments = tournaments.sortedByDescending {
it.computableResult?.ratedNet it.managedComputableResult?.ratedNet
}.toMutableList() }.toMutableList()
// Keep 10 items // Keep 10 items

@ -7,10 +7,7 @@ import android.view.ViewGroup
import io.realm.Realm import io.realm.Realm
import io.realm.RealmModel import io.realm.RealmModel
import io.realm.RealmResults import io.realm.RealmResults
import kotlinx.coroutines.Dispatchers
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import timber.log.Timber
import kotlin.coroutines.CoroutineContext
interface RealmAsyncListener { interface RealmAsyncListener {
fun asyncListenedEntityChange(realm: Realm) fun asyncListenedEntityChange(realm: Realm)
@ -67,7 +64,7 @@ open class RealmFragment : BaseFragment() {
this.changeListener = listener this.changeListener = listener
val results = this.realm.where(clazz).findAllAsync() val results = this.realm.where(clazz).findAllAsync()
results.addChangeListener { t, _ -> results.addChangeListener { t, _ ->
Timber.d("Realm changes: ${realmResults?.size}, $this") // Timber.d("Realm changes: ${realmResults?.size}, $this")
this.changeListener?.asyncListenedEntityChange(t.realm) this.changeListener?.asyncListenedEntityChange(t.realm)
} }
this.observedRealmResults.add(results) this.observedRealmResults.add(results)

@ -22,10 +22,7 @@ import net.pokeranalytics.android.model.Criteria
import net.pokeranalytics.android.model.combined import net.pokeranalytics.android.model.combined
import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.model.realm.*
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.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
@ -106,7 +103,9 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
addRealmChangeListener(this, UserConfig::class.java) addRealmChangeListener(this, UserConfig::class.java)
addRealmChangeListener(this, ComputableResult::class.java) addRealmChangeListener(this, ComputableResult::class.java)
addRealmChangeListener(this, Transaction::class.java) addRealmChangeListener(this, Transaction::class.java)
addRealmChangeListener(this, SessionSet::class.java)
} }
private var transactionFilterMenuItem: MenuItem? = null private var transactionFilterMenuItem: MenuItem? = null
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {

@ -309,6 +309,11 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
} }
getRealm().executeTransactionAsync { realm -> getRealm().executeTransactionAsync { realm ->
realm.copyToRealmOrUpdate(this.currentSession) realm.copyToRealmOrUpdate(this.currentSession)
this.currentSession.inverseComputableResult?.get()?.let { computableResult ->
realm.copyToRealmOrUpdate(computableResult)
}
} }
} }

@ -1,6 +1,8 @@
package net.pokeranalytics.android.util.extensions package net.pokeranalytics.android.util.extensions
import io.realm.* 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.Filterable
import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.Identifiable
@ -149,8 +151,20 @@ fun Realm.lookupForNameInAllTablesById(id: String): String? {
return null return null
} }
fun Realm.computableResult(session: Session): ComputableResult? {
val crs = this.where<ComputableResult>().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 { fun Realm.copySessionFromRealm(session: Session): Session {
val copy = this.copyFromRealm(session) val copy = this.copyFromRealm(session)
copy.result?.inverseSession = WeakReference(copy) copy.result?.inverseSession = WeakReference(copy)
this.computableResult(session)?.let {
val computableResult = this.copyFromRealm(it)
copy.inverseComputableResult = WeakReference(computableResult)
}
return copy return copy
} }
Loading…
Cancel
Save