package net.pokeranalytics.android.unitTests import androidx.test.ext.junit.runners.AndroidJUnit4 import io.realm.RealmResults 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.SessionInstrumentedUnitTest import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.model.realm.Currency import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith import java.text.SimpleDateFormat import java.util.* /** * Instrumented test, which will execute on an Android device. * * See [testing documentation](http://d.android.com/tools/testing). */ @RunWith(AndroidJUnit4::class) class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { @Test fun testAllSessionStats() { val realm = this.mockRealm val computableResults = realm.where(ComputableResult::class.java).findAll() assertEquals(0, computableResults.size) realm.beginTransaction() val s1 = newSessionInstance(realm) val s2 = newSessionInstance(realm) s1.result?.buyin = 100.0 // net result = -100 s2.result?.buyin = 200.0 s2.result?.cashout = 500.0 // net result = 300 s1.cgBigBlind = 0.5 // bb net result = -200bb s2.cgBigBlind = 2.0 // bb net result = 150bb s2.tableSize = 5 val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sd1 = sdf.parse("01/1/2019 10:00") val ed1 = sdf.parse("01/1/2019 11:00") // 1 hour val sd2 = sdf.parse("02/1/2019 08:00") val ed2 = sdf.parse("02/1/2019 11:00") // 3 hours s1.startDate = sd1 s1.endDate = ed1 s2.startDate = sd2 s2.endDate = ed2 val l1 = realm.createObject(Location::class.java, UUID.randomUUID().toString()) s1.location = l1 s2.location = l1 realm.commitTransaction() assertEquals(2, computableResults.size) computableResults.forEach { println(">>>>>> rated net = ${it.ratedNet} ") } val group = ComputableGroup("test") val options = Calculator.Options() options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION, Stat.LONGEST_STREAKS, Stat.LOCATIONS_PLAYED, Stat.DAYS_PLAYED) val results: ComputedResults = Calculator.compute(realm, group, options) val delta = 0.01 val sum = results.computedStat(Stat.NET_RESULT) if (sum != null) { assertEquals(200.0, sum.value, delta) } else { Assert.fail("No Net result stat") } val average = results.computedStat(Stat.AVERAGE) if (average != null) { assertEquals(100.0, average.value, delta) } else { Assert.fail("No AVERAGE stat") } val duration = results.computedStat(Stat.HOURLY_DURATION) if (duration != null) { assertEquals(4.0, duration.value, delta) } else { Assert.fail("No netDuration stat") } val hourlyRate = results.computedStat(Stat.HOURLY_RATE) if (hourlyRate != null) { assertEquals(50.0, hourlyRate.value, delta) } else { Assert.fail("No houry rate stat") } val handsPlayed = results.computedStat(Stat.HANDS_PLAYED) if (handsPlayed != null) { assertEquals(177.77, handsPlayed.value, delta) } else { Assert.fail("No hands played stat") } val numberOfGames = results.computedStat(Stat.NUMBER_OF_GAMES) if (numberOfGames != null) { assertEquals(2, numberOfGames.value.toInt()) } else { Assert.fail("No numberOfGames stat") } val numberOfSets = results.computedStat(Stat.NUMBER_OF_SETS) if (numberOfSets != null) { assertEquals(2, numberOfSets.value.toInt()) } else { Assert.fail("No numberOfSets stat") } val avgBuyin = results.computedStat(Stat.AVERAGE_BUYIN) if (avgBuyin != null) { assertEquals(150.0, avgBuyin.value, delta) } else { Assert.fail("No avgBuyin stat") } val avgDuration = results.computedStat(Stat.AVERAGE_HOURLY_DURATION) if (avgDuration != null) { assertEquals(2.0, avgDuration.value, delta) } else { Assert.fail("No avgDuration stat") } val roi = results.computedStat(Stat.ROI) if (roi != null) { assertEquals(200 / 300.0, roi.value, delta) } else { Assert.fail("No roi stat") } val avgBBNet = results.computedStat(Stat.AVERAGE_NET_BB) if (avgBBNet != null) { assertEquals(-25.0, avgBBNet.value, delta) } else { Assert.fail("No avgBBNet stat") } val bbHourlyRate = results.computedStat(Stat.HOURLY_RATE_BB) if (bbHourlyRate != null) { assertEquals(-12.5, bbHourlyRate.value, delta) } else { Assert.fail("No bbHourlyRate stat") } val netbbPer100Hands = results.computedStat(Stat.NET_BB_PER_100_HANDS) if (netbbPer100Hands != null) { assertEquals(-28.12, netbbPer100Hands.value, delta) } else { Assert.fail("No netbbPer100Hands stat") } val std = results.computedStat(Stat.STANDARD_DEVIATION) if (std != null) { assertEquals(200.0, std.value, delta) } else { Assert.fail("No std stat") } val stdHourly = results.computedStat(Stat.STANDARD_DEVIATION_HOURLY) if (stdHourly != null) { assertEquals(111.8, stdHourly.value, delta) } else { Assert.fail("No stdHourly stat") } val std100 = results.computedStat(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS) if (std100 != null) { assertEquals(497.54, std100.value, delta) } else { Assert.fail("No std100 stat") } results.computedStat(Stat.MAXIMUM_NETRESULT)?.let { assertEquals(300.0, it.value, delta) } ?: run { Assert.fail("No MAXIMUM_NETRESULT") } results.computedStat(Stat.MINIMUM_NETRESULT)?.let { assertEquals(-100.0, it.value, delta) } ?: run { Assert.fail("No MINIMUM_NETRESULT") } results.computedStat(Stat.MAXIMUM_DURATION)?.let { assertEquals(3.0, it.value, delta) } ?: run { Assert.fail("No MAXIMUM_DURATION") } results.computedStat(Stat.DAYS_PLAYED)?.let { assertEquals(2.0, it.value, delta) } ?: run { Assert.fail("No DAYS_PLAYED") } results.computedStat(Stat.LOCATIONS_PLAYED)?.let { assertEquals(1.0, it.value, delta) } ?: run { Assert.fail("No LOCATIONS_PLAYED") } results.computedStat(Stat.LONGEST_STREAKS)?.let { assertEquals(1.0, it.value, delta) assertEquals(1.0, it.secondValue!!, delta) } ?: run { Assert.fail("No LOCATIONS_PLAYED") } } @Test fun testOverlappingSessions1() { val realm = this.mockRealm realm.executeTransaction { val s1 = newSessionInstance(realm) val s2 = newSessionInstance(realm) val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") 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") s1.startDate = sd1 s1.endDate = ed1 s2.startDate = sd2 s2.endDate = ed2 // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800 // netDuration = 4h, hourly = 100, bb100 = 150 / 75 * 100 = +200 } val stats: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION) val results: ComputedResults = Calculator.compute(realm, group, options) val delta = 0.01 val duration = results.computedStat(Stat.HOURLY_DURATION) if (duration != null) { assertEquals(3.0, duration.value, delta) } else { Assert.fail("No Net result stat") } val numberOfSets = results.computedStat(Stat.NUMBER_OF_SETS) if (numberOfSets != null) { assertEquals(1, numberOfSets.value.toInt()) } else { Assert.fail("No numberOfSets stat") } val numberOfGames = results.computedStat(Stat.NUMBER_OF_GAMES) if (numberOfGames != null) { assertEquals(2, numberOfGames.value.toInt()) } else { Assert.fail("No numberOfSets stat") } } @Test fun testOverlappingSessions2() { val realm = this.mockRealm realm.beginTransaction() val s1 = newSessionInstance(realm) val s2 = newSessionInstance(realm) val s3 = newSessionInstance(realm) realm.insert(s1) realm.insert(s2) realm.insert(s3) val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sd1 = sdf.parse("01/1/2019 05:00") val ed1 = sdf.parse("01/1/2019 09:00") // 4h val sd2 = sdf.parse("01/1/2019 07:00") val ed2 = sdf.parse("01/1/2019 11:00") // 4h val sd3 = sdf.parse("01/1/2019 03:00") val ed3 = sdf.parse("01/1/2019 06:00") // 3h s1.startDate = sd1 s1.endDate = ed1 s2.startDate = sd2 s2.endDate = ed2 s3.startDate = sd3 s3.endDate = ed3 realm.copyToRealmOrUpdate(s1) realm.copyToRealmOrUpdate(s2) realm.copyToRealmOrUpdate(s3) realm.commitTransaction() val stats: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION) val results: ComputedResults = Calculator.compute(realm, group, options) val delta = 0.01 val duration = results.computedStat(Stat.HOURLY_DURATION) if (duration != null) { assertEquals(8.0, duration.value, delta) } else { Assert.fail("No Net result stat") } val numberOfSets = results.computedStat(Stat.NUMBER_OF_SETS) if (numberOfSets != null) { assertEquals(1, numberOfSets.value.toInt()) } else { Assert.fail("No numberOfSets stat") } val numberOfGames = results.computedStat(Stat.NUMBER_OF_GAMES) if (numberOfGames != null) { assertEquals(3, numberOfGames.value.toInt()) } else { Assert.fail("No numberOfSets stat") } } private var sessions: RealmResults? = null // @Test fun testOverlappingSessionDeletion() { val realm = this.mockRealm this.sessions = realm.where(Session::class.java).findAll() // monitor session deletions this.sessions?.addChangeListener { _, changeSet -> val deletedSessions = realm.where(Session::class.java).`in`("id", changeSet.deletions.toTypedArray()).findAll() deletedSessions.forEach { it.cleanup() } } realm.beginTransaction() val s1 = realm.createObject(Session::class.java, "1") val s2 = realm.createObject(Session::class.java, "2") val s3 = realm.createObject(Session::class.java, "3") realm.insert(s1) realm.insert(s2) realm.insert(s3) realm.commitTransaction() val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sd1 = sdf.parse("01/1/2019 05:00") val ed1 = sdf.parse("01/1/2019 09:00") val sd2 = sdf.parse("01/1/2019 07:00") val ed2 = sdf.parse("01/1/2019 11:00") val sd3 = sdf.parse("01/1/2019 03:00") val ed3 = sdf.parse("01/1/2019 06:00") realm.beginTransaction() s1.startDate = sd1 s1.endDate = ed1 s2.startDate = sd2 s2.endDate = ed2 s3.startDate = sd3 s3.endDate = ed3 realm.copyToRealmOrUpdate(s1) realm.copyToRealmOrUpdate(s2) realm.copyToRealmOrUpdate(s3) realm.commitTransaction() val stats: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION) val results: ComputedResults = Calculator.compute(realm, group, options) val delta = 0.01 val duration = results.computedStat(Stat.HOURLY_DURATION) if (duration != null) { assertEquals(8.0, duration.value, delta) } else { Assert.fail("No netDuration stat") } realm.executeTransaction { s1.deleteFromRealm() } val stats2: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group2 = ComputableGroup("test", listOf(), stats2) val results2: ComputedResults = Calculator.compute(realm, group2, options) val duration2 = results2.computedStat(Stat.HOURLY_DURATION) if (duration2 != null) { assertEquals(7.0, duration2.value, delta) } else { Assert.fail("No duration2 stat") } } @Test fun testSessionSetCount() { val realm = this.mockRealm realm.beginTransaction() val s1 = newSessionInstance(realm) realm.insert(s1) val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sd1 = sdf.parse("01/1/2019 09:00") val ed1 = sdf.parse("01/1/2019 10:00") s1.startDate = sd1 //netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800 s1.endDate = ed1 realm.copyToRealmOrUpdate(s1) realm.commitTransaction() val sets = realm.where(SessionSet::class.java).findAll() assertEquals(1, sets.size) val set = sets.first() if (set != null) { assertEquals(sd1.time, set.startDate.time) assertEquals(ed1.time, set.endDate.time) } else { Assert.fail("No set") } } @Test fun testSessionSetCount2() { val realm = this.mockRealm realm.beginTransaction() val s1 = newSessionInstance(realm) val s2 = newSessionInstance(realm) realm.insert(s1) realm.insert(s2) val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sd1 = sdf.parse("01/1/2019 09:00") val ed1 = sdf.parse("01/1/2019 10:00") val sd2 = sdf.parse("01/2/2018 09:00") val ed2 = sdf.parse("01/2/2018 10:00") s1.startDate = sd1 s1.endDate = ed1 s2.startDate = sd2 s2.endDate = ed2 realm.copyToRealmOrUpdate(s1) realm.copyToRealmOrUpdate(s2) realm.commitTransaction() val sets = realm.where(SessionSet::class.java).findAll() assertEquals(2, sets.size) } @Test fun testSessionRestartInOverlappingSessions() { val realm = this.mockRealm realm.beginTransaction() val s1 = newSessionInstance(realm) val s2 = newSessionInstance(realm) val s3 = newSessionInstance(realm) realm.insert(s1) realm.insert(s2) realm.insert(s3) val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sd1 = sdf.parse("01/1/2019 05:00") val ed1 = sdf.parse("01/1/2019 09:00") // 4h val sd2 = sdf.parse("01/1/2019 07:00") val ed2 = sdf.parse("01/1/2019 11:00") // 4h val sd3 = sdf.parse("01/1/2019 03:00") val ed3 = sdf.parse("01/1/2019 06:00") // 3h s1.startDate = sd1 s1.endDate = ed1 s2.startDate = sd2 s2.endDate = ed2 s3.startDate = sd3 s3.endDate = ed3 realm.copyToRealmOrUpdate(s1) realm.copyToRealmOrUpdate(s2) realm.copyToRealmOrUpdate(s3) realm.commitTransaction() realm.executeTransaction { s1.endDate = null } val stats: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() // options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION) val results: ComputedResults = Calculator.compute(realm, group, options) val delta = 0.01 val duration = results.computedStat(Stat.HOURLY_DURATION) if (duration != null) { assertEquals(7.0, duration.value, delta) } else { Assert.fail("No Net result stat") } val numberOfSets = results.computedStat(Stat.NUMBER_OF_SETS) if (numberOfSets != null) { assertEquals(2, numberOfSets.value.toInt()) } else { Assert.fail("No numberOfSets stat") } } // @Test fun testRatedNetResultSessions() { val realm = this.mockRealm realm.executeTransaction { val s1 = newSessionInstance(realm) val s2 = newSessionInstance(realm) val b1 = realm.createObject(Bankroll::class.java, "1") val b2 = realm.createObject(Bankroll::class.java, "2") val c1 = realm.createObject(Currency::class.java, "1") val c2 = realm.createObject(Currency::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 stats: List = listOf(Stat.NET_RESULT) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() val results: ComputedResults = Calculator.compute(realm, group, options) val netResult = results.computedStat(Stat.NET_RESULT) assertEquals(250.0, netResult?.value) } // @Test fun testUpdateRatedNetResultSessions() { val realm = this.mockRealm realm.executeTransaction { val s1 = newSessionInstance(realm) val s2 = newSessionInstance(realm) val b1 = realm.createObject(Bankroll::class.java, "1") val b2 = realm.createObject(Bankroll::class.java, "2") val c1 = realm.createObject(Currency::class.java, "1") val c2 = realm.createObject(Currency::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 stats: List = listOf(Stat.NET_RESULT) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() val results: ComputedResults = Calculator.compute(realm, group, options) val netResult = results.computedStat(Stat.NET_RESULT) assertEquals(250.0, netResult?.value) println("currency set rate real test starts here") val updatedC2 = realm.where(Currency::class.java).equalTo("id", "2").findFirst() updatedC2?.let { currency -> val newC2 = realm.copyFromRealm(currency) newC2.rate = 3.0 realm.executeTransaction { it.copyToRealmOrUpdate(newC2) } } val updatedGroup = ComputableGroup("test", listOf(), stats) val updatedResults: ComputedResults = Calculator.compute(realm, updatedGroup, options) val updatedNetResult = updatedResults.computedStat(Stat.NET_RESULT) assertEquals(650.0, updatedNetResult?.value) } @Test fun testDaysPlayed() { val realm = this.mockRealm realm.executeTransaction { val s1 = newSessionInstance(realm) val s2 = newSessionInstance(realm) val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") 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 19:00") val ed2 = sdf.parse("01/1/2019 20:00") s1.startDate = sd1 s1.endDate = ed1 s2.startDate = sd2 s2.endDate = ed2 } val group = ComputableGroup("", listOf(), listOf()) val options = Calculator.Options(stats = listOf(Stat.DAYS_PLAYED)) val report = Calculator.computeGroups(realm, listOf(group), options) report.results.firstOrNull()?.computedStat(Stat.DAYS_PLAYED)?.let { assertEquals(1, it.value.toInt()) } ?: run { Assert.fail("Missing DAYS_PLAYED") } } @Test fun testFilteredHourlyRate() { val realm = this.mockRealm realm.executeTransaction { val s1 = newSessionInstance(realm, true) val s2 = newSessionInstance(realm, true) val s3 = newSessionInstance(realm, false) val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") 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 04:00") val ed2 = sdf.parse("01/1/2019 05:00") val sd3 = sdf.parse("01/1/2019 03:00") val ed3 = sdf.parse("01/1/2019 11:00") s1.startDate = sd1 s1.endDate = ed1 s2.startDate = sd2 s2.endDate = ed2 s3.startDate = sd3 s3.endDate = ed3 } val group = ComputableGroup("test", listOf(QueryCondition.IsCash)) val options = Calculator.Options() options.displayedStats = listOf(Stat.HOURLY_DURATION) val results: ComputedResults = Calculator.compute(realm, group, options) val delta = 0.01 val duration = results.computedStat(Stat.HOURLY_DURATION) if (duration != null) { assertEquals(2.0, duration.value, delta) } else { Assert.fail("No Net result stat") } } @Test fun testFilteredHourlyRate2() { val realm = this.mockRealm realm.executeTransaction { val s1 = newSessionInstance(realm, true) val s2 = newSessionInstance(realm, true) val s3 = newSessionInstance(realm, false) val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sd1 = sdf.parse("01/1/2019 06:00") val ed1 = sdf.parse("01/1/2019 09:00") val sd2 = sdf.parse("01/1/2019 07:00") val ed2 = sdf.parse("01/1/2019 10:00") val sd3 = sdf.parse("01/1/2019 03:00") val ed3 = sdf.parse("01/1/2019 11:00") s1.startDate = sd1 s1.endDate = ed1 s2.startDate = sd2 s2.endDate = ed2 s3.startDate = sd3 s3.endDate = ed3 } val group = ComputableGroup("test", listOf(QueryCondition.IsCash)) val options = Calculator.Options() options.displayedStats = listOf(Stat.HOURLY_DURATION) val results: ComputedResults = Calculator.compute(realm, group, options) val delta = 0.01 val duration = results.computedStat(Stat.HOURLY_DURATION) if (duration != null) { assertEquals(4.0, duration.value, delta) } else { Assert.fail("No Net result stat") } } }