Merge branch 'master' of gitlab.com:stax-river/poker-analytics

feature/top10
Razmig Sarkissian 7 years ago
commit bb611a53d3
  1. 4
      app/src/androidTest/java/net/pokeranalytics/android/BankrollInstrumentedUnitTest.kt
  2. 14
      app/src/androidTest/java/net/pokeranalytics/android/StatsInstrumentedUnitTest.kt
  3. 64
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  4. 52
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  5. 12
      app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt
  6. 40
      app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt
  7. 122
      app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt
  8. 17
      app/src/main/java/net/pokeranalytics/android/calculus/interfaces/Computable.kt
  9. 11
      app/src/main/java/net/pokeranalytics/android/calculus/interfaces/Datable.kt
  10. 2
      app/src/main/java/net/pokeranalytics/android/model/filter/FilterComponent.kt
  11. 51
      app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt
  12. 19
      app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt
  13. 67
      app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt
  14. 42
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  15. 2
      app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt
  16. 54
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt
  17. 6
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/SessionObserverFragment.kt
  18. 4
      app/src/test/java/net/pokeranalytics/android/ExampleUnitTest.kt

@ -3,7 +3,7 @@ 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.ComputableGroup
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.model.realm.Currency
@ -56,7 +56,7 @@ class BankrollInstrumentedUnitTest : RealmInstrumentedUnitTest() {
realm.commitTransaction()
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val group = ComputableGroup(name = "test", computables = sessions)
val options = Calculator.Options()

@ -7,7 +7,7 @@ import io.realm.RealmResults
import io.realm.kotlin.where
import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.ComputedResults
import net.pokeranalytics.android.calculus.SessionGroup
import net.pokeranalytics.android.calculus.ComputableGroup
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.model.Limit
import net.pokeranalytics.android.model.realm.*
@ -127,7 +127,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
realm.commitTransaction()
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val group = ComputableGroup(name = "test", computables = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
@ -277,7 +277,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
realm.commitTransaction()
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val group = ComputableGroup(name = "test", computables = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
@ -344,7 +344,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
realm.commitTransaction()
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val group = ComputableGroup(name = "test", computables = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
@ -427,7 +427,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
realm.commitTransaction()
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val group = ComputableGroup(name = "test", computables = sessions)
val options = Calculator.Options()
options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)
@ -446,7 +446,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
s1.deleteFromRealm()
}
val group2 = SessionGroup(name = "test", sessions = sessions)
val group2 = ComputableGroup(name = "test", computables = sessions)
val results2: ComputedResults = Calculator.compute(group2, options)
val duration2 = results2.computedStat(Stat.DURATION)
@ -598,7 +598,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() {
}
val sessions = realm.where(Session::class.java).findAll()
val group = SessionGroup(name = "test", sessions = sessions)
val group = ComputableGroup(name = "test", computables = sessions)
val options = Calculator.Options()
// options.displayedStats = listOf(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS, Stat.STANDARD_DEVIATION)

@ -70,6 +70,64 @@ class PokerAnalyticsApplication : Application() {
}
}
//
// private fun createFakeStats() {
//
// val buyinList = arrayListOf(100.0, 200.0, 300.0, 500.0, 1000.0, 2000.0)
// val resultsList = arrayListOf(
// -2500.0, -2000.0, -1500.0, -1000.0, -500.0, 200.0, 1000.0, 1500.0, 2500.0
// )
//
// val commitFrequency = 100
//
// Thread() {
//
// try {
//
// val realm = Realm.getDefaultInstance()
//
// // Test endedSessions
// val pstats = realm.where<ComputableResult>().findAll()
// if (pstats.size < 10) {
//
// val numberOfSessions = 2000
// Timber.d("*** Start creating ${numberOfSessions} fake computables...")
//
// val s = Date()
//
// realm.beginTransaction()
//
// for (index in 0..numberOfSessions) {
//
// if (index % commitFrequency == 0) {
// Timber.d("****** committing at ${index} computables...")
// realm.commitTransaction()
// realm.beginTransaction()
// }
//
// val ps = realm.createObject(ComputableResult::class.java)
// ps.ratedBuyin = buyinList.random()
// ps.ratedNet = resultsList.random()
//
// }
//
// realm.commitTransaction()
//
// val e = Date()
// val duration = (e.time - s.time) / 1000.0
// Timber.d("*** ended in ${duration} seconds")
//
// }
//
// realm.close()
//
// } catch (e: Exception) {
// Timber.e(e)
// }
//
// }.start()
//
// }
private fun createFakeSessions() {
@ -92,8 +150,8 @@ class PokerAnalyticsApplication : Application() {
val sessions = realm.where<Session>().findAll()
if (sessions.size < 10) {
val numberOfSessions = 200
Timber.d("*** Start creating ${numberOfSessions} fake sessions...")
val numberOfSessions = 2000
Timber.d("*** Start creating ${numberOfSessions} fake computables...")
val s = Date()
@ -102,7 +160,7 @@ class PokerAnalyticsApplication : Application() {
for (index in 0..numberOfSessions) {
if (index % commitFrequency == 0) {
Timber.d("****** committing at ${index} sessions...")
Timber.d("****** committing at ${index} computables...")
realm.commitTransaction()
realm.beginTransaction()
}

@ -1,7 +1,7 @@
package net.pokeranalytics.android.calculus
import net.pokeranalytics.android.calculus.Stat.*
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.calculus.interfaces.Computable
import net.pokeranalytics.android.model.realm.SessionSet
import timber.log.Timber
import java.util.*
@ -66,7 +66,7 @@ class Calculator {
/**
* Computes all stats for list of Session sessionGroup
*/
fun computeGroups(groups: List<SessionGroup>, options: Options): List<ComputedResults> {
fun computeGroups(groups: List<ComputableGroup>, options: Options): List<ComputedResults> {
val computedResults = mutableListOf<ComputedResults>()
groups.forEach { group ->
@ -75,7 +75,7 @@ class Calculator {
val results: ComputedResults = Calculator.compute(group, options = options)
// Computes the compared sessionGroup if existing
val comparedGroup = group.comparedSessions
val comparedGroup = group.comparedComputables
if (comparedGroup != null) {
val comparedResults = Calculator.compute(comparedGroup, options = options)
group.comparedComputedResults = comparedResults
@ -94,13 +94,13 @@ class Calculator {
return computedResults
}
// fun compute(sessionGroup: SessionGroup, options: Options): ComputedResults {
// fun compute(sessionGroup: ComputableGroup, options: Options): ComputedResults {
//
// var sum: Double = 0.0
// val sessions: List<SessionInterface> = sessionGroup.sessions
// val computables: List<SessionInterface> = sessionGroup.computables
// val results: ComputedResults = ComputedResults(sessionGroup)
//
// sessions.forEach { s ->
// computables.forEach { s ->
// sum += s.ratedNet
// }
//
@ -117,34 +117,34 @@ class Calculator {
/**
* Computes stats for a SessionSet
*/
fun compute(sessionGroup: SessionGroup, options: Options): ComputedResults {
fun compute(computableGroup: ComputableGroup, options: Options): ComputedResults {
Timber.d(">>>> Start computing group ${sessionGroup.name}, ${sessionGroup.sessions.size} sessions")
Timber.d(">>>> Start computing group ${computableGroup.name}, ${computableGroup.computables.size} computables")
val sessions: List<Session> = sessionGroup.sessions
val sessionSets = sessionGroup.sessions.mapNotNull { it.sessionSet }.toHashSet()
val computables: List<Computable> = computableGroup.computables
val sessionSets = computableGroup.computables.mapNotNull { it.sessionSet }.toHashSet()
val results: ComputedResults = ComputedResults(sessionGroup)
val results: ComputedResults = ComputedResults(computableGroup)
var sum: Double = 0.0
var totalHands: Double = 0.0
var bbSum: Double = 0.0
var bbSessionCount: Int = 0
var winningSessionCount: Int = 0 // sessions.filter { it.value >= 0.0 }.size
var winningSessionCount: Int = 0 // computables.filter { it.value >= 0.0 }.size
var totalBuyin = 0.0
// Compute for each session
var index: Int = 0
sessions.forEach { s ->
computables.forEach { s ->
index++;
val result = s.result!! // ok to crash to see problems
// val result = s.result!! // ok to crash to see problems
sum += result.ratedNet
sum += s.ratedNet
bbSum += s.bbNetResult
bbSessionCount += s.hasBigBlind
winningSessionCount = result.isPositive
totalBuyin += s.buyin
winningSessionCount += s.isPositive
totalBuyin += s.ratedBuyin
totalHands += s.estimatedHands
when (options.evolutionValues) {
@ -212,10 +212,10 @@ class Calculator {
}
var average = 0.0
if (sessions.size > 0) {
average = sum / sessions.size.toDouble()
val winRatio = winningSessionCount.toDouble() / sessions.size.toDouble()
val avgBuyin = totalBuyin / sessions.size
if (computables.size > 0) {
average = sum / computables.size.toDouble()
val winRatio = winningSessionCount.toDouble() / computables.size.toDouble()
val avgBuyin = totalBuyin / computables.size
results.addStats(
setOf(
@ -242,7 +242,7 @@ class Calculator {
ComputedStat(NETRESULT, sum),
ComputedStat(DURATION, duration),
ComputedStat(NUMBER_OF_SETS, sessionSets.size.toDouble()),
ComputedStat(NUMBER_OF_GAMES, sessions.size.toDouble()),
ComputedStat(NUMBER_OF_GAMES, computables.size.toDouble()),
ComputedStat(HOURLY_RATE_BB, bbSum / duration),
ComputedStat(AVERAGE_NET_BB, bbSum / bbSessionCount),
ComputedStat(HANDS_PLAYED, totalHands)
@ -268,12 +268,12 @@ class Calculator {
// Session
var stdSum: Double = 0.0
var stdBBper100HandsSum: Double = 0.0
sessions.forEach { session ->
stdSum += Math.pow(session.result!!.ratedNet - average, 2.0)
computables.forEach { session ->
stdSum += Math.pow(session.ratedNet - average, 2.0)
stdBBper100HandsSum += Math.pow(session.bbPer100Hands - bbPer100Hands, 2.0)
}
val standardDeviation: Double = Math.sqrt(stdSum / sessions.size)
val standardDeviationBBper100Hands: Double = Math.sqrt(stdBBper100HandsSum / sessions.size)
val standardDeviation: Double = Math.sqrt(stdSum / computables.size)
val standardDeviationBBper100Hands: Double = Math.sqrt(stdBBper100HandsSum / computables.size)
// Session Set
var hourlyStdSum: Double = 0.0

@ -1,11 +1,11 @@
package net.pokeranalytics.android.calculus
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.calculus.interfaces.Computable
/**
* A sessionGroup of computable items identified by a name
*/
class SessionGroup(name: String, sessions: List<Session>, stats: List<Stat>? = null) {
class ComputableGroup(name: String, computables: List<Computable>, stats: List<Stat>? = null) {
/**
* The display name of the group
@ -15,7 +15,7 @@ class SessionGroup(name: String, sessions: List<Session>, stats: List<Stat>? = n
/**
* The list of endedSessions to compute
*/
var sessions: List<Session> = sessions
var computables: List<Computable> = computables
/**
* The list of stats to display
@ -25,7 +25,7 @@ class SessionGroup(name: String, sessions: List<Session>, stats: List<Stat>? = n
/**
* A subgroup used to compute stat variation
*/
var comparedSessions: SessionGroup? = null
var comparedComputables: ComputableGroup? = null
/**
* The computed stats of the comparable sessionGroup
@ -34,12 +34,12 @@ class SessionGroup(name: String, sessions: List<Session>, stats: List<Stat>? = n
}
class ComputedResults(group: SessionGroup) {
class ComputedResults(group: ComputableGroup) {
/**
* The session group used to computed the stats
*/
var group: SessionGroup = group
var group: ComputableGroup = group
// The computed stats of the sessionGroup
private var _computedStats: MutableMap<Stat, ComputedStat> = mutableMapOf()

@ -0,0 +1,40 @@
package net.pokeranalytics.android.calculus.bankroll
import io.realm.Realm
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.Transaction
class BankrollCalculator {
companion object {
fun computeReport(setup: BankrollReportSetup) : BankrollReport {
val realm = Realm.getDefaultInstance()
val report = BankrollReport(setup)
val sessionQuery = realm.where(Session::class.java)
if (setup.bankroll != null) {
sessionQuery.equalTo("bankroll.id", setup.bankroll.id)
}
val sessions = sessionQuery.findAll()
val transactionQuery = realm.where(Transaction::class.java)
if (setup.bankroll != null) {
transactionQuery.equalTo("bankroll.id", setup.bankroll.id).findAll()
}
val transactions = transactionQuery.findAll()
val sessionsNet = sessions.sum("result.net")
val transactionsNet = transactions.sum("value")
transactions.forEach {
report.addTransaction(it)
}
return report
}
}
}

@ -0,0 +1,122 @@
package net.pokeranalytics.android.calculus.bankroll
import net.pokeranalytics.android.calculus.interfaces.DatableValue
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.model.realm.Transaction
import java.util.*
import kotlin.collections.HashMap
/**
* A class describing the parameters required to launch a bankroll report
*
*/
class BankrollReportSetup(bankroll: Bankroll?, from: Date? = null, to: Date? = null) {
/**
* The bankroll to compute. If null, the virtual global bankroll
*/
val bankroll = bankroll
/**
* The start of the report
*/
val from = from
/**
* The end of the report
*/
val to = to
}
class TransactionBucket(useRate: Boolean = false) {
var transactions: MutableList<Transaction> = mutableListOf()
private set
var total: Double = 0.0
private set
var useRate: Boolean = useRate
private set
fun addTransaction(transaction: Transaction) {
this.transactions.add(transaction)
var rate = 1.0
if (this.useRate) {
rate = transaction.bankroll?.currency?.rate ?: 1.0
}
val ratedAmount = rate * transaction.amount
this.total += ratedAmount
}
}
class BRGraphPoint {
var value: Double = 0.0
var variation: Double = 0.0
var date: Date? = null
}
class BankrollReport(setup: BankrollReportSetup) {
/**
* The setup used to compute the report
*/
var setup: BankrollReportSetup = setup
/**
* The value of the bankroll
*/
var total: Double = 0.0
private set
/**
* The net result from poker computables
*/
var netResult: Double = 0.0
private set
/**
* The difference between withdrawals and deposits
*/
var netBanked: Double = 0.0
private set
/**
* The risk of ruin
*/
var riskOfRuin: Double = 0.0
private set
var transactions: List<Transaction> = mutableListOf()
private set
var transactionBuckets: HashMap<String, TransactionBucket> = HashMap()
var evolutionPoints: Array<BRGraphPoint> = arrayOf()
var evolutionItems: Array<DatableValue> = arrayOf()
fun addTransaction(transaction: Transaction) {
transaction.type?.let { type ->
var bucket = this.transactionBuckets[type.id]
if (bucket == null) {
val b = TransactionBucket(this.setup.bankroll == null)
this.transactionBuckets[type.id] = b
bucket = b
}
bucket.addTransaction(transaction)
} ?: run {
throw Exception("Transaction has no type")
}
}
}

@ -0,0 +1,17 @@
package net.pokeranalytics.android.calculus.interfaces
import net.pokeranalytics.android.model.realm.SessionSet
interface Computable {
var ratedNet: Double
var bbNetResult: Double
var hasBigBlind: Int
var isPositive: Int
var ratedBuyin: Double
var estimatedHands: Double
var bbPer100Hands: Double
var sessionSet: SessionSet?
}

@ -0,0 +1,11 @@
package net.pokeranalytics.android.calculus.interfaces
import java.util.*
interface Datable {
var date: Date
}
interface DatableValue : Datable {
var value: Double
}

@ -2,4 +2,4 @@ package net.pokeranalytics.android.model.filter
enum class FilterComponent {
}
}

@ -0,0 +1,51 @@
package net.pokeranalytics.android.model.realm
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.Ignore
import io.realm.annotations.LinkingObjects
import net.pokeranalytics.android.calculus.interfaces.Computable
open class ComputableResult : RealmObject(), Computable {
override var ratedNet: Double = 0.0
override var bbNetResult: Double = 0.0
override var hasBigBlind: Int = 0
override var isPositive: Int = 0
override var ratedBuyin: Double = 0.0
override var estimatedHands: Double = 0.0
override var bbPer100Hands: Double = 0.0
override var sessionSet: SessionSet? = null
@LinkingObjects("computableResult")
private val sessions: RealmResults<Session>? = null
@Ignore
val session: Session? = this.sessions?.firstOrNull()
fun updateWith(session: Session) {
val rate = session.bankroll?.currency?.rate ?: 1.0
session.result?.let { result ->
this.ratedNet = result.net * rate
this.isPositive = result.isPositive
this.ratedBuyin = (result.buyin ?: 0.0) * rate
}
this.bbNetResult = session.bbNetResult
this.hasBigBlind = session.hasBigBlind
this.estimatedHands = session.estimatedHands
this.bbPer100Hands = session.bbPer100Hands
this.sessionSet = session.sessionSet
}
}

@ -15,5 +15,24 @@ open class Currency : RealmObject() {
// The rate of the currency with the main currency
var rate: Double? = null
set(value) {
field = value
val rate = value ?: 1.0
// could be async
val cResults = this.realm.where(ComputableResult::class.java).equalTo("session.bankroll.currency", this.id).findAll()
cResults.forEach { computable ->
computable.session?.result?.net?.let {
computable.ratedNet = it * rate
}
computable.session?.result?.buyin?.let {
computable.ratedBuyin = it * rate
}
}
}
}

@ -2,47 +2,52 @@ package net.pokeranalytics.android.model.realm
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.Ignore
import io.realm.annotations.LinkingObjects
import io.realm.annotations.RealmClass
@RealmClass
open class Result : RealmObject() {
// The buyin amount
/**
* The buyin amount
*/
var buyin: Double? = null
set(value) {
field = value
this.computeNet()
}
// the cashed out amount
/**
* The cashed out amount
*/
var cashout: Double? = null
set(value) {
field = value
this.computeNet()
}
// Tips
var tips: Double? = null
// The net result
var netResult: Double? = null
set(value) {
field = value
this.computeNet()
}
/**
* The pre-computed net (readonly)
*/
var net: Double = 0.0
private set
* The net result
*/
var netResult: Double? = null
set(value) {
field = value
this.computeNet()
}
/**
* The pre-computed rated net (readonly)
* The pre-computed net (readonly)
*/
var ratedNet: Double = 0.0
var net: Double = 0.0
private set
/**
* Tips
*/
var tips: Double? = null
// The transactions associated with the Result, impacting the result
var transactions: RealmList<Transaction> = RealmList()
set(value) {
@ -53,23 +58,17 @@ open class Result : RealmObject() {
// The tournament final position, if applicable
var tournamentFinalPosition: Int? = null
/**
* The automatically Realm-updated sessions list
* Should contain only one element
*/
// @LinkingObjects("result")
// private val sessions: RealmResults<Session>? = null
@LinkingObjects("result")
private val sessions: RealmResults<Session>? = null
/**
* The associated Session
*/
// @Ignore
// val session: Session? = this.sessions?.firstOrNull()
@Ignore
val session: Session? = this.sessions?.firstOrNull()
/**
* Returns 1 if the session is positive
*/
var isPositive: Int = 0
@Ignore
val isPositive: Int = if (this.net >= 0.0) 1 else 0
// Computes the Net
private fun computeNet() {
@ -82,11 +81,11 @@ open class Result : RealmObject() {
val cashOut = this.cashout ?: 0.0
this.net = cashOut - buyin + transactionsSum
}
this.ratedNet = this.net * 1.0
this.isPositive = if (this.ratedNet >= 0.0) 1 else 0
// Update ComputableResult
this.session?.updateComputableResult()
}
// private var rate: Double = (this.session?.bankroll?.currency?.rate ?: 1.0)
// @todo tips?
// @todo tips?
}

@ -5,6 +5,7 @@ import io.realm.Realm
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.Ignore
import io.realm.annotations.Index
import io.realm.annotations.PrimaryKey
import io.realm.kotlin.where
import net.pokeranalytics.android.R
@ -39,6 +40,18 @@ import kotlin.collections.ArrayList
open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable, Timed,
TimeFilterable {
// @Ignore
// var rate: Double = 0.0
// get() = this.bankroll?.currency?.rate ?: 0.0
//
// @Ignore
// override var ratedNet: Double = 0.0
// get() = this.result!!.net * this.rate
//
// @Ignore
// override var isPositive: Int = 0
// get() = this.result!!.isPositive
enum class Type {
CASH_GAME,
TOURNAMENT
@ -48,6 +61,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
fun newInstance(realm: Realm, isTournament: Boolean, bankroll: Bankroll? = null): Session {
val session = Session()
session.result = Result()
session.computableResult = ComputableResult()
if (bankroll != null) {
session.bankroll = bankroll
} else {
@ -69,6 +83,11 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
// The result of the main user
var result: Result? = null
/**
* Optimized result for faster stats
*/
var computableResult: ComputableResult? = null
// Timed interface
override var dayOfWeek : Int? = null
@ -84,23 +103,24 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
this.updateTimeParameter(field)
this.computeNetDuration()
this.computeStats()
// nullifies endate when setting the start date after the end date
if (value != null && this.endDate != null && value.after(this.endDate)) {
this.endDate = null
}
this.dateChanged()
this.computeStats()
}
/**
* the end date of the session
*/
@Index
var endDate: Date? = null
set(value) {
field = value
this.computeNetDuration()
this.computeStats()
this.dateChanged()
this.computeStats()
}
/**
@ -175,6 +195,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
set(value) {
this.hasBigBlind = if (value != null) 1 else 0
field = value
this.updateComputableResult()
}
// Tournament
@ -204,6 +225,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
} else if (this.sessionSet != null) {
SessionSetManager.removeFromTimeline(this)
}
this.updateComputableResult()
this.updateRowRepresentation()
}
@ -267,6 +289,15 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
this.computeEstimatedHands()
this.computeBBNetResult()
this.computeBBPer100Hands()
this.updateComputableResult()
}
fun updateComputableResult() {
this.computableResult?.let {
it.updateWith(this)
} ?: run {
throw IllegalStateException("Session should always have a Light Result")
}
}
/**
@ -304,7 +335,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
private set
@Ignore
var buyin: Double = 0.0
var ratedBuyin: Double = 0.0
get() {
this.result?.let { result ->
result.buyin?.let {
@ -481,7 +512,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
}
@Ignore
private var rowRepresentationForCurrentState : List<RowRepresentable> = this.updatedRowRepresentationForCurrentState()
private var rowRepresentationForCurrentState : List<RowRepresentable> = mutableListOf()
private fun updatedRowRepresentationForCurrentState(): List<RowRepresentable> {
val rows = ArrayList<RowRepresentable>()
@ -550,7 +581,6 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
override fun adapterRows(): List<RowRepresentable>? {
return this.rowRepresentationForCurrentState
}
override fun boolForRow(row: RowRepresentable): Boolean {
@ -635,7 +665,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
SessionRow.BUY_IN -> row.editingDescriptors(mapOf(
"bb" to cgBigBlind,
"fee" to this.tournamentEntryFee,
"buyin" to buyin
"ratedBuyin" to ratedBuyin
))
SessionRow.BREAK_TIME -> row.editingDescriptors(mapOf())
SessionRow.CASHED_OUT, SessionRow.PRIZE, SessionRow.NET_RESULT -> row.editingDescriptors(mapOf(

@ -68,7 +68,7 @@ open class SessionSet : RealmObject(), Timed {
val sessions: RealmResults<Session>? = null
@Ignore
val ratedNet: Double = this.sessions?.sumByDouble { it.result!!.ratedNet } ?: 0.0
val ratedNet: Double = this.sessions?.sumByDouble { it.computableResult!!.ratedNet } ?: 0.0
@Ignore
val hourlyRate: Double = this.ratedNet / this.hourlyDuration

@ -10,8 +10,9 @@ import kotlinx.android.synthetic.main.fragment_stats.*
import kotlinx.coroutines.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.*
import net.pokeranalytics.android.calculus.interfaces.Computable
import net.pokeranalytics.android.model.StatRepresentable
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.ui.adapter.DisplayDescriptor
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
@ -97,7 +98,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
// Override
override fun sessionsChanged() {
// this.launchStatComputation()
this.launchStatComputation()
this.statsAdapter.notifyDataSetChanged()
}
@ -132,26 +133,6 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
private fun launchStatComputation() {
// Thread() {
//// var results = listOf<ComputedResults>()
// val s = Date()
// Timber.d(">>> start...")
//
// val results = createSessionGroupsAndStartCompute()
//
// val e = Date()
// val duration = (e.time - s.time) / 1000.0
// Timber.d(">>> ended in ${duration} seconds")
//
//
// val mainHandler = Handler(Looper.getMainLooper())
// val runnable = Runnable {
// showResults(results)
// }
// mainHandler.post(runnable)
//
// }.start()
GlobalScope.launch(coroutineContext) {
var results = listOf<ComputedResults>()
@ -177,35 +158,36 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
private fun createSessionGroupsAndStartCompute() : List<ComputedResults> {
val cgSessions = mutableListOf<Session>()
val tSessions = mutableListOf<Session>()
val cgSessions = mutableListOf<Computable>()
val tSessions = mutableListOf<Computable>()
val s = Date()
val realm = Realm.getDefaultInstance()
val allSessions = realm.where(Session::class.java).isNotNull("endDate").findAll()
Timber.d(">>>>> number of sessions to compute = ${allSessions.size}")
val sessionsList = allSessions.toList()
// val allSessions = realm.where(ComputableResult::class.java).findAll()
val allSessions = realm.where(ComputableResult::class.java).isNotNull("sessions.endDate").findAll()
Timber.d(">>>>> number of computables to compute = ${allSessions.size}")
val e = Date()
val duration = (e.time - s.time) / 1000.0
Timber.d(">>> filtering in ${duration} seconds")
val computableList = realm.copyFromRealm(allSessions)
realm.close()
sessionsList.forEach { session ->
if (session.isCashGame()) {
computableList.forEach { session ->
if (true) { // @todo
cgSessions.add(session)
} else {
tSessions.add(session)
}
}
val e = Date()
val duration = (e.time - s.time) / 1000.0
Timber.d(">>> filtering in ${duration} seconds")
val allStats: List<Stat> = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE, Stat.NUMBER_OF_SETS, Stat.AVERAGE_DURATION, Stat.DURATION)
val allSessionGroup = SessionGroup(stringAll, sessionsList, allStats)
val allSessionGroup = ComputableGroup(getString(R.string.all), computableList, 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(stringCashGame, cgSessions, cgStats)
val cgSessionGroup = ComputableGroup(getString(R.string.cash_game), cgSessions, cgStats)
val tStats: List<Stat> = listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.ROI, Stat.WIN_RATIO, Stat.NUMBER_OF_GAMES, Stat.AVERAGE_BUYIN)
val tSessionGroup = SessionGroup(stringTournament, tSessions, tStats)
val tSessionGroup = ComputableGroup(getString(R.string.tournament), tSessions, tStats)
Timber.d(">>>>> Start computations...")

@ -2,15 +2,15 @@ package net.pokeranalytics.android.ui.fragment.components
import io.realm.Realm
import io.realm.RealmResults
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.ComputableResult
open class SessionObserverFragment : PokerAnalyticsFragment() {
val endedSessions: RealmResults<Session>
val endedSessions: RealmResults<ComputableResult>
init {
val realm = Realm.getDefaultInstance()
this.endedSessions = realm.where(Session::class.java).isNotNull("endDate").findAll()
this.endedSessions = realm.where(ComputableResult::class.java).isNotNull("sessions.endDate").findAll()
this.endedSessions.addChangeListener { _, _ ->
this.sessionsChanged()
}

@ -27,7 +27,7 @@ class ExampleUnitTest : RealmUnitTest() {
// override var estimatedHands: Double = 0.0
// override var bbNetResult: Double = 0.0
// override var bigBlindSessionCount: Int = 0 // 0 or 1
// override var buyin: Double = 0.0
// override var ratedBuyin: Double = 0.0
//
// }
//
@ -35,7 +35,7 @@ class ExampleUnitTest : RealmUnitTest() {
// fun testStats() {
//
// val grades: List<Grade> = listOf(Grade(10.0), Grade(20.0))
// val group = SessionGroup(name = "test", sessions = grades)
// val group = ComputableGroup(name = "test", computables = grades)
//
// val results: ComputedResults = Calculator.compute(group, Calculator.Options())
//

Loading…
Cancel
Save