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 20c76063..c7fb7fd0 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -87,7 +87,8 @@ class Calculator { fun computeStatsWithEvolutionByAggregationType( realm: Realm, group: ComputableGroup, - aggregationType: AggregationType + aggregationType: AggregationType, + stats: List? = null ): Report { val options = Options(evolutionValues = Options.EvolutionValues.STANDARD) @@ -95,6 +96,10 @@ class Calculator { options.evolutionValues = Options.EvolutionValues.TIMED } + stats?.let { + options.displayedStats = stats + } + return when (aggregationType) { AggregationType.SESSION, AggregationType.DURATION -> this.computeGroups(realm, listOf(group), options) AggregationType.MONTH -> { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/StatisticDetailsActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/StatisticDetailsActivity.kt index e7fa885e..a93369c5 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/StatisticDetailsActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/StatisticDetailsActivity.kt @@ -3,12 +3,14 @@ package net.pokeranalytics.android.ui.activity import android.content.Context import android.content.Intent import android.os.Bundle +import com.google.android.libraries.places.internal.it import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.ComputableGroup import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.fragment.GraphParameters +import net.pokeranalytics.android.ui.fragment.StatisticDetailsFragment class StatisticDetailsActivity : PokerAnalyticsActivity() { @@ -47,6 +49,15 @@ class StatisticDetailsActivity : PokerAnalyticsActivity() { */ private fun initUI() { + val fragmentTransaction = supportFragmentManager.beginTransaction() + val statisticDetailsFragment = StatisticDetailsFragment() + fragmentTransaction.add(R.id.statisticDetailsContainer, statisticDetailsFragment) + fragmentTransaction.commit() + + parameters?.let { + statisticDetailsFragment.setData(it.stat, it.computableGroup, it.report) + } + } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt index e0314d6a..7cd9184d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt @@ -4,33 +4,27 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.core.view.isVisible import com.github.mikephil.charting.charts.BarChart import com.github.mikephil.charting.charts.BarLineChartBase import com.github.mikephil.charting.charts.LineChart import com.github.mikephil.charting.data.* import com.github.mikephil.charting.highlight.Highlight import com.github.mikephil.charting.listener.OnChartValueSelectedListener -import com.google.android.material.chip.Chip -import com.google.android.material.chip.ChipGroup -import io.realm.Realm import kotlinx.android.synthetic.main.fragment_evograph.* -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.* import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity -import net.pokeranalytics.android.ui.extensions.ChipGroupExtension -import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.graph.PALineDataSet import net.pokeranalytics.android.ui.graph.setStyle import net.pokeranalytics.android.ui.view.LegendView import timber.log.Timber -import java.util.* import kotlin.coroutines.CoroutineContext -class GraphParameters(var stat: Stat, var computableGroup: ComputableGroup, var report: Report) { +class GraphParameters(var stat: Stat, var computableGroup: ComputableGroup, var report: Report) { } class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, CoroutineScope { @@ -49,15 +43,12 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co } private lateinit var parentActivity: PokerAnalyticsActivity - private lateinit var computableGroup: ComputableGroup private lateinit var selectedReport: Report private lateinit var legendView: LegendView private lateinit var chartView: BarLineChartBase<*> private var stat: Stat = Stat.NET_RESULT - private var reports: MutableMap = hashMapOf() - private var aggregationTypes: List = listOf() - private var displayAggregationChoices: Boolean = true + private var aggregationType: AggregationType = AggregationType.SESSION override val coroutineContext: CoroutineContext get() = Dispatchers.Main @@ -70,26 +61,41 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initUI() + loadGraph() } - /** - * Set data - */ - fun setData(stat: Stat, group: ComputableGroup, report: Report, displayAggregationChoices: Boolean = true) { - this.stat = report.options.displayedStats.first() - this.computableGroup = group + // OnChartValueSelectedListener + override fun onNothingSelected() { + // nothing to do + } - this.aggregationTypes = stat.aggregationTypes - this.reports[this.aggregationTypes.first()] = report - this.selectedReport = report - this.displayAggregationChoices = displayAggregationChoices + override fun onValueSelected(e: Entry?, h: Highlight?) { + e?.let { entry -> + val statEntry = when (entry.data) { + is ObjectIdentifier -> { + val identifier = entry.data as ObjectIdentifier + getRealm().where(identifier.clazz).equalTo("id", identifier.id).findAll().firstOrNull() + } + is StatEntry -> entry.data as StatEntry? + else -> null + } + statEntry?.let { + val formattedDate = it.entryTitle + val entryValue = it.formattedValue(this.stat, requireContext()) + val totalStatValue = this.stat.format(entry.y.toDouble(), currency = null, context = requireContext()) + + this.legendView.setItemData(this.stat, formattedDate, entryValue, totalStatValue) + } + } } + /** * Init UI */ private fun initUI() { + Timber.d("initUI") parentActivity = activity as PokerAnalyticsActivity parentActivity.title = stat.localizedTitle(requireContext()) @@ -104,80 +110,20 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co this.chartView.setStyle(false, requireContext()) this.chartContainer.addView(this.chartView) - - this.loadGraph(this.aggregationTypes.first(), this.selectedReport) - - this.aggregationTypes.forEachIndexed { index, type -> - val chip = Chip(requireContext()) - chip.id = index - chip.text = requireContext().getString(type.resId) - chip.chipStartPadding = 8f.px - chip.chipEndPadding = 8f.px - this.chipGroup.addView(chip) - } - - this.chipGroup.isVisible = displayAggregationChoices - this.chipGroup.check(0) - - this.chipGroup.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() { - override fun onCheckedChanged(group: ChipGroup, checkedId: Int) { - super.onCheckedChanged(group, checkedId) - val aggregationType = aggregationTypes[checkedId] - - reports[aggregationType]?.let { - loadGraph(aggregationType, it) - } ?: run { - launchStatComputation(aggregationType) - } - - } - }) - } - private fun launchStatComputation(aggregationType: AggregationType) { - - GlobalScope.launch(coroutineContext) { - - var r: Report? = null - val test = GlobalScope.async { - val s = Date() - Timber.d(">>> start...") - - val realm = Realm.getDefaultInstance() - - val report = - Calculator.computeStatsWithEvolutionByAggregationType(realm, computableGroup, aggregationType) - reports[aggregationType] = report - - r = report - - realm.close() - - val e = Date() - val duration = (e.time - s.time) / 1000.0 - Timber.d(">>> ended in $duration seconds") - - } - test.await() - - if (!isDetached) { - r?.let { - loadGraph(aggregationType, it) - } - } - } - - } - - fun loadGraph(aggregationType: AggregationType, report: Report) { + /** + * Load graph + */ + private fun loadGraph() { + Timber.d("loadGraph") val graphEntries = when (aggregationType) { - AggregationType.SESSION, AggregationType.DURATION -> report.results.firstOrNull()?.defaultStatEntries(stat) + AggregationType.SESSION, AggregationType.DURATION -> selectedReport.results.firstOrNull()?.defaultStatEntries(stat) AggregationType.MONTH, AggregationType.YEAR -> { when (this.stat) { - Stat.NUMBER_OF_GAMES, Stat.NUMBER_OF_SETS -> report.barEntries(this.stat) - else -> report.lineEntries(this.stat) + Stat.NUMBER_OF_GAMES, Stat.NUMBER_OF_SETS -> selectedReport.barEntries(this.stat) + else -> selectedReport.lineEntries(this.stat) } } } @@ -216,32 +162,18 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co } - // OnChartValueSelectedListener - - override fun onNothingSelected() { - // nothing to do - } - - override fun onValueSelected(e: Entry?, h: Highlight?) { - e?.let { entry -> - - val statEntry = when (entry.data) { - is ObjectIdentifier -> { - val identifier = entry.data as ObjectIdentifier - getRealm().where(identifier.clazz).equalTo("id", identifier.id).findAll().firstOrNull() - } - is StatEntry -> entry.data as StatEntry? - else -> null - } - - statEntry?.let { + /** + * Set data + */ + fun setData(report: Report, aggregationType: AggregationType) { + Timber.d("setData") - val formattedDate = it.entryTitle - val entryValue = it.formattedValue(this.stat, requireContext()) - val totalStatValue = this.stat.format(entry.y.toDouble(), currency = null, context = requireContext()) + this.selectedReport = report + this.aggregationType = aggregationType + this.stat = report.options.displayedStats.first() - this.legendView.setItemData(this.stat, formattedDate, entryValue, totalStatValue) - } + if (isAdded && !isDetached) { + loadGraph() } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticDetailsFragment.kt index 16e9c3aa..efb19b62 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticDetailsFragment.kt @@ -6,13 +6,25 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.github.mikephil.charting.data.Entry +import androidx.core.view.isVisible +import com.google.android.material.chip.Chip +import com.google.android.material.chip.ChipGroup +import io.realm.Realm import kotlinx.android.synthetic.main.fragment_statistic_details.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import net.pokeranalytics.android.R -import net.pokeranalytics.android.calculus.Stat -import net.pokeranalytics.android.ui.activity.StatisticDetailsActivity +import net.pokeranalytics.android.calculus.* +import net.pokeranalytics.android.ui.activity.StatisticDetailsActivity.Companion.displayAggregationChoices import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity +import net.pokeranalytics.android.ui.extensions.ChipGroupExtension +import net.pokeranalytics.android.ui.extensions.hideWithAnimation +import net.pokeranalytics.android.ui.extensions.px +import net.pokeranalytics.android.ui.extensions.showWithAnimation import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment +import timber.log.Timber +import java.util.* class StatisticDetailsFragment : PokerAnalyticsFragment() { @@ -24,9 +36,12 @@ class StatisticDetailsFragment : PokerAnalyticsFragment() { } private lateinit var parentActivity: PokerAnalyticsActivity + private lateinit var computableGroup: ComputableGroup + private lateinit var graphFragment: GraphFragment + private lateinit var selectedReport: Report + private var reports: MutableMap = hashMapOf() private var stat: Stat = Stat.NET_RESULT - private var entries: List = ArrayList() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_statistic_details, container, false) @@ -41,6 +56,7 @@ class StatisticDetailsFragment : PokerAnalyticsFragment() { * Init UI */ private fun initUI() { + Timber.d("initUI") parentActivity = activity as PokerAnalyticsActivity @@ -51,29 +67,120 @@ class StatisticDetailsFragment : PokerAnalyticsFragment() { parentActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true) setHasOptionsMenu(true) - toolbar.title = stat.localizedTitle(requireContext()) val fragmentManager = parentActivity.supportFragmentManager val fragmentTransaction = fragmentManager.beginTransaction() - val fragment = GraphFragment() + graphFragment = GraphFragment() - fragmentTransaction.add(R.id.container, fragment) + fragmentTransaction.add(R.id.graphContainer, graphFragment) fragmentTransaction.commit() + + stat.aggregationTypes.firstOrNull()?.let { aggregationType -> + reports[aggregationType]?.let { report -> + graphFragment.setData(report, aggregationType) + } + } + + toolbar.title = stat.localizedTitle(requireContext()) + val aggregationTypes = stat.aggregationTypes + + aggregationTypes.forEachIndexed { index, type -> + val chip = Chip(requireContext()) + chip.id = index + chip.text = requireContext().getString(type.resId) + chip.chipStartPadding = 8f.px + chip.chipEndPadding = 8f.px + this.chipGroup.addView(chip) + } + + this.chipGroup.isVisible = displayAggregationChoices + this.chipGroup.check(0) + + this.chipGroup.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() { + override fun onCheckedChanged(group: ChipGroup, checkedId: Int) { + super.onCheckedChanged(group, checkedId) + val aggregationType = aggregationTypes[checkedId] + + reports[aggregationType]?.let { report -> + graphFragment.setData(report, aggregationType) + } ?: run { + launchStatComputation(aggregationType) + } + + } + }) + + /* StatisticDetailsActivity.parameters?.let { - fragment.setData(it.stat, it.computableGroup, it.report, StatisticDetailsActivity.displayAggregationChoices) + + //TODO: Set in the function setData + //stat = it.stat + + graphFragment.setData(report, aggregationType) + + //launchStatComputation(aggregationType) + //graphFragment.setData(it.stat, it.computableGroup, it.report, StatisticDetailsActivity.displayAggregationChoices) StatisticDetailsActivity.parameters = null } ?: run { throw Exception("Missing graph parameters") } + */ } + /** + * Launch stat computation + */ + private fun launchStatComputation(aggregationType: AggregationType) { + + graphContainer.hideWithAnimation() + progressBar.showWithAnimation() + + //TODO: Create loader here + Timber.d("launchStatComputation: $aggregationType") + + GlobalScope.launch { + + val s = Date() + Timber.d(">>> start...") + + val realm = Realm.getDefaultInstance() + + val requiredStats: List = listOf(stat) + + val report = Calculator.computeStatsWithEvolutionByAggregationType(realm, computableGroup, aggregationType, requiredStats) + reports[aggregationType] = report + + realm.close() + + val e = Date() + val duration = (e.time - s.time) / 1000.0 + Timber.d(">>> ended in $duration seconds") + + launch(Dispatchers.Main) { + graphFragment.setData(report, aggregationType) + progressBar.hideWithAnimation() + graphContainer.showWithAnimation() + } + + } + + } + + /** * Set data */ - fun setData(stat: Stat, entries: List) { + fun setData(stat: Stat, computableGroup: ComputableGroup, report: Report) { + Timber.d("setData") this.stat = stat - this.entries = entries + this.computableGroup = computableGroup + this.selectedReport = report + + stat.aggregationTypes.firstOrNull()?.let { + reports[it] = report + } + } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt index 0ffd0696..192c35e3 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt @@ -246,8 +246,9 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc val realm = Realm.getDefaultInstance() + val requiredStats: List = listOf(stat) val aggregationType = stat.aggregationTypes.first() - report = Calculator.computeStatsWithEvolutionByAggregationType(realm, computableGroup, aggregationType) + report = Calculator.computeStatsWithEvolutionByAggregationType(realm, computableGroup, aggregationType, requiredStats) realm.close() diff --git a/app/src/main/res/layout/activity_statistic_details.xml b/app/src/main/res/layout/activity_statistic_details.xml index 62d1cb20..401d6f55 100644 --- a/app/src/main/res/layout/activity_statistic_details.xml +++ b/app/src/main/res/layout/activity_statistic_details.xml @@ -1,15 +1,7 @@ - + android:id="@+id/statisticDetailsContainer"> - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_evograph.xml b/app/src/main/res/layout/fragment_evograph.xml index 63506299..8c937fd5 100644 --- a/app/src/main/res/layout/fragment_evograph.xml +++ b/app/src/main/res/layout/fragment_evograph.xml @@ -19,32 +19,9 @@ android:layout_height="0dp" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" - app:layout_constraintBottom_toTopOf="@id/chips" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/legendContainer" /> - - - - - - + app:layout_constraintTop_toBottomOf="@+id/legendContainer" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_statistic_details.xml b/app/src/main/res/layout/fragment_statistic_details.xml index 44e1e283..952dc2da 100644 --- a/app/src/main/res/layout/fragment_statistic_details.xml +++ b/app/src/main/res/layout/fragment_statistic_details.xml @@ -14,13 +14,54 @@ app:layout_constraintTop_toTopOf="parent" tools:title="@string/app_name" /> + + + + + + + +