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 47468433..44890270 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt @@ -4,7 +4,8 @@ import android.content.Context import android.os.CountDownTimer import io.realm.Realm import io.realm.RealmResults -import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import net.pokeranalytics.android.model.realm.CustomField import net.pokeranalytics.android.model.realm.Performance @@ -12,6 +13,7 @@ import net.pokeranalytics.android.model.realm.Result import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.view.rows.StaticReport import timber.log.Timber +import kotlin.coroutines.CoroutineContext interface NewPerformanceListener { fun newBestPerformanceHandler() @@ -24,39 +26,24 @@ class ReportWhistleBlower(var context: Context) { var timer: CountDownTimer? = null -// private lateinit var realm: Realm + private var currentTask: ReportTask? = null private val currentNotifications: MutableList = mutableListOf() private val listeners: MutableList = mutableListOf() -// companion object { -// -// @Volatile private var INSTANCE: ReportWhistleBlower? = null -// -// fun getInstance(context: Context, realm: Realm): ReportWhistleBlower = -// INSTANCE ?: synchronized(this) { -// INSTANCE ?: newInstance(context, realm).also { INSTANCE = it } -// } -// -// private fun newInstance(context: Context, realm: Realm): ReportWhistleBlower { -// return ReportWhistleBlower(context, realm) -// } -// -// } - init { val realm = Realm.getDefaultInstance() this.sessions = realm.where(Session::class.java).findAll() this.sessions?.addChangeListener { _ -> - launchReports() + requestReportLaunch() } this.results = realm.where(Result::class.java).findAll() this.results?.addChangeListener { _ -> - launchReports() + requestReportLaunch() } } @@ -69,10 +56,10 @@ class ReportWhistleBlower(var context: Context) { synchronized(this) { this.timer?.cancel() - this.timer = object : CountDownTimer(500L, 0L) { + this.timer = object : CountDownTimer(500L, 500L) { override fun onTick(p0: Long) { } override fun onFinish() { - launchReports() + launchReport() timer = null } } @@ -81,49 +68,83 @@ class ReportWhistleBlower(var context: Context) { } - private fun launchReports() { + fun launchReport() { + Timber.d(">>> Launch report") - // Basic - for (basicReport in StaticReport.basicReports) { - launchReport(basicReport) - } + this.currentTask?.cancel() + val reportTask = ReportTask(this, this.context) + this.currentTask = reportTask + reportTask.start() + } - val realm = Realm.getDefaultInstance() + fun has(performanceId: String): Boolean { + return this.currentNotifications.contains(performanceId) + } - // CustomField - val customFields = realm.where(CustomField::class.java) - .equalTo("type", CustomField.Type.LIST.uniqueIdentifier).findAll() - for (customField in customFields) { - launchReport(StaticReport.CustomFieldList(customField)) - } + fun notify(performance: Performance) { + this.currentNotifications.add(performance.id) + for (listener in this.listeners) { + listener.newBestPerformanceHandler() + } } - private fun launchReport(report: StaticReport) { +} - Timber.d(">>> launch report = $report") +class ReportTask(private var whistleBlower: ReportWhistleBlower, var context: Context) { - val options = Calculator.Options( - stats = report.stats, - criterias = report.criteria - ) + private var cancelled = false - this.launchReportWithOptions(report, options) + private val coroutineContext: CoroutineContext + get() = Dispatchers.Main + fun start() { + launchReports() } - private fun launchReportWithOptions(staticReport: StaticReport, options: Calculator.Options) { + fun cancel() { + this.cancelled = true + } - GlobalScope.launch { + private fun launchReports() { + CoroutineScope(coroutineContext).launch { val realm = Realm.getDefaultInstance() -// realm.refresh() - val result = Calculator.computeStats(realm, options = options) - analyseReport(realm, staticReport, result) + // Basic + for (basicReport in StaticReport.basicReports) { + if (cancelled) { + break + } + launchReport(realm, basicReport) + } + // CustomField + val customFields = realm.where(CustomField::class.java) + .equalTo("type", CustomField.Type.LIST.uniqueIdentifier).findAll() + for (customField in customFields) { + if (cancelled) { + break + } + launchReport(realm, StaticReport.CustomFieldList(customField)) + } realm.close() } + + } + + private fun launchReport(realm: Realm, report: StaticReport) { + + Timber.d(">>> launch report = $report") + + val options = Calculator.Options( + stats = report.stats, + criterias = report.criteria + ) + + val result = Calculator.computeStats(realm, options = options) + analyseReport(realm, report, result) + } private fun analyseReport(realm: Realm, staticReport: StaticReport, result: Report) { @@ -174,7 +195,7 @@ class ReportWhistleBlower(var context: Context) { currentPerf.objectId = computedResults.group.query.objectId currentPerf.customFieldId = customField?.id } - this.notify(currentPerf) + this.whistleBlower.notify(currentPerf) } } @@ -189,7 +210,7 @@ class ReportWhistleBlower(var context: Context) { null ) realm.executeTransaction { it.copyToRealm(performance) } - this.notify(performance) + this.whistleBlower.notify(performance) } } @@ -202,16 +223,4 @@ class ReportWhistleBlower(var context: Context) { } - private fun notify(performance: Performance) { - - this.currentNotifications.add(performance.id) - for (listener in this.listeners) { - listener.newBestPerformanceHandler() - } - } - - fun has(performanceId: String): Boolean { - return this.currentNotifications.contains(performanceId) - } - } \ No newline at end of file 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 381af597..bdcbea8a 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 @@ -11,8 +11,8 @@ import android.widget.Toast import androidx.recyclerview.widget.LinearLayoutManager import io.realm.Realm import io.realm.RealmResults +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import net.pokeranalytics.android.R @@ -117,10 +117,12 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc } else if (requestCode == RequestCode.DEFAULT.value && resultCode == Activity.RESULT_OK) { val itemToDeleteId = data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName) itemToDeleteId?.let { id -> - GlobalScope.launch(Dispatchers.Main) { + + CoroutineScope(coroutineContext).launch { delay(300) deleteItem(dataListAdapter, reportSetups, id) } + } } @@ -161,7 +163,7 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc ReportCreationActivity.newInstanceForResult(this, requireContext()) } - this.paApplication.reportWhistleBlower?.addListener(this) + this.paApplication?.reportWhistleBlower?.addListener(this) } @@ -199,7 +201,7 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc for (performance in performances) { val report = performance.toStaticReport(getRealm()) - val badge = this.paApplication.reportWhistleBlower?.has(performance.id) ?: false + val badge = this.paApplication?.reportWhistleBlower?.has(performance.id) ?: false val reportRow = PerformanceRow(performance, report, badge) sections.firstOrNull { it.report == report }?.let { section -> @@ -268,7 +270,7 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc showLoader() - GlobalScope.launch { + CoroutineScope(coroutineContext).launch { val startDate = Date() val realm = Realm.getDefaultInstance() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt index 1ca1d073..66dd9b9e 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt @@ -62,9 +62,8 @@ abstract class BaseFragment : Fragment() { CrashLogging.log("$this.localClassName onActivityCreated") } - - val paApplication: PokerAnalyticsApplication - get() { return (this.requireActivity() as BaseActivity).paApplication } + val paApplication: PokerAnalyticsApplication? + get() { return (this.activity as? BaseActivity)?.paApplication } /** * Method called when the activity override onBackPressed and send the information to the fragment 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 bfc2d752..7b9a647a 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 @@ -56,8 +56,8 @@ sealed class StaticReport(override var uniqueIdentifier: Int) : RowRepresentable } - val basicReports: Set = setOf(Blinds) // setOf(General, Blinds, TournamentBuyin, -// DayOfWeek, Location, TournamentType, Game, TableSize, Duration, OptimalDuration) + val basicReports: Set = setOf(General, Blinds, TournamentBuyin, + DayOfWeek, Location, TournamentType, Game, TableSize, Duration, OptimalDuration) } diff --git a/app/src/main/res/layout/fragment_reports.xml b/app/src/main/res/layout/fragment_reports.xml index 761f3dba..29f6aecb 100644 --- a/app/src/main/res/layout/fragment_reports.xml +++ b/app/src/main/res/layout/fragment_reports.xml @@ -30,6 +30,7 @@ android:layout_width="0dp" android:layout_height="0dp" android:paddingBottom="72dp" + android:clipToPadding="false" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"