Fixes tests, states and bugs

feature/top10
Laurent 7 years ago
parent cf35b92104
commit 77f9fd44f5
  1. 4
      app/src/androidTest/java/net/pokeranalytics/android/components/RealmInstrumentedUnitTest.kt
  2. 61
      app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt
  3. 43
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  4. 2
      app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt
  5. 23
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  6. 31
      app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt

@ -2,7 +2,6 @@ package net.pokeranalytics.android.components
import io.realm.Realm import io.realm.Realm
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Result import net.pokeranalytics.android.model.realm.Result
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import org.junit.After import org.junit.After
@ -18,8 +17,7 @@ open class RealmInstrumentedUnitTest {
fun newSessionInstance(realm: Realm) : Session { fun newSessionInstance(realm: Realm) : Session {
val session = realm.createObject(Session::class.java, UUID.randomUUID().toString()) val session = realm.createObject(Session::class.java, UUID.randomUUID().toString())
val computableResult = realm.createObject(ComputableResult::class.java) session.startDate = Date()
computableResult.session = session
session.result = realm.createObject(Result::class.java) session.result = realm.createObject(Result::class.java)
return session return session
} }

@ -3,11 +3,11 @@ package net.pokeranalytics.android.unitTests
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import io.realm.RealmList import io.realm.RealmList
import io.realm.RealmResults import io.realm.RealmResults
import net.pokeranalytics.android.components.RealmInstrumentedUnitTest
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.ComputableGroup import net.pokeranalytics.android.calculus.ComputableGroup
import net.pokeranalytics.android.calculus.ComputedResults import net.pokeranalytics.android.calculus.ComputedResults
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.components.RealmInstrumentedUnitTest
import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.model.realm.*
import net.pokeranalytics.android.model.realm.Currency import net.pokeranalytics.android.model.realm.Currency
import org.junit.Assert import org.junit.Assert
@ -48,8 +48,8 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
session.limit = limit session.limit = limit
session.numberOfTables = numberOfTable session.numberOfTables = numberOfTable
session.tableSize = tableSize session.tableSize = tableSize
session.result?.netResult = netResult
session.startDate = startDate session.startDate = startDate
session.result?.netResult = netResult
val cal = Calendar.getInstance() // creates calendar val cal = Calendar.getInstance() // creates calendar
cal.time = startDate // sets calendar time/date cal.time = startDate // sets calendar time/date
cal.add(Calendar.HOUR_OF_DAY, endDate) // adds one hour cal.add(Calendar.HOUR_OF_DAY, endDate) // adds one hour
@ -81,6 +81,11 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
fun testSessionStats() { fun testSessionStats() {
val realm = this.mockRealm val realm = this.mockRealm
val computableResults = realm.where(ComputableResult::class.java).findAll()
assertEquals(0, computableResults.size)
realm.beginTransaction() realm.beginTransaction()
val s1 = newSessionInstance(realm) val s1 = newSessionInstance(realm)
@ -95,10 +100,6 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
s2.tableSize = 5 s2.tableSize = 5
realm.insert(s1)
realm.insert(s2)
realm.commitTransaction()
val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sdf = SimpleDateFormat("dd/M/yyyy hh:mm")
val sd1 = sdf.parse("01/1/2019 10:00") 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 sd2 = sdf.parse("02/1/2019 08:00")
val ed2 = sdf.parse("02/1/2019 11:00") // 3 hours val ed2 = sdf.parse("02/1/2019 11:00") // 3 hours
realm.beginTransaction()
s1.startDate = sd1 s1.startDate = sd1
s1.endDate = ed1 s1.endDate = ed1
s2.startDate = sd2 s2.startDate = sd2
s2.endDate = ed2 s2.endDate = ed2
realm.copyToRealmOrUpdate(s1) val d1 = s1.sessionSet?.netDuration
realm.copyToRealmOrUpdate(s2) val d2 = s2.sessionSet?.netDuration
realm.commitTransaction() 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 sets = realm.where(SessionSet::class.java).findAll()
val stats: List<Stat> = listOf(Stat.NETRESULT, Stat.AVERAGE) val stats: List<Stat> = listOf(Stat.NETRESULT, Stat.AVERAGE)
val group = ComputableGroup("test", computableResults, sets, stats) val group = ComputableGroup("test", computableResults, sets, stats)
@ -239,14 +243,12 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
fun testOverlappingSessions1() { fun testOverlappingSessions1() {
val realm = this.mockRealm val realm = this.mockRealm
realm.beginTransaction()
realm.executeTransaction {
val s1 = newSessionInstance(realm) val s1 = newSessionInstance(realm)
val s2 = newSessionInstance(realm) val s2 = newSessionInstance(realm)
realm.insert(s1)
realm.insert(s2)
val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sdf = SimpleDateFormat("dd/M/yyyy hh:mm")
val sd1 = sdf.parse("01/1/2019 09:00") val sd1 = sdf.parse("01/1/2019 09:00")
@ -262,10 +264,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
// netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800 // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
// netDuration = 4h, hourly = 100, bb100 = 150 / 75 * 100 = +200 // netDuration = 4h, hourly = 100, bb100 = 150 / 75 * 100 = +200
realm.copyToRealmOrUpdate(s1) }
realm.copyToRealmOrUpdate(s2)
realm.commitTransaction()
val computableResults = realm.where(ComputableResult::class.java).findAll() val computableResults = realm.where(ComputableResult::class.java).findAll()
val sets = realm.where(SessionSet::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 sd1 = sdf.parse("01/1/2019 09:00")
val ed1 = sdf.parse("01/1/2019 10: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 s1.endDate = ed1
realm.copyToRealmOrUpdate(s1) realm.copyToRealmOrUpdate(s1)
@ -624,7 +624,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
fun testRatedNetResultSessions() { fun testRatedNetResultSessions() {
val realm = this.mockRealm val realm = this.mockRealm
realm.beginTransaction() realm.executeTransaction {
val s1 = newSessionInstance(realm) val s1 = newSessionInstance(realm)
val s2 = newSessionInstance(realm) val s2 = newSessionInstance(realm)
@ -644,13 +644,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
s1.result?.netResult = 100.0 s1.result?.netResult = 100.0
s2.result?.netResult = 200.0 s2.result?.netResult = 200.0
realm.insert(s1) }
realm.insert(s2)
realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2)
realm.commitTransaction()
val computableResults = realm.where(ComputableResult::class.java).findAll() val computableResults = realm.where(ComputableResult::class.java).findAll()
val sets = realm.where(SessionSet::class.java).findAll() val sets = realm.where(SessionSet::class.java).findAll()
@ -667,7 +661,8 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
fun testUpdateRatedNetResultSessions() { fun testUpdateRatedNetResultSessions() {
val realm = this.mockRealm val realm = this.mockRealm
realm.beginTransaction()
realm.executeTransaction {
val s1 = newSessionInstance(realm) val s1 = newSessionInstance(realm)
val s2 = newSessionInstance(realm) val s2 = newSessionInstance(realm)
@ -687,13 +682,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
s1.result?.netResult = 100.0 s1.result?.netResult = 100.0
s2.result?.netResult = 200.0 s2.result?.netResult = 200.0
realm.insert(s1) }
realm.insert(s2)
realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2)
realm.commitTransaction()
val computableResults = realm.where(ComputableResult::class.java).findAll() val computableResults = realm.where(ComputableResult::class.java).findAll()
val sets = realm.where(SessionSet::class.java).findAll() val sets = realm.where(SessionSet::class.java).findAll()

@ -87,7 +87,7 @@ class Calculator {
val e = Date() val e = Date()
val duration = (e.time - s.time) / 1000.0 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) val results: ComputedResults = ComputedResults(computableGroup)
var sum: Double = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble() val sum = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble()
var totalHands: Double = computables.sum(ComputableResult.Field.ESTIMATED_HANDS.identifier).toDouble() val totalHands = computables.sum(ComputableResult.Field.ESTIMATED_HANDS.identifier).toDouble()
var bbSum: Double = computables.sum(ComputableResult.Field.BB_NET.identifier).toDouble() val bbSum = computables.sum(ComputableResult.Field.BB_NET.identifier).toDouble()
var bbSessionCount: Int = computables.sum(ComputableResult.Field.HAS_BIG_BLIND.identifier).toInt() val bbSessionCount = computables.sum(ComputableResult.Field.HAS_BIG_BLIND.identifier).toInt()
var winningSessionCount: Int = computables.sum(ComputableResult.Field.IS_POSITIVE.identifier).toInt() val winningSessionCount = computables.sum(ComputableResult.Field.IS_POSITIVE.identifier).toInt()
var totalBuyin = computables.sum(ComputableResult.Field.RATED_BUYIN.identifier).toDouble() val totalBuyin = computables.sum(ComputableResult.Field.RATED_BUYIN.identifier).toDouble()
// Compute for each session // Compute for each session
@ -141,7 +141,7 @@ class Calculator {
var tHands = 0.0 var tHands = 0.0
computables.forEach { s -> computables.forEach { s ->
index++; index++
tSum += s.ratedNet tSum += s.ratedNet
tBBSum += s.bbNet tBBSum += s.bbNet
tBBSessionCount += s.hasBigBlind tBBSessionCount += s.hasBigBlind
@ -176,13 +176,12 @@ class Calculator {
val sessionSets = computableGroup.sets val sessionSets = computableGroup.sets
// Compute for each serie // 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() val hourlyRate = gSum / gHourlyDuration
var gTotalHands = sessionSets.sum(SessionSet.Field.ESTIMATED_HANDS.identifier).toDouble()
var gBBSum = sessionSets.sum(SessionSet.Field.BB_NET.identifier).toDouble()
var hourlyRate = gSum / gHourlyDuration
// var hourlyRateBB = gBBSum / gDuration // var hourlyRateBB = gBBSum / gDuration
when (options.evolutionValues) { when (options.evolutionValues) {
@ -193,8 +192,8 @@ class Calculator {
var tSum = 0.0 var tSum = 0.0
var tTotalHands = 0.0 var tTotalHands = 0.0
var tBBSum = 0.0 var tBBSum = 0.0
var tHourlyRate: Double = 0.0 var tHourlyRate = 0.0
var tHourlyRateBB: Double = 0.0 var tHourlyRateBB = 0.0
sessionSets.forEach { sessionSet -> sessionSets.forEach { sessionSet ->
tIndex++ tIndex++
@ -282,21 +281,21 @@ class Calculator {
if (options.shouldComputeStandardDeviation()) { if (options.shouldComputeStandardDeviation()) {
// Session // Session
var stdSum: Double = 0.0 var stdSum = 0.0
var stdBBper100HandsSum: Double = 0.0 var stdBBper100HandsSum = 0.0
computables.forEach { session -> computables.forEach { session ->
stdSum += Math.pow(session.ratedNet - average, 2.0) stdSum += Math.pow(session.ratedNet - average, 2.0)
stdBBper100HandsSum += Math.pow(session.bbPer100Hands - bbPer100Hands, 2.0) stdBBper100HandsSum += Math.pow(session.bbPer100Hands - bbPer100Hands, 2.0)
} }
val standardDeviation: Double = Math.sqrt(stdSum / computables.size) val standardDeviation = Math.sqrt(stdSum / computables.size)
val standardDeviationBBper100Hands: Double = Math.sqrt(stdBBper100HandsSum / computables.size) val standardDeviationBBper100Hands = Math.sqrt(stdBBper100HandsSum / computables.size)
// Session Set // Session Set
var hourlyStdSum: Double = 0.0 var hourlyStdSum = 0.0
sessionSets.forEach { set -> sessionSets.forEach { set ->
hourlyStdSum += Math.pow(set.hourlyRate - hourlyRate, 2.0) 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( results.addStats(
setOf( setOf(

@ -89,7 +89,7 @@ open class Result : RealmObject() {
} }
// Precompute results // Precompute results
this.session?.updateComputableResult() this.session?.computeStats()
this.session?.sessionSet?.computeStats() this.session?.sessionSet?.computeStats()
} }

@ -251,7 +251,6 @@ open class Session : RealmObject(), Identifiable, Manageable, StaticRowRepresent
} else if (this.sessionSet != null) { } else if (this.sessionSet != null) {
SessionSetManager.removeFromTimeline(this) SessionSetManager.removeFromTimeline(this)
} }
this.updateComputableResult()
this.updateRowRepresentation() this.updateRowRepresentation()
} }
@ -317,25 +316,25 @@ open class Session : RealmObject(), Identifiable, Manageable, StaticRowRepresent
/** /**
* Pre-compute various stats * 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) val computableResult = realm.createObject(ComputableResult::class.java)
computableResult.session = this 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.computableResult?.deleteFromRealm()
} }
this.updateComputableResult() // Update the ComputableResult
this.computableResults?.forEachIndexed { index, computableResult ->
computableResult.updateWith(this)
if (index > 0) {
throw IllegalStateException("Session cannot have more than one computable result")
} }
fun updateComputableResult() {
this.computableResults?.forEach {
it.updateWith(this)
} ?: run {
throw IllegalStateException("Session should always have a computable results")
} }
this.sessionSet?.computeStats()
} }
/** /**

@ -6,6 +6,10 @@ import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet import net.pokeranalytics.android.model.realm.SessionSet
import kotlin.math.max import kotlin.math.max
class CorruptSessionSetException(message: String) : Exception(message) {
}
/** /**
* The manager is in charge of updating the abstract concept of timeline, * The manager is in charge of updating the abstract concept of timeline,
* representing the sequenced time frames where the user plays. * representing the sequenced time frames where the user plays.
@ -100,22 +104,29 @@ class SessionSetManager {
var startDate = session.startDate!! var startDate = session.startDate!!
var endDate = session.endDate!! 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 // get all endedSessions from sets
val sessions = mutableSetOf<Session>() val sessions = mutableSetOf<Session>()
sessionSets.forEach { set -> sessionSets.forEach { set ->
set.sessions?.asIterable()?.let { sessions.addAll(it) } 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 // delete all sets
sessionSets.deleteAllFromRealm() sessionSets.deleteAllFromRealm()

Loading…
Cancel
Save