|
|
|
|
@ -7,14 +7,17 @@ import android.view.ViewGroup |
|
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager |
|
|
|
|
import com.google.android.material.tabs.TabLayout |
|
|
|
|
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 |
|
|
|
|
import net.pokeranalytics.android.calculus.ComputedResults |
|
|
|
|
import net.pokeranalytics.android.calculus.Stat |
|
|
|
|
import net.pokeranalytics.android.databinding.FragmentCalendarBinding |
|
|
|
|
import net.pokeranalytics.android.exceptions.PAIllegalStateException |
|
|
|
|
import net.pokeranalytics.android.model.Criteria |
|
|
|
|
import net.pokeranalytics.android.model.combined |
|
|
|
|
import net.pokeranalytics.android.model.filter.QueryCondition |
|
|
|
|
@ -40,7 +43,7 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable |
|
|
|
|
RowRepresentableDelegate, RealmAsyncListener { |
|
|
|
|
|
|
|
|
|
enum class TimeFilter { |
|
|
|
|
MONTH, YEAR |
|
|
|
|
ALL, MONTH, YEAR |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
companion object { |
|
|
|
|
@ -58,18 +61,16 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable |
|
|
|
|
|
|
|
|
|
private lateinit var calendarAdapter: RowRepresentableAdapter |
|
|
|
|
|
|
|
|
|
// override val coroutineContext: CoroutineContext |
|
|
|
|
// get() = Dispatchers.Main |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private var rows: ArrayList<CustomizableRowRepresentable> = ArrayList() |
|
|
|
|
|
|
|
|
|
private var allComputedResults: ComputedResults? = null |
|
|
|
|
private var sortedMonthlyReports: SortedMap<Date, ComputedResults> = HashMap<Date, ComputedResults>().toSortedMap() |
|
|
|
|
private var sortedYearlyReports: SortedMap<Date, ComputedResults> = HashMap<Date, ComputedResults>().toSortedMap() |
|
|
|
|
|
|
|
|
|
private var datesForRows: HashMap<CustomizableRowRepresentable, Date> = HashMap() |
|
|
|
|
|
|
|
|
|
private var sessionTypeCondition: QueryCondition? = null |
|
|
|
|
private var currentTimeFilter: TimeFilter = |
|
|
|
|
TimeFilter.MONTH |
|
|
|
|
private var currentTimeFilter: TimeFilter = TimeFilter.MONTH |
|
|
|
|
private var currentStat = Stat.NET_RESULT |
|
|
|
|
|
|
|
|
|
private var _binding: FragmentCalendarBinding? = null |
|
|
|
|
@ -123,10 +124,16 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable |
|
|
|
|
CalendarDetailsActivity.newInstance(requireContext(), it, sessionTypeCondition, date?.getDateYear()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
TimeFilter.ALL -> { |
|
|
|
|
this.allComputedResults?.let { |
|
|
|
|
CalendarDetailsActivity.newInstance(requireContext(), it, sessionTypeCondition, getString( |
|
|
|
|
R.string.all)) |
|
|
|
|
} ?: throw PAIllegalStateException("all results required to display details but null") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// override val observedEntities: List<Class<out RealmModel>> = listOf(ComputableResult::class.java) |
|
|
|
|
override val observedEntities: List<Class<out RealmModel>> = listOf(ComputableResult::class.java) |
|
|
|
|
|
|
|
|
|
// override fun entitiesChanged(clazz: Class<out RealmModel>, results: RealmResults<out RealmModel>) { |
|
|
|
|
// launchAsyncStatComputation() |
|
|
|
|
@ -206,27 +213,33 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
binding.filterTimeAll?.setOnCheckedChangeListener { _, isChecked -> |
|
|
|
|
selectTimeFilter(TimeFilter.ALL, isChecked) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Manage time queryWith |
|
|
|
|
binding.filterTimeMonth.setOnCheckedChangeListener { _, isChecked -> |
|
|
|
|
if (isChecked) { |
|
|
|
|
currentTimeFilter = |
|
|
|
|
TimeFilter.MONTH |
|
|
|
|
binding.filterTimeYear.isChecked = false |
|
|
|
|
displayData() |
|
|
|
|
} else if (currentTimeFilter == TimeFilter.MONTH) { |
|
|
|
|
binding.filterTimeMonth.isChecked = true |
|
|
|
|
} |
|
|
|
|
selectTimeFilter(TimeFilter.MONTH, isChecked) |
|
|
|
|
// if (isChecked) { |
|
|
|
|
// currentTimeFilter = |
|
|
|
|
// TimeFilter.MONTH |
|
|
|
|
// binding.filterTimeYear.isChecked = false |
|
|
|
|
// displayData() |
|
|
|
|
// } else if (currentTimeFilter == TimeFilter.MONTH) { |
|
|
|
|
// binding.filterTimeMonth.isChecked = true |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
binding.filterTimeYear.setOnCheckedChangeListener { _, isChecked -> |
|
|
|
|
if (isChecked) { |
|
|
|
|
currentTimeFilter = |
|
|
|
|
TimeFilter.YEAR |
|
|
|
|
binding.filterTimeMonth.isChecked = false |
|
|
|
|
displayData() |
|
|
|
|
} else if (currentTimeFilter == TimeFilter.YEAR) { |
|
|
|
|
binding.filterTimeYear.isChecked = true |
|
|
|
|
} |
|
|
|
|
selectTimeFilter(TimeFilter.YEAR, isChecked) |
|
|
|
|
// if (isChecked) { |
|
|
|
|
// currentTimeFilter = |
|
|
|
|
// TimeFilter.YEAR |
|
|
|
|
// binding.filterTimeMonth.isChecked = false |
|
|
|
|
// displayData() |
|
|
|
|
// } else if (currentTimeFilter == TimeFilter.YEAR) { |
|
|
|
|
// binding.filterTimeYear.isChecked = true |
|
|
|
|
// } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
val viewManager = LinearLayoutManager(requireContext()) |
|
|
|
|
@ -240,6 +253,29 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun selectTimeFilter(timeFilter: TimeFilter, isChecked: Boolean) { |
|
|
|
|
|
|
|
|
|
if (isChecked) { |
|
|
|
|
currentTimeFilter = timeFilter |
|
|
|
|
TimeFilter.values().forEach { tf -> |
|
|
|
|
if (tf != timeFilter) { |
|
|
|
|
when (tf) { |
|
|
|
|
TimeFilter.ALL -> binding.filterTimeAll?.isChecked = false |
|
|
|
|
TimeFilter.MONTH -> binding.filterTimeMonth.isChecked = false |
|
|
|
|
TimeFilter.YEAR -> binding.filterTimeYear.isChecked = false |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
displayData() |
|
|
|
|
} else if (currentTimeFilter == timeFilter) { |
|
|
|
|
when (timeFilter) { |
|
|
|
|
TimeFilter.ALL -> binding.filterTimeAll?.isChecked = true |
|
|
|
|
TimeFilter.MONTH -> binding.filterTimeMonth.isChecked = true |
|
|
|
|
TimeFilter.YEAR -> binding.filterTimeYear.isChecked = true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Asynchronously Launch stat computation |
|
|
|
|
*/ |
|
|
|
|
@ -270,15 +306,19 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable |
|
|
|
|
|
|
|
|
|
val startDate = Date() |
|
|
|
|
|
|
|
|
|
val monthlyReports: HashMap<Date, ComputedResults> = HashMap() |
|
|
|
|
val yearlyReports: HashMap<Date, ComputedResults> = HashMap() |
|
|
|
|
|
|
|
|
|
val requiredStats: List<Stat> = |
|
|
|
|
listOf(Stat.LOCATIONS_PLAYED, Stat.LONGEST_STREAKS, Stat.DAYS_PLAYED, Stat.STANDARD_DEVIATION_HOURLY) |
|
|
|
|
|
|
|
|
|
// Compute data per AnyYear and AnyMonthOfYear |
|
|
|
|
// All |
|
|
|
|
val allOptions = Calculator.Options( |
|
|
|
|
progressValues = Calculator.Options.ProgressValues.STANDARD, |
|
|
|
|
stats = requiredStats, |
|
|
|
|
) |
|
|
|
|
val allReport = Calculator.computeStats(realm, options = allOptions) |
|
|
|
|
this.allComputedResults = allReport.results.first() |
|
|
|
|
|
|
|
|
|
// println(">>>> ${Criteria.MonthsOfYear.queryConditions.map { it.id }}") |
|
|
|
|
// Month |
|
|
|
|
val monthlyReports: HashMap<Date, ComputedResults> = HashMap() |
|
|
|
|
|
|
|
|
|
val monthlyQueries = when (sessionTypeCondition) { |
|
|
|
|
QueryCondition.IsCash -> listOf(Criteria.AllMonthsUpToNow, Criteria.Cash).combined() |
|
|
|
|
@ -313,7 +353,9 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable |
|
|
|
|
|
|
|
|
|
calendar.time = Date().startOfYear() |
|
|
|
|
|
|
|
|
|
// Compute data per AnyYear |
|
|
|
|
// Year |
|
|
|
|
val yearlyReports: HashMap<Date, ComputedResults> = HashMap() |
|
|
|
|
|
|
|
|
|
val yearConditions = when (sessionTypeCondition) { |
|
|
|
|
QueryCondition.IsCash -> listOf(Criteria.Years, Criteria.Cash).combined() |
|
|
|
|
QueryCondition.IsTournament -> listOf(Criteria.Years, Criteria.Tournament).combined() |
|
|
|
|
@ -370,9 +412,24 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable |
|
|
|
|
datesForRows.clear() |
|
|
|
|
rows.clear() |
|
|
|
|
|
|
|
|
|
when (currentTimeFilter) { |
|
|
|
|
// Create all rows |
|
|
|
|
when (this.currentTimeFilter) { |
|
|
|
|
|
|
|
|
|
// All |
|
|
|
|
TimeFilter.ALL -> { |
|
|
|
|
this.allComputedResults?.computedStat(currentStat)?.let { computedStat -> |
|
|
|
|
val row = CustomizableRowRepresentable( |
|
|
|
|
customViewType = RowViewType.TITLE_VALUE_ARROW, |
|
|
|
|
title = getString(R.string.all), |
|
|
|
|
valueTextFormat = computedStat.textFormat, |
|
|
|
|
isSelectable = true |
|
|
|
|
) |
|
|
|
|
rows.add(row) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Create monthly reports |
|
|
|
|
// MONTH |
|
|
|
|
TimeFilter.MONTH -> { |
|
|
|
|
val years: ArrayList<String> = ArrayList() |
|
|
|
|
sortedMonthlyReports.keys.forEach { date -> |
|
|
|
|
@ -401,7 +458,7 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Create yearly reports |
|
|
|
|
// YEAR |
|
|
|
|
TimeFilter.YEAR -> { |
|
|
|
|
sortedYearlyReports.keys.forEach { date -> |
|
|
|
|
sortedYearlyReports[date]?.computedStat(currentStat)?.let { computedStat -> |
|
|
|
|
@ -430,15 +487,8 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
override fun asyncListenedEntityChange(realm: Realm) { |
|
|
|
|
|
|
|
|
|
launchAsyncStatComputation() |
|
|
|
|
|
|
|
|
|
// Timber.d("asyncListenedEntityChange") |
|
|
|
|
// launchStatComputation(realm) |
|
|
|
|
// |
|
|
|
|
// activity?.runOnUiThread { |
|
|
|
|
// displayData() |
|
|
|
|
// } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|