Merge branch 'master' of gitlab.com:stax-river/poker-analytics

feature/top10
Aurelien Hubert 7 years ago
commit 72a35056ee
  1. 58
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  2. 22
      app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt
  3. 22
      app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt
  4. 8
      app/src/main/java/net/pokeranalytics/android/model/StatRepresentable.kt
  5. 43
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt
  6. 3
      app/src/main/java/net/pokeranalytics/android/ui/view/RowRepresentable.kt
  7. 3
      app/src/main/java/net/pokeranalytics/android/util/Global.kt

@ -94,16 +94,12 @@ class Calculator {
var results: ComputedResults = ComputedResults(sessionGroup) var results: ComputedResults = ComputedResults(sessionGroup)
if (sessions.size == 0) {
return results
}
var sum: Double = 0.0 var sum: Double = 0.0
var totalHands: Double = 0.0 var totalHands: Double = 0.0
var bbSum: Double = 0.0 var bbSum: Double = 0.0
var bbSessionCount: Int = 0 var bbSessionCount: Int = 0
var winningSessionCount: Int = 0 var winningSessionCount: Int = 0
var totalBuyin: Double = 0.0 var totalBuyin = 0.0
// Compute for each session // Compute for each session
var index: Int = 0 var index: Int = 0
@ -125,10 +121,19 @@ class Calculator {
results.addEvolutionValue(sum / index, AVERAGE) results.addEvolutionValue(sum / index, AVERAGE)
results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES) results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES)
results.addEvolutionValue(bbSum / bbSessionCount, AVERAGE_NET_BB) results.addEvolutionValue(bbSum / bbSessionCount, AVERAGE_NET_BB)
results.addEvolutionValue(Stat.netBBPer100Hands(bbSum, totalHands), NET_BB_PER_100_HANDS)
results.addEvolutionValue((winningSessionCount / index).toDouble(), WIN_RATIO) results.addEvolutionValue((winningSessionCount / index).toDouble(), WIN_RATIO)
results.addEvolutionValue(totalBuyin / index, AVERAGE_BUYIN) results.addEvolutionValue(totalBuyin / index, AVERAGE_BUYIN)
results.addEvolutionValue(Stat.returnOnInvestment(sum, totalBuyin), ROI)
val netBB100 = Stat.netBBPer100Hands(bbSum, totalHands)
if (netBB100 != null) {
results.addEvolutionValue(netBB100, NET_BB_PER_100_HANDS)
}
val roi = Stat.returnOnInvestment(sum, totalBuyin)
if (roi != null) {
results.addEvolutionValue(roi, ROI)
}
} }
} }
@ -152,36 +157,59 @@ class Calculator {
if (options.evolutionValues == Options.EvolutionValues.DATED) { if (options.evolutionValues == Options.EvolutionValues.DATED) {
results.addEvolutionValue(gSum, duration, NETRESULT) results.addEvolutionValue(gSum, duration, NETRESULT)
results.addEvolutionValue(gSum / duration, duration, HOURLY_RATE) results.addEvolutionValue(gSum / duration, duration, HOURLY_RATE)
results.addEvolutionValue(Stat.netBBPer100Hands(gBBSum, gTotalHands), duration, NET_BB_PER_100_HANDS)
results.addEvolutionValue(hourlyRate, duration, HOURLY_RATE) results.addEvolutionValue(hourlyRate, duration, HOURLY_RATE)
results.addEvolutionValue(gIndex.toDouble(), duration, NUMBER_OF_SETS) results.addEvolutionValue(gIndex.toDouble(), duration, NUMBER_OF_SETS)
results.addEvolutionValue(sessionSet.duration.toDouble(), duration, DURATION) results.addEvolutionValue(sessionSet.duration.toDouble(), duration, DURATION)
results.addEvolutionValue(duration / gIndex, duration, AVERAGE_DURATION) results.addEvolutionValue(duration / gIndex, duration, AVERAGE_DURATION)
results.addEvolutionValue(hourlyRateBB, duration, HOURLY_RATE_BB) results.addEvolutionValue(hourlyRateBB, duration, HOURLY_RATE_BB)
} }
val netBB100 = Stat.netBBPer100Hands(gBBSum, gTotalHands)
if (netBB100 != null) {
results.addEvolutionValue(netBB100, duration, NET_BB_PER_100_HANDS)
} else { //@todo maybe not
results.addEvolutionValue(0.0, duration, NET_BB_PER_100_HANDS)
}
} }
val average: Double = sum / sessions.size.toDouble() var average = 0.0
if (sessions.size > 0) {
average = sum / sessions.size.toDouble()
val avgDuration = duration / sessions.size
val winRatio = (winningSessionCount / sessions.size).toDouble()
val avgBuyin = totalBuyin / sessions.size
results.addStats(setOf(
ComputedStat(AVERAGE, average),
ComputedStat(AVERAGE_DURATION, avgDuration),
ComputedStat(WIN_RATIO, winRatio),
ComputedStat(AVERAGE_BUYIN, avgBuyin)
))
}
// Create stats // Create stats
results.addStats(setOf( results.addStats(setOf(
ComputedStat(NETRESULT, sum), ComputedStat(NETRESULT, sum),
ComputedStat(HOURLY_RATE, hourlyRate), ComputedStat(HOURLY_RATE, hourlyRate),
ComputedStat(AVERAGE, average),
ComputedStat(DURATION, duration), ComputedStat(DURATION, duration),
ComputedStat(NUMBER_OF_SETS, sessionSets.size.toDouble()), ComputedStat(NUMBER_OF_SETS, sessionSets.size.toDouble()),
ComputedStat(NUMBER_OF_GAMES, sessions.size.toDouble()), ComputedStat(NUMBER_OF_GAMES, sessions.size.toDouble()),
ComputedStat(AVERAGE_DURATION, duration / sessions.size),
ComputedStat(NET_BB_PER_100_HANDS, Stat.netBBPer100Hands(bbSum, totalHands)),
ComputedStat(HOURLY_RATE_BB, bbSum / duration), ComputedStat(HOURLY_RATE_BB, bbSum / duration),
ComputedStat(AVERAGE_NET_BB, bbSum / bbSessionCount), ComputedStat(AVERAGE_NET_BB, bbSum / bbSessionCount),
ComputedStat(WIN_RATIO, (winningSessionCount / sessions.size).toDouble()),
ComputedStat(AVERAGE_BUYIN, totalBuyin / sessions.size),
ComputedStat(ROI, Stat.returnOnInvestment(sum, totalBuyin)),
ComputedStat(HANDS_PLAYED, totalHands) ComputedStat(HANDS_PLAYED, totalHands)
)) ))
val roi = Stat.returnOnInvestment(sum, totalBuyin)
val netBB100 = Stat.netBBPer100Hands(bbSum, totalHands)
if (roi != null) {
results.addStats(setOf(ComputedStat(ROI, roi)))
}
if (netBB100 != null) {
results.addStats(setOf(ComputedStat(NET_BB_PER_100_HANDS, netBB100)))
}
val bbPer100Hands = bbSum / totalHands * 100 val bbPer100Hands = bbSum / totalHands * 100
// Standard Deviation // Standard Deviation

@ -25,15 +25,31 @@ interface SessionInterface : Summable {
/** /**
* A sessionGroup of computable items identified by a name * A sessionGroup of computable items identified by a name
*/ */
class SessionGroup(name: String, sessions: List<SessionInterface>) { class SessionGroup(name: String, sessions: List<SessionInterface>, stats: List<Stat>? = null) {
/**
* The display name of the group
*/
var name: String = name var name: String = name
/**
* The list of sessions to compute
*/
var sessions: List<SessionInterface> = sessions var sessions: List<SessionInterface> = sessions
// A subgroup used to compute stat variation /**
* The list of stats to display
*/
var stats: List<Stat>? = stats
/**
* A subgroup used to compute stat variation
*/
var comparedSessions: SessionGroup? = null var comparedSessions: SessionGroup? = null
// The computed stats of the comparable sessionGroup /**
* The computed stats of the comparable sessionGroup
*/
var comparedComputedResults: ComputedResults? = null var comparedComputedResults: ComputedResults? = null
} }

@ -45,11 +45,17 @@ enum class Stat : RowRepresentable {
companion object { companion object {
fun returnOnInvestment(netResult: Double, buyin: Double) : Double { fun returnOnInvestment(netResult: Double, buyin: Double) : Double? {
if (buyin == 0.0) {
return null
}
return netResult / buyin return netResult / buyin
} }
fun netBBPer100Hands(netBB: Double, numberOfHands: Double) : Double { fun netBBPer100Hands(netBB: Double, numberOfHands: Double) : Double? {
if (numberOfHands == 0.0) {
return null
}
return netBB / numberOfHands * 100 return netBB / numberOfHands * 100
} }
@ -119,7 +125,8 @@ class ComputedStat(stat: Stat, value: Double) {
/** /**
* Formats the value of the stat to be suitable for display * Formats the value of the stat to be suitable for display
*/ */
fun format(context: Context) : TextFormat { fun format(context: Context): TextFormat {
when (this.stat) { when (this.stat) {
// Amounts + red/green // Amounts + red/green
Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE, Stat.NET_BB_PER_100_HANDS, Stat.HOURLY_RATE_BB, Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE, Stat.NET_BB_PER_100_HANDS, Stat.HOURLY_RATE_BB,
@ -131,14 +138,14 @@ class ComputedStat(stat: Stat, value: Double) {
return TextFormat(numberFormat.format(this.value), color) return TextFormat(numberFormat.format(this.value), color)
} // white integers } // white integers
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.HANDS_PLAYED -> { Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.HANDS_PLAYED -> {
return TextFormat("${this.value.toInt()}") return TextFormat("${value.toInt()}")
} // white durations } // white durations
Stat.DURATION, Stat.AVERAGE_DURATION -> { Stat.DURATION, Stat.AVERAGE_DURATION -> {
return TextFormat("${this.value.toLong().toMinutes()}") return TextFormat("${value.toLong().toMinutes()}")
} // red/green percentages } // red/green percentages
Stat.WIN_RATIO, Stat.ROI -> { Stat.WIN_RATIO, Stat.ROI -> {
val color = if (this.value >= this.stat.threshold) R.color.green else R.color.red val color = if (value >= this.stat.threshold) R.color.green else R.color.red
return TextFormat("${this.value.formatted()}%", color) return TextFormat("${value.formatted()}%", color)
} // white amounts } // white amounts
Stat.AVERAGE_BUYIN, Stat.STANDARD_DEVIATION, Stat.STANDARD_DEVIATION_HOURLY, Stat.AVERAGE_BUYIN, Stat.STANDARD_DEVIATION, Stat.STANDARD_DEVIATION_HOURLY,
Stat.STANDARD_DEVIATION_BB_PER_100_HANDS -> { Stat.STANDARD_DEVIATION_BB_PER_100_HANDS -> {
@ -149,7 +156,6 @@ class ComputedStat(stat: Stat, value: Double) {
} }
else -> throw FormattingException("Stat formatting of ${this.stat.name} not handled") else -> throw FormattingException("Stat formatting of ${this.stat.name} not handled")
} }
} }
/** /**

@ -1,18 +1,20 @@
package net.pokeranalytics.android.model package net.pokeranalytics.android.model
import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
class StatRepresentable(stat: ComputedStat) : RowRepresentable { class StatRepresentable(stat: Stat, computedStat: ComputedStat?) : RowRepresentable {
var computedStat: ComputedStat = stat var stat: Stat = stat
var computedStat: ComputedStat? = computedStat
override val viewType: Int override val viewType: Int
get() = RowViewType.STAT.ordinal get() = RowViewType.STAT.ordinal
override val resId: Int? override val resId: Int?
get() = this.computedStat.stat.resId get() = this.stat.resId
} }

@ -9,10 +9,7 @@ import io.realm.Realm
import kotlinx.android.synthetic.main.fragment_stats.* import kotlinx.android.synthetic.main.fragment_stats.*
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.*
import net.pokeranalytics.android.calculus.ComputedResults
import net.pokeranalytics.android.calculus.SessionGroup
import net.pokeranalytics.android.calculus.TextFormat
import net.pokeranalytics.android.model.StatRepresentable import net.pokeranalytics.android.model.StatRepresentable
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
@ -21,6 +18,7 @@ import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.HeaderRowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.HeaderRowRepresentable
import net.pokeranalytics.android.util.NULL_TEXT
class StatsFragment : PokerAnalyticsFragment(), RowRepresentableDataSource { class StatsFragment : PokerAnalyticsFragment(), RowRepresentableDataSource {
@ -60,23 +58,13 @@ class StatsFragment : PokerAnalyticsFragment(), RowRepresentableDataSource {
override fun statFormatForRow(row: RowRepresentable): TextFormat { override fun statFormatForRow(row: RowRepresentable): TextFormat {
if (row is StatRepresentable) { if (row is StatRepresentable) {
context?.let { context?.let { context ->
return row.computedStat.format(it) row.computedStat?.let { return it.format(context) }
} }
} }
return TextFormat("shouldn't happen :)") return TextFormat(NULL_TEXT)
} }
// override fun stringForRow(row: RowRepresentable): String {
// if (row is StatRepresentable) {
// context?.let {
// val format = row.computedStat.format(it)
// return format.text
// }
// }
// return "shouldn't happen :)"
// }
/** /**
* Init data * Init data
*/ */
@ -103,9 +91,12 @@ class StatsFragment : PokerAnalyticsFragment(), RowRepresentableDataSource {
} }
} }
val allSessionGroup = SessionGroup(getString(R.string.all), allSessions) val allStats: List<Stat> = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE, Stat.NUMBER_OF_GAMES, Stat.AVERAGE_DURATION, Stat.DURATION)
val cgSessionGroup = SessionGroup(getString(R.string.cash_game), cgSessions) val allSessionGroup = SessionGroup(getString(R.string.all), allSessions, allStats)
val tSessionGroup = SessionGroup(getString(R.string.tournament), tSessions) val cgStats: List<Stat> = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.NET_BB_PER_100_HANDS, Stat.HOURLY_RATE_BB, Stat.AVERAGE, Stat.STANDARD_DEVIATION_HOURLY, Stat.WIN_RATIO, Stat.NUMBER_OF_GAMES, Stat.AVERAGE_BUYIN)
val cgSessionGroup = SessionGroup(getString(R.string.cash_game), cgSessions, cgStats)
val tStats: List<Stat> = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.ROI, Stat.WIN_RATIO, Stat.NUMBER_OF_GAMES, Stat.AVERAGE_BUYIN)
val tSessionGroup = SessionGroup(getString(R.string.tournament), tSessions, tStats)
results = Calculator.computeGroups(listOf(allSessionGroup, cgSessionGroup, tSessionGroup), Calculator.Options()) results = Calculator.computeGroups(listOf(allSessionGroup, cgSessionGroup, tSessionGroup), Calculator.Options())
@ -127,14 +118,14 @@ class StatsFragment : PokerAnalyticsFragment(), RowRepresentableDataSource {
} }
fun convertResultsIntoRepresentables(results: List<ComputedResults>) : ArrayList<RowRepresentable> { private fun convertResultsIntoRepresentables(results: List<ComputedResults>) : ArrayList<RowRepresentable> {
val rows: ArrayList<RowRepresentable> = ArrayList<RowRepresentable>() val rows: ArrayList<RowRepresentable> = ArrayList()
results.forEach { results.forEach { results ->
rows.add(HeaderRowRepresentable(RowViewType.TITLE, title = it.group.name)) rows.add(HeaderRowRepresentable(RowViewType.TITLE, title = results.group.name))
it.allStats().forEach { results.group.stats?.forEach { stat ->
rows.add(StatRepresentable(it)) rows.add(StatRepresentable(stat, results.computedStat(stat)))
} }
} }

@ -3,6 +3,7 @@ package net.pokeranalytics.android.ui.view
import android.content.Context import android.content.Context
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType
import net.pokeranalytics.android.util.NULL_TEXT
/** /**
* An interface extending Displayable to add a way to represent an object as a String * An interface extending Displayable to add a way to represent an object as a String
@ -10,7 +11,7 @@ import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheet
interface RowRepresentable : Displayable { interface RowRepresentable : Displayable {
fun getDisplayName(): String { fun getDisplayName(): String {
return "UNKNOWN NAME" return NULL_TEXT
} }
} }

@ -0,0 +1,3 @@
package net.pokeranalytics.android.util
val NULL_TEXT: String = "--"
Loading…
Cancel
Save