Put async transaction everywhere

perftest
Laurent 3 years ago
parent 4ab1f561d8
commit 621357610b
  1. 3
      app/src/androidTest/java/net/pokeranalytics/android/performanceTests/PerfsInstrumentedUnitTest.kt
  2. 9
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  3. 14
      app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt
  4. 1
      app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt
  5. 8
      app/src/main/java/net/pokeranalytics/android/model/LiveData.kt
  6. 10
      app/src/main/java/net/pokeranalytics/android/model/migrations/Patcher.kt
  7. 4
      app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt
  8. 82
      app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt
  9. 19
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  10. 8
      app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt
  11. 49
      app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt
  12. 5
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportCreationFragment.kt
  13. 19
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt
  14. 10
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt
  15. 24
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt
  16. 15
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt
  17. 16
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ComposableTableReportFragment.kt
  18. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/DataManagerFragment.kt
  19. 20
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/EditableDataFragment.kt
  20. 6
      app/src/main/java/net/pokeranalytics/android/ui/modules/datalist/DataListFragment.kt
  21. 12
      app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedFragment.kt
  22. 36
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt
  23. 3
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterViewModel.kt
  24. 11
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt
  25. 6
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersListFragment.kt
  26. 7
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/editor/EditorFragment.kt
  27. 65
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/EditorViewModel.kt
  28. 39
      app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt
  29. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/settings/DealtHandsPerHourFragment.kt
  30. 6
      app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterFragment.kt
  31. 4
      app/src/main/java/net/pokeranalytics/android/util/FakeDataManager.kt
  32. 2
      app/src/main/java/net/pokeranalytics/android/util/csv/PACSVDescriptor.kt
  33. 13
      app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt

@ -39,8 +39,7 @@ class PerfsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
Seed(app).execute(realm) Seed(app).execute(realm)
realm.commitTransaction() realm.commitTransaction()
FakeDataManager.createFakeSessions(5000) { success ->
FakeDataManager.createFakeSessions(5000) {success ->
if (success) { if (success) {

@ -7,13 +7,15 @@ import com.google.firebase.FirebaseApp
import io.realm.Realm import io.realm.Realm
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import io.realm.kotlin.where import io.realm.kotlin.where
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.calculus.ReportWhistleBlower import net.pokeranalytics.android.calculus.ReportWhistleBlower
import net.pokeranalytics.android.model.migrations.Patcher import net.pokeranalytics.android.model.migrations.Patcher
import net.pokeranalytics.android.model.migrations.PokerAnalyticsMigration import net.pokeranalytics.android.model.migrations.PokerAnalyticsMigration
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.utils.Seed import net.pokeranalytics.android.model.utils.Seed
import net.pokeranalytics.android.model.utils.SessionSetManager
import net.pokeranalytics.android.util.CrashLogging import net.pokeranalytics.android.util.CrashLogging
import net.pokeranalytics.android.util.FakeDataManager import net.pokeranalytics.android.util.FakeDataManager
import net.pokeranalytics.android.util.PokerAnalyticsLogs import net.pokeranalytics.android.util.PokerAnalyticsLogs
@ -53,7 +55,7 @@ class PokerAnalyticsApplication : Application() {
val realmConfiguration = RealmConfiguration.Builder() val realmConfiguration = RealmConfiguration.Builder()
.name(Realm.DEFAULT_REALM_NAME) .name(Realm.DEFAULT_REALM_NAME)
.schemaVersion(14) .schemaVersion(14)
.allowWritesOnUiThread(true) // .allowWritesOnUiThread(true)
.migration(PokerAnalyticsMigration()) .migration(PokerAnalyticsMigration())
.initialData(Seed(this)) .initialData(Seed(this))
.build() .build()
@ -82,6 +84,7 @@ class PokerAnalyticsApplication : Application() {
// Report // Report
this.reportWhistleBlower = ReportWhistleBlower(this.applicationContext) this.reportWhistleBlower = ReportWhistleBlower(this.applicationContext)
// SessionSetManager.configure()
// Infos // Infos
val locale = Locale.getDefault() val locale = Locale.getDefault()
@ -103,7 +106,7 @@ class PokerAnalyticsApplication : Application() {
realm.close() realm.close()
if (sessionsCount < 10) { if (sessionsCount < 10) {
GlobalScope.launch { CoroutineScope(Dispatchers.Default).launch {
FakeDataManager.createFakeSessions(500) FakeDataManager.createFakeSessions(500)
} }
} }

@ -62,12 +62,12 @@ object BankrollReportManager {
} }
// otherwise compute it // otherwise compute it
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Main).launch {
var report: BankrollReport? = null var report: BankrollReport? = null
val coroutine = async { val coroutine = CoroutineScope(Dispatchers.Default).async {
val s = Date() // val s = Date()
Timber.d(">>>>> start computing bankroll...") // Timber.d(">>>>> start computing bankroll...")
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
@ -76,9 +76,9 @@ object BankrollReportManager {
realm.close() realm.close()
val e = Date() // val e = Date()
val duration = (e.time - s.time) / 1000.0 // val duration = (e.time - s.time) / 1000.0
Timber.d(">>>>> ended in $duration seconds") // Timber.d(">>>>> ended in $duration seconds")
} }
coroutine.await() coroutine.await()

@ -11,6 +11,7 @@ class ConfigurationException(message: String) : Exception(message)
class EnumIdentifierNotFoundException(message: String) : Exception(message) class EnumIdentifierNotFoundException(message: String) : Exception(message)
class MisconfiguredSavableEnumException(message: String) : Exception(message) class MisconfiguredSavableEnumException(message: String) : Exception(message)
class PAIllegalStateException(message: String) : Exception(message) class PAIllegalStateException(message: String) : Exception(message)
class PADataModelException(message: String) : Exception(message)
sealed class PokerAnalyticsException(message: String) : Exception(message) { sealed class PokerAnalyticsException(message: String) : Exception(message) {
object FilterElementUnknownName : PokerAnalyticsException(message = "No filterElement name was found to identify the queryCondition") object FilterElementUnknownName : PokerAnalyticsException(message = "No filterElement name was found to identify the queryCondition")

@ -30,7 +30,7 @@ enum class LiveData : Localizable {
PLAYER, PLAYER,
HAND_HISTORY; HAND_HISTORY;
var subType:Int? = null var subType: Int? = null
val relatedEntity: Class<out Deletable> val relatedEntity: Class<out Deletable>
get() { get() {
@ -52,10 +52,10 @@ enum class LiveData : Localizable {
fun updateOrCreate(realm: Realm, primaryKey: String?): Deletable { fun updateOrCreate(realm: Realm, primaryKey: String?): Deletable {
val proxyItem: Deletable? = this.getData(realm, primaryKey) val proxyItem: Deletable? = this.getData(realm, primaryKey)
proxyItem?.let { return proxyItem?.let {
return realm.copyFromRealm(it) realm.copyFromRealm(it)
} ?: run { } ?: run {
return this.newEntity() this.newEntity()
} }
} }

@ -170,9 +170,9 @@ class Patcher {
private fun patchSessionSet() { private fun patchSessionSet() {
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
realm.executeTransactionAsync { realm.executeTransactionAsync { asyncRealm ->
realm.where(SessionSet::class.java).findAll().deleteAllFromRealm() asyncRealm.where(SessionSet::class.java).findAll().deleteAllFromRealm()
val sessions = realm.where(Session::class.java).isNotNull("startDate").isNotNull("endDate").findAll() val sessions = asyncRealm.where(Session::class.java).isNotNull("startDate").isNotNull("endDate").findAll()
sessions.forEach { session -> sessions.forEach { session ->
SessionSetManager.updateTimeline(session) SessionSetManager.updateTimeline(session)
} }
@ -187,8 +187,8 @@ class Patcher {
*/ */
private fun patchComputableResults() { private fun patchComputableResults() {
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
realm.executeTransactionAsync { realm.executeTransactionAsync { asyncRealm ->
val crs = realm.where(ComputableResult::class.java).findAll() val crs = asyncRealm.where(ComputableResult::class.java).findAll()
crs.forEach { cr -> crs.forEach { cr ->
cr.session?.let { cr.updateWith(it) } cr.session?.let { cr.updateWith(it) }
} }

@ -109,7 +109,7 @@ open class Filter : RealmObject(), RowRepresentable, RowUpdatable, Deletable, Us
val previousCondition = filterConditions.filter { val previousCondition = filterConditions.filter {
it.filterName == newFilterCondition.filterName && it.operator == newFilterCondition.operator it.filterName == newFilterCondition.filterName && it.operator == newFilterCondition.operator
} }
filterConditions.removeAll(previousCondition) filterConditions.removeAll(previousCondition.toSet())
filterConditions.add(newFilterCondition) filterConditions.add(newFilterCondition)
} }
} }
@ -118,7 +118,7 @@ open class Filter : RealmObject(), RowRepresentable, RowUpdatable, Deletable, Us
fun remove(filterCategoryRow: FilterCategoryRow) { fun remove(filterCategoryRow: FilterCategoryRow) {
val sections = filterCategoryRow.filterSectionRows.map { it.name } val sections = filterCategoryRow.filterSectionRows.map { it.name }
val savedSections = filterConditions.filter { sections.contains(it.sectionName) } val savedSections = filterConditions.filter { sections.contains(it.sectionName) }
this.filterConditions.removeAll(savedSections) this.filterConditions.removeAll(savedSections.toSet())
} }
fun countBy(filterCategoryRow: FilterCategoryRow): Int { fun countBy(filterCategoryRow: FilterCategoryRow): Int {

@ -6,8 +6,10 @@ import io.realm.RealmResults
import io.realm.annotations.Ignore import io.realm.annotations.Ignore
import io.realm.annotations.LinkingObjects import io.realm.annotations.LinkingObjects
import io.realm.annotations.RealmClass import io.realm.annotations.RealmClass
import net.pokeranalytics.android.exceptions.PADataModelException
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.lang.ref.WeakReference
@RealmClass @RealmClass
open class Result : RealmObject(), Filterable { open class Result : RealmObject(), Filterable {
@ -40,7 +42,7 @@ open class Result : RealmObject(), Filterable {
field = value field = value
this.computeNet(true) this.computeNet(true)
if (value != null) { if (value != null) {
this.session?.end() this.session().end()
} }
} }
@ -49,19 +51,10 @@ open class Result : RealmObject(), Filterable {
*/ */
var netResult: Double? = null var netResult: Double? = null
set(value) { set(value) {
// this.session?.bankroll?.let { bankroll ->
// if (bankroll.live) {
// throw PAIllegalStateException("Can't set net result on a live bankroll")
// }
// } ?: run {
// throw PAIllegalStateException("Session doesn't have any bankroll")
// }
field = value field = value
this.computeNet(false) this.computeNet(false)
if (value != null) { if (value != null) {
this.session?.end() this.session().end()
} }
} }
@ -77,7 +70,7 @@ open class Result : RealmObject(), Filterable {
var tips: Double? = null var tips: Double? = null
set(value) { set(value) {
field = value field = value
this.session?.computeStats() this.session().computeStats()
} }
// The transactions associated with the Result, impacting the result // The transactions associated with the Result, impacting the result
@ -96,16 +89,27 @@ open class Result : RealmObject(), Filterable {
@LinkingObjects("result") @LinkingObjects("result")
private val sessions: RealmResults<Session>? = null private val sessions: RealmResults<Session>? = null
// @Ignore
// private fun managedSession(): Session {
// return this.sessions?.firstOrNull() ?: throw PAIllegalStateException("Unmanaged Result")
// }
// Manually set session
@Ignore @Ignore
val session: Session? = this.sessions?.firstOrNull() var inverseSession: WeakReference<Session>? = null
// @Ignore
fun session() : Session {
return this.inverseSession?.get() ?: throw PADataModelException("Inverse session not set")
}
/** /**
* Returns 1 if the session is positive * Returns 1 if the session is positive
*/ */
val isPositive: Int val isPositive: Int
get() { get() {
return if (session?.isTournament() == true) { return if (session().isTournament()) {
if (this.cashout ?: -1.0 >= 0.0) 1 else 0 // if cashout is null we want to count a negative session if ((this.cashout ?: -1.0) >= 0.0) 1 else 0 // if cashout is null we want to count a negative session
} else { } else {
if (this.net >= 0.0) 1 else 0 if (this.net >= 0.0) 1 else 0
} }
@ -124,11 +128,9 @@ open class Result : RealmObject(), Filterable {
} else if (buyin != null || cashout != null) { } else if (buyin != null || cashout != null) {
useBuyin = true useBuyin = true
} else { } else {
this.session?.let { session -> if (this.session().isCashGame() && !this.session().isLive) {
if (session.isCashGame() && !session.isLive) { useBuyin = false
useBuyin = false }
}
}
} }
} }
@ -142,31 +144,29 @@ open class Result : RealmObject(), Filterable {
} }
// Precompute results // Precompute results
this.session?.computeStats() this.session().computeStats()
this.session?.sessionSet?.computeStats() this.session().sessionSet?.computeStats()
} }
// Computes the number of rebuy // Computes the number of rebuy
fun computeNumberOfRebuy() { fun computeNumberOfRebuy() {
this.session?.let { if (this.session().isCashGame()) {
if (it.isCashGame()) { this.session().cgBiggestBet?.let { bb ->
it.cgBiggestBet?.let { bb -> if (bb > 0.0) {
if (bb > 0.0) { this.numberOfRebuy = (this.buyin ?: 0.0) / (bb * 100.0)
this.numberOfRebuy = (this.buyin ?: 0.0) / (bb * 100.0) } else {
} else { this.numberOfRebuy = null
this.numberOfRebuy = null }
} }
} } else {
} else { this.session().tournamentEntryFee?.let { entryFee ->
it.tournamentEntryFee?.let { entryFee -> if (entryFee > 0.0) {
if (entryFee > 0.0) { this.numberOfRebuy = (this.buyin ?: 0.0) / entryFee
this.numberOfRebuy = (this.buyin ?: 0.0) / entryFee } else {
} else { this.numberOfRebuy = null
this.numberOfRebuy = null }
} }
} }
}
}
} }
// @todo tips? // @todo tips?

@ -37,6 +37,7 @@ import net.pokeranalytics.android.util.extensions.hourMinute
import net.pokeranalytics.android.util.extensions.shortDateTime import net.pokeranalytics.android.util.extensions.shortDateTime
import net.pokeranalytics.android.util.extensions.toCurrency import net.pokeranalytics.android.util.extensions.toCurrency
import net.pokeranalytics.android.util.extensions.toMinutes import net.pokeranalytics.android.util.extensions.toMinutes
import java.lang.ref.WeakReference
import java.text.DateFormat import java.text.DateFormat
import java.text.NumberFormat import java.text.NumberFormat
import java.text.ParseException import java.text.ParseException
@ -67,18 +68,27 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
companion object { companion object {
fun newInstance(realm: Realm, isTournament: Boolean, bankroll: Bankroll? = null, managed: Boolean = true): Session { fun newInstance(realm: Realm, isTournament: Boolean, bankroll: Bankroll? = null): Session {
val session = Session() val session = Session()
session.result = Result() val result = Result()
result.inverseSession = WeakReference(session)
session.result = result
if (bankroll != null) { if (bankroll != null) {
session.bankroll = bankroll session.bankroll = bankroll
} else { } else {
session.bankroll = realm.where<Bankroll>().findFirst() realm.where<Bankroll>().findFirst()?.let { br ->
session.bankroll = realm.copyFromRealm(br)
}
} }
session.type = if (isTournament) Type.TOURNAMENT.ordinal else Type.CASH_GAME.ordinal session.type = if (isTournament) Type.TOURNAMENT.ordinal else Type.CASH_GAME.ordinal
session.limit = Limit.NO.ordinal session.limit = Limit.NO.ordinal
session.game = realm.where(Game::class.java).equalTo("shortName", "HE").findFirst()
realm.where(Game::class.java)
.equalTo("shortName", "HE").findFirst()?.let {
session.game = it
}
return session return session
// return if (managed) { // return if (managed) {
@ -923,6 +933,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
return this.result return this.result
?: run { ?: run {
val result = realm.createObject(Result::class.java) val result = realm.createObject(Result::class.java)
result.inverseSession = WeakReference(this)
this.result = result this.result = result
result result
} }

@ -100,10 +100,10 @@ open class SessionSet() : RealmObject(), Timed, Filterable {
companion object { companion object {
// fun newInstance(realm: Realm) : SessionSet { fun newInstance(realm: Realm) : SessionSet {
// val sessionSet = SessionSet() val sessionSet = SessionSet()
// return realm.copyToRealm(sessionSet) return realm.copyToRealm(sessionSet)
// } }
fun fieldNameForQueryType(queryCondition: Class < out QueryCondition >): String? { fun fieldNameForQueryType(queryCondition: Class < out QueryCondition >): String? {
Session.fieldNameForQueryType(queryCondition)?.let { Session.fieldNameForQueryType(queryCondition)?.let {

@ -6,6 +6,8 @@ import io.realm.RealmResults
import net.pokeranalytics.android.exceptions.ModelException import net.pokeranalytics.android.exceptions.ModelException
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet import net.pokeranalytics.android.model.realm.SessionSet
import net.pokeranalytics.android.util.extensions.findById
import timber.log.Timber
import kotlin.math.max import kotlin.math.max
class CorruptSessionSetException(message: String) : Exception(message) class CorruptSessionSetException(message: String) : Exception(message)
@ -24,7 +26,7 @@ object SessionSetManager {
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
this.sessions = realm.where(Session::class.java).findAll() this.sessions = realm.where(Session::class.java).findAllAsync()
this.sessions.addChangeListener { sessions, changeSet -> this.sessions.addChangeListener { sessions, changeSet ->
changeSet.insertions.forEach { index -> changeSet.insertions.forEach { index ->
sessions[index]?.let { this.sessionsToProcess.add(it) } sessions[index]?.let { this.sessionsToProcess.add(it) }
@ -33,7 +35,11 @@ object SessionSetManager {
sessions[index]?.let { this.sessionsToProcess.add(it) } sessions[index]?.let { this.sessionsToProcess.add(it) }
} }
processSessions() val sessionIds = this.sessionsToProcess.map { it.id }
realm.executeTransactionAsync { asyncRealm ->
processSessions(asyncRealm, sessionIds)
}
} }
realm.close() realm.close()
@ -43,14 +49,25 @@ object SessionSetManager {
// this.sessionsToProcess.add(session) // this.sessionsToProcess.add(session)
// } // }
private fun processSessions() { private fun processSessions(realm: Realm, sessionIds: List<String>) {
for (session in this.sessionsToProcess) {
if (session.startDate != null && session.endDate != null) { for (sessionId in sessionIds) {
this.updateTimeline(session) realm.findById<Session>(sessionId)?.let { session ->
} else if (session.sessionSet != null) { if (session.startDate != null && session.endDate != null) {
removeFromTimeline(session) updateTimeline(session)
} else if (session.sessionSet != null) {
removeFromTimeline(session)
}
} }
} }
// for (session in this.sessionsToProcess) {
// if (session.startDate != null && session.endDate != null) {
// this.updateTimeline(realm, session)
// } else if (session.sessionSet != null) {
// removeFromTimeline(realm, session)
// }
// }
this.sessionsToProcess.clear() this.sessionsToProcess.clear()
} }
@ -59,6 +76,8 @@ object SessionSetManager {
*/ */
fun updateTimeline(session: Session) { fun updateTimeline(session: Session) {
Timber.d("updateTimeline")
// if (!session.realm.isInTransaction) { // if (!session.realm.isInTransaction) {
// throw PAIllegalStateException("realm should be in transaction at this point") // throw PAIllegalStateException("realm should be in transaction at this point")
// } // }
@ -73,6 +92,14 @@ object SessionSetManager {
val sessionSets = this.matchingSets(session) val sessionSets = this.matchingSets(session)
cleanupSessionSets(session, sessionSets) cleanupSessionSets(session, sessionSets)
// val sessionId = session.id
// realm.executeTransactionAsync { asyncRealm ->
// asyncRealm.findById<Session>(sessionId)?.let { s ->
// val sessionSets = this.matchingSets(session)
// cleanupSessionSets(session, sessionSets)
// }
// }
} }
private fun matchingSets(session: Session): RealmResults<SessionSet> { private fun matchingSets(session: Session): RealmResults<SessionSet> {
@ -125,12 +152,10 @@ object SessionSetManager {
* Update the global timeline using the impacted [sessionSets] and the updated [session] * Update the global timeline using the impacted [sessionSets] and the updated [session]
*/ */
private fun updateTimeFrames(sessionSets: RealmResults<SessionSet>, session: Session) { private fun updateTimeFrames(sessionSets: RealmResults<SessionSet>, session: Session) {
when (sessionSets.size) { when (sessionSets.size) {
0 -> this.createOrUpdateSessionSet(session) 0 -> this.createOrUpdateSessionSet(session)
else -> this.mergeSessionGroups(session, sessionSets) else -> this.mergeSessionGroups(session, sessionSets)
} }
} }
/** /**
@ -152,7 +177,7 @@ object SessionSetManager {
* Create a set and affect it to the [session] * Create a set and affect it to the [session]
*/ */
private fun createSessionSet(session: Session) { private fun createSessionSet(session: Session) {
val set = SessionSet() //.newInstance(session.realm) val set = SessionSet.newInstance(session.realm)
set.startDate = session.startDate!! set.startDate = session.startDate!!
set.endDate = session.endDate!! set.endDate = session.endDate!!
set.breakDuration = session.breakDuration set.breakDuration = session.breakDuration
@ -196,7 +221,7 @@ object SessionSetManager {
sessionSets.deleteAllFromRealm() sessionSets.deleteAllFromRealm()
// Create a new set // Create a new set
val set = SessionSet() //.newInstance(session.realm) val set = SessionSet.newInstance(session.realm)
set.startDate = startDate set.startDate = startDate
set.endDate = endDate set.endDate = endDate

@ -118,11 +118,6 @@ class ReportCreationFragment : RealmFragment(), RowRepresentableDataSource, RowR
if (this.assistant.step == Assistant.Step.FINALIZE) { if (this.assistant.step == Assistant.Step.FINALIZE) {
// getRealm().executeTransaction {
// val rs = this.assistant.options.reportSetup("test")
// it.insert(rs)
// }
// launch report // launch report
this.finishActivityWithOptions(this.assistant.options, this.assistant.reportDisplay) this.finishActivityWithOptions(this.assistant.options, this.assistant.reportDisplay)

@ -11,13 +11,11 @@ import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.Realm import io.realm.Realm
import io.realm.RealmResults import io.realm.RealmResults
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
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.NewPerformanceListener import net.pokeranalytics.android.calculus.NewPerformanceListener
import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.calculus.calcul.ReportDisplay import net.pokeranalytics.android.calculus.calcul.ReportDisplay
import net.pokeranalytics.android.databinding.FragmentReportsBinding import net.pokeranalytics.android.databinding.FragmentReportsBinding
@ -60,10 +58,7 @@ data class ReportSection(val report: StaticReport, var performances: MutableList
} }
data class PerformanceRow(val performance: Performance, val report: StaticReport): RowRepresentable { data class PerformanceRow(val performance: Performance, val report: StaticReport): RowRepresentable {
override val resId: Int? = this.performance.resId override val resId: Int? = this.performance.resId
override val viewType: Int = RowViewType.TITLE_BADGE_VALUE.identifier override val viewType: Int = RowViewType.TITLE_BADGE_VALUE.identifier
} }
@ -71,6 +66,7 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc
private lateinit var reportSetups: RealmResults<ReportSetup> private lateinit var reportSetups: RealmResults<ReportSetup>
private lateinit var performances: RealmResults<Performance> private lateinit var performances: RealmResults<Performance>
private var adapterRows = mutableListOf<RowRepresentable>() private var adapterRows = mutableListOf<RowRepresentable>()
override fun deletableItems(): List<Deletable> { override fun deletableItems(): List<Deletable> {
@ -152,12 +148,12 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc
* Init data * Init data
*/ */
private fun initData() { private fun initData() {
this.reportSetups = getRealm().where(ReportSetup::class.java).findAll().sort("name") this.reportSetups = getRealm().where(ReportSetup::class.java).findAllAsync().sort("name")
this.reportSetups.addChangeListener { _, _ -> this.reportSetups.addChangeListener { _, _ ->
this.updateRows() this.updateRows()
} }
this.performances = getRealm().where(Performance::class.java).findAll() this.performances = getRealm().where(Performance::class.java).findAllAsync()
this.performances.addChangeListener { _, _ -> this.performances.addChangeListener { _, _ ->
this.updateRows() this.updateRows()
} }
@ -315,15 +311,12 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
val startDate = Date()
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
realm.refresh() realm.refresh()
val report = Calculator.computeStats(realm, options = options) val report = Calculator.computeStats(realm, options = options)
// Timber.d("launchComputation: ${System.currentTimeMillis() - startDate.time}ms") CoroutineScope(Dispatchers.Main).launch {
launch(Dispatchers.Main) {
if (!isDetached) { if (!isDetached) {
hideLoader() hideLoader()
ReportActivity.newInstanceForResult(this@ReportsFragment, report, reportDisplay, reportName) ReportActivity.newInstanceForResult(this@ReportsFragment, report, reportDisplay, reportName)

@ -159,8 +159,8 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
val async = async { val async = async {
val s = Date() // val s = Date()
Timber.d(">>> start...") // Timber.d(">>> start...")
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
realm.refresh() realm.refresh()
@ -170,9 +170,9 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
realm.close() realm.close()
val e = Date() // val e = Date()
val duration = (e.time - s.time) / 1000.0 // val duration = (e.time - s.time) / 1000.0
Timber.d(">>> ended in $duration seconds") // Timber.d(">>> ended in $duration seconds")
} }
async.await() async.await()

@ -8,15 +8,13 @@ import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import io.realm.RealmObject import io.realm.RealmObject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.interfaces.Deletable import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.ui.modules.datalist.DataListActivity import net.pokeranalytics.android.ui.modules.datalist.DataListActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.util.extensions.findById
/** /**
* Deletable Item Fragment * Deletable Item Fragment
@ -56,7 +54,7 @@ abstract class DeletableItemFragment : RealmFragment() {
val itemToDeleteId = data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName) val itemToDeleteId = data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName)
itemToDeleteId?.let { id -> itemToDeleteId?.let { id ->
GlobalScope.launch(Dispatchers.Main) { CoroutineScope(Dispatchers.Main).launch {
delay(300) delay(300)
deleteItem(dataListAdapter, deletableItems(), id) deleteItem(dataListAdapter, deletableItems(), id)
} }
@ -84,14 +82,21 @@ abstract class DeletableItemFragment : RealmFragment() {
if (itemToDelete is RealmObject && itemPosition != -1) { if (itemToDelete is RealmObject && itemPosition != -1) {
val itemClass = itemToDelete.realmObjectClass
// Check if the object is valid for the deletion // Check if the object is valid for the deletion
if (itemToDelete.isValidForDelete(this.getRealm())) { if (itemToDelete.isValidForDelete(this.getRealm())) {
deletedItem = getRealm().copyFromRealm(itemToDelete) deletedItem = getRealm().copyFromRealm(itemToDelete)
lastDeletedItemPosition = itemPosition lastDeletedItemPosition = itemPosition
getRealm().executeTransaction {
itemToDelete.deleteDependencies(it) getRealm().executeTransactionAsync { asyncRealm ->
itemToDelete.deleteFromRealm() val item = asyncRealm.findById(itemClass, itemId) as? Deletable
item?.let {
item.deleteDependencies(asyncRealm)
(item as RealmObject).deleteFromRealm()
}
} }
itemHasBeenReInserted = false itemHasBeenReInserted = false
updateUIAfterDeletion(itemId, itemPosition) updateUIAfterDeletion(itemId, itemPosition)
showUndoSnackBar() showUndoSnackBar()
@ -117,7 +122,8 @@ abstract class DeletableItemFragment : RealmFragment() {
snackBar?.setAction(R.string.cancel) { snackBar?.setAction(R.string.cancel) {
if (!itemHasBeenReInserted) { if (!itemHasBeenReInserted) {
itemHasBeenReInserted = true itemHasBeenReInserted = true
getRealm().executeTransaction { realm ->
getRealm().executeTransactionAsync { realm ->
deletedItem?.let { deletedItem?.let {
val item = realm.copyToRealmOrUpdate(it) val item = realm.copyToRealmOrUpdate(it)
updateUIAfterUndoDeletion(item) updateUIAfterUndoDeletion(item)

@ -121,9 +121,12 @@ abstract class AbstractReportFragment : DataManagerFragment() {
this.reportViewModel.title = name this.reportViewModel.title = name
val rs = this.model.item as ReportSetup val rs = this.model.item as ReportSetup
getRealm().executeTransaction { realm -> val setupId = rs.id
val firstSave = (this.model.primaryKey == null)
getRealm().executeTransactionAsync { realm ->
val firstSave = (this.model.primaryKey == null)
if (firstSave) { if (firstSave) {
val options = this.selectedReport.options val options = this.selectedReport.options
rs.name = name rs.name = name
@ -143,13 +146,15 @@ abstract class AbstractReportFragment : DataManagerFragment() {
} }
realm.copyToRealmOrUpdate(rs) realm.copyToRealmOrUpdate(rs)
} else { } else {
rs.name = name realm.findById<ReportSetup>(setupId)?.let { reportSetup ->
realm.insertOrUpdate(rs) reportSetup.name = name
realm.insertOrUpdate(reportSetup)
}
} }
} }
this.model.primaryKey = rs.id this.model.primaryKey = setupId
this.deleteButtonShouldAppear = true this.deleteButtonShouldAppear = true
setToolbarTitle(this.reportViewModel.title) setToolbarTitle(this.reportViewModel.title)
} }

@ -9,11 +9,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.Realm import io.realm.Realm
import kotlinx.coroutines.* import kotlinx.coroutines.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.calcul.ReportDisplay
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.ComputableGroup import net.pokeranalytics.android.calculus.ComputableGroup
import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.calculus.calcul.ReportDisplay
import net.pokeranalytics.android.databinding.FragmentComposableTableReportBinding import net.pokeranalytics.android.databinding.FragmentComposableTableReportBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.ui.activity.components.ReportActivity import net.pokeranalytics.android.ui.activity.components.ReportActivity
@ -27,8 +27,6 @@ import net.pokeranalytics.android.ui.view.rows.CustomizableRowRepresentable
import net.pokeranalytics.android.ui.view.rows.StatRow import net.pokeranalytics.android.ui.view.rows.StatRow
import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.TextFormat import net.pokeranalytics.android.util.TextFormat
import timber.log.Timber
import java.util.*
open class ComposableTableReportFragment : RealmFragment(), StaticRowRepresentableDataSource, open class ComposableTableReportFragment : RealmFragment(), StaticRowRepresentableDataSource,
RowRepresentableDelegate { RowRepresentableDelegate {
@ -208,9 +206,9 @@ open class ComposableTableReportFragment : RealmFragment(), StaticRowRepresentab
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
var report: Report? = null var report: Report? = null
val test = GlobalScope.async { val test = async {
val s = Date() // val s = Date()
Timber.d(">>> start...") // Timber.d(">>> start...")
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
realm.refresh() realm.refresh()
@ -221,9 +219,9 @@ open class ComposableTableReportFragment : RealmFragment(), StaticRowRepresentab
realm.close() realm.close()
val e = Date() // val e = Date()
val duration = (e.time - s.time) / 1000.0 // val duration = (e.time - s.time) / 1000.0
Timber.d(">>> ended in $duration seconds") // Timber.d(">>> ended in $duration seconds")
} }
test.await() test.await()

@ -96,7 +96,7 @@ open class DataManagerFragment : RealmFragment() {
val status = savable.getSaveValidityStatus(realm = this.getRealm()) val status = savable.getSaveValidityStatus(realm = this.getRealm())
when (status) { when (status) {
SaveValidityStatus.VALID -> { SaveValidityStatus.VALID -> {
this.getRealm().executeTransaction { this.getRealm().executeTransactionAsync {
val managedItem = it.copyToRealmOrUpdate(this.model.item) val managedItem = it.copyToRealmOrUpdate(this.model.item)
if (managedItem is Savable) { if (managedItem is Savable) {
val uniqueIdentifier = managedItem.id val uniqueIdentifier = managedItem.id

@ -18,7 +18,6 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowUpdatable import net.pokeranalytics.android.ui.view.RowUpdatable
open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegate { open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegate {
lateinit var rowRepresentableAdapter: RowRepresentableAdapter lateinit var rowRepresentableAdapter: RowRepresentableAdapter
@ -67,15 +66,20 @@ open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegat
} }
override fun onRowValueChanged(value: Any?, row: RowRepresentable) { override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
getRealm().executeTransaction {
try {
(this.model.item as RowUpdatable).updateValue(value, row)
} catch (e: Exception) {
CrashLogging.log("Exception caught: row = $row, value=$value, class=${this.javaClass}")
throw e
}
(this.model.item as RowUpdatable).updateValue(value, row)
if (this.model.primaryKey != null) {
getRealm().executeTransactionAsync { asyncRealm ->
try {
asyncRealm.copyToRealmOrUpdate(this.model.item)
} catch (e: Exception) {
CrashLogging.log("Exception caught: row = $row, value=$value, class=${this.javaClass}")
throw e
}
}
} }
rowRepresentableAdapter.refreshRow(row) rowRepresentableAdapter.refreshRow(row)
} }

@ -81,10 +81,14 @@ open class DataListFragment : DeletableItemFragment(), RowRepresentableDelegate
getRealm().where(this.model.identifiableClass) getRealm().where(this.model.identifiableClass)
.`in`("id", itemIds) .`in`("id", itemIds)
.sort(this.model.dataType.sortFields, this.model.dataType.sortOrders) .sort(this.model.dataType.sortFields, this.model.dataType.sortOrders)
.findAll() .findAllAsync()
} else { } else {
this.retrieveItems(getRealm()) this.retrieveItems(getRealm())
} }
items.addChangeListener { _, _ ->
this.dataListAdapter.notifyDataSetChanged()
}
this.model.setItemsList(items) this.model.setItemsList(items)
} }

@ -44,6 +44,7 @@ import net.pokeranalytics.android.util.URL
import net.pokeranalytics.android.util.billing.AppGuard import net.pokeranalytics.android.util.billing.AppGuard
import net.pokeranalytics.android.util.billing.PurchaseListener import net.pokeranalytics.android.util.billing.PurchaseListener
import net.pokeranalytics.android.util.extensions.count import net.pokeranalytics.android.util.extensions.count
import net.pokeranalytics.android.util.extensions.findById
import java.util.* import java.util.*
class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseListener { class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseListener {
@ -493,9 +494,16 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
* Delete selected transaction * Delete selected transaction
*/ */
private fun deleteSelectedTransaction() { private fun deleteSelectedTransaction() {
getRealm().executeTransaction {
selectedTransaction?.deleteFromRealm() selectedTransaction?.id?.let { id ->
getRealm().executeTransactionAsync { asyncRealm ->
asyncRealm.findById<Transaction>(id)?.deleteFromRealm()
}
} }
// getRealm().executeTransaction {
// selectedTransaction?.deleteFromRealm()
// }
selectedTransactionPosition = -1 selectedTransactionPosition = -1
} }

@ -10,6 +10,7 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentFilterDetailsBinding import net.pokeranalytics.android.databinding.FragmentFilterDetailsBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.realm.Filter
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.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.RealmFragment
@ -17,6 +18,7 @@ import net.pokeranalytics.android.ui.helpers.DateTimePickerManager
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rows.* import net.pokeranalytics.android.ui.view.rows.*
import net.pokeranalytics.android.util.extensions.findById
import timber.log.Timber import timber.log.Timber
import java.util.* import java.util.*
@ -230,27 +232,33 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate {
*/ */
private fun saveData() { private fun saveData() {
val currentFilter = this.activityModel.currentFilter // val currentFilter = this.activityModel.currentFilter
//TODO: Save currentFilter details data this.activityModel.currentFilter?.id?.let { filterId ->
Timber.d("Save data for queryWith: ${currentFilter?.id}")
this.model.selectedRows.forEach {
Timber.d("Selected rows: $it")
}
this.activityModel.selectedCategoryRow?.let { category -> this.activityModel.selectedCategoryRow?.let { category ->
getRealm().executeTransaction { getRealm().executeTransactionAsync { asyncRealm ->
currentFilter?.remove(category) asyncRealm.findById<Filter>(filterId)?.let { filter ->
val validConditions = this.model.selectedRows.filter { it.queryCondition != null } filter.remove(category)
currentFilter?.createOrUpdateFilterConditions(validConditions) val validConditions = this.model.selectedRows.filter { it.queryCondition != null }
filter.createOrUpdateFilterConditions(validConditions)
}
}
} }
}
currentFilter?.filterConditions?.forEach {
Timber.d("Condition: $it")
} }
// //TODO: Save currentFilter details data
// Timber.d("Save data for queryWith: ${currentFilter?.id}")
// this.model.selectedRows.forEach {
// Timber.d("Selected rows: $it")
// }
// currentFilter?.filterConditions?.forEach {
// Timber.d("Condition: $it")
// }
// finishActivityWithResult(currentFilter?.id) // finishActivityWithResult(currentFilter?.id)
} }

@ -32,7 +32,6 @@ class FilterViewModel : ViewModel(), StaticRowRepresentableDataSource {
} }
this.primaryKey?.let { this.primaryKey?.let {
val filter = realm.findById<Filter>(it) ?: throw PAIllegalStateException("Can't find filter with id=$it") val filter = realm.findById<Filter>(it) ?: throw PAIllegalStateException("Can't find filter with id=$it")
this.currentFilter = realm.copyFromRealm(filter) this.currentFilter = realm.copyFromRealm(filter)
this.isUpdating = true this.isUpdating = true
@ -59,7 +58,7 @@ class FilterViewModel : ViewModel(), StaticRowRepresentableDataSource {
// Data source // Data source
override fun adapterRows(): List<RowRepresentable>? { override fun adapterRows(): List<RowRepresentable> {
return this.categoryRows return this.categoryRows
} }

@ -15,7 +15,6 @@ import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.model.realm.Filter
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.extensions.px
import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.rows.FilterCategoryRow import net.pokeranalytics.android.ui.view.rows.FilterCategoryRow
@ -220,10 +219,10 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
private fun validateUpdates() { private fun validateUpdates() {
val currentFilter = this.model.currentFilter val currentFilter = this.model.currentFilter
getRealm().executeTransaction { realm -> getRealm().executeTransactionAsync { realm ->
currentFilter?.let { currentFilter?.let { filter ->
it.name = it.query.getName(requireContext()) filter.name = filter.query.getName(requireContext())
realm.copyToRealmOrUpdate(it) realm.copyToRealmOrUpdate(filter)
} }
} }
@ -239,7 +238,7 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
val filterCopy = this.model.filterCopy val filterCopy = this.model.filterCopy
val filterId = filterCopy?.id ?: "" val filterId = filterCopy?.id ?: ""
getRealm().executeTransaction { realm -> getRealm().executeTransactionAsync { realm ->
filterCopy?.let { filterCopy?.let {
realm.copyToRealmOrUpdate(it) realm.copyToRealmOrUpdate(it)
} }

@ -15,8 +15,10 @@ open class FiltersListFragment : DataListFragment() {
override fun onRowValueChanged(value: Any?, row: RowRepresentable) { override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
when (row) { when (row) {
is Filter -> { is Filter -> {
getRealm().executeTransaction {
row.updateValue(value, row) row.updateValue(value, row)
getRealm().executeTransactionAsync { asyncRealm ->
asyncRealm.copyToRealmOrUpdate(row)
} }
val index = this.model.items.indexOf(row) val index = this.model.items.indexOf(row)
this.dataListAdapter.notifyItemChanged(index) this.dataListAdapter.notifyItemChanged(index)

@ -687,10 +687,9 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
*/ */
private fun deleteHand() { private fun deleteHand() {
getRealm().findById<HandHistory>(this.model.handHistory.id)?.let { hh -> val hhId = this.model.handHistory.id
getRealm().executeTransaction { getRealm().executeTransactionAsync { asyncRealm ->
hh.deleteFromRealm() asyncRealm.findById<HandHistory>(hhId)?.deleteFromRealm()
}
} }
this.activity?.finish() this.activity?.finish()

@ -24,12 +24,10 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.rows.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rows.CustomizableRowRepresentable
import net.pokeranalytics.android.util.CrashLogging import net.pokeranalytics.android.util.CrashLogging
import net.pokeranalytics.android.util.extensions.findById
import net.pokeranalytics.android.util.extensions.formatted import net.pokeranalytics.android.util.extensions.formatted
import timber.log.Timber import timber.log.Timber
import java.text.DecimalFormat import java.text.DecimalFormat
import java.text.ParseException import java.text.ParseException
import kotlin.coroutines.CoroutineContext
import kotlin.reflect.KClass import kotlin.reflect.KClass
enum class HHKeyboard { enum class HHKeyboard {
@ -640,25 +638,26 @@ class EditorViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer
this.handHistory.actions.addAll(actions) this.handHistory.actions.addAll(actions)
realm.executeTransactionAsync { execRealm -> realm.executeTransactionAsync { execRealm ->
this.handHistory.defineWinnerPositions()
execRealm.copyToRealmOrUpdate(this.handHistory) execRealm.copyToRealmOrUpdate(this.handHistory)
} }
this.defineWinnerPositions() // this.defineWinnerPositions()
} }
private fun defineWinnerPositions() { // private fun defineWinnerPositions() {
//
val hhId = this.handHistory.id // val hhId = this.handHistory.id
CoroutineScope(Dispatchers.Default).launch { // CoroutineScope(Dispatchers.Default).launch {
val realm = Realm.getDefaultInstance() // val realm = Realm.getDefaultInstance()
//
realm.findById<HandHistory>(hhId)?.defineWinnerPositions() // realm.findById<HandHistory>(hhId)?.defineWinnerPositions()
realm.executeTransactionAsync { execRealm -> // realm.executeTransactionAsync { execRealm ->
execRealm.copyToRealmOrUpdate(handHistory) // execRealm.copyToRealmOrUpdate(handHistory)
} // }
realm.close() // realm.close()
} // }
//
} // }
// Card Centralizer // Card Centralizer
@ -1027,20 +1026,20 @@ class EditorViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer
/*** /***
* Tries to deletes the row at the given [position] * Tries to deletes the row at the given [position]
*/ */
fun deleteIfPossible(position: Int) { // fun deleteIfPossible(position: Int) {
when (val row = this.rowRepresentables[position]) { // when (val row = this.rowRepresentables[position]) {
is PlayerSetupRow -> { // is PlayerSetupRow -> {
val playerSetup = this.handHistory.playerSetupForPosition(row.positionIndex) ?: throw PAIllegalStateException("Attempt to delete an null object") // val playerSetup = this.handHistory.playerSetupForPosition(row.positionIndex) ?: throw PAIllegalStateException("Attempt to delete an null object")
this.handHistory.playerSetups.remove(playerSetup) // this.handHistory.playerSetups.remove(playerSetup)
//
this.handHistory.realm?.let { // this.handHistory.realm?.let {
it.executeTransaction { // it.executeTransaction {
playerSetup.deleteFromRealm() // playerSetup.deleteFromRealm()
} // }
} // }
} // }
} // }
} // }
fun removePlayerSetup(positionIndex: Int) { fun removePlayerSetup(positionIndex: Int) {
val ps = this.handHistory.playerSetupForPosition(positionIndex) val ps = this.handHistory.playerSetupForPosition(positionIndex)

@ -177,7 +177,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
val sessionRealm = realm.findById<Session>(sessionId) val sessionRealm = realm.findById<Session>(sessionId)
sessionRealm?.let { sessionRealm?.let {
val copy = realm.copyFromRealm(it) val copy = realm.copySessionFromRealm(it)
if (this.model.duplicate) { // duplicate session if (this.model.duplicate) { // duplicate session
// realm.executeTransaction { // realm.executeTransaction {
@ -192,21 +192,6 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
} ?: throw PAIllegalStateException("Session cannot be null here, session id = $sessionId") } ?: throw PAIllegalStateException("Session cannot be null here, session id = $sessionId")
// if (sessionRealm != null) {
//
// if (this.model.duplicate) { // duplicate session
// realm.executeTransaction {
// val session = sessionRealm.duplicate()
// currentSession = session
// }
// sessionHasBeenUserCustomized = false
// } else { // show existing session
// currentSession = sessionRealm
// sessionHasBeenUserCustomized = true
// }
// } else {
// throw PAIllegalStateException("Session cannot be null here, session id = $sessionId")
// }
} else { // create new session } else { // create new session
currentSession = Session.newInstance(realm, this.model.isTournament) currentSession = Session.newInstance(realm, this.model.isTournament)
@ -530,8 +515,8 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
val bankrollId = this.currentSession.bankroll?.id val bankrollId = this.currentSession.bankroll?.id
val sessionId = this.currentSession.id val sessionId = this.currentSession.id
getRealm().executeTransactionAsync { realm -> getRealm().executeTransactionAsync { asyncRealm ->
realm.findById<Session>(sessionId)?.let { session -> asyncRealm.findById<Session>(sessionId)?.let { session ->
session.delete() session.delete()
} }
} }
@ -717,17 +702,19 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
override fun resultCaptureTypeSelected(resultCaptureType: ResultCaptureType, applyBankroll: Boolean) { override fun resultCaptureTypeSelected(resultCaptureType: ResultCaptureType, applyBankroll: Boolean) {
getRealm().executeTransaction { // cleanup existing results when (resultCaptureType) {
when (resultCaptureType) { ResultCaptureType.NET_RESULT -> {
ResultCaptureType.NET_RESULT -> { this.currentSession.clearBuyinCashedOut()
this.currentSession.clearBuyinCashedOut() }
} ResultCaptureType.BUYIN_CASHED_OUT -> {
ResultCaptureType.BUYIN_CASHED_OUT -> { this.currentSession.clearNetResult()
this.currentSession.clearNetResult()
}
} }
} }
getRealm().executeTransactionAsync { asyncRealm -> // cleanup existing results
asyncRealm.copyToRealmOrUpdate(this.currentSession)
}
this.model.resultCaptureType = resultCaptureType this.model.resultCaptureType = resultCaptureType
if (applyBankroll) { if (applyBankroll) {
this.currentSession.bankroll?.let { bankroll -> this.currentSession.bankroll?.let { bankroll ->

@ -58,7 +58,7 @@ class DealtHandsPerHourFragment : RealmFragment() {
private fun save() { private fun save() {
getRealm().executeTransaction { realm -> getRealm().executeTransactionAsync { realm ->
UserConfig.getConfiguration(realm) { userConfig -> UserConfig.getConfiguration(realm) { userConfig ->
this.liveValue.text.toString().toIntOrNull()?.let { liveDealtHandsPerHour -> this.liveValue.text.toString().toIntOrNull()?.let { liveDealtHandsPerHour ->

@ -97,10 +97,10 @@ class TransactionFilterFragment : RealmFragment(), StaticRowRepresentableDataSou
} }
private fun save() { private fun save() {
getRealm().executeTransaction { realm -> getRealm().executeTransactionAsync { asyncRealm ->
UserConfig.getConfiguration(this.getRealm()) { userConfig -> UserConfig.getConfiguration(asyncRealm) { userConfig ->
userConfig.setTransactionTypeIds(this.model.selectedTransactionTypes) userConfig.setTransactionTypeIds(this.model.selectedTransactionTypes)
realm.copyToRealmOrUpdate(userConfig) asyncRealm.copyToRealmOrUpdate(userConfig)
} }
} }
this.activity?.finish() this.activity?.finish()

@ -35,9 +35,9 @@ class FakeDataManager {
val locations = realm.where<Location>().findAll() val locations = realm.where<Location>().findAll()
if (locations.size == 0) { if (locations.size == 0) {
realm.executeTransaction { realm.executeTransactionAsync { asyncRealm ->
listOf("Bellagio", "Aria", "Borgata").map { listOf("Bellagio", "Aria", "Borgata").map {
realm.getOrCreate<Location>(it) asyncRealm.getOrCreate<Location>(it)
} }
} }
} }

@ -45,7 +45,7 @@ abstract class PACSVDescriptor<T : Identifiable>(source: DataSource,
protected fun parseSession(realm: Realm, record: CSVRecord): Session? { protected fun parseSession(realm: Realm, record: CSVRecord): Session? {
val isTournament = isTournament ?: false val isTournament = isTournament ?: false
val session = Session.newInstance(realm, isTournament, managed = false) val session = Session.newInstance(realm, isTournament)
var startDate: Date? = null var startDate: Date? = null
var endDate: Date? = null var endDate: Date? = null

@ -7,6 +7,7 @@ import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.NameManageable
import net.pokeranalytics.android.model.interfaces.UsageCountable import net.pokeranalytics.android.model.interfaces.UsageCountable
import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.model.realm.*
import java.lang.ref.WeakReference
fun <T : RealmModel>Realm.count(clazz: Class<T>) : Long { fun <T : RealmModel>Realm.count(clazz: Class<T>) : Long {
return this.where(clazz).count() return this.where(clazz).count()
@ -62,7 +63,7 @@ fun <T : RealmModel> Realm.sorted(clazz: Class<T>, editableOnly: Boolean = false
query.notEqualTo("id", it) query.notEqualTo("id", it)
} }
val items = query.findAll() val items = query.findAllAsync()
var sortField = arrayOf("name") var sortField = arrayOf("name")
var resultSort = arrayOf(Sort.ASCENDING) var resultSort = arrayOf(Sort.ASCENDING)
@ -96,8 +97,8 @@ inline fun <reified C : RealmModel> Realm.sorted(editableOnly: Boolean = false,
*/ */
fun <T : RealmModel>Realm.updateUsageCount(clazz: Class<T>) { fun <T : RealmModel>Realm.updateUsageCount(clazz: Class<T>) {
val results = this.where(clazz).findAll() this.executeTransactionAsync {
this.executeTransaction { val results = it.where(clazz).findAll()
results.forEach { countableUsage -> results.forEach { countableUsage ->
val countable = (countableUsage as UsageCountable) val countable = (countableUsage as UsageCountable)
@ -146,4 +147,10 @@ fun Realm.lookupForNameInAllTablesById(id: String): String? {
} }
} }
return null return null
}
fun Realm.copySessionFromRealm(session: Session): Session {
val copy = this.copyFromRealm(session)
copy.result?.inverseSession = WeakReference(copy)
return copy
} }
Loading…
Cancel
Save