diff --git a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt index 9119a8a3..371f98b9 100644 --- a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt +++ b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt @@ -90,7 +90,7 @@ class PokerAnalyticsApplication : Application() { val sessions = realm.where().findAll() if (sessions.size < 10) { - val numberOfSessions = 100 + val numberOfSessions = 200 Timber.d("*** Start creating ${numberOfSessions} fake sessions...") val s = Date() diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt index 75b016c4..1f7a1a93 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -1,6 +1,7 @@ package net.pokeranalytics.android.calculus import net.pokeranalytics.android.calculus.Stat.* +import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.SessionSet import timber.log.Timber @@ -113,7 +114,7 @@ class Calculator { Timber.d(">>>> Start computing group ${sessionGroup.name}, ${sessionGroup.sessions.size} sessions") - val sessions: List = sessionGroup.sessions + val sessions: List = sessionGroup.sessions val sessionSets = sessionGroup.sessions.mapNotNull { it.sessionSet }.toHashSet() val results: ComputedResults = ComputedResults(sessionGroup) @@ -130,12 +131,12 @@ class Calculator { sessions.forEach { s -> index++; - sum += s.ratedNet + val result = s.result!! // ok to crash to see problems + + sum += result.ratedNet bbSum += s.bbNetResult - bbSessionCount += s.bigBlindSessionCount - if (s.value >= 0) { - winningSessionCount++ - } + bbSessionCount += s.hasBigBlind + winningSessionCount = result.isPositive totalBuyin += s.buyin totalHands += s.estimatedHands @@ -164,9 +165,9 @@ class Calculator { } // Compute for each serie - var duration: Double = 0.0 - var hourlyRate: Double = 0.0 - var hourlyRateBB: Double = 0.0 + var duration = 0.0 + var hourlyRate = 0.0 + var hourlyRateBB = 0.0 var gIndex = 0; var gSum = 0.0; @@ -261,7 +262,7 @@ class Calculator { var stdSum: Double = 0.0 var stdBBper100HandsSum: Double = 0.0 sessions.forEach { session -> - stdSum += Math.pow(session.ratedNet - average, 2.0) + stdSum += Math.pow(session.result!!.ratedNet - average, 2.0) stdBBper100HandsSum += Math.pow(session.bbPer100Hands - bbPer100Hands, 2.0) } val standardDeviation: Double = Math.sqrt(stdSum / sessions.size) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt index c47a2b7f..e8846fbd 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt @@ -1,31 +1,11 @@ package net.pokeranalytics.android.calculus -import net.pokeranalytics.android.model.realm.SessionSet - -/** - * An interface to describe objects that can be summed - */ -interface Summable { - var value: Double -} - -/** - * An interface describing some class that can be computed - */ -interface SessionInterface : Summable { - var sessionSet: SessionSet? - var estimatedHands: Double - var bbNetResult: Double - var bigBlindSessionCount: Int // 0 or 1 - var buyin: Double - var bbPer100Hands: Double - var ratedNet: Double -} +import net.pokeranalytics.android.model.realm.Session /** * A sessionGroup of computable items identified by a name */ -class SessionGroup(name: String, sessions: List, stats: List? = null) { +class SessionGroup(name: String, sessions: List, stats: List? = null) { /** * The display name of the group @@ -35,7 +15,7 @@ class SessionGroup(name: String, sessions: List, stats: List = sessions + var sessions: List = sessions /** * The list of stats to display @@ -113,7 +93,7 @@ class ComputedResults(group: SessionGroup) { if (options.evolutionValues != Calculator.Options.EvolutionValues.NONE) { // Sort points as a distribution - this._computedStats.keys.filter { it.hasDistributionSorting() }.forEach { stat -> + this._computedStats.keys.filter { it.hasDistributionSorting() }.forEach { _ -> // @todo sort // var evolutionValues = this._evolutionValues[stat] // evolutionValues.so diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt index d16c0d5c..2b674f1a 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt @@ -31,11 +31,19 @@ open class Result : RealmObject() { this.computeNet() } - // The net (readonly) + /** + * The pre-computed net (readonly) + */ var net: Double = 0.0 private set - // The transactions associated with the Result, impacting the result + /** + * The pre-computed rated net (readonly) + */ + var ratedNet: Double = 0.0 + private set + + // The transactions associated with the Result, impacting the result var transactions: RealmList = RealmList() set(value) { field = value @@ -45,8 +53,26 @@ open class Result : RealmObject() { // The tournament final position, if applicable var tournamentFinalPosition: Int? = null + /** + * The automatically Realm-updated sessions list + * Should contain only one element + */ +// @LinkingObjects("result") +// private val sessions: RealmResults? = null + + /** + * The associated Session + */ +// @Ignore +// val session: Session? = this.sessions?.firstOrNull() + + /** + * Returns 1 if the session is positive + */ + var isPositive: Int = 0 + // Computes the Net - fun computeNet() { + private fun computeNet() { val transactionsSum = transactions.sumByDouble { it.amount } this.netResult?.let { @@ -56,8 +82,11 @@ open class Result : RealmObject() { val cashOut = this.cashout ?: 0.0 this.net = cashOut - buyin + transactionsSum } - + this.ratedNet = this.net * 1.0 + this.isPositive = if (this.ratedNet >= 0.0) 1 else 0 } +// private var rate: Double = (this.session?.bankroll?.currency?.rate ?: 1.0) + // @todo tips? } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt index e1a93915..0df35af9 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt @@ -10,7 +10,6 @@ import io.realm.annotations.PrimaryKey import io.realm.kotlin.where import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.ComputedStat -import net.pokeranalytics.android.calculus.SessionInterface import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.exceptions.ModelException import net.pokeranalytics.android.model.Limit @@ -30,14 +29,13 @@ import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.SeparatorRowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow -import net.pokeranalytics.android.util.* +import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.extensions.* import java.util.* import java.util.Currency import kotlin.collections.ArrayList -open class Session : RealmObject(), SessionInterface, Manageable, StaticRowRepresentableDataSource, RowRepresentable, - Timed { +open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable, Timed { enum class Type { CASH_GAME, @@ -78,6 +76,7 @@ open class Session : RealmObject(), SessionInterface, Manageable, StaticRowRepre set(value) { field = value this.computeNetDuration() + this.computeStats() // nullifies endate when setting the start date after the end date if (value != null && this.endDate != null && value.after(this.endDate)) { this.endDate = null @@ -92,6 +91,7 @@ open class Session : RealmObject(), SessionInterface, Manageable, StaticRowRepre set(value) { field = value this.computeNetDuration() + this.computeStats() this.dateChanged() } @@ -102,6 +102,7 @@ open class Session : RealmObject(), SessionInterface, Manageable, StaticRowRepre set(value) { field = value this.computeNetDuration() + this.computeStats() } /** @@ -118,16 +119,8 @@ open class Session : RealmObject(), SessionInterface, Manageable, StaticRowRepre this.updateRowRepresentation() } - - // The time frame of the Session, i.e. the start & end date -// var timeFrame: TimeFrame? = null -// set(value) { -// field = value -// value?.let { it.notifySessionDateChange(this) } -// } - // The time frame sessionGroup, which can contain multiple endedSessions - override var sessionSet: SessionSet? = null + var sessionSet: SessionSet? = null // the date of creation of the app var creationDate: Date = Date() @@ -171,6 +164,9 @@ open class Session : RealmObject(), SessionInterface, Manageable, StaticRowRepre // The big blind value var cgBigBlind: Double? = null + set(value) { + this.hasBigBlind = if (value != null) 1 else 0 + } // Tournament @@ -232,17 +228,38 @@ open class Session : RealmObject(), SessionInterface, Manageable, StaticRowRepre // Stats - @Ignore // SessionInterface value - override var value: Double = 0.0 - get() { - return this.result?.net ?: 0.0 - } - @Ignore val ONLINE_PLAYER_HANDS_PER_HOUR = 400.0 @Ignore val LIVE_PLAYER_HANDS_PER_HOUR = 250.0 + /** + * The estimation of hands played during the session + */ + var estimatedHands: Double = 0.0 + private set + + /** + * The result in big blinds + */ + var bbNetResult: Double = 0.0 + private set + + /** + * The number of big blinds won per 100 hands + */ + var bbPer100Hands: Double = 0.0 + private set + + /** + * Pre-compute various stats + */ + private fun computeStats() { + this.computeEstimatedHands() + this.computeBBNetResult() + this.computeBBPer100Hands() + } + /** * Approximates the number of hands played per hour at the table */ @@ -254,31 +271,31 @@ open class Session : RealmObject(), SessionInterface, Manageable, StaticRowRepre return playerHandsPerHour / tableSize.toDouble() } - @Ignore - override var estimatedHands: Double = this.numberOfHandsPerHour * this.hourlyDuration + private fun computeEstimatedHands() { + this.estimatedHands = this.numberOfHandsPerHour * this.hourlyDuration + } - @Ignore - override var bbNetResult: Double = 0.0 - get() { - this.cgBigBlind?.let { bb -> - this.result?.let { result -> - return result.net / bb - } - } - return 0.0 + private fun computeBBNetResult() { + val bb = this.cgBigBlind; val result = this.result + if (bb != null && result != null) { + this.bbNetResult = result.net / bb + } else { + this.bbNetResult = 0.0 } + } - @Ignore - override var bbPer100Hands: Double = 0.0 - get() { - return this.bbNetResult / this.estimatedHands * 100.0 - } + private fun computeBBPer100Hands() { + this.bbPer100Hands = this.bbNetResult / this.estimatedHands * 100 + } - @Ignore - override var bigBlindSessionCount: Int = if (this.cgBigBlind != null) 1 else 0 + /** + * Returns 1 if the session has big blinds, otherwise 0 + */ + var hasBigBlind: Int = 0 + private set @Ignore - override var buyin: Double = 0.0 + var buyin: Double = 0.0 get() { this.result?.let { result -> result.buyin?.let { @@ -296,17 +313,8 @@ open class Session : RealmObject(), SessionInterface, Manageable, StaticRowRepre throw ModelException("Session should have an existing Result relationship") } - override var ratedNet: Double = 0.0 - get() { - this.result?.net?.let { net -> - this.bankroll?.currency?.rate?.let { rate -> - return net * rate - } ?: run { - return net - } - } - return 0.0 - } +// @Ignore +// val ratedNet: Double = this.result?.ratedNet ?: 0.0 // States diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt index 8b211cdc..8c5baa63 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt @@ -68,7 +68,7 @@ open class SessionSet : RealmObject(), Timed { val sessions: RealmResults? = null @Ignore - val ratedNet: Double = this.sessions?.sumByDouble { it.ratedNet } ?: 0.0 + val ratedNet: Double = this.sessions?.sumByDouble { it.result!!.ratedNet } ?: 0.0 @Ignore val hourlyRate: Double = this.ratedNet / this.hourlyDuration