diff --git a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt index 33fcc8c2..ede13e9f 100644 --- a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt +++ b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt @@ -9,6 +9,8 @@ import timber.log.Timber class PokerAnalyticsApplication: Application() { +// var timeFrames: RealmResults? = null + override fun onCreate() { super.onCreate() @@ -20,6 +22,13 @@ class PokerAnalyticsApplication: Application() { .build() Realm.setDefaultConfiguration(realmConfiguration) +// val realm: Realm = Realm.getDefaultInstance() +// // Add observer on session time frame changes +// this.timeFrames = realm.where(Session::class.java).findAllAsync() +// this.timeFrames?.addChangeListener { t, changeSet -> // @todo check if main thread has running Looper, cf Realm doc +// changeSet.deletions +// } + if (BuildConfig.DEBUG) { // Logs Timber.plant(PokerAnalyticsLogs()) 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 374e4c03..43b967b4 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -1,7 +1,7 @@ package net.pokeranalytics.android.calculus import net.pokeranalytics.android.calculus.Stat.* -import net.pokeranalytics.android.model.realm.SessionGroup +import net.pokeranalytics.android.model.realm.SessionSet class Calculator { @@ -40,20 +40,20 @@ class Calculator { companion object { - fun computePreAggregation(groups: List, options: Options): List { + fun computePreAggregation(sets: List, options: Options): List { return listOf() } - // Computes all stats for list of Session group - fun computeGroups(groups: List, options: Options): List { + // Computes all stats for list of Session sessionGroup + fun computeGroups(groups: List, options: Options): List { var computedGroups: MutableList = mutableListOf() groups.forEach { group -> - // Computes actual group stats + // Computes actual sessionGroup stats val results: ComputedResults = Calculator.compute(group, options = options) - // Computes the compared group if existing - val comparedGroup = group.comparedGroup + // Computes the compared sessionGroup if existing + val comparedGroup = group.comparedSessions if (comparedGroup != null) { val comparedResults = Calculator.compute(comparedGroup, options = options) group.comparedComputedGroup = ComputedGroup(comparedGroup, comparedResults) @@ -68,11 +68,11 @@ class Calculator { return computedGroups } - // Computes stats for a SessionGroup - fun compute(group: ComputableSessions, options: Options) : ComputedResults { + // Computes stats for a SessionSet + fun compute(sessionGroup: SessionGroup, options: Options) : ComputedResults { - val sessions: List = group.sessionGroup - val sessionGroups: Set = setOf() // @todo get unique list of serie + val sessions: List = sessionGroup.sessions + val sessionSets: Set = setOf() // @todo get unique list of serie var results: ComputedResults = ComputedResults() var sum: Double = 0.0 @@ -82,28 +82,28 @@ class Calculator { var winningSessionCount: Int = 0 var totalBuyin: Double = 0.0 - // @todo add all stats - // Compute for each session var index: Int = 0 sessions.forEach { s -> index++; + sum += s.value + bbSum += s.bbNetResult bbSessionCount += s.bigBlindSessionCount if (s.value >= 0) { winningSessionCount++ } totalBuyin += s.buyin + totalHands += s.estimatedHands - if (options.evolutionValues != Options.EvolutionValues.NONE) { + if (options.evolutionValues == Options.EvolutionValues.STANDARD) { - sum += s.value - totalHands += s.estimatedHands - bbSum += s.bbNetResult + results.addEvolutionValue(sum, NETRESULT) results.addEvolutionValue(sum / index, AVERAGE) results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES) results.addEvolutionValue(bbSum / bbSessionCount, AVERAGE_NET_BB) + results.addEvolutionValue(Stat.netBBPer100Hands(bbSum, totalHands), NET_BB_PER_100_HANDS) results.addEvolutionValue((winningSessionCount / index).toDouble(), WIN_RATIO) results.addEvolutionValue(totalBuyin / index, AVERAGE_BUYIN) results.addEvolutionValue(Stat.returnOnInvestment(sum, totalBuyin), ROI) @@ -115,25 +115,25 @@ class Calculator { var duration: Double = 0.0 var hourlyRate: Double = 0.0; var hourlyRateBB: Double = 0.0 - index = 0; sum = 0.0; totalHands = 0.0; bbSum = 0.0; - sessionGroups.forEach { group -> - index++ + var gIndex = 0; var gSum = 0.0; var gTotalHands = 0.0; var gBBSum = 0.0; + sessionSets.forEach { group -> + gIndex++ duration += group.duration - sum += group.netResult - totalHands += group.estimatedHands - bbSum += group.bbNetResult + gSum += group.netResult + gTotalHands += group.estimatedHands + gBBSum += group.bbNetResult - hourlyRate = sum / duration * 3600.0 - hourlyRateBB = bbSum / duration * 3600.0 + hourlyRate = gSum / duration * 3600.0 + hourlyRateBB = gBBSum / duration * 3600.0 - if (options.evolutionValues != Options.EvolutionValues.NONE) { - results.addEvolutionValue(sum, duration, NETRESULT) - results.addEvolutionValue(sum / duration * 3600.0, duration, HOURLY_RATE) - results.addEvolutionValue(Stat.netBBPer100Hands(bbSum, totalHands), duration, NET_BB_PER_100_HANDS) + if (options.evolutionValues == Options.EvolutionValues.DATED) { + results.addEvolutionValue(gSum, duration, NETRESULT) + results.addEvolutionValue(gSum / duration * 3600.0, duration, HOURLY_RATE) + results.addEvolutionValue(Stat.netBBPer100Hands(gBBSum, gTotalHands), duration, NET_BB_PER_100_HANDS) results.addEvolutionValue(hourlyRate, duration, HOURLY_RATE) - results.addEvolutionValue(index.toDouble(), duration, NUMBER_OF_GROUPS) + results.addEvolutionValue(gIndex.toDouble(), duration, NUMBER_OF_GROUPS) results.addEvolutionValue(group.duration, duration, DURATION) - results.addEvolutionValue(duration / index, duration, AVERAGE_DURATION) + results.addEvolutionValue(duration / gIndex, duration, AVERAGE_DURATION) results.addEvolutionValue(hourlyRateBB, duration, HOURLY_RATE_BB) } } @@ -146,7 +146,7 @@ class Calculator { ComputedStat(HOURLY_RATE, hourlyRate), ComputedStat(AVERAGE, average), ComputedStat(DURATION, duration), - ComputedStat(NUMBER_OF_GROUPS, sessionGroups.size.toDouble()), + ComputedStat(NUMBER_OF_GROUPS, sessionSets.size.toDouble()), ComputedStat(NUMBER_OF_GAMES, sessions.size.toDouble()), ComputedStat(AVERAGE_DURATION, (duration / 3600.0) / sessions.size), ComputedStat(NET_BB_PER_100_HANDS, Stat.netBBPer100Hands(bbSum, totalHands)), @@ -154,7 +154,8 @@ class Calculator { ComputedStat(AVERAGE_NET_BB, bbSum / bbSessionCount), ComputedStat(WIN_RATIO, (winningSessionCount / sessions.size).toDouble()), ComputedStat(AVERAGE_BUYIN, totalBuyin / sessions.size), - ComputedStat(ROI, Stat.returnOnInvestment(sum, totalBuyin)) + ComputedStat(ROI, Stat.returnOnInvestment(sum, totalBuyin)), + ComputedStat(HANDS_PLAYED, totalHands) )) @@ -169,10 +170,10 @@ class Calculator { val standardDeviation: Double = Math.sqrt(stdSum / sessions.size) var hourlyStdSum: Double = 0.0 - sessionGroups.forEach { sg -> + sessionSets.forEach { sg -> hourlyStdSum += Math.pow(sg.hourlyRate - hourlyRate, 2.0) } - val hourlyStandardDeviation: Double = Math.sqrt(hourlyStdSum / sessionGroups.size) + val hourlyStandardDeviation: Double = Math.sqrt(hourlyStdSum / sessionSets.size) results.addStats(setOf( ComputedStat(STANDARD_DEVIATION, standardDeviation), diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt index 816de83c..94ce69bc 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Computable.kt @@ -1,6 +1,6 @@ package net.pokeranalytics.android.calculus -import net.pokeranalytics.android.model.realm.SessionGroup +import net.pokeranalytics.android.model.realm.SessionSet /** * An interface to describe objects that can be summed @@ -13,7 +13,7 @@ interface Summable { * An interface describing some class that can be computed */ interface SessionInterface : Summable { - var serie: SessionGroup + var serie: SessionSet var estimatedHands: Double var bbNetResult: Double var bigBlindSessionCount: Int // 0 or 1 @@ -21,26 +21,26 @@ interface SessionInterface : Summable { } /** - * A group of computable items identified by a name + * A sessionGroup of computable items identified by a name */ -class ComputableSessions(name: String, sessions: List) { +class SessionGroup(name: String, sessions: List) { var name: String = name - var sessionGroup: List = sessions + var sessions: List = sessions // A subgroup used to compute stat variation - var comparedGroup: ComputableSessions? = null + var comparedSessions: SessionGroup? = null - // The computed stats of the comparable group + // The computed stats of the comparable sessionGroup var comparedComputedGroup: ComputedGroup? = null } -class ComputedGroup(group: ComputableSessions, computedResults: ComputedResults) { - // A computable group - var group: ComputableSessions = group +class ComputedGroup(sessionGroup: SessionGroup, computedResults: ComputedResults) { + // A computable sessionGroup + var sessionGroup: SessionGroup = sessionGroup - // The computed stats of the group + // The computed stats of the sessionGroup var computedResults: ComputedResults = computedResults fun statValue(stat: Stat) : Double? { @@ -51,7 +51,7 @@ class ComputedGroup(group: ComputableSessions, computedResults: ComputedResults) class ComputedResults() { - // The computed stats of the group + // The computed stats of the sessionGroup private var _computedStats: MutableMap = mutableMapOf() // The map containing all evolution values for all stats diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt index a77de252..a95d1452 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt @@ -21,7 +21,8 @@ enum class Stat : AnyStat { ROI, STANDARD_DEVIATION, STANDARD_DEVIATION_HOURLY, - STANDARD_DEVIATION_BB_PER_100_HANDS; + STANDARD_DEVIATION_BB_PER_100_HANDS, + HANDS_PLAYED; fun label() : String = when (this) { NETRESULT -> "" 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 4839fc7b..a9071093 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 @@ -23,8 +23,8 @@ open class Session(comment: String = "") : RealmObject(), DynamicRowDelegate, Di // The time frame of the Session, i.e. the start & end date var timeFrame: TimeFrame? = null - // The time frame group, which can contain multiple sessions - var sessionGroup: SessionGroup? = null + // The time frame sessionGroup, which can contain multiple sessions + var sessionSet: SessionSet? = null // the date of creation of the app var creationDate: Date = Date() diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionGroup.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt similarity index 60% rename from app/src/main/java/net/pokeranalytics/android/model/realm/SessionGroup.kt rename to app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt index eb8f6521..6645c7c5 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionGroup.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt @@ -5,12 +5,12 @@ import io.realm.RealmObject import io.realm.annotations.Ignore -open class SessionGroup() : RealmObject() { +open class SessionSet() : RealmObject() { - // The timeframe of the group, i.e. its start & end date + // The timeframe of the set, i.e. its start & end date var timeFrame: TimeFrame? = null - // The list of Session played within the group, i.e. played within the same time frame + // The list of Session played within the set, i.e. played within the same time frame var sessions: RealmList = RealmList() @Ignore // a duration shortcut @@ -30,10 +30,10 @@ open class SessionGroup() : RealmObject() { companion object { - fun newInstance() : SessionGroup { - val sessionGroup: SessionGroup = SessionGroup() - sessionGroup.timeFrame = TimeFrame() - return sessionGroup + fun newInstance() : SessionSet { + val sessionSet: SessionSet = SessionSet() + sessionSet.timeFrame = TimeFrame() + 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 8f0eb411..a976f66b 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 @@ -44,11 +44,11 @@ open class TimeFrame : RealmObject() { // Group @LinkingObjects("timeFrame") - private val groups: RealmResults? = null // we should have only one group + private val sets: RealmResults? = null // we should have only one sessionGroup @Ignore - var group: SessionGroup? = null - get() = this.groups?.first() + var set: SessionSet? = null + get() = this.sets?.first() fun setDate(startDate: Date, endDate: Date?) { this.startDate = startDate @@ -68,7 +68,7 @@ open class TimeFrame : RealmObject() { private fun notifySessionDateChange() { val realm = Realm.getDefaultInstance() - var query: RealmQuery = realm.where(SessionGroup::class.java) + var query: RealmQuery = realm.where(SessionSet::class.java) query.isNotNull("timeFrame") if (this.endDate == null) { @@ -94,44 +94,44 @@ open class TimeFrame : RealmObject() { } /** - * Update Time frames from groups + * Update Time frames from sets */ - private fun updateTimeFrames(sessionGroups: RealmResults) { + private fun updateTimeFrames(sessionSets: RealmResults) { - when (sessionGroups.size) { + when (sessionSets.size) { 0 -> this.createSessionGroup() - 1 -> this.updateSingleSessionGroup(sessionGroups.first()!!) - else -> this.mergeSessionGroups(sessionGroups) + 1 -> this.updateSingleSessionGroup(sessionSets.first()!!) + else -> this.mergeSessionGroups(sessionSets) } } /** - * Creates the session group when the session has none + * Creates the session sessionGroup when the session has none */ private fun createSessionGroup() { val realm = Realm.getDefaultInstance() realm.beginTransaction() - val group: SessionGroup = SessionGroup.newInstance() - group.timeFrame?.let { + val set: SessionSet = SessionSet.newInstance() + set.timeFrame?.let { it.startDate = this.startDate it.endDate = this.endDate } ?: run { throw ModelException("TimeFrame should never be null here") } - group.sessions.add(this.session) + set.sessions.add(this.session) realm.commitTransaction() } /** - * Single session group update - * Changes the group timeframe using the current timeframe dates + * Single session sessionGroup update + * Changes the sessionGroup timeframe using the current timeframe dates */ - private fun updateSingleSessionGroup(sessionGroup: SessionGroup) { + private fun updateSingleSessionGroup(sessionSet: SessionSet) { - var groupTimeFrame: TimeFrame = sessionGroup.timeFrame!! // tested in the query + var groupTimeFrame: TimeFrame = sessionSet.timeFrame!! // tested in the query if (this.startDate.before(groupTimeFrame.startDate)) { groupTimeFrame.startDate = this.startDate @@ -146,8 +146,8 @@ open class TimeFrame : RealmObject() { // Realm Update val realm = Realm.getDefaultInstance() realm.beginTransaction() - if (!sessionGroup.sessions.contains(this.session)) { - sessionGroup.sessions.add(this.session) + if (!sessionSet.sessions.contains(this.session)) { + sessionSet.sessions.add(this.session) } realm.copyToRealmOrUpdate(groupTimeFrame) realm.commitTransaction() @@ -155,15 +155,15 @@ open class TimeFrame : RealmObject() { } /** - * Multiple session groups update: - * Merges all groups into one (delete all then create a new one) + * Multiple session sets update: + * Merges all sets into one (delete all then create a new one) */ - private fun mergeSessionGroups(sessionGroups: RealmResults) { + private fun mergeSessionGroups(sessionSets: RealmResults) { var startDate: Date = this.startDate var endDate: Date? = this.endDate - val timeFrames = sessionGroups.mapNotNull { it.timeFrame } + val timeFrames = sessionSets.mapNotNull { it.timeFrame } timeFrames.forEach { tf -> if (tf.startDate.before(startDate)) { startDate = tf.startDate @@ -181,34 +181,34 @@ open class TimeFrame : RealmObject() { } - // get all sessions from groups - var sessions = sessionGroups.flatMap { it.sessions } + // get all sessions from sets + var sessions = sessionSets.flatMap { it.sessions } // Start Realm updates val realm = Realm.getDefaultInstance() realm.beginTransaction() - // delete all groups - sessionGroups.deleteAllFromRealm() + // delete all sets + sessionSets.deleteAllFromRealm() - // Create a new groups - val group: SessionGroup = SessionGroup.newInstance() - group.timeFrame?.let { + // Create a new sets + val set: SessionSet = SessionSet.newInstance() + set.timeFrame?.let { it.startDate = startDate it.endDate = endDate } ?: run { throw ModelException("TimeFrame should never be null here") } - // Add the session linked to this timeframe to the new group + // Add the session linked to this timeframe to the new sessionGroup this.sessions?.first()?.let { - group.sessions.add(it) + set.sessions.add(it) } ?: run { throw ModelException("TimeFrame should never be null here") } // Add all orphan sessions - group.sessions.addAll(sessions) + set.sessions.addAll(sessions) 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 2370b6e3..e4b9978a 100644 --- a/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt +++ b/app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt @@ -1,7 +1,7 @@ package net.pokeranalytics.android import net.pokeranalytics.android.calculus.* -import net.pokeranalytics.android.model.realm.SessionGroup +import net.pokeranalytics.android.model.realm.SessionSet import org.junit.Assert.fail import org.junit.Test @@ -17,7 +17,7 @@ class ExampleUnitTest { // override var serie: Serie = Serie(TimeFrame()) override var value: Double = someValue - override var serie: SessionGroup = SessionGroup() + override var serie: SessionSet = SessionSet() override var estimatedHands: Double = 0.0 override var bbNetResult: Double = 0.0 override var bigBlindSessionCount: Int = 0 // 0 or 1 @@ -28,21 +28,21 @@ class ExampleUnitTest { @Test fun testStats() { - val grades: List = listOf(Grade(someValue = 10.0), Grade(someValue = 20.0)) + val grades: List = listOf(Grade(10.0), Grade(20.0)) val group = SessionGroup(name = "test", sessions = grades) val results: ComputedResults = Calculator.compute(group, Calculator.Options()) val sum = results.computedStat(Stat.NETRESULT) if (sum != null) { - assert(sum.value == 30.0) + assert(sum.value == 30.0) { "sum is ${sum.value}" } } else { fail("No Net result stat") } val average = results.computedStat(Stat.AVERAGE) if (average != null) { - assert(average.value == 15.0) + assert(average.value == 15.0) { "average is ${average.value}" } } else { fail("No AVERAGE stat") }