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

feature/top10
Laurent 7 years ago
commit 71d2b9c0ec
  1. 46
      app/src/androidTest/java/net/pokeranalytics/android/unitTests/BankrollInstrumentedUnitTest.kt
  2. 39
      app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/BlindFilterInstrumentedTest.kt
  3. 40
      app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt
  4. 20
      app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/SessionFilterInstrumentedUnitTest.kt
  5. 5
      app/src/main/AndroidManifest.xml
  6. 3
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  7. 8
      app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt
  8. 83
      app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt
  9. 4
      app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt
  10. 12
      app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt
  11. 12
      app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt
  12. 10
      app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt
  13. 37
      app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt
  14. 8
      app/src/main/java/net/pokeranalytics/android/model/realm/FilterElementBlind.kt
  15. 71
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  16. 7
      app/src/main/java/net/pokeranalytics/android/model/utils/Seed.kt
  17. 33
      app/src/main/java/net/pokeranalytics/android/ui/activity/ComparisonChartActivity.kt
  18. 8
      app/src/main/java/net/pokeranalytics/android/ui/activity/GraphActivity.kt
  19. 80
      app/src/main/java/net/pokeranalytics/android/ui/adapter/ComparisonChartPagerAdapter.kt
  20. 8
      app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDataFragment.kt
  21. 100
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ComparisonChartFragment.kt
  22. 17
      app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt
  23. 6
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt
  24. 5
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt
  25. 28
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt
  26. 7
      app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt
  27. 2
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterCategoryRow.kt
  28. 19
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt
  29. 33
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt
  30. 64
      app/src/main/java/net/pokeranalytics/android/util/CurrencyUtils.kt
  31. 92
      app/src/main/java/net/pokeranalytics/android/util/Preferences.kt
  32. 11
      app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt
  33. 15
      app/src/main/res/layout/activity_comparison_chart.xml
  34. 26
      app/src/main/res/layout/activity_graph.xml
  35. 57
      app/src/main/res/layout/fragment_comparison_chart.xml
  36. 11
      app/src/main/res/layout/fragment_evograph.xml
  37. 1
      app/src/main/res/values/strings.xml
  38. 9
      app/src/main/res/values/styles.xml

@ -28,53 +28,7 @@ class BankrollInstrumentedUnitTest : RealmInstrumentedUnitTest() {
@Test
fun testSessionStats() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = newSessionInstance(realm)
val s2 = newSessionInstance(realm)
val br1 = realm.createObject(Bankroll::class.java, "1")
val br2 = realm.createObject(Bankroll::class.java, "2")
val c1 = realm.createObject(Currency::class.java, "1")
val c2 = realm.createObject(Currency::class.java, "2")
c1.rate = 0.1
c2.rate = 2.0
br1.currency = c1
br2.currency = c2
s1.bankroll = br1
s2.bankroll = br2
s1.result?.netResult = 100.0
s2.result?.netResult = 200.0
realm.commitTransaction()
val computableResults = realm.where(ComputableResult::class.java).findAll()
val sets = realm.where(SessionSet::class.java).findAll()
val stats: List<Stat> = listOf(Stat.NETRESULT, Stat.AVERAGE)
val group = ComputableGroup("test", computableResults, sets, stats)
val options = Calculator.Options()
val results: ComputedResults = Calculator.compute(group, options)
val delta = 0.01
val sum = results.computedStat(Stat.NETRESULT)
if (sum != null) {
Assert.assertEquals(410.0, sum.value, delta)
} else {
Assert.fail("No Net result stat")
}
val average = results.computedStat(Stat.AVERAGE)
if (average != null) {
Assert.assertEquals(205.0, average.value, delta)
} else {
Assert.fail("No AVERAGE stat")
}
}

@ -21,7 +21,7 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() {
realm.beginTransaction()
val currency = realm.createObject(net.pokeranalytics.android.model.realm.Currency::class.java, "1")
currency.code = "AUD"
currency.code = "USD"
val b1 = realm.createObject(Bankroll::class.java, "1")
val b2 = realm.createObject(Bankroll::class.java, "2")
@ -42,9 +42,9 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() {
realm.commitTransaction()
val filter = QueryCondition.BLINDS
val blind = FilterElementRow.Blind(0.5, 1.0, null)
blind.filterSectionRow = FilterSectionRow.BLINDS
val filter = QueryCondition.BLIND
val blind = FilterElementRow.Blind(s1.blinds!!, true)
blind.filterSectionRow = FilterSectionRow.BLIND
val filterElement = FilterCondition(filterElementRows = arrayListOf(blind))
filter.updateValueMap(filterElement)
@ -86,12 +86,14 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() {
realm.commitTransaction()
val filter = QueryCondition.BLINDS
val blind = FilterElementRow.Blind(null, 1.0, null)
blind.filterSectionRow = FilterSectionRow.BLINDS
val filter = QueryCondition.BLIND
val blind1 = FilterElementRow.Blind(s1.blinds!!, true)
val blind2 = FilterElementRow.Blind(s2.blinds!!, true)
blind1.filterSectionRow = FilterSectionRow.BLIND
blind2.filterSectionRow = FilterSectionRow.BLIND
val filterElement = FilterCondition(filterElementRows = arrayListOf(blind))
filter.updateValueMap(filterElement)
val filterElements = FilterCondition(filterElementRows = arrayListOf(blind1, blind2))
filter.updateValueMap(filterElements)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filter))
@ -108,13 +110,14 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() {
realm.beginTransaction()
val currency = realm.createObject(net.pokeranalytics.android.model.realm.Currency::class.java, "1")
currency.code = "AUD"
currency.code = "USD"
val b1 = realm.createObject(Bankroll::class.java, "1")
val b2 = realm.createObject(Bankroll::class.java, "2")
b2.currency = currency
val s1 = Session.testInstance(100.0, false, Date(), 1, b1)
s1.cgBigBlind = 1.0
s1.cgSmallBlind = 0.5
@ -129,9 +132,9 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() {
realm.commitTransaction()
val filter = QueryCondition.BLINDS
val blind = FilterElementRow.Blind(1.0, 2.0, "AUD")
blind.filterSectionRow = FilterSectionRow.BLINDS
val filter = QueryCondition.BLIND
val blind = FilterElementRow.Blind(s3.blinds!!, false)
blind.filterSectionRow = FilterSectionRow.BLIND
val filterElement = FilterCondition(filterElementRows = arrayListOf(blind))
filter.updateValueMap(filterElement)
@ -172,12 +175,12 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() {
realm.commitTransaction()
val filter = QueryCondition.BLINDS
val blind1 = FilterElementRow.Blind(1.0, 2.0, null)
blind1.filterSectionRow = FilterSectionRow.BLINDS
val filter = QueryCondition.BLIND
val blind1 = FilterElementRow.Blind(s1.blinds!!, false)
blind1.filterSectionRow = FilterSectionRow.BLIND
val blind2 = FilterElementRow.Blind(0.5, 1.0, null)
blind2.filterSectionRow = FilterSectionRow.BLINDS
val blind2 = FilterElementRow.Blind(s2.blinds!!, false)
blind2.filterSectionRow = FilterSectionRow.BLIND
val filterElement = FilterCondition(filterElementRows = arrayListOf(blind1, blind2))
filter.updateValueMap(filterElement)

@ -35,14 +35,14 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
val filterElementRow = FilterElementRow.Day(cal.get(Calendar.DAY_OF_WEEK))
filterElementRow.filterSectionRow = FilterSectionRow.DYNAMIC_DATE
val filterElement = FilterCondition(filterElementRow)
val filterElement = FilterCondition(arrayListOf(filterElementRow))
filter.updateValueMap(filterElement)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filter))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, (this as Session).id)
Assert.assertEquals(s1.id, (this).id)
}
}
@ -64,14 +64,14 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
val filterElementRow = FilterElementRow.Month(cal.get(Calendar.MONTH))
filterElementRow.filterSectionRow = FilterSectionRow.DYNAMIC_DATE
val filterElement = FilterCondition(filterElementRow)
val filterElement = FilterCondition(arrayListOf(filterElementRow))
filter.updateValueMap(filterElement)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filter))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, (this as Session).id)
Assert.assertEquals(s1.id, (this).id)
}
}
@ -92,14 +92,14 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
cal.time = s1.startDate
val filterElementRow = FilterElementRow.Year(cal.get(Calendar.YEAR))
filterElementRow.filterSectionRow = FilterSectionRow.DYNAMIC_DATE
val filterElement = FilterCondition(filterElementRow)
val filterElement = FilterCondition(arrayListOf(filterElementRow))
filter.updateValueMap(filterElement)
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filter))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, (this as Session).id)
Assert.assertEquals(s1.id, (this).id)
}
}
@ -122,7 +122,7 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, (this as Session).id)
Assert.assertEquals(s1.id, (this).id)
}
}
@ -147,7 +147,7 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, (this as Session).id)
Assert.assertEquals(s1.id, (this).id)
}
}
@ -384,15 +384,15 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
realm.commitTransaction()
val filter = QueryCondition.STARTED_FROM_DATE
val filterElementRow = FilterElementRow.From(s2.startDate!!)
val filterElementRow = FilterElementRow.From.apply { dateValue = s2.startDate!!}
filterElementRow.filterSectionRow = FilterSectionRow.FIXED_DATE
filter.updateValueMap(FilterCondition(filterElementRow))
filter.updateValueMap(FilterCondition(arrayListOf(filterElementRow)))
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filter))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s2.id, (this as Session).id)
Assert.assertEquals(s2.id, (this).id)
}
}
@ -412,15 +412,15 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
realm.commitTransaction()
val filter = QueryCondition.STARTED_TO_DATE
val filterElementRow = FilterElementRow.From(s1.startDate!!)
val filterElementRow = FilterElementRow.From.apply { dateValue = s1.startDate!! }
filterElementRow.filterSectionRow = FilterSectionRow.FIXED_DATE
filter.updateValueMap(FilterCondition(filterElementRow))
filter.updateValueMap(FilterCondition(arrayListOf(filterElementRow)))
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filter))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, (this as Session).id)
Assert.assertEquals(s1.id, (this).id)
}
}
@ -441,15 +441,15 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
realm.commitTransaction()
val filter = QueryCondition.ENDED_FROM_DATE
val filterElementRow = FilterElementRow.From(s2.endDate())
val filterElementRow = FilterElementRow.From.apply { dateValue = s2.endDate() }
filterElementRow.filterSectionRow = FilterSectionRow.FIXED_DATE
filter.updateValueMap(FilterCondition(filterElementRow))
filter.updateValueMap(FilterCondition(arrayListOf(filterElementRow)))
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filter))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s2.id, (this as Session).id)
Assert.assertEquals(s2.id, (this).id)
}
}
@ -470,15 +470,15 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
val filter = QueryCondition.ENDED_TO_DATE
val filterElementRow = FilterElementRow.From(s1.endDate())
val filterElementRow = FilterElementRow.From.apply { dateValue = s1.endDate() }
filterElementRow.filterSectionRow = FilterSectionRow.FIXED_DATE
filter.updateValueMap(FilterCondition(filterElementRow))
filter.updateValueMap(FilterCondition(arrayListOf(filterElementRow)))
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filter))
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(s1.id, (this as Session).id)
Assert.assertEquals(s1.id, (this).id)
}
}
}

@ -30,7 +30,7 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(Session.Type.CASH_GAME.ordinal, (this as Session).type)
Assert.assertEquals(Session.Type.CASH_GAME.ordinal, (this).type)
}
}
@ -48,7 +48,7 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
Assert.assertEquals(1, sessions.size)
sessions[0]?.run {
Assert.assertEquals(Session.Type.TOURNAMENT.ordinal, (this as Session).type)
Assert.assertEquals(Session.Type.TOURNAMENT.ordinal, (this).type)
}
}
@ -480,9 +480,9 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
realm.commitTransaction()
val filter = QueryCondition.MORE_THAN_NET_RESULT
val filterElementRow = FilterElementRow.ResultMoreThan(204.0)
val filterElementRow = FilterElementRow.ResultMoreThan.apply { this.amount = 204.0 }
filterElementRow.filterSectionRow = FilterSectionRow.VALUE
filter.updateValueMap(FilterCondition(filterElementRow))
filter.updateValueMap(FilterCondition(arrayListOf(filterElementRow)))
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filter))
@ -505,9 +505,9 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
realm.commitTransaction()
val filter = QueryCondition.LESS_THAN_NET_RESULT
val filterElementRow = FilterElementRow.ResultLessThan(540.0)
val filterElementRow = FilterElementRow.ResultMoreThan.apply { this.amount = 540.0 }
filterElementRow.filterSectionRow = FilterSectionRow.VALUE
filter.updateValueMap(FilterCondition(filterElementRow))
filter.updateValueMap(FilterCondition(arrayListOf(filterElementRow)))
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filter))
@ -530,14 +530,14 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
realm.commitTransaction()
val filterMore = QueryCondition.MORE_THAN_NET_RESULT
val filterElementRow = FilterElementRow.ResultMoreThan(200.0)
val filterElementRow = FilterElementRow.ResultMoreThan.apply { this.amount = 200.0 }
filterElementRow.filterSectionRow = FilterSectionRow.VALUE
filterMore.updateValueMap(FilterCondition(filterElementRow))
filterMore.updateValueMap(FilterCondition(arrayListOf(filterElementRow)))
val filterLess = QueryCondition.LESS_THAN_NET_RESULT
val filterElementRow2 = FilterElementRow.ResultLessThan(400.0)
val filterElementRow2 = FilterElementRow.ResultMoreThan.apply { this.amount = 400.0 }
filterElementRow2.filterSectionRow = FilterSectionRow.VALUE
filterLess.updateValueMap(FilterCondition(filterElementRow2))
filterLess.updateValueMap(FilterCondition(arrayListOf(filterElementRow2)))
val sessions = Filter.queryOn<Session>(realm, arrayListOf(filterMore, filterLess))

@ -44,6 +44,11 @@
android:launchMode="singleTop"
android:screenOrientation="portrait" />
<activity
android:name=".ui.activity.ComparisonChartActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait" />
<activity
android:name=".ui.activity.DataListActivity"
android:launchMode="singleTop"

@ -14,6 +14,7 @@ import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.utils.Seed
import net.pokeranalytics.android.util.FakeDataManager
import net.pokeranalytics.android.util.PokerAnalyticsLogs
import net.pokeranalytics.android.util.UserDefaults
import timber.log.Timber
@ -22,6 +23,8 @@ class PokerAnalyticsApplication : Application() {
override fun onCreate() {
super.onCreate()
UserDefaults.init(this)
println("UserPreferences.defaultCurrency: ${UserDefaults.currency.symbol}")
// Realm
Realm.init(this)

@ -7,10 +7,10 @@ import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.interfaces.Timed
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.CurrencyUtils
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.extensions.formatted
import net.pokeranalytics.android.util.extensions.formattedHourlyDuration
import net.pokeranalytics.android.util.extensions.toCurrency
import java.util.*
class StatFormattingException(message: String) : Exception(message) {
@ -136,9 +136,8 @@ enum class Stat : RowRepresentable {
when (this) {
// Amounts + red/green
Stat.NETRESULT, Stat.HOURLY_RATE, Stat.AVERAGE -> {
val numberFormat = CurrencyUtils.getCurrencyFormatter(context, currency)
val color = if (value >= this.threshold) R.color.green else R.color.red
return TextFormat(numberFormat.format(value), color)
return TextFormat(value.toCurrency(currency), color)
}
// Red/green numericValues
Stat.HOURLY_RATE_BB, Stat.AVERAGE_NET_BB, Stat.NET_BB_PER_100_HANDS -> {
@ -158,8 +157,7 @@ enum class Stat : RowRepresentable {
} // white amountsr
Stat.AVERAGE_BUYIN, Stat.STANDARD_DEVIATION, Stat.STANDARD_DEVIATION_HOURLY,
Stat.STANDARD_DEVIATION_BB_PER_100_HANDS -> {
val numberFormat = CurrencyUtils.getCurrencyFormatter(context, currency)
return TextFormat(numberFormat.format(value))
return TextFormat(value.toCurrency(currency))
}
else -> throw FormattingException("Stat formatting of ${this.name} not handled")
}

@ -1,12 +1,9 @@
package net.pokeranalytics.android.model.filter
import io.realm.RealmList
import io.realm.RealmQuery
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.Preferences
import net.pokeranalytics.android.util.extensions.endOfDay
import net.pokeranalytics.android.util.extensions.startOfDay
import java.util.*
@ -32,7 +29,7 @@ enum class QueryCondition(var operator: Operator? = null) {
LIMIT,
TABLE_SIZE,
TOURNAMENT_TYPE,
BLINDS,
BLIND,
LAST_GAMES,
LAST_SESSIONS,
MORE_NUMBER_OF_TABLE(Operator.MORE),
@ -77,10 +74,6 @@ enum class QueryCondition(var operator: Operator? = null) {
STARTED_FROM_TIME,
ENDED_TO_TIME,
CURRENCY,
CURRENCY_CODE,
BIG_BLIND,
SMALL_BLIND,
COMMENT,
;
@ -118,7 +111,7 @@ enum class QueryCondition(var operator: Operator? = null) {
return when (this) {
BANKROLL, GAME, LOCATION, ANY_TOURNAMENT_FEATURES, ALL_TOURNAMENT_FEATURES, TOURNAMENT_NAME -> arrayOf("ids")
LIMIT, TOURNAMENT_TYPE, TABLE_SIZE -> arrayOf("values")
BLINDS -> arrayOf("blinds")
BLIND -> arrayOf("blinds", "hasDefaultCurrency")
STARTED_FROM_DATE, STARTED_TO_DATE, ENDED_FROM_DATE, ENDED_TO_DATE -> arrayOf("date")
DAY_OF_WEEK -> arrayOf("dayOfWeek")
MONTH -> arrayOf("month")
@ -132,50 +125,8 @@ enum class QueryCondition(var operator: Operator? = null) {
* providing a base RealmQuery [realmQuery], the method is able to attached the corresponding query and returns the newly formed [RealmQuery]
*/
inline fun <reified T : Filterable> filter(realmQuery: RealmQuery<T>): RealmQuery<T> {
when {
this == BLINDS -> {
val smallBlindFieldName = FilterHelper.fieldNameForQueryType<T>(SMALL_BLIND)
val bigBlindFieldName = FilterHelper.fieldNameForQueryType<T>(BIG_BLIND)
val currencyCodeFieldName = FilterHelper.fieldNameForQueryType<T>(CURRENCY_CODE)
smallBlindFieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
bigBlindFieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
currencyCodeFieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
val blinds: RealmList<FilterElementBlind> by valueMap
blinds.forEachIndexed { index, blind ->
realmQuery
.beginGroup()
blind.sb?.let {
realmQuery
.equalTo(smallBlindFieldName, it)
.and()
}
realmQuery
.equalTo(bigBlindFieldName, blind.bb)
.and()
blind.currencyCode?.let {
realmQuery.equalTo(currencyCodeFieldName, it)
} ?: run {
realmQuery.isNull(currencyCodeFieldName)
}
realmQuery.endGroup()
if (index < blinds.size - 1) {
realmQuery.or()
}
}
return realmQuery
}
else -> {
val fieldName = FilterHelper.fieldNameForQueryType<T>(this)
fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
when (operator) {
Operator.LESS -> {
val value: Double by valueMap
@ -207,6 +158,27 @@ enum class QueryCondition(var operator: Operator? = null) {
val ids: Array<String> by valueMap
realmQuery.`in`(fieldName, ids)
}
BLIND -> {
val blinds: Array<String> by valueMap
val hasDefaultCurrency: Array<Boolean> by valueMap
//realmQuery.`in`(fieldName, blinds)
blinds.forEachIndexed { index, s ->
val isUsingDefaultCurrency = hasDefaultCurrency[index]
realmQuery.beginGroup()
if (isUsingDefaultCurrency) {
realmQuery.endsWith(fieldName, s)
.and()
.isNull("bankroll.currency.code")
} else {
realmQuery.equalTo(fieldName, s)
}
.endGroup()
if (index < blinds.size - 1) {
realmQuery.or()
}
}
realmQuery
}
BANKROLL, GAME, LOCATION, TOURNAMENT_NAME -> {
val ids: Array<String> by valueMap
realmQuery.`in`(fieldName, ids)
@ -293,9 +265,6 @@ enum class QueryCondition(var operator: Operator? = null) {
}
}
}
}
}
fun updateValueMap(filterCondition: FilterCondition) {
if (filterValuesExpectedKeys == null) {
@ -314,8 +283,10 @@ enum class QueryCondition(var operator: Operator? = null) {
LIMIT, TOURNAMENT_TYPE, TABLE_SIZE -> {
valueMap = mapOf("values" to filterCondition.values)
}
BLINDS -> {
valueMap = mapOf("blinds" to filterCondition.blinds)
BLIND -> {
valueMap = mapOf(
"blinds" to filterCondition.blinds,
"hasDefaultCurrency" to filterCondition.hasDefaultCurrency)
}
STARTED_FROM_DATE, STARTED_TO_DATE, ENDED_FROM_DATE, ENDED_TO_DATE -> {
valueMap = mapOf("date" to filterCondition.date)

@ -35,7 +35,9 @@ class PokerAnalyticsMigration : RealmMigration {
// Migrate to version 2
if (currentVersion == 1) {
Timber.d("*** Running migration ${currentVersion + 1}")
schema.get("Session")?.let {
it.addField("blinds", String::class.java).setNullable("blinds", true)
}
schema.rename("FilterElement", "FilterCondition")
schema.get("Filter")?.let {
it.renameField("filterElements", "filterConditions")

@ -3,6 +3,8 @@ package net.pokeranalytics.android.model.realm
import io.realm.Realm
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.LinkingObjects
import io.realm.annotations.PrimaryKey
import io.realm.kotlin.where
import net.pokeranalytics.android.R
@ -32,6 +34,9 @@ open class Bankroll() : RealmObject(), NameManageable, StaticRowRepresentableDat
}
}
@LinkingObjects("bankroll")
private val sessions: RealmResults<Session>? = null
@PrimaryKey
override var id = UUID.randomUUID().toString()
@ -46,6 +51,12 @@ open class Bankroll() : RealmObject(), NameManageable, StaticRowRepresentableDat
// The currency of the bankroll
var currency: Currency? = null
fun currencyCodeHasBeenUpdated() {
sessions?.forEach {
it.bankrollHasBeenUpdated()
}
}
override fun getDisplayName(): String {
return this.name
}
@ -86,6 +97,7 @@ open class Bankroll() : RealmObject(), NameManageable, StaticRowRepresentableDat
this.live = if (value is Boolean) !value else false
}
BankrollRow.CURRENCY -> {
//TODO handle a use default currency option
this.currency?.code = value as String?
}
BankrollRow.RATE -> {

@ -1,8 +1,11 @@
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 io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.util.Preferences
import java.util.*
open class Currency : RealmObject() {
@ -13,10 +16,19 @@ open class Currency : RealmObject() {
@PrimaryKey
var id = UUID.randomUUID().toString()
@LinkingObjects("currency")
private val bankrolls: RealmResults<Bankroll>? = null
/**
* The currency code of the currency, i.e. USD, EUR...
*/
var code: String? = null
set(value) {
field = value
bankrolls?.forEach {
it.currencyCodeHasBeenUpdated()
}
}
/**
* The rate of the currency with the main currency

@ -65,7 +65,7 @@ open class Filter : RealmObject() {
private set
fun createOrUpdateFilterConditions(filterConditionRows: ArrayList<FilterElementRow>) {
filterConditions.clear()
val casted = arrayListOf<FilterElementRow>()
filterConditionRows
.map {
it.filterName
@ -77,9 +77,13 @@ open class Filter : RealmObject() {
it.filterName == filterName
}
.apply {
val casted = arrayListOf<FilterElementRow>()
casted.addAll(this)
filterConditions.add(FilterCondition(casted))
val newFilterCondition = FilterCondition(casted)
val previousCondition = filterConditions.filter {
it.sectionName == newFilterCondition.filterName
}
filterConditions.removeAll(previousCondition)
filterConditions.add(newFilterCondition)
}
}
}

@ -23,6 +23,19 @@ open class FilterCondition() : RealmObject() {
is DateFilterElementRow -> {
this.dateValue = row.dateValue
}
is Blind -> {
//TODO refactor raz
this.stringValues = RealmList<String>().apply {
this.addAll(filterElementRows.map {
(it as Blind).blind
})
}
this.booleanValues = RealmList<Boolean>().apply {
this.addAll(filterElementRows.map {
(it as Blind).hasDefaultCurrency
})
}
}
is StringFilterElementRow -> {
this.stringValues = RealmList<String>().apply {
this.addAll(filterElementRows.map {
@ -37,13 +50,6 @@ open class FilterCondition() : RealmObject() {
})
}
}
is FilterElementBlind -> {
this.blindValues = RealmList<FilterElementBlind>().apply {
this.addAll(filterElementRows.map {
FilterElementBlind((it as FilterElementRow.Blind).sb, it.bb, it.code)
})
}
}
}
}
@ -59,23 +65,16 @@ open class FilterCondition() : RealmObject() {
private var numericValues: RealmList<Double>? = null
private var dateValue: Date? = null
private var stringValues: RealmList<String>? = null
private var blindValues: RealmList<FilterElementBlind>? = null
private var booleanValues: RealmList<Boolean>? = null
val ids: Array<String>
get() = stringValues?.toTypedArray() ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val blinds: RealmList<FilterElementBlind>
get() {
blindValues?.let {
if (it.isNotEmpty()) {
return it
} else {
throw PokerAnalyticsException.FilterElementExpectedValueMissing
}
}
throw PokerAnalyticsException.FilterElementExpectedValueMissing
}
val blinds: Array<String>
get() = stringValues?.toTypedArray() ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val hasDefaultCurrency: Array<Boolean>
get() = booleanValues?.toTypedArray() ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val date: Date
get() = dateValue ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing

@ -1,8 +0,0 @@
package net.pokeranalytics.android.model.realm
import io.realm.RealmObject
open class FilterElementBlind(var sb : Double? = null,
var bb : Double? = null,
var currencyCode : String? = null
) : RealmObject()

@ -32,8 +32,8 @@ import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.SeparatorRowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow
import net.pokeranalytics.android.util.CurrencyUtils
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.UserDefaults
import net.pokeranalytics.android.util.extensions.*
import java.util.*
import java.util.Currency
@ -74,10 +74,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
LIMIT -> "limit"
TABLE_SIZE -> "tableSize"
TOURNAMENT_TYPE -> "tournamentType"
CURRENCY -> "bankroll.currency"
CURRENCY_CODE -> "bankroll.currency.code"
BIG_BLIND -> "cgBigBlind"
SMALL_BLIND -> "cgSmallBlind"
BLIND -> "blind"
COMMENT -> "comment"
BETWEEN_NUMBER_OF_TABLE, MORE_NUMBER_OF_TABLE, LESS_NUMBER_OF_TABLE -> "numberOfTable"
MORE_THAN_NET_RESULT, LESS_THAN_NET_RESULT -> "computableResults.ratedNet"
@ -216,14 +213,22 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
// The small blind value
var cgSmallBlind: Double? = null
set(value) {
field = value
formatBlinds()
}
// The big blind value
var cgBigBlind: Double? = null
set(value) {
field = value
this.computeStats()
formatBlinds()
}
var blinds: String? = null
private set
// Tournament
// The entry fee of the tournament
@ -241,6 +246,10 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
// The features of the tournament, like Knockout, Shootout, Turbo...
var tournamentFeatures: RealmList<TournamentFeature> = RealmList()
fun bankrollHasBeenUpdated() {
formatBlinds()
}
/**
* Manages impacts on SessionSets
* Should be called when the start / end date are changed
@ -478,13 +487,18 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
return NULL_TEXT
}
/**
* Return the formatted blinds
*/
fun getBlinds(): String {
val currencyCode = bankroll?.currency?.code ?: CurrencyUtils.getLocaleCurrency().currencyCode
val currencySymbol = Currency.getInstance(currencyCode).symbol
return if (cgSmallBlind == null) NULL_TEXT else "$currencySymbol ${cgSmallBlind?.formatted()}/${cgBigBlind?.round()}"
val hasDefaultCurrency: Boolean
get() {
return bankroll?.currency?.code == null
}
val currency : Currency
get() {
return bankroll?.currency?.code?.let {
Currency.getInstance(it)
} ?: run {
UserDefaults.currency
}
}
/**
@ -504,6 +518,19 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
return if (gameTitle.isNotBlank()) gameTitle else NULL_TEXT
}
fun getFormattedBlinds(): String {
return blinds ?: NULL_TEXT
}
private fun formatBlinds() {
blinds = null
if (cgBigBlind == null) return
cgBigBlind?.let { bb ->
val sb = cgSmallBlind ?: bb / 2.0
blinds = "${currency.symbol} ${sb.formatted()}/${bb.round()}"
}
}
// LifeCycle
/**
@ -554,7 +581,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
CustomizableRowRepresentable(
RowViewType.HEADER_TITLE_AMOUNT_BIG,
title = getFormattedDuration(),
computedStat = ComputedStat(Stat.NETRESULT, result?.net ?: 0.0, CurrencyUtils.getCurrency(bankroll))
computedStat = ComputedStat(Stat.NETRESULT, result?.net ?: 0.0, currency)
)
)
rows.add(SeparatorRowRepresentable())
@ -564,7 +591,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
CustomizableRowRepresentable(
RowViewType.HEADER_TITLE_AMOUNT_BIG,
resId = R.string.pause,
computedStat = ComputedStat(Stat.NETRESULT, result?.net ?: 0.0, CurrencyUtils.getCurrency(bankroll))
computedStat = ComputedStat(Stat.NETRESULT, result?.net ?: 0.0, currency)
)
)
rows.add(SeparatorRowRepresentable())
@ -574,14 +601,14 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
CustomizableRowRepresentable(
RowViewType.HEADER_TITLE_AMOUNT_BIG,
title = getFormattedDuration(),
computedStat = ComputedStat(Stat.NETRESULT, result?.net ?: 0.0, CurrencyUtils.getCurrency(bankroll))
computedStat = ComputedStat(Stat.NETRESULT, result?.net ?: 0.0, currency)
)
)
rows.add(
CustomizableRowRepresentable(
RowViewType.HEADER_TITLE_AMOUNT,
resId = R.string.hour_rate_without_pauses,
computedStat = ComputedStat(Stat.HOURLY_RATE, this.hourlyRate, CurrencyUtils.getCurrency(bankroll))
computedStat = ComputedStat(Stat.HOURLY_RATE, this.hourlyRate, currency)
)
)
@ -620,20 +647,20 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
override fun stringForRow(row: RowRepresentable, context: Context): String {
return when (row) {
SessionRow.BANKROLL -> bankroll?.name ?: NULL_TEXT
SessionRow.BLINDS -> getBlinds()
SessionRow.BLINDS -> getFormattedBlinds()
SessionRow.BREAK_TIME -> if (this.breakDuration > 0.0) this.breakDuration.toMinutes() else NULL_TEXT
SessionRow.BUY_IN -> this.result?.buyin?.toCurrency(CurrencyUtils.getCurrency(bankroll)) ?: NULL_TEXT
SessionRow.CASHED_OUT, SessionRow.PRIZE, SessionRow.NET_RESULT -> this.result?.cashout?.toCurrency(CurrencyUtils.getCurrency(bankroll)) ?: NULL_TEXT
SessionRow.BUY_IN -> this.result?.buyin?.toCurrency(currency) ?: NULL_TEXT
SessionRow.CASHED_OUT, SessionRow.PRIZE, SessionRow.NET_RESULT -> this.result?.cashout?.toCurrency(currency) ?: NULL_TEXT
SessionRow.COMMENT -> if (this.comment.isNotEmpty()) this.comment else NULL_TEXT
SessionRow.END_DATE -> this.endDate?.shortDateTime() ?: NULL_TEXT
SessionRow.GAME -> getFormattedGame()
SessionRow.INITIAL_BUY_IN -> tournamentEntryFee?.toCurrency(CurrencyUtils.getCurrency(bankroll)) ?: NULL_TEXT
SessionRow.INITIAL_BUY_IN -> tournamentEntryFee?.toCurrency(currency) ?: NULL_TEXT
SessionRow.LOCATION -> location?.name ?: NULL_TEXT
SessionRow.PLAYERS -> tournamentNumberOfPlayers?.toString() ?: NULL_TEXT
SessionRow.POSITION -> result?.tournamentFinalPosition?.toString() ?: NULL_TEXT
SessionRow.START_DATE -> this.startDate?.shortDateTime() ?: NULL_TEXT
SessionRow.TABLE_SIZE -> this.tableSize?.let { TableSize(it).localizedTitle(context) } ?: NULL_TEXT
SessionRow.TIPS -> result?.tips?.toCurrency(CurrencyUtils.getCurrency(bankroll)) ?: NULL_TEXT
SessionRow.TIPS -> result?.tips?.toCurrency(currency) ?: NULL_TEXT
SessionRow.TOURNAMENT_TYPE -> this.tournamentType?.let {
TournamentType.values()[it].localizedTitle(context)
} ?: run {
@ -856,7 +883,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
}
value?.let {
return stat.format(it, CurrencyUtils.getCurrency(this.bankroll), context)
return stat.format(it, currency, context)
} ?: run {
return TextFormat(NULL_TEXT)
}

@ -5,11 +5,10 @@ import io.realm.Realm
import io.realm.kotlin.where
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.model.realm.Currency
import net.pokeranalytics.android.model.realm.Game
import net.pokeranalytics.android.model.realm.TournamentFeature
import net.pokeranalytics.android.util.CurrencyUtils
import java.util.*
import net.pokeranalytics.android.model.realm.Game
import net.pokeranalytics.android.util.UserDefaults
class Seed(var context:Context) : Realm.Transaction {
@ -32,7 +31,7 @@ class Seed(var context:Context) : Realm.Transaction {
private fun createDefaultCurrencyAndBankroll(realm: Realm) {
// Currency
val localeCurrency = CurrencyUtils.getLocaleCurrency()
val localeCurrency = UserDefaults.getLocaleCurrency()
val defaultCurrency = Currency()
defaultCurrency.code = localeCurrency.currencyCode
realm.insertOrUpdate(defaultCurrency)

@ -0,0 +1,33 @@
package net.pokeranalytics.android.ui.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
class ComparisonChartActivity : PokerAnalyticsActivity() {
companion object {
fun newInstance(context: Context) {
val intent = Intent(context, ComparisonChartActivity::class.java)
context.startActivity(intent)
}
/**
* Create a new instance for result
*/
fun newInstanceForResult(fragment: Fragment, requestCode: Int) {
val intent = Intent(fragment.requireContext(), ComparisonChartActivity::class.java)
fragment.startActivityForResult(intent, requestCode)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_comparison_chart)
}
}

@ -4,6 +4,7 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.github.mikephil.charting.data.Entry
import kotlinx.android.synthetic.main.activity_graph.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
@ -30,9 +31,7 @@ class GraphActivity : PokerAnalyticsActivity() {
* Default constructor
*/
fun newInstance(context: Context, stat: Stat, entries: List<Entry>) {
GraphActivity.parameters = GraphParameters(stat, entries)
parameters = GraphParameters(stat, entries)
val intent = Intent(context, GraphActivity::class.java)
context.startActivity(intent)
}
@ -50,6 +49,9 @@ class GraphActivity : PokerAnalyticsActivity() {
*/
private fun initUI() {
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
val fragment = GraphFragment()

@ -0,0 +1,80 @@
package net.pokeranalytics.android.ui.adapter
import android.content.Context
import android.util.SparseArray
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.fragment.*
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import java.lang.ref.WeakReference
/**
* Comparison Chart Pager Adapter
*/
class ComparisonChartPagerAdapter(val context: Context, fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {
var weakReferences = SparseArray<WeakReference<PokerAnalyticsFragment>>()
override fun getItem(position: Int): PokerAnalyticsFragment {
return when (position) {
0 -> GraphFragment()
1 -> GraphFragment()
2 -> CalendarFragment.newInstance()
else -> HistoryFragment.newInstance()
}
}
override fun getCount(): Int {
return 3
}
override fun getPageTitle(position: Int): CharSequence? {
return when(position) {
0 -> context.getString(R.string.bar)
1 -> context.getString(R.string.line)
2-> context.getString(R.string.table)
else -> super.getPageTitle(position)
}
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
super.destroyItem(container, position, `object`)
weakReferences.remove(position)
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val fragment = super.instantiateItem(container, position) as PokerAnalyticsFragment
weakReferences.put(position, WeakReference(fragment))
return fragment
}
override fun getItemPosition(obj: Any): Int {
return when (obj) {
//CLEAN
/*
HistoryFragment::class.java -> 0
StatsFragment::class.java -> 1
SettingsFragment::class.java -> 2
*/
HistoryFragment::class.java -> 0
StatsFragment::class.java -> 1
CalendarFragment::class.java -> 2
ReportsFragment::class.java -> 3
MoreFragment::class.java -> 4
else -> -1
}
}
/**
* Return the fragment at the position key
*/
fun getFragment(key: Int): PokerAnalyticsFragment? {
if (weakReferences.get(key) != null) {
return weakReferences.get(key).get()
}
return null
}
}

@ -17,9 +17,9 @@ import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.BankrollRow
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import net.pokeranalytics.android.util.CurrencyUtils
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.extensions.toRate
import retrofit2.Call
import retrofit2.Response
import java.util.*
@ -96,9 +96,9 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
}
BankrollRow.RATE -> {
this.bankroll.currency?.rate?.let { rate ->
CurrencyUtils.getCurrencyRateFormatter().format(rate)
rate.toRate()
} ?: run {
CurrencyUtils.getCurrencyRateFormatter().format(1.0)
1.0.toRate()
}
}
else -> super.stringForRow(row)
@ -119,7 +119,7 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
BankrollRow.RATE -> {
this.bankroll.currency?.rate?.let { rate ->
row.editingDescriptors(mapOf("defaultValue" to CurrencyUtils.getCurrencyRateFormatter().format(rate)))
row.editingDescriptors(mapOf("defaultValue" to rate.toRate()))
} ?: run {
row.editingDescriptors(mapOf())
}

@ -0,0 +1,100 @@
package net.pokeranalytics.android.ui.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_comparison_chart.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.activity.BankrollActivity
import net.pokeranalytics.android.ui.activity.SettingsActivity
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.adapter.ComparisonChartPagerAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.MoreTabRow
class ComparisonChartFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate {
companion object {
/**
* Create new instance
*/
fun newInstance(): ComparisonChartFragment {
val fragment = ComparisonChartFragment()
val bundle = Bundle()
fragment.arguments = bundle
return fragment
}
val rowRepresentation: List<RowRepresentable> by lazy {
val rows = ArrayList<RowRepresentable>()
rows.addAll(MoreTabRow.values())
rows
}
}
private lateinit var parentActivity: PokerAnalyticsActivity
private lateinit var viewPagerAdapter: ComparisonChartPagerAdapter
// Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_comparison_chart, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initData()
initUI()
}
// Rows
override fun adapterRows(): List<RowRepresentable>? {
return rowRepresentation
}
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
super.onRowSelected(position, row, fromAction)
when(row) {
MoreTabRow.BANKROLL -> BankrollActivity.newInstance(requireContext())
MoreTabRow.SETTINGS -> SettingsActivity.newInstance(requireContext())
}
}
// Business
/**
* Init data
*/
private fun initData() {
}
/**
* Init UI
*/
private fun initUI() {
parentActivity = activity as PokerAnalyticsActivity
toolbar.title = ""
parentActivity.setSupportActionBar(toolbar)
parentActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
setHasOptionsMenu(true)
toolbar.title = "Comparison chart"
viewPagerAdapter = ComparisonChartPagerAdapter(requireContext(), parentActivity.supportFragmentManager)
viewPager.adapter = viewPagerAdapter
tabs.setupWithViewPager(viewPager)
}
}

@ -32,8 +32,8 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener {
private lateinit var parentActivity: PokerAnalyticsActivity
lateinit var stat: Stat
lateinit var entries: List<Entry>
private var stat: Stat = Stat.NETRESULT
private var entries: List<Entry> = ArrayList()
lateinit var legendView: LegendView
lateinit var chartView: BarLineChartBase<*>
@ -62,20 +62,12 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener {
private fun initUI() {
parentActivity = activity as PokerAnalyticsActivity
parentActivity.title = stat.localizedTitle(requireContext())
this.legendView = LegendView(requireContext())
this.legendContainer.addView(this.legendView)
this.legendView.prepareWithStat(this.stat, this.entries.size)
// Avoid a bug during setting the title
toolbar.title = ""
parentActivity.setSupportActionBar(toolbar)
parentActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
setHasOptionsMenu(true)
toolbar.title = stat.localizedTitle(requireContext())
val dataSet = LineDataSet(this.entries, this.stat.name)
val colors = arrayOf(R.color.green_light).toIntArray()
dataSet.setColors(colors, context)
@ -110,6 +102,8 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener {
this.chipGroup.addView(chip)
}
this.chipGroup.check(this.stat.aggregationTypes.first().ordinal)
this.chipGroup.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() {
override fun onCheckedChanged(group: ChipGroup, checkedId: Int) {
super.onCheckedChanged(group, checkedId)
@ -117,7 +111,6 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener {
}
})
this.chipGroup.check(this.stat.aggregationTypes.first().ordinal)
}
// OnChartValueSelectedListener

@ -7,6 +7,7 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_stats.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.activity.ComparisonChartActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
@ -56,6 +57,11 @@ class ReportsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSour
return rowRepresentation
}
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
super.onRowSelected(position, row, fromAction)
ComparisonChartActivity.newInstance(requireContext())
}
// Business

@ -27,7 +27,6 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableDiffCallback
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager
import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow
import net.pokeranalytics.android.util.CurrencyUtils
import java.util.*
@ -104,9 +103,9 @@ class SessionFragment : PokerAnalyticsFragment(), RowRepresentableDelegate {
}
SessionRow.BANKROLL -> {
BottomSheetFragment.create(fragmentManager, row, this, data, false, CurrencyUtils.getCurrency(currentSession.bankroll))
BottomSheetFragment.create(fragmentManager, row, this, data, false, currentSession.currency)
}
else -> BottomSheetFragment.create(fragmentManager, row, this, data, currentCurrency = CurrencyUtils.getCurrency(currentSession.bankroll))
else -> BottomSheetFragment.create(fragmentManager, row, this, data, currentCurrency = currentSession.currency)
}
}

@ -7,9 +7,11 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.Realm
import kotlinx.android.synthetic.main.fragment_settings.*
import net.pokeranalytics.android.BuildConfig
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.ui.activity.CurrenciesActivity
import net.pokeranalytics.android.ui.activity.DataListActivity
import net.pokeranalytics.android.ui.activity.GDPRActivity
@ -22,6 +24,7 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.SettingRow
import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.URL
import net.pokeranalytics.android.util.UserDefaults
import net.pokeranalytics.android.util.extensions.openContactMail
import net.pokeranalytics.android.util.extensions.openPlayStorePage
import net.pokeranalytics.android.util.extensions.openUrl
@ -30,7 +33,6 @@ import java.util.*
class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, StaticRowRepresentableDataSource {
private lateinit var parentActivity: PokerAnalyticsActivity
companion object {
@ -53,15 +55,8 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta
const val REQUEST_CODE_CURRENCY: Int = 100
}
override fun stringForRow(row: RowRepresentable): String {
return when (row) {
SettingRow.VERSION -> BuildConfig.VERSION_NAME + if (BuildConfig.DEBUG) " (${BuildConfig.VERSION_CODE}) DEBUG" else ""
SettingRow.CURRENCY -> Currency.getInstance(Preferences.getCurrencyLocale(this.parentActivity)).symbol
else -> ""
}
}
private lateinit var settingsAdapterRow: RowRepresentableAdapter
private lateinit var parentActivity: PokerAnalyticsActivity
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -78,6 +73,13 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta
if (requestCode == REQUEST_CODE_CURRENCY && resultCode == Activity.RESULT_OK) {
data?.let {
Preferences.setCurrencyCode(data.getStringExtra(CurrenciesFragment.INTENT_CURRENCY_CODE), requireContext())
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
it.where(Bankroll::class.java).isNull("currency.code").findAll().forEach { bankroll ->
bankroll.currencyCodeHasBeenUpdated()
}
}
realm.close()
settingsAdapterRow.refreshRow(SettingRow.CURRENCY)
}
}
@ -87,6 +89,14 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta
return rowRepresentation
}
override fun stringForRow(row: RowRepresentable): String {
return when (row) {
SettingRow.VERSION -> BuildConfig.VERSION_NAME + if (BuildConfig.DEBUG) " (${BuildConfig.VERSION_CODE}) DEBUG" else ""
SettingRow.CURRENCY -> UserDefaults.currency.symbol
else -> ""
}
}
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
when (row) {

@ -16,7 +16,6 @@ import net.pokeranalytics.android.model.extensions.SessionState
import net.pokeranalytics.android.model.extensions.getState
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.view.fields.setTextFormat
import net.pokeranalytics.android.util.CurrencyUtils
import net.pokeranalytics.android.util.extensions.getDayNumber
import net.pokeranalytics.android.util.extensions.getShortDayName
import net.pokeranalytics.android.util.extensions.shortTime
@ -69,7 +68,7 @@ class SessionRowView : FrameLayout {
if (session.isTournament()) {
session.tournamentEntryFee?.let {
parameters.add(it.toCurrency(CurrencyUtils.getCurrency(session.bankroll)))
parameters.add(it.toCurrency(session.currency))
}
session.tournamentName?.let {
@ -86,7 +85,7 @@ class SessionRowView : FrameLayout {
}
} else {
if (session.cgSmallBlind != null && session.cgBigBlind != null) {
parameters.add(session.getBlinds())
parameters.add(session.getFormattedBlinds())
}
session.game?.let {
parameters.add(session.getFormattedGame())
@ -150,7 +149,7 @@ class SessionRowView : FrameLayout {
rowHistorySession.infoTitle.isVisible = false
val result = session.result?.net ?: 0.0
val formattedStat = ComputedStat(Stat.NETRESULT, result, currency = CurrencyUtils.getCurrency(session.bankroll)).format(context)
val formattedStat = ComputedStat(Stat.NETRESULT, result, currency = session.currency).format(context)
rowHistorySession.gameResult.setTextFormat(formattedStat, context)
// rowHistorySession.gameResult.setTextColor(formattedStat.getColor(context))
// rowHistorySession.gameResult.text = formattedStat.text

@ -54,7 +54,7 @@ enum class FilterCategoryRow(override val resId: Int?, override val viewType: In
BANKROLL
)
CASH -> arrayListOf(
BLINDS,
BLIND,
CASH_RE_BUY_COUNT
)
TOURNAMENT -> arrayListOf(

@ -11,10 +11,8 @@ import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheet
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.CurrencyUtils
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.extensions.formatted
import net.pokeranalytics.android.util.extensions.round
import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.UserDefaults
import java.text.DateFormatSymbols
import java.util.*
@ -105,14 +103,7 @@ sealed class FilterElementRow : RowRepresentable {
data class Month(val month: Int) : SingleValueFilterElementRow(month)
data class Day(val day: Int) : SingleValueFilterElementRow(day)
data class Blind(var sb: Double? = null, var bb: Double? = null, var code: String? = null) : FilterElementRow() {
val name: String
get() {
val currencyCode = code ?: CurrencyUtils.getLocaleCurrency().currencyCode
val currencySymbol = Currency.getInstance(currencyCode).symbol
return if (sb == null) NULL_TEXT else "$currencySymbol ${sb?.formatted()}/${bb?.round()}"
}
}
data class Blind(val blind: String, val hasDefaultCurrency: Boolean) : StringFilterElementRow(blind)
//TODO: Refactor?
data class PastDays(var lastDays: Int = 0) : SingleValueFilterElementRow(lastDays) {
@ -155,7 +146,7 @@ sealed class FilterElementRow : RowRepresentable {
return when (this) {
is Cash -> QueryCondition.CASH
is Tournament -> QueryCondition.TOURNAMENT
is Blind -> QueryCondition.BLINDS
is Blind -> QueryCondition.BLIND
is From -> QueryCondition.STARTED_FROM_DATE
is To -> QueryCondition.ENDED_TO_DATE
is FromTime -> QueryCondition.STARTED_FROM_TIME
@ -308,7 +299,7 @@ sealed class FilterElementRow : RowRepresentable {
}
is DataFilterElementRow -> this.name
is StaticDataFilterElementRow -> this.name
is Blind -> this.name
is Blind -> this.blind
else -> super.getDisplayName()
}
}

@ -30,7 +30,7 @@ enum class FilterSectionRow(override val resId: Int?) : RowRepresentable {
SESSION_DURATION(net.pokeranalytics.android.R.string.session_duration),
RANGE(net.pokeranalytics.android.R.string.hour_slot),
SESSIONS(R.string.sessions),
BLINDS(net.pokeranalytics.android.R.string.blinds),
BLIND(net.pokeranalytics.android.R.string.blinds),
CASH_RE_BUY_COUNT(net.pokeranalytics.android.R.string.rebuy_count),
TOURNAMENT_TYPE(net.pokeranalytics.android.R.string.tournament_types),
TOURNAMENT_NAME(net.pokeranalytics.android.R.string.tournament_name),
@ -160,36 +160,15 @@ enum class FilterSectionRow(override val resId: Int?) : RowRepresentable {
SESSIONS -> arrayListOf(LastGames(0), LastSessions(0))
// Cash
BLINDS -> {
// TODO: Improve the way we get the blinds distinctly
val blinds = arrayListOf<FilterElementRow.Blind>()
BLIND -> {
val blinds = arrayListOf<Blind>()
val realm = Realm.getDefaultInstance()
val sessions =
realm.where<Session>().isNotNull("cgSmallBlind").isNotNull("cgBigBlind").findAll()
.sort("cgSmallBlind", Sort.ASCENDING)
val distinctBlinds: ArrayList<Session> = ArrayList()
val blindsHashMap: ArrayList<String> = ArrayList()
sessions.forEach {
if (!blindsHashMap.contains(it.getBlinds())) {
blindsHashMap.add(it.getBlinds())
distinctBlinds.add(it)
realm.where<Session>().distinct("blind", "bankroll.currency.code").findAll().sort("cgSmallBlind", Sort.ASCENDING).map {
it.blinds?.let { stake ->
blinds.add(Blind(stake, it.hasDefaultCurrency))
}
}
distinctBlinds.forEach { session ->
blinds.add(
Blind(
session.cgSmallBlind,
session.cgBigBlind,
session.bankroll?.currency?.code
)
)
session.getBlinds()
}
realm.close()
blinds
}
CASH_RE_BUY_COUNT -> arrayListOf(

@ -1,64 +0,0 @@
package net.pokeranalytics.android.util
import android.content.Context
import net.pokeranalytics.android.model.realm.Bankroll
import java.text.NumberFormat
import java.util.*
class CurrencyUtils {
companion object {
/**
* return the currency associated with this bankroll
*/
fun getCurrency(bankroll: Bankroll? = null) : Currency {
val currencyCode = bankroll?.currency?.code ?: CurrencyUtils.getLocaleCurrency().currencyCode
return Currency.getInstance(currencyCode)
}
/**
* Get a currency formatter
*/
fun getCurrencyFormatter(context: Context, currency: Currency? = null) : NumberFormat {
val currencyFormatter = NumberFormat.getCurrencyInstance(Preferences.getCurrencyLocale(context))
currency?.let {
currencyFormatter.currency = it
}
currencyFormatter.minimumFractionDigits = 0
currencyFormatter.maximumFractionDigits = 2
return currencyFormatter
}
/**
* Get a currency rate formatter
*/
fun getCurrencyRateFormatter() : NumberFormat {
val currencyFormatter = NumberFormat.getInstance()
currencyFormatter.minimumFractionDigits = 0
currencyFormatter.maximumFractionDigits = 6
return currencyFormatter
}
/**
* Return the locale currency, or en_US if there
*/
fun getLocaleCurrency() : Currency {
return try {
Currency.getInstance(Locale.getDefault())
} catch (ex: Exception) {
when (Locale.getDefault().language) {
"en" -> Currency.getInstance(Locale("en", "US"))
"fr" -> Currency.getInstance(Locale("fr", "FR"))
"es" -> Currency.getInstance(Locale("es", "ES"))
"de" -> Currency.getInstance(Locale("de", "DE"))
"ja" -> Currency.getInstance(Locale("ja", "JP"))
"zh" -> Currency.getInstance(Locale("zh", "CN"))
else -> Currency.getInstance(Locale("en", "US"))
}
}
}
}
}

@ -16,8 +16,6 @@ class Preferences {
companion object {
var currencyLocale : Locale? = null
fun setString(key: Keys, value: String, context: Context) {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val editor = preferences.edit()
@ -43,21 +41,16 @@ class Preferences {
}
fun setCurrencyCode(currencyCode: String, context: Context) {
Preferences.setString(Keys.CURRENCY_CODE, currencyCode, context)
currencyLocale = null
setString(Keys.CURRENCY_CODE, currencyCode, context)
UserDefaults.setCurrencyValues(context)
}
private fun getCurrencyCode(context: Context) : String? {
return Preferences.getString(Keys.CURRENCY_CODE, context)
return getString(Keys.CURRENCY_CODE, context)
}
fun getCurrencyLocale(context : Context) : Locale {
currencyLocale?. let {
return it
}
Preferences.getCurrencyCode(context)?.let { currencyCode ->
fun getCurrencyLocale(context : Context) : Locale? {
getCurrencyCode(context)?.let { currencyCode ->
Locale.getAvailableLocales().filter{
try {
Currency.getInstance(it).currencyCode == currencyCode
@ -65,22 +58,87 @@ class Preferences {
false
}
}.first().let {
currencyLocale = it
return it
}
}
currencyLocale = Locale.getDefault()
return currencyLocale!!
return null
}
fun getDefaultCurrency(context: Context) : Currency? {
getCurrencyLocale(context)?.let {
return Currency.getInstance(it)
}
return null
}
fun setStopShowingDisclaimer(context: Context) {
Preferences.setBoolean(Keys.STOP_SHOWING_DISCLAIMER, true, context)
setBoolean(Keys.STOP_SHOWING_DISCLAIMER, true, context)
}
fun shouldShowDisclaimer(context: Context) : Boolean {
return !Preferences.getBoolean(Keys.STOP_SHOWING_DISCLAIMER, context)
return !getBoolean(Keys.STOP_SHOWING_DISCLAIMER, context)
}
}
}
class UserDefaults private constructor(context: Context) {
init {
setCurrencyValues(context)
}
companion object : SingletonHolder<UserDefaults, Context>(::UserDefaults) {
lateinit var currency : Currency
lateinit var currencyLocale : Locale
fun setCurrencyValues(context: Context) {
currency = Preferences.getDefaultCurrency(context) ?: getLocaleCurrency()
currencyLocale = Preferences.getCurrencyLocale(context) ?: Locale.getDefault()
}
/**
* Return the locale currency, or en_US if there
*/
fun getLocaleCurrency() : Currency {
return try {
Currency.getInstance(Locale.getDefault())
} catch (ex: Exception) {
when (Locale.getDefault().language) {
"en" -> Currency.getInstance(Locale("en", "US"))
"fr" -> Currency.getInstance(Locale("fr", "FR"))
"es" -> Currency.getInstance(Locale("es", "ES"))
"de" -> Currency.getInstance(Locale("de", "DE"))
"ja" -> Currency.getInstance(Locale("ja", "JP"))
"zh" -> Currency.getInstance(Locale("zh", "CN"))
else -> Currency.getInstance(Locale("en", "US"))
}
}
}
}
}
open class SingletonHolder<out T, in A>(creator: (A) -> T) {
private var creator: ((A) -> T)? = creator
@Volatile private var instance: T? = null
fun init(context: A): T {
val i = instance
if (i != null) {
return i
}
return synchronized(this) {
val i2 = instance
if (i2 != null) {
i2
} else {
val created = creator!!(context)
instance = created
creator = null
created
}
}
}
}

@ -2,6 +2,7 @@ package net.pokeranalytics.android.util.extensions
import android.content.Context
import net.pokeranalytics.android.R
import net.pokeranalytics.android.util.UserDefaults
import java.text.DecimalFormat
import java.text.NumberFormat
import java.util.*
@ -23,7 +24,7 @@ fun Double.formatted(): String {
fun Double.toCurrency(currency: Currency? = null): String {
val currencyFormatter = NumberFormat.getCurrencyInstance()
val currencyFormatter = NumberFormat.getCurrencyInstance(UserDefaults.currencyLocale)
currency?.let {
currencyFormatter.currency = currency
}
@ -33,6 +34,14 @@ fun Double.toCurrency(currency: Currency? = null): String {
return currencyFormatter.format(this)
}
fun Double.toRate(): String {
val currencyFormatter = NumberFormat.getInstance()
currencyFormatter.minimumFractionDigits = 0
currencyFormatter.maximumFractionDigits = 6
return currencyFormatter.format(this)
}
fun Double.formattedHourlyDuration() : String {
return (this * 1000 * 3600).toLong().toMinutes()
}

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical">
<fragment
android:id="@+id/comparisonChartFragment"
android:name="net.pokeranalytics.android.ui.fragment.ComparisonChartFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_comparison_chart" />
</LinearLayout>

@ -1,8 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
<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">
</FrameLayout>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:title="@string/app_name" />
<FrameLayout
android:id="@+id/container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,57 @@
<?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.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/PokerAnalyticsTheme.Toolbar.Session"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:titleTextColor="@color/white"
tools:title="Poker Analytics" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bar" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/line" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/table" />
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/appBar" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -5,22 +5,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:title="@string/app_name" />
<FrameLayout
android:id="@+id/legendContainer"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/chartContainer"

@ -7,6 +7,7 @@
<string name="minute">Minute</string>
<string name="more">More</string>
<string name="variant">Variant</string>
<string name="line">Line</string>
<!--<string name="session_missing_end_date">Please set the end date for the session</string>-->
<!--<string name="default_error_message">Sorry, something went wrong...please contact us!</string>-->

@ -19,6 +19,7 @@
<item name="android:textViewStyle">@style/PokerAnalyticsTheme.TextView</item>
<item name="alertDialogTheme">@style/PokerAnalyticsTheme.AlertDialog</item>
<item name="chipStyle">@style/PokerAnalyticsTheme.Chip</item>
<item name="tabStyle">@style/PokerAnalyticsTheme.TabLayout</item>
</style>
@ -179,6 +180,14 @@
<item name="android:fontFamily">@font/roboto</item>
</style>
<!-- Tabs -->
<style name="PokerAnalyticsTheme.TabLayout" parent="Widget.MaterialComponents.TabLayout">
<item name="android:background">@color/colorPrimary</item>
<item name="tabTextColor">@color/gray_light</item>
<item name="tabSelectedTextColor">@color/green</item>
<item name="tabRippleColor">@color/green_transparent</item>
</style>
<!-- Session Row -->

Loading…
Cancel
Save