diff --git a/app/build.gradle b/app/build.gradle index feb0cc46..6c5c2788 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,7 +15,7 @@ repositories { android { - compileSdkVersion 30 + compileSdkVersion 32 buildToolsVersion "30.0.2" compileOptions { @@ -34,9 +34,9 @@ android { defaultConfig { applicationId "net.pokeranalytics.android" minSdkVersion 23 - targetSdkVersion 30 - versionCode 135 - versionName "5.4.11" + targetSdkVersion 32 + versionCode 136 + versionName "5.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -108,7 +108,7 @@ dependencies { implementation 'com.google.android.material:material:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' - implementation 'androidx.work:work-runtime-ktx:2.4.0' + implementation 'androidx.work:work-runtime-ktx:2.7.1' implementation 'com.google.android.play:core-ktx:1.8.1' // In-app Reviews // Places diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/FavoriteSessionUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/FavoriteSessionUnitTest.kt index 2a23d062..9cba685b 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/FavoriteSessionUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/FavoriteSessionUnitTest.kt @@ -30,12 +30,9 @@ class FavoriteSessionUnitTest : RealmInstrumentedUnitTest() { s2.endDate = Date() s3.endDate = Date() - s1.cgBigBlind = 4.0 - s1.cgSmallBlind = 2.0 - s2.cgBigBlind = 4.0 - s2.cgSmallBlind = 2.0 - s3.cgBigBlind = 1.0 - s3.cgSmallBlind = 1.0 + s1.cgBlinds = "2/4" + s2.cgBlinds = "2/4" + s3.cgBlinds = "1/2" realm.insert(s1) realm.insert(s2) @@ -45,7 +42,7 @@ class FavoriteSessionUnitTest : RealmInstrumentedUnitTest() { val favSession = FavoriteSessionFinder.favoriteSession(Session.Type.CASH_GAME.ordinal, null, realm, InstrumentationRegistry.getInstrumentation().targetContext) if (favSession != null) { - Assert.assertEquals(4.0, favSession.cgBigBlind) + Assert.assertEquals(4.0, favSession.cgBiggestBet) } else { Assert.fail("session shouldn't be null") } @@ -65,9 +62,9 @@ class FavoriteSessionUnitTest : RealmInstrumentedUnitTest() { val loc1 = realm.createObject(Location::class.java, "1") val loc2 = realm.createObject(Location::class.java, "2") - s1.cgBigBlind = 4.0 - s2.cgBigBlind = 4.0 - s3.cgBigBlind = 1.0 + s1.cgBiggestBet = 4.0 + s2.cgBiggestBet = 4.0 + s3.cgBiggestBet = 1.0 s1.location = loc1 s2.location = loc1 @@ -81,7 +78,7 @@ class FavoriteSessionUnitTest : RealmInstrumentedUnitTest() { val favSession = FavoriteSessionFinder.favoriteSession(Session.Type.CASH_GAME.ordinal, loc2, realm, InstrumentationRegistry.getInstrumentation().targetContext) if (favSession != null) { - Assert.assertEquals(1.0, favSession.cgBigBlind) + Assert.assertEquals(1.0, favSession.cgBiggestBet) } else { Assert.fail("session shouldn't be null") } diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt index 569a6eab..c98eb4b4 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt @@ -44,8 +44,8 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { s2.result?.buyin = 200.0 s2.result?.cashout = 500.0 // net result = 300 - s1.cgBigBlind = 0.5 // bb net result = -200bb - s2.cgBigBlind = 2.0 // bb net result = 150bb + s1.cgBlinds = "0.5" // bb net result = -200bb + s2.cgBlinds = "2.0" // bb net result = 150bb s2.tableSize = 5 diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/BlindFilterInstrumentedTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/BlindFilterInstrumentedTest.kt index 66ac9ec0..5ba57f99 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/BlindFilterInstrumentedTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/BlindFilterInstrumentedTest.kt @@ -28,28 +28,25 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() { b2.currency = currency val s1 = Session.testInstance(100.0, false, Date(), 1, b1) - s1.cgBigBlind = 1.0 - s1.cgSmallBlind = 0.5 + s1.cgBlinds = "0.5/1" val s2 = Session.testInstance(100.0, false, Date(), 1, b1) - s2.cgBigBlind = 1.0 - s2.cgSmallBlind = 0.5 + s2.cgBlinds = "0.5/1" val s3 = Session.testInstance(100.0, false, Date(), 1, b1) - s3.cgBigBlind = 2.0 - s3.cgSmallBlind = 1.0 + s3.cgBlinds = "1/2" realm.commitTransaction() - val filter = QueryCondition.AnyBlind() + val filter = QueryCondition.AnyStake() - val blind = QueryCondition.AnyBlind().apply { + val blind = QueryCondition.AnyStake().apply { listOfValues = arrayListOf(s1.blinds!!) } // blind.filterSectionRow = FilterSectionRow.Blind - val filterElement = FilterCondition(arrayListOf(blind), FilterSectionRow.Blind) + val filterElement = FilterCondition(arrayListOf(blind), FilterSectionRow.Stakes) filter.updateValueBy(filterElement) val sessions = Filter.queryOn(realm, Query(filter)) @@ -74,30 +71,27 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() { b2.currency = currency val s1 = Session.testInstance(100.0, false, Date(), 1, b1) - s1.cgBigBlind = 1.0 - s1.cgSmallBlind = 0.5 + s1.cgBlinds = "0.5/1" val s2 = Session.testInstance(100.0, false, Date(), 1, b1) - s2.cgBigBlind = 1.0 - s2.cgSmallBlind = 0.5 + s2.cgBlinds = "0.5/1" val s3 = Session.testInstance(100.0, false, Date(), 1, b1) - s3.cgBigBlind = 2.0 - s3.cgSmallBlind = 1.0 + s3.cgBlinds = "1/2" realm.commitTransaction() - val filter = QueryCondition.AnyBlind() + val filter = QueryCondition.AnyStake() - val blind1 = QueryCondition.AnyBlind().apply { + val blind1 = QueryCondition.AnyStake().apply { listOfValues = arrayListOf(s1.blinds!!) } - val blind2 = QueryCondition.AnyBlind().apply { + val blind2 = QueryCondition.AnyStake().apply { listOfValues = arrayListOf(s2.blinds!!) } - val filterElements = FilterCondition(arrayListOf(blind1, blind2), FilterSectionRow.Blind) + val filterElements = FilterCondition(arrayListOf(blind1, blind2), FilterSectionRow.Stakes) filter.updateValueBy(filterElements) val sessions = Filter.queryOn(realm, Query(filter)) @@ -122,28 +116,24 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() { b2.currency = currency val s1 = Session.testInstance(100.0, false, Date(), 1, b1) - - s1.cgBigBlind = 1.0 - s1.cgSmallBlind = 0.5 + s1.cgBlinds = "0.5/1" val s2 = Session.testInstance(100.0, false, Date(), 1, b1) - s2.cgBigBlind = 1.0 - s2.cgSmallBlind = 0.5 + s2.cgBlinds = "0.5/1" val s3 = Session.testInstance(100.0, false, Date(), 1, b2) - s3.cgBigBlind = 2.0 - s3.cgSmallBlind = 1.0 + s3.cgBlinds = "1/2" realm.commitTransaction() - val filter = QueryCondition.AnyBlind() + val filter = QueryCondition.AnyStake() - val blind = QueryCondition.AnyBlind().apply { + val blind = QueryCondition.AnyStake().apply { listOfValues = arrayListOf(s3.blinds!!) } - val filterElement = FilterCondition(arrayListOf(blind), FilterSectionRow.Blind) + val filterElement = FilterCondition(arrayListOf(blind), FilterSectionRow.Stakes) filter.updateValueBy(filterElement) val sessions = Filter.queryOn(realm, Query(filter)) @@ -167,31 +157,27 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() { b2.currency = currency val s1 = Session.testInstance(100.0, false, Date(), 1, b1) - s1.cgBigBlind = 1.0 - s1.cgSmallBlind = 0.5 + s1.cgBlinds = "0.5/1" val s2 = Session.testInstance(100.0, false, Date(), 1, b1) - s2.cgBigBlind = 2.0 - s2.cgSmallBlind = 1.0 + s2.cgBlinds = "0.5/1" val s3 = Session.testInstance(100.0, false, Date(), 1, b2) - s3.cgBigBlind = 2.0 - s3.cgSmallBlind = 1.0 + s3.cgBlinds = "1/2" realm.commitTransaction() + val filter = QueryCondition.AnyStake() - val filter = QueryCondition.AnyBlind() - - val blind1 = QueryCondition.AnyBlind().apply { - listOfValues = arrayListOf(s1.blinds!!) + val stake1 = QueryCondition.AnyStake().apply { + listOfValues = arrayListOf(s1.cgStakes!!) } - val blind2 = QueryCondition.AnyBlind().apply { - listOfValues = arrayListOf(s2.blinds!!) + val stake2 = QueryCondition.AnyStake().apply { + listOfValues = arrayListOf(s2.cgStakes!!) } - val filterElement = FilterCondition(arrayListOf(blind1, blind2), FilterSectionRow.Blind) + val filterElement = FilterCondition(arrayListOf(stake1, stake2), FilterSectionRow.Stakes) filter.updateValueBy(filterElement) val sessions = Filter.queryOn(realm, Query(filter)) diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/SessionFilterInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/SessionFilterInstrumentedUnitTest.kt index 1b56676b..395f4f26 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/SessionFilterInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/SessionFilterInstrumentedUnitTest.kt @@ -536,11 +536,11 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val s3 = Session.testInstance(netResult = 500.0) - s3.cgBigBlind = 2.0 + s3.cgBlinds = "2.0" s3.result!!.buyin = 1000.0 val s4 = Session.testInstance(netResult = 570.0) - s4.cgBigBlind = 5.0 + s4.cgBlinds = "5.0" s4.result!!.buyin = 200.0 realm.commitTransaction() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7e2af584..5776f99f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,7 +29,8 @@ android:name="net.pokeranalytics.android.ui.activity.HomeActivity" android:label="@string/app_name" android:launchMode="singleTop" - android:screenOrientation="portrait"> + android:screenOrientation="portrait" + android:exported="true"> @@ -42,7 +43,8 @@ + android:screenOrientation="portrait" + android:exported="true"> @@ -60,8 +62,7 @@ + android:screenOrientation="portrait" /> ()?.let { val values = it.mapNotNull { session -> when (this) { @@ -124,8 +123,8 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row is TournamentFees -> if (session.tournamentEntryFee is S) { session.tournamentEntryFee as S } else throw PokerAnalyticsException.QueryValueMapUnexpectedValue - is Blinds -> if (session.blinds is S) { - session.blinds as S + is Stakes -> if (session.cgStakes is S) { + session.cgStakes as S } else throw PokerAnalyticsException.QueryValueMapUnexpectedValue else -> null } @@ -159,7 +158,7 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row object DayPeriods : SimpleCriteria(listOf(QueryCondition.IsWeekDay, QueryCondition.IsWeekEnd), 14) object Years : ListCriteria(15) object AllMonthsUpToNow : ListCriteria(16) - object Blinds : ListCriteria(17) + object Stakes : ListCriteria(17) object TournamentFees : ListCriteria(18) object Cash : SimpleCriteria(listOf(QueryCondition.IsCash), 19) object Tournament : SimpleCriteria(listOf(QueryCondition.IsTournament), 20) @@ -237,7 +236,7 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row realm.close() years } - is Blinds -> comparison() + is Stakes -> comparison() is ListCustomFields -> comparison() is ValueCustomFields -> { val realm = Realm.getDefaultInstance() @@ -271,7 +270,7 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row DayPeriods -> R.string.weekdays_or_weekend Years -> R.string.year AllMonthsUpToNow -> R.string.month - Blinds -> R.string.blind + Stakes -> R.string.blind TournamentFees -> R.string.entry_fees // is ListCustomFields -> this.customField.resId // is ValueCustomFields -> this.customField.resId @@ -284,13 +283,13 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row inline fun , reified T : NameManageable> compare(): List { val objects = mutableListOf() val realm = Realm.getDefaultInstance() - realm.where().findAll().forEach { + realm.where().sort("name").findAll().forEach { val condition = (QueryCondition.getInstance() as S).apply { setObject(it) } objects.add(condition) } - objects.sorted() +// objects.sort() realm.close() return objects.map { Query(it) } } @@ -303,7 +302,7 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row } objects.add(condition) } - objects.sorted() + objects.sort() return objects.map { Query(it) } } @@ -319,7 +318,8 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row TournamentFeatures, Limits, TableSizes, TournamentTypes, MonthsOfYear, DaysOfWeek, SessionTypes, BankrollTypes, DayPeriods, Years, - AllMonthsUpToNow, Blinds, TournamentFees + AllMonthsUpToNow, + Stakes, TournamentFees ) } } diff --git a/app/src/main/java/net/pokeranalytics/android/model/Stakes.kt b/app/src/main/java/net/pokeranalytics/android/model/Stakes.kt new file mode 100644 index 00000000..8dc72a94 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/model/Stakes.kt @@ -0,0 +1,13 @@ +package net.pokeranalytics.android.model + +data class Stakes(var blinds: String?, var ante: Double?) { + + companion object { + + } + + + + + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/extensions/SessionExtensions.kt b/app/src/main/java/net/pokeranalytics/android/model/extensions/SessionExtensions.kt index 487da82f..325a9200 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/extensions/SessionExtensions.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/extensions/SessionExtensions.kt @@ -75,8 +75,8 @@ fun Session.getFormattedGameType(context: Context): String { parameters.add(context.getString(R.string.tournament).capitalize()) } } else { - if (cgSmallBlind != null && cgBigBlind != null) { - parameters.add(getFormattedBlinds()) + if (this.cgAnte != null || this.cgBlinds != null) { + parameters.add(getFormattedStakes()) } game?.let { parameters.add(getFormattedGame()) diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt index 27316d15..ebf26095 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt @@ -12,8 +12,10 @@ import net.pokeranalytics.android.exceptions.PokerAnalyticsException import net.pokeranalytics.android.model.Limit import net.pokeranalytics.android.model.TableSize import net.pokeranalytics.android.model.TournamentType +import net.pokeranalytics.android.model.interfaces.CodedStake import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable +import net.pokeranalytics.android.model.interfaces.StakesHolder import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType import net.pokeranalytics.android.ui.view.RowRepresentable @@ -322,6 +324,7 @@ sealed class QueryCondition : RowRepresentable { val query = realm.where(entity) return query.equalTo("id", value).findFirst()?.name ?: NULL_TEXT } + } interface DateTime { @@ -458,10 +461,20 @@ sealed class QueryCondition : RowRepresentable { } } - class AnyBlind : ListOfString() { + class AnyStake : ListOfString() { + + override fun labelForValue(value: String, context: Context): String { + return StakesHolder.readableStakes(value) + } + override fun entityName(context: Context): String { - return context.getString(R.string.blinds) + return context.getString(R.string.stakes) } + + override fun compareTo(other: ListOfValues): Int { + return CodedStake(this.listOfValues.first()).compareTo(CodedStake(other.listOfValues.first())) + } + } class NumberOfTable : ListOfInt() { @@ -615,7 +628,7 @@ sealed class QueryCondition : RowRepresentable { object DateNotNull : NotNullQueryCondition() object EndDateNotNull : NotNullQueryCondition() - object BigBlindNotNull : NotNullQueryCondition() + object BiggestBetNotNull : NotNullQueryCondition() class StartedFromTime(date: Date) : TimeQuery(date) { override var operator = Operator.MORE diff --git a/app/src/main/java/net/pokeranalytics/android/model/handhistory/HandSetup.kt b/app/src/main/java/net/pokeranalytics/android/model/handhistory/HandSetup.kt index af8c7897..81b32b3d 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/handhistory/HandSetup.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/handhistory/HandSetup.kt @@ -6,7 +6,6 @@ import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.util.extensions.findById import timber.log.Timber -import java.util.* class HandSetup { @@ -36,9 +35,31 @@ class HandSetup { } + var type: Session.Type? = null + + var blinds: String? = null + +// var bigBlind: Double? = null + + var ante: Double? = null + + var tableSize: Int? = null + + var bigBlindAnte: Boolean = false + + var game: Game? = null + + var session: Session? = null + + var straddlePositions: MutableList = mutableListOf() + private set + + fun clearStraddles() { + this.straddlePositions.clear() + } + private fun configure(handHistory: HandHistory) { - this.smallBlind = handHistory.smallBlind - this.bigBlind = handHistory.bigBlind + this.blinds = handHistory.blinds this.bigBlindAnte = handHistory.bigBlindAnte this.ante = handHistory.ante this.tableSize = handHistory.numberOfPlayers @@ -56,32 +77,15 @@ class HandSetup { this.game = session.game // we don't want to force the max number of cards if unsure } this.type = session.sessionType - this.smallBlind = session.cgSmallBlind - this.bigBlind = session.cgBigBlind + this.blinds = session.cgBlinds + this.ante = session.cgAnte this.tableSize = session.tableSize - } - - var type: Session.Type? = null - - var smallBlind: Double? = null - - var bigBlind: Double? = null - - var ante: Double? = null - - var tableSize: Int? = null - - var bigBlindAnte: Boolean = false - - var game: Game? = null - - var session: Session? = null - var straddlePositions: MutableList = mutableListOf() - private set + val blindValues = session.blindValues + if (blindValues.size > 2) { + this.straddlePositions = Position.positionsPerPlayers(10).drop(2).take(blindValues.size - 2).toMutableList() + } - fun clearStraddles() { - this.straddlePositions.clear() } /*** diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/StakesHolder.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/StakesHolder.kt new file mode 100644 index 00000000..eae6fdc4 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/model/interfaces/StakesHolder.kt @@ -0,0 +1,186 @@ +package net.pokeranalytics.android.model.interfaces + +import net.pokeranalytics.android.model.realm.Bankroll +import net.pokeranalytics.android.util.BLIND_SEPARATOR +import net.pokeranalytics.android.util.NULL_TEXT +import net.pokeranalytics.android.util.UserDefaults +import net.pokeranalytics.android.util.extensions.formatted +import net.pokeranalytics.android.util.extensions.toCurrency +import java.lang.Integer.min +import java.text.NumberFormat +import java.text.ParseException +import java.util.* + +data class CodedStake(var stakes: String) : Comparable { + + var ante: Double? = null + var blinds: String? = null + var currency: Currency + + init { + + var currencyCode: String? = null + + val parameters = this.stakes.split(StakesHolder.cbSeparator) + parameters.forEach { param -> + when { + param.contains(StakesHolder.cbAnte) -> ante = param.removePrefix(StakesHolder.cbAnte).let { NumberFormat.getInstance().parse(it)?.toDouble() } + param.contains(StakesHolder.cbBlinds) -> blinds = param.removePrefix(StakesHolder.cbBlinds) + param.contains(StakesHolder.cbCode) -> currencyCode = param.removePrefix( + StakesHolder.cbCode + ) + } + } + + this.currency = currencyCode?.let { Currency.getInstance(it) } + ?: run { UserDefaults.currency } + + } + + override fun compareTo(other: CodedStake): Int { + + if (this.currency == other.currency) { + + this.blinds?.let { b1 -> + other.blinds?.let { b2 -> + if (b1 == b2) { + return this.compareAnte(other) + } else { + val bv1 = this.reversedBlindsArray(b1) + val bv2 = this.reversedBlindsArray(b2) + + for (i in 0 until min(bv1.size, bv2.size)) { + if (bv1[i] != bv2[i]) { + return bv1[i].compareTo(bv2[i]) + } else { + continue + } + } + return bv1.size.compareTo(bv2.size) + } + } ?: run { + return 1 + } + + } ?: run { + return this.compareAnte(other) + } + } else { + return this.currency.currencyCode.compareTo(other.currency.currencyCode) + } + + } + + private fun compareAnte(other: CodedStake): Int { + this.ante?.let { a1 -> + other.ante?.let { a2 -> + return a1.compareTo(a2) + } ?: run { + return 1 + } + } ?: run { + return -1 + } + } + + private fun reversedBlindsArray(blinds: String): List { + return blinds.split(BLIND_SEPARATOR).mapNotNull { NumberFormat.getInstance().parse(it)?.toDouble() }.reversed() + } + + fun formattedStakes(): String { + val components = arrayListOf() + this.formattedBlinds()?.let { components.add(it) } + this.formattedAnte()?.let { components.add("($it)") } + + return if (components.isNotEmpty()) { + components.joinToString(" ") + } else { + NULL_TEXT + } + } + + private fun formattedBlinds(): String? { + this.blinds?.let { + val placeholder = 1.0 + val regex = Regex("-?\\d+(\\.\\d+)?") + return placeholder.toCurrency(currency).replace(regex, it) + } + return null + } + + private fun formattedAnte(): String? { + this.ante?.let { + return it.toCurrency(this.currency) + } + return null + } + +} + + +interface StakesHolder { + + companion object { + + const val cbSeparator = ";" + const val cbAnte = "A=" + const val cbBlinds = "B=" + const val cbCode = "C=" + + fun readableStakes(value: String): String { + return CodedStake(value).formattedStakes() + } + + } + + val ante: Double? + val blinds: String? + val biggestBet: Double? + val stakes: String? + + val bankroll: Bankroll? + + fun setHolderStakes(stakes: String?) + fun setHolderBiggestBet(biggestBet: Double?) + + val blindValues: List + get() { + this.blinds?.let { blinds -> + val blindsSplit = blinds.split(BLIND_SEPARATOR) + return blindsSplit.mapNotNull { + try { + NumberFormat.getInstance().parse(it)?.toDouble() + } catch (e: ParseException) { + null + } + } + } + return listOf() + } + + fun generateStakes() { + + if (this.ante == null && this.blinds == null) { + setHolderStakes(null) + return + } + + val components = arrayListOf() + + this.blinds?.let { components.add("${cbBlinds}${it}") } + this.ante?.let { components.add("${cbAnte}${it.formatted}") } + + val code = this.bankroll?.currency?.code ?: UserDefaults.currency.currencyCode + components.add("${cbCode}${code}") + + setHolderStakes(components.joinToString(cbSeparator)) + } + + fun defineHighestBet() { + val bets = arrayListOf() + this.ante?.let { bets.add(it) } + bets.addAll(this.blindValues) + setHolderBiggestBet(bets.maxOrNull()) + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/migrations/Patcher.kt b/app/src/main/java/net/pokeranalytics/android/model/migrations/Patcher.kt index a822febc..3f6a2a11 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/migrations/Patcher.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/migrations/Patcher.kt @@ -5,9 +5,12 @@ import io.realm.Realm import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.realm.* +import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.model.utils.Seed import net.pokeranalytics.android.model.utils.SessionSetManager +import net.pokeranalytics.android.util.BLIND_SEPARATOR import net.pokeranalytics.android.util.Preferences +import java.text.NumberFormat class Patcher { @@ -32,8 +35,8 @@ class Patcher { Preferences.executeOnce(Preferences.Keys.PATCH_TRANSACTION_TYPES_NAMES, context) { patchDefaultTransactionTypes(context) } - Preferences.executeOnce(Preferences.Keys.PATCH_BLINDS_FORMAT, context) { - patchBlindFormat() + Preferences.executeOnce(Preferences.Keys.PATCH_STAKES, context) { + patchStakes() } Preferences.executeOnce(Preferences.Keys.PATCH_NEGATIVE_LIMITS, context) { patchNegativeLimits() @@ -98,7 +101,8 @@ class Patcher { it.computeStats() } sessions.forEach { - it.formatBlinds() + it.generateStakes() + it.defineHighestBet() } results.forEach { it.computeNumberOfRebuy() @@ -123,13 +127,28 @@ class Patcher { realm.close() } - private fun patchBlindFormat() { + private fun patchStakes() { val realm = Realm.getDefaultInstance() realm.executeTransaction { val sessions = realm.where(Session::class.java).findAll() sessions.forEach { session -> - session.formatBlinds() + val blinds = arrayListOf(session.cgOldSmallBlind, session.cgOldBigBlind).filterNotNull() + val blindsFormatted = blinds.map { NumberFormat.getInstance().format(it) } + session.cgAnte = null + if (blindsFormatted.isNotEmpty()) { + session.cgBlinds = blindsFormatted.joinToString(BLIND_SEPARATOR) + } } + + val handHistories = realm.where(HandHistory::class.java).findAll() + handHistories.forEach { hh -> + val blinds = arrayListOf(hh.oldSmallBlind, hh.oldBigBlind).filterNotNull() + val blindsFormatted = blinds.map { NumberFormat.getInstance().format(it) } + if (blindsFormatted.isNotEmpty()) { + hh.blinds = blindsFormatted.joinToString(BLIND_SEPARATOR) + } + } + } realm.close() } diff --git a/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt b/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt index 6644d5e9..04e1fba9 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt @@ -252,6 +252,36 @@ class PokerAnalyticsMigration : RealmMigration { currentVersion++ } + // Migrate to version 12 + if (currentVersion == 11) { + + schema.get("Session")?.let { ss -> + + ss.addField("cgAnte", Double::class.java) + ?.setNullable("cgAnte", true) + ss.addField("cgBiggestBet", Double::class.java) + ?.setNullable("cgBiggestBet", true) + ss.addField("cgStakes", String::class.java) + ss.addField("cgBlinds", String::class.java) + ss.removeField("blinds") + + ss.renameField("cgSmallBlind", "cgOldSmallBlind") + ss.renameField("cgBigBlind", "cgOldBigBlind") + } + + schema.get("HandHistory")?.let { hs -> + hs.setNullable("ante", true) + hs.addField("stakes", String::class.java) + hs.addField("blinds", String::class.java) + hs.addField("biggestBet", Double::class.java) + ?.setNullable("biggestBet", true) + hs.renameField("smallBlind", "oldSmallBlind") + hs.renameField("bigBlind", "oldBigBlind") + } + + currentVersion++ + } + } override fun equals(other: Any?): Boolean { diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt index 40ba08b5..28a6be15 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt @@ -36,7 +36,7 @@ open class ComputableResult : RealmObject(), Filterable { } this.bbNet = session.bbNet - this.hasBigBlind = if (session.cgBigBlind != null) 1 else 0 + this.hasBigBlind = if (session.cgBiggestBet != null) 1 else 0 this.estimatedHands = session.estimatedHands this.bbPer100Hands = session.bbNet / (session.numberOfHandsPerHour * session.hourlyDuration) * 100 diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt index bad54e3e..ce63e633 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Result.kt @@ -150,7 +150,7 @@ open class Result : RealmObject(), Filterable { fun computeNumberOfRebuy() { this.session?.let { if (it.isCashGame()) { - it.cgBigBlind?.let { bb -> + it.cgBiggestBet?.let { bb -> if (bb > 0.0) { this.numberOfRebuy = (this.buyin ?: 0.0) / (bb * 100.0) } else { diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt index 9b415e4a..81952e0a 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt @@ -16,6 +16,7 @@ import net.pokeranalytics.android.calculus.StatFormattingException import net.pokeranalytics.android.exceptions.ModelException import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.Limit +import net.pokeranalytics.android.model.Stakes import net.pokeranalytics.android.model.TableSize import net.pokeranalytics.android.model.TournamentType import net.pokeranalytics.android.model.extensions.SessionState @@ -26,24 +27,26 @@ import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.filter.QueryCondition.* import net.pokeranalytics.android.model.interfaces.* import net.pokeranalytics.android.model.realm.handhistory.HandHistory -import net.pokeranalytics.android.util.CrashLogging import net.pokeranalytics.android.model.utils.SessionSetManager import net.pokeranalytics.android.ui.adapter.UnmanagedRowRepresentableException import net.pokeranalytics.android.ui.graph.Graph import net.pokeranalytics.android.ui.view.* import net.pokeranalytics.android.ui.view.rows.SessionPropertiesRow -import net.pokeranalytics.android.util.NULL_TEXT -import net.pokeranalytics.android.util.TextFormat -import net.pokeranalytics.android.util.UserDefaults -import net.pokeranalytics.android.util.extensions.* +import net.pokeranalytics.android.util.* +import net.pokeranalytics.android.util.extensions.hourMinute +import net.pokeranalytics.android.util.extensions.shortDateTime +import net.pokeranalytics.android.util.extensions.toCurrency +import net.pokeranalytics.android.util.extensions.toMinutes import java.text.DateFormat +import java.text.NumberFormat +import java.text.ParseException import java.util.* import java.util.Currency typealias BB = Double open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Timed, - TimeFilterable, Filterable, DatedBankrollGraphEntry { + TimeFilterable, Filterable, DatedBankrollGraphEntry, StakesHolder { enum class Type(val value: String) { CASH_GAME("Cash Game"), @@ -96,7 +99,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim AnyLimit::class.java -> "limit" AnyTableSize::class.java -> "tableSize" AnyTournamentType::class.java -> "tournamentType" - AnyBlind::class.java -> "blinds" + AnyStake::class.java -> "cgStakes" NumberOfTable::class.java -> "numberOfTables" NetAmountWon::class.java, NetAmountLost::class.java -> "computableResults.ratedNet" NumberOfRebuy::class.java -> "result.numberOfRebuy" @@ -118,7 +121,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim CustomFieldQuery::class.java -> "customFieldEntries.customFields.id" DateNotNull::class.java -> "startDate" EndDateNotNull::class.java -> "endDate" - BigBlindNotNull::class.java -> "cgBigBlind" + BiggestBetNotNull::class.java -> "cgBiggestBet" else -> null } } @@ -264,7 +267,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim override var bankroll: Bankroll? = null set(value) { field = value - this.formatBlinds() + this.generateStakes() this.computeStats() // this.updateRowRepresentation() } @@ -290,6 +293,10 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim // The number of tables played at the same time var numberOfTables: Int = 1 + set(value) { + field = value + this.computeStats() + } // The hand histories of the session @LinkingObjects("session") @@ -304,23 +311,43 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim // Cash Game // The small blind value - var cgSmallBlind: Double? = null + var cgOldSmallBlind: Double? = null set(value) { field = value - formatBlinds() } // The big blind value - var cgBigBlind: Double? = null + var cgOldBigBlind: Double? = null + set(value) { + field = value + this.computeStats() + this.result?.computeNumberOfRebuy() + } + +// var blinds: String? = null +// private set + + var cgAnte: Double? = null set(value) { field = value + this.generateStakes() + this.defineHighestBet() + this.computeStats() + this.result?.computeNumberOfRebuy() + } + + var cgBlinds: String? = null + set(value) { + field = cleanupBlinds(value) + this.generateStakes() + this.defineHighestBet() this.computeStats() - formatBlinds() this.result?.computeNumberOfRebuy() } - var blinds: String? = null - private set + var cgBiggestBet: Double? = null + + var cgStakes: String? = null // Tournament @@ -354,7 +381,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim } fun bankrollHasBeenUpdated() { - formatBlinds() + this.generateStakes() } /** @@ -405,7 +432,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim */ val bbNet: BB get() { - val bb = this.cgBigBlind + val bb = this.cgBiggestBet val result = this.result return if (bb != null && result != null) { result.net / bb @@ -474,7 +501,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim val tableSize = this.tableSize ?: 9 // 9 is the default table size if null val config = UserConfig.getConfiguration(this.realm) val playerHandsPerHour = if (this.isLive) config.liveDealtHandsPerHour else config.onlineDealtHandsPerHour - return playerHandsPerHour / tableSize.toDouble() + return this.numberOfTables * playerHandsPerHour / tableSize.toDouble() } val hourlyRate: Double @@ -646,23 +673,42 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim return if (gameTitle.isNotBlank()) gameTitle else NULL_TEXT } - fun getFormattedBlinds(): String { - return blinds ?: NULL_TEXT + fun getFormattedStakes(): String { + + return this.cgStakes?.let { StakesHolder.readableStakes(it) } ?: run { NULL_TEXT } + +// +// val formattedBlinds = StakesHolder.formattedBlinds(this.cgBlinds, this.currency) +// val formattedAntes = StakesHolder.formattedAnte(this.cgAnte, this.currency) +// +// return StakesHolder.formattedStakes(formattedBlinds, formattedAntes) + +// +// +// val components = arrayListOf() +// this.formattedBlinds?.let { components.add(it) } +// this.formattedAnte?.let { components.add("($it)") } +// +// return if (components.isNotEmpty()) { +// components.joinToString(" ") +// } else { +// NULL_TEXT +// } } - fun formatBlinds() { - blinds = null - if (cgBigBlind == null) return - cgBigBlind?.let { bb -> - val sb = cgSmallBlind ?: bb / 2.0 - val preFormattedBlinds = "${sb.formatted}/${bb.round()}" - println("<<<<<< bb.toCurrency(currency) : ${bb.toCurrency(currency)}") - println("<<<<<< preFormattedBlinds : $preFormattedBlinds") - val regex = Regex("-?\\d+(\\.\\d+)?") - blinds = bb.toCurrency(currency).replace(regex, preFormattedBlinds) - println("<<<<<< blinds = $blinds") - } - } +// fun formatBlinds() { +// blinds = null +// if (cgBigBlind == null) return +// cgBigBlind?.let { bb -> +// val sb = cgSmallBlind ?: bb / 2.0 +// val preFormattedBlinds = "${sb.formatted}/${bb.round()}" +// println("<<<<<< bb.toCurrency(currency) : ${bb.toCurrency(currency)}") +// println("<<<<<< preFormattedBlinds : $preFormattedBlinds") +// val regex = Regex("-?\\d+(\\.\\d+)?") +// blinds = bb.toCurrency(currency).replace(regex, preFormattedBlinds) +// println("<<<<<< blinds = $blinds") +// } +// } // LifeCycle @@ -703,8 +749,8 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim copy.game = this.game copy.limit = this.limit - copy.cgSmallBlind = this.cgSmallBlind - copy.cgBigBlind = this.cgBigBlind + copy.cgBiggestBet = this.cgBiggestBet + copy.cgAnte = this.cgAnte copy.tournamentEntryFee = this.tournamentEntryFee copy.tournamentFeatures = this.tournamentFeatures copy.tournamentName = this.tournamentName @@ -726,27 +772,36 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim when (row) { SessionPropertiesRow.BANKROLL -> bankroll = value as Bankroll? - SessionPropertiesRow.BLINDS -> if (value is ArrayList<*>) { - cgSmallBlind = try { - (value[0] as String? ?: "0").toDouble() - } catch (e: Exception) { - null - } + SessionPropertiesRow.STAKES -> if (value is Stakes) { - cgBigBlind = try { - (value[1] as String? ?: "0").toDouble() - } catch (e: Exception) { - null + if (value.ante != null) { + this.cgAnte = value.ante } - cgBigBlind?.let { - if (cgSmallBlind == null || cgSmallBlind == 0.0) { - cgSmallBlind = it / 2.0 - } + if (value.blinds != null) { + this.cgBlinds = value.blinds } + +// cgSmallBlind = try { +// (value[0] as String? ?: "0").toDouble() +// } catch (e: Exception) { +// null +// } +// +// cgBigBlind = try { +// (value[1] as String? ?: "0").toDouble() +// } catch (e: Exception) { +// null +// } +// +// cgBigBlind?.let { +// if (cgSmallBlind == null || cgSmallBlind == 0.0) { +// cgSmallBlind = it / 2.0 +// } +// } } else if (value == null) { - cgSmallBlind = null - cgBigBlind = null + this.cgBlinds = null + this.cgAnte = null } SessionPropertiesRow.BREAK_TIME -> { this.breakDuration = (value as Double? ?: 0.0).toLong() * 60 * 1000 @@ -827,6 +882,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim } } SessionPropertiesRow.HANDS_COUNT -> handsCount = (value as Double?)?.toInt() + SessionPropertiesRow.NUMBER_OF_TABLES -> this.numberOfTables = (value as Double?)?.toInt() ?: 1 is CustomField -> { customFieldEntries.filter { it.customField?.id == row.id }.let { customFieldEntries.removeAll(it) @@ -964,7 +1020,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim return when (row) { SessionPropertiesRow.BANKROLL -> bankroll?.name ?: NULL_TEXT - SessionPropertiesRow.BLINDS -> getFormattedBlinds() + SessionPropertiesRow.STAKES -> getFormattedStakes() SessionPropertiesRow.BREAK_TIME -> if (this.breakDuration > 0.0) this.breakDuration.toMinutes() else NULL_TEXT SessionPropertiesRow.BUY_IN -> this.result?.buyin?.toCurrency(currency) ?: NULL_TEXT SessionPropertiesRow.CASHED_OUT, SessionPropertiesRow.PRIZE -> this.result?.cashout?.toCurrency(currency) ?: NULL_TEXT @@ -1002,6 +1058,7 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim SessionPropertiesRow.TOURNAMENT_NAME -> tournamentName?.name ?: NULL_TEXT SessionPropertiesRow.HANDS -> this.handHistories?.size.toString() SessionPropertiesRow.HANDS_COUNT -> this.handsCountFormatted(context) + SessionPropertiesRow.NUMBER_OF_TABLES -> this.numberOfTables.toString() is CustomField -> { customFieldEntries.find { it.customField?.id == row.id }?.let { customFieldEntry -> return customFieldEntry.getFormattedValue(currency) @@ -1026,4 +1083,73 @@ open class Session : RealmObject(), Savable, RowUpdatable, RowRepresentable, Tim this.result?.netResult = null } + /// Stakes + +// fun generateStakes() { +// +// if (this.cgAnte == null && this.cgAnte == null) { +// this.cgStakes = null +// return +// } +// +// val components = arrayListOf() +// +// this.cgBlinds?.let { components.add("${cbBlinds}${it}") } +// this.cgAnte?.let { components.add("${cbAnte}${it.formatted}") } +// +// val code = this.bankroll?.currency?.code ?: UserDefaults.currency.currencyCode +// components.add("${cbCode}${code}") +// +// this.cgStakes = components.joinToString(cbSeparator) +// } +// +// fun defineHighestBet() { +// val bets = arrayListOf() +// this.cgAnte?.let { bets.add(it) } +// bets.addAll(this.blindValues) +// this.cgBiggestBet = bets.maxOrNull() +// } + + private fun cleanupBlinds(blinds: String?): String? { + + if (blinds == null) { + return null + } + + val blindValues = blinds.split(BLIND_SEPARATOR).mapNotNull { + try { + NumberFormat.getInstance().parse(it) + } catch (e: ParseException) { + null + } + } + return if (blindValues.isNotEmpty()) { + blindValues.joinToString(BLIND_SEPARATOR) + } else { + null + } + } + + /// StakesHolder + + override val ante: Double? + get() { return this.cgAnte } + + override val blinds: String? + get() { return this.cgBlinds } + + override val biggestBet: Double? + get() { return this.cgBiggestBet } + + override val stakes: String? + get() { return this.cgStakes } + + override fun setHolderStakes(stakes: String?) { + this.cgStakes = stakes + } + + override fun setHolderBiggestBet(biggestBet: Double?) { + this.cgBiggestBet = biggestBet + } + } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt index 9b8549d9..3dfbbfdd 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt @@ -15,10 +15,8 @@ import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.handhistory.HandSetup import net.pokeranalytics.android.model.handhistory.Position import net.pokeranalytics.android.model.handhistory.Street -import net.pokeranalytics.android.model.interfaces.Deletable -import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus -import net.pokeranalytics.android.model.interfaces.Identifiable -import net.pokeranalytics.android.model.interfaces.TimeFilterable +import net.pokeranalytics.android.model.interfaces.* +import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.modules.handhistory.evaluator.EvaluatorBridge import net.pokeranalytics.android.ui.modules.handhistory.model.ActionReadRow @@ -35,7 +33,7 @@ import kotlin.math.max data class PositionAmount(var position: Int, var amount: Double, var isAllin: Boolean) open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, TimeFilterable, - CardHolder, Comparator { + CardHolder, Comparator, StakesHolder { @PrimaryKey override var id = UUID.randomUUID().toString() @@ -64,34 +62,67 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, /*** * The small blind */ - var smallBlind: Double? = null + var oldSmallBlind: Double? = null set(value) { field = value - if (this.bigBlind == null && value != null) { - this.bigBlind = value * 2 - } +// if (this.bigBlind == null && value != null) { +// this.bigBlind = value * 2 +// } } /*** * The big blind */ - var bigBlind: Double? = null + var oldBigBlind: Double? = null set(value) { field = value - if (this.smallBlind == null && value != null) { - this.smallBlind = value / 2 - } +// if (this.smallBlind == null && value != null) { +// this.smallBlind = value / 2 +// } } + /*** + * Big blind ante + */ + var bigBlindAnte: Boolean = false + /*** * The ante */ - var ante: Double = 0.0 + override var ante: Double? = 0.0 + set(value) { + field = value + this.generateStakes() + this.defineHighestBet() + } + + /*** + * The blinds + */ + override var blinds: String? = null + set(value) { + field = value + this.generateStakes() + this.defineHighestBet() + } + + override var biggestBet: Double? = null /*** - * Big blind ante + * The coded stakes */ - var bigBlindAnte: Boolean = false + override var stakes: String? = null + + override val bankroll: Bankroll? + get() { return this.session?.bankroll } + + override fun setHolderStakes(stakes: String?) { + this.stakes = stakes + } + + override fun setHolderBiggestBet(biggestBet: Double?) { + this.biggestBet = biggestBet + } /*** * Number of players in the hand @@ -164,8 +195,8 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, this.playerSetups.removeAll(this.playerSetups) handSetup.tableSize?.let { this.numberOfPlayers = it } - handSetup.smallBlind?.let { this.smallBlind = it } - handSetup.bigBlind?.let { this.bigBlind = it } + handSetup.ante?.let { this.ante = it } + handSetup.blinds?.let { this.blinds = it } this.session = handSetup.session this.date = this.session?.handHistoryAutomaticDate ?: Date() @@ -180,18 +211,32 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, this.actions.clear() - this.addAction(0, Action.Type.POST_SB, this.smallBlind) - this.addAction(1, Action.Type.POST_BB, this.bigBlind) - -// var lastStraddler: Int? = null + var blindValues = this.blindValues + if (blindValues.isNotEmpty()) { + blindValues.forEachIndexed { index, blind -> + val action = when(index) { + 0 -> Action.Type.POST_SB + 1 -> Action.Type.POST_BB + else -> null + } + action?.let { this.addAction(index, action, blind) } + } + } else { + this.addAction(0, Action.Type.POST_SB, this.oldSmallBlind) + this.addAction(1, Action.Type.POST_BB, this.oldBigBlind) + } + blindValues = blindValues.drop(2) val positions = Position.positionsPerPlayers(this.numberOfPlayers) - handSetup.straddlePositions.forEach { position -> // position are sorted here + handSetup.straddlePositions.forEachIndexed { index, position -> // position are sorted here val positionIndex = positions.indexOf(position) - this.addAction(positionIndex, Action.Type.STRADDLE) -// lastStraddler = positionIndex + val amount = if (index < blindValues.size) { blindValues[index] } else null + this.addAction(positionIndex, Action.Type.STRADDLE, amount) } +// var lastStraddler: Int? = null + + // val totalActions = this.actions.size // val startingPosition = lastStraddler?.let { it + 1 } ?: totalActions @@ -237,9 +282,9 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, val anteSum: Double get() { return if (bigBlindAnte) { - this.bigBlind ?: 0.0 + this.biggestBet ?: 0.0 } else { - this.ante * this.numberOfPlayers + (this.ante ?: 0.0) * this.numberOfPlayers } } @@ -303,14 +348,20 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, val players = "${this.numberOfPlayers} ${context.getString(R.string.players)}" val firstLineComponents = mutableListOf(this.date.fullDate(), players) - this.smallBlind?.let { sb -> - this.bigBlind?.let { bb -> - firstLineComponents.add("${sb.formatted}/${bb.formatted}") + this.blinds?.let { firstLineComponents.add(it) } + +// this.smallBlind?.let { sb -> +// this.bigBlind?.let { bb -> +// firstLineComponents.add("${sb.formatted}/${bb.formatted}") +// } +// } + + this.ante?.let { + if (it > 0.0) { + firstLineComponents.add("ante ${this.ante}") } } - if (this.ante > 0.0) { - firstLineComponents.add("ante ${this.ante}") - } + string = string.plus(firstLineComponents.joinToString(" - ")) string = string.addLineReturn(2) @@ -373,12 +424,12 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, fun anteForPosition(position: Position): Double { return if (this.bigBlindAnte) { if (position == Position.BB) { - this.bigBlind ?: 0.0 + this.biggestBet ?: 0.0 } else { 0.0 } } else { - this.ante + this.ante ?: 0.0 } } @@ -394,7 +445,11 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, val heroString = context.getString(R.string.hero) playerItems.add("- $heroString") } - playerItems.add("[${playerSetup.cards.formatted(context)}]") + + if (playerSetup.cards.isNotEmpty()) { + playerItems.add("[${playerSetup.cards.formatted(context)}]") + } + playerSetup.stack?.let { stack -> playerItems.add("- $stack") } diff --git a/app/src/main/java/net/pokeranalytics/android/model/utils/DataUtils.kt b/app/src/main/java/net/pokeranalytics/android/model/utils/DataUtils.kt index 2e0bd3a6..e342d746 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/utils/DataUtils.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/utils/DataUtils.kt @@ -11,15 +11,18 @@ class DataUtils { companion object { /** - * Returns true if the provided parameters doesn't correspond to an existing session + * Returns the number of sessions corresponding to the provided parameters */ - fun sessionCount(realm: Realm, startDate: Date, endDate: Date, net: Double): Int { - val sessions = realm.where(Session::class.java) + fun sessionCount(realm: Realm, startDate: Date, endDate: Date?, net: Double): Int { + var sessionQuery = realm.where(Session::class.java) .equalTo("startDate", startDate) - .equalTo("endDate", endDate) .equalTo("result.net", net) - .findAll() - return sessions.size + + endDate?.let { + sessionQuery = sessionQuery.equalTo("endDate", it) + } + + return sessionQuery.findAll().size } /** diff --git a/app/src/main/java/net/pokeranalytics/android/model/utils/FavoriteSessionFinder.kt b/app/src/main/java/net/pokeranalytics/android/model/utils/FavoriteSessionFinder.kt index ff122db3..fe40b2bb 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/utils/FavoriteSessionFinder.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/utils/FavoriteSessionFinder.kt @@ -39,7 +39,7 @@ private fun Session.significantFields(): List { Session.Type.CASH_GAME.ordinal -> { return listOf( SessionPropertiesRow.GAME, - SessionPropertiesRow.BLINDS, + SessionPropertiesRow.STAKES, SessionPropertiesRow.BANKROLL, SessionPropertiesRow.TABLE_SIZE ) @@ -86,8 +86,8 @@ class FavoriteSessionFinder { when (session.type) { Session.Type.CASH_GAME.ordinal -> { - session.cgSmallBlind = fav.cgSmallBlind - session.cgBigBlind = fav.cgBigBlind + session.cgAnte = fav.cgAnte + session.cgBlinds = fav.cgBlinds } Session.Type.TOURNAMENT.ordinal -> { session.tournamentEntryFee = fav.tournamentEntryFee diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt index b4c56d5d..a01560de 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt @@ -31,7 +31,9 @@ class ImportFragment : RealmFragment(), ImportDelegate { private var _binding: FragmentImportBinding? = null private val binding get() = _binding!! - // Life Cycle + private val exceptions: MutableList = mutableListOf() + + // Life Cycle override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { super.onCreateView(inflater, container, savedInstanceState) @@ -44,7 +46,6 @@ class ImportFragment : RealmFragment(), ImportDelegate { _binding = null } - fun setData(path: String) { this.filePath = path } @@ -90,7 +91,6 @@ class ImportFragment : RealmFragment(), ImportDelegate { this.importer = CSVImporter(inputStream) this.importer.delegate = this - var exception: Exception? = null GlobalScope.launch(coroutineContext) { @@ -98,11 +98,8 @@ class ImportFragment : RealmFragment(), ImportDelegate { val s = Date() Timber.d(">>> Start Import...") - try { - importer.start() - } catch (e: Exception) { - exception = e - } + importer.start() + val e = Date() val duration = (e.time - s.time) / 1000.0 Timber.d(">>> Import ended in $duration seconds") @@ -110,9 +107,9 @@ class ImportFragment : RealmFragment(), ImportDelegate { } test.await() - val exceptionMessage = exception?.message + val exceptionMessage = exceptions.firstOrNull()?.message if (exceptionMessage != null && view != null) { - val message = exceptionMessage + ". " + requireContext().getString(R.string.import_error) + val message = "${exceptions.size} " + requireContext().getString(R.string.errors) + ":\n" + exceptionMessage + ".\n" + requireContext().getString(R.string.import_error) val snackBar = Snackbar.make(view!!, message, Snackbar.LENGTH_INDEFINITE) snackBar.setAction(R.string.ok) { snackBar.dismiss() @@ -160,4 +157,8 @@ class ImportFragment : RealmFragment(), ImportDelegate { binding.totalCounter.text = this.numberFormatter.format(totalCount) } + override fun exceptionCaught(e: Exception) { + this.exceptions.add(e) + } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt index ceee25aa..19bdad1d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt @@ -292,7 +292,7 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep private fun sessionsCSVExport() { val sessions = getRealm().where(Session::class.java).findAll().sort("startDate") - val csv = ProductCSVDescriptors.pokerAnalyticsAndroid.toCSV(sessions) + val csv = ProductCSVDescriptors.pokerAnalyticsAndroidSessions.toCSV(sessions) this.shareCSV(csv, "Sessions") } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDoubleEditTextFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDoubleEditTextFragment.kt index 7e6c3c01..e183e4a2 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDoubleEditTextFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDoubleEditTextFragment.kt @@ -12,12 +12,12 @@ import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorExcep import net.pokeranalytics.android.util.extensions.round -class BottomSheetDoubleEditTextFragment : BottomSheetFragment() { +open class BottomSheetDoubleEditTextFragment : BottomSheetFragment() { private var _binding: BottomSheetDoubleEditTextBinding? = null private val binding get() = _binding!! - override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View? { + override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View { _binding = BottomSheetDoubleEditTextBinding.inflate(inflater, container, true) return binding.root } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetEditTextFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetEditTextFragment.kt index 0171848b..e6048a32 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetEditTextFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetEditTextFragment.kt @@ -16,7 +16,7 @@ class BottomSheetEditTextFragment : BottomSheetFragment() { private var _binding: BottomSheetEditTextBinding? = null private val binding get() = _binding!! - override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View? { + override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View { _binding = BottomSheetEditTextBinding.inflate(inflater, container, true) return binding.root } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt index 5c3bac02..9ea6b621 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt @@ -86,6 +86,7 @@ open class BottomSheetFragment : BottomSheetDialogFragment() { BottomSheetType.DOUBLE_EDIT_TEXT -> BottomSheetDoubleEditTextFragment() BottomSheetType.NUMERIC_TEXT -> BottomSheetNumericTextFragment() BottomSheetType.SUM -> BottomSheetSumFragment() + BottomSheetType.CASH_GAME_STAKES -> BottomSheetStakesFragment() } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt index 3014d3c4..6f955154 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt @@ -18,7 +18,7 @@ open class BottomSheetListFragment : BottomSheetFragment(), LiveRowRepresentable private var _binding: BottomSheetListBinding? = null private val binding get() = _binding!! - override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View? { + override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View { _binding = BottomSheetListBinding.inflate(inflater, container, true) return binding.root } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt index 0cd9444d..edf77cd6 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt @@ -22,7 +22,7 @@ class BottomSheetListGameFragment : BottomSheetListFragment() { private var _binding: BottomSheetGameListBinding? = null private val binding get() = _binding!! - override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View? { + override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View { _binding = BottomSheetGameListBinding.inflate(inflater, container, true) return binding.root } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetNumericTextFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetNumericTextFragment.kt index be187f9d..61fc3da9 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetNumericTextFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetNumericTextFragment.kt @@ -17,7 +17,7 @@ class BottomSheetNumericTextFragment : BottomSheetFragment() { private var _binding: BottomSheetEditTextBinding? = null private val binding get() = _binding!! - override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View? { + override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View { _binding = BottomSheetEditTextBinding.inflate(inflater, container, true) return binding.root } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStakesFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStakesFragment.kt new file mode 100644 index 00000000..4b01b72e --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStakesFragment.kt @@ -0,0 +1,150 @@ +package net.pokeranalytics.android.ui.fragment.components.bottomsheet + +import android.content.Context +import android.os.Bundle +import android.text.InputType +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.EditorInfo +import android.view.inputmethod.InputMethodManager +import android.widget.EditText +import androidx.core.widget.addTextChangedListener +import kotlinx.android.synthetic.main.view_keyboard_stakes.view.* +import net.pokeranalytics.android.databinding.BottomSheetStakesBinding +import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException +import java.text.NumberFormat +import java.text.ParseException + + +class BottomSheetStakesFragment : BottomSheetFragment() { + + private var _binding: BottomSheetStakesBinding? = null + private val binding get() = _binding!! + + override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View { + _binding = BottomSheetStakesBinding.inflate(inflater, container, true) + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initData() + initUI() + } + + override fun onStart() { + super.onStart() + } + + /** + * Init data + */ + private fun initData() { +// this.viewModel.isEditingBlinds = this.viewModel.row == SessionRow.BLINDS + } + + private fun focusEditTextAndHideKeyboard(editText: EditText) { + + editText.requestFocus() + + editText.onCreateInputConnection(EditorInfo())?.let { + binding.stakesKeyboard.inputConnection = it + } + + val mgr: InputMethodManager? = + requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager? + mgr?.hideSoftInputFromWindow(editText.windowToken, InputMethodManager.SHOW_FORCED) + + } + + /** + * Init UI + */ + private fun initUI() { + + val data = getDescriptors()?:throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found") + if (data.size != 2) { + throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency") + } + + // Ante + val anteED = data[0] + anteED.defaultValue?.let { + binding.anteEditText.hint = NumberFormat.getInstance().format(it as Double) + } ?: run { + anteED.hintResId?.let { binding.anteEditText.hint = getString(it) } + } + +// binding.anteEditText.inputType = anteED.inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES + + +// binding.anteKeyboard.toolbar.isVisible = false +// binding.anteKeyboard.visibility = View.GONE + + binding.anteEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER) + binding.anteEditText.showSoftInputOnFocus = false + + // Blinds + val blindsED = data[1] + blindsED.defaultValue?.let { + binding.blindsEditText.hint = it as? String + } ?: run { + blindsED.hintResId?.let { binding.blindsEditText.hint = getString(it) } + } + + binding.blindsEditText.onCreateInputConnection(EditorInfo())?.let { + binding.stakesKeyboard.inputConnection = it + } + + binding.blindsEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER) + binding.blindsEditText.showSoftInputOnFocus = false + + binding.blindsEditText.setOnTouchListener { _, _ -> + + this.focusEditTextAndHideKeyboard(binding.blindsEditText) + +// binding.stakesKeyboard.visibility = View.VISIBLE + binding.stakesKeyboard.value_separator.visibility = View.VISIBLE + + return@setOnTouchListener true + + } + + binding.anteEditText.setOnTouchListener { _, _ -> + +// binding.anteKeyboard.setInputConnection(binding.anteEditText) + + this.focusEditTextAndHideKeyboard(binding.anteEditText) + + binding.stakesKeyboard.value_separator.visibility = View.GONE + +// binding.stakesKeyboard.visibility = View.VISIBLE +// binding.stakesKeyboard.visibility = View.GONE + return@setOnTouchListener true + } + + binding.anteEditText.addTextChangedListener { text -> + text?.let { + + val ante = try { + NumberFormat.getInstance().parse(it.toString()) + } catch(e: ParseException) { + null + } + this.model.ante = ante?.toDouble() + } + } + + binding.blindsEditText.addTextChangedListener { + this.model.secondStringValue = it?.toString() + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStaticListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStaticListFragment.kt index 82d9063f..2f3385d4 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStaticListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStaticListFragment.kt @@ -17,7 +17,7 @@ class BottomSheetStaticListFragment : BottomSheetFragment(), StaticRowRepresenta private var _binding: BottomSheetListBinding? = null private val binding get() = _binding!! - override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View? { + override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View { _binding = BottomSheetListBinding.inflate(inflater, container, true) return binding.root } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetSumFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetSumFragment.kt index 91f84b80..7a29177b 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetSumFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetSumFragment.kt @@ -19,7 +19,7 @@ class BottomSheetSumFragment : BottomSheetFragment() { private var _binding: BottomSheetSumBinding? = null private val binding get() = _binding!! - override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View? { + override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View { _binding = BottomSheetSumBinding.inflate(inflater, container, true) return binding.root } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetTableSizeGridFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetTableSizeGridFragment.kt index 3fdcc235..98deffc3 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetTableSizeGridFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetTableSizeGridFragment.kt @@ -19,7 +19,7 @@ class BottomSheetTableSizeGridFragment : BottomSheetFragment(), StaticRowReprese private var _binding: BottomSheetGridBinding? = null private val binding get() = _binding!! - override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View? { + override fun inflateContentView(inflater: LayoutInflater, container: ViewGroup): View { _binding = BottomSheetGridBinding.inflate(inflater, container, true) return binding.root } @@ -61,7 +61,7 @@ class BottomSheetTableSizeGridFragment : BottomSheetFragment(), StaticRowReprese } } - override fun adapterRows(): List? { + override fun adapterRows(): List { return TableSize.all(this.model.alternativeLabels) } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetType.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetType.kt index 9bcb2f54..fc046588 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetType.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetType.kt @@ -12,7 +12,8 @@ enum class BottomSheetType { EDIT_TEXT_MULTI_LINES, DOUBLE_EDIT_TEXT, NUMERIC_TEXT, - SUM; + SUM, + CASH_GAME_STAKES; val validationRequired: Boolean get() = when (this) { @@ -25,7 +26,7 @@ enum class BottomSheetType { val addRequired: Boolean get() = when (this) { - EDIT_TEXT, NUMERIC_TEXT, DOUBLE_EDIT_TEXT, EDIT_TEXT_MULTI_LINES, GRID, LIST_STATIC, SUM -> false + EDIT_TEXT, NUMERIC_TEXT, DOUBLE_EDIT_TEXT, EDIT_TEXT_MULTI_LINES, GRID, LIST_STATIC, SUM, CASH_GAME_STAKES -> false else -> true } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/editor/EditorAdapter.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/editor/EditorAdapter.kt index b0f6ec9d..8232aedf 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/editor/EditorAdapter.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/editor/EditorAdapter.kt @@ -192,7 +192,8 @@ class EditorAdapter( "Edit Text not found for tag: $tag, class: $this" ) - // hides soft input view + // hides soft input view, + // 22/06/22: does not seem useful as - I believe - manifest activity has android:windowSoftInputMode="stateAlwaysHidden" editText.setTextIsSelectable(true) // Enabled diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt index e92454c7..cae80b2a 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt @@ -536,9 +536,9 @@ class ActionList(var listener: ActionListListener? = null) : ArrayList this.handHistory.smallBlind = amount + Action.Type.POST_SB -> this.handHistory.oldSmallBlind = amount Action.Type.POST_BB -> { - this.handHistory.bigBlind = amount + this.handHistory.oldBigBlind = amount if (this.handHistory.bigBlindAnte) { this.updateBigBlindRemainingStack() } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/EditorViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/EditorViewModel.kt index 8cba02d5..11f7b6ff 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/EditorViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/EditorViewModel.kt @@ -30,7 +30,6 @@ import net.pokeranalytics.android.util.CrashLogging import net.pokeranalytics.android.util.extensions.findById import net.pokeranalytics.android.util.extensions.formatted import timber.log.Timber -import java.lang.Exception import java.text.DecimalFormat import java.text.ParseException import kotlin.coroutines.CoroutineContext @@ -63,6 +62,10 @@ class EditorViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer * The hand setup */ private var handSetup: HandSetup = HandSetup() + set(value) { + field = value + this.straddlePositions.addAll(value.straddlePositions) + } /*** * Indicates whether the HH is new or not @@ -261,8 +264,10 @@ class EditorViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer rows.add(CustomizableRowRepresentable(customViewType = HandRowType.HEADER, resId = R.string.settings, value = "")) rows.add(HandRowType.PLAYER_NUMBER) - if (this.handHistory.ante > 0) { - rows.add(HandRowType.ANTE) + this.handHistory.ante?.let { + if (it > 0) { + rows.add(HandRowType.ANTE) + } } if (this.handHistory.bigBlindAnte) { @@ -796,7 +801,7 @@ class EditorViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer val string = when (row) { HandRowType.PLAYER_NUMBER -> this.handHistory.numberOfPlayers.toString() HandRowType.COMMENT -> this.handHistory.comment ?: context.getString(R.string.comment) - HandRowType.ANTE -> this.handHistory.ante.formatted + HandRowType.ANTE -> this.handHistory.ante?.formatted HandRowType.BIG_BLIND_ANTE_READ -> context.getString(R.string.yes) // HandRowType.HERO_POSITION -> context.getString(R.string.set_hero_position) // HandRowType.PLAYER_POSITION -> context.getString(R.string.set_position_details) @@ -901,8 +906,8 @@ class EditorViewModel : ViewModel(), RowRepresentableDataSource, CardCentralizer fun changeStraddleSelection(positions: LinkedHashSet) { if (positions.isEmpty()) { - this.firstStraddlePosition = null - this.handSetup.clearStraddles() + this.firstStraddlePosition = null + this.handSetup.clearStraddles() } else { if (this.firstStraddlePosition == null) { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/AbstractKeyboardView.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/AbstractKeyboardView.kt index 2f3bc20a..6be5085d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/AbstractKeyboardView.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/AbstractKeyboardView.kt @@ -1,9 +1,16 @@ package net.pokeranalytics.android.ui.modules.handhistory.views import android.content.Context +import android.util.AttributeSet import android.widget.FrameLayout -abstract class AbstractKeyboardView(context: Context) : FrameLayout(context) { +abstract class AbstractKeyboardView : FrameLayout { + + constructor(context: Context) : super(context) + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) var keyboardListener: KeyboardListener? = null set(value) { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/KeyboardAmountView.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/KeyboardAmountView.kt index c59c3a88..0aeb47c3 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/KeyboardAmountView.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/KeyboardAmountView.kt @@ -1,6 +1,7 @@ package net.pokeranalytics.android.ui.modules.handhistory.views import android.content.Context +import android.util.AttributeSet import android.view.LayoutInflater import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputConnection @@ -19,6 +20,7 @@ import net.pokeranalytics.android.ui.view.GridSpacingItemDecoration import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.util.extensions.noGroupingFormatted +import timber.log.Timber import java.text.DecimalFormatSymbols class NumericKey : RowRepresentable { @@ -63,9 +65,16 @@ class NumericKey : RowRepresentable { } -class KeyboardAmountView(context: Context) : AbstractKeyboardView(context), +class KeyboardAmountView : AbstractKeyboardView, StaticRowRepresentableDataSource, RowRepresentableDelegate { + constructor(context: Context) : super(context) + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + + /*** * The adapter managing the grid displayed keyboard */ @@ -144,16 +153,19 @@ class KeyboardAmountView(context: Context) : AbstractKeyboardView(context), // Timber.d("edit text = $editText") - this.editText = editText + this.setInputConnection(editText) editText.setText(amount?.noGroupingFormatted) editText.requestFocus() editText.isEnabled = true // avoid crashes due to input connection null + } + + fun setInputConnection(editText: EditText) { + this.editText = editText editText.onCreateInputConnection(EditorInfo())?.let { this.inputConnection = it - } ?: run { throw PAIllegalStateException("EditText did not return an input Connection") } - + } ?: throw PAIllegalStateException("EditText did not return an input Connection") } override fun adapterRows(): List { @@ -175,6 +187,8 @@ class KeyboardAmountView(context: Context) : AbstractKeyboardView(context), val key = row as NumericKey + Timber.d("this.inputConnection = ${this.inputConnection}") + this.inputConnection?.let { when { @@ -190,9 +204,7 @@ class KeyboardAmountView(context: Context) : AbstractKeyboardView(context), this.keyboardListener?.amountChanged(this.editText.text.toString()) - } ?: run { - throw PAIllegalStateException("Requires an input connection to handle key selections") - } + } ?: throw PAIllegalStateException("Requires an input connection to handle key selections") } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/RowHandHistoryViewHolder.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/RowHandHistoryViewHolder.kt index eda969c7..b302de57 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/RowHandHistoryViewHolder.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/RowHandHistoryViewHolder.kt @@ -35,8 +35,7 @@ class RowHandHistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemVie val amount = itemView.findViewById(R.id.amount) amount.text = handHistory.potSizeForStreet(Street.SUMMARY).formatted - val heroWins = handHistory.heroWins - val colorId = when(heroWins) { + val colorId = when(handHistory.heroWins) { true -> R.color.green false -> R.color.red else -> R.color.kaki_light diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt index bc317e07..9ae44b4c 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt @@ -26,7 +26,6 @@ import net.pokeranalytics.android.model.extensions.getState import net.pokeranalytics.android.model.extensions.scheduleStopNotification import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.model.realm.* -import net.pokeranalytics.android.util.CrashLogging import net.pokeranalytics.android.model.utils.FavoriteSessionFinder import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate @@ -38,6 +37,7 @@ import net.pokeranalytics.android.ui.modules.datalist.DataListActivity import net.pokeranalytics.android.ui.modules.handhistory.HandHistoryActivity import net.pokeranalytics.android.ui.view.* import net.pokeranalytics.android.ui.view.rows.SessionPropertiesRow +import net.pokeranalytics.android.util.CrashLogging import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.extensions.* import timber.log.Timber @@ -206,9 +206,10 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr currentSession.location = realmLocation } - updateSessionUI(true) + this.updateSessionUI(true) } } + sessionHasBeenUserCustomized = false } } @@ -264,7 +265,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr when (row) { SessionPropertiesRow.CASHED_OUT, SessionPropertiesRow.PRIZE, SessionPropertiesRow.NET_RESULT, SessionPropertiesRow.BUY_IN, SessionPropertiesRow.TIPS, SessionPropertiesRow.START_DATE, - SessionPropertiesRow.END_DATE, SessionPropertiesRow.BREAK_TIME -> updateSessionUI() + SessionPropertiesRow.END_DATE, SessionPropertiesRow.BREAK_TIME, SessionPropertiesRow.NUMBER_OF_TABLES -> updateSessionUI() SessionPropertiesRow.BANKROLL -> { updateSessionUI() updateMenuUI() // result capture method @@ -577,15 +578,15 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr "defaultValue" to session.tableSize ) ) - SessionPropertiesRow.BLINDS -> row.editingDescriptors( + SessionPropertiesRow.STAKES -> row.editingDescriptors( mapOf( - "sb" to session.cgSmallBlind?.round(), - "bb" to session.cgBigBlind?.round() + "blinds" to session.cgBlinds, + "ante" to session.cgAnte ) ) SessionPropertiesRow.BUY_IN -> row.editingDescriptors( mapOf( - "bb" to session.cgBigBlind, + "bb" to session.cgBiggestBet, "fee" to session.tournamentEntryFee, "ratedBuyin" to session.result?.buyin ) @@ -626,10 +627,15 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr "defaultValue" to session.handsCount ) ) + SessionPropertiesRow.NUMBER_OF_TABLES -> row.editingDescriptors( + mapOf( + "defaultValue" to session.numberOfTables + ) + ) SessionPropertiesRow.TIPS -> row.editingDescriptors( mapOf( - "sb" to session.cgSmallBlind?.round(), - "bb" to session.cgBigBlind?.round(), + "sb" to session.cgBiggestBet?.round(), + "bb" to session.cgBiggestBet?.round(), "tips" to session.result?.tips ) ) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/keyboard/StakesKeyboardView.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/keyboard/StakesKeyboardView.kt new file mode 100644 index 00000000..7db5b1ab --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/keyboard/StakesKeyboardView.kt @@ -0,0 +1,79 @@ +package net.pokeranalytics.android.ui.view.keyboard + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.inputmethod.InputConnection +import android.widget.FrameLayout +import androidx.appcompat.widget.LinearLayoutCompat +import kotlinx.android.synthetic.main.view_keyboard_stakes.view.* +import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException +import net.pokeranalytics.android.util.BLIND_SEPARATOR +import java.text.DecimalFormatSymbols + +class StakesKeyboardView : LinearLayoutCompat { + + var inputConnection: InputConnection? = null + + constructor(context: Context) : super(context) { + init(context, null) + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(context, attrs) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + init(context, attrs) + } + + private fun init(context: Context, attrs: AttributeSet?) { + val layoutInflater = LayoutInflater.from(context) + val view = layoutInflater.inflate(R.layout.view_keyboard_stakes, this, false) + + view.value_0.text = "0" + view.value_1.text = "1" + view.value_2.text = "2" + view.value_3.text = "3" + view.value_4.text = "4" + view.value_5.text = "5" + view.value_6.text = "6" + view.value_7.text = "7" + view.value_8.text = "8" + view.value_9.text = "9" + view.value_decimal.text = DecimalFormatSymbols.getInstance().decimalSeparator.toString() + view.value_back.text = "⌫" + view.value_separator.text = "/" + + view.value_0.setOnClickListener { this.commitText("0") } + view.value_1.setOnClickListener { this.commitText("1") } + view.value_2.setOnClickListener { this.commitText("2") } + view.value_3.setOnClickListener { this.commitText("3") } + view.value_4.setOnClickListener { this.commitText("4") } + view.value_5.setOnClickListener { this.commitText("5") } + view.value_6.setOnClickListener { this.commitText("6") } + view.value_7.setOnClickListener { this.commitText("7") } + view.value_8.setOnClickListener { this.commitText("8") } + view.value_9.setOnClickListener { this.commitText("9") } + view.value_decimal.setOnClickListener { this.commitText(DecimalFormatSymbols.getInstance().decimalSeparator.toString()) } + view.value_separator.setOnClickListener { this.commitText(BLIND_SEPARATOR) } + view.value_back.setOnClickListener { this.deleteText() } + + val layoutParams = FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ) + addView(view, layoutParams) + + } + + private fun commitText(string: String) { + this.inputConnection?.commitText(string, 1) ?: throw PAIllegalStateException("No input connection") + } + + private fun deleteText() { + this.inputConnection?.deleteSurroundingText(1, 0) ?: throw PAIllegalStateException("No input connection") + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterCategoryRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterCategoryRow.kt index 61084287..f1384967 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterCategoryRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterCategoryRow.kt @@ -101,7 +101,7 @@ enum class FilterCategoryRow(override val resId: Int?, override val viewType: In Bankroll ) CASH -> arrayListOf( - Blind + Stakes ) TOURNAMENT -> arrayListOf( TournamentType, diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterSectionRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterSectionRow.kt index e967fe6a..ff3d21e2 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterSectionRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterSectionRow.kt @@ -26,7 +26,7 @@ sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable { object SessionDuration: FilterSectionRow(R.string.session_duration) object TimeFrameRange: FilterSectionRow(R.string.hour_slot) object Sessions: FilterSectionRow(R.string.sessions) - object Blind: FilterSectionRow(R.string.blinds) + object Stakes: FilterSectionRow(R.string.stakes) object CashRebuyCount: FilterSectionRow(R.string.rebuy_count) object TournamentType: FilterSectionRow(R.string.tournament_types) object TournamentName: FilterSectionRow(R.string.tournament_name) @@ -134,7 +134,7 @@ sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable { //Sessions -> arrayListOf(QueryCondition.LastGame(), QueryCondition.LastSession()) // Cash - Blind -> Criteria.Blinds.queryConditions.mapFirstCondition() + Stakes -> Criteria.Stakes.queryConditions.mapFirstCondition() // CashRebuyCount -> QueryCondition.moreOrLess() // Tournament diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/ReportRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/ReportRow.kt index 51b94abc..5ef8c002 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/ReportRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/ReportRow.kt @@ -49,7 +49,7 @@ enum class ReportRow : RowRepresentable { val criteria: List get() { return when (this) { - BLINDS -> listOf(Criteria.Blinds) + BLINDS -> listOf(Criteria.Stakes) BUY_IN -> listOf(Criteria.TournamentFees) DAY_OF_WEEKS -> listOf(Criteria.DaysOfWeek) GENERAL -> listOf(Criteria.SessionTypes, Criteria.BankrollTypes) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/SessionPropertiesRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/SessionPropertiesRow.kt index c945c930..f40ba622 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/SessionPropertiesRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/SessionPropertiesRow.kt @@ -28,13 +28,14 @@ enum class SessionPropertiesRow : RowRepresentable { TIPS, GAME, - BLINDS, + STAKES, LOCATION, BANKROLL, TABLE_SIZE, TOURNAMENT_TYPE, TOURNAMENT_NAME, TOURNAMENT_FEATURE, + NUMBER_OF_TABLES, START_DATE, END_DATE, @@ -104,7 +105,11 @@ enum class SessionPropertiesRow : RowRepresentable { Session.Type.CASH_GAME.ordinal -> { when (state) { SessionState.PENDING, SessionState.PLANNED -> { - return arrayListOf(GAME, BLINDS, LOCATION, BANKROLL, TABLE_SIZE, START_DATE, END_DATE) + return if (session.isLive) { + arrayListOf(GAME, STAKES, LOCATION, BANKROLL, TABLE_SIZE, START_DATE, END_DATE) + } else { + arrayListOf(GAME, STAKES, LOCATION, BANKROLL, TABLE_SIZE, NUMBER_OF_TABLES, START_DATE, END_DATE) + } } SessionState.STARTED, SessionState.PAUSED, SessionState.FINISHED -> { @@ -132,18 +137,28 @@ enum class SessionPropertiesRow : RowRepresentable { fields.add(HANDS) } fields.add(SeparatorRow()) - fields.addAll(listOf( + fields.addAll( + listOf( GAME, - BLINDS, + STAKES, LOCATION, BANKROLL, - TABLE_SIZE, + TABLE_SIZE + ) + ) + if (!session.isLive) { + fields.add(NUMBER_OF_TABLES) + } + + fields.addAll( + listOf( SeparatorRow(), START_DATE, END_DATE, BREAK_TIME ) ) + if (state == SessionState.FINISHED) { fields.add(HANDS_COUNT) } @@ -168,13 +183,14 @@ enum class SessionPropertiesRow : RowRepresentable { BUY_IN -> R.string.buyin TIPS -> R.string.tips GAME -> R.string.game - BLINDS -> R.string.blinds + STAKES -> R.string.stakes LOCATION -> R.string.location BANKROLL -> R.string.bankroll TABLE_SIZE -> R.string.table_size TOURNAMENT_TYPE -> R.string.tournament_type TOURNAMENT_NAME -> R.string.tournament_name TOURNAMENT_FEATURE -> R.string.tournament_feature + NUMBER_OF_TABLES -> R.string.number_of_tables START_DATE -> R.string.start_date END_DATE -> R.string.end_date BREAK_TIME -> R.string.break_time @@ -188,9 +204,9 @@ enum class SessionPropertiesRow : RowRepresentable { get() { return when (this) { NET_RESULT, PRIZE, POSITION, PLAYERS, CASHED_OUT, INITIAL_BUY_IN, BUY_IN, TIPS, - GAME, BLINDS, LOCATION, BANKROLL, TABLE_SIZE, COMMENT, + GAME, STAKES, LOCATION, BANKROLL, TABLE_SIZE, COMMENT, TOURNAMENT_TYPE, TOURNAMENT_NAME, TOURNAMENT_FEATURE, HANDS, - START_DATE, END_DATE, BREAK_TIME, HANDS_COUNT -> RowViewType.TITLE_VALUE.ordinal + START_DATE, END_DATE, BREAK_TIME, HANDS_COUNT, NUMBER_OF_TABLES -> RowViewType.TITLE_VALUE.ordinal } } @@ -198,9 +214,9 @@ enum class SessionPropertiesRow : RowRepresentable { get() { return when (this) { NET_RESULT, CASHED_OUT, INITIAL_BUY_IN, BREAK_TIME, POSITION, PLAYERS, - PRIZE, HANDS_COUNT -> BottomSheetType.NUMERIC_TEXT + PRIZE, HANDS_COUNT, NUMBER_OF_TABLES -> BottomSheetType.NUMERIC_TEXT BUY_IN, TIPS -> BottomSheetType.SUM - BLINDS -> BottomSheetType.DOUBLE_EDIT_TEXT + STAKES -> BottomSheetType.CASH_GAME_STAKES GAME -> BottomSheetType.LIST_GAME TOURNAMENT_TYPE -> BottomSheetType.LIST_STATIC LOCATION, BANKROLL, TOURNAMENT_NAME -> BottomSheetType.LIST @@ -214,17 +230,16 @@ enum class SessionPropertiesRow : RowRepresentable { override fun editingDescriptors(map: Map): ArrayList? { return when (this) { - BLINDS -> { - val sb: String? by map - val bb: String? by map + STAKES -> { + val ante: Double? by map + val blinds: String? by map arrayListOf( RowRepresentableEditDescriptor( - sb, R.string.smallblind, InputType.TYPE_CLASS_NUMBER + ante, R.string.ante, InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL ), RowRepresentableEditDescriptor( - bb, R.string.bigblind, InputType.TYPE_CLASS_NUMBER - or InputType.TYPE_NUMBER_FLAG_DECIMAL + blinds, R.string.blinds, InputType.TYPE_CLASS_TEXT ) ) } @@ -279,7 +294,7 @@ enum class SessionPropertiesRow : RowRepresentable { ) ) } - HANDS_COUNT -> { + HANDS_COUNT, NUMBER_OF_TABLES -> { arrayListOf( RowRepresentableEditDescriptor(inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/viewmodel/BottomSheetViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/viewmodel/BottomSheetViewModel.kt index 10f0fb20..c98b5ed3 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/viewmodel/BottomSheetViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/viewmodel/BottomSheetViewModel.kt @@ -6,6 +6,7 @@ import io.realm.RealmList import io.realm.RealmResults import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException +import net.pokeranalytics.android.model.Stakes import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType import net.pokeranalytics.android.ui.view.RowRepresentable @@ -93,6 +94,11 @@ class BottomSheetViewModel(var row: RowRepresentable) : ViewModel() { var limit: Int? = 0 val someValues = ArrayList() + /** + * Stakes + */ + var ante: Double? = null + fun load() { when(this.row.bottomSheetType) { @@ -102,7 +108,7 @@ class BottomSheetViewModel(var row: RowRepresentable) : ViewModel() { throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency") } - this.isEditingBlinds = this.row == SessionPropertiesRow.BLINDS + this.isEditingBlinds = this.row == SessionPropertiesRow.STAKES this.stringValue = descriptors[0].defaultValue as? String this.secondStringValue = descriptors[1].defaultValue as? String @@ -211,6 +217,7 @@ class BottomSheetViewModel(var row: RowRepresentable) : ViewModel() { BottomSheetType.DOUBLE_LIST, BottomSheetType.LIST_GAME -> this.someValues BottomSheetType.LIST_STATIC -> this.selectedRows.firstOrNull() BottomSheetType.SUM -> this.doubleValue + BottomSheetType.CASH_GAME_STAKES -> Stakes(this.secondStringValue, this.ante) else -> null } } diff --git a/app/src/main/java/net/pokeranalytics/android/util/FakeDataManager.kt b/app/src/main/java/net/pokeranalytics/android/util/FakeDataManager.kt index a5e94be2..c13ecc34 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/FakeDataManager.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/FakeDataManager.kt @@ -90,9 +90,13 @@ class FakeDataManager { if (isTournament) { session.tournamentEntryFee = buyin } else { - val bigBlind = arrayListOf(1.0, 2.0, 4.0).random() - session.cgBigBlind = bigBlind - session.cgSmallBlind = bigBlind / 2.0 + + session.cgAnte = arrayListOf(1.0, null).random() + session.cgBlinds = arrayListOf("1/2", "2/5/10", "2").random() + +// val bigBlind = arrayListOf(1.0, 2.0, 4.0).random() +// session.cgBigBlind = bigBlind +// session.cgSmallBlind = bigBlind / 2.0 } } diff --git a/app/src/main/java/net/pokeranalytics/android/util/Global.kt b/app/src/main/java/net/pokeranalytics/android/util/Global.kt index 19d486bb..85ffc3b2 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/Global.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/Global.kt @@ -2,4 +2,5 @@ package net.pokeranalytics.android.util const val NULL_TEXT: String = "--" const val RANDOM_PLAYER: String = "☺︎" -const val FFMPEG_DESCRIPTOR_FILE = "descriptor.txt" \ No newline at end of file +const val FFMPEG_DESCRIPTOR_FILE = "descriptor.txt" +const val BLIND_SEPARATOR: String = "/" diff --git a/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt b/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt index 03c4868f..c731e9c6 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt @@ -32,7 +32,7 @@ class Preferences { PATCH_BREAK("patchBreaks"), PATCH_SESSION_SETS("patchSessionSet"), PATCH_TRANSACTION_TYPES_NAMES("patchTransactionTypesNames"), - PATCH_BLINDS_FORMAT("patchBlindFormat"), +// PATCH_BLINDS_FORMAT("patchBlindFormat"), PATCH_COMPUTABLE_RESULTS("patchPositiveSessions"), SHOW_STOP_NOTIFICATIONS("showStopNotifications"), ADD_NEW_TRANSACTION_TYPES("addNewTransactionTypes"), @@ -43,7 +43,8 @@ class Preferences { LAST_BLOG_TIPS_RETRIEVAL("lastBlogTipsRetrieval"), SHOW_BLOG_TIPS("showBlogTips"), LAST_REVIEW_REQUEST_DATE("lastReviewRequestDate"), - PATCH_NEGATIVE_LIMITS("negativeLimits") + PATCH_NEGATIVE_LIMITS("negativeLimits"), + PATCH_STAKES("patchStakes") } enum class FeedMessage { diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/CSVDescriptor.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/CSVDescriptor.kt index e5e6b070..774cc807 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/CSVDescriptor.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/CSVDescriptor.kt @@ -14,6 +14,7 @@ import timber.log.Timber */ enum class DataSource { POKER_ANALYTICS, + POKER_ANALYTICS_6, POKER_INCOME, POKER_BANKROLL_TRACKER, RUN_GOOD, diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/CSVImporter.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/CSVImporter.kt index 38998792..23d98e31 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/CSVImporter.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/CSVImporter.kt @@ -18,6 +18,7 @@ class ImportException(message: String) : Exception(message) interface ImportDelegate { fun parsingCountUpdate(importedCount: Int, totalCount: Int) + fun exceptionCaught(e: Exception) } /** @@ -107,7 +108,7 @@ open class CSVImporter(istream: InputStream) { realm.beginTransaction() - parser.forEachIndexed { index, record -> + this.parser.forEachIndexed { index, record -> // Timber.d("line $index") this.notifyDelegate() @@ -146,12 +147,19 @@ open class CSVImporter(istream: InputStream) { null // reset descriptor when encountering an empty line (multiple descriptors can be found in a single file) this.descriptorFindingAttempts = 0 } else { - val count = it.parse(realm, record) - this.importedRecords += count - this.totalParsedRecords++ + try { + val count = it.parse(realm, record) + + this.importedRecords += count + this.totalParsedRecords++ + + this.notifyDelegate() + + } catch (e: Exception) { + this.delegate?.exceptionCaught(e) + } - this.notifyDelegate() } } ?: run { realm.cancelTransaction() diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/PACSVDescriptor.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/PACSVDescriptor.kt index 168460d6..5d36f9b3 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/PACSVDescriptor.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/PACSVDescriptor.kt @@ -1,19 +1,21 @@ package net.pokeranalytics.android.util.csv -import net.pokeranalytics.android.model.interfaces.Identifiable import io.realm.Realm import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.Limit import net.pokeranalytics.android.model.TableSize import net.pokeranalytics.android.model.TournamentType +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.model.utils.DataUtils +import net.pokeranalytics.android.util.BLIND_SEPARATOR import net.pokeranalytics.android.util.extensions.count import net.pokeranalytics.android.util.extensions.getOrCreate import net.pokeranalytics.android.util.extensions.setHourMinutes import org.apache.commons.csv.CSVRecord import timber.log.Timber import java.text.DateFormat +import java.text.NumberFormat import java.text.ParseException import java.text.SimpleDateFormat import java.util.* @@ -57,6 +59,9 @@ abstract class PACSVDescriptor(source: DataSource, var stackingIn: Double? = null var stackingOut: Double? = null + var sb: Double? = null + var bb: Double? = null + this.fields.forEach { field -> this.fieldMapping[field]?.let { index -> @@ -75,7 +80,9 @@ abstract class PACSVDescriptor(source: DataSource, } else {} } is SessionField.End -> { - endDate = parseDate(field, value) + if (value.isNotEmpty()) { + endDate = parseDate(field, value) + } } is SessionField.StartTime -> { startDate?.setHourMinutes(value) @@ -169,38 +176,17 @@ abstract class PACSVDescriptor(source: DataSource, is SessionField.Bankroll -> bankrollName = value is SessionField.LimitType -> session.limit = Limit.getInstance(value)?.ordinal is SessionField.Comment -> session.comment = value - is SessionField.Blind -> { // 1/2 - val blinds = field.parse(value) - session.cgSmallBlind = blinds?.first - session.cgBigBlind = blinds?.second + is SessionField.Blind, is SessionField.Blinds -> { // 1/2 + session.cgBlinds = value } is SessionField.SmallBlind -> { - val sb = field.parse(value) - if (sb != null && sb > 0.0) { - session.cgSmallBlind = sb - } else {} + sb = field.parse(value) } is SessionField.BigBlind -> { - val bb = field.parse(value) - if (bb != null && bb > 0.0) { - session.cgBigBlind = bb - } else {} - } - is SessionField.Blinds -> { - val blinds = value.split("/") - when (blinds.size) { - 0 -> {} - 1 -> { - session.cgBigBlind = field.parse(blinds.first()) - } - else -> { - session.cgSmallBlind = field.parse(blinds[blinds.size - 2]) - session.cgBigBlind = field.parse(blinds.last()) - } - } + bb = field.parse(value) } is SessionField.Ante -> { - // unmanaged atm + session.cgAnte = field.parse(value) } is SessionField.TableSize -> session.tableSize = TableSize.valueForLabel(value) is SessionField.TournamentPosition -> session.result?.tournamentFinalPosition = @@ -256,6 +242,11 @@ abstract class PACSVDescriptor(source: DataSource, } + val blinds = arrayListOf(sb, bb).filterNotNull() + if (blinds.isNotEmpty()) { + session.cgBlinds = blinds.joinToString(BLIND_SEPARATOR) { NumberFormat.getInstance().format(it) } + } + val bankroll = Bankroll.getOrCreate(realm, bankrollName, isLive, currencyCode, currencyRate) session.bankroll = bankroll @@ -264,9 +255,9 @@ abstract class PACSVDescriptor(source: DataSource, } val net = session.result?.net - if (startDate != null && endDate != null && net != null) { // valid session + if (startDate != null && net != null) { // valid session // session already in realm, we'd love not put it in Realm before doing the check - val count = DataUtils.sessionCount(realm, startDate!!, endDate!!, net) + val count = DataUtils.sessionCount(realm, startDate!!, endDate, net) if (this.noSessionImport || count == 0) { val managedSession = realm.copyToRealm(session) diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt index 137d840c..b5d79fe2 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt @@ -18,7 +18,8 @@ class ProductCSVDescriptors { runGoodTournaments, pokerAnalyticsiOS, pokerAnalytics6iOS, - pokerAnalyticsAndroid, + pokerAnalyticsAndroidSessions, + pokerAnalyticsAndroid6Sessions, pokerAnalyticsAndroidTransactions ) @@ -239,7 +240,7 @@ class ProductCSVDescriptors { ) } - val pokerAnalyticsAndroid: SessionCSVDescriptor + val pokerAnalyticsAndroidSessions: SessionCSVDescriptor get() { return SessionCSVDescriptor( DataSource.POKER_ANALYTICS, @@ -273,6 +274,42 @@ class ProductCSVDescriptors { SessionField.Comment("Comment") ) } + + + val pokerAnalyticsAndroid6Sessions: SessionCSVDescriptor + get() { + return SessionCSVDescriptor( + DataSource.POKER_ANALYTICS_6, + true, + SessionField.Start("Start Date", dateFormat = "MM/dd/yy HH:mm:ss"), + SessionField.End("End Date", dateFormat = "MM/dd/yy HH:mm:ss"), + SessionField.Break("Break"), + SessionField.SessionType("Type"), + SessionField.Live("Live"), + SessionField.NumberOfTables("Tables"), + SessionField.Buyin("Buyin"), + SessionField.CashedOut("Cashed Out"), + SessionField.NetResult("Online Net"), + SessionField.Tips("Tips"), + SessionField.HandsCount("Hands Count"), + SessionField.LimitType("Limit"), + SessionField.Game("Game"), + SessionField.TableSize("Table Size"), + SessionField.Location("Location"), + SessionField.Bankroll("Bankroll"), + SessionField.CurrencyCode("Currency Code"), + SessionField.CurrencyRate("Currency Rate"), + SessionField.Ante("Antes"), + SessionField.Blinds("Blinds"), + SessionField.TournamentTypeName("Tournament Type"), + SessionField.TournamentName("Tournament Name"), + SessionField.TournamentEntryFee("Entry fee"), + SessionField.TournamentNumberOfPlayers("Number of players"), + SessionField.TournamentFeatures("Tournament Features"), + SessionField.TournamentPosition("Position"), + SessionField.Comment("Comment") + ) + } } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/SessionCSVDescriptor.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/SessionCSVDescriptor.kt index 52af5f00..982e0cb5 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/SessionCSVDescriptor.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/SessionCSVDescriptor.kt @@ -7,7 +7,6 @@ import net.pokeranalytics.android.model.TournamentType import net.pokeranalytics.android.model.realm.CustomField import net.pokeranalytics.android.model.realm.Session import org.apache.commons.csv.CSVRecord -import timber.log.Timber /** * A SessionCSVDescriptor is a CSVDescriptor specialized in parsing Session objects @@ -63,8 +62,10 @@ class SessionCSVDescriptor(source: DataSource, isTournament: Boolean?, vararg el is SessionField.Bankroll -> data.bankroll?.name is SessionField.CurrencyCode -> data.bankroll?.currency?.code is SessionField.CurrencyRate -> field.format(data.bankroll?.currency?.rate) - is SessionField.SmallBlind -> field.format(data.cgSmallBlind) - is SessionField.BigBlind -> field.format(data.cgBigBlind) +// is SessionField.SmallBlind -> field.format(data.cgSmallBlind) +// is SessionField.BigBlind -> field.format(data.cgBigBlind) + is SessionField.Blinds -> data.cgBlinds + is SessionField.Ante -> field.format(data.cgAnte) is SessionField.TournamentType -> field.format(data.tournamentType) is SessionField.TournamentTypeName -> { data.tournamentType?.let { tt -> diff --git a/app/src/main/res/layout/activity_color_picker.xml b/app/src/main/res/layout/activity_color_picker.xml index e2942fff..a90a7cfc 100644 --- a/app/src/main/res/layout/activity_color_picker.xml +++ b/app/src/main/res/layout/activity_color_picker.xml @@ -87,7 +87,6 @@ app:layout_constraintStart_toEndOf="@+id/color5" app:layout_constraintTop_toBottomOf="@+id/color2" /> - + android:id="@+id/menuContainer" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginEnd="16dp" + android:layout_marginBottom="72dp" + android:background="@color/kaki_darkest" + android:elevation="4dp" + android:orientation="vertical" + android:visibility="invisible" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + tools:visibility="visible"> + android:id="@+id/newCashGame" + android:layout_width="wrap_content" + android:layout_height="48dp" + android:layout_marginTop="8dp" + android:background="?selectableItemBackground" + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingStart="16dp" + android:paddingEnd="16dp"> + android:layout_width="32dp" + android:layout_height="32dp" + android:tint="@color/green" + app:srcCompat="@drawable/add_cash_game" /> + style="@style/PokerAnalyticsTheme.TextView.RowTitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:text="@string/new_cash_game" + app:layout_constraintEnd_toEndOf="parent" /> diff --git a/app/src/main/res/layout/bottom_sheet_stakes.xml b/app/src/main/res/layout/bottom_sheet_stakes.xml new file mode 100644 index 00000000..e123545d --- /dev/null +++ b/app/src/main/res/layout/bottom_sheet_stakes.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/row_hand_action.xml b/app/src/main/res/layout/row_hand_action.xml index 0f6d320a..b47d4413 100644 --- a/app/src/main/res/layout/row_hand_action.xml +++ b/app/src/main/res/layout/row_hand_action.xml @@ -23,7 +23,7 @@ diff --git a/app/src/main/res/layout/view_keyboard_stakes.xml b/app/src/main/res/layout/view_keyboard_stakes.xml new file mode 100644 index 00000000..6ead7145 --- /dev/null +++ b/app/src/main/res/layout/view_keyboard_stakes.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index dd3b4830..e368e28a 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -529,7 +529,7 @@ Jetons Tapis initial (en grosses blindes) Tapis - Montants + Mises Standard Ecart type Démarrer @@ -778,4 +778,5 @@ estimation Vous pouvez changer le nombre de mains distribuées par heure. Cette valeur correspond au nombre total de mains distribuées à tous les joueur d\'une table en une heure. Exemple: Vous jouez 25 mains par heure sur des tables de 10 joueurs, entrez: 10 x 25 = 250. Mains par heure + erreur(s) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index aa2a30d9..74a9b5db 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -821,5 +821,6 @@ You need to give a name to the report The hand you\'ve created has suit wildcards. By convenience - sorry! - we\'re currently removing such cards to determine which hand wins, resulting in potentially wrong chip distribution. proceed + error(s) diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index dd114e52..5f4e55d1 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -386,6 +386,32 @@ @color/kaki_darker + + + +