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

# Conflicts:
#	app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt
feature/top10
Aurelien Hubert 7 years ago
commit ae519a700a
  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. 3
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  6. 16
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  7. 13
      app/src/main/java/net/pokeranalytics/android/calculus/Report.kt
  8. 18
      app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt
  9. 303
      app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt
  10. 5
      app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt
  11. 4
      app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt
  12. 12
      app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt
  13. 14
      app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt
  14. 14
      app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt
  15. 39
      app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt
  16. 8
      app/src/main/java/net/pokeranalytics/android/model/realm/FilterElementBlind.kt
  17. 84
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  18. 6
      app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt
  19. 7
      app/src/main/java/net/pokeranalytics/android/model/utils/Seed.kt
  20. 8
      app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDataFragment.kt
  21. 25
      app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt
  22. 5
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt
  23. 10
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt
  24. 19
      app/src/main/java/net/pokeranalytics/android/ui/view/LegendView.kt
  25. 11
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt
  26. 13
      app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt
  27. 6
      app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt
  28. 10
      app/src/main/java/net/pokeranalytics/android/ui/view/fields/FieldsExtension.kt
  29. 2
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterCategoryRow.kt
  30. 21
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt
  31. 41
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt
  32. 64
      app/src/main/java/net/pokeranalytics/android/util/CurrencyUtils.kt
  33. 92
      app/src/main/java/net/pokeranalytics/android/util/Preferences.kt
  34. 11
      app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt

@ -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))

@ -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)

@ -147,19 +147,19 @@ class Calculator {
tHands += computable.estimatedHands
val session = computable.session ?: throw IllegalStateException("Computing lone ComputableResult")
results.addEvolutionValue(tSum, NETRESULT, session)
results.addEvolutionValue(tSum / index, AVERAGE, session)
results.addEvolutionValue(index.toDouble(), NUMBER_OF_GAMES, session)
results.addEvolutionValue(tBBSum / tBBSessionCount, AVERAGE_NET_BB, session)
results.addEvolutionValue((tWinningSessionCount / index).toDouble(), WIN_RATIO, session)
results.addEvolutionValue(tBuyinSum / index, AVERAGE_BUYIN, session)
results.addEvolutionValue(tSum, stat = NETRESULT, data = session)
results.addEvolutionValue(tSum / index, stat = AVERAGE, data = session)
results.addEvolutionValue(index.toDouble(), stat = NUMBER_OF_GAMES, data = session)
results.addEvolutionValue(tBBSum / tBBSessionCount, stat = AVERAGE_NET_BB, data = session)
results.addEvolutionValue((tWinningSessionCount / index).toDouble(), stat = WIN_RATIO, data = session)
results.addEvolutionValue(tBuyinSum / index, stat = AVERAGE_BUYIN, data = session)
Stat.netBBPer100Hands(tBBSum, tHands)?.let { netBB100 ->
results.addEvolutionValue(netBB100, NET_BB_PER_100_HANDS, session)
results.addEvolutionValue(netBB100, stat = NET_BB_PER_100_HANDS, data = session)
}
Stat.returnOnInvestment(tSum, tBuyinSum)?.let { roi ->
results.addEvolutionValue(roi, ROI, session)
results.addEvolutionValue(roi, stat = ROI, data = session)
}
}

@ -158,13 +158,14 @@ class ComputedResults(group: ComputableGroup) {
/**
* 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? = null, stat: Stat, data: Timed) {
fun addEvolutionValue(value: Double, duration: Double, stat: Stat, data: Timed) {
stat.underlyingClass = data::class.java
this._addEvolutionValue(Point(value, y = duration, data = data.id), stat = stat)
val point = if (duration != null) {
Point(duration, y = value, data = data.objectIdentifier)
} else {
Point(value, data = data.objectIdentifier)
}
this._addEvolutionValue(point, stat = stat)
}
private fun _addEvolutionValue(point: Point, stat: Stat) {

@ -1,23 +1,27 @@
package net.pokeranalytics.android.calculus
import android.content.Context
import io.realm.RealmModel
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.FormattingException
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) {
}
interface StatBase : RealmModel {
class ObjectIdentifier(var id: String, var clazz: Class<out Timed>) {
}
interface StatBase : Identifiable {
fun formattedValue(stat: Stat, context: Context): TextFormat
@ -48,7 +52,7 @@ enum class AggregationType {
/**
* An enum representing all the types of Session statistics
*/
enum class Stat(var underlyingClass: Class<out Timed>? = null) : RowRepresentable {
enum class Stat : RowRepresentable {
NETRESULT,
HOURLY_RATE,
@ -132,9 +136,8 @@ enum class Stat(var underlyingClass: Class<out Timed>? = null) : RowRepresentabl
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 -> {
@ -154,8 +157,7 @@ enum class Stat(var underlyingClass: Class<out Timed>? = null) : RowRepresentabl
} // 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,169 +125,145 @@ 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()
val fieldName = FilterHelper.fieldNameForQueryType<T>(this)
fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
when (operator) {
Operator.LESS -> {
val value: Double by valueMap
return realmQuery.lessThanOrEqualTo(fieldName, value)
}
Operator.MORE -> {
val value: Double by valueMap
return realmQuery.greaterThanOrEqualTo(fieldName, value)
}
Operator.BETWEEN -> {
val leftValue: Double by valueMap
val rightValue: Double by valueMap
return realmQuery.between(fieldName, leftValue, rightValue)
}
}
if (index < blinds.size - 1) {
realmQuery.or()
}
return when (this) {
LIVE, ONLINE -> realmQuery.equalTo(fieldName, this == LIVE)
CASH -> realmQuery.equalTo(fieldName, Session.Type.CASH_GAME.ordinal)
TOURNAMENT -> realmQuery.equalTo(fieldName, Session.Type.TOURNAMENT.ordinal)
ALL_TOURNAMENT_FEATURES -> {
val ids: Array<String> by valueMap
ids.forEach {
realmQuery.equalTo(fieldName, it)
}
return realmQuery
realmQuery
}
else -> {
val fieldName = FilterHelper.fieldNameForQueryType<T>(this)
fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
when (operator) {
Operator.LESS -> {
val value: Double by valueMap
return realmQuery.lessThanOrEqualTo(fieldName, value)
}
Operator.MORE -> {
val value: Double by valueMap
return realmQuery.greaterThanOrEqualTo(fieldName, value)
}
Operator.BETWEEN -> {
val leftValue: Double by valueMap
val rightValue: Double by valueMap
return realmQuery.between(fieldName, leftValue, rightValue)
ANY_TOURNAMENT_FEATURES -> {
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()
}
}
return when (this) {
LIVE, ONLINE -> realmQuery.equalTo(fieldName, this == LIVE)
CASH -> realmQuery.equalTo(fieldName, Session.Type.CASH_GAME.ordinal)
TOURNAMENT -> realmQuery.equalTo(fieldName, Session.Type.TOURNAMENT.ordinal)
ALL_TOURNAMENT_FEATURES -> {
val ids: Array<String> by valueMap
ids.forEach {
realmQuery.equalTo(fieldName, it)
}
realmQuery
}
ANY_TOURNAMENT_FEATURES -> {
val ids: Array<String> by valueMap
realmQuery.`in`(fieldName, ids)
}
BANKROLL, GAME, LOCATION, TOURNAMENT_NAME -> {
val ids: Array<String> by valueMap
realmQuery.`in`(fieldName, ids)
}
LIMIT, TOURNAMENT_TYPE, TABLE_SIZE -> {
val values: Array<Int?>? by valueMap
realmQuery.`in`(fieldName, values)
}
STARTED_FROM_DATE -> {
val date: Date by valueMap
realmQuery.greaterThanOrEqualTo(fieldName, date)
}
STARTED_TO_DATE -> {
val date: Date by valueMap
realmQuery.lessThanOrEqualTo(fieldName, date)
}
ENDED_FROM_DATE -> {
val date: Date by valueMap
realmQuery.greaterThanOrEqualTo(fieldName, date)
}
ENDED_TO_DATE -> {
val date: Date by valueMap
realmQuery.lessThanOrEqualTo(fieldName, date)
}
DAY_OF_WEEK -> {
val dayOfWeek: Int by valueMap
realmQuery.equalTo(fieldName, dayOfWeek)
}
MONTH -> {
val month: Int by valueMap
realmQuery.equalTo(fieldName, month)
}
YEAR -> {
val year: Int by valueMap
realmQuery.equalTo(fieldName, year)
}
WEEK_END, WEEK_DAY -> {
var query = realmQuery
if (this == WEEK_DAY) {
query = realmQuery.not()
}
query.`in`(fieldName, arrayOf(Calendar.SATURDAY, Calendar.SUNDAY))
}
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
}
realmQuery
}
BANKROLL, GAME, LOCATION, TOURNAMENT_NAME -> {
val ids: Array<String> by valueMap
realmQuery.`in`(fieldName, ids)
}
LIMIT, TOURNAMENT_TYPE, TABLE_SIZE -> {
val values: Array<Int?>? by valueMap
realmQuery.`in`(fieldName, values)
}
STARTED_FROM_DATE -> {
val date: Date by valueMap
realmQuery.greaterThanOrEqualTo(fieldName, date)
}
STARTED_TO_DATE -> {
val date: Date by valueMap
realmQuery.lessThanOrEqualTo(fieldName, date)
}
ENDED_FROM_DATE -> {
val date: Date by valueMap
realmQuery.greaterThanOrEqualTo(fieldName, date)
}
ENDED_TO_DATE -> {
val date: Date by valueMap
realmQuery.lessThanOrEqualTo(fieldName, date)
}
DAY_OF_WEEK -> {
val dayOfWeek: Int by valueMap
realmQuery.equalTo(fieldName, dayOfWeek)
}
MONTH -> {
val month: Int by valueMap
realmQuery.equalTo(fieldName, month)
}
YEAR -> {
val year: Int by valueMap
realmQuery.equalTo(fieldName, year)
}
WEEK_END, WEEK_DAY -> {
var query = realmQuery
if (this == WEEK_DAY) {
query = realmQuery.not()
}
query.`in`(fieldName, arrayOf(Calendar.SATURDAY, Calendar.SUNDAY))
}
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
}
}
}
fun updateValueMap(filterCondition: FilterCondition) {
@ -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)

@ -1,9 +1,10 @@
package net.pokeranalytics.android.model.interfaces
import net.pokeranalytics.android.calculus.ObjectIdentifier
import net.pokeranalytics.android.calculus.StatBase
import java.util.*
interface Timed : StatBase, Identifiable {
interface Timed : StatBase {
fun startDate() : Date?
@ -29,4 +30,6 @@ interface Timed : StatBase, Identifiable {
val hourlyDuration: Double
get() = this.netDuration / 3600000.0
val objectIdentifier : ObjectIdentifier
}

@ -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,8 +65,8 @@ open class Filter : RealmObject() {
private set
fun createOrUpdateFilterConditions(filterConditionRows: ArrayList<FilterElementRow>) {
filterConditions.clear()
filterConditionRows
val casted = arrayListOf<FilterElementRow>()
filterConditionRows
.map {
it.filterName
}
@ -77,10 +77,14 @@ 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,25 +65,18 @@ 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
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()

@ -11,10 +11,7 @@ import io.realm.annotations.LinkingObjects
import io.realm.annotations.PrimaryKey
import io.realm.kotlin.where
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.calculus.StatFormattingException
import net.pokeranalytics.android.calculus.TextFormat
import net.pokeranalytics.android.calculus.*
import net.pokeranalytics.android.exceptions.ModelException
import net.pokeranalytics.android.model.Limit
import net.pokeranalytics.android.model.LiveData
@ -35,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
@ -47,7 +44,6 @@ typealias BB = Double
open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDataSource, RowRepresentable, Timed,
TimeFilterable, Filterable {
enum class Type {
CASH_GAME,
TOURNAMENT
@ -78,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"
@ -220,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
@ -245,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
@ -482,14 +487,19 @@ 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
}
}
/**
* Return the game title
@ -508,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
/**
@ -558,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())
@ -568,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())
@ -578,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)
)
)
@ -624,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 {
@ -860,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)
}
@ -871,6 +894,11 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
}
// Timed
override val objectIdentifier: ObjectIdentifier
get() = ObjectIdentifier(this.id, Session::class.java)
}

@ -7,6 +7,7 @@ import io.realm.RealmResults
import io.realm.annotations.Ignore
import io.realm.annotations.LinkingObjects
import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.calculus.ObjectIdentifier
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.calculus.StatFormattingException
import net.pokeranalytics.android.calculus.TextFormat
@ -109,5 +110,10 @@ open class SessionSet() : RealmObject(), Timed, Filterable {
}
// Timed
override val objectIdentifier: ObjectIdentifier
get() = ObjectIdentifier(this.id, SessionSet::class.java)
}

@ -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)

@ -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())
}

@ -17,6 +17,7 @@ import com.google.android.material.chip.ChipGroup
import kotlinx.android.synthetic.main.fragment_evograph.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.GraphType
import net.pokeranalytics.android.calculus.ObjectIdentifier
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
@ -25,16 +26,11 @@ import net.pokeranalytics.android.ui.view.LegendView
import net.pokeranalytics.android.util.extensions.ChipGroupExtension
import net.pokeranalytics.android.util.extensions.px
import net.pokeranalytics.android.util.extensions.toast
interface GraphDataSource {
}
import java.text.DateFormat
class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener {
private lateinit var parentActivity: PokerAnalyticsActivity
lateinit var dataSource: GraphDataSource
private var stat: Stat = Stat.NETRESULT
private var entries: List<Entry> = ArrayList()
@ -70,7 +66,7 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener {
this.legendView = LegendView(requireContext())
this.legendContainer.addView(this.legendView)
this.legendView.prepareWithStat(this.stat)
this.legendView.prepareWithStat(this.stat, this.entries.size)
val dataSet = LineDataSet(this.entries, this.stat.name)
val colors = arrayOf(R.color.green_light).toIntArray()
@ -125,23 +121,16 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener {
e?.let { entry ->
h?.let { highlight ->
val id = entry.data as String
val item = getRealm().where(this.stat.underlyingClass).equalTo("id", id).findAll().firstOrNull()
val identifier = entry.data as ObjectIdentifier
val item = getRealm().where(identifier.clazz).equalTo("id", identifier.id).findAll().firstOrNull()
item?.let {
val date = it.startDate()
val entryStatName = this.stat.localizedTitle(requireContext())
val formattedDate = DateFormat.getDateInstance(DateFormat.SHORT).format(it.startDate())
val entryValue = it.formattedValue(this.stat, requireContext())
val totalStatName = this.stat.cumulativeLabelResId(requireContext())
val totalStatValue = this.stat.format(e.y.toDouble(), null, requireContext())
this.legendView.setItemData(this.stat, formattedDate, entryValue, totalStatValue)
}
// this.text.text = ""
}
}

@ -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
@ -70,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)
}
}

@ -8,8 +8,8 @@ import androidx.constraintlayout.widget.ConstraintLayout
import kotlinx.android.synthetic.main.layout_legend_default.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.calculus.TextFormat
import net.pokeranalytics.android.ui.view.fields.setTextFormat
/**
* Display a row session
@ -46,23 +46,22 @@ class LegendView : FrameLayout {
/**
* Set the stat data to the view
*/
fun prepareWithStat(stat: Stat) {
fun prepareWithStat(stat: Stat, counter: Int) {
this.stat1Name.text = stat.localizedTitle(context)
this.stat2Name.text = stat.cumulativeLabelResId(context)
//TODO: Set real data
this.title.text = "11/04/2019"
this.stat1Value.text = "$521"
this.stat2Value.text = "$15,051"
this.counter.text = "21 Sessions"
this.counter.text = "$counter ${context.getString(R.string.sessions)}"
}
/**
*
*/
fun setData(session: Session) {
fun setItemData(stat: Stat, title: String, statFormat1: TextFormat, statFormat2: TextFormat) {
this.title.text = title
this.stat1Value.setTextFormat(statFormat1, context)
this.stat2Value.setTextFormat(statFormat2, context)
}

@ -16,6 +16,7 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.view.fields.setTextFormat
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
/**
@ -121,8 +122,9 @@ enum class RowViewType(private var layoutRes: Int) {
itemView.findViewById<AppCompatTextView?>(R.id.value)?.let {
if (row.computedStat != null) {
val format = row.computedStat!!.format(itemView.context)
it.setTextColor(format.getColor(itemView.context))
it.text = format.text
it.setTextFormat(format, itemView.context)
// it.setTextColor(format.getColor(itemView.context))
// it.text = format.text
} else if (row.value != null) {
it.text = row.value
}
@ -229,8 +231,9 @@ enum class RowViewType(private var layoutRes: Int) {
// Value
itemView.findViewById<AppCompatTextView?>(R.id.value)?.let { view ->
adapter.dataSource.contentDescriptorForRow(row)?.textFormat?.let {
view.text = it.text
view.setTextColor(it.getColor(itemView.context))
view.setTextFormat(it, itemView.context)
// view.text = it.text
// view.setTextColor(it.getColor(itemView.context))
}
}

@ -15,7 +15,7 @@ import net.pokeranalytics.android.model.TournamentType
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.util.CurrencyUtils
import net.pokeranalytics.android.ui.view.fields.setTextFormat
import net.pokeranalytics.android.util.extensions.getDayNumber
import net.pokeranalytics.android.util.extensions.getShortDayName
import net.pokeranalytics.android.util.extensions.shortTime
@ -68,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 {
@ -85,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())
@ -149,9 +149,10 @@ 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)
rowHistorySession.gameResult.setTextColor(formattedStat.getColor(context))
rowHistorySession.gameResult.text = formattedStat.text
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
}
}

@ -10,6 +10,7 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.ui.view.fields.setTextFormat
import net.pokeranalytics.android.util.extensions.getDayNumber
import net.pokeranalytics.android.util.extensions.getShortDayName
@ -63,8 +64,9 @@ class TransactionRowView : FrameLayout {
// Amount
val formattedStat = ComputedStat(Stat.NETRESULT, transaction.amount).format(context)
rowTransaction.transactionAmount.setTextColor(formattedStat.getColor(context))
rowTransaction.transactionAmount.text = formattedStat.text
rowTransaction.transactionAmount.setTextFormat(formattedStat, context)
// rowTransaction.transactionAmount.setTextColor(formattedStat.getColor(context))
// rowTransaction.transactionAmount.text = formattedStat.text
}

@ -0,0 +1,10 @@
package net.pokeranalytics.android.ui.view.fields
import android.content.Context
import androidx.appcompat.widget.AppCompatTextView
import net.pokeranalytics.android.calculus.TextFormat
fun AppCompatTextView.setTextFormat(textFormat: TextFormat, context: Context) {
this.setTextColor(textFormat.getColor(context))
this.text = textFormat.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,8 +299,8 @@ sealed class FilterElementRow : RowRepresentable {
}
is DataFilterElementRow -> this.name
is StaticDataFilterElementRow -> this.name
is Blind -> this.name
else -> super.getDisplayName()
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,38 +160,17 @@ 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)
}
}
distinctBlinds.forEach { session ->
blinds.add(
Blind(
session.cgSmallBlind,
session.cgBigBlind,
session.bankroll?.currency?.code
)
)
session.getBlinds()
}
realm.where<Session>().distinct("blind", "bankroll.currency.code").findAll().sort("cgSmallBlind", Sort.ASCENDING).map {
it.blinds?.let { stake ->
blinds.add(Blind(stake, it.hasDefaultCurrency))
}
}
realm.close()
blinds
}
blinds
}
CASH_RE_BUY_COUNT -> arrayListOf(
ReBuyMoreThan as FilterElementRow,
ReBuyLessThan as FilterElementRow

@ -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()
}

Loading…
Cancel
Save