From 3d8991baabfb3d0f24a069302ff9f24b7548e88c Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 30 Nov 2022 11:18:00 +0100 Subject: [PATCH] Fixes various issues with async writes --- .../android/calculus/Calculator.kt | 2 +- .../migrations/PokerAnalyticsMigration.kt | 6 +- .../android/model/realm/ComputableResult.kt | 4 +- .../android/model/realm/Result.kt | 56 +++--- .../android/model/realm/Session.kt | 170 +++++++----------- .../android/model/realm/SessionSet.kt | 2 +- .../android/model/utils/SessionSetManager.kt | 28 ++- .../android/ui/fragment/Top10Fragment.kt | 4 +- .../ui/fragment/components/RealmFragment.kt | 3 +- ...ment.kt => BottomSheetDataListFragment.kt} | 12 +- ... BottomSheetDataMultiSelectionFragment.kt} | 21 +-- .../bottomsheet/BottomSheetFragment.kt | 11 +- .../BottomSheetListGameFragment.kt | 2 +- .../BottomSheetStaticListFragment.kt | 2 - .../FeedSessionRowRepresentableAdapter.kt | 2 +- .../ui/modules/session/SessionFragment.kt | 43 ++--- .../ui/viewmodel/BottomSheetViewModel.kt | 23 ++- .../android/util/csv/PACSVDescriptor.kt | 2 + .../util/extensions/RealmExtensions.kt | 19 +- 19 files changed, 189 insertions(+), 223 deletions(-) rename app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/{BottomSheetListFragment.kt => BottomSheetDataListFragment.kt} (88%) rename app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/{BottomSheetMultiSelectionFragment.kt => BottomSheetDataMultiSelectionFragment.kt} (69%) 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 bd5f0617..ec880fbb 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.managedComputableResult?.ratedNet ?: 0.0 } + ratedNet = filteredSessions.sumOf { it.computableResult?.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/model/migrations/PokerAnalyticsMigration.kt b/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt index 6070ea18..9ed55aab 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 @@ -337,7 +337,11 @@ class PokerAnalyticsMigration : RealmMigration { // Migrate to version 15 if (currentVersion == 14) { - schema.get("ComputableResult")?.let { crs -> +// schema.get("ComputableResult")?.let { crs -> +// crs.addField("id", String::class.java).setRequired("id", true) +// crs.addPrimaryKey("id") +// } + schema.get("Result")?.let { crs -> crs.addField("id", String::class.java).setRequired("id", true) crs.addPrimaryKey("id") } 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 9e8a3313..e5415281 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 @@ -8,8 +8,8 @@ import java.util.* open class ComputableResult : RealmObject(), Filterable { - @PrimaryKey - var id = UUID.randomUUID().toString() +// @PrimaryKey +// var id = UUID.randomUUID().toString() var ratedNet: Double = 0.0 diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt index 82f7530a..facf5f5a 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt @@ -3,13 +3,13 @@ package net.pokeranalytics.android.model.realm import io.realm.RealmList import io.realm.RealmObject import io.realm.RealmResults -import io.realm.annotations.Ignore import io.realm.annotations.LinkingObjects +import io.realm.annotations.PrimaryKey import io.realm.annotations.RealmClass import net.pokeranalytics.android.exceptions.PADataModelException import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.QueryCondition -import java.lang.ref.WeakReference +import java.util.* @RealmClass open class Result : RealmObject(), Filterable { @@ -24,13 +24,17 @@ open class Result : RealmObject(), Filterable { } } + + @PrimaryKey + var id = UUID.randomUUID().toString() + /** * The buyin amount */ var buyin: Double? = null set(value) { field = value - this.computeNumberOfRebuy() +// this.computeNumberOfRebuy() this.computeNet(true) } @@ -41,9 +45,6 @@ open class Result : RealmObject(), Filterable { set(value) { field = value this.computeNet(true) - if (value != null) { - this.session().end() - } } /** @@ -53,9 +54,6 @@ open class Result : RealmObject(), Filterable { set(value) { field = value this.computeNet(false) - if (value != null) { - this.session().end() - } } /** @@ -68,10 +66,6 @@ open class Result : RealmObject(), Filterable { * Tips */ var tips: Double? = null - set(value) { - field = value - this.session().computeStats() - } // The transactions associated with the Result, impacting the result var transactions: RealmList = RealmList() @@ -89,26 +83,26 @@ open class Result : RealmObject(), Filterable { @LinkingObjects("result") private val sessions: RealmResults? = null -// @Ignore -// private fun managedSession(): Session { -// return this.sessions?.firstOrNull() ?: throw PAIllegalStateException("Unmanaged Result") -// } - - // Manually set session - @Ignore - var inverseSession: WeakReference? = null + private val managedSession: Session + get() { + return this.sessions?.firstOrNull() ?: throw PADataModelException("Unmanaged Result") + } +// // Manually set session // @Ignore - fun session() : Session { - return this.inverseSession?.get() ?: throw PADataModelException("Inverse session not set") - } +// var inverseSession: WeakReference? = null +// +//// @Ignore +// fun session() : Session { +// return this.inverseSession?.get() ?: throw PADataModelException("Inverse session not set") +// } /** * Returns 1 if the session is positive */ val isPositive: Int get() { - return if (session().isTournament()) { + return if (managedSession.isTournament()) { if ((this.cashout ?: -1.0) >= 0.0) 1 else 0 // if cashout is null we want to count a negative session } else { if (this.net >= 0.0) 1 else 0 @@ -128,7 +122,7 @@ open class Result : RealmObject(), Filterable { } else if (buyin != null || cashout != null) { useBuyin = true } else { - if (this.session().isCashGame() && !this.session().isLive) { + if (this.managedSession.isCashGame() && !this.managedSession.isLive) { useBuyin = false } } @@ -144,14 +138,14 @@ open class Result : RealmObject(), Filterable { } // Precompute results - this.session().computeStats() - this.session().sessionSet?.computeStats() +// this.managedSession.computeStats() +// this.managedSession.sessionSet?.computeStats() } // Computes the number of rebuy fun computeNumberOfRebuy() { - if (this.session().isCashGame()) { - this.session().cgBiggestBet?.let { bb -> + if (this.managedSession.isCashGame()) { + this.managedSession.cgBiggestBet?.let { bb -> if (bb > 0.0) { this.numberOfRebuy = (this.buyin ?: 0.0) / (bb * 100.0) } else { @@ -159,7 +153,7 @@ open class Result : RealmObject(), Filterable { } } } else { - this.session().tournamentEntryFee?.let { entryFee -> + this.managedSession.tournamentEntryFee?.let { entryFee -> if (entryFee > 0.0) { this.numberOfRebuy = (this.buyin ?: 0.0) / entryFee } else { 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 2a85c0a1..3ec43414 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,8 +33,11 @@ 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.* -import java.lang.ref.WeakReference +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 timber.log.Timber import java.text.DateFormat import java.text.NumberFormat import java.text.ParseException @@ -68,7 +71,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim fun newInstance(realm: Realm, isTournament: Boolean, bankroll: Bankroll? = null): Session { val session = Session() val result = Result() - result.inverseSession = WeakReference(session) +// result.inverseSession = WeakReference(session) session.result = result if (bankroll != null) { @@ -160,18 +163,10 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim var result: Result? = null @LinkingObjects("session") - private val managedComputableResults: RealmResults? = null + private val computableResults: RealmResults? = null @Ignore - val managedComputableResult: ComputableResult? = this.managedComputableResults?.firstOrNull() - - @Ignore - var inverseComputableResult: WeakReference? = null - - // @Ignore - fun computableResult() : ComputableResult? { - return this.inverseComputableResult?.get() - } + val computableResult: ComputableResult? = this.computableResults?.firstOrNull() // Timed interface @@ -225,8 +220,8 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim if (value != null && this.endDate != null && value.after(this.endDate)) { this.endDate = null } -// this.dateChanged() - this.computeStats() + this.dateChanged() +// this.computeStats() } /** @@ -245,9 +240,9 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim } this.computeNetDuration() -// this.dateChanged() + this.dateChanged() this.defineDefaultTournamentBuyinIfNecessary() - this.computeStats() +// this.computeStats() } /** @@ -257,7 +252,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim set(value) { field = value this.computeNetDuration() - this.computeStats() +// this.computeStats() } /** @@ -285,7 +280,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim set(value) { field = value this.generateStakes() - this.computeStats() +// this.computeStats() // this.updateRowRepresentation() } @@ -313,7 +308,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim set(value) { if (value > 0) { field = value - this.computeStats() +// this.computeStats() } } @@ -340,7 +335,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim set(value) { field = value this.computeStats() - this.result?.computeNumberOfRebuy() +// this.result?.computeNumberOfRebuy() } // var blinds: String? = null @@ -351,8 +346,8 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim field = value this.generateStakes() this.defineHighestBet() - this.computeStats() - this.result?.computeNumberOfRebuy() +// this.computeStats() +// this.result?.computeNumberOfRebuy() } var cgBlinds: String? = null @@ -360,8 +355,8 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim field = cleanupBlinds(value) this.generateStakes() this.defineHighestBet() - this.computeStats() - this.result?.computeNumberOfRebuy() +// this.computeStats() +// this.result?.computeNumberOfRebuy() } var cgBiggestBet: Double? = null @@ -374,7 +369,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim var tournamentEntryFee: Double? = null set(value) { field = value - this.result?.computeNumberOfRebuy() +// this.result?.computeNumberOfRebuy() } // The total number of players who participated in the tournament @@ -396,13 +391,17 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim var handsCount: Int? = null set(value) { field = value - this.computeStats() +// this.computeStats() } fun bankrollHasBeenUpdated() { this.generateStakes() } + private fun dateChanged() { + SessionSetManager.dateChange = true + } + // /** // * Manages impacts on SessionSets // * Should be called when the start / end date are changed @@ -489,35 +488,35 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim return this.result?.net ?: 0.0 } + fun preCompute() { + this.computeStats() + this.sessionSet?.computeStats() + this.result?.computeNumberOfRebuy() + } + /** * Pre-compute various statIds */ 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 && currentComputableResult == null && this.inverseComputableResult?.get() == null) { - val computableResult = ComputableResult() + if (this.startDate != null && this.endDate != null && this.computableResults?.size == 0) { + val computableResult = realm.createObject(ComputableResult::class.java) 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) && currentComputableResult != null && currentComputableResult.isValid) { - currentComputableResult.deleteFromRealm() + else if ((this.startDate == null || this.endDate == null) && this.computableResult != null && this.computableResult.isValid) { + this.computableResult.deleteFromRealm() } - realm.close() - - this.computableResult()?.updateWith(this) // Update the ComputableResult -// this.computableResult()?.forEachIndexed { index, computableResult -> -// computableResult.updateWith(this) -// if (index > 0) { -// throw PAIllegalStateException("Session cannot have more than one computable result") -// } -// } + this.computableResults?.forEachIndexed { index, computableResult -> + computableResult.updateWith(this) + if (index > 0) { + throw PAIllegalStateException("Session cannot have more than one computable result") + } + } this.sessionSet?.computeStats() + } /** @@ -707,42 +706,9 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim } fun getFormattedStakes(): String { - return this.cgStakes?.let { StakesHolder.readableStakes(it) } ?: run { NULL_TEXT } - -// -// val formattedBlinds = StakesHolder.formattedBlinds(this.cgBlinds, this.currency) -// val formattedAntes = StakesHolder.formattedAnte(this.cgAnte, this.currency) -// -// return StakesHolder.formattedStakes(formattedBlinds, formattedAntes) - -// -// -// val components = arrayListOf() -// this.formattedBlinds?.let { components.add(it) } -// this.formattedAnte?.let { components.add("($it)") } -// -// return if (components.isNotEmpty()) { -// components.joinToString(" ") -// } else { -// NULL_TEXT -// } } -// fun formatBlinds() { -// blinds = null -// if (cgBigBlind == null) return -// cgBigBlind?.let { bb -> -// val sb = cgSmallBlind ?: bb / 2.0 -// val preFormattedBlinds = "${sb.formatted}/${bb.round()}" -// println("<<<<<< bb.toCurrency(currency) : ${bb.toCurrency(currency)}") -// println("<<<<<< preFormattedBlinds : $preFormattedBlinds") -// val regex = Regex("-?\\d+(\\.\\d+)?") -// blinds = bb.toCurrency(currency).replace(regex, preFormattedBlinds) -// println("<<<<<< blinds = $blinds") -// } -// } - // LifeCycle /** @@ -772,7 +738,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim } // cleanup unnecessary related objects this.result?.deleteFromRealm() - this.computableResult()?.deleteFromRealm() + this.computableResult?.deleteFromRealm() } @@ -807,32 +773,12 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim when (row) { SessionPropertiesRow.BANKROLL -> bankroll = value as Bankroll? SessionPropertiesRow.STAKES -> if (value is Stakes) { - if (value.ante != null) { this.cgAnte = value.ante } - if (value.blinds != null) { this.cgBlinds = value.blinds } - -// cgSmallBlind = try { -// (value[0] as String? ?: "0").toDouble() -// } catch (e: Exception) { -// null -// } -// -// cgBigBlind = try { -// (value[1] as String? ?: "0").toDouble() -// } catch (e: Exception) { -// null -// } -// -// cgBigBlind?.let { -// if (cgSmallBlind == null || cgSmallBlind == 0.0) { -// cgSmallBlind = it / 2.0 -// } -// } } else if (value == null) { this.cgBlinds = null this.cgAnte = null @@ -843,15 +789,21 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim SessionPropertiesRow.BUY_IN -> { val localResult = getOrCreateResult() localResult.buyin = value as Double? -// this.updateRowRepresentation() } SessionPropertiesRow.CASHED_OUT, SessionPropertiesRow.PRIZE -> { val localResult = getOrCreateResult() localResult.cashout = value as Double? + Timber.d("localResult cashout = ${localResult.cashout}") + if (value != null) { + this.end() + } } SessionPropertiesRow.NET_RESULT -> { val localResult = getOrCreateResult() localResult.netResult = value as Double? + if (value != null) { + this.end() + } } SessionPropertiesRow.COMMENT -> comment = value as String? ?: "" SessionPropertiesRow.END_DATE -> if (value is Date?) { @@ -907,12 +859,10 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim SessionPropertiesRow.TOURNAMENT_NAME -> tournamentName = value as TournamentName? SessionPropertiesRow.TOURNAMENT_TYPE -> tournamentType = (value as TournamentType?)?.ordinal SessionPropertiesRow.TOURNAMENT_FEATURE -> { - + this.tournamentFeatures.clear() value?.let { tournamentFeatures = RealmList() - tournamentFeatures.addAll((it as ArrayList)) - } ?: run { - tournamentFeatures.removeAll(this.tournamentFeatures) + tournamentFeatures.addAll((it as List)) } } SessionPropertiesRow.HANDS_COUNT -> handsCount = (value as Double?)?.toInt() @@ -945,11 +895,11 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim private fun getOrCreateResult(): Result { return this.result ?: run { - val result = realm.createObject(Result::class.java) - result.inverseSession = WeakReference(this) - this.result = result - result - } + val result = Result() +// result.inverseSession = WeakReference(this) + this.result = result + result + } } // Stat Entry @@ -1030,7 +980,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim var right: TextFormat? = null if (!hasMainCurrencyCode) { - this.managedComputableResult?.ratedNet?.let { ratedNet -> + this.computableResult?.ratedNet?.let { ratedNet -> right = Stat.NET_RESULT.textFormat(ratedNet) } } @@ -1060,7 +1010,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim SessionPropertiesRow.BUY_IN -> this.result?.buyin?.toCurrency(currency) ?: NULL_TEXT SessionPropertiesRow.CASHED_OUT, SessionPropertiesRow.PRIZE -> this.result?.cashout?.toCurrency(currency) ?: NULL_TEXT SessionPropertiesRow.NET_RESULT -> this.result?.netResult?.toCurrency(currency) ?: NULL_TEXT - SessionPropertiesRow.COMMENT -> if (this.comment.isNotEmpty()) this.comment else NULL_TEXT + SessionPropertiesRow.COMMENT -> this.comment.ifEmpty { NULL_TEXT } SessionPropertiesRow.END_DATE -> this.endDate?.shortDateTime() ?: NULL_TEXT SessionPropertiesRow.GAME -> getFormattedGame() SessionPropertiesRow.INITIAL_BUY_IN -> tournamentEntryFee?.toCurrency(currency) ?: NULL_TEXT 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 5729e399..20025072 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.managedComputableResult?.ratedNet ?: 0.0 } ?: 0.0 + this.ratedNet = this.sessions?.sumOf { it.computableResult?.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/model/utils/SessionSetManager.kt b/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt index e3d965ff..93a42230 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt @@ -22,22 +22,30 @@ object SessionSetManager { private val sessionsToProcess = mutableSetOf() + var dateChange = false + + fun configure() {} // launch init + init { val realm = Realm.getDefaultInstance() this.sessions = realm.where(Session::class.java).findAllAsync() this.sessions.addChangeListener { sessions, changeSet -> - changeSet.insertions.forEach { index -> - sessions[index]?.let { this.sessionsToProcess.add(it) } - } - changeSet.changes.forEach { index -> - sessions[index]?.let { this.sessionsToProcess.add(it) } - } - val sessionIds = this.sessionsToProcess.map { it.id } - realm.executeTransactionAsync { asyncRealm -> - processSessions(asyncRealm, sessionIds) + if (this.dateChange) { + this.dateChange = false + changeSet.insertions.forEach { index -> + sessions[index]?.let { this.sessionsToProcess.add(it) } + } + changeSet.changes.forEach { index -> + sessions[index]?.let { this.sessionsToProcess.add(it) } + } + + val sessionIds = this.sessionsToProcess.map { it.id } + realm.executeTransactionAsync { asyncRealm -> + processSessions(asyncRealm, sessionIds) + } } } @@ -51,6 +59,8 @@ object SessionSetManager { private fun processSessions(realm: Realm, sessionIds: List) { + Timber.d("PROCESS SESSIONS") + for (sessionId in sessionIds) { realm.findById(sessionId)?.let { session -> if (session.startDate != null && session.endDate != null) { 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 a0ed866a..47934d3a 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.managedComputableResult?.ratedNet + it.computableResult?.ratedNet }.toMutableList() val sortedTournaments = tournaments.sortedByDescending { - it.managedComputableResult?.ratedNet + it.computableResult?.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 a4522964..d672139c 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 @@ -36,8 +36,7 @@ open class RealmFragment : BaseFragment() { realm = Realm.getDefaultInstance() this.observedEntities.forEach { - val realmResults = realm.where(it).findAll() - + val realmResults = realm.where(it).findAllAsync() realmResults.addChangeListener { t, _ -> this.entitiesChanged(it, t) } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDataListFragment.kt similarity index 88% rename from app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt rename to app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDataListFragment.kt index 6f955154..0764bb3c 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDataListFragment.kt @@ -13,7 +13,7 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType -open class BottomSheetListFragment : BottomSheetFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate { +open class BottomSheetDataListFragment : BottomSheetFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate { private var _binding: BottomSheetListBinding? = null private val binding get() = _binding!! @@ -62,18 +62,8 @@ open class BottomSheetListFragment : BottomSheetFragment(), LiveRowRepresentable } override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) { - this.onRowSelected(position) dismiss() -// this.viewModel.realmData?.let { -// val selectedData = it[position] -// selectedData?.let {data -> -// this.viewModel.onRowValueChanged(data) -//// this.delegate.onRowValueChanged(data, this.row) -// dismiss() -// } -// } -// super.onRowSelected(position, row, tag) } /** diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetMultiSelectionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDataMultiSelectionFragment.kt similarity index 69% rename from app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetMultiSelectionFragment.kt rename to app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDataMultiSelectionFragment.kt index 11362360..57ffac39 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetMultiSelectionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDataMultiSelectionFragment.kt @@ -2,22 +2,16 @@ package net.pokeranalytics.android.ui.fragment.components.bottomsheet import android.app.Activity import android.content.Intent -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import io.realm.RealmModel -import net.pokeranalytics.android.databinding.BottomSheetDoubleEditTextBinding -import net.pokeranalytics.android.databinding.BottomSheetListBinding import net.pokeranalytics.android.model.LiveData -import net.pokeranalytics.android.ui.modules.data.EditableDataActivity import net.pokeranalytics.android.ui.activity.components.BaseActivity +import net.pokeranalytics.android.ui.modules.data.EditableDataActivity import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType /** * Manage multiple items selection in a bottom sheet list */ -open class BottomSheetMultiSelectionFragment : BottomSheetListFragment() { +open class BottomSheetDataMultiSelectionFragment : BottomSheetDataListFragment() { override fun viewTypeForPosition(position: Int): Int { return RowViewType.TITLE_CHECK.ordinal @@ -27,11 +21,14 @@ open class BottomSheetMultiSelectionFragment : BottomSheetListFragment() { if (requestCode == REQUEST_CODE_ADD_NEW_OBJECT && resultCode == Activity.RESULT_OK && data != null) { val dataType = data.getIntExtra(EditableDataActivity.IntentKey.DATA_TYPE.keyName, 0) val primaryKey = data.getStringExtra(EditableDataActivity.IntentKey.PRIMARY_KEY.keyName) - val pokerAnalyticsActivity = activity as BaseActivity + val liveDataType = LiveData.values()[dataType] - val proxyItem: RealmModel? = liveDataType.getData(pokerAnalyticsActivity.getRealm(), primaryKey) - this.model.selectedRows.add(proxyItem as RowRepresentable) - this.refreshRow(proxyItem as RowRepresentable) + val realm = (activity as BaseActivity).getRealm() + liveDataType.getData(realm, primaryKey)?.let { proxyItem -> + val copy = realm.copyFromRealm(proxyItem) + this.model.selectedRows.add(copy as RowRepresentable) + this.refreshRow(copy as RowRepresentable) + } // dataAdapter.refreshRow(proxyItem as RowRepresentable) } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt index fd0a4d33..0950c429 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt @@ -82,11 +82,11 @@ open class BottomSheetFragment : BottomSheetDialogFragment() { private fun newInstance(bottomSheetType: BottomSheetType): BottomSheetFragment { return when (bottomSheetType) { BottomSheetType.NONE -> BottomSheetFragment() - BottomSheetType.LIST -> BottomSheetListFragment() + BottomSheetType.LIST -> BottomSheetDataListFragment() BottomSheetType.LIST_STATIC -> BottomSheetStaticListFragment() BottomSheetType.LIST_GAME -> BottomSheetListGameFragment() BottomSheetType.DOUBLE_LIST -> BottomSheetListGameFragment() - BottomSheetType.MULTI_SELECTION -> BottomSheetMultiSelectionFragment() + BottomSheetType.MULTI_SELECTION -> BottomSheetDataMultiSelectionFragment() BottomSheetType.GRID -> BottomSheetTableSizeGridFragment() BottomSheetType.EDIT_TEXT -> BottomSheetEditTextFragment() BottomSheetType.EDIT_TEXT_MULTI_LINES -> BottomSheetEditTextMultiLinesFragment() @@ -102,6 +102,7 @@ open class BottomSheetFragment : BottomSheetDialogFragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { //TODO: When dependency 'com.google.android.material:material:1.1.0' will be available in stable version, upgrade and remove that activity?.setTheme(R.style.PokerAnalyticsTheme) + _binding = FragmentBottomSheetBinding.inflate(inflater, container, false) inflateContentView(inflater, binding.root) return binding.root @@ -277,9 +278,9 @@ open class BottomSheetFragment : BottomSheetDialogFragment() { return this.model.rowRepresentableEditDescriptors } - private fun getValue(): Any? { - return this.model.getValue() - } +// private fun getValue(): Any? { +// return this.model.getValue() +// } private fun onClear() { this.delegate?.onRowValueChanged(null, this.model.row) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt index bdaf01f6..1ff4ae72 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt @@ -18,7 +18,7 @@ import net.pokeranalytics.android.ui.view.RowRepresentable * Bottom Sheet List Game Fragment * Display a list of game + chips to choose the game limit */ -class BottomSheetListGameFragment : BottomSheetListFragment() { +class BottomSheetListGameFragment : BottomSheetDataListFragment() { private var _binding: BottomSheetGameListBinding? = null private val binding get() = _binding!! diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStaticListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStaticListFragment.kt index 2f3385d4..837f7f1f 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStaticListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStaticListFragment.kt @@ -45,9 +45,7 @@ class BottomSheetStaticListFragment : BottomSheetFragment(), StaticRowRepresenta override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) { this.model.selectedRows.add(row) this.onRowValueChanged() -// this.delegate.onRowValueChanged(row, this.row) dismiss() -// super.onRowSelected(position, row, tag) } /** diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedSessionRowRepresentableAdapter.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedSessionRowRepresentableAdapter.kt index c5239c89..f4ef5479 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedSessionRowRepresentableAdapter.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedSessionRowRepresentableAdapter.kt @@ -182,7 +182,7 @@ class FeedSessionRowRepresentableAdapter( allSessions.clear() allSessions.addAll(this.pendingSessions) allSessions.addAll(this.startedSessions) - Timber.d("Update session list, total count = ${allSessions.size}") +// Timber.d("Update session list, total count = ${allSessions.size}") val headersPositions = HashMap() 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 7633994d..9f268007 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 @@ -11,7 +11,10 @@ import androidx.appcompat.content.res.AppCompatResources import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.DiffUtil -import kotlinx.coroutines.* +import io.realm.RealmModel +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager import net.pokeranalytics.android.calculus.optimalduration.CashGameOptimalDurationCalculator @@ -40,8 +43,8 @@ import net.pokeranalytics.android.util.CrashLogging import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.extensions.* import timber.log.Timber -import java.lang.Runnable import java.util.* +import kotlin.collections.ArrayList class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepresentableDataSource, ResultCaptureTypeDelegate { @@ -190,7 +193,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr val sessionRealm = realm.findById(sessionId) sessionRealm?.let { - val copy = realm.copySessionFromRealm(it) + val copy = realm.copyFromRealm(it) if (this.model.duplicate) { // duplicate session // realm.executeTransaction { @@ -307,13 +310,10 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr Toast.makeText(context, e.message, Toast.LENGTH_LONG).show() return } - getRealm().executeTransactionAsync { realm -> - realm.copyToRealmOrUpdate(this.currentSession) - - this.currentSession.inverseComputableResult?.get()?.let { computableResult -> - realm.copyToRealmOrUpdate(computableResult) - } + getRealm().executeTransactionAsync { realm -> + val session = realm.copyToRealmOrUpdate(this.currentSession) + session.preCompute() } } @@ -536,9 +536,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr val sessionId = this.currentSession.id getRealm().executeTransactionAsync { asyncRealm -> - asyncRealm.findById(sessionId)?.let { session -> - session.delete() - } + asyncRealm.findById(sessionId)?.delete() } // this.currentSession.delete() @@ -548,15 +546,18 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr activity?.finish() } - /** - * Called when the user pressed back on the parent activity - */ - override fun onBackPressed() { - super.onBackPressed() - if (!sessionHasBeenUserCustomized) { - currentSession.delete() - } - } +// /** +// * Called when the user pressed back on the parent activity +// */ +// override fun onBackPressed() { +// super.onBackPressed() +// if (!sessionHasBeenUserCustomized) { +// val sessionId = currentSession.id +// getRealm().executeTransactionAsync { asyncRealm -> +// asyncRealm.findById(sessionId)?.delete() +// } +// } +// } //// Static Data Source diff --git a/app/src/main/java/net/pokeranalytics/android/ui/viewmodel/BottomSheetViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/viewmodel/BottomSheetViewModel.kt index 71bd8a71..db1f2051 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/viewmodel/BottomSheetViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/viewmodel/BottomSheetViewModel.kt @@ -8,11 +8,13 @@ import io.realm.RealmResults import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException import net.pokeranalytics.android.model.Stakes +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.rows.SessionPropertiesRow +import net.pokeranalytics.android.util.extensions.findById import java.util.* class BottomSheetViewModelFactory(var row: RowRepresentable, var delegate: RowRepresentableDelegate): ViewModelProvider.Factory { @@ -85,7 +87,7 @@ class BottomSheetViewModel(var row: RowRepresentable) : ViewModel() { var alternativeLabels: Boolean = false /** - * Multiselection + * Multi-selection */ val selectedRows: ArrayList = ArrayList() @@ -225,12 +227,31 @@ class BottomSheetViewModel(var row: RowRepresentable) : ViewModel() { fun isSelected(row: RowRepresentable): Boolean { return this.selectedRows.contains(row) +// return when(row.bottomSheetType) { +// BottomSheetType.MULTI_SELECTION -> { +// val identifiables = this.selectedRows as List +// val ids = identifiables.map { it.id } +// val id = (row as Identifiable).id +// ids.contains(id) +// } +// else -> this.selectedRows.contains(row) +// } } fun changedValue(): Any? { return when(row.bottomSheetType) { BottomSheetType.DOUBLE_EDIT_TEXT -> arrayListOf(this.stringValue, this.secondStringValue) BottomSheetType.DOUBLE_LIST, BottomSheetType.LIST_GAME -> arrayListOf(this.someValues[0], this.someValues[1]) + BottomSheetType.MULTI_SELECTION -> { + this.realmData?.realm?.let { realm -> + val identifiables = this.selectedRows as List + identifiables.firstOrNull()?.realmObjectClass?.let { clazz -> + val ids = identifiables.map { it.id } + val objects = ids.mapNotNull { realm.findById(clazz, it) } + objects.map { realm.copyFromRealm(it) } + } ?: kotlin.run { this.selectedRows } + } ?: kotlin.run { this.selectedRows } + } else -> getValue() } } diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/PACSVDescriptor.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/PACSVDescriptor.kt index 856614f6..845f3ec3 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/PACSVDescriptor.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/PACSVDescriptor.kt @@ -276,6 +276,8 @@ abstract class PACSVDescriptor(source: DataSource, this.addAdditionallyCreatedIdentifiable(transaction) } + managedSession.preCompute() + return managedSession } else { Timber.d("Session already exists(count=$count): sd=$startDate, ed=$endDate, net=$net") 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 dc0d225c..c8c8eb7b 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 @@ -9,7 +9,6 @@ import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.UsageCountable import net.pokeranalytics.android.model.realm.* -import java.lang.ref.WeakReference fun Realm.count(clazz: Class) : Long { return this.where(clazz).count() @@ -159,12 +158,12 @@ fun Realm.computableResult(session: Session): ComputableResult? { 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 +//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