|
|
|
|
@ -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 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |