diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt index 4e1aea9b..6a2d3401 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt @@ -4,6 +4,7 @@ import android.content.Context import net.pokeranalytics.android.R import net.pokeranalytics.android.exceptions.FormattingException import net.pokeranalytics.android.model.interfaces.Timed +import net.pokeranalytics.android.ui.graph.AxisFormatting import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.util.NULL_TEXT @@ -40,14 +41,23 @@ enum class AggregationType { DURATION; val resId: Int - get() { - return when (this) { - SESSION -> R.string.session - MONTH -> R.string.month - YEAR -> R.string.year - DURATION -> R.string.duration + get() { + return when (this) { + SESSION -> R.string.session + MONTH -> R.string.month + YEAR -> R.string.year + DURATION -> R.string.duration + } } - } + + val axisFormatting: AxisFormatting + get() { + return when (this) { + DURATION -> AxisFormatting.X_DURATION + else -> AxisFormatting.DEFAULT + } + } + } /** @@ -195,10 +205,10 @@ enum class Stat : RowRepresentable { } - fun cumulativeLabelResId(context: Context) : String { + fun cumulativeLabelResId(context: Context): String { val resId = when (this) { AVERAGE, AVERAGE_DURATION, NET_BB_PER_100_HANDS, - HOURLY_RATE_BB, AVERAGE_NET_BB, ROI, WIN_RATIO, HOURLY_RATE -> R.string.average + HOURLY_RATE_BB, AVERAGE_NET_BB, ROI, WIN_RATIO, HOURLY_RATE -> R.string.average NUMBER_OF_SETS -> R.string.number_of_sessions NUMBER_OF_GAMES -> R.string.number_of_records NET_RESULT, DURATION -> R.string.total @@ -225,7 +235,12 @@ enum class Stat : RowRepresentable { val aggregationTypes: List get() { return when (this) { - NET_RESULT -> listOf(AggregationType.SESSION, AggregationType.MONTH, AggregationType.YEAR, AggregationType.DURATION) + NET_RESULT -> listOf( + AggregationType.SESSION, + AggregationType.MONTH, + AggregationType.YEAR, + AggregationType.DURATION + ) NUMBER_OF_GAMES, NUMBER_OF_SETS -> listOf(AggregationType.MONTH, AggregationType.YEAR) else -> listOf(AggregationType.SESSION, AggregationType.MONTH, AggregationType.YEAR) } 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 2492ed13..91240138 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 @@ -108,7 +108,8 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co GraphType.BAR -> BarChart(context) } - this.chartView.setStyle(false, requireContext()) + val axisFormatting = aggregationType.axisFormatting + this.chartView.setStyle(false, axisFormatting, requireContext()) this.chartContainer.addView(this.chartView) } @@ -118,7 +119,10 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co private fun loadGraph() { val graphEntries = when (aggregationType) { - AggregationType.SESSION, AggregationType.DURATION -> selectedReport.results.firstOrNull()?.defaultStatEntries(stat) + AggregationType.SESSION -> selectedReport.results.firstOrNull()?.defaultStatEntries(stat) + AggregationType.DURATION -> { + selectedReport.results.firstOrNull()?.durationEntries(stat) + } AggregationType.MONTH, AggregationType.YEAR -> { when (this.stat) { Stat.NUMBER_OF_GAMES, Stat.NUMBER_OF_SETS -> selectedReport.barEntries(this.stat) @@ -153,7 +157,8 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co } } - this.chartView.setStyle(false, requireContext()) + val axisFormatting = aggregationType.axisFormatting + this.chartView.setStyle(false, axisFormatting, requireContext()) this.chartView.setOnChartValueSelectedListener(this) this.chartView.highlightValue((entries.size - 1).toFloat(), 0) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphExtensions.kt b/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphExtensions.kt index 68aa648f..d667c35d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphExtensions.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphExtensions.kt @@ -8,9 +8,16 @@ import com.github.mikephil.charting.components.XAxis import net.pokeranalytics.android.R import net.pokeranalytics.android.ui.extensions.px +enum class AxisFormatting { + DEFAULT, + X_DURATION, + Y_DURATION, +} +fun BarLineChartBase<*>.setStyle(small: Boolean, axisFormatting: AxisFormatting = AxisFormatting.DEFAULT, context: Context) { -fun BarLineChartBase<*>.setStyle(small: Boolean, context: Context) { + this.legend.isEnabled = false + this.description.isEnabled = false // X Axis this.xAxis.axisLineColor = ContextCompat.getColor(context, R.color.chart_default) @@ -42,20 +49,22 @@ fun BarLineChartBase<*>.setStyle(small: Boolean, context: Context) { this.axisLeft.typeface = ResourcesCompat.getFont(context, R.font.roboto_medium) this.axisLeft.labelCount = if (small) 1 else 7 // @todo not great if interval is [0..2] for number of records as we get decimals this.axisLeft.textSize = 12f + this.axisLeft.valueFormatter = LargeNumberFormatter() this.axisRight.isEnabled = false - this.legend.isEnabled = false - this.description.isEnabled = false this.data?.isHighlightEnabled = !small -// @todo -// if timeYAxis { -// this.axisLeft.valueFormatter = HourValueFormatter() -// } else { -// this.axisLeft.valueFormatter = LargeNumberFormatter() -// } -// - + when (axisFormatting) { + AxisFormatting.DEFAULT -> { + this.axisLeft.valueFormatter = LargeNumberFormatter() + } + AxisFormatting.X_DURATION -> { + this.xAxis.valueFormatter = HourFormatter() + } + AxisFormatting.Y_DURATION -> { + this.axisLeft.valueFormatter = HourFormatter() + } + } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/graph/LargeNumberFormatter.kt b/app/src/main/java/net/pokeranalytics/android/ui/graph/LargeNumberFormatter.kt new file mode 100644 index 00000000..9c6fa0f3 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/graph/LargeNumberFormatter.kt @@ -0,0 +1,32 @@ +package net.pokeranalytics.android.ui.graph + +import com.github.mikephil.charting.components.AxisBase +import com.github.mikephil.charting.formatter.ValueFormatter +import net.pokeranalytics.android.util.extensions.kmbFormatted + +class LargeNumberFormatter : ValueFormatter() { + + override fun getFormattedValue(value: Float): String { + return value.kmbFormatted + } + + override fun getAxisLabel(value: Float, axis: AxisBase?): String { + val test = value.kmbFormatted + return test + } + +} + +class HourFormatter : ValueFormatter() { + + override fun getFormattedValue(value: Float): String { + return value.kmbFormatted + "H" + } + + override fun getAxisLabel(value: Float, axis: AxisBase?): String { + val test = value.kmbFormatted + "H" + return test + } + +} + 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 c36d8028..6302008b 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 @@ -22,6 +22,7 @@ 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.AxisFormatting import net.pokeranalytics.android.ui.graph.PALineDataSet import net.pokeranalytics.android.ui.graph.setStyle import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable @@ -349,7 +350,7 @@ enum class RowViewType(private var layoutRes: Int) { it.addView(chartView) } - chartView.setStyle(true, context) + chartView.setStyle(true, AxisFormatting.DEFAULT, context) chartView.setTouchEnabled(false) chartView.highlightValue((entries.size - 1).toFloat(), 0) } diff --git a/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt b/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt index 5e2bb841..9566e07a 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt @@ -2,11 +2,31 @@ package net.pokeranalytics.android.util.extensions import android.content.Context import net.pokeranalytics.android.R -import net.pokeranalytics.android.util.UserDefaults +import java.lang.Math.abs import java.text.DecimalFormat import java.text.NumberFormat import java.util.* +val Number.kmbFormatted: String + get() { + var thousandsExponent = 0 + var v = this.toDouble() + while (abs(v) >= 10000 && thousandsExponent < 3) { + v /= 1000 + thousandsExponent++ + } + + val unit = when(thousandsExponent) { + 0 -> "" + 1 -> "K" + 2 -> "M" + 3 -> "B" + else -> "B+" // shouldn't happen + } + + val formatter = NumberFormat.getInstance() + return formatter.format(v) + unit + } // Double diff --git a/app/src/test/java/net/pokeranalytics/android/BasicUnitTest.kt b/app/src/test/java/net/pokeranalytics/android/BasicUnitTest.kt new file mode 100644 index 00000000..0a2424f2 --- /dev/null +++ b/app/src/test/java/net/pokeranalytics/android/BasicUnitTest.kt @@ -0,0 +1,34 @@ +package net.pokeranalytics.android + +import net.pokeranalytics.android.util.extensions.kmbFormatted +import org.junit.Assert +import org.junit.Test + +class BasicUnitTest : RealmUnitTest() { + + @Test + fun testStats() { + Assert.assertEquals(0, 0) + } + + @Test + fun testFormatting() { + + val n1 = 100.0 + val n2 = 1000.0 + val n3 = n2 * n2 // 1M + val n4 = n3 * n2 // 1B + + val s1 = n1.kmbFormatted + val s2 = n2.kmbFormatted + val s3 = n3.kmbFormatted + val s4 = n4.kmbFormatted + + Assert.assertEquals("100", s1) + Assert.assertEquals("1K", s2) + Assert.assertEquals("1M", s3) + Assert.assertEquals("1B", s4) + + } + +} diff --git a/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt b/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt deleted file mode 100644 index c2cb85b7..00000000 --- a/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt +++ /dev/null @@ -1,59 +0,0 @@ -package net.pokeranalytics.android - -import org.junit.Assert -import org.junit.Test - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ - -class ExampleUnitTest : RealmUnitTest() { - - @Test - fun testStats() { - Assert.assertEquals(0, 0) - } - - -// class Grade(someValue: Double) : SessionInterface { -// -// override var bbPer100Hands: Double = 0.0 -// override var ratedNet: Double = 0.0 -// override var value: Double = someValue -// -// override var sessionSet: SessionSet? = SessionSet() -// override var estimatedHands: Double = 0.0 -// override var bbNet: Double = 0.0 -// override var bigBlindSessionCount: Int = 0 // 0 or 1 -// override var ratedBuyin: Double = 0.0 -// -// } -// -// @Test -// fun testStats() { -// -// val grades: List = listOf(Grade(10.0), Grade(20.0)) -// val group = ComputableGroup(name = "test", computables = grades) -// -// val results: ComputedResults = Calculator.compute(group, Calculator.Options()) -// -// val sum = results.computedStat(Stat.NET_RESULT) -// if (sum != null) { -// assert(sum.value == 0.0) { "sum is ${sum.value}" } -// } else { -// fail("No Net result stat") -// } -// -// val average = results.computedStat(Stat.AVERAGE) -// if (average != null) { -// assert(average.value == 0.0) { "average is ${average.value}" } -// } else { -// fail("No AVERAGE stat") -// } -// -// } - - -}