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

# Conflicts:
#	app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt
feature/top10
Aurelien Hubert 7 years ago
commit 8a4730707d
  1. 5
      app/build.gradle
  2. 218
      app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt
  3. 34
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  4. 66
      app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt
  5. 3
      app/src/main/java/net/pokeranalytics/android/model/StatRepresentable.kt
  6. 42
      app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt
  7. 38
      app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt
  8. 1
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  9. 58
      app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt
  10. 1
      app/src/main/java/net/pokeranalytics/android/ui/activity/DataListActivity.kt
  11. 1
      app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt
  12. 57
      app/src/main/java/net/pokeranalytics/android/ui/activity/GraphActivity.kt
  13. 59
      app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt
  14. 63
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt
  15. 7
      app/src/main/res/layout/activity_graph.xml
  16. 14
      app/src/main/res/layout/fragment_graph.xml

@ -7,6 +7,7 @@ apply plugin: 'io.fabric'
repositories {
maven { url 'https://maven.fabric.io/public' }
maven { url 'https://jitpack.io' }
}
android {
@ -95,6 +96,10 @@ dependencies {
// Logs
implementation 'com.jakewharton.timber:timber:4.7.1'
// MPAndroidChart
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
// Instrumented Tests
androidTestImplementation 'androidx.test:core:1.1.0'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test:rules:1.1.1'

@ -8,6 +8,7 @@ import net.pokeranalytics.android.model.realm.FilterCondition
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow
import net.pokeranalytics.android.util.extensions.startOfDay
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
@ -150,6 +151,223 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
}
}
@Test
fun testTodayFilter() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = Session.testInstance(100.0, false)
val cal = Calendar.getInstance()
cal.time = Date()
cal.add(Calendar.HOUR_OF_DAY, -72)
Session.testInstance(100.0, false, cal.time)
realm.commitTransaction()
Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 2)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(QueryCondition.TODAY))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, this.id)
}
}
@Test
fun testTodayNoonFilter() {
val realm = this.mockRealm
realm.beginTransaction()
val cal = Calendar.getInstance()
cal.time = Date().startOfDay()
val s1 = Session.testInstance(100.0, false, cal.time)
cal.add(Calendar.HOUR_OF_DAY, -72)
Session.testInstance(100.0, false, cal.time)
realm.commitTransaction()
Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 2)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(QueryCondition.TODAY))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, this.id)
}
}
@Test
fun testYesterdayFilter() {
val realm = this.mockRealm
realm.beginTransaction()
val cal = Calendar.getInstance()
cal.time = Date()
cal.add(Calendar.HOUR_OF_DAY, -24)
val s1 = Session.testInstance(100.0, false, cal.time)
Session.testInstance(100.0, false)
cal.add(Calendar.HOUR_OF_DAY, -72)
Session.testInstance(100.0, false, cal.time)
realm.commitTransaction()
Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 3)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(QueryCondition.YESTERDAY))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, this.id)
}
}
@Test
fun testYesterdayNoonFilter() {
val realm = this.mockRealm
realm.beginTransaction()
val cal = Calendar.getInstance()
cal.time = Date()
cal.add(Calendar.HOUR_OF_DAY, -24)
val s1 = Session.testInstance(100.0, false, cal.time.startOfDay())
Session.testInstance(100.0, false)
cal.add(Calendar.HOUR_OF_DAY, -72)
Session.testInstance(100.0, false, cal.time)
realm.commitTransaction()
Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 3)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(QueryCondition.YESTERDAY))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, this.id)
}
}
@Test
fun testTodayAndYesterdayFilter() {
val realm = this.mockRealm
realm.beginTransaction()
val cal = Calendar.getInstance()
cal.time = Date()
cal.add(Calendar.HOUR_OF_DAY, -24)
val s1 = Session.testInstance(100.0, false, cal.time)
val s2 = Session.testInstance(100.0, false)
cal.add(Calendar.HOUR_OF_DAY, -72)
Session.testInstance(100.0, false, cal.time)
realm.commitTransaction()
Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 3)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(QueryCondition.TODAY_AND_YESTERDAY))
Assert.assertEquals(2, sessions.size)
Assert.assertTrue(sessions.containsAll(arrayListOf(s1,s2)))
}
@Test
fun testThisYear() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = Session.testInstance(100.0, false)
val cal = Calendar.getInstance()
cal.time = Date()
cal.add(Calendar.HOUR_OF_DAY, -24)
val s2 = Session.testInstance(100.0, false, cal.time)
cal.add(Calendar.HOUR_OF_DAY, -72)
val s3 = Session.testInstance(100.0, false, cal.time)
cal.add(Calendar.YEAR, -4)
Session.testInstance(100.0, false, cal.time)
cal.add(Calendar.YEAR, -1)
Session.testInstance(100.0, false, cal.time)
realm.commitTransaction()
Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 5)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(QueryCondition.THIS_YEAR))
Assert.assertEquals(3, sessions.size)
Assert.assertTrue(sessions.containsAll(arrayListOf(s1,s2, s3)))
}
@Test
fun testThisMonth() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = Session.testInstance(100.0, false)
val cal = Calendar.getInstance()
cal.time = Date()
cal.set(Calendar.DAY_OF_MONTH, 1)
cal.time = cal.time.startOfDay()
val s2 = Session.testInstance(100.0, false, cal.time)
cal.add(Calendar.HOUR_OF_DAY, -1)
Session.testInstance(100.0, false, cal.time)
cal.add(Calendar.MONTH, -1)
Session.testInstance(100.0, false, cal.time)
cal.add(Calendar.YEAR, -1)
Session.testInstance(100.0, false, cal.time)
realm.commitTransaction()
Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 5)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(QueryCondition.THIS_MONTH))
Assert.assertEquals(2, sessions.size)
Assert.assertTrue(sessions.containsAll(arrayListOf(s1,s2)))
}
@Test
fun testThisWeek() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = Session.testInstance(100.0, false)
val cal = Calendar.getInstance()
cal.time = Date()
cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1)
cal.time = cal.time.startOfDay()
cal.add(Calendar.HOUR_OF_DAY, -1)
Session.testInstance(100.0, false, cal.time)
realm.commitTransaction()
Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 2)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(QueryCondition.THIS_WEEK))
Assert.assertEquals(1, sessions.size)
Assert.assertTrue(sessions.containsAll(arrayListOf(s1)))
}
@Test
fun testStartedFomDateFilter() {

@ -144,21 +144,21 @@ class Calculator {
tBuyinSum += s.ratedBuyin
tHands += s.estimatedHands
results.addEvolutionValue(tSum, NETRESULT)
results.addEvolutionValue(tSum / index, AVERAGE)
results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES)
results.addEvolutionValue(tBBSum / tBBSessionCount, AVERAGE_NET_BB)
results.addEvolutionValue((tWinningSessionCount / index).toDouble(), WIN_RATIO)
results.addEvolutionValue(tBuyinSum / index, AVERAGE_BUYIN)
results.addEvolutionValue(tSum, NETRESULT, s)
results.addEvolutionValue(tSum / index, AVERAGE, s)
results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES, s)
results.addEvolutionValue(tBBSum / tBBSessionCount, AVERAGE_NET_BB, s)
results.addEvolutionValue((tWinningSessionCount / index).toDouble(), WIN_RATIO, s)
results.addEvolutionValue(tBuyinSum / index, AVERAGE_BUYIN, s)
val netBB100 = Stat.netBBPer100Hands(tBBSum, tHands)
if (netBB100 != null) {
results.addEvolutionValue(netBB100, NET_BB_PER_100_HANDS)
results.addEvolutionValue(netBB100, NET_BB_PER_100_HANDS, s)
}
val roi = Stat.returnOnInvestment(tSum, tBuyinSum)
if (roi != null) {
results.addEvolutionValue(roi, ROI)
results.addEvolutionValue(roi, ROI, s)
}
}
@ -201,19 +201,19 @@ class Calculator {
tHourlyRate = gSum / tHourlyDuration
tHourlyRateBB = gBBSum / tHourlyDuration
results.addEvolutionValue(tSum, tHourlyDuration, NETRESULT)
results.addEvolutionValue(tSum / tHourlyDuration, tHourlyDuration, HOURLY_RATE)
results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE)
results.addEvolutionValue(tIndex.toDouble(), tHourlyDuration, NUMBER_OF_SETS)
results.addEvolutionValue(sessionSet.netDuration.toDouble(), tHourlyDuration, DURATION)
results.addEvolutionValue(tHourlyDuration / tIndex, tHourlyDuration, AVERAGE_DURATION)
results.addEvolutionValue(tHourlyRateBB, tHourlyDuration, HOURLY_RATE_BB)
results.addEvolutionValue(tSum, tHourlyDuration, NETRESULT, sessionSet)
results.addEvolutionValue(tSum / tHourlyDuration, tHourlyDuration, HOURLY_RATE, sessionSet)
results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, sessionSet)
results.addEvolutionValue(tIndex.toDouble(), tHourlyDuration, NUMBER_OF_SETS, sessionSet)
results.addEvolutionValue(sessionSet.netDuration.toDouble(), tHourlyDuration, DURATION, sessionSet)
results.addEvolutionValue(tHourlyDuration / tIndex, tHourlyDuration, AVERAGE_DURATION, sessionSet)
results.addEvolutionValue(tHourlyRateBB, tHourlyDuration, HOURLY_RATE_BB, sessionSet)
val netBB100 = Stat.netBBPer100Hands(gBBSum, gTotalHands)
if (netBB100 != null) {
results.addEvolutionValue(netBB100, tHourlyDuration, NET_BB_PER_100_HANDS)
results.addEvolutionValue(netBB100, tHourlyDuration, NET_BB_PER_100_HANDS, sessionSet)
} else { //@todo maybe not
results.addEvolutionValue(0.0, tHourlyDuration, NET_BB_PER_100_HANDS)
results.addEvolutionValue(0.0, tHourlyDuration, NET_BB_PER_100_HANDS, sessionSet)
}
}
}

@ -1,5 +1,7 @@
package net.pokeranalytics.android.calculus
import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.data.Entry
import io.realm.RealmResults
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.SessionSet
@ -58,20 +60,23 @@ class ComputedResults(group: ComputableGroup) {
return this._computedStats.values
}
fun addEvolutionValue(value: Double, stat: Stat) {
this._addEvolutionValue(Point(value), stat = stat)
/**
* Adds a value to the evolution values
*/
fun addEvolutionValue(value: Double, stat: Stat, data: Any) {
this._addEvolutionValue(Point(value, data), stat = stat)
}
fun addEvolutionValue(value: Double, duration: Double, stat: Stat) {
this._addEvolutionValue(Point(value, y = duration), stat = stat)
fun addEvolutionValue(value: Double, duration: Double, stat: Stat, data: Any) {
this._addEvolutionValue(Point(value, y = duration, data = data), stat = stat)
}
private fun _addEvolutionValue(point: Point, stat: Stat) {
var evolutionValues = this._evolutionValues[stat]
val evolutionValues = this._evolutionValues[stat]
if (evolutionValues != null) {
evolutionValues.add(point)
} else {
var values: MutableList<Point> = mutableListOf(point)
val values: MutableList<Point> = mutableListOf(point)
this._evolutionValues[stat] = values
}
}
@ -88,7 +93,7 @@ class ComputedResults(group: ComputableGroup) {
fun computeStatVariations(resultsToCompare: ComputedResults) {
this._computedStats.keys.forEach { stat ->
var computedStat = this.computedStat(stat)
val computedStat = this.computedStat(stat)
val comparedStat = resultsToCompare.computedStat(stat)
if (computedStat != null && comparedStat != null) {
computedStat.variation = (computedStat.value - comparedStat.value) / comparedStat.value
@ -116,12 +121,51 @@ class ComputedResults(group: ComputableGroup) {
return this._computedStats.size
}
// MPAndroidChart
fun defaultStatEntries(stat: Stat) : Array<out Entry> {
return when (stat) {
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES -> this.barEntries(stat)
else -> this.singleLineEntries(stat)
}
}
fun singleLineEntries(stat: Stat) : Array<Entry> {
var entries = mutableListOf<Entry>()
this._evolutionValues[stat]?.let { points ->
points.forEachIndexed { index, p ->
entries.add(Entry(index.toFloat(), p.y.toFloat(), p.data))
}
}
return entries.toTypedArray()
}
fun durationEntries(stat: Stat) : Array<Entry> {
var entries = mutableListOf<Entry>()
this._evolutionValues[stat]?.let { points ->
points.forEach { p ->
entries.add(Entry(p.x.toFloat(), p.y.toFloat(), p.data))
}
}
return entries.toTypedArray()
}
fun barEntries(stat: Stat) : Array<BarEntry> {
var entries = arrayOf<BarEntry>()
this._evolutionValues[stat]?.let { points ->
points.forEach { p ->
entries[0] = BarEntry(p.x.toFloat(), p.y.toFloat(), p.data)
}
}
return entries
}
}
class Point(x: Double, y: Double) {
val x: Double = x
val y: Double = y
class Point(val x: Double, val y: Double, val data: Any) {
constructor(x: Double) : this(x, 1.0)
constructor(y: Double, data: Any) : this(0.0, y, data)
}

@ -6,10 +6,11 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
class StatRepresentable(stat: Stat, computedStat: ComputedStat?) : RowRepresentable {
class StatRepresentable(stat: Stat, computedStat: ComputedStat?, groupName: String = "") : RowRepresentable {
var stat: Stat = stat
var computedStat: ComputedStat? = computedStat
var groupName: String = groupName
override val viewType: Int
get() = RowViewType.STAT.ordinal

@ -6,6 +6,9 @@ import net.pokeranalytics.android.exceptions.PokerAnalyticsException
import net.pokeranalytics.android.model.realm.FilterCondition
import net.pokeranalytics.android.model.realm.FilterElementBlind
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.util.extensions.endOfDay
import net.pokeranalytics.android.util.extensions.startOfDay
import java.time.*
import java.util.*
@ -240,8 +243,43 @@ enum class QueryCondition(var operator: Operator? = null) {
}
query.`in`(fieldName, arrayOf(Calendar.SATURDAY, Calendar.SUNDAY))
}
TODAY, YESTERDAY, TODAY_AND_YESTERDAY, THIS_WEEK, THIS_MONTH, THIS_YEAR -> {
realmQuery
TODAY -> {
val startDate = Date()
realmQuery.between(fieldName, startDate.startOfDay(), startDate.endOfDay())
}
TODAY_AND_YESTERDAY-> {
val startDate = Date()
val calendar = Calendar.getInstance()
calendar.time = startDate
calendar.add(Calendar.HOUR_OF_DAY, -24)
realmQuery.between(fieldName, calendar.time.startOfDay(), startDate.endOfDay())
}
YESTERDAY -> {
val calendar = Calendar.getInstance()
calendar.time = Date()
calendar.add(Calendar.HOUR_OF_DAY, -24)
realmQuery.between(fieldName, calendar.time.startOfDay(), calendar.time.endOfDay())
}
THIS_WEEK -> {
val startDate = Date()
val calendar = Calendar.getInstance()
calendar.time = startDate
calendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, Calendar.SUNDAY)
realmQuery.between(fieldName, calendar.time.startOfDay(), startDate.endOfDay())
}
THIS_MONTH -> {
val startDate = Date()
val calendar = Calendar.getInstance()
calendar.time = startDate
calendar.set(Calendar.DAY_OF_MONTH, 1)
realmQuery.between(fieldName, calendar.time.startOfDay(), startDate.endOfDay())
}
THIS_YEAR -> {
val startDate = Date()
val calendar = Calendar.getInstance()
calendar.time = startDate
calendar.set(Calendar.DAY_OF_YEAR, 1)
realmQuery.between(fieldName, calendar.time.startOfDay(), startDate.endOfDay())
}
else -> {
throw PokerAnalyticsException.QueryTypeUnhandled

@ -1,11 +1,13 @@
package net.pokeranalytics.android.model.realm
import android.os.Parcel
import android.os.Parcelable
import io.realm.RealmObject
import net.pokeranalytics.android.calculus.interfaces.Computable
import net.pokeranalytics.android.model.filter.Filterable
import net.pokeranalytics.android.model.filter.QueryCondition
open class ComputableResult : RealmObject(), Computable, Filterable {
open class ComputableResult() : RealmObject(), Computable, Filterable, Parcelable {
override var ratedNet: Double = 0.0
@ -25,6 +27,16 @@ open class ComputableResult : RealmObject(), Computable, Filterable {
var session: Session? = null
constructor(parcel: Parcel) : this() {
ratedNet = parcel.readDouble()
bbNet = parcel.readDouble()
hasBigBlind = parcel.readInt()
isPositive = parcel.readInt()
ratedBuyin = parcel.readDouble()
estimatedHands = parcel.readDouble()
bbPer100Hands = parcel.readDouble()
}
fun updateWith(session: Session) {
this.sessionSet = session.sessionSet
@ -54,7 +66,28 @@ open class ComputableResult : RealmObject(), Computable, Filterable {
BB_PER100HANDS("bbPer100Hands")
}
companion object : Filterable {
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeDouble(ratedNet)
parcel.writeDouble(bbNet)
parcel.writeInt(hasBigBlind)
parcel.writeInt(isPositive)
parcel.writeDouble(ratedBuyin)
parcel.writeDouble(estimatedHands)
parcel.writeDouble(bbPer100Hands)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<ComputableResult>, Filterable {
override fun createFromParcel(parcel: Parcel): ComputableResult {
return ComputableResult(parcel)
}
override fun newArray(size: Int): Array<ComputableResult?> {
return arrayOfNulls(size)
}
fun fieldNameForQueryType(queryCondition: QueryCondition): String? {
return "session." + Session.fieldNameForQueryType(queryCondition)
@ -62,5 +95,4 @@ open class ComputableResult : RealmObject(), Computable, Filterable {
}
}

@ -90,6 +90,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
DAY_OF_WEEK, WEEK_END, WEEK_DAY -> "dayOfWeek"
MONTH -> "month"
YEAR -> "year"
TODAY, YESTERDAY, TODAY_AND_YESTERDAY, THIS_YEAR, THIS_MONTH, THIS_WEEK -> "startDate"
else -> null
}
}

@ -1,5 +1,7 @@
package net.pokeranalytics.android.model.realm
import android.os.Parcel
import android.os.Parcelable
import io.realm.Realm
import io.realm.RealmObject
import io.realm.RealmResults
@ -11,7 +13,7 @@ import net.pokeranalytics.android.model.interfaces.Timed
import java.util.*
open class SessionSet : RealmObject(), Timed, Filterable {
open class SessionSet() : RealmObject(), Timed, Filterable, Parcelable {
var startDate: Date = Date()
set(value) {
@ -49,19 +51,6 @@ open class SessionSet : RealmObject(), Timed, Filterable {
*/
override var netDuration: Long = 0L
companion object : Filterable {
fun newInstance(realm: Realm) : SessionSet {
val sessionSet: SessionSet = realm.createObject(SessionSet::class.java)
return realm.copyToRealm(sessionSet)
}
fun fieldNameForQueryType(queryCondition: QueryCondition): String? {
return "sessions." + Session.fieldNameForQueryType(queryCondition)
}
}
fun computeStats() {
this.ratedNet = this.sessions?.sumByDouble { it.computableResult?.ratedNet ?: 0.0 } ?: 0.0
this.estimatedHands = this.sessions?.sumByDouble { it.estimatedHands } ?: 0.0
@ -83,6 +72,13 @@ open class SessionSet : RealmObject(), Timed, Filterable {
var bbNet: Double = 0.0
constructor(parcel: Parcel) : this() {
netDuration = parcel.readLong()
ratedNet = parcel.readDouble()
estimatedHands = parcel.readDouble()
bbNet = parcel.readDouble()
}
enum class Field(val identifier: String) {
RATED_NET("ratedNet"),
HOURLY_RATE("hourlyRate"),
@ -91,5 +87,39 @@ open class SessionSet : RealmObject(), Timed, Filterable {
NET_DURATION("netDuration")
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeLong(netDuration)
parcel.writeDouble(ratedNet)
parcel.writeDouble(estimatedHands)
parcel.writeDouble(bbNet)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<SessionSet>, Filterable {
override fun createFromParcel(parcel: Parcel): SessionSet {
return SessionSet(parcel)
}
override fun newArray(size: Int): Array<SessionSet?> {
return arrayOfNulls(size)
}
// Filterable
fun newInstance(realm: Realm) : SessionSet {
val sessionSet: SessionSet = realm.createObject(SessionSet::class.java)
return realm.copyToRealm(sessionSet)
}
fun fieldNameForQueryType(queryCondition: QueryCondition): String? {
return "sessions." + Session.fieldNameForQueryType(queryCondition)
}
}
}

@ -9,6 +9,7 @@ import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.fragment.DataListFragment
class DataListActivity : PokerAnalyticsActivity() {
enum class IntentKey(val keyName: String) {
DATA_TYPE("DATA_TYPE"),
ITEM_DELETED("ITEM_DELETED")

@ -72,4 +72,5 @@ class EditableDataActivity : PokerAnalyticsActivity() {
fragmentTransaction.commit()
fragment.setData(dataType, primaryKey)
}
}

@ -0,0 +1,57 @@
package net.pokeranalytics.android.ui.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.github.mikephil.charting.data.Entry
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.fragment.GraphFragment
class GraphActivity : PokerAnalyticsActivity() {
private enum class IntentKey(val keyName: String) {
STAT("STAT"),
ENTRIES("ENTRIES"),
}
companion object {
/**
* Default constructor
*/
fun newInstance(context: Context, stat: Stat, entries: Array<out Entry>) {
val intent = Intent(context, GraphActivity::class.java)
intent.putExtra(IntentKey.STAT.keyName, stat.name)
intent.putExtra(IntentKey.ENTRIES.keyName, entries)
context.startActivity(intent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_editable_data)
initUI()
}
/**
* Init UI
*/
private fun initUI() {
val stat = Stat.valueOf(intent.getStringExtra(IntentKey.STAT.keyName))
val entries = intent.getParcelableArrayExtra(IntentKey.ENTRIES.keyName)
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
val fragment = GraphFragment()
fragmentTransaction.add(R.id.container, fragment)
fragmentTransaction.commit()
fragment.setData(stat, entries)
}
}

@ -0,0 +1,59 @@
package net.pokeranalytics.android.ui.fragment
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import kotlinx.android.synthetic.main.fragment_graph.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
interface GraphDataSource {
}
class GraphFragment : PokerAnalyticsFragment() {
lateinit var dataSource: GraphDataSource
lateinit var entries: Array<Parcelable>
lateinit var stat: Stat
companion object {
}
fun setData(stat: Stat, entries: Array<Parcelable>) {
this.stat = stat
this.entries = entries
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_graph, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initUI()
}
private fun initUI() {
(this.entries.toList() as MutableList<Entry>).let { entries ->
val dataSet = LineDataSet(entries, stat.name)
val lineData = LineData(listOf(dataSet))
this.chart.data = lineData
}
}
}

@ -14,8 +14,10 @@ import net.pokeranalytics.android.model.StatRepresentable
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet
import net.pokeranalytics.android.ui.activity.GraphActivity
import net.pokeranalytics.android.ui.adapter.DisplayDescriptor
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.SessionObserverFragment
import net.pokeranalytics.android.ui.view.RowRepresentable
@ -25,7 +27,8 @@ import timber.log.Timber
import java.util.*
import kotlin.coroutines.CoroutineContext
class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSource, CoroutineScope {
class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSource, CoroutineScope,
RowRepresentableDelegate {
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main
@ -36,6 +39,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
private var stringTournament = ""
private lateinit var statsAdapter: RowRepresentableAdapter
private var computedResults : List<ComputedResults>? = null
companion object {
@ -114,7 +118,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
this.stringCashGame = getString(R.string.cash_game)
this.stringTournament = getString(R.string.tournament)
this.statsAdapter = RowRepresentableAdapter(this)
this.statsAdapter = RowRepresentableAdapter(this, this)
}
/**
@ -131,7 +135,6 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
}
}
private fun launchStatComputation() {
GlobalScope.launch(coroutineContext) {
@ -143,6 +146,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
val realm = Realm.getDefaultInstance()
results = createSessionGroupsAndStartCompute(realm)
computedResults = results
realm.close()
val e = Date()
@ -202,11 +206,62 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
results.forEach { result ->
rows.add(CustomizableRowRepresentable(title = result.group.name))
result.group.stats?.forEach { stat ->
rows.add(StatRepresentable(stat, result.computedStat(stat)))
rows.add(StatRepresentable(stat, result.computedStat(stat), result.group.name))
}
}
return rows
}
// RowRepresentableDelegate
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
return
if (row is StatRepresentable) {
// filter groups
val groupResults = this.computedResults?.filter {
it.group.name == row.groupName
}
groupResults?.firstOrNull()?.let {
this.launchStatComputationWithEvolution(row.stat, it.group)
}
}
}
private fun launchStatComputationWithEvolution(stat: Stat, computableGroup: ComputableGroup) {
GlobalScope.launch(coroutineContext) {
var results = listOf<ComputedResults>()
val test = GlobalScope.async {
val s = Date()
Timber.d(">>> start...")
val realm = Realm.getDefaultInstance()
val options = Calculator.Options()
options.evolutionValues = Calculator.Options.EvolutionValues.STANDARD
results = Calculator.computeGroups(listOf(computableGroup), options)
realm.close()
val e = Date()
val duration = (e.time - s.time) / 1000.0
Timber.d(">>> ended in ${duration} seconds")
}
test.await()
if (!isDetached) {
results.firstOrNull()?.defaultStatEntries(stat)?.let { entries ->
GraphActivity.newInstance(requireContext(), stat, entries)
}
}
}
}
}

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Loading…
Cancel
Save