Session/SessionSet date refactoring, TimeFrame removed

feature/top10
Laurent 7 years ago
parent 6dba82a895
commit 9c3134d866
  1. 518
      app/src/androidTest/java/net/pokeranalytics/android/ExampleInstrumentedUnitTest.kt
  2. 573
      app/src/androidTest/java/net/pokeranalytics/android/StatsInstrumentedUnitTest.kt
  3. 15
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  4. 19
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  5. 1
      app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt
  6. 45
      app/src/main/java/net/pokeranalytics/android/model/extensions/SessionExtensions.kt
  7. 30
      app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt
  8. 199
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  9. 63
      app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt
  10. 568
      app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt
  11. 2
      app/src/main/java/net/pokeranalytics/android/model/utils/FavoriteSessionFinder.kt
  12. 140
      app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt
  13. 4
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt
  14. 3
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt
  15. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/SessionObserverFragment.kt
  16. 14
      app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt
  17. 2
      app/src/main/res/values/strings.xml

@ -1,518 +0,0 @@
package net.pokeranalytics.android
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.Stat
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet
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 {
val session: Session = Session.newInstance(super.mockRealm, false)
session.result?.netResult = netResult
session.timeFrame?.setDate(startDate, endDate)
return session
}
@Test
fun testSessionStats() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = realm.createObject(Session::class.java, "1")
val 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)
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
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")
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")
realm.beginTransaction()
s1.timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
s2.timeFrame?.setDate(sd2, ed2) // netDuration = 3h, hourly = 100, bb100 = 150 / 75 * 100 = +200
realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2)
realm.commitTransaction()
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
val results: ComputedResults = Calculator.compute(group, 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 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(100.0, 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_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(-50.0, 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(559.01, std100.value, delta)
} else {
Assert.fail("No std100 stat")
}
}
@Test
fun testOverlappingSessions1() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = realm.createObject(Session::class.java, "1")
val 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)
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/1/2019 08:00")
val ed2 = sdf.parse("01/1/2019 11:00")
s1.timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
s2.timeFrame?.setDate(sd2, ed2) // netDuration = 4h, hourly = 100, bb100 = 150 / 75 * 100 = +200
realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2)
realm.commitTransaction()
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
val results: ComputedResults = Calculator.compute(group, options)
val delta = 0.01
val duration = results.computedStat(Stat.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 = realm.createObject(Session::class.java, "1")
val s2 = realm.createObject(Session::class.java, "2")
val s3 = realm.createObject(Session::class.java, "3")
s1.timeFrame = realm.createObject(TimeFrame::class.java)
s2.timeFrame = realm.createObject(TimeFrame::class.java)
s3.timeFrame = realm.createObject(TimeFrame::class.java)
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")
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")
s1.timeFrame?.setDate(sd1, ed1) // netDuration = 4h
s2.timeFrame?.setDate(sd2, ed2) // netDuration = 4h
s3.timeFrame?.setDate(sd3, ed3) // netDuration = 3h
realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2)
realm.copyToRealmOrUpdate(s3)
realm.commitTransaction()
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
val results: ComputedResults = Calculator.compute(group, options)
val delta = 0.01
val duration = results.computedStat(Stat.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")
}
}
var sessions: RealmResults<Session>? = null
// @Test
fun testOverlappingSessionDeletion() {
val realm = this.mockRealm
this.sessions = realm.where(Session::class.java).findAll() // monitor session deletions
this.sessions?.addChangeListener { t, 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")
s1.timeFrame = realm.createObject(TimeFrame::class.java)
s2.timeFrame = realm.createObject(TimeFrame::class.java)
s3.timeFrame = realm.createObject(TimeFrame::class.java)
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.timeFrame?.setDate(sd1, ed1) // netDuration = 4h
s2.timeFrame?.setDate(sd2, ed2) // netDuration = 4h
s3.timeFrame?.setDate(sd3, ed3) // netDuration = 3h
realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2)
realm.copyToRealmOrUpdate(s3)
realm.commitTransaction()
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
val results: ComputedResults = Calculator.compute(group, options)
val delta = 0.01
val duration = results.computedStat(Stat.DURATION)
if (duration != null) {
assertEquals(8.0, duration.value, delta)
} else {
Assert.fail("No netDuration stat")
}
realm.executeTransaction {
s1.deleteFromRealm()
}
val group2 = SessionGroup(name = "test", sessions = sessions)
val results2: ComputedResults = Calculator.compute(group2, options)
val duration2 = results2.computedStat(Stat.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 = realm.createObject(Session::class.java, "1")
s1.timeFrame = realm.createObject(TimeFrame::class.java)
s1.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
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.timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
realm.copyToRealmOrUpdate(s1)
realm.commitTransaction()
val sets = realm.where(SessionSet::class.java).findAll()
Assert.assertEquals(1, sets.size)
val set = sets.first()
if (set != null) {
Assert.assertEquals(sd1.time, set.timeFrame?.startDate?.time)
Assert.assertEquals(ed1.time, set.timeFrame?.endDate?.time)
} else {
Assert.fail("No set")
}
}
@Test
fun testSessionSetCount2() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = realm.createObject(Session::class.java, "1")
val 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)
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.timeFrame?.let {
it.setStart(sd1)
it.setEnd(ed1)
}
s2.timeFrame?.let {
it.setStart(sd2)
it.setEnd(ed2)
}
// s1.timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
// s2.timeFrame?.setDate(sd2, ed2) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2)
realm.commitTransaction()
val sets = realm.where(SessionSet::class.java).findAll()
Assert.assertEquals(2, sets.size)
// val set = sets.first()
// if (set != null) {
// Assert.assertEquals(sd1.time, set.timeFrame?.startDate?.time)
// Assert.assertEquals(ed1.time, set.timeFrame?.endDate?.time)
// } else {
// Assert.fail("No set")
// }
}
//
// @Test
// fun testDurationConversion() {
//
// val duration = 6.7555561274509826
// val longDuration = duration.toLong()
// val formatted = longDuration.toMinutes()
//
// assert(formatted == "11:00")
// }
}

@ -0,0 +1,573 @@
package net.pokeranalytics.android
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.Stat
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet
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 : RealmInstrumentedUnitTest() {
// convenience extension
fun Session.Companion.testInstance(netResult: Double, startDate: Date, endDate: Date?): Session {
val session: Session = Session.newInstance(super.mockRealm, false)
session.result?.netResult = netResult
session.startDate = startDate
session.endDate = endDate
return session
}
@Test
fun testSessionStats() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = realm.createObject(Session::class.java, "1")
val s2 = realm.createObject(Session::class.java, "2")
s1.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
s2.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
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
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")
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")
realm.beginTransaction()
s1.startDate = sd1
s1.endDate = ed1
s2.startDate = sd2
s2.endDate = 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 options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
val results: ComputedResults = Calculator.compute(group, 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 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(100.0, 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_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(-50.0, 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(559.01, std100.value, delta)
} else {
Assert.fail("No std100 stat")
}
}
@Test
fun testOverlappingSessions1() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = realm.createObject(Session::class.java, "1")
val s2 = realm.createObject(Session::class.java, "2")
s1.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
s2.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
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/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
realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2)
realm.commitTransaction()
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
val results: ComputedResults = Calculator.compute(group, options)
val delta = 0.01
val duration = results.computedStat(Stat.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 = 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)
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 sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
val results: ComputedResults = Calculator.compute(group, options)
val delta = 0.01
val duration = results.computedStat(Stat.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<Session>? = 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 sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
val results: ComputedResults = Calculator.compute(group, options)
val delta = 0.01
val duration = results.computedStat(Stat.DURATION)
if (duration != null) {
assertEquals(8.0, duration.value, delta)
} else {
Assert.fail("No netDuration stat")
}
realm.executeTransaction {
s1.deleteFromRealm()
}
val group2 = SessionGroup(name = "test", sessions = sessions)
val results2: ComputedResults = Calculator.compute(group2, options)
val duration2 = results2.computedStat(Stat.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 = realm.createObject(Session::class.java, "1")
s1.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
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 // timeFrame?.setDate(sd1, ed1) // 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()
Assert.assertEquals(1, sets.size)
val set = sets.first()
if (set != null) {
Assert.assertEquals(sd1.time, set.startDate.time)
Assert.assertEquals(ed1.time, set.endDate.time)
} else {
Assert.fail("No set")
}
}
@Test
fun testSessionSetCount2() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = realm.createObject(Session::class.java, "1")
val s2 = realm.createObject(Session::class.java, "2")
s1.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
s2.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
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
// s1.timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
// s2.timeFrame?.setDate(sd2, ed2) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2)
realm.commitTransaction()
val sets = realm.where(SessionSet::class.java).findAll()
Assert.assertEquals(2, sets.size)
// val set = sets.first()
// if (set != null) {
// Assert.assertEquals(sd1.time, set.timeFrame?.startDate?.time)
// Assert.assertEquals(ed1.time, set.timeFrame?.endDate?.time)
// } else {
// Assert.fail("No set")
// }
}
//
// @Test
// fun testDurationConversion() {
//
// val duration = 6.7555561274509826
// val longDuration = duration.toLong()
// val formatted = longDuration.toMinutes()
//
// assert(formatted == "11:00")
// }
@Test
fun testSessionRestartInOverlappingSessions() {
val realm = this.mockRealm
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)
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 sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val options = Calculator.Options()
// options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
val results: ComputedResults = Calculator.compute(group, options)
val delta = 0.01
val duration = results.computedStat(Stat.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")
}
}
}

@ -63,7 +63,7 @@ class PokerAnalyticsApplication : Application() {
this.createDefaultData()
if (BuildConfig.DEBUG) {
this.createFakeSessions() // debug
// this.createFakeSessions() // debug
}
}
@ -158,11 +158,14 @@ class PokerAnalyticsApplication : Application() {
// val timeFrame = TimeFrame()
session.timeFrame?.let {
// it.startDate = startDate
// it.endDate = endDate
it.setDate(startDate, endDate)
}
session.startDate = startDate
session.endDate = endDate
// session.timeFrame?.let {
// // it.startDate = startDate
//// it.endDate = endDate
// it.setDate(startDate, endDate)
// }
// session.timeFrame = timeFrame
session.creationDate = startDate

@ -64,7 +64,7 @@ class Calculator {
*/
fun computeGroups(groups: List<SessionGroup>, options: Options): List<ComputedResults> {
var computedResults: MutableList<ComputedResults> = mutableListOf()
val computedResults = mutableListOf<ComputedResults>()
groups.forEach { group ->
// Computes actual sessionGroup stats
val results: ComputedResults = Calculator.compute(group, options = options)
@ -90,9 +90,9 @@ class Calculator {
fun compute(sessionGroup: SessionGroup, options: Options) : ComputedResults {
val sessions: List<SessionInterface> = sessionGroup.sessions
var sessionSets = sessionGroup.sessions.mapNotNull { it.sessionSet }.toHashSet()
val sessionSets = sessionGroup.sessions.mapNotNull { it.sessionSet }.toHashSet()
var results: ComputedResults = ComputedResults(sessionGroup)
val results: ComputedResults = ComputedResults(sessionGroup)
var sum: Double = 0.0
var totalHands: Double = 0.0
@ -159,7 +159,7 @@ class Calculator {
results.addEvolutionValue(gSum / duration, duration, HOURLY_RATE)
results.addEvolutionValue(hourlyRate, duration, HOURLY_RATE)
results.addEvolutionValue(gIndex.toDouble(), duration, NUMBER_OF_SETS)
results.addEvolutionValue(sessionSet.duration.toDouble(), duration, DURATION)
results.addEvolutionValue(sessionSet.netDuration.toDouble(), duration, DURATION)
results.addEvolutionValue(duration / gIndex, duration, AVERAGE_DURATION)
results.addEvolutionValue(hourlyRateBB, duration, HOURLY_RATE_BB)
}
@ -175,19 +175,24 @@ class Calculator {
var average = 0.0
if (sessions.size > 0) {
average = sum / sessions.size.toDouble()
val avgDuration = duration / sessions.size
val winRatio = (winningSessionCount / sessions.size).toDouble()
val avgBuyin = totalBuyin / sessions.size
results.addStats(setOf(
ComputedStat(AVERAGE, average),
ComputedStat(AVERAGE_DURATION, avgDuration),
ComputedStat(WIN_RATIO, winRatio),
ComputedStat(AVERAGE_BUYIN, avgBuyin)
))
}
// Create stats
if (sessionSets.size > 0) {
val avgDuration = duration / sessionSets.size
results.addStats(setOf(
ComputedStat(AVERAGE_DURATION, avgDuration)
))
}
// Create stats
results.addStats(setOf(
ComputedStat(NETRESULT, sum),
ComputedStat(HOURLY_RATE, hourlyRate),

@ -19,7 +19,6 @@ interface SessionInterface : Summable {
var bigBlindSessionCount: Int // 0 or 1
var buyin: Double
var bbPer100Hands: Double
}
/**

@ -18,24 +18,35 @@ enum class SessionState {
*/
fun Session.getState(): SessionState {
if (timeFrame == null) {
return SessionState.PENDING
}
// if (timeFrame == null) {
// return SessionState.PENDING
// }
val endDate = timeFrame?.endDate
timeFrame?.let {sessionTimeFrame ->
timeFrame?.startDate?.let {startDate ->
if (startDate > Date()) {
return SessionState.PLANNED
} else if (endDate != null) {
return SessionState.FINISHED
} else if (sessionTimeFrame.paused) {
return SessionState.PAUSED
} else {
return SessionState.STARTED
}
}
if (startDate > Date()) {
return SessionState.PLANNED
} else if (endDate != null) {
return SessionState.FINISHED
} else if (this.pauseDate != null) {
return SessionState.PAUSED
} else {
return SessionState.STARTED
}
return SessionState.INVALID
// val endDate = timeFrame?.endDate
// timeFrame?.let {sessionTimeFrame ->
// timeFrame?.startDate?.let {startDate ->
// if (startDate > Date()) {
// return SessionState.PLANNED
// } else if (endDate != null) {
// return SessionState.FINISHED
// } else if (sessionTimeFrame.paused) {
// return SessionState.PAUSED
// } else {
// return SessionState.STARTED
// }
// }
// }
// return SessionState.INVALID
}

@ -0,0 +1,30 @@
package net.pokeranalytics.android.model.interfaces
import java.util.*
interface Timed {
var startDate: Date
fun endDate() : Date
var breakDuration: Long
var netDuration: Long
/**
* Computes the net netDuration of the session
*/
fun computeDuration() {
this.netDuration = this.endDate().time - this.startDate.time - this.breakDuration
}
// fun hourlyDuration() : Double {
// return this.netDuration / 3600000.0 // 3.6 millions of milliseconds
// }
var hourlyDuration: Double
get() = this.netDuration / 3600000.0
set(value) = TODO()
}

@ -19,6 +19,8 @@ import net.pokeranalytics.android.model.TableSize
import net.pokeranalytics.android.model.extensions.SessionState
import net.pokeranalytics.android.model.extensions.getState
import net.pokeranalytics.android.model.interfaces.Savable
import net.pokeranalytics.android.model.interfaces.Timed
import net.pokeranalytics.android.model.utils.SessionSetManager
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.UnmanagedRowRepresentableException
import net.pokeranalytics.android.ui.view.RowRepresentable
@ -31,8 +33,8 @@ import net.pokeranalytics.android.util.*
import java.util.*
import kotlin.collections.ArrayList
open class Session : RealmObject(), SessionInterface, Savable,
StaticRowRepresentableDataSource, RowRepresentable {
open class Session : RealmObject(), SessionInterface, Savable, StaticRowRepresentableDataSource, RowRepresentable,
Timed {
enum class Type {
CASH_GAME,
@ -60,13 +62,54 @@ open class Session : RealmObject(), SessionInterface, Savable,
// The result of the main user
var result: Result? = null
// The time frame of the Session, i.e. the start & end date
var timeFrame: TimeFrame? = null
// Timed interface
override var startDate: Date = Date()
set(value) {
field = value
this.computeDuration()
if (this.endDate != null && this.startDate.after(this.endDate)) {
this.endDate = null
}
this.dateChanged()
}
var endDate: Date? = null
set(value) {
field = value
value?.let { it.notifySessionDateChange(this) }
this.computeDuration()
this.dateChanged()
}
private fun dateChanged() {
if (this.endDate != null) {
SessionSetManager.updateTimeline(this)
} else if (this.sessionSet != null) {
SessionSetManager.removeFromTimeline(this)
}
}
override fun endDate(): Date {
return this.endDate ?: Date()
}
override var breakDuration: Long = 0L
set(value) {
field = value
this.computeDuration()
}
override var netDuration: Long = 0L
var pauseDate: Date? = null
// The time frame of the Session, i.e. the start & end date
// var timeFrame: TimeFrame? = null
// set(value) {
// field = value
// value?.let { it.notifySessionDateChange(this) }
// }
// The time frame sessionGroup, which can contain multiple sessions
override var sessionSet: SessionSet? = null
@ -129,16 +172,19 @@ open class Session : RealmObject(), SessionInterface, Savable,
* Return if this session is a tournament
*/
fun isTournament(): Boolean {
return type == Type.TOURNAMENT.ordinal
return this.type == Type.TOURNAMENT.ordinal
}
/**
* Return if this session is a cash game
*/
fun isCashGame(): Boolean {
return type == Type.CASH_GAME.ordinal
return this.type == Type.CASH_GAME.ordinal
}
// Stats
@Ignore // SessionInterface value
override var value: Double = 0.0
get() {
@ -146,7 +192,7 @@ open class Session : RealmObject(), SessionInterface, Savable,
}
@Ignore
override var estimatedHands: Double = 25.0 * (this.timeFrame?.hourlyDuration ?: 0.0)
override var estimatedHands: Double = 25.0 * this.hourlyDuration
@Ignore
override var bbNetResult: Double = 0.0
@ -171,25 +217,15 @@ open class Session : RealmObject(), SessionInterface, Savable,
@Ignore
override var buyin: Double = 0.0
get() {
this.result?.let {
it.buyin?.let {
this.result?.let { result ->
result.buyin?.let {
return it
}
}
return 0.0
}
@Ignore
var netDuration: Long = 0L
get() {
this.timeFrame?.let {
return it.netDuration
}
return 0L
}
@Ignore
var hourlyRate: Double = 0.0
val hourlyRate: Double
get() {
this.result?.let { result ->
return result.net / this.netDuration.toDouble()
@ -206,16 +242,19 @@ open class Session : RealmObject(), SessionInterface, Savable,
realm.executeTransaction {
when (getState()) {
SessionState.PENDING, SessionState.PLANNED -> {
val sessionTimeFrame = this.timeFrame ?: realm.createObject(TimeFrame::class.java)
sessionTimeFrame.setStart(Date())
this.startDate = Date()
// val sessionTimeFrame = this.timeFrame ?: realm.createObject(TimeFrame::class.java)
// sessionTimeFrame.setStart(Date())
// sessionTimeFrame.setDate(Date(), null)
this.timeFrame = sessionTimeFrame
// this.timeFrame = sessionTimeFrame
}
SessionState.PAUSED -> {
this.timeFrame?.paused = false
this.timeFrame?.pauseDate = null
// this.timeFrame?.paused = false
this.pauseDate = null
}
else -> {
throw IllegalStateException("unmanaged session state")
}
}
}
@ -228,9 +267,10 @@ open class Session : RealmObject(), SessionInterface, Savable,
realm.executeTransaction {
when (getState()) {
SessionState.STARTED -> {
this.timeFrame?.paused = true
this.timeFrame?.pauseDate = Date()
// this.?.paused = true
this.pauseDate = Date()
}
else -> throw IllegalStateException("unmanaged state")
}
}
}
@ -242,9 +282,10 @@ open class Session : RealmObject(), SessionInterface, Savable,
realm.executeTransaction {
when (getState()) {
SessionState.STARTED, SessionState.PAUSED -> {
this.timeFrame?.paused = false
this.timeFrame?.pauseDate = null
this.timeFrame?.setEnd(Date())
this.end()
// this.timeFrame?.paused = false
// this.pauseDate = null
// this.endDate = Date()
// this.timeFrame?.setDate(null, Date())
}
else -> throw Exception("Stopping session in unmanaged state")
@ -257,10 +298,17 @@ open class Session : RealmObject(), SessionInterface, Savable,
*/
fun restart() {
realm.executeTransaction {
this.timeFrame?.paused = false
this.timeFrame?.pauseDate = null
this.timeFrame?.setDate(Date(), null)
this.timeFrame?.breakDuration = 0L
// this.timeFrame?.paused = false
this.pauseDate = null
this.startDate = Date() // timeFrame?.setDate(Date(), null)
this.breakDuration = 0L
}
}
private fun end() {
this.pauseDate = null
if (this.endDate == null) {
this.endDate = Date()
}
}
@ -270,8 +318,7 @@ open class Session : RealmObject(), SessionInterface, Savable,
* Return the netDuration of the current session
*/
fun getDuration(): String {
val startDate = timeFrame?.startDate ?: Date()
val enDate = timeFrame?.endDate ?: Date()
val enDate = this.endDate ?: Date()
return startDate.getDuration(enDate)
}
@ -321,13 +368,14 @@ open class Session : RealmObject(), SessionInterface, Savable,
// cleanup unnecessary related objects
set.deleteFromRealm()
this.timeFrame?.deleteFromRealm()
// this.timeFrame?.deleteFromRealm()
this.result?.deleteFromRealm()
// make sessions recreate/find their session set
sessionsFromSet?.let { sessions ->
sessions.forEach { session ->
session.timeFrame?.notifySessionDateChange(session)
// @todo
// session.timeFrame?.notifySessionDateChange(session)
}
}
}
@ -381,7 +429,7 @@ open class Session : RealmObject(), SessionInterface, Savable,
HeaderRowRepresentable(
RowViewType.HEADER_TITLE_AMOUNT,
resId = R.string.hour_rate_without_pauses,
computedStat = ComputedStat(Stat.HOURLY_RATE, this.hourlyRate ?: 0.0)
computedStat = ComputedStat(Stat.HOURLY_RATE, this.hourlyRate)
)
)
@ -417,19 +465,17 @@ open class Session : RealmObject(), SessionInterface, Savable,
return when (row) {
SessionRow.BANKROLL -> bankroll?.name ?: NULL_TEXT
SessionRow.BLINDS -> getBlinds()
SessionRow.BREAK_TIME -> timeFrame?.breakDuration?.toMinutes() ?: NULL_TEXT
SessionRow.BREAK_TIME -> this.breakDuration.toMinutes()
SessionRow.BUY_IN -> buyin.toCurrency()
SessionRow.CASHED_OUT, SessionRow.PRIZE, SessionRow.NET_RESULT -> result?.cashout?.toCurrency() ?: NULL_TEXT
SessionRow.COMMENT -> if (comment.isNotEmpty()) comment else NULL_TEXT
SessionRow.END_DATE -> if (timeFrame != null) timeFrame?.endDate?.shortDateTime()
?: NULL_TEXT else NULL_TEXT
SessionRow.END_DATE -> this.endDate?.shortDateTime() ?: NULL_TEXT
SessionRow.GAME -> getGameTitle()
SessionRow.INITIAL_BUY_IN -> tournamentEntryFee?.toCurrency() ?: NULL_TEXT
SessionRow.LOCATION -> location?.name ?: NULL_TEXT
SessionRow.PLAYERS -> tournamentNumberOfPlayers?.toString() ?: NULL_TEXT
SessionRow.POSITION -> result?.tournamentFinalPosition?.toString() ?: NULL_TEXT
SessionRow.START_DATE -> if (timeFrame != null) timeFrame?.startDate?.shortDateTime()
?: NULL_TEXT else NULL_TEXT
SessionRow.START_DATE -> this.startDate.shortDateTime()
SessionRow.TABLE_SIZE -> this.tableSize?.let { TableSize(it).localizedTitle(context) } ?: NULL_TEXT
SessionRow.TIPS -> result?.tips?.toCurrency() ?: NULL_TEXT
SessionRow.TOURNAMENT_TYPE -> tournamentType?.name ?: NULL_TEXT
@ -481,12 +527,12 @@ open class Session : RealmObject(), SessionInterface, Savable,
}
SessionRow.BUY_IN -> {
// Add first & second buttons values, current value & set the 2 edit texts
if (cgBigBlind != null) {
data.add(RowRepresentableEditDescriptor(100.0 * (cgBigBlind ?: 0.0)))
data.add(RowRepresentableEditDescriptor(200.0 * (cgBigBlind ?: 0.0)))
} else if (tournamentEntryFee != null) {
data.add(RowRepresentableEditDescriptor((tournamentEntryFee ?: 0.0) * 1.0))
data.add(RowRepresentableEditDescriptor((tournamentEntryFee ?: 0.0) * 2.0))
if (this.cgBigBlind != null) {
data.add(RowRepresentableEditDescriptor(100.0 * (this.cgBigBlind ?: 0.0)))
data.add(RowRepresentableEditDescriptor(200.0 * (this.cgBigBlind ?: 0.0)))
} else if (this.tournamentEntryFee != null) {
data.add(RowRepresentableEditDescriptor((this.tournamentEntryFee ?: 0.0) * 1.0))
data.add(RowRepresentableEditDescriptor((this.tournamentEntryFee ?: 0.0) * 2.0))
} else {
data.add(RowRepresentableEditDescriptor(0))
data.add(RowRepresentableEditDescriptor(0))
@ -596,10 +642,10 @@ open class Session : RealmObject(), SessionInterface, Savable,
cgBigBlind = null
}
SessionRow.BREAK_TIME -> {
val timeFrameToUpdate =
if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
timeFrameToUpdate.breakDuration = if (value != null) (value as String).toLong() * 60 * 1000 else 0
timeFrame = timeFrameToUpdate
// val timeFrameToUpdate =
// if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
this.breakDuration = if (value != null) (value as String).toLong() * 60 * 1000 else 0
// timeFrame = timeFrameToUpdate
}
SessionRow.BUY_IN -> {
val localResult = if (result != null) result as Result else realm.createObject(Result::class.java)
@ -613,10 +659,12 @@ open class Session : RealmObject(), SessionInterface, Savable,
localResult.cashout = null
} else {
localResult.cashout = (value as String).toDouble()
val timeFrameToUpdate =
if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
timeFrameToUpdate.setEnd(Date())
timeFrame = timeFrameToUpdate
this.end()
// val timeFrameToUpdate =
// if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
// timeFrameToUpdate.setEnd(Date())
// timeFrame = timeFrameToUpdate
}
result = localResult
@ -624,11 +672,13 @@ open class Session : RealmObject(), SessionInterface, Savable,
SessionRow.COMMENT -> comment = value as String? ?: ""
SessionRow.END_DATE -> if (value is Date?) {
val timeFrameToUpdate =
if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
// timeFrameToUpdate.setDate(null, value)
timeFrameToUpdate.setEnd(value)
timeFrame = timeFrameToUpdate
this.endDate = value
// val timeFrameToUpdate =
// if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
//// timeFrameToUpdate.setDate(null, value)
// timeFrameToUpdate.setEnd(value)
// timeFrame = timeFrameToUpdate
}
SessionRow.GAME -> {
if (value is ArrayList<*>) {
@ -655,16 +705,17 @@ open class Session : RealmObject(), SessionInterface, Savable,
localResult.tournamentFinalPosition = if (value == null) null else (value as String).toInt()
result = localResult
}
SessionRow.START_DATE -> if (value is Date?) {
if (value == null) {
timeFrame = null
} else {
val timeFrameToUpdate =
if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
timeFrameToUpdate.setStart(value)
// timeFrameToUpdate.setDate(value, null)
timeFrame = timeFrameToUpdate
}
SessionRow.START_DATE -> if (value is Date) {
this.startDate = value
// if (value == null) {
// timeFrame = null
// } else {
// val timeFrameToUpdate =
// if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
// timeFrameToUpdate.setStart(value)
//// timeFrameToUpdate.setDate(value, null)
// timeFrame = timeFrameToUpdate
// }
}
SessionRow.TABLE_SIZE -> tableSize = value as Int?
SessionRow.TIPS -> {

@ -5,15 +5,41 @@ import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.Ignore
import io.realm.annotations.LinkingObjects
import net.pokeranalytics.android.model.interfaces.Timed
import java.util.*
open class SessionSet() : RealmObject() {
open class SessionSet : RealmObject(), Timed {
override var startDate: Date = Date()
set(value) {
field = value
this.computeDuration()
}
var endDate: Date = Date()
set(value) {
field = value
this.computeDuration()
}
override fun endDate(): Date {
return this.endDate
}
override var breakDuration: Long = 0L
set(value) {
field = value
this.computeDuration()
}
override var netDuration: Long = 0L
companion object {
fun newInstance(realm: Realm) : SessionSet {
val sessionSet: SessionSet = realm.createObject(SessionSet::class.java)
sessionSet.timeFrame = realm.createObject(TimeFrame::class.java)
// sessionSet.timeFrame = realm.createObject(TimeFrame::class.java)
return realm.copyToRealm(sessionSet)
}
@ -22,8 +48,7 @@ open class SessionSet() : RealmObject() {
/**
* The timeframe of the set, i.e. its start & end date
*/
var timeFrame: TimeFrame? = null
// var timeFrame: TimeFrame? = null
/**
* The list of sessions associated with this set
@ -31,37 +56,17 @@ open class SessionSet() : RealmObject() {
@LinkingObjects("sessionSet")
val sessions: RealmResults<Session>? = null
@Ignore // a netDuration shortcut
var duration: Long = 0L
get() {
return this.timeFrame?.netDuration ?: 0L
}
@Ignore // a netDuration in hour
var hourlyDuration: Double = 0.0
get() {
return this.timeFrame?.hourlyDuration ?: 0.0
}
@Ignore // a netResult shortcut
var netResult: Double = 0.0
get () {
return this.sessions?.sumByDouble { it.value } ?: 0.0
}
@Ignore
val netResult: Double = this.sessions?.sumByDouble { it.value } ?: 0.0
@Ignore // a netDuration shortcut
var hourlyRate: Double = 0.0
get () {
return this.netResult / this.hourlyDuration
}
@Ignore
val hourlyRate: Double = this.netResult / this.hourlyDuration
@Ignore
var estimatedHands: Double = 25.0 * (this.timeFrame?.hourlyDuration?.toDouble() ?: 0.0)
val estimatedHands: Double = 25.0 * this.hourlyDuration
@Ignore
var bbNetResult: Double = 0.0
}

@ -1,280 +1,288 @@
package net.pokeranalytics.android.model.realm
import io.realm.RealmObject
import io.realm.RealmQuery
import io.realm.RealmResults
import io.realm.annotations.Ignore
import io.realm.annotations.LinkingObjects
import net.pokeranalytics.android.exceptions.ModelException
import timber.log.Timber
import java.util.*
open class TimeFrame : RealmObject() {
// A start date
var startDate: Date = Date()
private set(value) {
field = value
this.computeDuration()
}
// An end date
var endDate: Date? = null
private set(value) {
field = value
this.computeDuration()
}
// The latest pause date
var pauseDate: Date? = null
set(value) {
field?.let {
if (value == null && field != null) {
breakDuration += Date().time - it.time
}
}
field = value
this.computeDuration()
}
// The break netDuration
var breakDuration: Long = 0L
set(value) {
field = value
this.computeDuration()
}
// the total netDuration
var netDuration: Long = 0L
private set
var hourlyDuration: Double = 0.0
get() {
return this.netDuration / 3600000.0 // 3.6 millions of milliseconds
}
// indicates a state of pause
var paused: Boolean = false
// Session
@LinkingObjects("timeFrame")
private val sessions: RealmResults<Session>? = null // we should have only one session
@Ignore
var session: Session? = null
get() = if (this.sessions != null && this.sessions.isEmpty()) null else this.sessions?.first()
// Group
@LinkingObjects("timeFrame")
private val sets: RealmResults<SessionSet>? = null // we should have only one sessionGroup
@Ignore
var set: SessionSet? = null
get() = this.sets?.first()
fun setStart(startDate: Date) {
this.startDate = startDate
this.session?.let {
this.notifySessionDateChange(it)
}
}
fun setEnd(endDate: Date?) {
this.endDate = endDate
this.session?.let {
this.notifySessionDateChange(it)
}
}
fun setDate(startDate: Date, endDate: Date?) {
this.startDate = startDate
this.endDate = endDate
this.session?.let {
this.notifySessionDateChange(it)
}
}
/**
* Computes the net netDuration of the session
*/
private fun computeDuration() {
var endDate: Date = this.endDate ?: Date()
this.netDuration = endDate.time - this.startDate.time - this.breakDuration
}
/**
* Queries all time frames that might be impacted by the date change
* Makes all necessary changes to keep sequential time frames
*/
fun notifySessionDateChange(owner: Session) {
var query: RealmQuery<SessionSet> = this.realm.where(SessionSet::class.java)
query.isNotNull("timeFrame")
// Timber.d("this> sd = : ${this.startDate}, ed = ${this.endDate}")
val sets = realm.where(SessionSet::class.java).findAll()
// Timber.d("set count = ${sets.size}")
if (this.endDate == null) {
query.greaterThanOrEqualTo("timeFrame.startDate", this.startDate)
.or()
.greaterThanOrEqualTo("timeFrame.endDate", this.startDate)
.or()
.isNull("timeFrame.endDate")
} else {
val endDate = this.endDate!!
query
.lessThanOrEqualTo("timeFrame.startDate", this.startDate)
.greaterThanOrEqualTo("timeFrame.endDate", this.startDate)
.or()
.lessThanOrEqualTo("timeFrame.startDate", endDate)
.greaterThanOrEqualTo("timeFrame.endDate", endDate)
.or()
.greaterThanOrEqualTo("timeFrame.startDate", this.startDate)
.lessThanOrEqualTo("timeFrame.endDate", endDate)
.or()
.isNull("timeFrame.endDate")
.lessThanOrEqualTo("timeFrame.startDate", endDate)
}
val sessionGroups = query.findAll()
this.updateTimeFrames(sessionGroups, owner)
}
/**
* Update Time frames from sets
*/
private fun updateTimeFrames(sessionSets: RealmResults<SessionSet>, owner: Session) {
when (sessionSets.size) {
0 -> this.createSessionGroup(owner)
1 -> this.updateSessionGroup(owner, sessionSets.first()!!)
else -> this.mergeSessionGroups(owner, sessionSets)
}
}
/**
* Creates the session sessionGroup when the session has none
*/
private fun createSessionGroup(owner: Session) {
val set: SessionSet = SessionSet.newInstance(this.realm)
set.timeFrame?.let {
it.startDate = this.startDate
it.endDate = this.endDate
} ?: run {
throw ModelException("TimeFrame should never be null here")
}
owner.sessionSet = set
// Timber.d("sd = : ${set.timeFrame?.startDate}, ed = ${set.timeFrame?.endDate}")
Timber.d("netDuration 1 = : ${set.timeFrame?.netDuration}")
}
/**
* Single SessionSet update, the session might be the owner
* Changes the sessionGroup timeframe using the current timeframe dates
*/
private fun updateSessionGroup(owner: Session, sessionSet: SessionSet) {
var timeFrame: TimeFrame = sessionSet.timeFrame!! // tested in the query
// timeFrame.setDate(this.startDate, this.endDate)
val sisterSessions = sessionSet.sessions!! // shouldn't crash ever
// if we have only one session in the set and that it corresponds to the set
if (sessionSet.sessions?.size == 1 && sessionSet.sessions?.first() == owner) {
timeFrame.setDate(this.startDate, this.endDate)
} else { // there are 2+ sessions to manage and possible splits
val endDate = this.endDate
// case where all sessions are over but the set is not, we might have a split, so we delete the set and save everything again
if (endDate != null && sisterSessions.all { it.timeFrame?.endDate != null } && timeFrame.endDate == null) {
var sessions = mutableListOf<Session>(owner)
sessionSet.sessions?.forEach { sessions.add(it) }
sessionSet.deleteFromRealm()
sessions.forEach { it.timeFrame?.notifySessionDateChange(it) }
} else {
if (this.startDate.before(timeFrame.startDate)) {
timeFrame.startDate = this.startDate
}
if (endDate != null && timeFrame.endDate != null && endDate.after(timeFrame.endDate)) {
timeFrame.endDate = endDate
} else if (endDate == null) {
timeFrame.endDate = null
}
owner.sessionSet = sessionSet
// Timber.d("sd = : ${sessionSet.timeFrame?.startDate}, ed = ${sessionSet.timeFrame?.endDate}")
Timber.d("netDuration 2 = : ${sessionSet.timeFrame?.netDuration}")
}
}
}
/**
* Multiple session sets update:
* Merges all sets into one (delete all then create a new one)
*/
private fun mergeSessionGroups(owner: Session, sessionSets: RealmResults<SessionSet>) {
var startDate: Date = this.startDate
var endDate: Date? = this.endDate
// find earlier and later dates from all sets
val timeFrames = sessionSets.mapNotNull { it.timeFrame }
timeFrames.forEach { tf ->
if (tf.startDate.before(startDate)) {
startDate = tf.startDate
}
endDate?.let { ed ->
tf.endDate?.let { tfed ->
if (tfed.after(ed)) {
endDate = tfed
}
}
} ?: run {
endDate = tf.endDate
}
}
// get all sessions from sets
var sessions = mutableSetOf<Session>()
sessionSets.forEach { set ->
set.sessions?.asIterable()?.let { sessions.addAll(it) }
}
// delete all sets
sessionSets.deleteAllFromRealm()
// Create a new sets
val set: SessionSet = SessionSet.newInstance(this.realm)
set.timeFrame?.let {
it.setDate(startDate, endDate)
} ?: run {
throw ModelException("TimeFrame should never be null here")
}
// Add the session linked to this timeframe to the new sessionGroup
owner.sessionSet = set
// Add all orphan sessions
sessions.forEach { it.sessionSet = set }
Timber.d("netDuration 3 = : ${set.timeFrame?.netDuration}")
}
}
//package net.pokeranalytics.android.model.realm
//
//import io.realm.RealmObject
//import io.realm.RealmQuery
//import io.realm.RealmResults
//import io.realm.annotations.Ignore
//import io.realm.annotations.LinkingObjects
//import net.pokeranalytics.android.exceptions.ModelException
//import timber.log.Timber
//import java.util.*
//
//open class TimeFrame : RealmObject() {
//
// // A start date
// var startDate: Date = Date()
// private set(value) {
// field = value
// this.computeDuration()
// }
//
// // An end date
// var endDate: Date? = null
// private set(value) {
// field = value
// this.computeDuration()
// }
//
// // The latest pause date
// var pauseDate: Date? = null
// set(value) {
// field?.let {
// if (value == null && field != null) {
// breakDuration += Date().time - it.time
// }
// }
// field = value
// this.computeDuration()
// }
//
// // The break netDuration
// var breakDuration: Long = 0L
// set(value) {
// field = value
// this.computeDuration()
// }
//
// // the total netDuration
// var netDuration: Long = 0L
// private set
//
// var hourlyDuration: Double = 0.0
// get() {
// return this.netDuration / 3600000.0 // 3.6 millions of milliseconds
// }
//
// // Session
// @LinkingObjects("timeFrame")
// private val sessions: RealmResults<Session>? = null // we should have only one session
//
// @Ignore
// var session: Session? = null
// get() = if (this.sessions != null && this.sessions.isEmpty()) null else this.sessions?.first()
//
// // Group
// @LinkingObjects("timeFrame")
// private val sets: RealmResults<SessionSet>? = null // we should have only one sessionGroup
//
// @Ignore
// var set: SessionSet? = null
// get() = this.sets?.first()
//
// fun setStart(startDate: Date) {
// this.startDate = startDate
// this.session?.let {
// this.notifySessionDateChange(it)
// }
// }
//
// fun setEnd(endDate: Date?) {
// this.endDate = endDate
// this.session?.let {
// this.notifySessionDateChange(it)
// }
// }
//
// fun setDate(startDate: Date, endDate: Date?) {
// this.startDate = startDate
// this.endDate = endDate
//
// this.session?.let {
// this.notifySessionDateChange(it)
// }
// }
//
// /**
// * Computes the net netDuration of the session
// */
// private fun computeDuration() {
// var endDate: Date = this.endDate ?: Date()
// this.netDuration = endDate.time - this.startDate.time - this.breakDuration
// }
//
// /**
// * Queries all time frames that might be impacted by the date change
// * Makes all necessary changes to keep sequential time frames
// */
// fun notifySessionDateChange(owner: Session) {
//
// var query: RealmQuery<SessionSet> = this.realm.where(SessionSet::class.java)
// query.isNotNull("timeFrame")
//
//// Timber.d("this> sd = : ${this.startDate}, ed = ${this.endDate}")
//
// val sets = realm.where(SessionSet::class.java).findAll()
//// Timber.d("set count = ${sets.size}")
//
// if (this.endDate == null) {
// query.greaterThanOrEqualTo("timeFrame.startDate", this.startDate)
// .or()
// .greaterThanOrEqualTo("timeFrame.endDate", this.startDate)
// .or()
// .isNull("timeFrame.endDate")
// } else {
// val endDate = this.endDate!!
// query
// .lessThanOrEqualTo("timeFrame.startDate", this.startDate)
// .greaterThanOrEqualTo("timeFrame.endDate", this.startDate)
// .or()
// .lessThanOrEqualTo("timeFrame.startDate", endDate)
// .greaterThanOrEqualTo("timeFrame.endDate", endDate)
// .or()
// .greaterThanOrEqualTo("timeFrame.startDate", this.startDate)
// .lessThanOrEqualTo("timeFrame.endDate", endDate)
// .or()
// .isNull("timeFrame.endDate")
// .lessThanOrEqualTo("timeFrame.startDate", endDate)
// }
//
// val sessionGroups = query.findAll()
//
// this.updateTimeFrames(sessionGroups, owner)
//
// }
//
// /**
// * Update Time frames from sets
// */
// private fun updateTimeFrames(sessionSets: RealmResults<SessionSet>, owner: Session) {
//
// when (sessionSets.size) {
// 0 -> this.createOrUpdateSessionSet(owner)
// 1 -> this.updateSessionGroup(owner, sessionSets.first()!!)
// else -> this.mergeSessionGroups(owner, sessionSets)
// }
//
// }
//
// /**
// * Creates the session sessionGroup when the session has none
// */
// private fun createOrUpdateSessionSet(owner: Session) {
//
// val set = owner.sessionSet
// if (set != null) {
// set.timeFrame?.startDate = this.startDate
// set.timeFrame?.endDate = this.endDate
// } else {
// this.createSessionSet(owner)
// }
//
//// Timber.d("sd = : ${set.timeFrame?.startDate}, ed = ${set.timeFrame?.endDate}")
// Timber.d("netDuration 1 = : ${set?.timeFrame?.netDuration}")
//
// }
//
// fun createSessionSet(owner: Session) {
// val set: SessionSet = SessionSet.newInstance(this.realm)
// set.timeFrame?.let {
// it.startDate = this.startDate
// it.endDate = this.endDate
// } ?: run {
// throw ModelException("TimeFrame should never be null here")
// }
//
// owner.sessionSet = set
// }
//
//
// /**
// * Single SessionSet update, the session might be the owner
// * Changes the sessionGroup timeframe using the current timeframe dates
// */
// private fun updateSessionGroup(owner: Session, sessionSet: SessionSet) {
//
// var timeFrame: TimeFrame = sessionSet.timeFrame!! // tested in the query
//// timeFrame.setDate(this.startDate, this.endDate)
//
// val sisterSessions = sessionSet.sessions!! // shouldn't crash ever
//
// // if we have only one session in the set and that it corresponds to the set
// if (sessionSet.sessions?.size == 1 && sessionSet.sessions?.first() == owner) {
// timeFrame.setDate(this.startDate, this.endDate)
// } else { // there are 2+ sessions to manage and possible splits
//
// val endDate = this.endDate
//
// // case where all sessions are over but the set is not, we might have a split, so we delete the set and save everything again
// if (endDate != null && sisterSessions.all { it.timeFrame?.endDate != null } && timeFrame.endDate == null) {
// var sessions = mutableListOf<Session>(owner)
// sessionSet.sessions?.forEach { sessions.add(it) }
// sessionSet.deleteFromRealm()
// sessions.forEach { it.timeFrame?.notifySessionDateChange(it) }
// } else {
//
// if (this.startDate.before(timeFrame.startDate)) {
// timeFrame.startDate = this.startDate
// }
// if (endDate != null && timeFrame.endDate != null && endDate.after(timeFrame.endDate)) {
// timeFrame.endDate = endDate
// } else if (endDate == null) {
// timeFrame.endDate = null
// }
//
// owner.sessionSet = sessionSet
//
//// Timber.d("sd = : ${sessionSet.timeFrame?.startDate}, ed = ${sessionSet.timeFrame?.endDate}")
// Timber.d("netDuration 2 = : ${sessionSet.timeFrame?.netDuration}")
// }
//
// }
//
// }
//
// /**
// * Multiple session sets update:
// * Merges all sets into one (delete all then create a new one)
// */
// private fun mergeSessionGroups(owner: Session, sessionSets: RealmResults<SessionSet>) {
//
// var startDate: Date = this.startDate
// var endDate: Date? = this.endDate
//
// // find earlier and later dates from all sets
// val timeFrames = sessionSets.mapNotNull { it.timeFrame }
// timeFrames.forEach { tf ->
// if (tf.startDate.before(startDate)) {
// startDate = tf.startDate
// }
//
// endDate?.let { ed ->
// tf.endDate?.let { tfed ->
// if (tfed.after(ed)) {
// endDate = tfed
// }
// }
// } ?: run {
// endDate = tf.endDate
// }
//
// }
//
// // get all sessions from sets
// var sessions = mutableSetOf<Session>()
// sessionSets.forEach { set ->
// set.sessions?.asIterable()?.let { sessions.addAll(it) }
// }
//
// // delete all sets
// sessionSets.deleteAllFromRealm()
//
// // Create a new sets
// val set: SessionSet = SessionSet.newInstance(this.realm)
// set.timeFrame?.let {
// it.setDate(startDate, endDate)
// } ?: run {
// throw ModelException("TimeFrame should never be null here")
// }
//
// // Add the session linked to this timeframe to the new sessionGroup
// owner.sessionSet = set
//
// // Add all orphan sessions
// sessions.forEach { it.sessionSet = set }
// Timber.d("netDuration 3 = : ${set.timeFrame?.netDuration}")
//
// }
//
//}

@ -106,7 +106,7 @@ class FavoriteSessionFinder {
lastSessionsQuery.equalTo("location.id", location.id)
}
val lastSessions = lastSessionsQuery
.sort("timeFrame.startDate", Sort.DESCENDING)
.sort("startDate", Sort.DESCENDING)
.limit(FAVORITE_SIGNIFICANT_SESSIONS)
.findAll()

@ -0,0 +1,140 @@
package net.pokeranalytics.android.model.utils
import io.realm.RealmQuery
import io.realm.RealmResults
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet
class SessionSetManager {
companion object {
fun updateTimeline(session: Session) {
if (!session.realm.isInTransaction) {
throw IllegalStateException("realm should be in transaction at this point")
}
if (session.endDate == null) {
throw IllegalStateException("End date should never be null here")
}
val endDate = session.endDate!! // tested above
val startDate = session.startDate
val realm = session.realm
val query: RealmQuery<SessionSet> = realm.where(SessionSet::class.java)
query
.lessThanOrEqualTo("startDate", startDate)
.greaterThanOrEqualTo("endDate", startDate)
.or()
.lessThanOrEqualTo("startDate", endDate)
.greaterThanOrEqualTo("endDate", endDate)
.or()
.greaterThanOrEqualTo("startDate", startDate)
.lessThanOrEqualTo("endDate", endDate)
val sessionGroups = query.findAll()
this.updateTimeFrames(sessionGroups, session)
}
/**
* Update Time frames from sets
*/
private fun updateTimeFrames(sessionSets: RealmResults<SessionSet>, session: Session) {
when (sessionSets.size) {
0 -> this.createOrUpdateSessionSet(session)
else -> this.mergeSessionGroups(session, sessionSets)
}
}
private fun createOrUpdateSessionSet(session: Session) {
val set = session.sessionSet
if (set != null) {
set.startDate = session.startDate
set.endDate = session.endDate!!
} else {
this.createSessionSet(session)
}
}
private fun createSessionSet(session: Session) {
val set: SessionSet = SessionSet.newInstance(session.realm)
set.startDate = session.startDate
set.endDate = session.endDate!!
session.sessionSet = set
}
/**
* Multiple session sets update:
* Merges all sets into one (delete all then create a new one)
*/
private fun mergeSessionGroups(session: Session, sessionSets: RealmResults<SessionSet>) {
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 sessions from sets
val sessions = mutableSetOf<Session>()
sessionSets.forEach { set ->
set.sessions?.asIterable()?.let { sessions.addAll(it) }
}
// delete all sets
sessionSets.deleteAllFromRealm()
// Create a new set
val set: SessionSet = SessionSet.newInstance(session.realm)
set.startDate = startDate
set.endDate = endDate
// Add the session linked to this timeframe to the new sessionGroup
session.sessionSet = set
// Add all orphan sessions
sessions.forEach { it.sessionSet = set }
// Timber.d("netDuration 3 = : ${set.timeFrame?.netDuration}")
}
fun removeFromTimeline(session: Session) {
if (!session.realm.isInTransaction) {
throw IllegalStateException("realm should be in transaction at this point")
}
val sessionSet = session.sessionSet
if (sessionSet != null) {
val sessions = mutableSetOf<Session>()
sessionSet.sessions?.asIterable()?.let { sessions.addAll(it) }
sessions.remove(session)
sessionSet.deleteFromRealm()
sessions.forEach {
SessionSetManager.updateTimeline(it)
}
}
}
}
}

@ -90,13 +90,13 @@ class SessionFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Bott
requireContext(),
row,
this,
currentSession.timeFrame?.startDate ?: Date()
currentSession.startDate
)
SessionRow.END_DATE -> DateTimePickerManager.create(
requireContext(),
row,
this,
currentSession.timeFrame?.endDate ?: currentSession.timeFrame?.startDate ?: Date()
currentSession.endDate ?: currentSession.startDate ?: Date()
)
SessionRow.BANKROLL -> {
BottomSheetFragment.create(fragmentManager, row, this, data, false)

@ -16,7 +16,6 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.SessionObserverFragment
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.HeaderRowRepresentable
import net.pokeranalytics.android.util.NULL_TEXT
@ -111,7 +110,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
}
}
val allStats: List<Stat> = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE, Stat.NUMBER_OF_GAMES, Stat.AVERAGE_DURATION, Stat.DURATION)
val allStats: List<Stat> = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE, Stat.NUMBER_OF_SETS, Stat.AVERAGE_DURATION, Stat.DURATION)
val allSessionGroup = SessionGroup(getString(R.string.all), super.sessions, allStats)
val cgStats: List<Stat> = 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)

@ -10,7 +10,7 @@ open class SessionObserverFragment : PokerAnalyticsFragment() {
init {
val realm = Realm.getDefaultInstance()
this.sessions = realm.where(Session::class.java).isNotNull("timeFrame.endDate").findAll()
this.sessions = realm.where(Session::class.java).isNotNull("endDate").findAll()
this.sessions.addChangeListener { _, _ ->
this.sessionsChanged()
}

@ -95,11 +95,13 @@ class SessionRowView : FrameLayout {
rowHistorySession.sessionTitle.text = title
// Duration
rowHistorySession.sessionInfoDurationIcon.isVisible = session.timeFrame != null
rowHistorySession.sessionInfoDurationValue.isVisible = session.timeFrame != null
session.timeFrame?.let {
rowHistorySession.sessionInfoDurationValue.text = session.getDuration()
}
// rowHistorySession.sessionInfoDurationIcon.isVisible = session.timeFrame != null
// rowHistorySession.sessionInfoDurationValue.isVisible = session.timeFrame != null
// session.timeFrame?.let {
// rowHistorySession.sessionInfoDurationValue.text = session.getDuration()
// }
rowHistorySession.sessionInfoDurationValue.text = session.getDuration()
// Location
rowHistorySession.sessionInfoLocationIcon.isVisible = session.location != null
@ -127,7 +129,7 @@ class SessionRowView : FrameLayout {
rowHistorySession.infoIcon.isVisible = true
rowHistorySession.infoIcon.setImageResource(R.drawable.ic_planned)
rowHistorySession.infoTitle.isVisible = true
rowHistorySession.infoTitle.text = session.timeFrame?.startDate?.shortTime()
rowHistorySession.infoTitle.text = session.startDate.shortTime()
} else {
rowHistorySession.gameResult.isVisible = true
rowHistorySession.infoIcon.isVisible = false

@ -8,7 +8,7 @@
<!-- Stats -->
<string name="hourly_rate">Hourly Rate</string>
<string name="number_of_groups">Number of groups</string>
<string name="number_of_groups">Number of sessions</string>
<string name="number_of_games">Number of games</string>
<string name="average_duration">Average duration</string>
<string name="net_bb_per_100_hands">Net(BB) per 100 hands</string>

Loading…
Cancel
Save