package net.pokeranalytics.android.calculus import android.content.Context import net.pokeranalytics.android.R import net.pokeranalytics.android.exceptions.FormattingException import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.util.FormatUtils import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.extensions.formatted import net.pokeranalytics.android.util.extensions.formattedHourlyDuration /** * An enum representing all the types of Session statistics */ enum class Stat : RowRepresentable { NETRESULT, HOURLY_RATE, AVERAGE, NUMBER_OF_SETS, NUMBER_OF_GAMES, DURATION, AVERAGE_DURATION, NET_BB_PER_100_HANDS, HOURLY_RATE_BB, AVERAGE_NET_BB, WIN_RATIO, AVERAGE_BUYIN, ROI, STANDARD_DEVIATION, STANDARD_DEVIATION_HOURLY, STANDARD_DEVIATION_BB_PER_100_HANDS, HANDS_PLAYED; /** * Returns whether the stat evolution values requires a distribution sorting */ fun hasDistributionSorting() : Boolean { return when (this) { STANDARD_DEVIATION, STANDARD_DEVIATION_HOURLY, STANDARD_DEVIATION_BB_PER_100_HANDS -> true else -> false } } companion object { fun returnOnInvestment(netResult: Double, buyin: Double) : Double? { if (buyin == 0.0) { return null } return netResult / buyin } fun netBBPer100Hands(netBB: Double, numberOfHands: Double) : Double? { if (numberOfHands == 0.0) { return null } return netBB / numberOfHands * 100 } } override val resId: Int? get() { return when (this) { NETRESULT -> R.string.net_result HOURLY_RATE -> R.string.average_hour_rate AVERAGE -> R.string.average NUMBER_OF_SETS -> R.string.number_of_groups NUMBER_OF_GAMES -> R.string.number_of_games DURATION -> R.string.duration AVERAGE_DURATION -> R.string.average_duration NET_BB_PER_100_HANDS -> R.string.net_bb_per_100_hands HOURLY_RATE_BB -> R.string.hourly_rate_bb AVERAGE_NET_BB -> R.string.average_net_bb WIN_RATIO -> R.string.win_ratio AVERAGE_BUYIN -> R.string.average_buyin ROI -> R.string.roi STANDARD_DEVIATION -> R.string.standard_deviation STANDARD_DEVIATION_HOURLY -> R.string.standard_deviation_hourly STANDARD_DEVIATION_BB_PER_100_HANDS -> R.string.standard_deviation_bb_per_100_hands HANDS_PLAYED -> R.string.hands_played } } val threshold: Double get() { return when (this) { WIN_RATIO -> 50.0 else -> 0.0 } } override val viewType: Int = RowViewType.TITLE_VALUE.ordinal } /** * ComputedStat contains a [stat] and their associated [value] */ class ComputedStat(stat: Stat, value: Double) { constructor(stat: Stat, value: Double, previousValue: Double?) : this(stat, value) { if (previousValue != null) { this.variation = (value - previousValue) / previousValue } } /** * The statistic type */ var stat: Stat = stat /** * The stat value */ var value: Double = value /** * The variation of the stat */ var variation: Double? = null /** * 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, Stat.NET_BB_PER_100_HANDS, Stat.HOURLY_RATE_BB, Stat.AVERAGE_NET_BB -> { val numberFormat= FormatUtils.getCurrencyFormatter(context) val color = if (this.value >= this.stat.threshold) R.color.green else R.color.red return TextFormat(numberFormat.format(this.value), 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 amounts Stat.AVERAGE_BUYIN, Stat.STANDARD_DEVIATION, Stat.STANDARD_DEVIATION_HOURLY, Stat.STANDARD_DEVIATION_BB_PER_100_HANDS -> { val numberFormat= FormatUtils.getCurrencyFormatter(context) return TextFormat(numberFormat.format(this.value)) } else -> throw FormattingException("Stat formatting of ${this.stat.name} not handled") } } /** * Returns a TextFormat instance for an evolution value located at the specified [index] */ fun evolutionValueFormat(index: Int) : TextFormat { return TextFormat("undef ${index}") } }