From 77f9fd44f59f21be4804f192f7cb332f8a6d793e Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 2 Apr 2019 11:59:58 +0200 Subject: [PATCH] Fixes tests, states and bugs --- .../components/RealmInstrumentedUnitTest.kt | 4 +- .../unitTests/StatsInstrumentedUnitTest.kt | 143 ++++++++---------- .../android/calculus/Calculator.kt | 43 +++--- .../android/model/realm/Result.kt | 2 +- .../android/model/realm/Session.kt | 25 ++- .../android/model/utils/SessionSetManager.kt | 31 ++-- 6 files changed, 122 insertions(+), 126 deletions(-) diff --git a/app/src/androidTest/java/net/pokeranalytics/android/components/RealmInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/components/RealmInstrumentedUnitTest.kt index e78adf39..7df48545 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/components/RealmInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/components/RealmInstrumentedUnitTest.kt @@ -2,7 +2,6 @@ package net.pokeranalytics.android.components import io.realm.Realm import io.realm.RealmConfiguration -import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.model.realm.Result import net.pokeranalytics.android.model.realm.Session import org.junit.After @@ -18,8 +17,7 @@ open class RealmInstrumentedUnitTest { fun newSessionInstance(realm: Realm) : Session { val session = realm.createObject(Session::class.java, UUID.randomUUID().toString()) - val computableResult = realm.createObject(ComputableResult::class.java) - computableResult.session = session + session.startDate = Date() session.result = realm.createObject(Result::class.java) return session } diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt index cbbacfc8..c4d22653 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt @@ -3,11 +3,11 @@ package net.pokeranalytics.android.unitTests import androidx.test.ext.junit.runners.AndroidJUnit4 import io.realm.RealmList import io.realm.RealmResults -import net.pokeranalytics.android.components.RealmInstrumentedUnitTest import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.ComputableGroup import net.pokeranalytics.android.calculus.ComputedResults import net.pokeranalytics.android.calculus.Stat +import net.pokeranalytics.android.components.RealmInstrumentedUnitTest import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.model.realm.Currency import org.junit.Assert @@ -33,7 +33,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { endDate: Int = 1, bankroll: Bankroll? = null, game: Game? = null, - location : Location? = null, + location: Location? = null, tournamentName: TournamentName? = null, tournamentFeatures: RealmList = RealmList(), numberOfTable: Int = 1, @@ -48,8 +48,8 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { session.limit = limit session.numberOfTables = numberOfTable session.tableSize = tableSize - session.result?.netResult = netResult session.startDate = startDate + session.result?.netResult = netResult val cal = Calendar.getInstance() // creates calendar cal.time = startDate // sets calendar time/date cal.add(Calendar.HOUR_OF_DAY, endDate) // adds one hour @@ -81,6 +81,11 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { fun testSessionStats() { val realm = this.mockRealm + + val computableResults = realm.where(ComputableResult::class.java).findAll() + + assertEquals(0, computableResults.size) + realm.beginTransaction() val s1 = newSessionInstance(realm) @@ -95,10 +100,6 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { s2.tableSize = 5 - realm.insert(s1) - realm.insert(s2) - realm.commitTransaction() - val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sd1 = sdf.parse("01/1/2019 10:00") @@ -106,19 +107,22 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { val sd2 = sdf.parse("02/1/2019 08:00") val ed2 = sdf.parse("02/1/2019 11:00") // 3 hours - realm.beginTransaction() - s1.startDate = sd1 s1.endDate = ed1 s2.startDate = sd2 s2.endDate = ed2 - realm.copyToRealmOrUpdate(s1) - realm.copyToRealmOrUpdate(s2) + val d1 = s1.sessionSet?.netDuration + val d2 = s2.sessionSet?.netDuration realm.commitTransaction() - val computableResults = realm.where(ComputableResult::class.java).findAll() + assertEquals(2, computableResults.size) + + computableResults.forEach { + println(">>>>>> rated net = ${it.ratedNet} ") + } + val sets = realm.where(SessionSet::class.java).findAll() val stats: List = listOf(Stat.NETRESULT, Stat.AVERAGE) val group = ComputableGroup("test", computableResults, sets, stats) @@ -239,33 +243,28 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { fun testOverlappingSessions1() { val realm = this.mockRealm - realm.beginTransaction() - - val s1 = newSessionInstance(realm) - val s2 = newSessionInstance(realm) - realm.insert(s1) - realm.insert(s2) + realm.executeTransaction { - val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") + val s1 = newSessionInstance(realm) + val s2 = newSessionInstance(realm) - val sd1 = sdf.parse("01/1/2019 09:00") - val ed1 = sdf.parse("01/1/2019 10:00") - val sd2 = sdf.parse("01/1/2019 08:00") - val ed2 = sdf.parse("01/1/2019 11:00") + val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") - s1.startDate = sd1 - s1.endDate = ed1 - s2.startDate = sd2 - s2.endDate = ed2 + val sd1 = sdf.parse("01/1/2019 09:00") + val ed1 = sdf.parse("01/1/2019 10:00") + val sd2 = sdf.parse("01/1/2019 08:00") + val ed2 = sdf.parse("01/1/2019 11:00") - // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800 - // netDuration = 4h, hourly = 100, bb100 = 150 / 75 * 100 = +200 + s1.startDate = sd1 + s1.endDate = ed1 + s2.startDate = sd2 + s2.endDate = ed2 - realm.copyToRealmOrUpdate(s1) - realm.copyToRealmOrUpdate(s2) + // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800 + // netDuration = 4h, hourly = 100, bb100 = 150 / 75 * 100 = +200 - realm.commitTransaction() + } val computableResults = realm.where(ComputableResult::class.java).findAll() val sets = realm.where(SessionSet::class.java).findAll() @@ -474,7 +473,8 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { val sd1 = sdf.parse("01/1/2019 09:00") val ed1 = sdf.parse("01/1/2019 10:00") - s1.startDate = sd1 // timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800 + s1.startDate = + sd1 // timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800 s1.endDate = ed1 realm.copyToRealmOrUpdate(s1) @@ -624,33 +624,27 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { fun testRatedNetResultSessions() { val realm = this.mockRealm - realm.beginTransaction() - - val s1 = newSessionInstance(realm) - val s2 = newSessionInstance(realm) + realm.executeTransaction { - val b1 = realm.createObject(Bankroll::class.java, "1") - val b2 = realm.createObject(Bankroll::class.java, "2") + val s1 = newSessionInstance(realm) + val s2 = newSessionInstance(realm) - val c1 = realm.createObject(Currency::class.java, "1") - val c2 = realm.createObject(Currency::class.java, "2") + val b1 = realm.createObject(Bankroll::class.java, "1") + val b2 = realm.createObject(Bankroll::class.java, "2") - c1.rate = 0.5 - c2.rate = 1.0 - b1.currency = c1 - b2.currency = c2 - s1.bankroll = b1 - s2.bankroll = b2 - s1.result?.netResult = 100.0 - s2.result?.netResult = 200.0 + val c1 = realm.createObject(Currency::class.java, "1") + val c2 = realm.createObject(Currency::class.java, "2") - realm.insert(s1) - realm.insert(s2) + c1.rate = 0.5 + c2.rate = 1.0 + b1.currency = c1 + b2.currency = c2 + s1.bankroll = b1 + s2.bankroll = b2 + s1.result?.netResult = 100.0 + s2.result?.netResult = 200.0 - realm.copyToRealmOrUpdate(s1) - realm.copyToRealmOrUpdate(s2) - - realm.commitTransaction() + } val computableResults = realm.where(ComputableResult::class.java).findAll() val sets = realm.where(SessionSet::class.java).findAll() @@ -667,33 +661,28 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { fun testUpdateRatedNetResultSessions() { val realm = this.mockRealm - realm.beginTransaction() - - val s1 = newSessionInstance(realm) - val s2 = newSessionInstance(realm) - val b1 = realm.createObject(Bankroll::class.java, "1") - val b2 = realm.createObject(Bankroll::class.java, "2") + realm.executeTransaction { - val c1 = realm.createObject(Currency::class.java, "1") - val c2 = realm.createObject(Currency::class.java, "2") + val s1 = newSessionInstance(realm) + val s2 = newSessionInstance(realm) - c1.rate = 0.5 - c2.rate = 1.0 - b1.currency = c1 - b2.currency = c2 - s1.bankroll = b1 - s2.bankroll = b2 - s1.result?.netResult = 100.0 - s2.result?.netResult = 200.0 + val b1 = realm.createObject(Bankroll::class.java, "1") + val b2 = realm.createObject(Bankroll::class.java, "2") - realm.insert(s1) - realm.insert(s2) + val c1 = realm.createObject(Currency::class.java, "1") + val c2 = realm.createObject(Currency::class.java, "2") - realm.copyToRealmOrUpdate(s1) - realm.copyToRealmOrUpdate(s2) + c1.rate = 0.5 + c2.rate = 1.0 + b1.currency = c1 + b2.currency = c2 + s1.bankroll = b1 + s2.bankroll = b2 + s1.result?.netResult = 100.0 + s2.result?.netResult = 200.0 - realm.commitTransaction() + } val computableResults = realm.where(ComputableResult::class.java).findAll() val sets = realm.where(SessionSet::class.java).findAll() @@ -708,7 +697,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { println("currency set rate real test starts here") val updatedC2 = realm.where(Currency::class.java).equalTo("id", "2").findFirst() - updatedC2?.let {currency -> + updatedC2?.let { currency -> val newC2 = realm.copyFromRealm(currency) newC2.rate = 3.0 realm.executeTransaction { 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 f657b5d3..e72bf3a7 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -87,7 +87,7 @@ class Calculator { val e = Date() val duration = (e.time - s.time) / 1000.0 - Timber.d(">>> group ${group.name} in ${duration} seconds") + Timber.d(">>> group ${group.name} in $duration seconds") } @@ -120,12 +120,12 @@ class Calculator { val results: ComputedResults = ComputedResults(computableGroup) - var sum: Double = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble() - var totalHands: Double = computables.sum(ComputableResult.Field.ESTIMATED_HANDS.identifier).toDouble() - var bbSum: Double = computables.sum(ComputableResult.Field.BB_NET.identifier).toDouble() - var bbSessionCount: Int = computables.sum(ComputableResult.Field.HAS_BIG_BLIND.identifier).toInt() - var winningSessionCount: Int = computables.sum(ComputableResult.Field.IS_POSITIVE.identifier).toInt() - var totalBuyin = computables.sum(ComputableResult.Field.RATED_BUYIN.identifier).toDouble() + val sum = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble() + val totalHands = computables.sum(ComputableResult.Field.ESTIMATED_HANDS.identifier).toDouble() + val bbSum = computables.sum(ComputableResult.Field.BB_NET.identifier).toDouble() + val bbSessionCount = computables.sum(ComputableResult.Field.HAS_BIG_BLIND.identifier).toInt() + val winningSessionCount = computables.sum(ComputableResult.Field.IS_POSITIVE.identifier).toInt() + val totalBuyin = computables.sum(ComputableResult.Field.RATED_BUYIN.identifier).toDouble() // Compute for each session @@ -141,7 +141,7 @@ class Calculator { var tHands = 0.0 computables.forEach { s -> - index++; + index++ tSum += s.ratedNet tBBSum += s.bbNet tBBSessionCount += s.hasBigBlind @@ -176,13 +176,12 @@ class Calculator { val sessionSets = computableGroup.sets // Compute for each serie - var gHourlyDuration = sessionSets.sum(SessionSet.Field.NET_DURATION.identifier).toDouble() / 3600000 // (milliseconds to hours) + val gHourlyDuration = sessionSets.sum(SessionSet.Field.NET_DURATION.identifier).toDouble() / 3600000 // (milliseconds to hours) + val gSum = sessionSets.sum(SessionSet.Field.RATED_NET.identifier).toDouble() + val gTotalHands = sessionSets.sum(SessionSet.Field.ESTIMATED_HANDS.identifier).toDouble() + val gBBSum = sessionSets.sum(SessionSet.Field.BB_NET.identifier).toDouble() - var gSum = sessionSets.sum(SessionSet.Field.RATED_NET.identifier).toDouble() - var gTotalHands = sessionSets.sum(SessionSet.Field.ESTIMATED_HANDS.identifier).toDouble() - var gBBSum = sessionSets.sum(SessionSet.Field.BB_NET.identifier).toDouble() - - var hourlyRate = gSum / gHourlyDuration + val hourlyRate = gSum / gHourlyDuration // var hourlyRateBB = gBBSum / gDuration when (options.evolutionValues) { @@ -193,8 +192,8 @@ class Calculator { var tSum = 0.0 var tTotalHands = 0.0 var tBBSum = 0.0 - var tHourlyRate: Double = 0.0 - var tHourlyRateBB: Double = 0.0 + var tHourlyRate = 0.0 + var tHourlyRateBB = 0.0 sessionSets.forEach { sessionSet -> tIndex++ @@ -282,21 +281,21 @@ class Calculator { if (options.shouldComputeStandardDeviation()) { // Session - var stdSum: Double = 0.0 - var stdBBper100HandsSum: Double = 0.0 + var stdSum = 0.0 + var stdBBper100HandsSum = 0.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 / computables.size) - val standardDeviationBBper100Hands: Double = Math.sqrt(stdBBper100HandsSum / computables.size) + val standardDeviation = Math.sqrt(stdSum / computables.size) + val standardDeviationBBper100Hands = Math.sqrt(stdBBper100HandsSum / computables.size) // Session Set - var hourlyStdSum: Double = 0.0 + var hourlyStdSum = 0.0 sessionSets.forEach { set -> hourlyStdSum += Math.pow(set.hourlyRate - hourlyRate, 2.0) } - val hourlyStandardDeviation: Double = Math.sqrt(hourlyStdSum / sessionSets.size) + val hourlyStandardDeviation = Math.sqrt(hourlyStdSum / sessionSets.size) results.addStats( setOf( 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 97755def..1a3ecdb5 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 @@ -89,7 +89,7 @@ open class Result : RealmObject() { } // Precompute results - this.session?.updateComputableResult() + this.session?.computeStats() this.session?.sessionSet?.computeStats() } 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 a0ee3446..1d7ddd64 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 @@ -251,7 +251,6 @@ open class Session : RealmObject(), Identifiable, Manageable, StaticRowRepresent } else if (this.sessionSet != null) { SessionSetManager.removeFromTimeline(this) } - this.updateComputableResult() this.updateRowRepresentation() } @@ -317,25 +316,25 @@ open class Session : RealmObject(), Identifiable, Manageable, StaticRowRepresent /** * Pre-compute various stats */ - private fun computeStats() { + fun computeStats() { - if (this.startDate != null && this.endDate != null && this.computableResult == null) { + // ComputableResult are created only when a session is over + if (this.startDate != null && this.endDate != null && this.computableResults?.size == 0) { val computableResult = realm.createObject(ComputableResult::class.java) computableResult.session = this - } else { + } // if a ComputableResult exists and the session is not completed, delete it + else if (this.startDate == null || this.endDate == null) { this.computableResult?.deleteFromRealm() } - this.updateComputableResult() - } - - fun updateComputableResult() { - - this.computableResults?.forEach { - it.updateWith(this) - } ?: run { - throw IllegalStateException("Session should always have a computable results") + // Update the ComputableResult + this.computableResults?.forEachIndexed { index, computableResult -> + computableResult.updateWith(this) + if (index > 0) { + throw IllegalStateException("Session cannot have more than one computable result") + } } + this.sessionSet?.computeStats() } /** diff --git a/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt b/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt index 1d28ac2e..611aa32c 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt @@ -6,6 +6,10 @@ import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.SessionSet import kotlin.math.max +class CorruptSessionSetException(message: String) : Exception(message) { + +} + /** * The manager is in charge of updating the abstract concept of timeline, * representing the sequenced time frames where the user plays. @@ -100,22 +104,29 @@ class SessionSetManager { var startDate = session.startDate!! var endDate = session.endDate!! - // find earlier and later dates from all sets - sessionSets.forEach { set -> - if (set.startDate.before(startDate)) { - startDate = set.startDate - } - if (set.endDate.after(endDate)) { - endDate = set.endDate - } - } - // get all endedSessions from sets val sessions = mutableSetOf() sessionSets.forEach { set -> set.sessions?.asIterable()?.let { sessions.addAll(it) } } + // find earlier and later dates from all sets + sessions.forEach { s -> + + if (s.startDate != null && s.endDate != null) { + val start = s.startDate!! + val end = s.endDate!! + if (start.before(startDate)) { + startDate = start + } + if (end.after(endDate)) { + endDate = end + } + } else { + throw CorruptSessionSetException("Set contains unfinished sessions!") + } + } + // delete all sets sessionSets.deleteAllFromRealm()