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

feature/top10
Aurelien Hubert 7 years ago
commit 8358fc4c07
  1. 2
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  2. 511
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  3. 3
      app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt

@ -92,7 +92,7 @@ class PokerAnalyticsApplication : Application() {
val sessions = realm.where<Session>().findAll()
if (sessions.size < 10) {
val numberOfSessions = 200
val numberOfSessions = 100
Timber.d("*** Start creating ${numberOfSessions} fake sessions...")
val s = Date()

@ -9,249 +9,284 @@ import timber.log.Timber
*/
class Calculator {
/**
* The options used for calculations or display
*/
class Options {
/**
* The way the stats are going to be displayed
*/
enum class Display {
TABLE,
EVOLUTION,
COMPARISON,
MAP,
POLYNOMIAL
}
/**
* The type of evolution values
*/
enum class EvolutionValues {
NONE,
STANDARD,
DATED
}
var display: Display = Display.TABLE
var evolutionValues: EvolutionValues = EvolutionValues.NONE
var displayedStats: List<Stat> = listOf()
/**
* This function determines whether the standard deviation should be computed
*/
fun shouldComputeStandardDeviation() : Boolean {
this.displayedStats.forEach { stat ->
return when (stat) {
STANDARD_DEVIATION, STANDARD_DEVIATION_HOURLY, STANDARD_DEVIATION_BB_PER_100_HANDS -> true
else -> false
}
}
return true
}
/**
* The options used for calculations or display
*/
class Options {
/**
* The way the stats are going to be displayed
*/
enum class Display {
TABLE,
EVOLUTION,
COMPARISON,
MAP,
POLYNOMIAL
}
/**
* The type of evolution values
*/
enum class EvolutionValues {
NONE,
STANDARD,
DATED
}
var display: Display = Display.TABLE
var evolutionValues: EvolutionValues = EvolutionValues.NONE
var displayedStats: List<Stat> = listOf()
/**
* This function determines whether the standard deviation should be computed
*/
fun shouldComputeStandardDeviation(): Boolean {
this.displayedStats.forEach { stat ->
return when (stat) {
STANDARD_DEVIATION, STANDARD_DEVIATION_HOURLY, STANDARD_DEVIATION_BB_PER_100_HANDS -> true
else -> false
}
}
return true
}
// var aggregation: Aggregation? = null
}
companion object {
fun computePreAggregation(sets: List<SessionSet>, options: Options): List<ComputedResults> {
Timber.d("sets = ${sets.size}")
return listOf()
}
/**
* Computes all stats for list of Session sessionGroup
*/
fun computeGroups(groups: List<SessionGroup>, options: Options): List<ComputedResults> {
val computedResults = mutableListOf<ComputedResults>()
groups.forEach { group ->
// Computes actual sessionGroup stats
val results: ComputedResults = Calculator.compute(group, options = options)
// Computes the compared sessionGroup if existing
val comparedGroup = group.comparedSessions
if (comparedGroup != null) {
val comparedResults = Calculator.compute(comparedGroup, options = options)
group.comparedComputedResults = comparedResults
results.computeStatVariations(comparedResults)
}
results.finalize(options) // later treatment, such as evolution values sorting
computedResults.add(results)
}
return computedResults
}
/**
* Computes stats for a SessionSet
*/
fun compute(sessionGroup: SessionGroup, options: Options) : ComputedResults {
Timber.d(">>>> Start computing group ${sessionGroup.name}, ${sessionGroup.sessions.size} sessions")
val sessions: List<SessionInterface> = sessionGroup.sessions
val sessionSets = sessionGroup.sessions.mapNotNull { it.sessionSet }.toHashSet()
val results: ComputedResults = ComputedResults(sessionGroup)
var sum: Double = 0.0
var totalHands: Double = 0.0
var bbSum: Double = 0.0
var bbSessionCount: Int = 0
var winningSessionCount: Int = 0
var totalBuyin = 0.0
// Compute for each session
var index: Int = 0
sessions.forEach { s ->
index++;
sum += s.ratedNet
bbSum += s.bbNetResult
bbSessionCount += s.bigBlindSessionCount
}
companion object {
fun computePreAggregation(sets: List<SessionSet>, options: Options): List<ComputedResults> {
Timber.d("sets = ${sets.size}")
return listOf()
}
/**
* Computes all stats for list of Session sessionGroup
*/
fun computeGroups(groups: List<SessionGroup>, options: Options): List<ComputedResults> {
val computedResults = mutableListOf<ComputedResults>()
groups.forEach { group ->
// Computes actual sessionGroup stats
val results: ComputedResults = Calculator.compute(group, options = options)
// Computes the compared sessionGroup if existing
val comparedGroup = group.comparedSessions
if (comparedGroup != null) {
val comparedResults = Calculator.compute(comparedGroup, options = options)
group.comparedComputedResults = comparedResults
results.computeStatVariations(comparedResults)
}
results.finalize(options) // later treatment, such as evolution values sorting
computedResults.add(results)
}
return computedResults
}
// fun compute(sessionGroup: SessionGroup, options: Options): ComputedResults {
//
// var sum: Double = 0.0
// val sessions: List<SessionInterface> = sessionGroup.sessions
// val results: ComputedResults = ComputedResults(sessionGroup)
//
// sessions.forEach { s ->
// sum += s.ratedNet
// }
//
// results.addStats(
// setOf(
// ComputedStat(NETRESULT, sum)
// )
// )
//
// return results
// }
/**
* Computes stats for a SessionSet
*/
fun compute(sessionGroup: SessionGroup, options: Options): ComputedResults {
Timber.d(">>>> Start computing group ${sessionGroup.name}, ${sessionGroup.sessions.size} sessions")
val sessions: List<SessionInterface> = sessionGroup.sessions
val sessionSets = sessionGroup.sessions.mapNotNull { it.sessionSet }.toHashSet()
val results: ComputedResults = ComputedResults(sessionGroup)
var sum: Double = 0.0
var totalHands: Double = 0.0
var bbSum: Double = 0.0
var bbSessionCount: Int = 0
var winningSessionCount: Int = 0 // sessions.filter { it.value >= 0.0 }.size
var totalBuyin = 0.0
// Compute for each session
var index: Int = 0
sessions.forEach { s ->
index++;
sum += s.ratedNet
bbSum += s.bbNetResult
bbSessionCount += s.bigBlindSessionCount
if (s.value >= 0) {
winningSessionCount++
}
totalBuyin += s.buyin
totalHands += s.estimatedHands
if (options.evolutionValues == Options.EvolutionValues.STANDARD) {
results.addEvolutionValue(sum, NETRESULT)
results.addEvolutionValue(sum / index, AVERAGE)
results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES)
results.addEvolutionValue(bbSum / bbSessionCount, AVERAGE_NET_BB)
results.addEvolutionValue((winningSessionCount / index).toDouble(), WIN_RATIO)
results.addEvolutionValue(totalBuyin / index, AVERAGE_BUYIN)
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)
}
}
}
// Compute for each serie
var duration: Double = 0.0
var hourlyRate: Double = 0.0
var hourlyRateBB: Double = 0.0
var gIndex = 0; var gSum = 0.0; var gTotalHands = 0.0; var gBBSum = 0.0;
sessionSets.forEach { sessionSet ->
gIndex++
duration += sessionSet.hourlyDuration
gSum += sessionSet.ratedNet
gTotalHands += sessionSet.estimatedHands
gBBSum += sessionSet.bbNetResult
hourlyRate = gSum / duration
hourlyRateBB = gBBSum / duration
if (options.evolutionValues == Options.EvolutionValues.DATED) {
results.addEvolutionValue(gSum, duration, NETRESULT)
results.addEvolutionValue(gSum / duration, duration, HOURLY_RATE)
results.addEvolutionValue(hourlyRate, duration, HOURLY_RATE)
results.addEvolutionValue(gIndex.toDouble(), duration, NUMBER_OF_SETS)
results.addEvolutionValue(sessionSet.netDuration.toDouble(), duration, DURATION)
results.addEvolutionValue(duration / gIndex, duration, AVERAGE_DURATION)
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)
}
}
var average = 0.0
if (sessions.size > 0) {
average = sum / sessions.size.toDouble()
val winRatio = winningSessionCount.toDouble() / sessions.size.toDouble()
val avgBuyin = totalBuyin / sessions.size
results.addStats(setOf(
ComputedStat(AVERAGE, average),
ComputedStat(WIN_RATIO, winRatio),
ComputedStat(AVERAGE_BUYIN, avgBuyin)
))
}
if (sessionSets.size > 0) {
val avgDuration = duration / sessionSets.size
results.addStats(setOf(
ComputedStat(HOURLY_RATE, hourlyRate),
ComputedStat(AVERAGE_DURATION, avgDuration)
))
}
// Create stats
results.addStats(setOf(
ComputedStat(NETRESULT, sum),
ComputedStat(DURATION, duration),
ComputedStat(NUMBER_OF_SETS, sessionSets.size.toDouble()),
ComputedStat(NUMBER_OF_GAMES, sessions.size.toDouble()),
ComputedStat(HOURLY_RATE_BB, bbSum / duration),
ComputedStat(AVERAGE_NET_BB, bbSum / bbSessionCount),
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
// Standard Deviation
if (options.shouldComputeStandardDeviation()) {
// Session
var stdSum: Double = 0.0
var stdBBper100HandsSum: Double = 0.0
sessions.forEach { session ->
stdSum += Math.pow(session.ratedNet - average, 2.0)
stdBBper100HandsSum += Math.pow(session.bbPer100Hands - bbPer100Hands, 2.0)
}
val standardDeviation: Double = Math.sqrt(stdSum / sessions.size)
val standardDeviationBBper100Hands: Double = Math.sqrt(stdBBper100HandsSum / sessions.size)
// Session Set
var hourlyStdSum: Double = 0.0
sessionSets.forEach { set ->
hourlyStdSum += Math.pow(set.hourlyRate - hourlyRate, 2.0)
}
val hourlyStandardDeviation: Double = Math.sqrt(hourlyStdSum / sessionSets.size)
results.addStats(setOf(
ComputedStat(STANDARD_DEVIATION, standardDeviation),
ComputedStat(STANDARD_DEVIATION_HOURLY, hourlyStandardDeviation),
ComputedStat(STANDARD_DEVIATION_BB_PER_100_HANDS, standardDeviationBBper100Hands)
))
}
return results
}
}
totalBuyin += s.buyin
totalHands += s.estimatedHands
when (options.evolutionValues) {
Options.EvolutionValues.STANDARD -> {
results.addEvolutionValue(sum, NETRESULT)
results.addEvolutionValue(sum / index, AVERAGE)
results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES)
results.addEvolutionValue(bbSum / bbSessionCount, AVERAGE_NET_BB)
results.addEvolutionValue((winningSessionCount / index).toDouble(), WIN_RATIO)
results.addEvolutionValue(totalBuyin / index, AVERAGE_BUYIN)
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)
}
}
}
}
// Compute for each serie
var duration: Double = 0.0
var hourlyRate: Double = 0.0
var hourlyRateBB: Double = 0.0
var gIndex = 0;
var gSum = 0.0;
var gTotalHands = 0.0;
var gBBSum = 0.0;
sessionSets.forEach { sessionSet ->
gIndex++
duration += sessionSet.hourlyDuration
gSum += sessionSet.ratedNet
gTotalHands += sessionSet.estimatedHands
gBBSum += sessionSet.bbNetResult
hourlyRate = gSum / duration
hourlyRateBB = gBBSum / duration
when (options.evolutionValues) {
Options.EvolutionValues.DATED -> {
results.addEvolutionValue(gSum, duration, NETRESULT)
results.addEvolutionValue(gSum / duration, duration, HOURLY_RATE)
results.addEvolutionValue(hourlyRate, duration, HOURLY_RATE)
results.addEvolutionValue(gIndex.toDouble(), duration, NUMBER_OF_SETS)
results.addEvolutionValue(sessionSet.netDuration.toDouble(), duration, DURATION)
results.addEvolutionValue(duration / gIndex, duration, AVERAGE_DURATION)
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)
}
}
}
}
var average = 0.0
if (sessions.size > 0) {
average = sum / sessions.size.toDouble()
val winRatio = winningSessionCount.toDouble() / sessions.size.toDouble()
val avgBuyin = totalBuyin / sessions.size
results.addStats(
setOf(
ComputedStat(AVERAGE, average),
ComputedStat(WIN_RATIO, winRatio),
ComputedStat(AVERAGE_BUYIN, avgBuyin)
)
)
}
if (sessionSets.size > 0) {
val avgDuration = duration / sessionSets.size
results.addStats(
setOf(
ComputedStat(HOURLY_RATE, hourlyRate),
ComputedStat(AVERAGE_DURATION, avgDuration)
)
)
}
// Create stats
results.addStats(
setOf(
ComputedStat(NETRESULT, sum),
ComputedStat(DURATION, duration),
ComputedStat(NUMBER_OF_SETS, sessionSets.size.toDouble()),
ComputedStat(NUMBER_OF_GAMES, sessions.size.toDouble()),
ComputedStat(HOURLY_RATE_BB, bbSum / duration),
ComputedStat(AVERAGE_NET_BB, bbSum / bbSessionCount),
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
// Standard Deviation
if (options.shouldComputeStandardDeviation()) {
// Session
var stdSum: Double = 0.0
var stdBBper100HandsSum: Double = 0.0
sessions.forEach { session ->
stdSum += Math.pow(session.ratedNet - average, 2.0)
stdBBper100HandsSum += Math.pow(session.bbPer100Hands - bbPer100Hands, 2.0)
}
val standardDeviation: Double = Math.sqrt(stdSum / sessions.size)
val standardDeviationBBper100Hands: Double = Math.sqrt(stdBBper100HandsSum / sessions.size)
// Session Set
var hourlyStdSum: Double = 0.0
sessionSets.forEach { set ->
hourlyStdSum += Math.pow(set.hourlyRate - hourlyRate, 2.0)
}
val hourlyStandardDeviation: Double = Math.sqrt(hourlyStdSum / sessionSets.size)
results.addStats(
setOf(
ComputedStat(STANDARD_DEVIATION, standardDeviation),
ComputedStat(STANDARD_DEVIATION_HOURLY, hourlyStandardDeviation),
ComputedStat(STANDARD_DEVIATION_BB_PER_100_HANDS, standardDeviationBBper100Hands)
)
)
}
return results
}
}
}

@ -7,9 +7,6 @@ import io.realm.annotations.RealmClass
@RealmClass
open class Result : RealmObject() {
// the user associated to this session result
var player: Player? = null
// The buyin amount
var buyin: Double? = null
set(value) {

Loading…
Cancel
Save