Refactor executeTransaction into executeTransactionAsync

perftest
Laurent 3 years ago
parent c99ef285af
commit 56019357b4
  1. 4
      app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt
  2. 4
      app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt
  3. 20
      app/src/main/java/net/pokeranalytics/android/model/migrations/Patcher.kt
  4. 22
      app/src/main/java/net/pokeranalytics/android/model/realm/CustomField.kt
  5. 2
      app/src/main/java/net/pokeranalytics/android/model/realm/Player.kt
  6. 2
      app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt
  7. 70
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  8. 8
      app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt
  9. 14
      app/src/main/java/net/pokeranalytics/android/model/realm/UserConfig.kt
  10. 10
      app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt
  11. 14
      app/src/main/java/net/pokeranalytics/android/model/utils/FavoriteSessionFinder.kt
  12. 392
      app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt
  13. 2
      app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt
  14. 6
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt
  15. 13
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt
  16. 18
      app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarFragment.kt
  17. 3
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterHandler.kt
  18. 9
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/editor/EditorFragment.kt
  19. 24
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/EditorViewModel.kt
  20. 120
      app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt
  21. 24
      app/src/main/java/net/pokeranalytics/android/ui/modules/settings/DealtHandsPerHourFragment.kt
  22. 12
      app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterFragment.kt
  23. 11
      app/src/main/java/net/pokeranalytics/android/ui/viewmodel/BottomSheetViewModel.kt
  24. 2
      app/src/main/java/net/pokeranalytics/android/util/csv/CSVDescriptor.kt

@ -186,13 +186,13 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() {
Assert.fail("No std100 stat")
}
results.computedStat(Stat.MAXIMUM_NETRESULT)?.let {
results.computedStat(Stat.MAXIMUM_NET_RESULT)?.let {
assertEquals(300.0, it.value, delta)
} ?: run {
Assert.fail("No MAXIMUM_NETRESULT")
}
results.computedStat(Stat.MINIMUM_NETRESULT)?.let {
results.computedStat(Stat.MINIMUM_NET_RESULT)?.let {
assertEquals(-100.0, it.value, delta)
} ?: run {
Assert.fail("No MINIMUM_NETRESULT")

@ -200,7 +200,7 @@ class ReportTask(private var whistleBlower: ReportWhistleBlower, var context: Co
for (stat in result.options.stats) {
Timber.d("analyse stat: $stat for report: $staticReport")
// Timber.d("analyse stat: $stat for report: $staticReport")
// Get current performance
var query = performancesQuery(realm, staticReport, stat)
@ -219,7 +219,7 @@ class ReportTask(private var whistleBlower: ReportWhistleBlower, var context: Co
val performanceQuery = computedResults.group.query
val performanceName = performanceQuery.getName(this.context, nameSeparator)
Timber.d("Best computed = $performanceName, ${computedResults.computedStat(Stat.NET_RESULT)?.value}")
// Timber.d("Best computed = $performanceName, ${computedResults.computedStat(Stat.NET_RESULT)?.value}")
var storePerf = true
currentPerf?.let {

@ -70,7 +70,7 @@ class Patcher {
val transactionTypes = TransactionType.Value.values()
realm.executeTransaction {
realm.executeTransactionAsync {
Seed.createDefaultTransactionTypes(transactionTypes, context, realm)
}
@ -84,7 +84,7 @@ class Patcher {
val sessions = Filter.queryOn<Session>(realm, Query(QueryCondition.IsCash))
val results = realm.where(Result::class.java).findAll()
realm.executeTransaction {
realm.executeTransactionAsync {
sets.forEach {
it.computeStats()
}
@ -103,7 +103,7 @@ class Patcher {
private fun patchDefaultTransactionTypes(context: Context) {
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.executeTransactionAsync {
val tts = realm.where(TransactionType::class.java).findAll()
tts.forEach { tt ->
tt.kind?.let { kind ->
@ -117,7 +117,7 @@ class Patcher {
private fun patchStakes() {
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.executeTransactionAsync {
val sessions = realm.where(Session::class.java).findAll()
sessions.forEach { session ->
val blinds = arrayListOf(session.cgOldSmallBlind, session.cgOldBigBlind).filterNotNull()
@ -143,7 +143,7 @@ class Patcher {
private fun patchNegativeLimits() {
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.executeTransactionAsync {
val sessions = realm.where(Session::class.java).lessThan("limit", 0).findAll()
sessions.forEach { session ->
session.limit = null
@ -154,7 +154,7 @@ class Patcher {
private fun cleanBlindsFilters() {
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.executeTransactionAsync {
val blindFilterConditions = realm.where(FilterCondition::class.java).equalTo("filterName", "AnyBlind").findAll()
val filterIds = blindFilterConditions.mapNotNull { it.filters?.firstOrNull() }.map { it.id }
val filters = realm.where(Filter::class.java).`in`("id", filterIds.toTypedArray()).findAll()
@ -170,7 +170,7 @@ class Patcher {
private fun patchSessionSet() {
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.executeTransactionAsync {
realm.where(SessionSet::class.java).findAll().deleteAllFromRealm()
val sessions = realm.where(Session::class.java).isNotNull("startDate").isNotNull("endDate").findAll()
sessions.forEach { session ->
@ -187,7 +187,7 @@ class Patcher {
*/
private fun patchComputableResults() {
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.executeTransactionAsync {
val crs = realm.where(ComputableResult::class.java).findAll()
crs.forEach { cr ->
cr.session?.let { cr.updateWith(it) }
@ -211,7 +211,7 @@ class Patcher {
val realm = Realm.getDefaultInstance()
val zero = 0
val sessions = realm.where<Session>().equalTo("numberOfTables", zero).findAll()
realm.executeTransaction {
realm.executeTransactionAsync {
sessions.forEach { s ->
s.numberOfTables = 1
}
@ -222,7 +222,7 @@ class Patcher {
private fun patchRatedAmounts() {
val realm = Realm.getDefaultInstance()
val transactions = realm.where<Transaction>().findAll()
realm.executeTransaction {
realm.executeTransactionAsync {
transactions.forEach { t ->
t.computeRatedAmount()
}

@ -250,7 +250,7 @@ open class CustomField : RealmObject(), RowRepresentable, RowUpdatable, NameMana
fun cleanupEntries() { // called when saving the custom field
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.executeTransactionAsync {
this.entriesToDelete.forEach { // entries are out of realm
realm.where<CustomFieldEntry>().equalTo("id", it.id).findFirst()?.deleteFromRealm()
}
@ -272,26 +272,6 @@ open class CustomField : RealmObject(), RowRepresentable, RowUpdatable, NameMana
}
}
/**
* Clean the entries if the type is not a list & remove the deleted entries from realm
*/
// fun cleanEntries(realm: Realm) {
// realm.executeTransaction {
//
// if (!isListType) {
// entriesToDelete.addAll(entries)
// entries.clear()
// }
//
// // @TODO
// entriesToDelete.forEach {
// Timber.d("Delete entry: V=${it.value} N=${it.numericValue} / ID=${it.id}")
// realm.where<CustomFieldEntry>().equalTo("id", it.id).findFirst()?.deleteFromRealm()
// }
// entriesToDelete.clear()
// }
// }
/**
* Returns a comparison criteria based on this custom field
*/

@ -174,7 +174,7 @@ open class Player : RealmObject(), NameManageable, Savable, Deletable, StaticRow
*/
fun cleanupComments() { // called when saving the custom field
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.executeTransactionAsync {
this.commentsToDelete.forEach { // entries are out of realm
realm.where<Comment>().equalTo("id", it.id).findFirst()?.deleteFromRealm()
}

@ -14,7 +14,7 @@ open class Result : RealmObject(), Filterable {
companion object {
fun fieldNameForQueryType(queryCondition: Class < out QueryCondition>): String? {
fun fieldNameForQueryType(queryCondition: Class <out QueryCondition>): String? {
Session.fieldNameForQueryType(queryCondition)?.let {
return "sessions.$it"
}

@ -80,11 +80,12 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
session.limit = Limit.NO.ordinal
session.game = realm.where(Game::class.java).equalTo("shortName", "HE").findFirst()
return if (managed) {
realm.copyToRealm(session)
} else {
session
}
return session
// return if (managed) {
// realm.copyToRealm(session)
// } else {
// session
// }
}
fun fieldNameForQueryType(queryCondition: Class < out QueryCondition >): String? {
@ -208,7 +209,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
if (value != null && this.endDate != null && value.after(this.endDate)) {
this.endDate = null
}
this.dateChanged()
// this.dateChanged()
this.computeStats()
}
@ -228,7 +229,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
}
this.computeNetDuration()
this.dateChanged()
// this.dateChanged()
this.defineDefaultTournamentBuyinIfNecessary()
this.computeStats()
}
@ -386,18 +387,19 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
this.generateStakes()
}
/**
* Manages impacts on SessionSets
* Should be called when the start / end date are changed
*/
private fun dateChanged() {
if (this.endDate != null) {
SessionSetManager.updateTimeline(this)
} else if (this.sessionSet != null) {
SessionSetManager.removeFromTimeline(this)
}
// this.updateRowRepresentation()
}
// /**
// * Manages impacts on SessionSets
// * Should be called when the start / end date are changed
// */
// private fun dateChanged() {
// SessionSetManager.updatedSession(this)
//// if (this.endDate != null) {
//// SessionSetManager.updateTimeline(this)
//// } else if (this.sessionSet != null) {
//// SessionSetManager.removeFromTimeline(this)
//// }
//// this.updateRowRepresentation()
// }
/**
* Returns a non-null date for the session
@ -501,8 +503,14 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
val numberOfHandsPerHour: Double
get() {
val tableSize = this.tableSize ?: 9 // 9 is the default table size if null
val config = UserConfig.getConfiguration(this.realm)
val playerHandsPerHour = if (this.isLive) config.liveDealtHandsPerHour else config.onlineDealtHandsPerHour
var playerHandsPerHour = 0
UserConfig.getConfiguration(this.realm) { config ->
playerHandsPerHour = if (this.isLive) config.liveDealtHandsPerHour else config.onlineDealtHandsPerHour
}
// val config = UserConfig.getConfiguration(this.realm)
// val playerHandsPerHour = if (this.isLive) config.liveDealtHandsPerHour else config.onlineDealtHandsPerHour
return this.numberOfTables * playerHandsPerHour / tableSize.toDouble()
}
@ -557,7 +565,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
* Start or continue a session
*/
fun startOrContinue() {
realm.executeTransaction {
// realm.executeTransaction {
when (val state = getState()) {
SessionState.PENDING, SessionState.PLANNED -> {
this.startDate = Date()
@ -576,7 +584,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
throw PAIllegalStateException("unmanaged session state: $state")
}
}
}
// }
}
private fun defineDefaultTournamentBuyinIfNecessary() {
@ -589,28 +597,28 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
* Pause a session
*/
fun pause() {
realm.executeTransaction {
// realm.executeTransaction {
when (val state = getState()) {
SessionState.STARTED -> {
this.pauseDate = Date()
}
else -> throw PAIllegalStateException("Pausing a session in an unmanaged state: $state")
}
}
// }
}
/**
* Stop a session
*/
fun stop(context: Context) {
realm.executeTransaction {
// realm.executeTransaction {
when (val state = getState()) {
SessionState.STARTED, SessionState.PAUSED -> {
this.end()
}
else -> throw Exception("Stopping session in unmanaged state: $state")
}
}
// }
cancelStopNotification(context)
}
@ -618,12 +626,12 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
* Restart a session
*/
fun restart() {
realm.executeTransaction {
// realm.executeTransaction {
this.pauseDate = null
this.startDate = Date()
this.endDate = null
this.breakDuration = 0L
}
// }
}
/**
@ -721,10 +729,10 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim
CrashLogging.log("Deletes session. Id = ${this.id}")
if (isValid) {
realm.executeTransaction {
// realm.executeTransaction {
cleanup()
deleteFromRealm()
}
// }
} else {
CrashLogging.log("Attempt to delete an invalid session")
}

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

@ -11,7 +11,19 @@ open class UserConfig : RealmObject() {
companion object {
fun getConfiguration(realm: Realm): UserConfig {
fun getConfiguration(realm: Realm?, handler: (UserConfig) -> (Unit)) {
if (realm != null) {
handler(userConfiguration(realm))
} else {
val r = Realm.getDefaultInstance()
handler(userConfiguration(r))
r.close()
}
}
private fun userConfiguration(realm: Realm): UserConfig {
realm.where(UserConfig::class.java).findFirst()?.let { config ->
return config
}

@ -313,13 +313,7 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable,
* Creates and affect a PlayerSetup at the given [positionIndex]
*/
fun createPlayerSetup(positionIndex: Int): PlayerSetup {
val playerSetup = if (this.realm != null) {
this.realm.createObject(PlayerSetup::class.java) }
else {
PlayerSetup()
}
val playerSetup = PlayerSetup()
playerSetup.position = positionIndex
this.playerSetups.add(playerSetup)
return playerSetup
@ -562,7 +556,7 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable,
this.winnerPots.clear()
this.winnerPots.addAll(wonPots)
Timber.d("Pot won: ${this.winnerPots.size} for positions: ${this.winnerPots.map {it.position}} ")
Timber.d("Pot won: ${this.winnerPots.size} for positions: ${this.winnerPots.map { it.position }} ")
}
/***

@ -73,15 +73,21 @@ class FavoriteSessionFinder {
/**
* Copies the favorite session parameters on the [session]
*/
fun copyParametersFromFavoriteSession(session: Session, location: Location?, context: Context) {
fun copyParametersFromFavoriteSession(realm: Realm, session: Session, location: Location?, context: Context) {
val favoriteSession = favoriteSession(session.type, location, session.realm, context)
val favoriteSession = favoriteSession(session.type, location, realm, context)
favoriteSession?.let { fav ->
session.limit = fav.limit
session.game = fav.game
session.bankroll = fav.bankroll
fav.game?.let {
session.game = realm.copyFromRealm(it)
}
fav.bankroll?.let {
session.bankroll = realm.copyFromRealm(it)
}
session.tableSize = fav.tableSize
when (session.type) {

@ -1,9 +1,9 @@
package net.pokeranalytics.android.model.utils
import io.realm.Realm
import io.realm.RealmQuery
import io.realm.RealmResults
import net.pokeranalytics.android.exceptions.ModelException
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet
import kotlin.math.max
@ -14,196 +14,228 @@ class CorruptSessionSetException(message: String) : Exception(message)
* The manager is in charge of updating the abstract concept of timeline,
* representing the sequenced time frames where the user plays.
*/
class SessionSetManager {
companion object {
/**
* Updates the global timeline using the updated [session]
*/
fun updateTimeline(session: Session) {
if (!session.realm.isInTransaction) {
throw PAIllegalStateException("realm should be in transaction at this point")
}
if (session.startDate == null) {
throw ModelException("Start date should never be null here")
}
if (session.endDate == null) {
throw ModelException("End date should never be null here")
}
val sessionSets = this.matchingSets(session)
cleanupSessionSets(session, sessionSets)
}
private fun matchingSets(session: Session) : RealmResults<SessionSet> {
val realm = session.realm
val endDate = session.endDate!! // tested above
val startDate = session.startDate!!
val query: RealmQuery<SessionSet> = realm.where(SessionSet::class.java)
query
.lessThanOrEqualTo("startDate", startDate)
.greaterThanOrEqualTo("endDate", startDate)
.or()
.lessThanOrEqualTo("startDate", endDate)
.greaterThanOrEqualTo("endDate", endDate)
.or()
.greaterThanOrEqualTo("startDate", startDate)
.lessThanOrEqualTo("endDate", endDate)
return query.findAll()
}
/**
* Multiple session sets update:
* Merges or splits session sets
* Does that by deleting then recreating
*/
private fun cleanupSessionSets(session: Session, sessionSets: RealmResults<SessionSet>) {
// get all endedSessions from sets
val allImpactedSessions = mutableSetOf<Session>()
sessionSets.forEach { set ->
set.sessions?.asIterable()?.let { allImpactedSessions.addAll(it) }
}
allImpactedSessions.add(session)
// delete all sets
sessionSets.deleteAllFromRealm()
allImpactedSessions.forEach { impactedSession ->
val sets = matchingSets(impactedSession)
this.updateTimeFrames(sets, impactedSession)
}
object SessionSetManager {
var sessions: RealmResults<Session>
private val sessionsToProcess = mutableSetOf<Session>()
init {
val realm = Realm.getDefaultInstance()
this.sessions = realm.where(Session::class.java).findAll()
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) }
}
processSessions()
}
realm.close()
}
// fun updatedSession(session: Session) {
// this.sessionsToProcess.add(session)
// }
private fun processSessions() {
for (session in this.sessionsToProcess) {
if (session.startDate != null && session.endDate != null) {
this.updateTimeline(session)
} else if (session.sessionSet != null) {
removeFromTimeline(session)
}
}
this.sessionsToProcess.clear()
}
/**
* Updates the global timeline using the updated [session]
*/
fun updateTimeline(session: Session) {
// if (!session.realm.isInTransaction) {
// throw PAIllegalStateException("realm should be in transaction at this point")
// }
if (session.startDate == null) {
throw ModelException("Start date should never be null here")
}
if (session.endDate == null) {
throw ModelException("End date should never be null here")
}
val sessionSets = this.matchingSets(session)
cleanupSessionSets(session, sessionSets)
}
private fun matchingSets(session: Session): RealmResults<SessionSet> {
val realm = session.realm
val endDate = session.endDate!! // tested above
val startDate = session.startDate!!
val query: RealmQuery<SessionSet> = realm.where(SessionSet::class.java)
query
.lessThanOrEqualTo("startDate", startDate)
.greaterThanOrEqualTo("endDate", startDate)
.or()
.lessThanOrEqualTo("startDate", endDate)
.greaterThanOrEqualTo("endDate", endDate)
.or()
.greaterThanOrEqualTo("startDate", startDate)
.lessThanOrEqualTo("endDate", endDate)
return query.findAll()
}
/**
* Multiple session sets update:
* Merges or splits session sets
* Does that by deleting then recreating
*/
private fun cleanupSessionSets(session: Session, sessionSets: RealmResults<SessionSet>) {
// get all endedSessions from sets
val allImpactedSessions = mutableSetOf<Session>()
sessionSets.forEach { set ->
set.sessions?.asIterable()?.let { allImpactedSessions.addAll(it) }
}
allImpactedSessions.add(session)
// delete all sets
sessionSets.deleteAllFromRealm()
allImpactedSessions.forEach { impactedSession ->
val sets = matchingSets(impactedSession)
this.updateTimeFrames(sets, impactedSession)
}
// Timber.d("netDuration 3 = : ${set.timeFrame?.netDuration}")
}
/**
* Update the global timeline using the impacted [sessionSets] and the updated [session]
*/
private fun updateTimeFrames(sessionSets: RealmResults<SessionSet>, session: Session) {
when (sessionSets.size) {
0 -> this.createOrUpdateSessionSet(session)
else -> this.mergeSessionGroups(session, sessionSets)
}
}
/**
* Creates or update the session set for the [session]
*/
private fun createOrUpdateSessionSet(session: Session) {
val set = session.sessionSet
if (set != null) {
set.startDate = session.startDate!! // tested above
set.endDate = session.endDate!!
} else {
this.createSessionSet(session)
}
}
/**
* Create a set and affect it to the [session]
*/
private fun createSessionSet(session: Session) {
val set: SessionSet = SessionSet.newInstance(session.realm)
set.startDate = session.startDate!!
set.endDate = session.endDate!!
set.breakDuration = session.breakDuration
session.sessionSet = set
set.computeStats()
}
/**
* Multiple session sets update:
* Merges all sets into one (delete all then create a new one)
*/
private fun mergeSessionGroups(session: Session, sessionSets: RealmResults<SessionSet>) {
var startDate = session.startDate!!
var endDate = session.endDate!!
// get all endedSessions from sets
val sessions = mutableSetOf<Session>()
sessionSets.forEach { set ->
set.sessions?.asIterable()?.let { sessions.addAll(it) }
}
// find earlier and later dates from all sets
sessions.forEach { s ->
if (s.startDate != null && s.endDate != null) {
val start = s.startDate!!
val end = s.endDate!!
if (start.before(startDate)) {
startDate = start
}
if (end.after(endDate)) {
endDate = end
}
} else {
throw CorruptSessionSetException("Set contains unfinished sessions!")
}
}
// delete all sets
sessionSets.deleteAllFromRealm()
// Create a new set
val set: SessionSet = SessionSet.newInstance(session.realm)
set.startDate = startDate
set.endDate = endDate
// Add the session linked to this timeframe to the new sessionGroup
session.sessionSet = set
// Add all orphan endedSessions
sessions.forEach { s ->
s.sessionSet = set
set.breakDuration = max(set.breakDuration, s.breakDuration)
}
set.computeStats()
}
/**
* Update the global timeline using the impacted [sessionSets] and the updated [session]
*/
private fun updateTimeFrames(sessionSets: RealmResults<SessionSet>, session: Session) {
when (sessionSets.size) {
0 -> this.createOrUpdateSessionSet(session)
else -> this.mergeSessionGroups(session, sessionSets)
}
}
/**
* Creates or update the session set for the [session]
*/
private fun createOrUpdateSessionSet(session: Session) {
val set = session.sessionSet
if (set != null) {
set.startDate = session.startDate!! // tested above
set.endDate = session.endDate!!
} else {
this.createSessionSet(session)
}
}
/**
* Create a set and affect it to the [session]
*/
private fun createSessionSet(session: Session) {
val set = SessionSet() //.newInstance(session.realm)
set.startDate = session.startDate!!
set.endDate = session.endDate!!
set.breakDuration = session.breakDuration
session.sessionSet = set
set.computeStats()
}
/**
* Multiple session sets update:
* Merges all sets into one (delete all then create a new one)
*/
private fun mergeSessionGroups(session: Session, sessionSets: RealmResults<SessionSet>) {
var startDate = session.startDate!!
var endDate = session.endDate!!
// get all endedSessions from sets
val sessions = mutableSetOf<Session>()
sessionSets.forEach { set ->
set.sessions?.asIterable()?.let { sessions.addAll(it) }
}
// find earlier and later dates from all sets
sessions.forEach { s ->
if (s.startDate != null && s.endDate != null) {
val start = s.startDate!!
val end = s.endDate!!
if (start.before(startDate)) {
startDate = start
}
if (end.after(endDate)) {
endDate = end
}
} else {
throw CorruptSessionSetException("Set contains unfinished sessions!")
}
}
// delete all sets
sessionSets.deleteAllFromRealm()
// Create a new set
val set = SessionSet() //.newInstance(session.realm)
set.startDate = startDate
set.endDate = endDate
// Add the session linked to this timeframe to the new sessionGroup
session.sessionSet = set
// Add all orphan endedSessions
sessions.forEach { s ->
s.sessionSet = set
set.breakDuration = max(set.breakDuration, s.breakDuration)
}
set.computeStats()
// Timber.d("netDuration 3 = : ${set.timeFrame?.netDuration}")
}
}
/**
* Removes the [session] from the timeline
*/
fun removeFromTimeline(session: Session) {
/**
* Removes the [session] from the timeline
*/
fun removeFromTimeline(session: Session) {
if (!session.realm.isInTransaction) {
throw PAIllegalStateException("realm should be in transaction at this point")
}
// if (!session.realm.isInTransaction) {
// throw PAIllegalStateException("realm should be in transaction at this point")
// }
val sessionSet = session.sessionSet
if (sessionSet != null) {
val sessionSet = session.sessionSet
if (sessionSet != null) {
val sessions = mutableSetOf<Session>()
sessionSet.sessions?.asIterable()?.let { sessions.addAll(it) }
sessions.remove(session)
val sessions = mutableSetOf<Session>()
sessionSet.sessions?.asIterable()?.let { sessions.addAll(it) }
sessions.remove(session)
sessionSet.deleteFromRealm()
sessionSet.deleteFromRealm()
sessions.forEach {
updateTimeline(it)
}
}
}
}
sessions.forEach {
updateTimeline(it)
}
}
}
}

@ -115,7 +115,7 @@ class HomeActivity : BaseActivity(), NewPerformanceListener {
// observe currency changes
this.currencies = realm.where(Currency::class.java).findAll()
this.currencies.addChangeListener { currencies, _ ->
realm.executeTransaction {
realm.executeTransactionAsync {
currencies.forEach {
it.refreshRelatedRatedValues()
}

@ -185,12 +185,12 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep
Preferences.setCurrencyCode(currencyCode, requireContext())
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.where(Currency::class.java).findAll().forEach { currency ->
realm.executeTransactionAsync { execRealm->
execRealm.where(Currency::class.java).findAll().forEach { currency ->
currency.rate = (currency.rate ?: 1.0) * rate
}
realm.where(Session::class.java).findAll().forEach { session ->
execRealm.where(Session::class.java).findAll().forEach { session ->
session.bankrollHasBeenUpdated()
}
}

@ -96,10 +96,11 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
private fun setTransactionFilterItemColor() {
context?.let {
val userConfig = UserConfig.getConfiguration(getRealm())
val color = if (userConfig.transactionTypeIds.isNotEmpty()) R.color.red else R.color.white
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.transactionFilterMenuItem?.iconTintList = ColorStateList.valueOf(it.getColor(color))
UserConfig.getConfiguration(getRealm()) { userConfig ->
val color = if (userConfig.transactionTypeIds.isNotEmpty()) R.color.red else R.color.white
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.transactionFilterMenuItem?.iconTintList = ColorStateList.valueOf(it.getColor(color))
}
}
}
}
@ -246,7 +247,9 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
computedStats.addAll(tStats)
options.stats = computedStats
options.includedTransactions = UserConfig.getConfiguration(realm).transactionTypes(realm)
UserConfig.getConfiguration(realm) { userConfig ->
options.includedTransactions = userConfig.transactionTypes(realm)
}
return Calculator.computeGroups(realm, listOf(allSessionGroup, cgSessionGroup, tSessionGroup), options)
}

@ -11,7 +11,6 @@ import io.realm.Realm
import io.realm.RealmModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Calculator
@ -25,6 +24,7 @@ import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.model.realm.TransactionType
import net.pokeranalytics.android.model.realm.UserConfig
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
@ -133,11 +133,10 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
private fun setTransactionFilterItemColor() {
context?.let {
val userConfig = UserConfig.getConfiguration(getRealm())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.transactionFilterMenuItem?.let { item ->
val color = if (userConfig.transactionTypeIds.isNotEmpty()) R.color.red else R.color.white
item.iconTintList = ColorStateList.valueOf(it.getColor(color))
UserConfig.getConfiguration(getRealm()) { userConfig ->
val color = if (userConfig.transactionTypeIds.isNotEmpty()) R.color.red else R.color.white
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.transactionFilterMenuItem?.iconTintList = ColorStateList.valueOf(it.getColor(color))
}
}
}
@ -378,7 +377,12 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
Stat.STANDARD_DEVIATION_HOURLY
)
val transactionTypes = UserConfig.getConfiguration(realm).transactionTypes(realm)
var transactionTypes = listOf<TransactionType>()
UserConfig.getConfiguration(realm) { userConfig ->
transactionTypes = userConfig.transactionTypes(realm)
}
// val transactionTypes = UserConfig.getConfiguration(realm).transactionTypes(realm)
// All
val allOptions = Calculator.Options(

@ -45,9 +45,8 @@ interface FilterHandler {
fun saveFilter(context: Context, filterId: String) {
Preferences.setActiveFilterId(filterId, context)
val realm = Realm.getDefaultInstance()
realm.executeTransaction { executeRealm ->
realm.executeTransactionAsync { executeRealm ->
currentFilter(context, executeRealm)?.let {
it.useCount++
}

@ -202,12 +202,15 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
if (resultCode == Activity.RESULT_OK) {
val playerId = data?.getStringExtra(BaseFragment.BundleKey.PRIMARY_KEY.value)
?: throw PAIllegalStateException("Primary key not set where as activity has finished")
getRealm().findById<Player>(playerId)?.let { player ->
this.model.playerSelected(player)
val realm = getRealm()
realm.findById<Player>(playerId)?.let { player ->
val p = realm.copyFromRealm(player)
this.model.playerSelected(p)
} ?: throw PAIllegalStateException("Player (id=$playerId) not found")
this.editorAdapter.notifyDataSetChanged()
}
}
}

@ -635,14 +635,12 @@ class EditorViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer
* Saves the current hand state in the database
*/
fun save(realm: Realm) {
realm.executeTransaction {
this.handHistory.actions.clear()
val actions = this.sortedActions.map { it.action }
this.handHistory.actions.addAll(actions)
this.handHistory.actions.clear()
val actions = this.sortedActions.map { it.action }
this.handHistory.actions.addAll(actions)
if (!this.handHistory.isManaged) {
realm.copyToRealmOrUpdate(this.handHistory)
}
realm.executeTransactionAsync { execRealm ->
execRealm.copyToRealmOrUpdate(this.handHistory)
}
this.defineWinnerPositions()
}
@ -652,8 +650,10 @@ class EditorViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer
val hhId = this.handHistory.id
CoroutineScope(Dispatchers.Default).launch {
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.findById<HandHistory>(hhId)?.defineWinnerPositions()
realm.findById<HandHistory>(hhId)?.defineWinnerPositions()
realm.executeTransactionAsync { execRealm ->
execRealm.copyToRealmOrUpdate(handHistory)
}
realm.close()
}
@ -1004,16 +1004,16 @@ class EditorViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer
fun playerSelected(player: Player) {
// Remove all use of the selected player
this.handHistory.playerSetups.filter { it.player == player }.forEach {
this.handHistory.playerSetups.filter { it.player?.id == player.id }.forEach {
it.player = null
}
// Affects the player to the selected position
this.tappedPlayerPositionIndex?.let { positionIndex ->
player.realm.executeTransaction {
// player.realm.executeTransaction {
val ps = this.handHistory.playerSetupForPosition(positionIndex) ?: this.handHistory.createPlayerSetup(positionIndex)
ps.player = player
}
// }
} ?: throw PAIllegalStateException("Click position not set for player selection")
}

@ -176,40 +176,59 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
if (sessionId != null) {
val sessionRealm = realm.findById<Session>(sessionId)
if (sessionRealm != null) {
sessionRealm?.let {
val copy = realm.copyFromRealm(it)
if (this.model.duplicate) { // duplicate session
realm.executeTransaction {
val session = sessionRealm.duplicate()
// realm.executeTransaction {
val session = copy.duplicate()
currentSession = session
}
// }
sessionHasBeenUserCustomized = false
} else { // show existing session
currentSession = sessionRealm
currentSession = copy
sessionHasBeenUserCustomized = true
}
} else {
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
realm.executeTransaction { executeRealm ->
currentSession = Session.newInstance(executeRealm, this.model.isTournament)
FavoriteSessionFinder.copyParametersFromFavoriteSession(currentSession, null, requireContext())
}
currentSession = Session.newInstance(realm, this.model.isTournament)
FavoriteSessionFinder.copyParametersFromFavoriteSession(realm, currentSession, null, requireContext())
// realm.executeTransaction { executeRealm ->
// currentSession = Session.newInstance(executeRealm, this.model.isTournament)
// FavoriteSessionFinder.copyParametersFromFavoriteSession(currentSession, null, requireContext())
// }
// Find the nearest location around the user
parentActivity?.findNearestLocation {
it?.let { location ->
realm.executeTransaction { executeRealm ->
val realmLocation = executeRealm.findById<Location>(location.id)
FavoriteSessionFinder.copyParametersFromFavoriteSession(currentSession, realmLocation, requireContext())
currentSession.location = realmLocation
}
// realm.executeTransaction { executeRealm ->
val realmLocation = realm.findById<Location>(location.id)
FavoriteSessionFinder.copyParametersFromFavoriteSession(realm, currentSession, realmLocation, requireContext())
currentSession.location = realmLocation
// }
this.updateSessionUI(true)
}
}
sessionHasBeenUserCustomized = false
this.sessionHasBeenUserCustomized = false
}
}
@ -251,15 +270,23 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
}
override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
Timber.d("value changed: $value, row: $row")
this.sessionHasBeenUserCustomized = true
try {
getRealm().executeTransaction {
this.currentSession.updateValue(value, row)
}
} catch (e: PAIllegalStateException) {
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
return
updateSessionThenSaveAsynchronously { session ->
session.updateValue(value, row)
}
// try {
// this.currentSession.updateValue(value, row)
// getRealm().executeTransactionAsync { realm ->
// realm.copyToRealmOrUpdate(this.currentSession)
// }
// } catch (e: PAIllegalStateException) {
// Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
// return
// }
this.sessionAdapter.refreshRow(row)
when (row) {
SessionPropertiesRow.CASHED_OUT, SessionPropertiesRow.PRIZE, SessionPropertiesRow.NET_RESULT,
@ -273,6 +300,18 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
}
private fun updateSessionThenSaveAsynchronously(handler: (Session) -> (Unit)) {
try {
handler(this.currentSession)
} catch (e: PAIllegalStateException) {
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
return
}
getRealm().executeTransactionAsync { realm ->
realm.copyToRealmOrUpdate(this.currentSession)
}
}
/**
* Update the UI with the session data
* Should be called after the initialization of the session
@ -386,12 +425,20 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
}
}
currentSession.startOrContinue()
updateSessionThenSaveAsynchronously { session ->
session.startOrContinue()
}
// currentSession.startOrContinue()
binding.recyclerView.smoothScrollToPosition(0)
}
SessionState.STARTED -> {
currentSession.pause()
updateSessionThenSaveAsynchronously { session ->
session.pause()
}
// currentSession.pause()
}
else -> {
}
@ -435,7 +482,9 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
* Stop the current session
*/
private fun stopSession() {
this.currentSession.stop(requireContext())
updateSessionThenSaveAsynchronously { session ->
session.stop(requireContext())
}
updateSessionUI()
}
@ -454,7 +503,9 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
* Restart timer
*/
private fun restartTimer() {
currentSession.restart()
updateSessionThenSaveAsynchronously { session ->
session.restart()
}
updateSessionUI()
}
@ -478,7 +529,14 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
val bankrollId = this.currentSession.bankroll?.id
this.currentSession.delete()
val sessionId = this.currentSession.id
getRealm().executeTransactionAsync { realm ->
realm.findById<Session>(sessionId)?.let { session ->
session.delete()
}
}
// this.currentSession.delete()
bankrollId?.let {
BankrollReportManager.notifyBankrollReportImpact(bankrollId)
}

@ -49,9 +49,10 @@ class DealtHandsPerHourFragment : RealmFragment() {
setDisplayHomeAsUpEnabled(true)
val userConfig = UserConfig.getConfiguration(this.getRealm())
this.liveValue.hint = "${userConfig.liveDealtHandsPerHour}"
this.onlineValue.hint = "${userConfig.onlineDealtHandsPerHour}"
UserConfig.getConfiguration(this.getRealm()) { userConfig ->
this.liveValue.hint = "${userConfig.liveDealtHandsPerHour}"
this.onlineValue.hint = "${userConfig.onlineDealtHandsPerHour}"
}
}
@ -59,14 +60,17 @@ class DealtHandsPerHourFragment : RealmFragment() {
getRealm().executeTransaction { realm ->
val userConfig = UserConfig.getConfiguration(realm)
this.liveValue.text.toString().toIntOrNull()?.let { liveDealtHandsPerHour ->
userConfig.liveDealtHandsPerHour = liveDealtHandsPerHour
}
this.onlineValue.text.toString().toIntOrNull()?.let { onlineDealtHandsPerHour ->
userConfig.onlineDealtHandsPerHour = onlineDealtHandsPerHour
UserConfig.getConfiguration(realm) { userConfig ->
this.liveValue.text.toString().toIntOrNull()?.let { liveDealtHandsPerHour ->
userConfig.liveDealtHandsPerHour = liveDealtHandsPerHour
}
this.onlineValue.text.toString().toIntOrNull()?.let { onlineDealtHandsPerHour ->
userConfig.onlineDealtHandsPerHour = onlineDealtHandsPerHour
}
realm.copyToRealmOrUpdate(userConfig)
}
realm.copyToRealmOrUpdate(userConfig)
// val userConfig = UserConfig.getConfiguration(realm)
// update all precomputed hand counts
realm.where(ComputableResult::class.java).findAll().forEach { cr ->

@ -90,16 +90,18 @@ class TransactionFilterFragment : RealmFragment(), StaticRowRepresentableDataSou
.findAll()
this.model.transactionTypes = transactionTypes
val userConfig = UserConfig.getConfiguration(this.getRealm())
this.model.selectedTransactionTypes = userConfig.transactionTypes(getRealm()).toMutableSet()
UserConfig.getConfiguration(this.getRealm()) { userConfig ->
this.model.selectedTransactionTypes = userConfig.transactionTypes(getRealm()).toMutableSet()
}
}
private fun save() {
getRealm().executeTransaction { realm ->
val userConfig = UserConfig.getConfiguration(realm)
userConfig.setTransactionTypeIds(this.model.selectedTransactionTypes)
realm.copyToRealmOrUpdate(userConfig)
UserConfig.getConfiguration(this.getRealm()) { userConfig ->
userConfig.setTransactionTypeIds(this.model.selectedTransactionTypes)
realm.copyToRealmOrUpdate(userConfig)
}
}
this.activity?.finish()
}

@ -3,6 +3,7 @@ package net.pokeranalytics.android.ui.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import io.realm.RealmList
import io.realm.RealmModel
import io.realm.RealmResults
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException
@ -242,9 +243,15 @@ class BottomSheetViewModel(var row: RowRepresentable) : ViewModel() {
}
}
fun rowSelected(position: Int): RowRepresentable? {
fun rowSelected(position: Int): RowRepresentable {
return when(this.row.bottomSheetType) {
BottomSheetType.LIST -> this.realmData?.get(position)
BottomSheetType.LIST -> {
realmData?.realm?.let { realm ->
this.realmData?.get(position)?.let {
realm.copyFromRealm(it as RealmModel) as? RowRepresentable
} ?: throw PAIllegalStateException("item not found at $position")
} ?: throw PAIllegalStateException("realm not found")
}
BottomSheetType.LIST_STATIC -> this.staticRows[position]
else -> throw PAIllegalStateException("row selected for unmanaged bottom sheet type")
}

@ -61,7 +61,7 @@ abstract class DataCSVDescriptor<T : Identifiable>(source: DataSource, vararg el
if (realm.isInTransaction) {
this.deleteInsertedFromRealm(realm)
} else {
realm.executeTransaction {
realm.executeTransactionAsync {
this.deleteInsertedFromRealm(realm)
}
}

Loading…
Cancel
Save