|
|
|
@ -27,7 +27,8 @@ class Calculator { |
|
|
|
class Options( |
|
|
|
class Options( |
|
|
|
display: Display = Display.TABLE, |
|
|
|
display: Display = Display.TABLE, |
|
|
|
evolutionValues: EvolutionValues = EvolutionValues.NONE, |
|
|
|
evolutionValues: EvolutionValues = EvolutionValues.NONE, |
|
|
|
stats: List<Stat> = listOf() |
|
|
|
stats: List<Stat> = listOf(), |
|
|
|
|
|
|
|
aggregationType: AggregationType? = null |
|
|
|
) { |
|
|
|
) { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -53,6 +54,7 @@ class Calculator { |
|
|
|
var display: Display = display |
|
|
|
var display: Display = display |
|
|
|
var evolutionValues: EvolutionValues = evolutionValues |
|
|
|
var evolutionValues: EvolutionValues = evolutionValues |
|
|
|
var displayedStats: List<Stat> = stats |
|
|
|
var displayedStats: List<Stat> = stats |
|
|
|
|
|
|
|
var aggregationType: AggregationType? = aggregationType |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* This function determines whether the standard deviation should be computed |
|
|
|
* This function determines whether the standard deviation should be computed |
|
|
|
@ -80,21 +82,37 @@ class Calculator { |
|
|
|
return this.displayedStats.contains(DAYS_PLAYED) |
|
|
|
return this.displayedStats.contains(DAYS_PLAYED) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val shouldManageMultiGroupProgressValues: Boolean |
|
|
|
|
|
|
|
get() { |
|
|
|
|
|
|
|
if (this.aggregationType != null) { |
|
|
|
|
|
|
|
return this.aggregationType == AggregationType.MONTH || this.aggregationType == AggregationType.YEAR |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
companion object { |
|
|
|
companion object { |
|
|
|
|
|
|
|
|
|
|
|
fun computeStatsWithEvolutionByAggregationType( |
|
|
|
fun computeStatsWithEvolutionByAggregationType( |
|
|
|
realm: Realm, |
|
|
|
realm: Realm, |
|
|
|
|
|
|
|
stat: Stat, |
|
|
|
group: ComputableGroup, |
|
|
|
group: ComputableGroup, |
|
|
|
aggregationType: AggregationType |
|
|
|
aggregationType: AggregationType, |
|
|
|
|
|
|
|
stats: List<Stat>? = null |
|
|
|
): Report { |
|
|
|
): Report { |
|
|
|
|
|
|
|
|
|
|
|
val options = Options(evolutionValues = Options.EvolutionValues.STANDARD) |
|
|
|
val options = Options(evolutionValues = Options.EvolutionValues.STANDARD, aggregationType = aggregationType) |
|
|
|
|
|
|
|
options.displayedStats = listOf(stat) |
|
|
|
if (aggregationType == AggregationType.DURATION) { |
|
|
|
if (aggregationType == AggregationType.DURATION) { |
|
|
|
options.evolutionValues = Options.EvolutionValues.TIMED |
|
|
|
options.evolutionValues = Options.EvolutionValues.TIMED |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stats?.let { |
|
|
|
|
|
|
|
options.displayedStats = stats |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return when (aggregationType) { |
|
|
|
return when (aggregationType) { |
|
|
|
AggregationType.SESSION, AggregationType.DURATION -> this.computeGroups(realm, listOf(group), options) |
|
|
|
AggregationType.SESSION, AggregationType.DURATION -> this.computeGroups(realm, listOf(group), options) |
|
|
|
AggregationType.MONTH -> { |
|
|
|
AggregationType.MONTH -> { |
|
|
|
@ -116,6 +134,8 @@ class Calculator { |
|
|
|
): Report { |
|
|
|
): Report { |
|
|
|
|
|
|
|
|
|
|
|
val computableGroups: MutableList<ComputableGroup> = mutableListOf() |
|
|
|
val computableGroups: MutableList<ComputableGroup> = mutableListOf() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var previousGroup: ComputableGroup? = null |
|
|
|
comparators.combined().forEach { comparatorConditions -> |
|
|
|
comparators.combined().forEach { comparatorConditions -> |
|
|
|
|
|
|
|
|
|
|
|
val allConditions = mutableListOf<QueryCondition>() |
|
|
|
val allConditions = mutableListOf<QueryCondition>() |
|
|
|
@ -123,8 +143,10 @@ class Calculator { |
|
|
|
allConditions.addAll(comparatorConditions) |
|
|
|
allConditions.addAll(comparatorConditions) |
|
|
|
|
|
|
|
|
|
|
|
val group = ComputableGroup(allConditions.name(), allConditions) |
|
|
|
val group = ComputableGroup(allConditions.name(), allConditions) |
|
|
|
|
|
|
|
group.comparedGroup = previousGroup |
|
|
|
computableGroups.add(group) |
|
|
|
computableGroups.add(group) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
previousGroup = group |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (computableGroups.size == 0) { |
|
|
|
if (computableGroups.size == 0) { |
|
|
|
@ -140,7 +162,7 @@ class Calculator { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
fun computeGroups(realm: Realm, groups: List<ComputableGroup>, options: Options): Report { |
|
|
|
fun computeGroups(realm: Realm, groups: List<ComputableGroup>, options: Options): Report { |
|
|
|
|
|
|
|
|
|
|
|
val report = Report() |
|
|
|
val report = Report(options) |
|
|
|
groups.forEach { group -> |
|
|
|
groups.forEach { group -> |
|
|
|
val s = Date() |
|
|
|
val s = Date() |
|
|
|
|
|
|
|
|
|
|
|
@ -151,7 +173,7 @@ class Calculator { |
|
|
|
val results: ComputedResults = this.compute(realm, group, options = options) |
|
|
|
val results: ComputedResults = this.compute(realm, group, options = options) |
|
|
|
|
|
|
|
|
|
|
|
// Computes the compared sessionGroup if existing |
|
|
|
// Computes the compared sessionGroup if existing |
|
|
|
val comparedGroup = group.comparedComputables |
|
|
|
val comparedGroup = group.comparedGroup |
|
|
|
if (comparedGroup != null) { |
|
|
|
if (comparedGroup != null) { |
|
|
|
val comparedResults = this.compute(realm, comparedGroup, options = options) |
|
|
|
val comparedResults = this.compute(realm, comparedGroup, options = options) |
|
|
|
group.comparedComputedResults = comparedResults |
|
|
|
group.comparedComputedResults = comparedResults |
|
|
|
@ -175,29 +197,70 @@ class Calculator { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
fun compute(realm: Realm, computableGroup: ComputableGroup, options: Options): ComputedResults { |
|
|
|
fun compute(realm: Realm, computableGroup: ComputableGroup, options: Options): ComputedResults { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val results = ComputedResults(computableGroup, options.shouldManageMultiGroupProgressValues) |
|
|
|
|
|
|
|
|
|
|
|
val computables = computableGroup.computables(realm) |
|
|
|
val computables = computableGroup.computables(realm) |
|
|
|
Timber.d(">>>> Start computing group ${computableGroup.name}, ${computables.size} computables") |
|
|
|
Timber.d(">>>> Start computing group ${computableGroup.name}, ${computables.size} computables") |
|
|
|
|
|
|
|
results.addStat(NUMBER_OF_GAMES, computables.size.toDouble()) |
|
|
|
|
|
|
|
|
|
|
|
if (options.computeLongestStreak) { |
|
|
|
if (options.computeLongestStreak) { |
|
|
|
computables.sort("session.startDate") |
|
|
|
computables.sort("session.startDate") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val results = ComputedResults(computableGroup) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val sum = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble() |
|
|
|
val sum = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble() |
|
|
|
|
|
|
|
results.addStat(NET_RESULT, sum) |
|
|
|
|
|
|
|
|
|
|
|
val totalHands = computables.sum(ComputableResult.Field.ESTIMATED_HANDS.identifier).toDouble() |
|
|
|
val totalHands = computables.sum(ComputableResult.Field.ESTIMATED_HANDS.identifier).toDouble() |
|
|
|
|
|
|
|
results.addStat(HANDS_PLAYED, totalHands) |
|
|
|
|
|
|
|
|
|
|
|
val bbSum = computables.sum(ComputableResult.Field.BB_NET.identifier).toDouble() |
|
|
|
val bbSum = computables.sum(ComputableResult.Field.BB_NET.identifier).toDouble() |
|
|
|
|
|
|
|
results.addStat(BB_NET_RESULT, bbSum) |
|
|
|
|
|
|
|
|
|
|
|
val bbSessionCount = computables.sum(ComputableResult.Field.HAS_BIG_BLIND.identifier).toInt() |
|
|
|
val bbSessionCount = computables.sum(ComputableResult.Field.HAS_BIG_BLIND.identifier).toInt() |
|
|
|
|
|
|
|
results.addStat(BB_SESSION_COUNT, bbSessionCount.toDouble()) |
|
|
|
|
|
|
|
|
|
|
|
val winningSessionCount = computables.sum(ComputableResult.Field.IS_POSITIVE.identifier).toInt() |
|
|
|
val winningSessionCount = computables.sum(ComputableResult.Field.IS_POSITIVE.identifier).toInt() |
|
|
|
|
|
|
|
results.addStat(WINNING_SESSION_COUNT, winningSessionCount.toDouble()) |
|
|
|
|
|
|
|
|
|
|
|
val totalBuyin = computables.sum(ComputableResult.Field.RATED_BUYIN.identifier).toDouble() |
|
|
|
val totalBuyin = computables.sum(ComputableResult.Field.RATED_BUYIN.identifier).toDouble() |
|
|
|
|
|
|
|
results.addStat(TOTAL_BUYIN, totalBuyin) |
|
|
|
|
|
|
|
|
|
|
|
val maxNetResult = computables.max(ComputableResult.Field.RATED_NET.identifier)?.toDouble() |
|
|
|
val maxNetResult = computables.max(ComputableResult.Field.RATED_NET.identifier)?.toDouble() |
|
|
|
|
|
|
|
maxNetResult?.let { |
|
|
|
|
|
|
|
results.addStat(MAXIMUM_NETRESULT, it) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val minNetResult = computables.min(ComputableResult.Field.RATED_NET.identifier)?.toDouble() |
|
|
|
val minNetResult = computables.min(ComputableResult.Field.RATED_NET.identifier)?.toDouble() |
|
|
|
|
|
|
|
minNetResult?.let { |
|
|
|
|
|
|
|
results.addStat(MINIMUM_NETRESULT, it) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Stat.netBBPer100Hands(bbSum, totalHands)?.let { netBB100 -> |
|
|
|
|
|
|
|
results.addStat(NET_BB_PER_100_HANDS, netBB100) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Stat.returnOnInvestment(sum, totalBuyin)?.let { roi -> |
|
|
|
|
|
|
|
results.addStat(ROI, roi) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (options.computeLocationsPlayed) { |
|
|
|
if (options.computeLocationsPlayed) { |
|
|
|
results.addStat(LOCATIONS_PLAYED, computables.distinctBy { it.session?.location?.id }.size.toDouble()) |
|
|
|
results.addStat(LOCATIONS_PLAYED, computables.distinctBy { it.session?.location?.id }.size.toDouble()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var average = 0.0 // also used for standard deviation later |
|
|
|
|
|
|
|
if (computables.size > 0) { |
|
|
|
|
|
|
|
average = sum / computables.size.toDouble() |
|
|
|
|
|
|
|
val winRatio = winningSessionCount.toDouble() / computables.size.toDouble() |
|
|
|
|
|
|
|
val avgBuyin = totalBuyin / computables.size.toDouble() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
results.addStats( |
|
|
|
|
|
|
|
setOf( |
|
|
|
|
|
|
|
ComputedStat(AVERAGE, average), |
|
|
|
|
|
|
|
ComputedStat(WIN_RATIO, winRatio), |
|
|
|
|
|
|
|
ComputedStat(AVERAGE_BUYIN, avgBuyin) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val shouldIterateOverComputables = |
|
|
|
val shouldIterateOverComputables = |
|
|
|
(options.evolutionValues == Options.EvolutionValues.STANDARD || options.computeLongestStreak) |
|
|
|
(options.evolutionValues == Options.EvolutionValues.STANDARD || options.computeLongestStreak) |
|
|
|
|
|
|
|
|
|
|
|
@ -242,7 +305,7 @@ class Calculator { |
|
|
|
|
|
|
|
|
|
|
|
val session = |
|
|
|
val session = |
|
|
|
computable.session ?: throw IllegalStateException("Computing lone ComputableResult") |
|
|
|
computable.session ?: throw IllegalStateException("Computing lone ComputableResult") |
|
|
|
results.addEvolutionValue(tSum, stat = NETRESULT, data = session) |
|
|
|
results.addEvolutionValue(tSum, stat = NET_RESULT, data = session) |
|
|
|
results.addEvolutionValue(tSum / index, stat = AVERAGE, data = session) |
|
|
|
results.addEvolutionValue(tSum / index, stat = AVERAGE, data = session) |
|
|
|
results.addEvolutionValue(index.toDouble(), stat = NUMBER_OF_GAMES, data = session) |
|
|
|
results.addEvolutionValue(index.toDouble(), stat = NUMBER_OF_GAMES, data = session) |
|
|
|
results.addEvolutionValue(tBBSum / tBBSessionCount, stat = AVERAGE_NET_BB, data = session) |
|
|
|
results.addEvolutionValue(tBBSum / tBBSessionCount, stat = AVERAGE_NET_BB, data = session) |
|
|
|
@ -275,6 +338,7 @@ class Calculator { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val sessionSets = computableGroup.sessionSets(realm) |
|
|
|
val sessionSets = computableGroup.sessionSets(realm) |
|
|
|
|
|
|
|
results.addStat(NUMBER_OF_SETS, sessionSets.size.toDouble()) |
|
|
|
|
|
|
|
|
|
|
|
var gHourlyDuration: Double? = null |
|
|
|
var gHourlyDuration: Double? = null |
|
|
|
var gBBSum: Double? = null |
|
|
|
var gBBSum: Double? = null |
|
|
|
@ -343,7 +407,7 @@ class Calculator { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
Options.EvolutionValues.TIMED -> { |
|
|
|
Options.EvolutionValues.TIMED -> { |
|
|
|
results.addEvolutionValue(tRatedNetSum, tHourlyDuration, NETRESULT, sessionSet) |
|
|
|
results.addEvolutionValue(tRatedNetSum, tHourlyDuration, NET_RESULT, sessionSet) |
|
|
|
results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, sessionSet) |
|
|
|
results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, sessionSet) |
|
|
|
results.addEvolutionValue( |
|
|
|
results.addEvolutionValue( |
|
|
|
tIndex.toDouble(), |
|
|
|
tIndex.toDouble(), |
|
|
|
@ -389,23 +453,7 @@ class Calculator { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var average = 0.0 |
|
|
|
|
|
|
|
var hourlyRate = 0.0 |
|
|
|
var hourlyRate = 0.0 |
|
|
|
|
|
|
|
|
|
|
|
if (computables.size > 0) { |
|
|
|
|
|
|
|
average = sum / computables.size.toDouble() |
|
|
|
|
|
|
|
val winRatio = winningSessionCount.toDouble() / computables.size.toDouble() |
|
|
|
|
|
|
|
val avgBuyin = totalBuyin / computables.size |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
results.addStats( |
|
|
|
|
|
|
|
setOf( |
|
|
|
|
|
|
|
ComputedStat(AVERAGE, average), |
|
|
|
|
|
|
|
ComputedStat(WIN_RATIO, winRatio), |
|
|
|
|
|
|
|
ComputedStat(AVERAGE_BUYIN, avgBuyin) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (gHourlyDuration != null) { |
|
|
|
if (gHourlyDuration != null) { |
|
|
|
|
|
|
|
|
|
|
|
hourlyRate = sum / gHourlyDuration |
|
|
|
hourlyRate = sum / gHourlyDuration |
|
|
|
@ -424,29 +472,6 @@ class Calculator { |
|
|
|
results.addStat(AVERAGE_NET_BB, gBBSum / bbSessionCount) |
|
|
|
results.addStat(AVERAGE_NET_BB, gBBSum / bbSessionCount) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Create stats |
|
|
|
|
|
|
|
results.addStats( |
|
|
|
|
|
|
|
setOf( |
|
|
|
|
|
|
|
ComputedStat(NETRESULT, sum), |
|
|
|
|
|
|
|
ComputedStat(NUMBER_OF_SETS, sessionSets.size.toDouble()), |
|
|
|
|
|
|
|
ComputedStat(NUMBER_OF_GAMES, computables.size.toDouble()), |
|
|
|
|
|
|
|
ComputedStat(HANDS_PLAYED, totalHands) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Stat.returnOnInvestment(sum, totalBuyin)?.let { roi -> |
|
|
|
|
|
|
|
results.addStat(ROI, roi) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Stat.netBBPer100Hands(bbSum, totalHands)?.let { netBB100 -> |
|
|
|
|
|
|
|
results.addStat(NET_BB_PER_100_HANDS, netBB100) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maxNetResult?.let { max -> |
|
|
|
|
|
|
|
results.addStat(MAXIMUM_NETRESULT, max) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
minNetResult?.let { min -> |
|
|
|
|
|
|
|
results.addStat(MINIMUM_NETRESULT, min) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
maxDuration?.let { maxd -> |
|
|
|
maxDuration?.let { maxd -> |
|
|
|
results.addStat(MAXIMUM_DURATION, maxd) // (milliseconds to hours) |
|
|
|
results.addStat(MAXIMUM_DURATION, maxd) // (milliseconds to hours) |
|
|
|
} |
|
|
|
} |
|
|
|
@ -489,7 +514,6 @@ class Calculator { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class SSStats(sessionSet: SessionSet, conditions: List<QueryCondition>) { // Session Set Stats |
|
|
|
class SSStats(sessionSet: SessionSet, conditions: List<QueryCondition>) { // Session Set Stats |
|
|
|
|