Stats and graphs: Added intelligence to provide labels for legends

feature/top10
Laurent 7 years ago
parent 0be3cd5527
commit e0cbc7b00a
  1. 66
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  2. 15
      app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt
  3. 109
      app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt
  4. 3
      app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt
  5. 1
      app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt
  6. 47
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  7. 16
      app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt
  8. 4
      app/src/main/java/net/pokeranalytics/android/ui/activity/GraphActivity.kt
  9. 2
      app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt
  10. 45
      app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt
  11. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/HistoryFragment.kt
  12. 66
      app/src/main/java/net/pokeranalytics/android/ui/graph/GraphExtensions.kt
  13. 1
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SessionRow.kt
  14. 11
      app/src/main/res/layout/fragment_graph.xml

@ -1,7 +1,5 @@
package net.pokeranalytics.android.calculus
import android.os.Parcel
import android.os.Parcelable
import io.realm.Realm
import net.pokeranalytics.android.calculus.Stat.*
import net.pokeranalytics.android.model.realm.ComputableResult
@ -10,31 +8,6 @@ import net.pokeranalytics.android.model.realm.SessionSet
import timber.log.Timber
import java.util.*
class ParcelableString(var string: String) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString()) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(string)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<ParcelableString> {
override fun createFromParcel(parcel: Parcel): ParcelableString {
return ParcelableString(parcel)
}
override fun newArray(size: Int): Array<ParcelableString?> {
return arrayOfNulls(size)
}
}
}
/**
* The class performing stats computation
*/
@ -92,8 +65,6 @@ class Calculator {
var computableGroups: MutableList<ComputableGroup> = mutableListOf()
filters.forEach { filter ->
val results = filter.results<ComputableResult>()
val sets = filter.results<SessionSet>()
val group = ComputableGroup(filter.name, filter.filterConditions.map { it.queryCondition })
computableGroups.add(group)
@ -175,20 +146,20 @@ class Calculator {
tBuyinSum += computable.ratedBuyin
tHands += computable.estimatedHands
val sessionId = ParcelableString(computable.session?.id ?: throw IllegalStateException("Computing lone ComputableResult"))
results.addEvolutionValue(tSum, NETRESULT, sessionId)
results.addEvolutionValue(tSum / index, AVERAGE, sessionId)
results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES, sessionId)
results.addEvolutionValue(tBBSum / tBBSessionCount, AVERAGE_NET_BB, sessionId)
results.addEvolutionValue((tWinningSessionCount / index).toDouble(), WIN_RATIO, sessionId)
results.addEvolutionValue(tBuyinSum / index, AVERAGE_BUYIN, sessionId)
val session = computable.session ?: throw IllegalStateException("Computing lone ComputableResult")
results.addEvolutionValue(tSum, NETRESULT, session)
results.addEvolutionValue(tSum / index, AVERAGE, session)
results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES, session)
results.addEvolutionValue(tBBSum / tBBSessionCount, AVERAGE_NET_BB, session)
results.addEvolutionValue((tWinningSessionCount / index).toDouble(), WIN_RATIO, session)
results.addEvolutionValue(tBuyinSum / index, AVERAGE_BUYIN, session)
Stat.netBBPer100Hands(tBBSum, tHands)?.let { netBB100 ->
results.addEvolutionValue(netBB100, NET_BB_PER_100_HANDS, sessionId)
results.addEvolutionValue(netBB100, NET_BB_PER_100_HANDS, session)
}
Stat.returnOnInvestment(tSum, tBuyinSum)?.let { roi ->
results.addEvolutionValue(roi, ROI, sessionId)
results.addEvolutionValue(roi, ROI, session)
}
}
@ -208,7 +179,7 @@ class Calculator {
val gBBSum = sessionSets.sum(SessionSet.Field.BB_NET.identifier).toDouble()
val hourlyRate = gSum / gHourlyDuration
// var hourlyRateBB = gBBSum / gDuration
// var bbHourlyRate = gBBSum / gDuration
when (options.evolutionValues) {
Options.EvolutionValues.DATED -> {
@ -231,17 +202,16 @@ class Calculator {
tHourlyRate = gSum / tHourlyDuration
tHourlyRateBB = gBBSum / tHourlyDuration
val id = ParcelableString(sessionSet.id)
results.addEvolutionValue(tSum, tHourlyDuration, NETRESULT, id)
results.addEvolutionValue(tSum / tHourlyDuration, tHourlyDuration, HOURLY_RATE, id)
results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, id)
results.addEvolutionValue(tIndex.toDouble(), tHourlyDuration, NUMBER_OF_SETS, id)
results.addEvolutionValue(sessionSet.netDuration.toDouble(), tHourlyDuration, DURATION, id)
results.addEvolutionValue(tHourlyDuration / tIndex, tHourlyDuration, AVERAGE_DURATION, id)
results.addEvolutionValue(tHourlyRateBB, tHourlyDuration, HOURLY_RATE_BB, id)
results.addEvolutionValue(tSum, tHourlyDuration, NETRESULT, sessionSet)
results.addEvolutionValue(tSum / tHourlyDuration, tHourlyDuration, HOURLY_RATE, sessionSet)
results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, sessionSet)
results.addEvolutionValue(tIndex.toDouble(), tHourlyDuration, NUMBER_OF_SETS, sessionSet)
results.addEvolutionValue(sessionSet.netDuration.toDouble(), tHourlyDuration, DURATION, sessionSet)
results.addEvolutionValue(tHourlyDuration / tIndex, tHourlyDuration, AVERAGE_DURATION, sessionSet)
results.addEvolutionValue(tHourlyRateBB, tHourlyDuration, HOURLY_RATE_BB, sessionSet)
Stat.netBBPer100Hands(gBBSum, gTotalHands)?.let { netBB100 ->
results.addEvolutionValue(netBB100, tHourlyDuration, NET_BB_PER_100_HANDS, id)
results.addEvolutionValue(netBB100, tHourlyDuration, NET_BB_PER_100_HANDS, sessionSet)
}
}

@ -5,6 +5,7 @@ import com.github.mikephil.charting.data.Entry
import io.realm.Realm
import io.realm.RealmResults
import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.interfaces.Timed
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.SessionSet
@ -113,8 +114,9 @@ class ComputedResults(group: ComputableGroup) {
this._addEvolutionValue(Point(value, data), stat = stat)
}
fun addEvolutionValue(value: Double, duration: Double, stat: Stat, data: Any) {
this._addEvolutionValue(Point(value, y = duration, data = data), stat = stat)
fun addEvolutionValue(value: Double, duration: Double, stat: Stat, data: Timed) {
stat.underlyingClass = data::class.java
this._addEvolutionValue(Point(value, y = duration, data = data.id), stat = stat)
}
private fun _addEvolutionValue(point: Point, stat: Stat) {
@ -169,7 +171,7 @@ class ComputedResults(group: ComputableGroup) {
// MPAndroidChart
fun defaultStatEntries(stat: Stat): List<out Entry> {
fun defaultStatEntries(stat: Stat): List<Entry> {
return when (stat) {
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES -> this.barEntries(stat)
else -> this.singleLineEntries(stat)
@ -177,7 +179,7 @@ class ComputedResults(group: ComputableGroup) {
}
fun singleLineEntries(stat: Stat): List<Entry> {
var entries = mutableListOf<Entry>()
val entries = mutableListOf<Entry>()
this._evolutionValues[stat]?.let { points ->
points.forEachIndexed { index, p ->
entries.add(Entry(index.toFloat(), p.y.toFloat(), p.data))
@ -187,7 +189,7 @@ class ComputedResults(group: ComputableGroup) {
}
fun durationEntries(stat: Stat): List<Entry> {
var entries = mutableListOf<Entry>()
val entries = mutableListOf<Entry>()
this._evolutionValues[stat]?.let { points ->
points.forEach { p ->
entries.add(Entry(p.x.toFloat(), p.y.toFloat(), p.data))
@ -198,8 +200,7 @@ class ComputedResults(group: ComputableGroup) {
fun barEntries(stat: Stat): List<BarEntry> {
var entries = mutableListOf<BarEntry>()
val entries = mutableListOf<BarEntry>()
this._evolutionValues[stat]?.let { points ->
points.forEach { p ->
entries.add(BarEntry(p.x.toFloat(), p.y.toFloat(), p.data))

@ -1,8 +1,10 @@
package net.pokeranalytics.android.calculus
import android.content.Context
import io.realm.RealmModel
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.FormattingException
import net.pokeranalytics.android.model.interfaces.Timed
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.CurrencyUtils
@ -11,10 +13,20 @@ import net.pokeranalytics.android.util.extensions.formatted
import net.pokeranalytics.android.util.extensions.formattedHourlyDuration
import java.util.*
class StatFormattingException(message: String) : Exception(message) {
}
interface StatBase : RealmModel {
fun formattedValue(stat: Stat, context: Context): TextFormat
}
/**
* An enum representing all the types of Session statistics
*/
enum class Stat : RowRepresentable {
enum class Stat(var underlyingClass: Class<out Timed>? = null) : RowRepresentable {
NETRESULT,
HOURLY_RATE,
@ -85,6 +97,48 @@ enum class Stat : RowRepresentable {
}
}
/**
* Formats the value of the stat to be suitable for display
*/
fun format(value: Double, currency: Currency? = null, context: Context): TextFormat {
if (value.isNaN()) {
return TextFormat(NULL_TEXT, R.color.white)
}
when (this) {
// Amounts + red/green
Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE -> {
val numberFormat = CurrencyUtils.getCurrencyFormatter(context, currency)
val color = if (value >= this.threshold) R.color.green else R.color.red
return TextFormat(numberFormat.format(value), color)
}
// Red/green numericValues
Stat.HOURLY_RATE_BB, Stat.AVERAGE_NET_BB, Stat.NET_BB_PER_100_HANDS -> {
val color = if (value >= this.threshold) R.color.green else R.color.red
return TextFormat(value.formatted(), color)
}
// white integers
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.HANDS_PLAYED -> {
return TextFormat("${value.toInt()}")
} // white durations
Stat.DURATION, Stat.AVERAGE_DURATION -> {
return TextFormat(value.formattedHourlyDuration())
} // red/green percentages
Stat.WIN_RATIO, Stat.ROI -> {
val color = if (value * 100 >= this.threshold) R.color.green else R.color.red
return TextFormat("${(value * 100).formatted()}%", color)
} // white amountsr
Stat.AVERAGE_BUYIN, Stat.STANDARD_DEVIATION, Stat.STANDARD_DEVIATION_HOURLY,
Stat.STANDARD_DEVIATION_BB_PER_100_HANDS -> {
val numberFormat = CurrencyUtils.getCurrencyFormatter(context, currency)
return TextFormat(numberFormat.format(value))
}
else -> throw FormattingException("Stat formatting of ${this.name} not handled")
}
}
val threshold: Double
get() {
return when (this) {
@ -94,6 +148,23 @@ enum class Stat : RowRepresentable {
}
fun cumulativeLabelResId(context: Context) : String {
val resId = when (this) {
AVERAGE, AVERAGE_DURATION, NETRESULT, NET_BB_PER_100_HANDS,
HOURLY_RATE_BB, AVERAGE_NET_BB, ROI, WIN_RATIO, HOURLY_RATE -> R.string.average
NETRESULT, DURATION -> R.string.total
STANDARD_DEVIATION -> R.string.net_result
STANDARD_DEVIATION_HOURLY -> R.string.hour_rate_without_pauses
STANDARD_DEVIATION_BB_PER_100_HANDS -> R.string.net_result_bb_per_100_hands
else -> null
}
resId?.let {
return context.getString(it)
} ?: run {
return NULL_TEXT
}
}
override val viewType: Int = RowViewType.TITLE_VALUE.ordinal
}
@ -117,41 +188,7 @@ class ComputedStat(var stat: Stat, var value: Double, var currency: Currency? =
* Formats the value of the stat to be suitable for display
*/
fun format(context: Context): TextFormat {
if (this.value.isNaN()) {
return TextFormat(NULL_TEXT, R.color.white)
}
when (this.stat) {
// Amounts + red/green
Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE -> {
val numberFormat= CurrencyUtils.getCurrencyFormatter(context, currency)
val color = if (this.value >= this.stat.threshold) R.color.green else R.color.red
return TextFormat(numberFormat.format(this.value), color)
}
// Red/green numericValues
Stat.HOURLY_RATE_BB, Stat.AVERAGE_NET_BB, Stat.NET_BB_PER_100_HANDS -> {
val color = if (this.value >= this.stat.threshold) R.color.green else R.color.red
return TextFormat(this.value.formatted(), color)
}
// white integers
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.HANDS_PLAYED -> {
return TextFormat("${value.toInt()}")
} // white durations
Stat.DURATION, Stat.AVERAGE_DURATION -> {
return TextFormat(value.formattedHourlyDuration())
} // red/green percentages
Stat.WIN_RATIO, Stat.ROI -> {
val color = if (value * 100 >= this.stat.threshold) R.color.green else R.color.red
return TextFormat("${(value * 100).formatted()}%", color)
} // white amountsr
Stat.AVERAGE_BUYIN, Stat.STANDARD_DEVIATION, Stat.STANDARD_DEVIATION_HOURLY,
Stat.STANDARD_DEVIATION_BB_PER_100_HANDS -> {
val numberFormat= CurrencyUtils.getCurrencyFormatter(context, currency)
return TextFormat(numberFormat.format(this.value))
}
else -> throw FormattingException("Stat formatting of ${this.stat.name} not handled")
}
return this.stat.format(this.value, this.currency, context)
}
/**

@ -1,8 +1,9 @@
package net.pokeranalytics.android.model.interfaces
import net.pokeranalytics.android.calculus.StatBase
import java.util.*
interface Timed {
interface Timed : StatBase, Identifiable {
fun startDate() : Date?

@ -43,7 +43,6 @@ class PokerAnalyticsMigration : RealmMigration {
schema.get("SessionSet")?.let {
it.addPrimaryKey("id")
}
currentVersion++
}

@ -13,6 +13,8 @@ import io.realm.kotlin.where
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.calculus.StatFormattingException
import net.pokeranalytics.android.calculus.TextFormat
import net.pokeranalytics.android.exceptions.ModelException
import net.pokeranalytics.android.model.Limit
import net.pokeranalytics.android.model.LiveData
@ -365,6 +367,11 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
throw ModelException("Session should have an existing Result relationship")
}
val bbHourlyRate: Double
get() {
return this.bbNet / this.hourlyDuration
}
// Manageable
override fun isValidForSave(): Boolean {
@ -822,5 +829,45 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
}
}
// Stat Base
override fun formattedValue(stat: Stat, context: Context) : TextFormat {
this.result?.let { result ->
val value: Double? = when (stat) {
Stat.NETRESULT, Stat.AVERAGE, Stat.STANDARD_DEVIATION -> result.net
Stat.NUMBER_OF_GAMES, Stat.NUMBER_OF_SETS -> 1.0
Stat.AVERAGE_BUYIN -> result.buyin
Stat.ROI -> {
result.buyin?.let {
Stat.returnOnInvestment(result.net, it)
} ?: run {
null
}
}
Stat.HOURLY_RATE_BB -> this.bbHourlyRate
Stat.NET_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION_BB_PER_100_HANDS -> Stat.netBBPer100Hands(this.bbNet, this.estimatedHands)
Stat.AVERAGE_NET_BB -> this.bbNet
Stat.DURATION, Stat.AVERAGE_DURATION -> this.netDuration.toDouble()
Stat.HOURLY_RATE, Stat.STANDARD_DEVIATION_HOURLY -> this.hourlyRate
Stat.HANDS_PLAYED -> this.estimatedHands
else -> throw StatFormattingException("format undefined for stat ${stat.name}")
}
value?.let {
return stat.format(it, CurrencyUtils.getCurrency(this.bankroll), context)
} ?: run {
return TextFormat(NULL_TEXT)
}
} ?: run {
throw java.lang.IllegalStateException("Asking for stats on Session without Result")
}
}
}

@ -1,11 +1,15 @@
package net.pokeranalytics.android.model.realm
import android.content.Context
import io.realm.Realm
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.Ignore
import io.realm.annotations.LinkingObjects
import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.calculus.StatFormattingException
import net.pokeranalytics.android.calculus.TextFormat
import net.pokeranalytics.android.model.filter.Filterable
import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.interfaces.Timed
@ -15,7 +19,7 @@ import java.util.*
open class SessionSet() : RealmObject(), Timed, Filterable {
@PrimaryKey
var id = UUID.randomUUID().toString()
override var id = UUID.randomUUID().toString()
var startDate: Date = Date()
set(value) {
@ -74,6 +78,16 @@ open class SessionSet() : RealmObject(), Timed, Filterable {
var bbNet: Double = 0.0
override fun formattedValue(stat: Stat, context: Context) : TextFormat {
return when (stat) {
Stat.NETRESULT, Stat.AVERAGE -> stat.format(this.ratedNet, null, context)
Stat.DURATION, Stat.AVERAGE_DURATION -> stat.format(this.netDuration.toDouble(), null, context)
Stat.HOURLY_RATE -> stat.format(this.hourlyRate, null, context)
Stat.HANDS_PLAYED -> stat.format(this.estimatedHands, null, context)
else -> throw StatFormattingException("format undefined for stat ${stat.name}")
}
}
enum class Field(val identifier: String) {
RATED_NET("ratedNet"),
HOURLY_RATE("hourlyRate"),

@ -9,9 +9,9 @@ import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.fragment.GraphFragment
class GraphParameters(stat: Stat, entries: List<out Entry>) {
class GraphParameters(stat: Stat, entries: List<Entry>) {
var stat: Stat = stat
var entries: List<out Entry> = entries
var entries: List<Entry> = entries
}
class GraphActivity : PokerAnalyticsActivity() {

@ -78,7 +78,7 @@ class HomeActivity : PokerAnalyticsActivity() {
// observe currency changes
this.currencies = realm.where(Currency::class.java).findAll()
this.currencies.addChangeListener { t, set ->
this.currencies.addChangeListener { t, _ ->
realm.beginTransaction()
t.forEach {

@ -7,17 +7,20 @@ import android.view.ViewGroup
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.highlight.Highlight
import com.github.mikephil.charting.listener.OnChartValueSelectedListener
import kotlinx.android.synthetic.main.fragment_graph.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.graph.setStyle
interface GraphDataSource {
}
class GraphFragment : PokerAnalyticsFragment() {
class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener {
lateinit var dataSource: GraphDataSource
@ -46,8 +49,48 @@ class GraphFragment : PokerAnalyticsFragment() {
private fun initUI() {
val dataSet = LineDataSet(this.entries, this.stat.name)
val colors = arrayOf(R.color.green_light).toIntArray()
dataSet.setColors(colors, context)
val lineData = LineData(listOf(dataSet))
this.chart.setStyle()
this.chart.data = lineData
this.chart.setOnChartValueSelectedListener(this)
}
// OnChartValueSelectedListener
override fun onNothingSelected() {
// nothing to do
}
override fun onValueSelected(e: Entry?, h: Highlight?) {
e?.let { entry ->
h?.let { highlight ->
val id = entry.data as String
val item = getRealm().where(this.stat.underlyingClass).equalTo("id", id).findAll().firstOrNull()
item?.let {
val date = it.startDate()
val entryStatName = this.stat.localizedTitle(requireContext())
val entryValue = it.formattedValue(this.stat, requireContext())
val totalStatName = this.stat.cumulativeLabelResId(requireContext())
val totalStatValue = this.stat.format(e.y.toDouble(), null, requireContext())
}
this.text.text = ""
}
}
}

@ -112,7 +112,7 @@ class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource
private fun initData() {
this.realmSessions = getRealm().where<Session>().findAll().sort("startDate", Sort.DESCENDING)
this.realmSessions.addChangeListener { t, changeSet ->
this.realmSessions.addChangeListener { _, changeSet ->
this.historyAdapter.refreshData()
this.historyAdapter.notifyDataSetChanged()
}

@ -0,0 +1,66 @@
package net.pokeranalytics.android.ui.graph
import com.github.mikephil.charting.charts.BarChart
import com.github.mikephil.charting.charts.BarLineChartBase
import com.github.mikephil.charting.charts.LineChart
fun BarChart.setStyle() {
GraphHelper.setStyle(this)
}
fun LineChart.setStyle() {
GraphHelper.setStyle(this)
}
class GraphHelper {
companion object {
fun setStyle(chart: BarLineChartBase<*>) {
// this.xAxis.axisLineColor = ContextCompat.getColor(context, R.color.) ChartAppearance.defaultColor
// this.xAxis.axisLineWidth = ChartAppearance.lineWidth
// this.xAxis.enableGridDashedLine(3.0f, 5.0f, 1.0f)
//
// this.xAxis.labelTextColor = ChartAppearance.defaultColor
// this.xAxis.labelFont = Fonts.graphAxis
// this.xAxis.labelCount = 4
// this.xAxis.labelPosition = .bottom
//
// this.xAxis.drawLabelsEnabled = true
// this.xAxis.drawGridLinesEnabled = true
// this.xAxis.granularity = 1.0
// this.xAxis.granularityEnabled = true
// this.xAxis.enabled = true
//
// // Y Axis
// this.leftAxis.drawAxisLineEnabled = false
// this.leftAxis.drawGridLinesEnabled = true
// this.leftAxis.gridLineDashLengths = [3.0, 5.0]
//
// this.leftAxis.drawZeroLineEnabled = true
// this.leftAxis.zeroLineWidth = ChartAppearance.lineWidth
// this.leftAxis.zeroLineColor = ChartAppearance.defaultColor
//
// this.leftAxis.granularityEnabled = true
// this.leftAxis.granularity = 1.0
//
// this.leftAxis.labelTextColor = ChartAppearance.defaultColor
// this.leftAxis.labelFont = Fonts.graphAxis
// this.leftAxis.labelCount = small ? 1 : 7 // @todo not great if interval is [0..2] for number of records as we get decimals
//
// if timeYAxis {
// this.leftAxis.valueFormatter = HourValueFormatter()
// } else {
// this.leftAxis.valueFormatter = LargeNumberFormatter()
// }
//
// this.rightAxis.enabled = false
//
// this.legend.enabled = false
}
}
}

@ -62,7 +62,6 @@ enum class SessionRow : RowRepresentable {
START_DATE, END_DATE, BREAK_TIME, COMMENT
)
}
else -> arrayListOf()
}
}
Session.Type.CASH_GAME.ordinal -> {

@ -6,6 +6,17 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text"
android:textColor="@color/white"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintTop_toTopOf="@+id/chart"
android:layout_marginTop="8dp"/>
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart"
android:layout_width="match_parent"

Loading…
Cancel
Save