diff --git a/app/src/androidTest/java/net/pokeranalytics/android/BankrollInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/BankrollInstrumentedUnitTest.kt index f2bb163b..72bc6a52 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/BankrollInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/BankrollInstrumentedUnitTest.kt @@ -3,7 +3,7 @@ package net.pokeranalytics.android import androidx.test.ext.junit.runners.AndroidJUnit4 import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.ComputedResults -import net.pokeranalytics.android.calculus.SessionGroup +import net.pokeranalytics.android.calculus.ComputableGroup import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Currency @@ -56,7 +56,7 @@ class BankrollInstrumentedUnitTest : RealmInstrumentedUnitTest() { realm.commitTransaction() val sessions = realm.where(Session::class.java).findAll() - val group = SessionGroup(name = "test", sessions = sessions) + val group = ComputableGroup(name = "test", computables = sessions) val options = Calculator.Options() diff --git a/app/src/androidTest/java/net/pokeranalytics/android/StatsInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/StatsInstrumentedUnitTest.kt index fdd5a18f..415030ea 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/StatsInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/StatsInstrumentedUnitTest.kt @@ -4,7 +4,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.realm.RealmResults import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.ComputedResults -import net.pokeranalytics.android.calculus.SessionGroup +import net.pokeranalytics.android.calculus.ComputableGroup import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.SessionSet @@ -77,7 +77,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { realm.commitTransaction() val sessions = realm.where(Session::class.java).findAll() - val group = SessionGroup(name = "test", sessions = sessions) + val group = ComputableGroup(name = "test", computables = sessions) val options = Calculator.Options() options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION) @@ -227,7 +227,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { realm.commitTransaction() val sessions = realm.where(Session::class.java).findAll() - val group = SessionGroup(name = "test", sessions = sessions) + val group = ComputableGroup(name = "test", computables = sessions) val options = Calculator.Options() options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION) @@ -294,7 +294,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { realm.commitTransaction() val sessions = realm.where(Session::class.java).findAll() - val group = SessionGroup(name = "test", sessions = sessions) + val group = ComputableGroup(name = "test", computables = sessions) val options = Calculator.Options() options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION) @@ -377,7 +377,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { realm.commitTransaction() val sessions = realm.where(Session::class.java).findAll() - val group = SessionGroup(name = "test", sessions = sessions) + val group = ComputableGroup(name = "test", computables = sessions) val options = Calculator.Options() options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION) @@ -396,7 +396,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { s1.deleteFromRealm() } - val group2 = SessionGroup(name = "test", sessions = sessions) + val group2 = ComputableGroup(name = "test", computables = sessions) val results2: ComputedResults = Calculator.compute(group2, options) val duration2 = results2.computedStat(Stat.DURATION) @@ -548,7 +548,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { } val sessions = realm.where(Session::class.java).findAll() - val group = SessionGroup(name = "test", sessions = sessions) + val group = ComputableGroup(name = "test", computables = sessions) val options = Calculator.Options() // options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION) diff --git a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt index 4b52ad4f..7bfb7c77 100644 --- a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt +++ b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt @@ -70,6 +70,64 @@ class PokerAnalyticsApplication : Application() { } } +// +// private fun createFakeStats() { +// +// val buyinList = arrayListOf(100.0, 200.0, 300.0, 500.0, 1000.0, 2000.0) +// val resultsList = arrayListOf( +// -2500.0, -2000.0, -1500.0, -1000.0, -500.0, 200.0, 1000.0, 1500.0, 2500.0 +// ) +// +// val commitFrequency = 100 +// +// Thread() { +// +// try { +// +// val realm = Realm.getDefaultInstance() +// +// // Test endedSessions +// val pstats = realm.where().findAll() +// if (pstats.size < 10) { +// +// val numberOfSessions = 2000 +// Timber.d("*** Start creating ${numberOfSessions} fake computables...") +// +// val s = Date() +// +// realm.beginTransaction() +// +// for (index in 0..numberOfSessions) { +// +// if (index % commitFrequency == 0) { +// Timber.d("****** committing at ${index} computables...") +// realm.commitTransaction() +// realm.beginTransaction() +// } +// +// val ps = realm.createObject(ComputableResult::class.java) +// ps.ratedBuyin = buyinList.random() +// ps.ratedNet = resultsList.random() +// +// } +// +// realm.commitTransaction() +// +// val e = Date() +// val duration = (e.time - s.time) / 1000.0 +// Timber.d("*** ended in ${duration} seconds") +// +// } +// +// realm.close() +// +// } catch (e: Exception) { +// Timber.e(e) +// } +// +// }.start() +// +// } private fun createFakeSessions() { @@ -92,8 +150,8 @@ class PokerAnalyticsApplication : Application() { val sessions = realm.where().findAll() if (sessions.size < 10) { - val numberOfSessions = 200 - Timber.d("*** Start creating ${numberOfSessions} fake sessions...") + val numberOfSessions = 2000 + Timber.d("*** Start creating ${numberOfSessions} fake computables...") val s = Date() @@ -102,7 +160,7 @@ class PokerAnalyticsApplication : Application() { for (index in 0..numberOfSessions) { if (index % commitFrequency == 0) { - Timber.d("****** committing at ${index} sessions...") + Timber.d("****** committing at ${index} computables...") realm.commitTransaction() realm.beginTransaction() } 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 1f122c39..95a6a611 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -1,7 +1,7 @@ package net.pokeranalytics.android.calculus import net.pokeranalytics.android.calculus.Stat.* -import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.calculus.interfaces.Computable import net.pokeranalytics.android.model.realm.SessionSet import timber.log.Timber import java.util.* @@ -66,7 +66,7 @@ class Calculator { /** * Computes all stats for list of Session sessionGroup */ - fun computeGroups(groups: List, options: Options): List { + fun computeGroups(groups: List, options: Options): List { val computedResults = mutableListOf() groups.forEach { group -> @@ -75,7 +75,7 @@ class Calculator { val results: ComputedResults = Calculator.compute(group, options = options) // Computes the compared sessionGroup if existing - val comparedGroup = group.comparedSessions + val comparedGroup = group.comparedComputables if (comparedGroup != null) { val comparedResults = Calculator.compute(comparedGroup, options = options) group.comparedComputedResults = comparedResults @@ -94,13 +94,13 @@ class Calculator { return computedResults } -// fun compute(sessionGroup: SessionGroup, options: Options): ComputedResults { +// fun compute(sessionGroup: ComputableGroup, options: Options): ComputedResults { // // var sum: Double = 0.0 -// val sessions: List = sessionGroup.sessions +// val computables: List = sessionGroup.computables // val results: ComputedResults = ComputedResults(sessionGroup) // -// sessions.forEach { s -> +// computables.forEach { s -> // sum += s.ratedNet // } // @@ -117,34 +117,34 @@ class Calculator { /** * Computes stats for a SessionSet */ - fun compute(sessionGroup: SessionGroup, options: Options): ComputedResults { + fun compute(computableGroup: ComputableGroup, options: Options): ComputedResults { - Timber.d(">>>> Start computing group ${sessionGroup.name}, ${sessionGroup.sessions.size} sessions") + Timber.d(">>>> Start computing group ${computableGroup.name}, ${computableGroup.computables.size} computables") - val sessions: List = sessionGroup.sessions - val sessionSets = sessionGroup.sessions.mapNotNull { it.sessionSet }.toHashSet() + val computables: List = computableGroup.computables + val sessionSets = computableGroup.computables.mapNotNull { it.sessionSet }.toHashSet() - val results: ComputedResults = ComputedResults(sessionGroup) + val results: ComputedResults = ComputedResults(computableGroup) 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 winningSessionCount: Int = 0 // computables.filter { it.value >= 0.0 }.size var totalBuyin = 0.0 // Compute for each session var index: Int = 0 - sessions.forEach { s -> + computables.forEach { s -> index++; - val result = s.result!! // ok to crash to see problems +// val result = s.result!! // ok to crash to see problems - sum += result.ratedNet + sum += s.ratedNet bbSum += s.bbNetResult bbSessionCount += s.hasBigBlind - winningSessionCount = result.isPositive - totalBuyin += s.buyin + winningSessionCount += s.isPositive + totalBuyin += s.ratedBuyin totalHands += s.estimatedHands when (options.evolutionValues) { @@ -212,10 +212,10 @@ class Calculator { } 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 + if (computables.size > 0) { + average = sum / computables.size.toDouble() + val winRatio = winningSessionCount.toDouble() / computables.size.toDouble() + val avgBuyin = totalBuyin / computables.size results.addStats( setOf( @@ -242,7 +242,7 @@ class Calculator { ComputedStat(NETRESULT, sum), ComputedStat(DURATION, duration), ComputedStat(NUMBER_OF_SETS, sessionSets.size.toDouble()), - ComputedStat(NUMBER_OF_GAMES, sessions.size.toDouble()), + ComputedStat(NUMBER_OF_GAMES, computables.size.toDouble()), ComputedStat(HOURLY_RATE_BB, bbSum / duration), ComputedStat(AVERAGE_NET_BB, bbSum / bbSessionCount), ComputedStat(HANDS_PLAYED, totalHands) @@ -268,12 +268,12 @@ class Calculator { // Session var stdSum: Double = 0.0 var stdBBper100HandsSum: Double = 0.0 - sessions.forEach { session -> - stdSum += Math.pow(session.result!!.ratedNet - average, 2.0) + computables.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) + val standardDeviation: Double = Math.sqrt(stdSum / computables.size) + val standardDeviationBBper100Hands: Double = Math.sqrt(stdBBper100HandsSum / computables.size) // Session Set var hourlyStdSum: Double = 0.0 diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt b/app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt similarity index 89% rename from app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt rename to app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt index e8846fbd..520ee0f0 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt @@ -1,11 +1,11 @@ package net.pokeranalytics.android.calculus -import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.calculus.interfaces.Computable /** * A sessionGroup of computable items identified by a name */ -class SessionGroup(name: String, sessions: List, stats: List? = null) { +class ComputableGroup(name: String, computables: List, stats: List? = null) { /** * The display name of the group @@ -15,7 +15,7 @@ class SessionGroup(name: String, sessions: List, stats: List? = n /** * The list of endedSessions to compute */ - var sessions: List = sessions + var computables: List = computables /** * The list of stats to display @@ -25,7 +25,7 @@ class SessionGroup(name: String, sessions: List, stats: List? = n /** * A subgroup used to compute stat variation */ - var comparedSessions: SessionGroup? = null + var comparedComputables: ComputableGroup? = null /** * The computed stats of the comparable sessionGroup @@ -34,12 +34,12 @@ class SessionGroup(name: String, sessions: List, stats: List? = n } -class ComputedResults(group: SessionGroup) { +class ComputedResults(group: ComputableGroup) { /** * The session group used to computed the stats */ - var group: SessionGroup = group + var group: ComputableGroup = group // The computed stats of the sessionGroup private var _computedStats: MutableMap = mutableMapOf() diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt index 8e254483..cd830a50 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt @@ -1,6 +1,6 @@ package net.pokeranalytics.android.calculus.bankroll -import net.pokeranalytics.android.calculus.`interface`.DatableValue +import net.pokeranalytics.android.calculus.interfaces.DatableValue import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Transaction import java.util.* @@ -73,7 +73,7 @@ class BankrollReport(setup: BankrollReportSetup) { private set /** - * The net result from poker sessions + * The net result from poker computables */ var netResult: Double = 0.0 private set diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/interfaces/Computable.kt b/app/src/main/java/net/pokeranalytics/android/calculus/interfaces/Computable.kt new file mode 100644 index 00000000..d3d91520 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/calculus/interfaces/Computable.kt @@ -0,0 +1,17 @@ +package net.pokeranalytics.android.calculus.interfaces + +import net.pokeranalytics.android.model.realm.SessionSet + +interface Computable { + + var ratedNet: Double + var bbNetResult: Double + var hasBigBlind: Int + var isPositive: Int + var ratedBuyin: Double + var estimatedHands: Double + var bbPer100Hands: Double + + var sessionSet: SessionSet? + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/interface/Datable.kt b/app/src/main/java/net/pokeranalytics/android/calculus/interfaces/Datable.kt similarity index 67% rename from app/src/main/java/net/pokeranalytics/android/calculus/interface/Datable.kt rename to app/src/main/java/net/pokeranalytics/android/calculus/interfaces/Datable.kt index 56fe1000..7e8855f2 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/interface/Datable.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/interfaces/Datable.kt @@ -1,4 +1,4 @@ -package net.pokeranalytics.android.calculus.`interface` +package net.pokeranalytics.android.calculus.interfaces import java.util.* diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/FilterComponent.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/FilterComponent.kt index 6a399360..157ed965 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/FilterComponent.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/FilterComponent.kt @@ -27,7 +27,7 @@ enum class SessionFilterable(var fieldName:String? = null) : Filterable { TOURNAMENT_FEATURES("tournamentFeature.id"), TOURNAMENT_NUMBER_OF_PLAYER("tournamentNumberOfPlayers"), TOURNAMENT_ENTRY_FEE("tournamentEntryFee"), - RESULT_BUYIN("result.buyin"), + RESULT_BUYIN("result.ratedBuyin"), RESULT_CASHED_OUT("result.cashout"), RESULT_NET("result.ratedNet"), RESULT_TIPS("result.tips"), diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt new file mode 100644 index 00000000..5f6223dd --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt @@ -0,0 +1,51 @@ +package net.pokeranalytics.android.model.realm + +import io.realm.RealmObject +import io.realm.RealmResults +import io.realm.annotations.Ignore +import io.realm.annotations.LinkingObjects +import net.pokeranalytics.android.calculus.interfaces.Computable + +open class ComputableResult : RealmObject(), Computable { + + override var ratedNet: Double = 0.0 + + override var bbNetResult: Double = 0.0 + + override var hasBigBlind: Int = 0 + + override var isPositive: Int = 0 + + override var ratedBuyin: Double = 0.0 + + override var estimatedHands: Double = 0.0 + + override var bbPer100Hands: Double = 0.0 + + override var sessionSet: SessionSet? = null + + @LinkingObjects("computableResult") + private val sessions: RealmResults? = null + + @Ignore + val session: Session? = this.sessions?.firstOrNull() + + fun updateWith(session: Session) { + + val rate = session.bankroll?.currency?.rate ?: 1.0 + + session.result?.let { result -> + this.ratedNet = result.net * rate + this.isPositive = result.isPositive + this.ratedBuyin = (result.buyin ?: 0.0) * rate + } + this.bbNetResult = session.bbNetResult + this.hasBigBlind = session.hasBigBlind + this.estimatedHands = session.estimatedHands + this.bbPer100Hands = session.bbPer100Hands + + this.sessionSet = session.sessionSet + + } + +} diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt index 5f3baf30..5f6f4fc2 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt @@ -15,5 +15,24 @@ open class Currency : RealmObject() { // The rate of the currency with the main currency var rate: Double? = null + set(value) { + field = value + + val rate = value ?: 1.0 + + // could be async + + val cResults = this.realm.where(ComputableResult::class.java).equalTo("session.bankroll.currency", this.id).findAll() + cResults.forEach { computable -> + + computable.session?.result?.net?.let { + computable.ratedNet = it * rate + } + computable.session?.result?.buyin?.let { + computable.ratedBuyin = it * rate + } + + } + } } \ No newline at end of file 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 2b674f1a..b9ef6e21 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 @@ -2,47 +2,52 @@ package net.pokeranalytics.android.model.realm import io.realm.RealmList import io.realm.RealmObject +import io.realm.RealmResults +import io.realm.annotations.Ignore +import io.realm.annotations.LinkingObjects import io.realm.annotations.RealmClass @RealmClass open class Result : RealmObject() { - // The buyin amount + /** + * The buyin amount + */ var buyin: Double? = null set(value) { field = value this.computeNet() } - // the cashed out amount + /** + * The cashed out amount + */ var cashout: Double? = null set(value) { field = value this.computeNet() } - // Tips - var tips: Double? = null - - // The net result - var netResult: Double? = null - set(value) { - field = value - this.computeNet() - } - /** - * The pre-computed net (readonly) - */ - var net: Double = 0.0 - private set + * The net result + */ + var netResult: Double? = null + set(value) { + field = value + this.computeNet() + } /** - * The pre-computed rated net (readonly) + * The pre-computed net (readonly) */ - var ratedNet: Double = 0.0 + var net: Double = 0.0 private set + /** + * Tips + */ + var tips: Double? = null + // The transactions associated with the Result, impacting the result var transactions: RealmList = RealmList() set(value) { @@ -53,23 +58,17 @@ 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 + @LinkingObjects("result") + private val sessions: RealmResults? = null - /** - * The associated Session - */ -// @Ignore -// val session: Session? = this.sessions?.firstOrNull() + @Ignore + val session: Session? = this.sessions?.firstOrNull() /** * Returns 1 if the session is positive */ - var isPositive: Int = 0 + @Ignore + val isPositive: Int = if (this.net >= 0.0) 1 else 0 // Computes the Net private fun computeNet() { @@ -82,11 +81,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 + + // Update ComputableResult + this.session?.updateComputableResult() } -// private var rate: Double = (this.session?.bankroll?.currency?.rate ?: 1.0) + // @todo tips? - // @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 2f19b5bf..76816b65 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 @@ -5,6 +5,7 @@ import io.realm.Realm import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.Ignore +import io.realm.annotations.Index import io.realm.annotations.PrimaryKey import io.realm.kotlin.where import net.pokeranalytics.android.R @@ -36,6 +37,18 @@ import kotlin.collections.ArrayList open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable, Timed { +// @Ignore +// var rate: Double = 0.0 +// get() = this.bankroll?.currency?.rate ?: 0.0 +// +// @Ignore +// override var ratedNet: Double = 0.0 +// get() = this.result!!.net * this.rate +// +// @Ignore +// override var isPositive: Int = 0 +// get() = this.result!!.isPositive + enum class Type { CASH_GAME, TOURNAMENT @@ -45,6 +58,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource fun newInstance(realm: Realm, isTournament: Boolean, bankroll: Bankroll? = null): Session { val session = Session() session.result = Result() + session.computableResult = ComputableResult() if (bankroll != null) { session.bankroll = bankroll } else { @@ -66,6 +80,11 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource // The result of the main user var result: Result? = null + /** + * Optimized result for faster stats + */ + var computableResult: ComputableResult? = null + // Timed interface /** @@ -75,23 +94,24 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource 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 } this.dateChanged() + this.computeStats() } /** * the end date of the session */ + @Index var endDate: Date? = null set(value) { field = value this.computeNetDuration() - this.computeStats() this.dateChanged() + this.computeStats() } /** @@ -166,6 +186,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource set(value) { this.hasBigBlind = if (value != null) 1 else 0 field = value + this.updateComputableResult() } // Tournament @@ -195,6 +216,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource } else if (this.sessionSet != null) { SessionSetManager.removeFromTimeline(this) } + this.updateComputableResult() this.updateRowRepresentation() } @@ -258,6 +280,15 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource this.computeEstimatedHands() this.computeBBNetResult() this.computeBBPer100Hands() + this.updateComputableResult() + } + + fun updateComputableResult() { + this.computableResult?.let { + it.updateWith(this) + } ?: run { + throw IllegalStateException("Session should always have a Light Result") + } } /** @@ -295,7 +326,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource private set @Ignore - var buyin: Double = 0.0 + var ratedBuyin: Double = 0.0 get() { this.result?.let { result -> result.buyin?.let { @@ -472,7 +503,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource } @Ignore - private var rowRepresentationForCurrentState : List = this.updatedRowRepresentationForCurrentState() + private var rowRepresentationForCurrentState : List = mutableListOf() private fun updatedRowRepresentationForCurrentState(): List { val rows = ArrayList() @@ -541,7 +572,6 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource override fun adapterRows(): List? { return this.rowRepresentationForCurrentState - } override fun boolForRow(row: RowRepresentable): Boolean { @@ -624,7 +654,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource SessionRow.BUY_IN -> row.editingDescriptors(mapOf( "bb" to cgBigBlind, "fee" to this.tournamentEntryFee, - "buyin" to buyin + "ratedBuyin" to ratedBuyin )) SessionRow.BREAK_TIME -> row.editingDescriptors(mapOf()) SessionRow.CASHED_OUT, SessionRow.PRIZE, SessionRow.NET_RESULT -> row.editingDescriptors(mapOf( 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 8c5baa63..480cb220 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.result!!.ratedNet } ?: 0.0 + val ratedNet: Double = this.sessions?.sumByDouble { it.computableResult!!.ratedNet } ?: 0.0 @Ignore val hourlyRate: Double = this.ratedNet / this.hourlyDuration diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt index 0d68efc2..6230ef7b 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt @@ -10,8 +10,9 @@ import kotlinx.android.synthetic.main.fragment_stats.* import kotlinx.coroutines.* import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.* +import net.pokeranalytics.android.calculus.interfaces.Computable import net.pokeranalytics.android.model.StatRepresentable -import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.ui.adapter.DisplayDescriptor import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource @@ -92,7 +93,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc // Override override fun sessionsChanged() { -// this.launchStatComputation() + this.launchStatComputation() this.statsAdapter.notifyDataSetChanged() } @@ -109,26 +110,6 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc private fun launchStatComputation() { -// Thread() { -//// var results = listOf() -// val s = Date() -// Timber.d(">>> start...") -// -// val results = createSessionGroupsAndStartCompute() -// -// val e = Date() -// val duration = (e.time - s.time) / 1000.0 -// Timber.d(">>> ended in ${duration} seconds") -// -// -// val mainHandler = Handler(Looper.getMainLooper()) -// val runnable = Runnable { -// showResults(results) -// } -// mainHandler.post(runnable) -// -// }.start() - GlobalScope.launch(coroutineContext) { var results = listOf() @@ -151,35 +132,36 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc private fun createSessionGroupsAndStartCompute() : List { - val cgSessions = mutableListOf() - val tSessions = mutableListOf() + val cgSessions = mutableListOf() + val tSessions = mutableListOf() val s = Date() val realm = Realm.getDefaultInstance() - val allSessions = realm.where(Session::class.java).isNotNull("endDate").findAll() - Timber.d(">>>>> number of sessions to compute = ${allSessions.size}") +// val allSessions = realm.where(ComputableResult::class.java).findAll() + val allSessions = realm.where(ComputableResult::class.java).isNotNull("sessions.endDate").findAll() + Timber.d(">>>>> number of computables to compute = ${allSessions.size}") - val sessionsList = allSessions.toList() + val computableList = realm.copyFromRealm(allSessions) + realm.close() - val e = Date() - val duration = (e.time - s.time) / 1000.0 - Timber.d(">>> filtering in ${duration} seconds") - - sessionsList.forEach { session -> - if (session.isCashGame()) { + computableList.forEach { session -> + if (true) { // @todo cgSessions.add(session) } else { tSessions.add(session) } } + val e = Date() + val duration = (e.time - s.time) / 1000.0 + Timber.d(">>> filtering in ${duration} seconds") val allStats: List = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE, Stat.NUMBER_OF_SETS, Stat.AVERAGE_DURATION, Stat.DURATION) - val allSessionGroup = SessionGroup(getString(R.string.all), sessionsList, allStats) + val allSessionGroup = ComputableGroup(getString(R.string.all), computableList, allStats) val cgStats: List = 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 cgSessionGroup = ComputableGroup(getString(R.string.cash_game), cgSessions, cgStats) val tStats: List = 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) + val tSessionGroup = ComputableGroup(getString(R.string.tournament), tSessions, tStats) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/SessionObserverFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/SessionObserverFragment.kt index f974d937..2f5b288d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/SessionObserverFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/SessionObserverFragment.kt @@ -2,15 +2,15 @@ package net.pokeranalytics.android.ui.fragment.components import io.realm.Realm import io.realm.RealmResults -import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.model.realm.ComputableResult open class SessionObserverFragment : PokerAnalyticsFragment() { - val endedSessions: RealmResults + val endedSessions: RealmResults init { val realm = Realm.getDefaultInstance() - this.endedSessions = realm.where(Session::class.java).isNotNull("endDate").findAll() + this.endedSessions = realm.where(ComputableResult::class.java).isNotNull("sessions.endDate").findAll() this.endedSessions.addChangeListener { _, _ -> this.sessionsChanged() } diff --git a/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt b/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt index 5fe79392..40a6e864 100644 --- a/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt +++ b/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt @@ -27,7 +27,7 @@ class ExampleUnitTest : RealmUnitTest() { // override var estimatedHands: Double = 0.0 // override var bbNetResult: Double = 0.0 // override var bigBlindSessionCount: Int = 0 // 0 or 1 -// override var buyin: Double = 0.0 +// override var ratedBuyin: Double = 0.0 // // } // @@ -35,7 +35,7 @@ class ExampleUnitTest : RealmUnitTest() { // fun testStats() { // // val grades: List = listOf(Grade(10.0), Grade(20.0)) -// val group = SessionGroup(name = "test", sessions = grades) +// val group = ComputableGroup(name = "test", computables = grades) // // val results: ComputedResults = Calculator.compute(group, Calculator.Options()) //