Add formatting to graph axis

feature/top10
Laurent 7 years ago
parent 058c0b0db6
commit a983dc7598
  1. 19
      app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt
  2. 11
      app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt
  3. 31
      app/src/main/java/net/pokeranalytics/android/ui/graph/GraphExtensions.kt
  4. 32
      app/src/main/java/net/pokeranalytics/android/ui/graph/LargeNumberFormatter.kt
  5. 3
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt
  6. 22
      app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt
  7. 34
      app/src/test/java/net/pokeranalytics/android/BasicUnitTest.kt
  8. 59
      app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.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
@ -48,6 +49,15 @@ enum class AggregationType {
DURATION -> R.string.duration
}
}
val axisFormatting: AxisFormatting
get() {
return when (this) {
DURATION -> AxisFormatting.X_DURATION
else -> AxisFormatting.DEFAULT
}
}
}
/**
@ -195,7 +205,7 @@ 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
@ -225,7 +235,12 @@ enum class Stat : RowRepresentable {
val aggregationTypes: List<AggregationType>
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)
}

@ -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)

@ -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()
}
}
}

@ -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
}
}

@ -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)
}

@ -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

@ -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)
}
}

@ -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<Grade> = 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")
// }
//
// }
}
Loading…
Cancel
Save