From 991cb6bf6e4bb35dc7a0054aab06bb122074d13e Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 20 Oct 2022 13:56:30 +0200 Subject: [PATCH] Fixes --- .../android/calculus/Calculator.kt | 7 +- .../android/calculus/ReportWhistleBlower.kt | 115 ++++++++++++------ .../android/model/filter/QueryCondition.kt | 1 + .../android/ui/activity/HomeActivity.kt | 5 + .../android/ui/fragment/ImportFragment.kt | 16 +-- .../android/ui/fragment/ReportsFragment.kt | 21 ++-- .../android/ui/view/rows/StaticReport.kt | 12 +- 7 files changed, 115 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt index 0b029716..3ac8c835 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -13,6 +13,7 @@ import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.model.realm.SessionSet import net.pokeranalytics.android.util.extensions.startOfDay +import timber.log.Timber import java.util.* import kotlin.math.max import kotlin.math.min @@ -178,13 +179,13 @@ class Calculator { val computableGroups: MutableList = mutableListOf() - options.criterias.combined().forEach { comparatorQuery -> + val combinations = options.criterias.combined() + Timber.d("Combinations: ${ combinations.map { it.defaultName }}") + for (comparatorQuery in combinations) { comparatorQuery.merge(options.query) - val group = ComputableGroup(comparatorQuery) computableGroups.add(group) - } if (computableGroups.size == 0) { diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt b/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt index 0ca2cdf4..374e7308 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt @@ -2,6 +2,7 @@ package net.pokeranalytics.android.calculus import android.content.Context import io.realm.Realm +import io.realm.RealmQuery import io.realm.RealmResults import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -30,6 +31,8 @@ class ReportWhistleBlower(var context: Context) { private val listeners: MutableList = mutableListOf() + private var paused: Boolean = false + init { val realm = Realm.getDefaultInstance() @@ -43,15 +46,25 @@ class ReportWhistleBlower(var context: Context) { this.results?.addChangeListener { _ -> launchReportTask() } + + realm.close() } fun addListener(newPerformanceListener: NewPerformanceListener) { this.listeners.add(newPerformanceListener) } + fun removeListener(listener: NewPerformanceListener) { + this.listeners.remove(listener) + } + fun launchReportTask() { Timber.d(">>> Launch report") + if (paused) { + return + } + synchronized(this) { this.currentTask?.cancel() val reportTask = ReportTask(this, this.context) @@ -61,6 +74,15 @@ class ReportWhistleBlower(var context: Context) { } + fun pause() { + this.paused = true + } + + fun resume() { + this.paused = false + this.launchReportTask() + } + fun has(performanceId: String): Boolean { return this.currentNotifications.contains(performanceId) } @@ -144,43 +166,46 @@ class ReportTask(private var whistleBlower: ReportWhistleBlower, var context: Co private fun launchOptimalDuration(realm: Realm, report: StaticReport) { LiveOnline.values().forEach { key -> val duration = CashGameOptimalDurationCalculator.start(key.isLive) - duration?.let { - analyseOptimalDuration(realm, report, key, it) - } + analyseOptimalDuration(realm, report, key, duration) } } private fun analyseDefaultReport(realm: Realm, staticReport: StaticReport, result: Report) { + val nameSeparator = " " + for (stat in result.options.stats) { Timber.d("analyse stat: $stat for report: $staticReport") - result.max(stat)?.let { computedResults -> + // Get current performance + var query = performancesQuery(realm, staticReport, stat) - val customField: CustomField? = - (staticReport as? StaticReport.CustomFieldList)?.customField - var query = realm.where(Performance::class.java) - .equalTo("key", stat.uniqueIdentifier) - .equalTo("reportId", staticReport.uniqueIdentifier) + val customField: CustomField? = + (staticReport as? StaticReport.CustomFieldList)?.customField + customField?.let { + query = query.equalTo("customFieldId", it.id) + } + val currentPerf = query.findFirst() - customField?.let { - query = query.equalTo("customFieldId", it.id) - } - val currentPerf = query.findFirst() + // Store if necessary, delete if necessary + val bestComputedResults = result.max(stat) + bestComputedResults?.let { computedResults -> val performanceQuery = computedResults.group.query - val performanceName = performanceQuery.getName(this.context, " ") + val performanceName = performanceQuery.getName(this.context, nameSeparator) + + Timber.d("Best computed = $performanceName, ${computedResults.computedStat(Stat.NET_RESULT)?.value}") var storePerf = true currentPerf?.let { - currentPerf.name?.let { - if (computedResults.group.query.defaultName == it) { + currentPerf.name?.let { name -> + if (computedResults.group.query.getName(this.context, nameSeparator) == name) { storePerf = false } } - currentPerf.objectId?.let { - if (computedResults.group.query.objectId == it) { + currentPerf.objectId?.let { objectId -> + if (computedResults.group.query.objectId == objectId) { storePerf = false } } @@ -209,41 +234,61 @@ class ReportTask(private var whistleBlower: ReportWhistleBlower, var context: Co this.whistleBlower.notify(performance) } + } ?: run { // if there is no max but a now irrelevant Performance, we delete it + Timber.d("NO best computed value, current perf = $currentPerf ") + currentPerf?.let { perf -> + realm.executeTransaction { + Timber.d("Delete perf: stat = ${perf.stat}, report = ${perf.reportId}") + perf.deleteFromRealm() + } + } } } } - private fun analyseOptimalDuration(realm: Realm, staticReport: StaticReport, key: PerformanceKey, duration: Double) { + private fun analyseOptimalDuration(realm: Realm, staticReport: StaticReport, key: PerformanceKey, duration: Double?) { - var storePerf = true + val performance = performancesQuery(realm, staticReport, key).findFirst() - val performance = realm.where(Performance::class.java) - .equalTo("reportId", staticReport.uniqueIdentifier) - .equalTo("key", key.value) - .findFirst() + duration?.let { + var storePerf = true - val formattedDuration = (duration / 3600 / 1000).formattedHourlyDuration() - performance?.let { perf -> - if (perf.value == duration) { - storePerf = false + val formattedDuration = (duration / 3600 / 1000).formattedHourlyDuration() + performance?.let { perf -> + if (perf.value == duration) { + storePerf = false + } + + if (storePerf) { + realm.executeTransaction { + perf.name = formattedDuration + perf.value = duration + } + } } if (storePerf) { + val perf = Performance(staticReport, key, name = formattedDuration, value = duration) + realm.executeTransaction { it.copyToRealm(perf) } + this.whistleBlower.notify(perf) + } + + } ?: run { // no duration + performance?.let { perf -> realm.executeTransaction { - perf.name = formattedDuration - perf.value = duration + perf.deleteFromRealm() // delete if the perf exists } } } - if (storePerf) { - val perf = Performance(staticReport, key, name = formattedDuration, value = duration) - realm.executeTransaction { it.copyToRealm(perf) } - this.whistleBlower.notify(perf) - } + } + private fun performancesQuery(realm: Realm, staticReport: StaticReport, key: PerformanceKey): RealmQuery { + return realm.where(Performance::class.java) + .equalTo("reportId", staticReport.uniqueIdentifier) + .equalTo("key", key.value) } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt index 73364c13..8354a29c 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt @@ -95,6 +95,7 @@ sealed class QueryCondition : RowRepresentable { inline fun > distinct(): RealmResults? { FilterHelper.fieldNameForQueryType(S::class.java)?.let { val realm = Realm.getDefaultInstance() + realm.refresh() val distincts = when (T::class) { String::class, Int::class -> realm.where().distinct(it).findAll().sort(it, Sort.ASCENDING) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt index 5ca73359..59fe47b9 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt @@ -103,6 +103,11 @@ class HomeActivity : BaseActivity(), NewPerformanceListener { } + override fun onDestroy() { + super.onDestroy() + this.paApplication.reportWhistleBlower?.removeListener(this) + } + private fun observeRealmObjects() { val realm = getRealm() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt index a01560de..89bb5374 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt @@ -6,6 +6,7 @@ import android.view.View import android.view.ViewGroup import android.widget.TextView import com.google.android.material.snackbar.Snackbar +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async import kotlinx.coroutines.launch @@ -21,9 +22,6 @@ import java.util.* class ImportFragment : RealmFragment(), ImportDelegate { -// val coroutineContext: CoroutineContext -// get() = Dispatchers.Main - private lateinit var filePath: String private lateinit var inputStream: InputStream private lateinit var importer: CSVImporter @@ -86,15 +84,14 @@ class ImportFragment : RealmFragment(), ImportDelegate { private fun startImport() { -// var shouldDismissActivity = false + this.parentActivity?.paApplication?.reportWhistleBlower?.pause() this.importer = CSVImporter(inputStream) this.importer.delegate = this + CoroutineScope(coroutineContext).launch { - GlobalScope.launch(coroutineContext) { - - val test = GlobalScope.async { + val coroutine = GlobalScope.async { val s = Date() Timber.d(">>> Start Import...") @@ -105,7 +102,7 @@ class ImportFragment : RealmFragment(), ImportDelegate { Timber.d(">>> Import ended in $duration seconds") } - test.await() + coroutine.await() val exceptionMessage = exceptions.firstOrNull()?.message if (exceptionMessage != null && view != null) { @@ -139,12 +136,11 @@ class ImportFragment : RealmFragment(), ImportDelegate { } private fun importDidFinish() { - binding.save.isEnabled = true - } private fun end() { + this.parentActivity?.paApplication?.reportWhistleBlower?.resume() activity?.finish() } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt index a76e3706..02ed5483 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt @@ -190,6 +190,11 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc } + override fun onDestroy() { + super.onDestroy() + this.paApplication?.reportWhistleBlower?.removeListener(this) + } + // Rows private fun updateRows() { @@ -207,15 +212,16 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc private fun addStaticReportRows() { - val sections = buildReportSections() - for (section in sections) { + context?.let { context -> + val sections = buildReportSections() + for (section in sections) { - adapterRows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, title = section.getDisplayName(requireContext()))) - for (performance in section.performances) { - adapterRows.add(performance) + adapterRows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, title = section.getDisplayName(context))) + for (performance in section.performances) { + adapterRows.add(performance) + } } } - } private fun buildReportSections(): List { @@ -330,8 +336,7 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc override fun newBestPerformanceHandler() { Timber.d("newBestPerformanceHandler called") - requireActivity().runOnUiThread { -// this.updateRows() + activity?.runOnUiThread { this.dataListAdapter.notifyDataSetChanged() } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/StaticReport.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/StaticReport.kt index 5d0fab35..eaede814 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/StaticReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/StaticReport.kt @@ -17,7 +17,7 @@ import net.pokeranalytics.android.util.enumerations.IntIdentifiable */ sealed class StaticReport(override var uniqueIdentifier: Int) : RowRepresentable, IntIdentifiable { object General : StaticReport(1) - object Blinds : StaticReport(2) + object Stakes : StaticReport(2) object TournamentBuyin : StaticReport(3) object DayOfWeek : StaticReport(4) object Location : StaticReport(5) @@ -35,7 +35,7 @@ sealed class StaticReport(override var uniqueIdentifier: Int) : RowRepresentable return when (reportIdentifier) { 1 -> General - 2 -> Blinds + 2 -> Stakes 3 -> TournamentBuyin 4 -> DayOfWeek 5 -> Location @@ -56,8 +56,8 @@ sealed class StaticReport(override var uniqueIdentifier: Int) : RowRepresentable } -// val basicReports: Set = setOf(Duration) - val basicReports: Set = setOf(General, Blinds, TournamentBuyin, +// val basicReports: Set = setOf(Stakes, TableSize) + val basicReports: Set = setOf(General, Stakes, TournamentBuyin, DayOfWeek, Location, TournamentType, Game, TableSize, Duration, OptimalDuration) } @@ -71,7 +71,7 @@ sealed class StaticReport(override var uniqueIdentifier: Int) : RowRepresentable override val resId: Int? get() { return when (this) { - Blinds -> R.string.blinds + Stakes -> R.string.stakes TournamentBuyin -> R.string.buyin DayOfWeek -> R.string.day_of_the_week General -> R.string.general @@ -91,7 +91,7 @@ sealed class StaticReport(override var uniqueIdentifier: Int) : RowRepresentable val criteria: List get() { return when (this) { - Blinds -> listOf(Criteria.Stakes) + Stakes -> listOf(Criteria.Stakes) TournamentBuyin -> listOf(Criteria.TournamentFees) DayOfWeek -> listOf(Criteria.DaysOfWeek) General -> listOf(Criteria.BankrollTypes, Criteria.SessionTypes)