|
|
|
@ -4,33 +4,27 @@ import android.os.Bundle |
|
|
|
import android.view.LayoutInflater |
|
|
|
import android.view.LayoutInflater |
|
|
|
import android.view.View |
|
|
|
import android.view.View |
|
|
|
import android.view.ViewGroup |
|
|
|
import android.view.ViewGroup |
|
|
|
import androidx.core.view.isVisible |
|
|
|
|
|
|
|
import com.github.mikephil.charting.charts.BarChart |
|
|
|
import com.github.mikephil.charting.charts.BarChart |
|
|
|
import com.github.mikephil.charting.charts.BarLineChartBase |
|
|
|
import com.github.mikephil.charting.charts.BarLineChartBase |
|
|
|
import com.github.mikephil.charting.charts.LineChart |
|
|
|
import com.github.mikephil.charting.charts.LineChart |
|
|
|
import com.github.mikephil.charting.data.* |
|
|
|
import com.github.mikephil.charting.data.* |
|
|
|
import com.github.mikephil.charting.highlight.Highlight |
|
|
|
import com.github.mikephil.charting.highlight.Highlight |
|
|
|
import com.github.mikephil.charting.listener.OnChartValueSelectedListener |
|
|
|
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.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.R |
|
|
|
import net.pokeranalytics.android.calculus.* |
|
|
|
import net.pokeranalytics.android.calculus.* |
|
|
|
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity |
|
|
|
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.fragment.components.PokerAnalyticsFragment |
|
|
|
import net.pokeranalytics.android.ui.graph.PALineDataSet |
|
|
|
import net.pokeranalytics.android.ui.graph.PALineDataSet |
|
|
|
import net.pokeranalytics.android.ui.graph.setStyle |
|
|
|
import net.pokeranalytics.android.ui.graph.setStyle |
|
|
|
import net.pokeranalytics.android.ui.view.LegendView |
|
|
|
import net.pokeranalytics.android.ui.view.LegendView |
|
|
|
import timber.log.Timber |
|
|
|
import timber.log.Timber |
|
|
|
import java.util.* |
|
|
|
|
|
|
|
import kotlin.coroutines.CoroutineContext |
|
|
|
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 { |
|
|
|
class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, CoroutineScope { |
|
|
|
@ -49,15 +43,12 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private lateinit var parentActivity: PokerAnalyticsActivity |
|
|
|
private lateinit var parentActivity: PokerAnalyticsActivity |
|
|
|
private lateinit var computableGroup: ComputableGroup |
|
|
|
|
|
|
|
private lateinit var selectedReport: Report |
|
|
|
private lateinit var selectedReport: Report |
|
|
|
private lateinit var legendView: LegendView |
|
|
|
private lateinit var legendView: LegendView |
|
|
|
private lateinit var chartView: BarLineChartBase<*> |
|
|
|
private lateinit var chartView: BarLineChartBase<*> |
|
|
|
|
|
|
|
|
|
|
|
private var stat: Stat = Stat.NET_RESULT |
|
|
|
private var stat: Stat = Stat.NET_RESULT |
|
|
|
private var reports: MutableMap<AggregationType, Report> = hashMapOf() |
|
|
|
private var aggregationType: AggregationType = AggregationType.SESSION |
|
|
|
private var aggregationTypes: List<AggregationType> = listOf() |
|
|
|
|
|
|
|
private var displayAggregationChoices: Boolean = true |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override val coroutineContext: CoroutineContext |
|
|
|
override val coroutineContext: CoroutineContext |
|
|
|
get() = Dispatchers.Main |
|
|
|
get() = Dispatchers.Main |
|
|
|
@ -70,26 +61,41 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co |
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
|
|
|
super.onViewCreated(view, savedInstanceState) |
|
|
|
super.onViewCreated(view, savedInstanceState) |
|
|
|
initUI() |
|
|
|
initUI() |
|
|
|
|
|
|
|
loadGraph() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
// OnChartValueSelectedListener |
|
|
|
* Set data |
|
|
|
override fun onNothingSelected() { |
|
|
|
*/ |
|
|
|
// nothing to do |
|
|
|
fun setData(stat: Stat, group: ComputableGroup, report: Report, displayAggregationChoices: Boolean = true) { |
|
|
|
} |
|
|
|
this.stat = report.options.displayedStats.first() |
|
|
|
|
|
|
|
this.computableGroup = group |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.aggregationTypes = stat.aggregationTypes |
|
|
|
override fun onValueSelected(e: Entry?, h: Highlight?) { |
|
|
|
this.reports[this.aggregationTypes.first()] = report |
|
|
|
e?.let { entry -> |
|
|
|
this.selectedReport = report |
|
|
|
val statEntry = when (entry.data) { |
|
|
|
this.displayAggregationChoices = displayAggregationChoices |
|
|
|
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 |
|
|
|
* Init UI |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private fun initUI() { |
|
|
|
private fun initUI() { |
|
|
|
|
|
|
|
Timber.d("initUI") |
|
|
|
|
|
|
|
|
|
|
|
parentActivity = activity as PokerAnalyticsActivity |
|
|
|
parentActivity = activity as PokerAnalyticsActivity |
|
|
|
parentActivity.title = stat.localizedTitle(requireContext()) |
|
|
|
parentActivity.title = stat.localizedTitle(requireContext()) |
|
|
|
@ -104,80 +110,20 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co |
|
|
|
|
|
|
|
|
|
|
|
this.chartView.setStyle(false, requireContext()) |
|
|
|
this.chartView.setStyle(false, requireContext()) |
|
|
|
this.chartContainer.addView(this.chartView) |
|
|
|
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) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
/** |
|
|
|
}) |
|
|
|
* Load graph |
|
|
|
|
|
|
|
*/ |
|
|
|
} |
|
|
|
private fun loadGraph() { |
|
|
|
|
|
|
|
Timber.d("loadGraph") |
|
|
|
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) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val graphEntries = when (aggregationType) { |
|
|
|
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 -> { |
|
|
|
AggregationType.MONTH, AggregationType.YEAR -> { |
|
|
|
when (this.stat) { |
|
|
|
when (this.stat) { |
|
|
|
Stat.NUMBER_OF_GAMES, Stat.NUMBER_OF_SETS -> report.barEntries(this.stat) |
|
|
|
Stat.NUMBER_OF_GAMES, Stat.NUMBER_OF_SETS -> selectedReport.barEntries(this.stat) |
|
|
|
else -> report.lineEntries(this.stat) |
|
|
|
else -> selectedReport.lineEntries(this.stat) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -216,32 +162,18 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// OnChartValueSelectedListener |
|
|
|
/** |
|
|
|
|
|
|
|
* Set data |
|
|
|
override fun onNothingSelected() { |
|
|
|
*/ |
|
|
|
// nothing to do |
|
|
|
fun setData(report: Report, aggregationType: AggregationType) { |
|
|
|
} |
|
|
|
Timber.d("setData") |
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
this.selectedReport = report |
|
|
|
val entryValue = it.formattedValue(this.stat, requireContext()) |
|
|
|
this.aggregationType = aggregationType |
|
|
|
val totalStatValue = this.stat.format(entry.y.toDouble(), currency = null, context = requireContext()) |
|
|
|
this.stat = report.options.displayedStats.first() |
|
|
|
|
|
|
|
|
|
|
|
this.legendView.setItemData(this.stat, formattedDate, entryValue, totalStatValue) |
|
|
|
if (isAdded && !isDetached) { |
|
|
|
} |
|
|
|
loadGraph() |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|