You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.4 KiB
168 lines
5.4 KiB
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}")
|
|
}
|
|
|
|
}
|
|
|