From d84cf9fad58d179b58c699826e1209715ea9f80b Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Wed, 17 Apr 2019 10:38:08 +0200 Subject: [PATCH] Improve calendar details (wip) --- .../ui/activity/CalendarDetailsActivity.kt | 5 + .../ui/fragment/CalendarDetailsFragment.kt | 126 ++++++++++++------ .../android/ui/view/RowViewType.kt | 46 +++++++ .../ui/view/rowrepresentable/GraphRow.kt | 11 +- 4 files changed, 139 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/CalendarDetailsActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/CalendarDetailsActivity.kt index 6a8e5654..721f98f2 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/CalendarDetailsActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/CalendarDetailsActivity.kt @@ -3,10 +3,12 @@ package net.pokeranalytics.android.ui.activity import android.content.Context import android.content.Intent import android.os.Bundle +import kotlinx.android.synthetic.main.activity_calendar_details.* import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.ComputedResults import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity +import net.pokeranalytics.android.ui.fragment.CalendarDetailsFragment class CalendarDetailsActivity : PokerAnalyticsActivity() { @@ -41,6 +43,9 @@ class CalendarDetailsActivity : PokerAnalyticsActivity() { */ private fun initUI() { + val calendarDetailsFragment = calendarDetailsFragment as CalendarDetailsFragment + calendarDetailsFragment.setData(computedResults, sessionTypeCondition) + } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt index 15f72051..028fff65 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt @@ -7,24 +7,32 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager -import com.github.mikephil.charting.data.Entry import com.google.android.material.tabs.TabLayout +import io.realm.Realm import kotlinx.android.synthetic.main.fragment_calendar_details.* +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.model.comparison.Comparator import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.ui.activity.CalendarDetailsActivity import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource -import net.pokeranalytics.android.ui.extensions.toast import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.GraphRow import net.pokeranalytics.android.ui.view.rowrepresentable.StatDoubleRow +import timber.log.Timber +import java.util.* +import kotlin.collections.ArrayList class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { @@ -38,6 +46,8 @@ class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable private lateinit var parentActivity: PokerAnalyticsActivity private lateinit var statsAdapter: RowRepresentableAdapter + private var computedResults: ComputedResults? = null + private var sessionTypeCondition: QueryCondition? = null private var rowRepresentables: ArrayList = ArrayList() //private var stat: Stat = Stat.NETRESULT @@ -49,13 +59,34 @@ class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + initData() initUI() + launchStatComputation() } override fun adapterRows(): List? { return rowRepresentables } + override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { + when(row) { + is GraphRow -> { + //TODO: Open graph details + } + } + } + + /** + * Init data + */ + private fun initData() { + Timber.d("initData") + + this.computedResults = CalendarDetailsActivity.computedResults + this.sessionTypeCondition = CalendarDetailsActivity.sessionTypeCondition + + } + /** * Init UI */ @@ -74,9 +105,12 @@ class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { override fun onTabSelected(tab: TabLayout.Tab) { - toast("Tab: ${tab.position}") - - + when(tab.position) { + 0 -> sessionTypeCondition = null + 1 -> sessionTypeCondition = QueryCondition.CASH + 2 -> sessionTypeCondition = QueryCondition.TOURNAMENT + } + launchStatComputation() } override fun onTabUnselected(tab: TabLayout.Tab) { @@ -86,7 +120,7 @@ class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable } }) - CalendarDetailsActivity.sessionTypeCondition?.let { + sessionTypeCondition?.let { when(it) { QueryCondition.CASH -> tabs.getTabAt(1)?.select() QueryCondition.TOURNAMENT -> tabs.getTabAt(2)?.select() @@ -94,28 +128,9 @@ class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable } } - CalendarDetailsActivity.computedResults?.let { computedResults -> - - rowRepresentables.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.net_result)) - rowRepresentables.add(GraphRow(Stat.NETRESULT, null, "")) - rowRepresentables.add(StatDoubleRow(computedResults.computedStat(Stat.NETRESULT), computedResults.computedStat(Stat.HOURLY_RATE))) - rowRepresentables.add(StatDoubleRow(computedResults.computedStat(Stat.LOCATIONS_PLAYED), computedResults.computedStat(Stat.LONGEST_STREAKS))) - rowRepresentables.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.distribution)) - rowRepresentables.add(GraphRow(Stat.NETRESULT, null, "")) - rowRepresentables.add(StatDoubleRow(computedResults.computedStat(Stat.WIN_RATIO))) - rowRepresentables.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.volume)) - rowRepresentables.add(GraphRow(Stat.NETRESULT, null, "")) - rowRepresentables.add(StatDoubleRow(computedResults.computedStat(Stat.DURATION), computedResults.computedStat(Stat.AVERAGE_DURATION))) - rowRepresentables.add(StatDoubleRow(computedResults.computedStat(Stat.DAYS_PLAYED))) - - //computedResults.group.conditions - - } statsAdapter = RowRepresentableAdapter(this, this) - - val viewManager = LinearLayoutManager(requireContext()) recyclerView.apply { @@ -124,29 +139,60 @@ class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable adapter = statsAdapter } - /* - toolbar.title = stat.localizedTitle(requireContext()) - - val fragmentManager = parentActivity.supportFragmentManager - val fragmentTransaction = fragmentManager.beginTransaction() - val fragment = GraphFragment() + } - fragmentTransaction.add(R.id.container, fragment) - fragmentTransaction.commit() + /** + * + */ + private fun launchStatComputation() { + + computedResults?.let { computedResults -> + + GlobalScope.launch { + + val startDate = Date() + + val realm = Realm.getDefaultInstance() + val conditions = ArrayList().apply { + addAll(computedResults.group.conditions) + when (sessionTypeCondition) { + QueryCondition.CASH -> addAll(Comparator.CASH.queryConditions) + QueryCondition.TOURNAMENT -> addAll(Comparator.TOURNAMENT.queryConditions) + } + } + + val options = Calculator.Options(evolutionValues = Calculator.Options.EvolutionValues.STANDARD) + val report = Calculator.computeStatsWithComparators(realm, conditions = conditions, options = options) + + Timber.d("Report take: ${System.currentTimeMillis() - startDate.time}ms") + + rowRepresentables.clear() + rowRepresentables.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.net_result)) + rowRepresentables.add(GraphRow(report, Stat.NETRESULT)) + rowRepresentables.add(StatDoubleRow(computedResults.computedStat(Stat.NETRESULT), computedResults.computedStat(Stat.HOURLY_RATE))) + rowRepresentables.add(StatDoubleRow(computedResults.computedStat(Stat.LOCATIONS_PLAYED), computedResults.computedStat(Stat.LONGEST_STREAKS))) + rowRepresentables.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.distribution)) + rowRepresentables.add(GraphRow(report, Stat.NETRESULT)) + rowRepresentables.add(StatDoubleRow(computedResults.computedStat(Stat.WIN_RATIO))) + rowRepresentables.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.volume)) + rowRepresentables.add(GraphRow(report, Stat.NETRESULT)) + rowRepresentables.add(StatDoubleRow(computedResults.computedStat(Stat.DURATION), computedResults.computedStat(Stat.AVERAGE_DURATION))) + rowRepresentables.add(StatDoubleRow(computedResults.computedStat(Stat.DAYS_PLAYED))) + + launch(Dispatchers.Main) { + statsAdapter.notifyDataSetChanged() + } + } - StatisticDetailsActivity.parameters?.let { - fragment.setData(it.stat, it.report) - StatisticDetailsActivity.parameters = null - } ?: run { - throw Exception("Missing graph parameters") } - */ + } /** * Set data */ - fun setData(stat: Stat, entries: List) { + fun setData(computedResults: ComputedResults?, sessionTypeCondition: QueryCondition?) { + Timber.d("Set data") //this.stat = stat //this.entries = entries } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt index 24aa7c18..14dea0a6 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt @@ -3,6 +3,7 @@ package net.pokeranalytics.android.ui.view import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.FrameLayout import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.SwitchCompat @@ -10,14 +11,21 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import androidx.core.widget.ContentLoadingProgressBar import androidx.recyclerview.widget.RecyclerView +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.LineData import kotlinx.android.synthetic.main.row_history_session.view.* import kotlinx.android.synthetic.main.row_transaction.view.* import net.pokeranalytics.android.R +import net.pokeranalytics.android.calculus.GraphType import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.extensions.setTextFormat +import net.pokeranalytics.android.ui.graph.PALineDataSet +import net.pokeranalytics.android.ui.graph.setStyle import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable +import net.pokeranalytics.android.ui.view.rowrepresentable.GraphRow import net.pokeranalytics.android.ui.view.rowrepresentable.StatDoubleRow import net.pokeranalytics.android.ui.view.rowrepresentable.StatRow import timber.log.Timber @@ -319,6 +327,44 @@ enum class RowViewType(private var layoutRes: Int) { //TODO: Implementation + if (row is GraphRow) { + + row.report.results.firstOrNull()?.defaultStatEntries(row.stat)?.let { entries -> + + val context = itemView.context + + val dataSet = PALineDataSet(entries, row.stat.name, context) + val colors = arrayOf(R.color.green_light).toIntArray() + dataSet.setColors(colors, context) + dataSet.setDrawCircles(false) + val lineData = LineData(listOf(dataSet)) + + val chartView = when (row.stat.graphType) { + GraphType.LINE -> { + val lineChart = LineChart(context) + lineChart.data = lineData + lineChart + } + GraphType.BAR -> { + val barChart = BarChart(context) + barChart + } + } + + itemView.findViewById(R.id.chartContainer)?.let { + it.removeAllViews() + it.addView(chartView) + } + + chartView.setStyle(false, context) + //chartView.setOnChartValueSelectedListener(this) + chartView.highlightValue((entries.size - 1).toFloat(), 0) + + } + + } + + // Listener val listener = View.OnClickListener { adapter.delegate?.onRowSelected(position, row) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/GraphRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/GraphRow.kt index 4290aa75..5803cc84 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/GraphRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/GraphRow.kt @@ -1,21 +1,14 @@ package net.pokeranalytics.android.ui.view.rowrepresentable -import net.pokeranalytics.android.calculus.ComputedStat +import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType -class GraphRow(stat: Stat, computedStat: ComputedStat?, groupName: String = "") : RowRepresentable { - - var stat: Stat = stat - var computedStat: ComputedStat? = computedStat - var groupName: String = groupName +class GraphRow(var report: Report, var stat: Stat) : RowRepresentable { override val viewType: Int get() = RowViewType.GRAPH.ordinal - override val resId: Int? - get() = this.stat.resId - }