diff --git a/app/build.gradle b/app/build.gradle index 9696e598..2b5195f7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -61,11 +61,24 @@ dependencies { implementation 'com.jakewharton.timber:timber:4.7.1' // Test - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:core:1.1.0' + androidTestImplementation 'androidx.test:core:1.0.0' androidTestImplementation 'androidx.test:runner:1.1.0' androidTestImplementation 'androidx.test:rules:1.1.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.0' + + + + // Required -- JUnit 4 framework + testImplementation 'junit:junit:4.12' + // Optional -- Robolectric environment +// testImplementation 'androidx.test:core:1.1.0' + // Optional -- Mockito framework + testImplementation 'com.android.support.test:runner:1.0.1' + testImplementation 'com.android.support.test:rules:1.0.1' + +// testImplementation 'androidx.test.espresso:espresso-core:3.1.0' + + } apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/app/src/androidTest/java/net/pokeranalytics/android/ExampleInstrumentedTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/ExampleInstrumentedTest.kt deleted file mode 100644 index 0face4e3..00000000 --- a/app/src/androidTest/java/net/pokeranalytics/android/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.pokeranalytics.android - -import androidx.test.InstrumentationRegistry -import androidx.test.runner.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getTargetContext() - assertEquals("net.pokeranalytics.android", appContext.packageName) - } -} diff --git a/app/src/androidTest/java/net/pokeranalytics/android/ExampleInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/ExampleInstrumentedUnitTest.kt new file mode 100644 index 00000000..4b834a9f --- /dev/null +++ b/app/src/androidTest/java/net/pokeranalytics/android/ExampleInstrumentedUnitTest.kt @@ -0,0 +1,106 @@ +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.Stat +import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.model.realm.TimeFrame +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 ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() { + + // convenience extension + fun Session.Companion.testInstance(netResult: Double, startDate: Date, endDate: Date?): Session { + var session: Session = Session.newInstance() + session.result?.netResult = netResult + session.timeFrame?.setDate(startDate, endDate) + return session + } + + @Test + fun testSessionStats() { + + val realm = this.mockRealm + realm.beginTransaction() + + 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") + val sd2 = sdf.parse("02/1/2019 08:00") + val ed2 = sdf.parse("02/1/2019 11:00") + + var s1 = realm.createObject(Session::class.java, "1") + var s2 = realm.createObject(Session::class.java, "2") + + s1.timeFrame = realm.createObject(TimeFrame::class.java) + s2.timeFrame = realm.createObject(TimeFrame::class.java) + + s1.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java) + s2.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java) + +// var s1: Session = Session.newInstance() +// var s2: Session = Session.newInstance() + + s1.result?.netResult = -100.0 + s2.result?.netResult = 300.0 + + realm.insert(s1) + realm.insert(s2) + realm.commitTransaction() + + realm.beginTransaction() + s1.timeFrame?.setDate(sd1, ed1) + s2.timeFrame?.setDate(sd2, ed2) + + realm.copyToRealmOrUpdate(s1) + realm.copyToRealmOrUpdate(s2) + + realm.commitTransaction() + + val sessions = realm.where(Session::class.java).findAll() + val group = SessionGroup(name = "test", sessions = sessions) + + val results: ComputedResults = Calculator.compute(group, Calculator.Options()) + val delta = 0.01 + + val sum = results.computedStat(Stat.NETRESULT) + 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.DURATION) + if (duration != null) { + assertEquals(4.0, duration.value, delta) + } else { + Assert.fail("No duration stat") + } + + } + + + +} diff --git a/app/src/androidTest/java/net/pokeranalytics/android/RealmInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/RealmInstrumentedUnitTest.kt new file mode 100644 index 00000000..8c91dc1f --- /dev/null +++ b/app/src/androidTest/java/net/pokeranalytics/android/RealmInstrumentedUnitTest.kt @@ -0,0 +1,26 @@ +package net.pokeranalytics.android + +import io.realm.Realm +import io.realm.RealmConfiguration +import org.junit.After +import org.junit.Before + +open class RealmInstrumentedUnitTest { + + lateinit var mockRealm: Realm + + @Before + fun setup() { + + val testConfig = RealmConfiguration.Builder().inMemory().name("test-realm").build() + Realm.setDefaultConfiguration(testConfig) + mockRealm = Realm.getDefaultInstance() + } + + @After + @Throws(Exception::class) + public fun tearDown() { + mockRealm.close() + } + +} \ No newline at end of file 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 c8afd8d8..c28b04b1 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -117,12 +117,12 @@ class Calculator { var hourlyRate: Double = 0.0; var hourlyRateBB: Double = 0.0 var gIndex = 0; var gSum = 0.0; var gTotalHands = 0.0; var gBBSum = 0.0; - sessionSets.forEach { group -> + sessionSets.forEach { sessionSet -> gIndex++ - duration += group.duration - gSum += group.netResult - gTotalHands += group.estimatedHands - gBBSum += group.bbNetResult + duration += sessionSet.hourlyDuration + gSum += sessionSet.netResult + gTotalHands += sessionSet.estimatedHands + gBBSum += sessionSet.bbNetResult hourlyRate = gSum / duration * 3600.0 hourlyRateBB = gBBSum / duration * 3600.0 @@ -133,7 +133,7 @@ class Calculator { results.addEvolutionValue(Stat.netBBPer100Hands(gBBSum, gTotalHands), duration, NET_BB_PER_100_HANDS) results.addEvolutionValue(hourlyRate, duration, HOURLY_RATE) results.addEvolutionValue(gIndex.toDouble(), duration, NUMBER_OF_GROUPS) - results.addEvolutionValue(group.duration, duration, DURATION) + results.addEvolutionValue(sessionSet.duration.toDouble(), duration, DURATION) results.addEvolutionValue(duration / gIndex, duration, AVERAGE_DURATION) results.addEvolutionValue(hourlyRateBB, duration, HOURLY_RATE_BB) } 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 d2a92ecd..13ae1695 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,15 +2,11 @@ package net.pokeranalytics.android.model.realm import io.realm.RealmList import io.realm.RealmObject -import io.realm.annotations.PrimaryKey -import java.util.* - +import io.realm.annotations.RealmClass +@RealmClass open class Result : RealmObject() { - @PrimaryKey - var id = UUID.randomUUID().toString() - // the user associated to this session result var player: Player? = null 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 74c482ea..a5bee990 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 @@ -12,7 +12,6 @@ import net.pokeranalytics.android.util.data.sessionDao import java.util.* import kotlin.collections.ArrayList - open class Session : RealmObject(), SessionInterface, DynamicRowDelegate, DisplayableDataSource { @PrimaryKey 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 6645c7c5..071a31a0 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 @@ -1,5 +1,6 @@ package net.pokeranalytics.android.model.realm +import io.realm.Realm import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.Ignore @@ -14,7 +15,16 @@ open class SessionSet() : RealmObject() { var sessions: RealmList = RealmList() @Ignore // a duration shortcut - var duration: Double = 0.0 + var duration: Long = 0L + get() { + return this.timeFrame?.duration ?: 0L + } + + @Ignore // a duration in hour + var hourlyDuration: Double = 0.0 + get() { + return this.timeFrame?.hourlyDuration ?: 0.0 + } @Ignore // a netResult shortcut var netResult: Double = 0.0 @@ -30,9 +40,9 @@ open class SessionSet() : RealmObject() { companion object { - fun newInstance() : SessionSet { - val sessionSet: SessionSet = SessionSet() - sessionSet.timeFrame = TimeFrame() + fun newInstance(realm: Realm) : SessionSet { + val sessionSet: SessionSet = realm.createObject(SessionSet::class.java) + sessionSet.timeFrame = realm.createObject(TimeFrame::class.java) return sessionSet } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt index a976f66b..f443f44e 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt @@ -9,16 +9,21 @@ import io.realm.annotations.LinkingObjects import net.pokeranalytics.android.exceptions.ModelException import java.util.* - open class TimeFrame : RealmObject() { // A start date var startDate: Date = Date() - private set + private set(value) { + field = value + this.computeDuration() + } // An end date var endDate: Date? = null - private set + private set(value) { + field = value + this.computeDuration() + } // The break duration var breakDuration: Long = 0L @@ -31,6 +36,11 @@ open class TimeFrame : RealmObject() { var duration: Long = 0L private set + var hourlyDuration: Double = 0.0 + get() { + return this.duration / 3600000.0 // 3.6 millions of milliseconds + } + // indicates a state of pause var paused: Boolean = false @@ -63,7 +73,8 @@ open class TimeFrame : RealmObject() { private fun computeDuration() { var endDate: Date = this.endDate ?: Date() - this.duration = endDate.time - startDate.time - this.breakDuration + val netDuration = endDate.time - this.startDate.time - this.breakDuration + this.duration = netDuration } private fun notifySessionDateChange() { @@ -76,13 +87,13 @@ open class TimeFrame : RealmObject() { } else { val endDate = this.endDate!! query - .greaterThan("timeFrame.startDate", this.startDate.time) - .lessThan("timeFrame.endDate", this.startDate.time) + .greaterThan("timeFrame.startDate", this.startDate) + .lessThan("timeFrame.endDate", this.startDate) .or() .greaterThan("timeFrame.startDate", endDate) .lessThan("timeFrame.endDate", endDate) .or() - .lessThan("timeFrame.startDate", this.startDate.time) + .lessThan("timeFrame.startDate", this.startDate) .greaterThan("timeFrame.endDate", endDate) } @@ -90,7 +101,7 @@ open class TimeFrame : RealmObject() { this.updateTimeFrames(sessionGroups) - realm.close() +// realm.close() } /** @@ -112,17 +123,24 @@ open class TimeFrame : RealmObject() { private fun createSessionGroup() { val realm = Realm.getDefaultInstance() - realm.beginTransaction() +// realm.beginTransaction() - val set: SessionSet = SessionSet.newInstance() + val set: SessionSet = SessionSet.newInstance(realm) set.timeFrame?.let { it.startDate = this.startDate it.endDate = this.endDate } ?: run { throw ModelException("TimeFrame should never be null here") } - set.sessions.add(this.session) - realm.commitTransaction() + + this.session?.let { + it.sessionSet = set + } ?: run { + throw ModelException("Session should never be null here") + } +// this.session?.sessionSet = set +// set.sessions.add(this.session) +// realm.commitTransaction() } /** @@ -144,13 +162,13 @@ open class TimeFrame : RealmObject() { } // Realm Update - val realm = Realm.getDefaultInstance() +// val realm = Realm.getDefaultInstance() realm.beginTransaction() if (!sessionSet.sessions.contains(this.session)) { sessionSet.sessions.add(this.session) } - realm.copyToRealmOrUpdate(groupTimeFrame) - realm.commitTransaction() +// realm.copyToRealmOrUpdate(groupTimeFrame) +// realm.commitTransaction() } @@ -185,14 +203,14 @@ open class TimeFrame : RealmObject() { var sessions = sessionSets.flatMap { it.sessions } // Start Realm updates - val realm = Realm.getDefaultInstance() - realm.beginTransaction() +// val realm = Realm.getDefaultInstance() +// realm.beginTransaction() // delete all sets sessionSets.deleteAllFromRealm() // Create a new sets - val set: SessionSet = SessionSet.newInstance() + val set: SessionSet = SessionSet.newInstance(realm) set.timeFrame?.let { it.startDate = startDate it.endDate = endDate @@ -210,7 +228,7 @@ open class TimeFrame : RealmObject() { // Add all orphan sessions set.sessions.addAll(sessions) - realm.commitTransaction() +// realm.commitTransaction() } } diff --git a/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt b/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt index b5e83530..9ae7c2fa 100644 --- a/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt +++ b/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt @@ -1,11 +1,9 @@ package net.pokeranalytics.android import net.pokeranalytics.android.calculus.* -import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.SessionSet import org.junit.Assert.fail import org.junit.Test -import java.util.* /** * Example local unit test, which will execute on the development machine (host). @@ -27,7 +25,7 @@ class ExampleUnitTest : RealmUnitTest() { } -// @Test + @Test fun testStats() { val grades: List = listOf(Grade(10.0), Grade(20.0)) @@ -51,61 +49,5 @@ class ExampleUnitTest : RealmUnitTest() { } - // convenience extension - fun Session.Companion.testInstance(netResult: Double, startDate: Date, endDate: Date?): Session { - var session: Session = Session.newInstance() - session.result?.netResult = netResult - session.timeFrame?.setDate(startDate, endDate) - return session - } - - @Test - fun testSessionStats() { - - val realm = RealmUnitTest.realmInstance() - realm.beginTransaction() - - Calendar.getInstance().set(2019,1,1,10,0) - val sd1 = Calendar.getInstance().time - Calendar.getInstance().set(2019,1,1,11,0) - val ed1 = Calendar.getInstance().time - val s1 = Session.testInstance(-100.0, sd1, ed1) - - Calendar.getInstance().set(2019,1,2,8,0) - val sd2 = Calendar.getInstance().time - Calendar.getInstance().set(2019,1,2,11,0) - val ed2 = Calendar.getInstance().time - val s2 = Session.testInstance(300.0, sd2, ed2) - - val sessions: List = listOf(s1, s2) - val group = SessionGroup(name = "test", sessions = sessions) - - realm.commitTransaction() - - val results: ComputedResults = Calculator.compute(group, Calculator.Options()) - - val sum = results.computedStat(Stat.NETRESULT) - if (sum != null) { - assert(sum.value == 200.0) { "sum is ${sum.value}" } - } else { - fail("No Net result stat") - } - - val average = results.computedStat(Stat.AVERAGE) - if (average != null) { - assert(average.value == 100.0) { "average is ${average.value}" } - } else { - fail("No AVERAGE stat") - } - - val duration = results.computedStat(Stat.DURATION) - if (duration != null) { - assert(duration.value == 4.0) { "duration is ${duration.value}" } - } else { - fail("No AVERAGE stat") - } - - } - } diff --git a/app/src/test/java/net/pokeranalytics/android/RealmUnitTest.kt b/app/src/test/java/net/pokeranalytics/android/RealmUnitTest.kt index b231491f..ffe2ffdd 100644 --- a/app/src/test/java/net/pokeranalytics/android/RealmUnitTest.kt +++ b/app/src/test/java/net/pokeranalytics/android/RealmUnitTest.kt @@ -1,22 +1,25 @@ package net.pokeranalytics.android -//import androidx.test.core.app.ApplicationProvider import io.realm.Realm import io.realm.RealmConfiguration +import org.junit.After +import org.junit.Before open class RealmUnitTest { - companion object { + lateinit var mockRealm: Realm - fun realmInstance() : Realm { - -// Application - -// Realm.init(ApplicationProvider.getApplicationContext()) - val testConfig = RealmConfiguration.Builder().inMemory().name("test-realm").build() - return Realm.getInstance(testConfig) - } + @Before + fun setup() { + val testConfig = RealmConfiguration.Builder().inMemory().name("test-realm").build() + Realm.setDefaultConfiguration(testConfig) + mockRealm = Realm.getDefaultInstance() + } + @After + @Throws(Exception::class) + public fun tearDown() { + mockRealm.close() } } \ No newline at end of file