From 5b7d8ab2b99106c727f8cabf881ffd4f144646c3 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Thu, 6 Jun 2019 14:39:19 +0200 Subject: [PATCH 001/125] Merge Laurent updates --- .../net/pokeranalytics/android/model/realm/Filter.kt | 9 +++++---- .../android/ui/activity/NewDataMenuActivity.kt | 7 +++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt index a65edf11..8fd1e6e9 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt @@ -48,12 +48,13 @@ open class Filter : RealmObject(), RowRepresentable, Editable, Deletable, Counta } inline fun queryOn(realm: Realm, query: Query, sortField: String? = null): RealmResults { - val realmQuery = realm.where() + val rootQuery = realm.where() + var realmQuery = query.queryWith(rootQuery) sortField?.let { - return query.queryWith(realmQuery).sort(it).findAll() - } ?: run { - return query.queryWith(realmQuery).findAll() + realmQuery = realmQuery.sort(it) } + val desc = realmQuery.description + return realmQuery.findAll() } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/NewDataMenuActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/NewDataMenuActivity.kt index 49b9b97b..8cc3dfcb 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/NewDataMenuActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/NewDataMenuActivity.kt @@ -4,6 +4,8 @@ import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.content.Context import android.content.Intent +import android.content.pm.ActivityInfo +import android.os.Build import android.os.Bundle import android.view.View import android.view.ViewAnimationUtils @@ -36,6 +38,11 @@ class NewDataMenuActivity : PokerAnalyticsActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // used to fix Oreo crash + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + setContentView(R.layout.activity_new_data) initUI() } From c1d271b495e86ec27b111ac505bdb9457b00e547 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Thu, 6 Jun 2019 17:27:15 +0200 Subject: [PATCH 002/125] Add Top 10 view --- app/src/main/AndroidManifest.xml | 5 + .../model/extensions/SessionExtensions.kt | 44 ++++- .../android/ui/activity/Top10Activity.kt | 33 ++++ .../android/ui/fragment/MoreFragment.kt | 2 + .../android/ui/fragment/Top10Fragment.kt | 154 ++++++++++++++++++ .../android/ui/view/RowViewType.kt | 47 ++++++ .../android/ui/view/SessionRowView.kt | 39 +---- .../ui/view/rowrepresentable/MoreTabRow.kt | 3 + app/src/main/res/drawable/ic_outline_star.xml | 5 + app/src/main/res/layout/activity_top_10.xml | 15 ++ app/src/main/res/layout/fragment_top_10.xml | 71 ++++++++ app/src/main/res/layout/row_top_10.xml | 71 ++++++++ app/src/main/res/values/styles.xml | 16 ++ 13 files changed, 467 insertions(+), 38 deletions(-) create mode 100644 app/src/main/java/net/pokeranalytics/android/ui/activity/Top10Activity.kt create mode 100644 app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt create mode 100644 app/src/main/res/drawable/ic_outline_star.xml create mode 100644 app/src/main/res/layout/activity_top_10.xml create mode 100644 app/src/main/res/layout/fragment_top_10.xml create mode 100644 app/src/main/res/layout/row_top_10.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8cf3f769..04c3d2ef 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -74,6 +74,11 @@ android:launchMode="singleTop" android:screenOrientation="portrait" /> + + () + if (isTournament()) { + + tournamentEntryFee?.let { + parameters.add(it.toCurrency(currency)) + } + + tournamentName?.let { + parameters.add(it.name) + } ?: run { + parameters.add(getFormattedGame()) + tournamentType?.let { type -> + parameters.add(TournamentType.values()[type].localizedTitle(context)) + } + } + if (parameters.size == 0) { + parameters.add(context.getString(R.string.tournament).capitalize()) + } + } else { + if (cgSmallBlind != null && cgBigBlind != null) { + parameters.add(getFormattedBlinds()) + } + game?.let { + parameters.add(getFormattedGame()) + } + + if (parameters.size == 0) { + parameters.add(context.getString(R.string.cash_game).capitalize()) + } + } + return parameters.joinToString(separator = " ") } val AbstractList.hourlyDuration: Double @@ -95,4 +137,4 @@ fun MutableList.update(timeInterval: TimeInterval): MutableList BankrollActivity.newInstance(requireContext()) + MoreTabRow.TOP_10 -> Top10Activity.newInstance(requireContext()) MoreTabRow.SETTINGS -> SettingsActivity.newInstance(requireContext()) } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt new file mode 100644 index 00000000..9dfc8361 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt @@ -0,0 +1,154 @@ +package net.pokeranalytics.android.ui.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.google.android.material.tabs.TabLayout +import io.realm.RealmModel +import io.realm.RealmResults +import io.realm.Sort +import io.realm.kotlin.where +import kotlinx.android.synthetic.main.fragment_feed.* +import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.model.realm.Transaction +import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter +import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource +import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate +import net.pokeranalytics.android.ui.fragment.components.RealmFragment +import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.ui.view.RowViewType +import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager + + +class Top10Fragment : RealmFragment(), RowRepresentableDataSource, RowRepresentableDelegate { + + private enum class Tab { + CASH_GAMES, + TOURNAMENTS + } + + companion object { + fun newInstance(): Top10Fragment { + val fragment = Top10Fragment() + val bundle = Bundle() + fragment.arguments = bundle + return fragment + } + } + + private lateinit var dataListAdapter: RowRepresentableAdapter + private lateinit var realmCashGames: RealmResults + private lateinit var realmTournaments: RealmResults + + private var currentTab: Tab = Tab.CASH_GAMES + + override val observedEntities: List> = listOf(Session::class.java, Transaction::class.java) + + override fun entitiesChanged(clazz: Class) { + super.entitiesChanged(clazz) + when (clazz.kotlin) { + Session::class -> { + this.dataListAdapter.notifyDataSetChanged() + } + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + super.onCreateView(inflater, container, savedInstanceState) + return inflater.inflate(R.layout.fragment_top_10, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initUI() + initData() + } + + override fun adapterRows(): List? { + return when (currentTab) { + Tab.CASH_GAMES -> realmCashGames + Tab.TOURNAMENTS -> realmTournaments + } + } + + override fun rowRepresentableForPosition(position: Int): RowRepresentable? { + return when (currentTab) { + Tab.CASH_GAMES -> realmCashGames[position] + Tab.TOURNAMENTS -> realmTournaments[position] + } + } + + override fun numberOfRows(): Int { + return when (currentTab) { + Tab.CASH_GAMES -> realmCashGames.size + Tab.TOURNAMENTS -> realmTournaments.size + } + } + + override fun viewTypeForPosition(position: Int): Int { + return RowViewType.ROW_TOP_10.ordinal + } + + /** + * Init UI + */ + private fun initUI() { + + setDisplayHomeAsUpEnabled(true) + + tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + override fun onTabSelected(tab: TabLayout.Tab) { + when (tab.position) { + 0 -> { + currentTab = Tab.CASH_GAMES + dataListAdapter.notifyDataSetChanged() + } + 1 -> { + currentTab = Tab.TOURNAMENTS + } + } + dataListAdapter.notifyDataSetChanged() + } + + override fun onTabUnselected(tab: TabLayout.Tab) { + } + + override fun onTabReselected(tab: TabLayout.Tab) { + } + }) + + + val viewManager = SmoothScrollLinearLayoutManager(requireContext()) + recyclerView.apply { + setHasFixedSize(true) + layoutManager = viewManager + } + + } + + /** + * Init data + */ + private fun initData() { + + this.realmCashGames = getRealm().where() + .equalTo("type", Session.Type.CASH_GAME.ordinal) + .greaterThanOrEqualTo("result.net", 0.0) + .sort("result.net", Sort.DESCENDING) + .limit(10) + .findAll() + + this.realmTournaments = getRealm().where() + .equalTo("type", Session.Type.TOURNAMENT.ordinal) + .greaterThanOrEqualTo("result.net", 0.0) + .sort("result.net", Sort.DESCENDING) + .limit(10) + .findAll() + + dataListAdapter = RowRepresentableAdapter(this, this) + recyclerView.adapter = dataListAdapter + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt index 12ccaece..3ad02065 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt @@ -26,6 +26,7 @@ import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.bankroll.BankrollReport +import net.pokeranalytics.android.model.extensions.getFormattedGameType import net.pokeranalytics.android.model.realm.CustomField import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Transaction @@ -37,6 +38,7 @@ import net.pokeranalytics.android.ui.extensions.setTextFormat import net.pokeranalytics.android.ui.graph.AxisFormatting import net.pokeranalytics.android.ui.graph.setStyle import net.pokeranalytics.android.ui.view.rowrepresentable.* +import net.pokeranalytics.android.util.extensions.longDate /** * An interface used to factor the configuration of RecyclerView.ViewHolder @@ -78,6 +80,7 @@ enum class RowViewType(private var layoutRes: Int) { // Custom row ROW_SESSION(R.layout.row_feed_session), ROW_TRANSACTION(R.layout.row_transaction), + ROW_TOP_10(R.layout.row_top_10), ROW_BUTTON(R.layout.row_button), ROW_FOLLOW_US(R.layout.row_follow_us), STATS(R.layout.row_stats_title_value), @@ -110,6 +113,10 @@ enum class RowViewType(private var layoutRes: Int) { // Row Transaction ROW_TRANSACTION -> RowTransactionViewHolder(layout) + // Row Transaction + ROW_TOP_10 -> RowTop10ViewHolder(layout) + + // Row Button ROW_BUTTON -> RowButtonViewHolder(layout) @@ -513,6 +520,46 @@ enum class RowViewType(private var layoutRes: Int) { } } + + /** + * Display a top 10 row + */ + inner class RowTop10ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { + override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { + + if (row is Session) { + + itemView.findViewById(R.id.gameResult)?.let { gameResult -> + val result = row.result?.net ?: 0.0 + val formattedStat = ComputedStat(Stat.NET_RESULT, result, currency = row.currency).format() + gameResult.setTextFormat(formattedStat, itemView.context) + } + + itemView.findViewById(R.id.top10ResultPart1)?.let { part1 -> + part1.text = row.getFormattedGameType(itemView.context) + } + + itemView.findViewById(R.id.top10ResultPart2)?.let { part2 -> + var content = row.getFormattedDuration() + + if (!row.location?.name.isNullOrEmpty()) { + content += " - " + row.location?.name + } else if (!row.bankroll?.name.isNullOrEmpty()) { + content += " - " + row.bankroll?.name + } + + part2.text = content + } + + itemView.findViewById(R.id.top10ResultPart3)?.let { part3 -> + part3.text = row.creationDate.longDate() + } + } + + } + } + + /** * Display a separator */ diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt index 40db96da..69edd181 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt @@ -11,15 +11,14 @@ import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.model.TableSize -import net.pokeranalytics.android.model.TournamentType import net.pokeranalytics.android.model.extensions.SessionState +import net.pokeranalytics.android.model.extensions.getFormattedGameType import net.pokeranalytics.android.model.extensions.getState import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.extensions.setTextFormat import net.pokeranalytics.android.util.extensions.getDayNumber import net.pokeranalytics.android.util.extensions.getShortDayName import net.pokeranalytics.android.util.extensions.shortTime -import net.pokeranalytics.android.util.extensions.toCurrency /** * Display a row session @@ -65,41 +64,7 @@ class SessionRowView : FrameLayout { rowSession.dateNumber.text = date.getDayNumber() // Title / Game type - - var parameters = mutableListOf() - if (session.isTournament()) { - - session.tournamentEntryFee?.let { - parameters.add(it.toCurrency(session.currency)) - } - - session.tournamentName?.let { - parameters.add(it.name) - } ?: run { - parameters.add(session.getFormattedGame()) - session.tournamentType?.let { type -> - parameters.add(TournamentType.values()[type].localizedTitle(context)) - } - } - - if (parameters.size == 0) { - parameters.add(context.getString(R.string.tournament).capitalize()) - } - } else { - if (session.cgSmallBlind != null && session.cgBigBlind != null) { - parameters.add(session.getFormattedBlinds()) - } - session.game?.let { - parameters.add(session.getFormattedGame()) - } - - if (parameters.size == 0) { - parameters.add(context.getString(R.string.cash_game).capitalize()) - } - } - val title = parameters.joinToString(separator = " ") - - rowSession.sessionTitle.text = title + rowSession.sessionTitle.text = session.getFormattedGameType(context) // Duration rowSession.sessionInfoDurationValue.text = session.getFormattedDuration() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/MoreTabRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/MoreTabRow.kt index 4e2fe8bc..3885a4a1 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/MoreTabRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/MoreTabRow.kt @@ -9,12 +9,14 @@ import net.pokeranalytics.android.ui.view.RowViewType */ enum class MoreTabRow : RowRepresentable { BANKROLL, + TOP_10, SETTINGS; override val resId: Int? get() { return when(this) { BANKROLL -> R.string.bankroll + TOP_10 -> R.string.top_10 SETTINGS -> R.string.services } } @@ -23,6 +25,7 @@ enum class MoreTabRow : RowRepresentable { get() { return when(this) { BANKROLL -> R.drawable.ic_outline_lock + TOP_10 -> R.drawable.ic_outline_star SETTINGS -> R.drawable.ic_outline_settings } } diff --git a/app/src/main/res/drawable/ic_outline_star.xml b/app/src/main/res/drawable/ic_outline_star.xml new file mode 100644 index 00000000..3fc251d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_star.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_top_10.xml b/app/src/main/res/layout/activity_top_10.xml new file mode 100644 index 00000000..44318e12 --- /dev/null +++ b/app/src/main/res/layout/activity_top_10.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_top_10.xml b/app/src/main/res/layout/fragment_top_10.xml new file mode 100644 index 00000000..07d841a5 --- /dev/null +++ b/app/src/main/res/layout/fragment_top_10.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/row_top_10.xml b/app/src/main/res/layout/row_top_10.xml new file mode 100644 index 00000000..6d143692 --- /dev/null +++ b/app/src/main/res/layout/row_top_10.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index eecdebee..43efcfbc 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -228,6 +228,22 @@ @color/green + + + + + + From d1136c317afa30a57267973c63bab38154bb1ea8 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Thu, 6 Jun 2019 18:10:46 +0200 Subject: [PATCH 003/125] Update Top 10 UI --- .../android/ui/view/RowViewType.kt | 29 ++++--- app/src/main/res/layout/row_top_10.xml | 80 +++++++++++++++++-- 2 files changed, 94 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt index 3ad02065..244e8674 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt @@ -539,18 +539,27 @@ enum class RowViewType(private var layoutRes: Int) { part1.text = row.getFormattedGameType(itemView.context) } - itemView.findViewById(R.id.top10ResultPart2)?.let { part2 -> - var content = row.getFormattedDuration() - - if (!row.location?.name.isNullOrEmpty()) { - content += " - " + row.location?.name - } else if (!row.bankroll?.name.isNullOrEmpty()) { - content += " - " + row.bankroll?.name - } - - part2.text = content + // Duration + val durationIcon = itemView.findViewById(R.id.sessionInfoDurationIcon) + val durationText = itemView.findViewById(R.id.sessionInfoDuration) + durationIcon?.isVisible = true + durationText?.isVisible = true + durationText?.text = row.getFormattedDuration() + + // Location + val locationIcon = itemView.findViewById(R.id.sessionInfoLocationIcon) + val locationText = itemView.findViewById(R.id.sessionInfoLocation) + + if (!row.location?.name.isNullOrEmpty()) { + locationIcon?.isVisible = true + locationText?.isVisible = true + locationText?.text = row.location?.name + } else { + locationIcon?.isVisible = false + locationText?.isVisible = false } + itemView.findViewById(R.id.top10ResultPart3)?.let { part3 -> part3.text = row.creationDate.longDate() } diff --git a/app/src/main/res/layout/row_top_10.xml b/app/src/main/res/layout/row_top_10.xml index 6d143692..157d62a2 100644 --- a/app/src/main/res/layout/row_top_10.xml +++ b/app/src/main/res/layout/row_top_10.xml @@ -13,8 +13,8 @@ android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="8dp" - android:gravity="center" android:layout_marginEnd="16dp" + android:gravity="center" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" @@ -25,17 +25,87 @@ style="@style/PokerAnalyticsTheme.TextView.Top10Row" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="16dp" + android:layout_marginStart="8dp" android:layout_marginTop="4dp" - android:layout_marginEnd="16dp" + android:layout_marginEnd="8dp" android:gravity="center" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/gameResult" app:layout_constraintVertical_chainStyle="packed" tools:text="$300 NL Hold'em" /> + + + + + + + + + + + Date: Thu, 6 Jun 2019 19:00:39 +0200 Subject: [PATCH 004/125] Bump version code --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 4304c29c..b46f503c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,7 +29,7 @@ android { applicationId "net.pokeranalytics.android" minSdkVersion 23 targetSdkVersion 28 - versionCode 30 + versionCode 31 versionName "2.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } From f5babae7344be97acfe3bb5d260e6ff8684d46e0 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 7 Jun 2019 14:23:10 +0200 Subject: [PATCH 005/125] Upgrade test libs + bump version --- app/build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b46f503c..1c421f35 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,7 +29,7 @@ android { applicationId "net.pokeranalytics.android" minSdkVersion 23 targetSdkVersion 28 - versionCode 31 + versionCode 32 versionName "2.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -114,10 +114,10 @@ dependencies { implementation 'org.apache.commons:commons-csv:1.6' // Instrumented Tests - androidTestImplementation 'androidx.test:core:1.1.0' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test:rules:1.1.1' - androidTestImplementation 'androidx.test.ext:junit:1.1.0' + androidTestImplementation 'androidx.test:core:1.2.0' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test:rules:1.2.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' // Test testImplementation 'junit:junit:4.12' From db056d42f976ffbfc5de25151b846b6a4a469fdd Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 7 Jun 2019 14:38:32 +0200 Subject: [PATCH 006/125] Hides subscription row --- .../android/ui/view/rowrepresentable/SettingRow.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt index e3ab95ea..adda5f89 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt @@ -46,7 +46,8 @@ enum class SettingRow : RowRepresentable { val rows = ArrayList() rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.information)) - rows.addAll(arrayListOf(SUBSCRIPTION, VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) + rows.addAll(arrayListOf(VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) +// rows.addAll(arrayListOf(SUBSCRIPTION, VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.follow_us)) rows.addAll(arrayListOf(FOLLOW_US)) From 9ed96f17a09e0297c57565060a9c17d398b24371 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 7 Jun 2019 14:49:37 +0200 Subject: [PATCH 007/125] french translations --- app/src/main/res/values-fr/strings.xml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 28d11de2..67ab23ec 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -15,7 +15,28 @@ Passer Pro d\'essai gratuit Cette bankroll contient au moins une transaction empêchant la suppression. - + Illimité + Suivez toute votre vie de joueur en ajoutant autant de données que vous le souhaitez + Hors ligne avant tout + Poker Analytics est disponible à tout moment et vos données vous appartiennent. Vous êtes pour l\'instant en charge de faire des sauvegarde mais cela changera dans le futur! + Vie privée + Nous ne sauvegardons pas vos données, nous ne savons rien de vos gains ni de vos pertes + Support + Nous essayons de répondre le plus vite possible, en français ou en anglais ! + Chargement, veuillez patienter… + Choisissez un type de rapport + Choisissez une statistique, ou plusieurs + Sélectionnez un critère de comparaison, ou plusieurs + Sélectionnez un filtre ou lancez maintenant le rapport + Afficher le rapport + Evolution + Sauvegarder le rapport + Voulez-vous effectuer l\'import des données? + Graphique de comparaison + Le filtre ne peut être effacé car utilisé en ce moment + Champ perso + L\'élement est utilisé dans une ou plusieurs transactions…Veuillez effacer les transactions en premier lieu + À partir de Jusqu\'à ère From 95e4755cdf44f7eaa14b402552d99b7557064025 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 7 Jun 2019 14:50:32 +0200 Subject: [PATCH 008/125] cleanup --- app/src/main/res/values-fr/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 67ab23ec..f382b4fe 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -36,7 +36,7 @@ Le filtre ne peut être effacé car utilisé en ce moment Champ perso L\'élement est utilisé dans une ou plusieurs transactions…Veuillez effacer les transactions en premier lieu - + À partir de Jusqu\'à ère From f0dfe12ed9c41250fa551b8fde19178df0c15223 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 7 Jun 2019 18:03:05 +0200 Subject: [PATCH 009/125] bumped version 33 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 1c421f35..77cc85ce 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,7 +29,7 @@ android { applicationId "net.pokeranalytics.android" minSdkVersion 23 targetSdkVersion 28 - versionCode 32 + versionCode 33 versionName "2.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } From 6b452bd17e86d55da856f04ce1d1ec7ba559ee27 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 10 Jun 2019 10:45:49 +0200 Subject: [PATCH 010/125] realm: change to executeTransaction (from beginTransaction / commitTransaction) --- .../android/ui/fragment/FeedFragment.kt | 7 +++-- .../ui/fragment/FilterDetailsFragment.kt | 10 +++---- .../android/ui/fragment/FiltersFragment.kt | 26 +++++++++---------- .../android/ui/fragment/SessionFragment.kt | 19 +++++++------- .../android/ui/interfaces/FilterHandler.kt | 12 ++++----- 5 files changed, 34 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt index 35454cc4..3d026bfa 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt @@ -308,10 +308,9 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { * Delete selected transaction */ private fun deleteSelectedTransaction() { - val realm = getRealm() - realm.beginTransaction() - selectedTransaction?.deleteFromRealm() - realm.commitTransaction() + getRealm().executeTransaction { + selectedTransaction?.deleteFromRealm() + } selectedTransactionPosition = -1 } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FilterDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FilterDetailsFragment.kt index 7fe858e8..481557e5 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FilterDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FilterDetailsFragment.kt @@ -243,12 +243,10 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSo Timber.d("Selected rows: $it") } - val realm = getRealm() - realm.beginTransaction() - currentFilter?.remove(filterCategoryRow) - currentFilter?.createOrUpdateFilterConditions(selectedRows) - realm.commitTransaction() - + getRealm().executeTransaction { + currentFilter?.remove(filterCategoryRow) + currentFilter?.createOrUpdateFilterConditions(selectedRows) + } currentFilter?.filterConditions?.forEach { Timber.d("Condition: $it") } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt index 3aeebf19..0a1b696e 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt @@ -251,13 +251,12 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, * Validate the updates of the queryWith */ private fun validateUpdates() { - val realm = getRealm() - realm.beginTransaction() - currentFilter?.let { - it.name = it.query.getName(requireContext()) - realm.copyToRealmOrUpdate(it) - } - realm.commitTransaction() + getRealm().executeTransaction { realm -> + currentFilter?.let { + it.name = it.query.getName(requireContext()) + realm.copyToRealmOrUpdate(it) + } + } val filterId = currentFilter?.id ?: "" finishActivityWithResult(filterId) @@ -268,13 +267,12 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, */ private fun cancelUpdates() { val filterId = filterCopy?.id ?: "" - val realm = getRealm() - realm.beginTransaction() - filterCopy?.let { - realm.copyToRealmOrUpdate(it) - } - realm.commitTransaction() - finishActivityWithResult(filterId) + getRealm().executeTransaction { realm -> + filterCopy?.let { + realm.copyToRealmOrUpdate(it) + } + } + finishActivityWithResult(filterId) } /** diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt index cb13262e..aefaa32d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt @@ -67,20 +67,19 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate { currentSession = sessionRealm sessionHasBeenCustomized = true } else { - realm.beginTransaction() - currentSession = Session.newInstance(realm, isTournament) - FavoriteSessionFinder.copyParametersFromFavoriteSession(currentSession, null, requireContext()) - realm.commitTransaction() - + realm.executeTransaction { executeRealm -> + currentSession = Session.newInstance(executeRealm, isTournament) + FavoriteSessionFinder.copyParametersFromFavoriteSession(currentSession, null, requireContext()) + } // Find the nearest location around the user parentActivity?.findNearestLocation { it?.let { location -> - realm.beginTransaction() - val realmLocation = realm.findById(location.id) - FavoriteSessionFinder.copyParametersFromFavoriteSession(currentSession, realmLocation, requireContext()) + realm.executeTransaction { executeRealm -> + val realmLocation = executeRealm.findById(location.id) + FavoriteSessionFinder.copyParametersFromFavoriteSession(currentSession, realmLocation, requireContext()) - currentSession.location = realmLocation - realm.commitTransaction() + currentSession.location = realmLocation + } updateSessionUI(true) } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/interfaces/FilterHandler.kt b/app/src/main/java/net/pokeranalytics/android/ui/interfaces/FilterHandler.kt index 15d45a77..8e8c1167 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/interfaces/FilterHandler.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/interfaces/FilterHandler.kt @@ -47,12 +47,12 @@ interface FilterHandler { val realm = Realm.getDefaultInstance() - realm.beginTransaction() - currentFilter(context, realm)?.let { - it.useCount++ - } - realm.commitTransaction() - realm.close() + realm.executeTransaction { executeRealm -> + currentFilter(context, executeRealm)?.let { + it.useCount++ + } + } + realm.close() // Send broadcast val intent = Intent() From 2210016627e7c00a806347e5bd3ad2c34392bbed Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 10 Jun 2019 11:02:28 +0200 Subject: [PATCH 011/125] filter / duration fix crash when the user validate empty values --- .../components/bottomsheet/BottomSheetDoubleEditTextFragment.kt | 2 ++ 1 file changed, 2 insertions(+) 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 320197f1..814ff646 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 @@ -35,6 +35,8 @@ class BottomSheetDoubleEditTextFragment : BottomSheetFragment() { } override fun getValue(): Any? { + if (values.isEmpty()) { return null } + if (values.all { it.isEmpty() }) { return null } return values } From fbaf8c869e0c2a8cc60a895fc06af3a102bbd182 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 10 Jun 2019 13:00:44 +0200 Subject: [PATCH 012/125] Filter: fix issue with place holder --- .../bottomsheet/BottomSheetDoubleEditTextFragment.kt | 4 ++-- .../android/ui/view/rowrepresentable/FilterElementRow.kt | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) 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 814ff646..14adf917 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 @@ -71,8 +71,8 @@ class BottomSheetDoubleEditTextFragment : BottomSheetFragment() { editText2.inputType = data[1].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES if (valueHasPlaceholder) { - editText1.hint = values[0] - editText2.hint = values[1] + if (values[0].isNotBlank()) { editText1.hint = values[0] } + if (values[1].isNotBlank()) { editText2.hint = values[1] } } else { editText1.setText(values[0]) editText2.setText(values[1]) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt index 3e8b783e..9829f9ee 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt @@ -22,8 +22,13 @@ interface FilterElementRow : RowRepresentable { } is QueryCondition.ListOfValues<*> -> { val valueAsString: String? by map + val hint = when (this.operator) { + QueryCondition.Operator.MORE, QueryCondition.Operator.LESS -> this.filterSectionRow.resId + else -> this.resId + } + arrayListOf( - RowRepresentableEditDescriptor(valueAsString, this.resId, inputType = InputType.TYPE_CLASS_NUMBER) + RowRepresentableEditDescriptor(valueAsString, hint, inputType = InputType.TYPE_CLASS_NUMBER) ) } else -> super.editingDescriptors(map) From ed372c1c712d5ddbb0fc90104accf38986321621 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 10 Jun 2019 14:02:33 +0200 Subject: [PATCH 013/125] Fixing issue where tab item were truncated on selection --- app/src/main/res/values/dimens.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 47c82246..802da918 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,5 +1,8 @@ - + 16dp 16dp + + 12sp + 11sp From 7cc2510da3ed7d8d6afbfb962de19f511df250a6 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 10 Jun 2019 14:15:28 +0200 Subject: [PATCH 014/125] Fixing tab item sizes --- app/src/main/res/values/dimens.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 802da918..1f75d3f0 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,8 +1,8 @@ - - 16dp - 16dp + +16dp +16dp - 12sp - 11sp +12sp +11sp From 3e9e61b9483812290d4716a65376f556252737f9 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 10 Jun 2019 14:15:42 +0200 Subject: [PATCH 015/125] Filter / custom field : fix res id issue for place holder --- .../android/ui/view/rowrepresentable/FilterElementRow.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt index 9829f9ee..43860b3a 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt @@ -23,7 +23,13 @@ interface FilterElementRow : RowRepresentable { is QueryCondition.ListOfValues<*> -> { val valueAsString: String? by map val hint = when (this.operator) { - QueryCondition.Operator.MORE, QueryCondition.Operator.LESS -> this.filterSectionRow.resId + QueryCondition.Operator.MORE, QueryCondition.Operator.LESS -> { + when (this) { + is QueryCondition.CustomFieldNumberQuery -> R.string.value + is QueryCondition.CustomFieldAmountQuery -> R.string.amount + else -> this.filterSectionRow.resId + } + } else -> this.resId } From 61e0d080f059dbfa75404902a874e332a6b36e55 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 10 Jun 2019 14:25:46 +0200 Subject: [PATCH 016/125] file formatting --- app/src/main/res/values/dimens.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 1f75d3f0..802da918 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,8 +1,8 @@ - -16dp -16dp + + 16dp + 16dp -12sp -11sp + 12sp + 11sp From 31c2038857c7378a48d06e89e7799b284f4848c7 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 10 Jun 2019 14:46:26 +0200 Subject: [PATCH 017/125] bumping to 35 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 77cc85ce..91d6b38d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,7 +29,7 @@ android { applicationId "net.pokeranalytics.android" minSdkVersion 23 targetSdkVersion 28 - versionCode 33 + versionCode 35 versionName "2.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } From 4c79b32c1f4ecf0f40858dab28448f2384e434e7 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 11 Jun 2019 18:07:20 +0200 Subject: [PATCH 018/125] Fixing bankroll report updates --- .../android/PokerAnalyticsApplication.kt | 2 +- .../pokeranalytics/android/calculus/Stat.kt | 1 + .../calculus/bankroll/BankrollCalculator.kt | 9 +- .../calculus/bankroll/BankrollReport.kt | 93 ++----- .../bankroll/BankrollReportManager.kt | 114 ++++++++ .../android/exceptions/Exceptions.kt | 1 + .../android/ui/activity/BankrollActivity.kt | 41 --- .../android/ui/activity/components/Codes.kt | 2 + .../ui/fragment/BankrollDetailsFragment.kt | 135 +++++++--- .../android/ui/fragment/BankrollFragment.kt | 127 ++++----- .../android/ui/fragment/FeedFragment.kt | 13 +- .../android/ui/fragment/SessionFragment.kt | 4 + .../components/DeletableItemFragment.kt | 4 +- .../ui/fragment/data/DataManagerFragment.kt | 4 + .../fragment/data/TransactionDataFragment.kt | 8 + .../android/ui/view/RowViewType.kt | 251 ++++++++++-------- .../view/rowrepresentable/BankrollMainRow.kt | 12 + .../CustomizableRowRepresentable.kt | 11 + .../ui/view/rowrepresentable/GraphRow.kt | 9 +- 19 files changed, 502 insertions(+), 339 deletions(-) create mode 100644 app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt create mode 100644 app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/BankrollMainRow.kt diff --git a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt index 35ea4536..1b81d955 100644 --- a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt +++ b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt @@ -60,7 +60,7 @@ class PokerAnalyticsApplication : Application() { if (BuildConfig.DEBUG) { Timber.d("UserPreferences.defaultCurrency: ${UserDefaults.currency.symbol}") -// this.createFakeSessions() + this.createFakeSessions() } Patcher.patchAll(this.applicationContext) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt index d065af5f..2b8a30c8 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt @@ -177,6 +177,7 @@ enum class Stat(override var uniqueIdentifier: Int) : IntIdentifiable, RowRepres private val threshold: Double get() { return when (this) { + RISK_OF_RUIN -> 5.0 WIN_RATIO -> 50.0 else -> 0.0 } diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt index 2f889e24..3f7b144a 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt @@ -5,7 +5,9 @@ import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.ComputableGroup import net.pokeranalytics.android.calculus.ComputedResults import net.pokeranalytics.android.calculus.Stat +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.realm.* +import net.pokeranalytics.android.util.extensions.findById class BankrollCalculator { @@ -18,7 +20,10 @@ class BankrollCalculator { val report = BankrollReport(setup) val bankrolls: List = - if (setup.bankroll != null) listOf(setup.bankroll) + if (setup.bankrollId != null) { + val bankroll = realm.findById(setup.bankrollId) ?: throw PAIllegalStateException("Bankroll not found with id=${setup.bankrollId}") + listOf(bankroll) + } else realm.where(Bankroll::class.java).findAll() var initialValue = 0.0 @@ -41,7 +46,7 @@ class BankrollCalculator { report.transactionsNet = transactionNet report.initial = initialValue - val query = setup.query + val query = setup.query(realm) val transactions = Filter.queryOn(realm, query) report.addDatedItems(transactions) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt index 2b7e4724..b6c079d6 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt @@ -3,54 +3,22 @@ package net.pokeranalytics.android.calculus.bankroll import android.content.Context import com.github.mikephil.charting.data.Entry import com.github.mikephil.charting.data.LineDataSet +import io.realm.Realm import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.interfaces.DatedValue import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.ui.graph.DataSetFactory -import net.pokeranalytics.android.ui.view.RowRepresentable -import net.pokeranalytics.android.ui.view.RowViewType +import net.pokeranalytics.android.util.extensions.findById import java.util.* import kotlin.collections.HashMap -//object BankrollReportManager { -// -// var mainReport: BankrollReport? = null -// var reports: MutableMap = mutableMapOf() -// -// fun udpateBankrolls(bankrolls: List) { -// this.invalidateMainReport() -// bankrolls.forEach { -// this.reports.remove(it.id) -// } -// } -// -// fun deleteBankrolls(bankrolls: List) { -// this.invalidateMainReport() -// bankrolls.forEach { -// this.reports.remove(it.id) -// } -// } -// -// private fun invalidateMainReport() { -// this.mainReport = null -// } -// -// private fun launchReports(bankrolls: List) { -// -// this.mainReport = BankrollCalculator.computeReport() -// -// -// } -// -//} - /** * This class holds the results from the BankrollCalculator computations * It has all the information required for the Bankroll various displays */ -class BankrollReport(var setup: BankrollReportSetup) : RowRepresentable { +class BankrollReport(var setup: BankrollReportSetup) { /** * The value of the bankroll @@ -150,15 +118,6 @@ class BankrollReport(var setup: BankrollReportSetup) : RowRepresentable { */ private var evolutionItems: MutableList = mutableListOf() - override val viewType: Int - get() { - return if (setup.bankroll == null) { - RowViewType.LEGEND_DEFAULT.ordinal - } else { - RowViewType.TITLE_VALUE_ARROW.ordinal - } - } - /** * Adds a list of dated items to the evolution items used to get the bankroll graph */ @@ -176,7 +135,7 @@ class BankrollReport(var setup: BankrollReportSetup) : RowRepresentable { var bucket = this.transactionBuckets[type.id] if (bucket == null) { - val b = TransactionBucket(this.setup.virtualBankroll) + val b = TransactionBucket(type.name, this.setup.virtualBankroll) this.transactionBuckets[type.id] = b bucket = b } @@ -200,7 +159,7 @@ class BankrollReport(var setup: BankrollReportSetup) : RowRepresentable { this.evolutionItems.sortBy { it.date } - var total = 0.0 + var total = this.initial this.evolutionItems.forEach { total += it.amount val point = BRGraphPoint(total, it.date, it) @@ -228,7 +187,7 @@ class BankrollReport(var setup: BankrollReportSetup) : RowRepresentable { * A class describing the parameters required to launch a bankroll report * */ -class BankrollReportSetup(val bankroll: Bankroll? = null, val from: Date? = null, val to: Date? = null) { +class BankrollReportSetup(val bankrollId: String? = null, val from: Date? = null, val to: Date? = null) { /** * Returns whether the setup concerns the virtual bankroll, @@ -236,32 +195,32 @@ class BankrollReportSetup(val bankroll: Bankroll? = null, val from: Date? = null */ val virtualBankroll: Boolean get() { - return this.bankroll == null + return this.bankrollId == null } /** * the query used to get bankroll transactions */ - val query: Query - get() { - val query = Query() + fun query(realm: Realm): Query { + val query = Query() - this.bankroll?.let { - val bankrollCondition = QueryCondition.AnyBankroll(bankroll) - query.add(bankrollCondition) - } - this.from?.let { - val fromCondition = QueryCondition.StartedFromDate() - fromCondition.singleValue = it - query.add(fromCondition) - } - this.to?.let { - val toCondition = QueryCondition.StartedToDate() - toCondition.singleValue = it - query.add(toCondition) - } - return query + this.bankrollId?.let { + val bankroll = realm.findById(it) ?: throw IllegalStateException("Bankroll not found with id $it") + val bankrollCondition = QueryCondition.AnyBankroll(bankroll) + query.add(bankrollCondition) } + this.from?.let { + val fromCondition = QueryCondition.StartedFromDate() + fromCondition.singleValue = it + query.add(fromCondition) + } + this.to?.let { + val toCondition = QueryCondition.StartedToDate() + toCondition.singleValue = it + query.add(toCondition) + } + return query + } /** * Returns whether or not the initial value should be added for the bankroll total @@ -276,7 +235,7 @@ class BankrollReportSetup(val bankroll: Bankroll? = null, val from: Date? = null /** * A TransactionBucket holds a list of _transactions and computes its amount sum */ -class TransactionBucket(useRate: Boolean = false) { +class TransactionBucket(var name: String, useRate: Boolean = false) { /** * Whether the bankroll rate should be used diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt new file mode 100644 index 00000000..9f68008f --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt @@ -0,0 +1,114 @@ +package net.pokeranalytics.android.calculus.bankroll + +import io.realm.Realm +import io.realm.RealmResults +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.async +import kotlinx.coroutines.launch +import net.pokeranalytics.android.model.realm.Bankroll +import net.pokeranalytics.android.model.realm.ComputableResult +import net.pokeranalytics.android.model.realm.Transaction +import timber.log.Timber +import java.util.* +import kotlin.coroutines.CoroutineContext + +object BankrollReportManager { + + val coroutineContext: CoroutineContext + get() = Dispatchers.Main + + private var reports: MutableMap = mutableMapOf() + + private var computableResults: RealmResults + private var bankrolls: RealmResults + private var transactions: RealmResults + + init { + + val realm = Realm.getDefaultInstance() + computableResults = realm.where(ComputableResult::class.java).findAll() + bankrolls = realm.where(Bankroll::class.java).findAll() + transactions = realm.where(Transaction::class.java).findAll() + + initializeListeners() + realm.close() + } + + /** + * Listens to all objects that might have an impact on any bankroll report + */ + private fun initializeListeners() { + + this.computableResults.addChangeListener { t, changeSet -> + val indexes = changeSet.changes.plus(changeSet.insertions).toList() + val bankrolls = indexes.mapNotNull { t[it]?.session?.bankroll }.toSet() + this.updateBankrolls(bankrolls) + } + this.bankrolls.addChangeListener { t, changeSet -> + val indexes = changeSet.changes.plus(changeSet.insertions).toList() + val bankrolls = indexes.mapNotNull { t[it] }.toSet() + this.updateBankrolls(bankrolls) + } + this.transactions.addChangeListener { t, changeSet -> + val indexes = changeSet.changes.plus(changeSet.insertions).toList() + val bankrolls = indexes.mapNotNull { t[it]?.bankroll }.toSet() + this.updateBankrolls(bankrolls) + } + } + + fun reportForBankroll(bankrollId: String?, handler: (BankrollReport) -> Unit) { + + // if the report exists, return it + val existingReport: BankrollReport? = this.reports[bankrollId] + if (existingReport != null) { + handler(existingReport) + return + } + + // otherwise compute it + GlobalScope.launch(coroutineContext) { + + var report: BankrollReport? = null + val scope = GlobalScope.async { + val s = Date() + Timber.d(">>>>> start computing bankroll...") + + val realm = Realm.getDefaultInstance() + + val setup = BankrollReportSetup(bankrollId) + report = BankrollCalculator.computeReport(realm, setup) + + realm.close() + + val e = Date() + val duration = (e.time - s.time) / 1000.0 + Timber.d(">>>>> ended in $duration seconds") + + } + scope.await() + report?.let { handler(it) } + + } + } + + /** + * Notifies the manager of cases not managed by RealmResults listener, such as deletions + */ + fun notifyBankrollReportImpact(bankrollId: String) { + this.reports.remove(bankrollId) + this.reports.remove(null) + } + + private fun updateBankrolls(bankrolls: Set) { + this.invalidateReport(bankrolls) + } + + private fun invalidateReport(bankrolls: Set) { + this.reports.remove(null) + bankrolls.forEach { br -> + this.reports.remove(br.id) + } + } + +} diff --git a/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt b/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt index 7716e745..b8358605 100644 --- a/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt +++ b/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt @@ -10,6 +10,7 @@ class ConfigurationException(message: String) : Exception(message) class EnumIdentifierNotFoundException(message: String) : Exception(message) class MisconfiguredSavableEnumException(message: String) : Exception(message) +class PAIllegalStateException(message: String) : Exception(message) sealed class PokerAnalyticsException(message: String) : Exception(message) { object FilterElementUnknownName : PokerAnalyticsException(message = "No filterElement name was found to identify the queryCondition") diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/BankrollActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/BankrollActivity.kt index 0f37c4d8..db9237b3 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/BankrollActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/BankrollActivity.kt @@ -37,47 +37,6 @@ class BankrollActivity : PokerAnalyticsActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bankroll) -// this.computableResults = getRealm().where(ComputableResult::class.java).findAll() // ComputableResult are existing only if sessions are ended -// this.computableResults.addChangeListener { t, changeSet -> -// -// val bankrolls = mutableSetOf() -// val indexes = mutableSetOf() -// indexes.addAll(changeSet.changes.toList()) -// indexes.addAll(changeSet.insertions.toList()) -// indexes.addAll(changeSet.deletions.toList()) -// indexes.forEach { index -> -// t[index]?.session?.bankroll?.let { br -> -// bankrolls.add(br) -// } -// } -// this.computeBankrollReports(bankrolls) -// } -// this.bankrolls = getRealm().where(Bankroll::class.java).findAll() // ComputableResult are existing only if sessions are ended -// this.bankrolls.addChangeListener { _, changeSet -> -// -// -// -// -// -// } -// this.transactions = getRealm().where(Transaction::class.java).findAll() // ComputableResult are existing only if sessions are ended -// this.transactions.addChangeListener { t, changeSet -> -// -// val bankrolls = mutableSetOf() -// val indexes = mutableSetOf() -// indexes.addAll(changeSet.changes.toList()) -// indexes.addAll(changeSet.insertions.toList()) -// indexes.addAll(changeSet.deletions.toList()) -// indexes.forEach { index -> -// if (t.isNotEmpty()) { -// t[index]?.bankroll?.let { br -> -// bankrolls.add(br) -// } -// } -// } -// this.computeBankrollReports(bankrolls) -// } - } fun computeBankrollReports(bankrolls: Collection) { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt index ed11d47f..23cb64f8 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt @@ -2,6 +2,8 @@ package net.pokeranalytics.android.ui.activity.components enum class RequestCode(var value: Int) { DEFAULT(1), + BANKROLL_DETAILS(700), + BANKROLL_CREATE(701), NEW_SESSION(800), NEW_TRANSACTION(801), NEW_REPORT(802), diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt index ab2175f2..923695d5 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt @@ -10,18 +10,22 @@ import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.bankroll.BankrollReport +import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.LiveData +import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.ui.activity.DataListActivity import net.pokeranalytics.android.ui.activity.EditableDataActivity import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource -import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment +import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable +import net.pokeranalytics.android.util.extensions.findById -class BankrollDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { +class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { companion object { @@ -32,27 +36,32 @@ class BankrollDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable */ fun newInstance(bankrollReport: BankrollReport): BankrollDetailsFragment { val fragment = BankrollDetailsFragment() - fragment.bankrollReport = bankrollReport + fragment.bankrollId = bankrollReport.setup.bankrollId +// fragment.bankrollReport = bankrollReport return fragment } } + private var bankrollId: String? = null + private lateinit var bankroll: Bankroll + + private var rows: ArrayList = ArrayList() private lateinit var bankrollAdapter: RowRepresentableAdapter - private lateinit var bankrollReport: BankrollReport +// private lateinit var bankrollReport: BankrollReport private var bankrollDetailsMenu: Menu? = null - private var rows: ArrayList = ArrayList() // Life Cycle override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.fragment_bankroll_details, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - initUI() initData() + initUI() } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { @@ -62,40 +71,35 @@ class BankrollDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable activity?.setResult(RESULT_OK, data) activity?.finish() } else { - updateMenuUI() + BankrollReportManager.reportForBankroll(this.bankrollId) { + updateUI(it) + } } } } - override fun adapterRows(): List? { - return rows + private fun updateUI(bankrollReport: BankrollReport) { + this.initRows(bankrollReport) + this.updateMenuUI(bankrollReport) + this.bankrollAdapter.notifyDataSetChanged() } - override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { - - } + /** + * Init data + */ + private fun initData() { - override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { - menu?.clear() - inflater?.inflate(R.menu.toolbar_comparison_chart, menu) - this.bankrollDetailsMenu = menu - updateMenuUI() - super.onCreateOptionsMenu(menu, inflater) - } + this.bankrollId?.let { id -> + this.bankroll = getRealm().findById(id) ?: throw PAIllegalStateException("Bankroll not found, id=$id") + } - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - when (item!!.itemId) { - R.id.settings -> editBankroll() + BankrollReportManager.reportForBankroll(this.bankrollId) { + updateUI(it) } - return true - } - // Business + } - /** - * Init data - */ - private fun initData() { + private fun initRows(bankrollReport: BankrollReport) { rows.clear() @@ -105,23 +109,47 @@ class BankrollDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable val netComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netResult) val netBankedComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netBanked) - rows.add(CustomizableRowRepresentable(RowViewType.TITLE_VALUE, resId = R.string.bankroll, computedStat = totalComputedStat)) - rows.add(CustomizableRowRepresentable(RowViewType.TITLE_VALUE, resId = R.string.net_result, computedStat = netComputedStat)) - rows.add(CustomizableRowRepresentable(RowViewType.TITLE_VALUE, resId = R.string.net_banked, computedStat = netBankedComputedStat)) + rows.add( + CustomizableRowRepresentable( + RowViewType.TITLE_VALUE, + resId = R.string.bankroll, + computedStat = totalComputedStat + ) + ) + rows.add( + CustomizableRowRepresentable( + RowViewType.TITLE_VALUE, + resId = R.string.net_result, + computedStat = netComputedStat + ) + ) + rows.add( + CustomizableRowRepresentable( + RowViewType.TITLE_VALUE, + resId = R.string.net_banked, + computedStat = netBankedComputedStat + ) + ) if (bankrollReport.transactionBuckets.isNotEmpty()) { rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.operations)) bankrollReport.transactionBuckets.keys.forEach { key -> bankrollReport.transactionBuckets[key]?.let { transactionBucket -> - val typeName = transactionBucket.transactions.firstOrNull()?.type?.getDisplayName(requireContext()) + val typeName = transactionBucket.name val computedStat = ComputedStat(Stat.NET_RESULT, transactionBucket.total) - rows.add(CustomizableRowRepresentable(RowViewType.TITLE_VALUE, title = typeName, computedStat = computedStat)) + rows.add( + CustomizableRowRepresentable( + RowViewType.TITLE_VALUE, + title = typeName, + computedStat = computedStat + ) + ) } } } - } + /** * Init UI */ @@ -129,8 +157,6 @@ class BankrollDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable setDisplayHomeAsUpEnabled(true) - updateMenuUI() - bankrollAdapter = RowRepresentableAdapter(this, this) val viewManager = LinearLayoutManager(requireContext()) @@ -145,23 +171,52 @@ class BankrollDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable /** * Update menu UI */ - private fun updateMenuUI() { + private fun updateMenuUI(bankrollReport: BankrollReport) { if (bankrollReport.setup.virtualBankroll) { setToolbarTitle(getString(R.string.total)) bankrollDetailsMenu?.findItem(R.id.settings)?.isVisible = false } else { - setToolbarTitle(bankrollReport.setup.bankroll?.name) + setToolbarTitle(this.bankroll.name) bankrollDetailsMenu?.findItem(R.id.settings)?.isVisible = true } } + // StaticRowRepresentableDataSource + + override fun adapterRows(): List? { + return rows + } + + // RowRepresentableDelegate + + override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { + + } + + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + menu?.clear() + inflater?.inflate(R.menu.toolbar_comparison_chart, menu) + this.bankrollDetailsMenu = menu +// updateMenuUI() + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + when (item!!.itemId) { + R.id.settings -> editBankroll() + } + return true + } + + // Business + /** * Open Bankroll edit activity */ private fun editBankroll() { - EditableDataActivity.newInstanceForResult(this, LiveData.BANKROLL, bankrollReport.setup.bankroll?.id, REQUEST_CODE_EDIT) + EditableDataActivity.newInstanceForResult(this, LiveData.BANKROLL, this.bankrollId, REQUEST_CODE_EDIT) } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt index 58e954a9..0524f996 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt @@ -16,39 +16,34 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import net.pokeranalytics.android.R -import net.pokeranalytics.android.calculus.ComputedStat -import net.pokeranalytics.android.calculus.Stat -import net.pokeranalytics.android.calculus.bankroll.BankrollCalculator -import net.pokeranalytics.android.calculus.bankroll.BankrollReport -import net.pokeranalytics.android.calculus.bankroll.BankrollReportSetup +import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.interfaces.Deletable -import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.ui.activity.BankrollDetailsActivity import net.pokeranalytics.android.ui.activity.DataListActivity import net.pokeranalytics.android.ui.activity.EditableDataActivity import net.pokeranalytics.android.ui.activity.GraphActivity +import net.pokeranalytics.android.ui.activity.components.RequestCode import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.fragment.components.DeletableItemFragment import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType -import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable -import net.pokeranalytics.android.ui.view.rowrepresentable.GraphRow +import net.pokeranalytics.android.ui.view.rowrepresentable.* import net.pokeranalytics.android.util.extensions.sorted -import timber.log.Timber import java.util.* import kotlin.collections.ArrayList +interface BankrollRowRepresentable : RowRepresentable { + var bankrollId: String? +} + class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { companion object { - const val REQUEST_CODE_DETAILS = 100 - const val REQUEST_CODE_CREATE = 101 - /** * Create new instance */ @@ -61,14 +56,14 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour } private var rows: ArrayList = ArrayList() - private var bankrollReportForRow: HashMap = HashMap() + private var bankrollRowRepresentables: HashMap> = HashMap() private var lastItemClickedPosition: Int = 0 - private var lastItemClickedId: String = "" +// private var lastItemClickedId: String = "" private var deletedRow: RowRepresentable? = null private lateinit var bankrolls: RealmResults - override fun deletableItems() : List { + override fun deletableItems(): List { return this.bankrolls } @@ -85,21 +80,26 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour initData() } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (requestCode == REQUEST_CODE_DETAILS && resultCode == Activity.RESULT_OK) { + if (requestCode == RequestCode.BANKROLL_DETAILS.value && resultCode == Activity.RESULT_OK) { val itemToDeleteId = data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName) itemToDeleteId?.let { id -> GlobalScope.launch(Dispatchers.Main) { delay(300) deleteItem(dataListAdapter, bankrolls, id) + + // update view + BankrollReportManager.notifyBankrollReportImpact(id) + dataListAdapter.notifyDataSetChanged() } } - } else if (requestCode == REQUEST_CODE_CREATE && resultCode == Activity.RESULT_OK) { + } else if (requestCode == RequestCode.BANKROLL_CREATE.value && resultCode == Activity.RESULT_OK) { //TODO: Refresh bankrolls initData() + } else { + dataListAdapter.notifyDataSetChanged() } } @@ -109,20 +109,19 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour } override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { + lastItemClickedPosition = position when (row) { + is BankrollRowRepresentable -> { + BankrollReportManager.reportForBankroll(row.bankrollId) { bankrollReport -> + +// lastItemClickedId = row.bankrollId ?: "" + BankrollDetailsActivity.newInstanceForResult(this, bankrollReport, RequestCode.BANKROLL_DETAILS.value) + } + } is GraphRow -> { val lineDataSet = row.dataSet as LineDataSet GraphActivity.newInstance(requireContext(), listOf(lineDataSet), title = getString(R.string.bankroll)) } - else -> { - if (bankrollReportForRow.containsKey(row)) { - bankrollReportForRow[row]?.let { bankrollReport -> - lastItemClickedPosition = position - lastItemClickedId = (row as? Identifiable)?.id ?: "" - BankrollDetailsActivity.newInstanceForResult(this, bankrollReport, REQUEST_CODE_DETAILS) - } - } - } } } @@ -137,49 +136,26 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour this.bankrolls = realm.sorted() rows.clear() - bankrollReportForRow.clear() - - GlobalScope.launch { - - launch(Dispatchers.Main) { - // TODO: Improve that - // We are in the main thread... + // Virtual bankroll + val graphRow = BankrollGraphRow() + rows.add(0, graphRow) + val mainRow = BankrollMainRow() + rows.add(mainRow) - val startDate = Date() + bankrollRowRepresentables[null] = listOf(graphRow, mainRow) - // Graph - val globalBankrollReportSetup = BankrollReportSetup() - val globalBankrollReport = BankrollCalculator.computeReport(getRealm(), globalBankrollReportSetup) - rows.add(0, GraphRow(dataSet = globalBankrollReport.lineDataSet(requireContext()))) - rows.add(globalBankrollReport) - bankrollReportForRow[globalBankrollReport] = globalBankrollReport + // Bankrolls + rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.bankrolls)) - // Bankrolls - rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.bankrolls)) - - Timber.d("initData: ${System.currentTimeMillis() - startDate.time}ms") - -// val bankrolls = LiveData.Bankroll.items(getRealm()) as RealmResults - - bankrolls.forEach { bankroll -> - val bankrollReportSetup = BankrollReportSetup(bankroll) - val bankrollReport = BankrollCalculator.computeReport(getRealm(), bankrollReportSetup) - val computedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.total) - val row = - CustomizableRowRepresentable(RowViewType.TITLE_VALUE_ARROW, title = bankroll.name, computedStat = computedStat, isSelectable = true) - row.id = bankroll.id - - rows.add(row) - bankrollReportForRow[row] = bankrollReport - } - - if (!isDetached) { - dataListAdapter.notifyDataSetChanged() - } - } + bankrolls.forEach { bankroll -> + val row = BankrollTotalRow(bankroll.id, bankroll.name) + rows.add(row) + bankrollRowRepresentables[bankroll.id] = listOf(row) } + dataListAdapter.notifyDataSetChanged() + } /** @@ -200,13 +176,18 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour } addButton.setOnClickListener { - EditableDataActivity.newInstanceForResult(this@BankrollFragment, dataType = LiveData.BANKROLL, primaryKey = null, requestCode = REQUEST_CODE_CREATE) + EditableDataActivity.newInstanceForResult( + this@BankrollFragment, + dataType = LiveData.BANKROLL, + primaryKey = null, + requestCode = RequestCode.BANKROLL_CREATE.value + ) } } - override fun updateUIAfterDeletion(itemPosition: Int) { - lastItemClickedPosition = rows.indexOfFirst { if (it is Identifiable) it.id == lastItemClickedId else false } - deletedRow = rows.find { if (it is Identifiable) it.id == lastItemClickedId else false } + override fun updateUIAfterDeletion(itemId: String, itemPosition: Int) { + lastItemClickedPosition = rows.indexOfFirst { if (it is BankrollRowRepresentable) it.bankrollId == itemId else false } + deletedRow = rows.find { if (it is BankrollRowRepresentable) it.bankrollId == itemId else false } rows.removeAt(lastItemClickedPosition) dataListAdapter.notifyItemRemoved(lastItemClickedPosition) } @@ -217,12 +198,14 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour // We are recreating a Bankroll report because the last one is invalid => the bankroll of the setup has been deleted deletedRow?.let { row -> - val bankrollReportSetup = BankrollReportSetup(newItem as Bankroll) - val bankrollReport = BankrollCalculator.computeReport(getRealm(), bankrollReportSetup) - bankrollReportForRow[row] = bankrollReport +// val bankrollReportSetup = BankrollReportSetup(newItem as Bankroll) +// val bankrollReport = BankrollCalculator.computeReport(getRealm(), bankrollReportSetup) +// bankrollReportForRow[row] = bankrollReport rows.add(lastItemClickedPosition, row) - dataListAdapter.notifyItemInserted(lastItemClickedPosition) + dataListAdapter.notifyDataSetChanged() // update both virtual + ex-deleted + +// dataListAdapter.notifyItemInserted(lastItemClickedPosition) } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt index 3d026bfa..cd33cc31 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt @@ -33,6 +33,7 @@ import net.pokeranalytics.android.ui.interfaces.FilterableType import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager import net.pokeranalytics.android.util.Preferences +import net.pokeranalytics.android.util.billing.AppGuard import java.text.SimpleDateFormat import java.util.* @@ -274,12 +275,12 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { */ private fun createNewSession(isTournament: Boolean) { -// val sessionCount = this.feedSessionAdapter.realmResults.size -// if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG -// Toast.makeText(context, "Please subscribe!", Toast.LENGTH_LONG).show() -// BillingActivity.newInstanceForResult(requireContext()) -// return -// } + val sessionCount = this.feedSessionAdapter.realmResults.size + if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG + Toast.makeText(context, "Please subscribe!", Toast.LENGTH_LONG).show() + BillingActivity.newInstance(requireContext()) + return + } if (Date().after(betaLimitDate)) { this.showEndOfBetaMessage() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt index aefaa32d..0f1a2da3 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt @@ -10,6 +10,7 @@ import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.recyclerview.widget.DiffUtil import kotlinx.android.synthetic.main.fragment_session.* import net.pokeranalytics.android.R +import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.extensions.SessionState import net.pokeranalytics.android.model.extensions.getState @@ -344,6 +345,9 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate { * Delete a session */ private fun deleteSession() { + currentSession.bankroll?.id?.let { id -> + BankrollReportManager.notifyBankrollReportImpact(id) + } currentSession.delete() activity?.finish() } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt index 71cea8c1..07595c6d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt @@ -92,7 +92,7 @@ abstract class DeletableItemFragment : RealmFragment() { itemToDelete.deleteFromRealm() } itemHasBeenReInserted = false - updateUIAfterDeletion(itemPosition) + updateUIAfterDeletion(itemId, itemPosition) showUndoSnackBar() } else { dataListAdapter.notifyItemChanged(itemPosition) @@ -133,7 +133,7 @@ abstract class DeletableItemFragment : RealmFragment() { /** * Called once the object has been deleted */ - open fun updateUIAfterDeletion(itemPosition: Int) { + open fun updateUIAfterDeletion(itemId: String, itemPosition: Int) { dataListAdapter.notifyItemRemoved(itemPosition) } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/DataManagerFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/DataManagerFragment.kt index a7ee9216..1234528b 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/DataManagerFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/DataManagerFragment.kt @@ -128,6 +128,8 @@ open class DataManagerFragment : RealmFragment() { */ protected open fun deleteData() { + this.willDeleteData() + val realm = this.getRealm() if (this.item.isValidForDelete(realm)) { @@ -145,6 +147,8 @@ open class DataManagerFragment : RealmFragment() { } } + open fun willDeleteData() { } + /** * Finish the activity with a result */ diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/TransactionDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/TransactionDataFragment.kt index 789c00ed..9d60fe96 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/TransactionDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/TransactionDataFragment.kt @@ -6,6 +6,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.model.realm.TransactionType @@ -115,4 +116,11 @@ class TransactionDataFragment : EditableDataFragment(), StaticRowRepresentableDa } } + override fun willDeleteData() { + super.willDeleteData() + this.transaction?.bankroll?.id?.let { id -> + BankrollReportManager.notifyBankrollReportImpact(id) + } + } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt index 12ccaece..42e6da6f 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt @@ -14,10 +14,7 @@ import androidx.core.widget.ContentLoadingProgressBar import androidx.recyclerview.widget.RecyclerView import com.github.mikephil.charting.charts.BarChart import com.github.mikephil.charting.charts.LineChart -import com.github.mikephil.charting.data.BarData -import com.github.mikephil.charting.data.BarDataSet -import com.github.mikephil.charting.data.LineData -import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.data.* import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipGroup import kotlinx.android.synthetic.main.row_feed_session.view.* @@ -25,7 +22,7 @@ import kotlinx.android.synthetic.main.row_transaction.view.* import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.Stat -import net.pokeranalytics.android.calculus.bankroll.BankrollReport +import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager import net.pokeranalytics.android.model.realm.CustomField import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Transaction @@ -34,6 +31,7 @@ import net.pokeranalytics.android.ui.extensions.ChipGroupExtension import net.pokeranalytics.android.ui.extensions.addCircleRipple import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.setTextFormat +import net.pokeranalytics.android.ui.fragment.BankrollRowRepresentable import net.pokeranalytics.android.ui.graph.AxisFormatting import net.pokeranalytics.android.ui.graph.setStyle import net.pokeranalytics.android.ui.view.rowrepresentable.* @@ -139,93 +137,118 @@ enum class RowViewType(private var layoutRes: Int) { inner class RowViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { - if (row is CustomizableRowRepresentable) { + when (row) { - // Customizable Row + is BankrollRowRepresentable -> { - // Title - itemView.findViewById(R.id.title)?.let { - it.text = row.localizedTitle(itemView.context) - } - - // Value - itemView.findViewById(R.id.value)?.let { - if (row.computedStat != null) { - val format = row.computedStat!!.format() - it.setTextFormat(format, itemView.context) - } else if (row.value != null) { - it.text = row.value + // Title + itemView.findViewById(R.id.title)?.let { + it.text = row.localizedTitle(itemView.context) } - } - // Listener - row.isSelectable?.let { isSelectable -> - if (isSelectable) { - val listener = View.OnClickListener { - adapter.delegate?.onRowSelected(position, row) + BankrollReportManager.reportForBankroll(row.bankrollId) { report -> + + itemView.findViewById(R.id.title)?.let { + it.text = row.localizedTitle(itemView.context) } - itemView.findViewById(R.id.container)?.setOnClickListener(listener) + val computedStat = ComputedStat(Stat.NET_RESULT, report.total) + itemView.findViewById(R.id.value)?.setTextFormat(computedStat.format(), itemView.context) } - } - } else { + val listener = View.OnClickListener { + adapter.delegate?.onRowSelected(position, row) + } + itemView.findViewById(R.id.container)?.setOnClickListener(listener) + } + is CustomizableRowRepresentable -> { - // Classic row + // Customizable Row - // Title - itemView.findViewById(R.id.title)?.let { - if (row.resId != null) { + // Title + itemView.findViewById(R.id.title)?.let { it.text = row.localizedTitle(itemView.context) - } else { - it.text = row.getDisplayName(itemView.context) } - } - // Value - itemView.findViewById(R.id.value)?.let { - it.text = adapter.dataSource.stringForRow(row, itemView.context) - } + // Value + itemView.findViewById(R.id.value)?.let { + if (row.computedStat != null) { + val format = row.computedStat!!.format() + it.setTextFormat(format, itemView.context) + } else if (row.value != null) { + it.text = row.value + } + } - // Icon - itemView.findViewById(R.id.icon)?.let { imageView -> - imageView.setImageDrawable(null) - row.imageRes?.let { imageRes -> - imageView.setImageResource(imageRes) + // Listener + row.isSelectable?.let { isSelectable -> + if (isSelectable) { + val listener = View.OnClickListener { + adapter.delegate?.onRowSelected(position, row) + } + itemView.findViewById(R.id.container)?.setOnClickListener(listener) + } } + } + else -> { - // Action - itemView.findViewById(R.id.action)?.let { imageView -> - imageView.setImageDrawable(null) - row.imageRes?.let { imageRes -> - imageView.visibility = View.VISIBLE - imageView.setImageResource(imageRes) + // Classic row + + // Title + itemView.findViewById(R.id.title)?.let { + if (row.resId != null) { + it.text = row.localizedTitle(itemView.context) + } else { + it.text = row.getDisplayName(itemView.context) + } } - row.imageTint?.let { color -> - imageView.setColorFilter(ContextCompat.getColor(imageView.context, color)) + + // Value + itemView.findViewById(R.id.value)?.let { + it.text = adapter.dataSource.stringForRow(row, itemView.context) } - if (row.imageClickable == true) { - imageView.addCircleRipple() - imageView.setOnClickListener { - adapter.delegate?.onRowSelected(position, row, true) + + // Icon + itemView.findViewById(R.id.icon)?.let { imageView -> + imageView.setImageDrawable(null) + row.imageRes?.let { imageRes -> + imageView.setImageResource(imageRes) } - } else { - imageView.setBackgroundResource(0) } - } - // Listener - val listener = View.OnClickListener { - itemView.findViewById(R.id.switchView)?.let { - if (adapter.dataSource.isEnabled(row)) { - it.isChecked = !it.isChecked + // Action + itemView.findViewById(R.id.action)?.let { imageView -> + imageView.setImageDrawable(null) + row.imageRes?.let { imageRes -> + imageView.visibility = View.VISIBLE + imageView.setImageResource(imageRes) + } + row.imageTint?.let { color -> + imageView.setColorFilter(ContextCompat.getColor(imageView.context, color)) + } + if (row.imageClickable == true) { + imageView.addCircleRipple() + imageView.setOnClickListener { + adapter.delegate?.onRowSelected(position, row, true) + } + } else { + imageView.setBackgroundResource(0) + } + } + + // Listener + val listener = View.OnClickListener { + itemView.findViewById(R.id.switchView)?.let { + if (adapter.dataSource.isEnabled(row)) { + it.isChecked = !it.isChecked + } + } ?: run { + adapter.delegate?.onRowSelected(position, row) } - } ?: run { - adapter.delegate?.onRowSelected(position, row) } - } - itemView.findViewById(R.id.container)?.setOnClickListener(listener) + itemView.findViewById(R.id.container)?.setOnClickListener(listener) + } } // Switch @@ -346,43 +369,52 @@ enum class RowViewType(private var layoutRes: Int) { /** * Display a graph */ - inner class GraphViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), - BindableHolder { - override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { + inner class GraphViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { - if (row is GraphRow) { + private fun loadWithDataSet(dataSet: DataSet<*>) { + val context = itemView.context - row.dataSet?.let { dataSet -> + val chartView = when (dataSet) { + is LineDataSet -> { + val lineChart = LineChart(context) + lineChart.data = LineData(dataSet) + lineChart + } + is BarDataSet -> { + val barChart = BarChart(context) + barChart.data = BarData(dataSet) + barChart + } + else -> null + } - val context = itemView.context + itemView.findViewById(R.id.chartContainer)?.let { + it.removeAllViews() + it.addView(chartView) + } - val chartView = when (dataSet) { - is LineDataSet -> { - val lineChart = LineChart(context) - lineChart.data = LineData(dataSet) - lineChart - } - is BarDataSet -> { - val barChart = BarChart(context) - barChart.data = BarData(dataSet) - barChart - } - else -> null - } + chartView?.let { + chartView.setStyle(true, AxisFormatting.DEFAULT, context) + chartView.setTouchEnabled(false) + } - itemView.findViewById(R.id.chartContainer)?.let { - it.removeAllViews() - it.addView(chartView) - } + } - chartView?.let { - chartView.setStyle(true, AxisFormatting.DEFAULT, context) - chartView.setTouchEnabled(false) - } + override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { -// chartView.highlightValue((entries.size - 1).toFloat(), 0) + when (row) { + is BankrollGraphRow -> { + BankrollReportManager.reportForBankroll(row.bankrollId) { report -> + val dataSet = report.lineDataSet(itemView.context) + row.dataSet = dataSet + loadWithDataSet(dataSet) + } + } + is GraphRow -> { + row.dataSet?.let { dataSet -> + loadWithDataSet(dataSet) + } } - } // Listener @@ -400,22 +432,27 @@ enum class RowViewType(private var layoutRes: Int) { BindableHolder { override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { - if (row is BankrollReport) { + if (row is BankrollRowRepresentable) { + + BankrollReportManager.reportForBankroll(row.bankrollId) { report -> + + itemView.findViewById(R.id.stat1Value)?.let { + val formattedStat = ComputedStat(Stat.NET_RESULT, report.total).format() + it.setTextFormat(formattedStat, itemView.context) + } + itemView.findViewById(R.id.stat2Value)?.let { + val riskOfRuin = report.riskOfRuin ?: 0.0 + val formattedStat = ComputedStat(Stat.RISK_OF_RUIN, riskOfRuin).format() + it.setTextFormat(formattedStat, itemView.context) + } + } + itemView.findViewById(R.id.stat1Name)?.let { it.text = itemView.context.getString(R.string.total) } - itemView.findViewById(R.id.stat1Value)?.let { - val formattedStat = ComputedStat(Stat.NET_RESULT, row.total).format() - it.setTextFormat(formattedStat, itemView.context) - } itemView.findViewById(R.id.stat2Name)?.let { it.text = itemView.context.getString(R.string.risk_of_ruin) } - itemView.findViewById(R.id.stat2Value)?.let { - val riskOfRuin = row.riskOfRuin ?: 0.0 - val formattedStat = ComputedStat(Stat.RISK_OF_RUIN, riskOfRuin).format() - it.setTextFormat(formattedStat, itemView.context) - } val listener = View.OnClickListener { adapter.delegate?.onRowSelected(position, row) } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/BankrollMainRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/BankrollMainRow.kt new file mode 100644 index 00000000..1e42445f --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/BankrollMainRow.kt @@ -0,0 +1,12 @@ +package net.pokeranalytics.android.ui.view.rowrepresentable + +import net.pokeranalytics.android.ui.fragment.BankrollRowRepresentable +import net.pokeranalytics.android.ui.view.RowViewType + +class BankrollMainRow : BankrollRowRepresentable { + + override var bankrollId: String? = null + + override val viewType: Int = RowViewType.LEGEND_DEFAULT.ordinal + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/CustomizableRowRepresentable.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/CustomizableRowRepresentable.kt index 3cdc0ace..84d223f6 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/CustomizableRowRepresentable.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/CustomizableRowRepresentable.kt @@ -3,9 +3,20 @@ package net.pokeranalytics.android.ui.view.rowrepresentable import android.content.Context import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.model.interfaces.Identifiable +import net.pokeranalytics.android.ui.fragment.BankrollRowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType +class BankrollTotalRow(override var bankrollId: String?, var name: String) : BankrollRowRepresentable { + + override val viewType: Int = RowViewType.TITLE_VALUE_ARROW.ordinal + + override fun localizedTitle(context: Context): String { + return name + } + +} + /** * A class to display a titleResId (and a value) as a Row Representable object */ diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/GraphRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/GraphRow.kt index 7af17e6b..3f8f185b 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/GraphRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/GraphRow.kt @@ -3,11 +3,18 @@ package net.pokeranalytics.android.ui.view.rowrepresentable import com.github.mikephil.charting.data.DataSet import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Stat +import net.pokeranalytics.android.ui.fragment.BankrollRowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType -class GraphRow(var dataSet: DataSet<*>?, var title: String? = null, var report: Report? = null, var stat: Stat? = null) : RowRepresentable { +class BankrollGraphRow : GraphRow(null, null, null, null), BankrollRowRepresentable { + + override var bankrollId: String? = null + +} + +open class GraphRow(var dataSet: DataSet<*>? = null, var title: String? = null, var report: Report? = null, var stat: Stat? = null) : RowRepresentable { override val viewType: Int get() = RowViewType.GRAPH.ordinal From 01914614e18f34e3fb7e24edd36debdc857c8e9e Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 11 Jun 2019 18:10:04 +0200 Subject: [PATCH 019/125] cleanup comments --- .../android/ui/fragment/BankrollFragment.kt | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt index 0524f996..97d98541 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt @@ -58,7 +58,6 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour private var rows: ArrayList = ArrayList() private var bankrollRowRepresentables: HashMap> = HashMap() private var lastItemClickedPosition: Int = 0 -// private var lastItemClickedId: String = "" private var deletedRow: RowRepresentable? = null private lateinit var bankrolls: RealmResults @@ -113,8 +112,6 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour when (row) { is BankrollRowRepresentable -> { BankrollReportManager.reportForBankroll(row.bankrollId) { bankrollReport -> - -// lastItemClickedId = row.bankrollId ?: "" BankrollDetailsActivity.newInstanceForResult(this, bankrollReport, RequestCode.BANKROLL_DETAILS.value) } } @@ -132,8 +129,7 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour */ private fun initData() { - val realm = getRealm() - this.bankrolls = realm.sorted() + this.bankrolls = getRealm().sorted() rows.clear() @@ -193,19 +189,9 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour } override fun updateUIAfterUndoDeletion(newItem: RealmObject) { - - // TODO: Improve that - // We are recreating a Bankroll report because the last one is invalid => the bankroll of the setup has been deleted - deletedRow?.let { row -> -// val bankrollReportSetup = BankrollReportSetup(newItem as Bankroll) -// val bankrollReport = BankrollCalculator.computeReport(getRealm(), bankrollReportSetup) -// bankrollReportForRow[row] = bankrollReport - rows.add(lastItemClickedPosition, row) dataListAdapter.notifyDataSetChanged() // update both virtual + ex-deleted - -// dataListAdapter.notifyItemInserted(lastItemClickedPosition) } } From 9a3cd3d7161b15356a2845c95461068ddef98f61 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 11 Jun 2019 19:44:37 +0200 Subject: [PATCH 020/125] Fixes issue with row selection + graph --- .../android/PokerAnalyticsApplication.kt | 2 +- .../net/pokeranalytics/android/calculus/Report.kt | 5 +++-- .../net/pokeranalytics/android/calculus/Stat.kt | 9 +++++++-- .../android/calculus/bankroll/BankrollReport.kt | 13 +++++++------ .../calculus/bankroll/BankrollReportManager.kt | 9 ++++++--- .../android/model/interfaces/Dated.kt | 4 +++- .../android/model/interfaces/Manageable.kt | 1 + .../android/model/interfaces/Timed.kt | 10 +++++++--- .../pokeranalytics/android/model/realm/Session.kt | 6 +++--- .../android/model/realm/Transaction.kt | 12 ++++++++---- .../android/ui/fragment/BankrollFragment.kt | 13 ++++++++----- .../android/ui/fragment/StatisticsFragment.kt | 2 +- .../android/ui/graph/GraphUnderlyingEntry.kt | 4 ++-- .../pokeranalytics/android/ui/view/RowViewType.kt | 4 ++-- 14 files changed, 59 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt index 1b81d955..35ea4536 100644 --- a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt +++ b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt @@ -60,7 +60,7 @@ class PokerAnalyticsApplication : Application() { if (BuildConfig.DEBUG) { Timber.d("UserPreferences.defaultCurrency: ${UserDefaults.currency.symbol}") - this.createFakeSessions() +// this.createFakeSessions() } Patcher.patchAll(this.applicationContext) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt index f4b61d7f..63501b46 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt @@ -7,7 +7,8 @@ import io.realm.RealmResults import net.pokeranalytics.android.R import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.QueryCondition -import net.pokeranalytics.android.model.interfaces.Timed +import net.pokeranalytics.android.model.interfaces.GraphIdentifiableEntry +//import net.pokeranalytics.android.model.interfaces.Timed import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.model.realm.SessionSet @@ -196,7 +197,7 @@ class ComputedResults(group: ComputableGroup, shouldManageMultiGroupProgressValu /** * Adds a value to the evolution values */ - fun addEvolutionValue(value: Double, duration: Double? = null, stat: Stat, data: Timed) { + fun addEvolutionValue(value: Double, duration: Double? = null, stat: Stat, data: GraphIdentifiableEntry) { val point = if (duration != null) { Point(duration, y = value, data = data.objectIdentifier) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt index 2b8a30c8..ec9e50a7 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt @@ -159,10 +159,15 @@ enum class Stat(override var uniqueIdentifier: Int) : IntIdentifiable, RowRepres HOURLY_DURATION, AVERAGE_HOURLY_DURATION, MAXIMUM_DURATION -> { return TextFormat(value.formattedHourlyDuration()) } // red/green percentages - WIN_RATIO, ROI, RISK_OF_RUIN -> { + WIN_RATIO, ROI -> { val color = if (value * 100 >= this.threshold) R.color.green else R.color.red return TextFormat("${(value * 100).formatted()}%", color) - } // white amountsr + } + RISK_OF_RUIN -> { + val color = if (value * 100 <= this.threshold) R.color.green else R.color.red + return TextFormat("${(value * 100).formatted()}%", color) + } + // white amountsr AVERAGE_BUYIN, STANDARD_DEVIATION, STANDARD_DEVIATION_HOURLY, STANDARD_DEVIATION_BB_PER_100_HANDS -> { return TextFormat(value.toCurrency(currency)) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt index b6c079d6..f3bbe059 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt @@ -4,9 +4,10 @@ import android.content.Context import com.github.mikephil.charting.data.Entry import com.github.mikephil.charting.data.LineDataSet import io.realm.Realm +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.QueryCondition -import net.pokeranalytics.android.model.interfaces.DatedValue +import net.pokeranalytics.android.model.interfaces.DatedGraphEntry import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.ui.graph.DataSetFactory @@ -116,12 +117,12 @@ class BankrollReport(var setup: BankrollReportSetup) { /** * The list of dated items used for the graph */ - private var evolutionItems: MutableList = mutableListOf() + private var evolutionItems: MutableList = mutableListOf() /** * Adds a list of dated items to the evolution items used to get the bankroll graph */ - fun addDatedItems(items: Collection) { + fun addDatedItems(items: Collection) { this.evolutionItems.addAll(items) } @@ -143,7 +144,7 @@ class BankrollReport(var setup: BankrollReportSetup) { bucket.addTransaction(transaction) } ?: run { - throw IllegalStateException("Transaction has no type") + throw PAIllegalStateException("Transaction has no type") } } @@ -162,7 +163,7 @@ class BankrollReport(var setup: BankrollReportSetup) { var total = this.initial this.evolutionItems.forEach { total += it.amount - val point = BRGraphPoint(total, it.date, it) + val point = BRGraphPoint(total, it.date, it.objectIdentifier) this.evolutionPoints.add(point) } @@ -276,6 +277,6 @@ class TransactionBucket(var name: String, useRate: Boolean = false) { data class BRGraphPoint(var value: Double, var date: Date, var data: Any? = null) { - var variation: Double = 0.0 +// var variation: Double = 0.0 } diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt index 9f68008f..a6fd8917 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt @@ -70,7 +70,7 @@ object BankrollReportManager { GlobalScope.launch(coroutineContext) { var report: BankrollReport? = null - val scope = GlobalScope.async { + val coroutine = GlobalScope.async { val s = Date() Timber.d(">>>>> start computing bankroll...") @@ -86,8 +86,11 @@ object BankrollReportManager { Timber.d(">>>>> ended in $duration seconds") } - scope.await() - report?.let { handler(it) } + coroutine.await() + + report?.let { + handler(it) + } } } diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Dated.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Dated.kt index 86cea43b..bb20862a 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Dated.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Dated.kt @@ -12,4 +12,6 @@ interface DatedValue : Dated { var amount: Double -} \ No newline at end of file +} + +interface DatedGraphEntry : DatedValue, GraphIdentifiableEntry \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt index 05624c3a..26ebd99a 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt @@ -55,6 +55,7 @@ interface Identifiable : RealmModel { * A unique uniqueIdentifier getter */ var id: String + } /** diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt index 1123f298..31ca5fe9 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt @@ -4,7 +4,13 @@ import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry import net.pokeranalytics.android.ui.graph.ObjectIdentifier import java.util.* -interface Timed : GraphUnderlyingEntry, Identifiable { +interface GraphIdentifiableEntry : GraphUnderlyingEntry, Identifiable { + + val objectIdentifier : ObjectIdentifier + +} + +interface Timed : GraphIdentifiableEntry { fun startDate() : Date? @@ -30,6 +36,4 @@ interface Timed : GraphUnderlyingEntry, Identifiable { val hourlyDuration: Double get() = this.netDuration / 3600000.0 - val objectIdentifier : ObjectIdentifier - } \ No newline at end of file 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 088ac609..aa97a132 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 @@ -46,7 +46,7 @@ import kotlin.collections.ArrayList typealias BB = Double open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDataSource, RowRepresentable, Timed, - TimeFilterable, Filterable, DatedValue { + TimeFilterable, Filterable, DatedGraphEntry { enum class Type { CASH_GAME, @@ -791,7 +791,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat } return NULL_TEXT } - else -> throw UnmanagedRowRepresentableException("Unmanaged row = ${row}") + else -> throw UnmanagedRowRepresentableException("Unmanaged row = $row") } } @@ -1138,7 +1138,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat DefaultLegendValues(this.entryTitle(context), left, right) } else -> { - super.legendValues(stat, entry, style, groupName, context) + super.legendValues(stat, entry, style, groupName, context) } } } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt index 748b3e84..66432946 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt @@ -13,7 +13,7 @@ import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.interfaces.* import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.fragment.GraphFragment -import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry +import net.pokeranalytics.android.ui.graph.ObjectIdentifier import net.pokeranalytics.android.ui.view.DefaultLegendValues import net.pokeranalytics.android.ui.view.LegendContent import net.pokeranalytics.android.ui.view.RowRepresentable @@ -26,8 +26,8 @@ import java.util.* import kotlin.collections.ArrayList -open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable, TimeFilterable, Filterable, DatedValue, - GraphUnderlyingEntry { +open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable, TimeFilterable, + Filterable, DatedGraphEntry { companion object { @@ -134,7 +134,10 @@ open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSo return SaveValidityStatus.VALID } - // GraphUnderlyingEntry + // GraphIdentifiableEntry + + override val objectIdentifier: ObjectIdentifier + get() = ObjectIdentifier(this.id, Transaction::class.java) override fun entryTitle(context: Context): String { return DateFormat.getDateInstance(DateFormat.SHORT).format(this.date) @@ -158,4 +161,5 @@ open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSo return DefaultLegendValues(this.entryTitle(context), entryValue, totalStatValue, leftName = leftName) } + } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt index 97d98541..6cb4fb42 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt @@ -31,7 +31,10 @@ import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.fragment.components.DeletableItemFragment import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType -import net.pokeranalytics.android.ui.view.rowrepresentable.* +import net.pokeranalytics.android.ui.view.rowrepresentable.BankrollGraphRow +import net.pokeranalytics.android.ui.view.rowrepresentable.BankrollMainRow +import net.pokeranalytics.android.ui.view.rowrepresentable.BankrollTotalRow +import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable import net.pokeranalytics.android.util.extensions.sorted import java.util.* import kotlin.collections.ArrayList @@ -110,15 +113,15 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { lastItemClickedPosition = position when (row) { + is BankrollGraphRow -> { + val lineDataSet = row.dataSet as LineDataSet + GraphActivity.newInstance(requireContext(), listOf(lineDataSet), title = getString(R.string.bankroll)) + } is BankrollRowRepresentable -> { BankrollReportManager.reportForBankroll(row.bankrollId) { bankrollReport -> BankrollDetailsActivity.newInstanceForResult(this, bankrollReport, RequestCode.BANKROLL_DETAILS.value) } } - is GraphRow -> { - val lineDataSet = row.dataSet as LineDataSet - GraphActivity.newInstance(requireContext(), listOf(lineDataSet), title = getString(R.string.bankroll)) - } } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt index dfcc828a..18d92fdd 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt @@ -32,7 +32,7 @@ import kotlin.coroutines.CoroutineContext class StatisticsFragment : FilterableFragment() { - val coroutineContext: CoroutineContext + private val coroutineContext: CoroutineContext get() = Dispatchers.Main private lateinit var tableReportFragment: ComposableTableReportFragment diff --git a/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt b/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt index 897ff3f9..01d9ead9 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt @@ -3,13 +3,13 @@ package net.pokeranalytics.android.ui.graph import android.content.Context import com.github.mikephil.charting.data.Entry import net.pokeranalytics.android.calculus.Stat -import net.pokeranalytics.android.model.interfaces.Timed +import net.pokeranalytics.android.model.interfaces.GraphIdentifiableEntry import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.view.DefaultLegendValues import net.pokeranalytics.android.ui.view.LegendContent import net.pokeranalytics.android.util.TextFormat -class ObjectIdentifier(var id: String, var clazz: Class) { +class ObjectIdentifier(var id: String, var clazz: Class) { } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt index 42e6da6f..9a453d39 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt @@ -428,8 +428,8 @@ enum class RowViewType(private var layoutRes: Int) { /** * Display a legend */ - inner class LegendDefaultViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), - BindableHolder { + inner class LegendDefaultViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { + override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { if (row is BankrollRowRepresentable) { From 4728074bc2f1be74ce00090071cd3967afeb775e Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 11 Jun 2019 19:45:16 +0200 Subject: [PATCH 021/125] Bumps to version 37 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 91d6b38d..4600a2b6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,8 +29,8 @@ android { applicationId "net.pokeranalytics.android" minSdkVersion 23 targetSdkVersion 28 - versionCode 35 - versionName "2.0" + versionCode 37 + versionName "2.0.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } From b20135e95ff00279d97691b13148b19154fa7b76 Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 10:23:20 +0200 Subject: [PATCH 022/125] Fixes bankroll details title --- .../android/ui/fragment/BankrollDetailsFragment.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt index 923695d5..05f014f6 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt @@ -80,7 +80,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc private fun updateUI(bankrollReport: BankrollReport) { this.initRows(bankrollReport) - this.updateMenuUI(bankrollReport) + this.updateMenuUI() this.bankrollAdapter.notifyDataSetChanged() } @@ -156,6 +156,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc private fun initUI() { setDisplayHomeAsUpEnabled(true) + this.updateMenuUI() bankrollAdapter = RowRepresentableAdapter(this, this) @@ -171,9 +172,9 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc /** * Update menu UI */ - private fun updateMenuUI(bankrollReport: BankrollReport) { + private fun updateMenuUI() { - if (bankrollReport.setup.virtualBankroll) { + if (this.bankrollId == null) { setToolbarTitle(getString(R.string.total)) bankrollDetailsMenu?.findItem(R.id.settings)?.isVisible = false } else { @@ -199,7 +200,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc menu?.clear() inflater?.inflate(R.menu.toolbar_comparison_chart, menu) this.bankrollDetailsMenu = menu -// updateMenuUI() + updateMenuUI() super.onCreateOptionsMenu(menu, inflater) } From f327eab7baa2be3b4ebaf00c99a05862183275ec Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 10:27:44 +0200 Subject: [PATCH 023/125] Put local code into RequestCode --- .../android/ui/activity/components/Codes.kt | 1 + .../android/ui/fragment/BankrollDetailsFragment.kt | 12 +++--------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt index 23cb64f8..c8ada486 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt @@ -4,6 +4,7 @@ enum class RequestCode(var value: Int) { DEFAULT(1), BANKROLL_DETAILS(700), BANKROLL_CREATE(701), + BANKROLL_EDIT(702), NEW_SESSION(800), NEW_TRANSACTION(801), NEW_REPORT(802), diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt index 05f014f6..533b8c7b 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt @@ -16,6 +16,7 @@ import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.ui.activity.DataListActivity import net.pokeranalytics.android.ui.activity.EditableDataActivity +import net.pokeranalytics.android.ui.activity.components.RequestCode import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource @@ -29,15 +30,9 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc companion object { - const val REQUEST_CODE_EDIT = 1000 - - /** - * Create new instance - */ fun newInstance(bankrollReport: BankrollReport): BankrollDetailsFragment { val fragment = BankrollDetailsFragment() fragment.bankrollId = bankrollReport.setup.bankrollId -// fragment.bankrollReport = bankrollReport return fragment } } @@ -47,7 +42,6 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc private var rows: ArrayList = ArrayList() private lateinit var bankrollAdapter: RowRepresentableAdapter -// private lateinit var bankrollReport: BankrollReport private var bankrollDetailsMenu: Menu? = null @@ -66,7 +60,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (requestCode == REQUEST_CODE_EDIT && resultCode == RESULT_OK) { + if (requestCode == RequestCode.BANKROLL_EDIT.value && resultCode == RESULT_OK) { if (data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName) != null) { activity?.setResult(RESULT_OK, data) activity?.finish() @@ -217,7 +211,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc * Open Bankroll edit activity */ private fun editBankroll() { - EditableDataActivity.newInstanceForResult(this, LiveData.BANKROLL, this.bankrollId, REQUEST_CODE_EDIT) + EditableDataActivity.newInstanceForResult(this, LiveData.BANKROLL, this.bankrollId, RequestCode.BANKROLL_EDIT.value) } } \ No newline at end of file From d0b142dad944cfc8cd2ceac0e943c5681d973e0b Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 11:25:17 +0200 Subject: [PATCH 024/125] Fixes currency and such --- .../calculus/bankroll/BankrollCalculator.kt | 1 + .../calculus/bankroll/BankrollReport.kt | 5 ++ .../android/model/realm/Bankroll.kt | 9 +++ .../ui/fragment/BankrollDetailsFragment.kt | 81 +++++++++---------- .../android/ui/fragment/BankrollFragment.kt | 2 +- .../android/ui/view/RowViewType.kt | 2 +- 6 files changed, 56 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt index 3f7b144a..63507abc 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt @@ -22,6 +22,7 @@ class BankrollCalculator { val bankrolls: List = if (setup.bankrollId != null) { val bankroll = realm.findById(setup.bankrollId) ?: throw PAIllegalStateException("Bankroll not found with id=${setup.bankrollId}") + report.currency = bankroll.utilCurrency listOf(bankroll) } else realm.where(Bankroll::class.java).findAll() diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt index f3bbe059..e8a3c761 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt @@ -21,6 +21,11 @@ import kotlin.collections.HashMap */ class BankrollReport(var setup: BankrollReportSetup) { + /** + * The java.util.Currency + */ + var currency: Currency? = null + /** * The value of the bankroll */ diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt index 8f5574a2..9c1c4f08 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt @@ -14,6 +14,7 @@ import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.BankrollRow import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow +import net.pokeranalytics.android.util.UserDefaults import java.util.* open class Bankroll : RealmObject(), NameManageable, RowRepresentable { @@ -118,4 +119,12 @@ open class Bankroll : RealmObject(), NameManageable, RowRepresentable { } + val utilCurrency: java.util.Currency + get() { + this.currency?.code?.let { + return java.util.Currency.getInstance(it) + } + return UserDefaults.currency + } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt index 533b8c7b..88e393ce 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt @@ -56,6 +56,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc super.onViewCreated(view, savedInstanceState) initData() initUI() + updateUI() } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { @@ -65,17 +66,17 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc activity?.setResult(RESULT_OK, data) activity?.finish() } else { - BankrollReportManager.reportForBankroll(this.bankrollId) { - updateUI(it) - } + updateUI() } } } - private fun updateUI(bankrollReport: BankrollReport) { - this.initRows(bankrollReport) - this.updateMenuUI() - this.bankrollAdapter.notifyDataSetChanged() + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + menu?.clear() + inflater?.inflate(R.menu.toolbar_comparison_chart, menu) // TODO R.menu.toolbar_comparison_chart? + this.bankrollDetailsMenu = menu + updateMenuUI() + super.onCreateOptionsMenu(menu, inflater) } /** @@ -87,10 +88,33 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc this.bankroll = getRealm().findById(id) ?: throw PAIllegalStateException("Bankroll not found, id=$id") } - BankrollReportManager.reportForBankroll(this.bankrollId) { - updateUI(it) + } + + /** + * Init UI + */ + private fun initUI() { + + setDisplayHomeAsUpEnabled(true) + this.updateMenuUI() + + bankrollAdapter = RowRepresentableAdapter(this, this) + + val viewManager = LinearLayoutManager(requireContext()) + + recyclerView.apply { + setHasFixedSize(true) + layoutManager = viewManager + adapter = bankrollAdapter } + } + private fun updateUI() { + this.updateMenuUI() + BankrollReportManager.reportForBankroll(this.bankrollId) { bankrollReport -> + this.initRows(bankrollReport) + this.bankrollAdapter.notifyDataSetChanged() + } } private fun initRows(bankrollReport: BankrollReport) { @@ -99,9 +123,10 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.global)) - val totalComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.total) - val netComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netResult) - val netBankedComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netBanked) + val currency = this.bankroll.utilCurrency + val totalComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.total, currency = currency) + val netComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netResult, currency = currency) + val netBankedComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netBanked, currency = currency) rows.add( CustomizableRowRepresentable( @@ -130,7 +155,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc bankrollReport.transactionBuckets.keys.forEach { key -> bankrollReport.transactionBuckets[key]?.let { transactionBucket -> val typeName = transactionBucket.name - val computedStat = ComputedStat(Stat.NET_RESULT, transactionBucket.total) + val computedStat = ComputedStat(Stat.NET_RESULT, transactionBucket.total, currency = currency) rows.add( CustomizableRowRepresentable( RowViewType.TITLE_VALUE, @@ -144,25 +169,6 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc } - /** - * Init UI - */ - private fun initUI() { - - setDisplayHomeAsUpEnabled(true) - this.updateMenuUI() - - bankrollAdapter = RowRepresentableAdapter(this, this) - - val viewManager = LinearLayoutManager(requireContext()) - - recyclerView.apply { - setHasFixedSize(true) - layoutManager = viewManager - adapter = bankrollAdapter - } - } - /** * Update menu UI */ @@ -175,7 +181,6 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc setToolbarTitle(this.bankroll.name) bankrollDetailsMenu?.findItem(R.id.settings)?.isVisible = true } - } // StaticRowRepresentableDataSource @@ -190,16 +195,8 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc } - override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { - menu?.clear() - inflater?.inflate(R.menu.toolbar_comparison_chart, menu) - this.bankrollDetailsMenu = menu - updateMenuUI() - super.onCreateOptionsMenu(menu, inflater) - } - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - when (item!!.itemId) { + when (item?.itemId) { R.id.settings -> editBankroll() } return true diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt index 6cb4fb42..47cc09fc 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt @@ -101,7 +101,7 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour //TODO: Refresh bankrolls initData() } else { - dataListAdapter.notifyDataSetChanged() + initData() } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt index 9a453d39..d5044187 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt @@ -151,7 +151,7 @@ enum class RowViewType(private var layoutRes: Int) { itemView.findViewById(R.id.title)?.let { it.text = row.localizedTitle(itemView.context) } - val computedStat = ComputedStat(Stat.NET_RESULT, report.total) + val computedStat = ComputedStat(Stat.NET_RESULT, report.total, currency = report.currency) itemView.findViewById(R.id.value)?.setTextFormat(computedStat.format(), itemView.context) } From 7e267abe2770579fa92d872b1101654f23595028 Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 11:29:30 +0200 Subject: [PATCH 025/125] Fixes transaction currency --- .../ui/adapter/FeedTransactionRowRepresentableAdapter.kt | 1 + .../net/pokeranalytics/android/ui/view/TransactionRowView.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedTransactionRowRepresentableAdapter.kt b/app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedTransactionRowRepresentableAdapter.kt index ea262236..9691d7bd 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedTransactionRowRepresentableAdapter.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedTransactionRowRepresentableAdapter.kt @@ -40,6 +40,7 @@ class FeedTransactionRowRepresentableAdapter( * Display a transaction view */ inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { + fun bind(position: Int, row: Transaction?, adapter: FeedTransactionRowRepresentableAdapter) { itemView.transactionRow.setData(row as Transaction) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt index f9971876..eb9b6fa4 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt @@ -63,7 +63,7 @@ class TransactionRowView : FrameLayout { rowTransaction.transactionSubtitle.text = subtitle // Amount - val formattedStat = ComputedStat(Stat.NET_RESULT, transaction.amount).format() + val formattedStat = ComputedStat(Stat.NET_RESULT, transaction.amount, currency = transaction.bankroll?.utilCurrency).format() rowTransaction.transactionAmount.setTextFormat(formattedStat, context) } From 29b3d553400f44fc0be90ef9770f41f677e2669e Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 12:00:28 +0200 Subject: [PATCH 026/125] Fixes bankroll graph currencies --- .../android/calculus/bankroll/BankrollReport.kt | 13 +++++++++---- .../android/model/interfaces/Dated.kt | 7 ++++++- .../pokeranalytics/android/model/realm/Bankroll.kt | 2 +- .../pokeranalytics/android/model/realm/Currency.kt | 12 ++++++++---- .../pokeranalytics/android/model/realm/Session.kt | 6 +++--- .../android/model/realm/Transaction.kt | 6 +++--- 6 files changed, 30 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt index e8a3c761..cd83fb07 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt @@ -7,11 +7,12 @@ import io.realm.Realm import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.QueryCondition -import net.pokeranalytics.android.model.interfaces.DatedGraphEntry +import net.pokeranalytics.android.model.interfaces.DatedBankrollGraphEntry import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.ui.graph.DataSetFactory import net.pokeranalytics.android.util.extensions.findById +import timber.log.Timber import java.util.* import kotlin.collections.HashMap @@ -122,12 +123,12 @@ class BankrollReport(var setup: BankrollReportSetup) { /** * The list of dated items used for the graph */ - private var evolutionItems: MutableList = mutableListOf() + private var evolutionItems: MutableList = mutableListOf() /** * Adds a list of dated items to the evolution items used to get the bankroll graph */ - fun addDatedItems(items: Collection) { + fun addDatedItems(items: Collection) { this.evolutionItems.addAll(items) } @@ -167,7 +168,11 @@ class BankrollReport(var setup: BankrollReportSetup) { var total = this.initial this.evolutionItems.forEach { - total += it.amount + val rate = it.bankroll?.rate ?: 1.0 + + Timber.d("rate = $rate, amount = ${it.amount}") + total += it.amount * rate + Timber.d("total = $total") val point = BRGraphPoint(total, it.date, it.objectIdentifier) this.evolutionPoints.add(point) } diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Dated.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Dated.kt index bb20862a..a3d8f428 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Dated.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Dated.kt @@ -1,5 +1,6 @@ package net.pokeranalytics.android.model.interfaces +import net.pokeranalytics.android.model.realm.Bankroll import java.util.* interface Dated { @@ -14,4 +15,8 @@ interface DatedValue : Dated { } -interface DatedGraphEntry : DatedValue, GraphIdentifiableEntry \ No newline at end of file +interface DatedBankrollGraphEntry : DatedValue, GraphIdentifiableEntry { + + var bankroll: Bankroll? + +} diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt index 9c1c4f08..00af3d42 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt @@ -41,7 +41,7 @@ open class Bankroll : RealmObject(), NameManageable, RowRepresentable { val rate: Double get() { - return this.currency?.rate ?: 1.0 + return this.currency?.rate ?: Currency.DEFAULT_RATE } override fun getDisplayName(context: Context): String { diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt index 304f3a2b..75655d36 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Currency.kt @@ -8,8 +8,12 @@ import java.util.* open class Currency : RealmObject() { - @Ignore - val DEFAULTRATE: Double = 1.0 + companion object { + + @Ignore + val DEFAULT_RATE: Double = 1.0 + + } @PrimaryKey var id = UUID.randomUUID().toString() @@ -22,11 +26,11 @@ open class Currency : RealmObject() { /** * The rate of the currency with the main currency */ - var rate: Double? = DEFAULTRATE + var rate: Double? = DEFAULT_RATE fun refreshRelatedRatedValues() { - val rate = this.rate ?: DEFAULTRATE + val rate = this.rate ?: DEFAULT_RATE val query = this.realm.where(ComputableResult::class.java) query.`in`("session.bankroll.currency.id", arrayOf(this.id)) val cResults = query.findAll() 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 aa97a132..975da7d5 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 @@ -46,7 +46,7 @@ import kotlin.collections.ArrayList typealias BB = Double open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDataSource, RowRepresentable, Timed, - TimeFilterable, Filterable, DatedGraphEntry { + TimeFilterable, Filterable, DatedBankrollGraphEntry { enum class Type { CASH_GAME, @@ -235,7 +235,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat var creationDate: Date = Date() // The bankroll hosting the results - var bankroll: Bankroll? = null + override var bankroll: Bankroll? = null set(value) { field = value this.updateRowRepresentation() @@ -399,7 +399,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat @Ignore override var amount: Double = 0.0 get() { - return this.computableResult?.ratedNet ?: 0.0 + return this.result?.net ?: 0.0 } /** diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt index 66432946..a3ef5368 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt @@ -27,7 +27,7 @@ import kotlin.collections.ArrayList open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable, TimeFilterable, - Filterable, DatedGraphEntry { + Filterable, DatedBankrollGraphEntry { companion object { @@ -60,7 +60,7 @@ open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSo override var id = UUID.randomUUID().toString() // The bankroll of the transaction - var bankroll: Bankroll? = null + override var bankroll: Bankroll? = null // The amount of the transaction override var amount: Double = 0.0 @@ -144,7 +144,7 @@ open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSo } override fun formattedValue(stat: Stat): TextFormat { - return stat.format(this.amount) + return stat.format(this.amount, currency = this.bankroll?.utilCurrency) } override fun legendValues( From 3130f0232797f4f5413f4fa3f8416288606b47bb Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 12:16:26 +0200 Subject: [PATCH 027/125] Fixes layout of disclosure rows --- app/src/main/res/layout/row_legend_default.xml | 4 ++-- app/src/main/res/layout/row_title_value_arrow.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout/row_legend_default.xml b/app/src/main/res/layout/row_legend_default.xml index caeace10..974a8900 100644 --- a/app/src/main/res/layout/row_legend_default.xml +++ b/app/src/main/res/layout/row_legend_default.xml @@ -35,7 +35,7 @@ android:layout_width="wrap_content" android:layout_height="0dp" android:layout_marginTop="8dp" - android:layout_marginEnd="16dp" + android:layout_marginEnd="8dp" app:layout_constraintEnd_toStartOf="@+id/nextArrow" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toEndOf="@+id/stat1Name" @@ -48,7 +48,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" - android:layout_marginEnd="16dp" + android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/nextArrow" diff --git a/app/src/main/res/layout/row_title_value_arrow.xml b/app/src/main/res/layout/row_title_value_arrow.xml index 52ab6295..6491c8a9 100644 --- a/app/src/main/res/layout/row_title_value_arrow.xml +++ b/app/src/main/res/layout/row_title_value_arrow.xml @@ -24,7 +24,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" + android:layout_marginEnd="8dp" android:ellipsize="end" android:gravity="end" android:maxLines="1" From e76c09cdeae0949ac631f3df3e018276df1ffdf2 Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 12:35:23 +0200 Subject: [PATCH 028/125] Fixes test build --- .../android/unitTests/BankrollInstrumentedUnitTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/BankrollInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/BankrollInstrumentedUnitTest.kt index a76308ed..82807498 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/BankrollInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/BankrollInstrumentedUnitTest.kt @@ -72,12 +72,12 @@ class BankrollInstrumentedUnitTest : SessionInstrumentedUnitTest() { } val br1 = realm.where(Bankroll::class.java).equalTo("name", "br1").findFirst() - val brSetup1 = BankrollReportSetup(br1) + val brSetup1 = BankrollReportSetup(br1?.id) val report1 = BankrollCalculator.computeReport(realm, brSetup1) Assert.assertEquals(400.0, report1.total, EPSILON) val br2 = realm.where(Bankroll::class.java).equalTo("name", "br2").findFirst() - val brSetup2 = BankrollReportSetup(br2) + val brSetup2 = BankrollReportSetup(br2?.id) val report2 = BankrollCalculator.computeReport(realm, brSetup2) Assert.assertEquals(2000.0, report2.total, EPSILON) @@ -116,7 +116,7 @@ class BankrollInstrumentedUnitTest : SessionInstrumentedUnitTest() { } - val brSetup1 = BankrollReportSetup(br1) + val brSetup1 = BankrollReportSetup(br1?.id) val report1 = BankrollCalculator.computeReport(realm, brSetup1) Assert.assertEquals(400.0, report1.total, EPSILON) From 7f8e9240ed9f18106d91df79934f16b466881ecc Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 14:19:33 +0200 Subject: [PATCH 029/125] Removes logs --- .../android/calculus/bankroll/BankrollReport.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt index cd83fb07..69df9109 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt @@ -12,7 +12,6 @@ import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.ui.graph.DataSetFactory import net.pokeranalytics.android.util.extensions.findById -import timber.log.Timber import java.util.* import kotlin.collections.HashMap @@ -170,9 +169,9 @@ class BankrollReport(var setup: BankrollReportSetup) { this.evolutionItems.forEach { val rate = it.bankroll?.rate ?: 1.0 - Timber.d("rate = $rate, amount = ${it.amount}") +// Timber.d("rate = $rate, amount = ${it.amount}") total += it.amount * rate - Timber.d("total = $total") +// Timber.d("total = $total") val point = BRGraphPoint(total, it.date, it.objectIdentifier) this.evolutionPoints.add(point) } From 3385beced2af63eac77c331e8daf9e133c25cb16 Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 15:13:33 +0200 Subject: [PATCH 030/125] Fixes crash on bankroll main row --- app/build.gradle | 2 +- .../android/ui/fragment/BankrollDetailsFragment.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4600a2b6..174fae59 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,7 +29,7 @@ android { applicationId "net.pokeranalytics.android" minSdkVersion 23 targetSdkVersion 28 - versionCode 37 + versionCode 38 versionName "2.0.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt index 88e393ce..7a188e18 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt @@ -123,7 +123,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.global)) - val currency = this.bankroll.utilCurrency + val currency = if (this.bankrollId != null) { this.bankroll.utilCurrency } else { null } val totalComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.total, currency = currency) val netComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netResult, currency = currency) val netBankedComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netBanked, currency = currency) From 90fe6ef40f08c2f06800ac610726541978c0621c Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 18:43:17 +0200 Subject: [PATCH 031/125] CSV import update --- .../android/ui/fragment/ImportFragment.kt | 9 +- .../android/util/csv/CSVDescriptor.kt | 4 +- .../android/util/csv/CSVImporter.kt | 10 + .../android/util/csv/SessionCSVDescriptor.kt | 174 +++++++++++++++--- app/src/main/res/layout/bottom_sheet_sum.xml | 4 +- app/src/main/res/layout/fragment_import.xml | 40 ++++ app/src/main/res/values/styles.xml | 11 ++ 7 files changed, 226 insertions(+), 26 deletions(-) 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 0727dd0d..c0d0775c 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 @@ -12,13 +12,14 @@ import net.pokeranalytics.android.R import net.pokeranalytics.android.ui.activity.components.ResultCode import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.util.csv.CSVImporter +import net.pokeranalytics.android.util.csv.ImportDelegate import net.pokeranalytics.android.util.csv.ImportException import timber.log.Timber import java.io.InputStream import java.util.* import kotlin.coroutines.CoroutineContext -class ImportFragment : RealmFragment() { +class ImportFragment : RealmFragment(), ImportDelegate { val coroutineContext: CoroutineContext get() = Dispatchers.Main @@ -81,4 +82,10 @@ class ImportFragment : RealmFragment() { } + // ImportDelegate + + override fun parsingCountUpdate(count: Int) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + } \ No newline at end of file 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 f4ef3174..bf517d5e 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 @@ -3,6 +3,7 @@ package net.pokeranalytics.android.util.csv import io.realm.Realm import io.realm.RealmModel import org.apache.commons.csv.CSVRecord +import timber.log.Timber /** * The various sources of CSV @@ -77,9 +78,8 @@ abstract class CSVDescriptor(var source: DataSource, vararg elements: CSVField) if (index >= 0) { count++ } - } - + Timber.d("source= ${this.source.name} > total fields = ${this.fields.size}, identified = $count") return count == this.fields.size } 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 7a1bfb90..a2772236 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 @@ -11,6 +11,10 @@ import java.io.Reader class ImportException(message: String) : Exception(message) +interface ImportDelegate { + fun parsingCountUpdate(count: Int) +} + /** * A CSVImporter is a class in charge of parsing a CSV file and processing it * When starting the parsing of a file, the instance will search for a CSVDescriptor, which describes @@ -20,6 +24,11 @@ class ImportException(message: String) : Exception(message) */ open class CSVImporter(istream: InputStream) { + /** + * The object being notified of the import progress + */ + var delegate: ImportDelegate? = null + /** * Number of commits required to commit a Realm transaction */ @@ -100,6 +109,7 @@ open class CSVImporter(istream: InputStream) { val parsingIndex = index + 1 if (parsingIndex % COMMIT_FREQUENCY == 0) { Timber.d("****** committing at $parsingIndex sessions...") + this.delegate?.parsingCountUpdate(parsingIndex) realm.commitTransaction() realm.beginTransaction() } 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 d33e719f..c70d15bb 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 @@ -1,11 +1,14 @@ package net.pokeranalytics.android.util.csv import io.realm.Realm +import io.realm.RealmModel import net.pokeranalytics.android.model.Limit import net.pokeranalytics.android.model.TableSize import net.pokeranalytics.android.model.TournamentType import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.model.realm.Transaction +import net.pokeranalytics.android.model.realm.TransactionType import net.pokeranalytics.android.model.utils.SessionUtils import net.pokeranalytics.android.util.extensions.getOrCreate import net.pokeranalytics.android.util.extensions.setHourMinutes @@ -83,7 +86,22 @@ sealed class SessionField { override val numberFormat: String? = null ) : NumberCSVField - data class Blind(override var header: String, override var callback: ((String) -> Pair?)? = null) : BlindCSVField + data class Rebuy( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class Addon( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + + data class Blind(override var header: String, override var callback: ((String) -> Pair?)? = null) : + BlindCSVField + data class Game(override var header: String) : CSVField data class Location(override var header: String) : CSVField data class LocationType(override var header: String) : CSVField @@ -118,7 +136,8 @@ sealed class SessionField { /** * A SessionCSVDescriptor is a CSVDescriptor specialized in parsing Session objects */ -class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean, vararg elements: CSVField) : DataCSVDescriptor(source, *elements) { +class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean, vararg elements: CSVField) : + DataCSVDescriptor(source, *elements) { companion object { val pokerIncomeCash: CSVDescriptor = SessionCSVDescriptor( @@ -142,17 +161,19 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean val pokerBankrollTracker: CSVDescriptor = SessionCSVDescriptor( DataSource.POKER_BANKROLL_TRACKER, true, - SessionField.Start("starttime", dateFormat = "MM/dd/yyyy HH:mm"), - SessionField.End("endtime", dateFormat = "MM/dd/yyyy HH:mm"), + SessionField.Start("starttime", dateFormat = "MM/dd/yy HH:mm"), + SessionField.End("endtime", dateFormat = "MM/dd/yy HH:mm"), SessionField.SessionType("variant"), SessionField.Buyin("buyin"), SessionField.CashedOut("cashout"), + SessionField.Rebuy("rebuycosts"), + SessionField.Addon("addoncosts"), SessionField.Break("breakminutes"), SessionField.LimitType("limit"), SessionField.Game("game"), SessionField.Bankroll("currency"), // same as currency code - SessionField.Location("location"), - SessionField.Comment("sessionnote"), + SessionField.Location("type"), +// SessionField.Comment("sessionnote"), SessionField.Tips("expensesfromstack"), SessionField.SmallBlind("smallblind"), SessionField.BigBlind("bigblind"), @@ -209,7 +230,8 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean SessionField.LocationType("Location Type"), SessionField.Comment("Notes"), SessionField.CurrencyCode("Currency"), - SessionField.Blind("Stakes", callback = { value -> // $10/20 + SessionField.Blind("Stakes", callback = { value -> + // $10/20 value.drop(1) val blinds = value.split("/") if (blinds.size == 2) { @@ -222,10 +244,90 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean } + private enum class DataType { + TRANSACTION, + SESSION; + + companion object { + + fun valueForString(type: String): DataType? { + return when (type) { + "Deposit/Payout" -> TRANSACTION + "Cash Game", "Tournament" -> SESSION + else -> null + } + } + } + + } + /** * Parses a [record] and return an optional Session */ - override fun parseData(realm: Realm, record: CSVRecord): Session? { + override fun parseData(realm: Realm, record: CSVRecord): RealmModel? { + + var dataType: DataType? = null + val typeField = fields.firstOrNull { it is SessionField.SessionType } + typeField?.let { field -> + this.fieldMapping[field]?.let { index -> + val typeValue = record.get(index) + dataType = DataType.valueForString(typeValue) + } + } + + return when (dataType) { + DataType.TRANSACTION -> parseTransaction(realm, record) + else -> parseSession(realm, record) + } + + } + + fun parseTransaction(realm: Realm, record: CSVRecord): Transaction? { + + var date: Date? = null + var amount: Double? = null + var type: TransactionType? = null + var currencyCode: String? = null + var currencyRate: Double? = null + + fields.forEach { field -> + + val index = this.fieldMapping[field] + if (index != null) { + val value = record.get(index) + when (field) { + is SessionField.Start -> { + date = field.parse(value) + } + is SessionField.Buyin -> amount = field.parse(value) + is SessionField.SessionType -> { + type = realm.getOrCreate(value) + } + is SessionField.CurrencyCode -> currencyCode = value + is SessionField.CurrencyRate -> currencyRate = field.parse(value) + else -> { + } + } + } + } + + if (date != null && amount != null && type != null && currencyCode != null) { + + val transaction = realm.copyToRealm(Transaction()) + transaction.date = date!! + transaction.amount = amount!! + transaction.type = type + + val bankroll = Bankroll.getOrCreate(realm, currencyCode!!, currencyRate = currencyRate) + transaction.bankroll = bankroll + + return transaction + } + + return null + } + + fun parseSession(realm: Realm, record: CSVRecord): Session? { val session = Session.newInstance(realm, this.isTournament) @@ -233,6 +335,7 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean var bankrollName: String? = null var currencyCode: String? = null var currencyRate: Double? = null + var additionalBuyins = 0.0 // rebuy + addon fields.forEach { field -> @@ -246,18 +349,34 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean is SessionField.End -> { session.endDate = field.parse(value) } - is SessionField.StartTime -> { session.startDate?.setHourMinutes(value) } - is SessionField.EndTime -> { session.endDate?.setHourMinutes(value) } + is SessionField.StartTime -> { + session.startDate?.setHourMinutes(value) + } + is SessionField.EndTime -> { + session.endDate?.setHourMinutes(value) + } is SessionField.Buyin -> session.result?.buyin = field.parse(value) is SessionField.CashedOut -> session.result?.cashout = field.parse(value) + is SessionField.Addon -> additionalBuyins += field.parse(value) ?: 0.0 + is SessionField.Rebuy -> additionalBuyins += field.parse(value) ?: 0.0 is SessionField.Tips -> session.result?.tips = field.parse(value) is SessionField.Break -> { field.parse(value)?.let { session.breakDuration = it.toLong() * 60 * 1000 } } - is SessionField.Game -> session.game = realm.getOrCreate(value) - is SessionField.Location -> session.location = realm.getOrCreate(value) + is SessionField.Game -> { + if (value.isNotEmpty()) { + session.game = realm.getOrCreate(value) + } else { + } + } + is SessionField.Location -> { + if (value.isNotEmpty()) { + session.location = realm.getOrCreate(value) + } else { + } + } is SessionField.Bankroll -> bankrollName = value is SessionField.LimitType -> session.limit = Limit.getInstance(value)?.ordinal is SessionField.Comment -> session.comment = value @@ -274,31 +393,44 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean session.type = type.ordinal } } - is SessionField.TournamentPosition -> session.result?.tournamentFinalPosition = field.parse(value)?.toInt() + is SessionField.TournamentPosition -> session.result?.tournamentFinalPosition = + field.parse(value)?.toInt() is SessionField.TournamentName -> session.tournamentName = realm.getOrCreate(value) - is SessionField.TournamentType -> session.tournamentType = TournamentType.getValueForLabel(value)?.ordinal - is SessionField.TournamentNumberOfPlayers -> session.tournamentNumberOfPlayers = field.parse(value)?.toInt() + is SessionField.TournamentType -> session.tournamentType = + TournamentType.getValueForLabel(value)?.ordinal + is SessionField.TournamentNumberOfPlayers -> session.tournamentNumberOfPlayers = + field.parse(value)?.toInt() is SessionField.CurrencyCode -> currencyCode = value is SessionField.CurrencyRate -> currencyRate = field.parse(value) - else -> { } + else -> { + } } } } + if (bankrollName.isNullOrEmpty()) { + bankrollName = "Import" + } + session.bankroll = Bankroll.getOrCreate(realm, bankrollName ?: "Import", isLive, currencyCode, currencyRate) val startDate = session.startDate val endDate = session.endDate val net = session.result?.net + session.result?.buyin?.let { + session.result?.buyin = it + additionalBuyins + } - return if (startDate != null && endDate != null && net != null) { // valid session - val unique = SessionUtils.unicityCheck(realm, startDate, endDate, net) - if (unique) session else null - } else { // invalid session - null + if (startDate != null && endDate != null && net != null) { // valid session + if (SessionUtils.unicityCheck(realm, startDate, endDate, net)) { + return session + } } + session.deleteFromRealm() + return null + } } \ No newline at end of file diff --git a/app/src/main/res/layout/bottom_sheet_sum.xml b/app/src/main/res/layout/bottom_sheet_sum.xml index b5451b6a..b657682d 100644 --- a/app/src/main/res/layout/bottom_sheet_sum.xml +++ b/app/src/main/res/layout/bottom_sheet_sum.xml @@ -15,7 +15,7 @@ android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" - android:text="+ 1000 $" + tools:text="+ 1000 $" app:layout_constraintEnd_toStartOf="@+id/button2" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintHorizontal_chainStyle="packed" @@ -30,7 +30,7 @@ android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" - android:text="+ 2000 $" + tools:text="+ 2000 $" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toEndOf="@+id/button1" diff --git a/app/src/main/res/layout/fragment_import.xml b/app/src/main/res/layout/fragment_import.xml index efbb84d7..3d2e9ce5 100644 --- a/app/src/main/res/layout/fragment_import.xml +++ b/app/src/main/res/layout/fragment_import.xml @@ -5,4 +5,44 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index eecdebee..94f1afb6 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -351,4 +351,15 @@ 28sp + + + + From 79c2152d9ec81e0fb788652aa76693b1af2fde37 Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 12 Jun 2019 18:43:26 +0200 Subject: [PATCH 032/125] Bumping version --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 174fae59..5e354191 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,8 +29,8 @@ android { applicationId "net.pokeranalytics.android" minSdkVersion 23 targetSdkVersion 28 - versionCode 38 - versionName "2.0.1" + versionCode 39 + versionName "2.0.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } From 9af997c6a0d3e9fc344b41b276af10f043e25e32 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 13 Jun 2019 18:39:23 +0200 Subject: [PATCH 033/125] CSV import update --- .../android/model/interfaces/Manageable.kt | 7 + .../android/model/realm/Filter.kt | 5 - .../android/model/realm/Session.kt | 2 + .../android/model/utils/DataUtils.kt | 39 +++ .../android/model/utils/SessionUtils.kt | 21 -- .../android/ui/fragment/FiltersFragment.kt | 6 +- .../android/ui/fragment/ImportFragment.kt | 73 ++++- .../android/util/csv/CSVDescriptor.kt | 43 ++- .../android/util/csv/CSVImporter.kt | 75 +++-- .../android/util/csv/ProductCSVDescriptors.kt | 112 ++++++++ .../android/util/csv/SessionCSVDescriptor.kt | 265 ++---------------- .../android/util/csv/SessionField.kt | 122 ++++++++ app/src/main/res/layout/fragment_import.xml | 41 ++- app/src/main/res/values/strings.xml | 1 + app/src/main/res/values/styles.xml | 20 +- 15 files changed, 520 insertions(+), 312 deletions(-) create mode 100644 app/src/main/java/net/pokeranalytics/android/model/utils/DataUtils.kt delete mode 100644 app/src/main/java/net/pokeranalytics/android/model/utils/SessionUtils.kt create mode 100644 app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt create mode 100644 app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt index 26ebd99a..aa9ea5f2 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt @@ -46,6 +46,8 @@ interface NameManageable : Manageable { } +class Identificator(var id: String, var clazz: Class) + /** * An interface associate a unique uniqueIdentifier to an object */ @@ -56,6 +58,11 @@ interface Identifiable : RealmModel { */ var id: String + val identificator: Identificator + get() { + return Identificator(this.id, this::class.java) + } + } /** diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt index 010e2340..3a506826 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt @@ -42,11 +42,6 @@ open class Filter : RealmObject(), RowRepresentable, Editable, Deletable, Counta //return realm.copyToRealm(filter) } - // Get a queryWith by its id - fun getFilterBydId(realm: Realm, filterId: String): Filter? { - return realm.where().equalTo("id", filterId).findFirst() - } - inline fun queryOn(realm: Realm, query: Query, sortField: String? = null): RealmResults { val rootQuery = realm.where() var realmQuery = query.queryWith(rootQuery) 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 975da7d5..25651110 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 @@ -67,6 +67,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat } companion object { + fun newInstance(realm: Realm, isTournament: Boolean, bankroll: Bankroll? = null): Session { val session = Session() session.result = Result() @@ -76,6 +77,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat session.bankroll = realm.where().findFirst() } session.type = if (isTournament) Session.Type.TOURNAMENT.ordinal else Session.Type.CASH_GAME.ordinal + return realm.copyToRealm(session) } 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 new file mode 100644 index 00000000..2e0bd3a6 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/model/utils/DataUtils.kt @@ -0,0 +1,39 @@ +package net.pokeranalytics.android.model.utils + +import io.realm.Realm +import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.model.realm.Transaction +import net.pokeranalytics.android.model.realm.TransactionType +import java.util.* + +class DataUtils { + + companion object { + + /** + * Returns true if the provided parameters doesn't correspond to an existing session + */ + fun sessionCount(realm: Realm, startDate: Date, endDate: Date, net: Double): Int { + val sessions = realm.where(Session::class.java) + .equalTo("startDate", startDate) + .equalTo("endDate", endDate) + .equalTo("result.net", net) + .findAll() + return sessions.size + } + + /** + * Returns true if the provided parameters doesn't correspond to an existing transaction + */ + fun transactionUnicityCheck(realm: Realm, date: Date, amount: Double, type: TransactionType): Boolean { + val transactions = realm.where(Transaction::class.java) + .equalTo("date", date) + .equalTo("amount", amount) + .equalTo("type.id", type.id) + .findAll() + return transactions.isEmpty() + } + + } + +} diff --git a/app/src/main/java/net/pokeranalytics/android/model/utils/SessionUtils.kt b/app/src/main/java/net/pokeranalytics/android/model/utils/SessionUtils.kt deleted file mode 100644 index d8d93f7e..00000000 --- a/app/src/main/java/net/pokeranalytics/android/model/utils/SessionUtils.kt +++ /dev/null @@ -1,21 +0,0 @@ -package net.pokeranalytics.android.model.utils - -import io.realm.Realm -import net.pokeranalytics.android.model.realm.Session -import java.util.* - -class SessionUtils { - - companion object { - - /** - * Returns true if the provided parameters doesn't correspond to an existing session - */ - fun unicityCheck(realm: Realm, startDate: Date, endDate: Date, net: Double) : Boolean { - val sessions = realm.where(Session::class.java).equalTo("startDate", startDate).equalTo("endDate", endDate).equalTo("result.net", net).findAll() - return sessions.isEmpty() - } - - } - -} diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt index 0a1b696e..564fb7ac 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt @@ -12,6 +12,7 @@ import kotlinx.android.synthetic.main.fragment_editable_data.recyclerView import kotlinx.android.synthetic.main.fragment_filters.* import kotlinx.android.synthetic.main.fragment_filters.view.toolbar import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.ui.activity.FilterDetailsActivity @@ -27,6 +28,7 @@ import net.pokeranalytics.android.ui.interfaces.FilterableType import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.util.Preferences +import net.pokeranalytics.android.util.extensions.findById import net.pokeranalytics.android.util.extensions.sorted import timber.log.Timber @@ -173,7 +175,9 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, val realm = getRealm() primaryKey?.let { - currentFilter = realm.copyFromRealm(Filter.getFilterBydId(realm, it)) + + val filter = realm.findById(it) ?: throw PAIllegalStateException("Can't find filter with id=$it") + currentFilter = realm.copyFromRealm(filter) isUpdating = true } ?: run { currentFilter = Filter.newInstance(this.filterableType.uniqueIdentifier) //realm.copyFromRealm(Filter.newInstanceForResult(realm, this.filterableType.ordinal)) 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 c0d0775c..e8025a10 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 @@ -4,18 +4,19 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import kotlinx.android.synthetic.main.fragment_import.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async import kotlinx.coroutines.launch import net.pokeranalytics.android.R -import net.pokeranalytics.android.ui.activity.components.ResultCode import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.util.csv.CSVImporter import net.pokeranalytics.android.util.csv.ImportDelegate import net.pokeranalytics.android.util.csv.ImportException import timber.log.Timber import java.io.InputStream +import java.text.NumberFormat import java.util.* import kotlin.coroutines.CoroutineContext @@ -26,6 +27,7 @@ class ImportFragment : RealmFragment(), ImportDelegate { private lateinit var filePath: String private lateinit var inputStream: InputStream + private lateinit var importer: CSVImporter fun setData(path: String) { this.filePath = path @@ -43,12 +45,34 @@ class ImportFragment : RealmFragment(), ImportDelegate { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + this.initUI() + this.startImport() } - fun startImport() { + private fun initUI() { + + this.imported.text = requireContext().getString(R.string.imported) + this.total.text = requireContext().getString(R.string.total) + + this.save.isEnabled = false + this.save.setOnClickListener { + this.end() + } - var shouldDismissActivity = false + this.cancel.setOnClickListener { + this.cancel() + this.end() + } + + } + + private fun startImport() { + +// var shouldDismissActivity = false + + this.importer = CSVImporter(inputStream) + this.importer.delegate = this GlobalScope.launch(coroutineContext) { @@ -57,10 +81,9 @@ class ImportFragment : RealmFragment(), ImportDelegate { Timber.d(">>> Start Import...") try { - val csv = CSVImporter(inputStream) - csv.start() + importer.start() } catch (e: ImportException) { - shouldDismissActivity = true +// shouldDismissActivity = true } val e = Date() val duration = (e.time - s.time) / 1000.0 @@ -69,23 +92,43 @@ class ImportFragment : RealmFragment(), ImportDelegate { } test.await() - if (shouldDismissActivity) { +// if (shouldDismissActivity) { +// +// activity?.let { +// it.setResult(ResultCode.IMPORT_UNRECOGNIZED_FORMAT.value) +// it.finish() +// } +// +// } else { +// } + importDidFinish() - activity?.let { - it.setResult(ResultCode.IMPORT_UNRECOGNIZED_FORMAT.value) - it.finish() - } + } - } + } - } + private fun cancel() { + this.importer.cancel(getRealm()) + } + + private fun importDidFinish() { + this.save.isEnabled = true + + } + + private fun end() { + activity?.finish() } + val numberFormatter = NumberFormat.getNumberInstance() + // ImportDelegate - override fun parsingCountUpdate(count: Int) { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + override fun parsingCountUpdate(importedCount: Int, totalCount: Int) { + this.counter.text = this.numberFormatter.format(importedCount) + this.totalCounter.text = this.numberFormatter.format(totalCount) } + } \ No newline at end of file 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 bf517d5e..847a775c 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 @@ -1,7 +1,10 @@ package net.pokeranalytics.android.util.csv import io.realm.Realm -import io.realm.RealmModel +import io.realm.kotlin.deleteFromRealm +import net.pokeranalytics.android.model.interfaces.Identifiable +import net.pokeranalytics.android.model.interfaces.Identificator +import net.pokeranalytics.android.util.extensions.findById import org.apache.commons.csv.CSVRecord import timber.log.Timber @@ -17,19 +20,30 @@ enum class DataSource { /** * A DataCSVDescriptor produces RealmModel instances for each row */ -abstract class DataCSVDescriptor(source: DataSource, vararg elements: CSVField) : CSVDescriptor(source, *elements) { +abstract class DataCSVDescriptor(source: DataSource, vararg elements: CSVField) : CSVDescriptor(source, *elements) { - val realmModels = mutableListOf() + /** + * List of Realm object identificators + */ + val realmModelIds = mutableListOf() abstract fun parseData(realm: Realm, record: CSVRecord): T? - override fun parse(realm: Realm, record: CSVRecord) { + override fun parse(realm: Realm, record: CSVRecord): Int { val data = this.parseData(realm, record) data?.let { - this.realmModels.add(it) + this.realmModelIds.add(it.identificator) } + return if (data != null) 1 else 0 + } + override fun cancel(realm: Realm) { + realm.executeTransaction { + this.realmModelIds.forEach { identificator -> + realm.findById(identificator.clazz, identificator.id)?.deleteFromRealm() + } + } } } @@ -59,7 +73,19 @@ abstract class CSVDescriptor(var source: DataSource, vararg elements: CSVField) * The list of all managed CSVDescriptors */ val all: List = - listOf(SessionCSVDescriptor.pokerIncomeCash, SessionCSVDescriptor.pokerBankrollTracker, SessionCSVDescriptor.runGoodCashGames, SessionCSVDescriptor.runGoodTournaments) + listOf(ProductCSVDescriptors.pokerIncomeCash, + ProductCSVDescriptors.pokerBankrollTracker, + ProductCSVDescriptors.runGoodCashGames, + ProductCSVDescriptors.runGoodTournaments) + } + + /** + * Method called when iterating on a CSVRecord + */ + abstract fun parse(realm: Realm, record: CSVRecord): Int + + open fun cancel(realm: Realm) { + } /** @@ -83,9 +109,4 @@ abstract class CSVDescriptor(var source: DataSource, vararg elements: CSVField) return count == this.fields.size } - /** - * Method called when iterating on a CSVRecord - */ - abstract fun parse(realm: Realm, record: CSVRecord) - } 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 a2772236..17476360 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 @@ -1,7 +1,10 @@ package net.pokeranalytics.android.util.csv +import android.os.Handler +import android.os.Looper import io.realm.Realm import org.apache.commons.csv.CSVFormat +import org.apache.commons.csv.CSVParser import org.apache.commons.csv.CSVRecord import timber.log.Timber import java.io.FileReader @@ -12,7 +15,7 @@ import java.io.Reader class ImportException(message: String) : Exception(message) interface ImportDelegate { - fun parsingCountUpdate(count: Int) + fun parsingCountUpdate(importedCount: Int, totalCount: Int) } /** @@ -60,11 +63,27 @@ open class CSVImporter(istream: InputStream) { * Stores the descriptors found */ private var usedDescriptors: MutableList = mutableListOf() + /** * The currently used CSVDescriptor for parsing */ private var currentDescriptor: CSVDescriptor? = null + /** + * The number of valid record parsed + */ + private var totalParsedRecords = 0 + + /** + * The number of successfully imported records + */ + private var importedRecords = 0 + + /** + * The CSV parser + */ + private lateinit var parser: CSVParser + /** * Constructs a CSVParser object and starts parsing the CSV */ @@ -80,7 +99,7 @@ open class CSVImporter(istream: InputStream) { reader = InputStreamReader(this.inputStream) } - val parser = CSVFormat.DEFAULT.withAllowMissingColumnNames().parse(reader) + this.parser = CSVFormat.DEFAULT.withAllowMissingColumnNames().parse(reader) Timber.d("Starting import...") @@ -89,6 +108,7 @@ open class CSVImporter(istream: InputStream) { parser.forEachIndexed { index, record -> Timber.d("line $index") + this.notifyDelegate() if (this.currentDescriptor == null) { // find descriptor this.currentDescriptor = this.findDescriptor(record) @@ -106,10 +126,10 @@ open class CSVImporter(istream: InputStream) { } else { // parse + // batch commit val parsingIndex = index + 1 if (parsingIndex % COMMIT_FREQUENCY == 0) { Timber.d("****** committing at $parsingIndex sessions...") - this.delegate?.parsingCountUpdate(parsingIndex) realm.commitTransaction() realm.beginTransaction() } @@ -117,19 +137,27 @@ open class CSVImporter(istream: InputStream) { this.currentDescriptor?.let { if (record.size() == 0) { this.usedDescriptors.add(it) - this.currentDescriptor = null // reset descriptor when encountering an empty line (multiple descriptors can be found in a single file) + this.currentDescriptor = + null // reset descriptor when encountering an empty line (multiple descriptors can be found in a single file) this.descriptorFindingAttempts = 0 } else { - it.parse(realm, record) + val count = it.parse(realm, record) + + this.importedRecords += count + this.totalParsedRecords++ + + this.notifyDelegate() } } ?: run { realm.cancelTransaction() - throw IllegalStateException("CSVDescriptor should never be null here") + throw ImportException("CSVDescriptor should never be null here") } } } + this.notifyDelegate() + realm.commitTransaction() Timber.d("Ending import...") @@ -137,10 +165,16 @@ open class CSVImporter(istream: InputStream) { realm.close() } + private fun notifyDelegate() { + Handler(Looper.getMainLooper()).post { + this.delegate?.parsingCountUpdate(this.importedRecords, this.totalParsedRecords) + } + } + /** * Search for a descriptor in the list of managed formats */ - private fun findDescriptor(record: CSVRecord) : CSVDescriptor? { + private fun findDescriptor(record: CSVRecord): CSVDescriptor? { CSVDescriptor.all.forEach { descriptor -> if (descriptor.matches(record)) { @@ -152,17 +186,26 @@ open class CSVImporter(istream: InputStream) { return null } - fun save(realm: Realm) { - +// fun save(realm: Realm) { +// +// this.usedDescriptors.forEach { descriptor -> +// +// if (descriptor is DataCSVDescriptor<*>) { +// realm.executeTransaction { +// realm.copyToRealm(descriptor.realmModels) +// } +// } +// } +// } + + fun cancel(realm: Realm) { + this.parser.close() + realm.refresh() + + this.currentDescriptor?.cancel(realm) this.usedDescriptors.forEach { descriptor -> - - if (descriptor is DataCSVDescriptor<*>) { - realm.executeTransaction { - realm.copyToRealm(descriptor.realmModels) - } - } + descriptor.cancel(realm) } - } } 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 new file mode 100644 index 00000000..a475972b --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt @@ -0,0 +1,112 @@ +package net.pokeranalytics.android.util.csv + +class ProductCSVDescriptors { + + companion object { + + val pokerIncomeCash: CSVDescriptor = SessionCSVDescriptor( + DataSource.POKER_INCOME, + false, + SessionField.Start("Start Time"), + SessionField.End("End Time"), + SessionField.Buyin("Buy In"), + SessionField.CashedOut("Cashed Out"), + SessionField.Break("Break Minutes"), + SessionField.LimitType("Limit Type"), + SessionField.Game("Game"), + SessionField.Bankroll("Bankroll"), + SessionField.Location("Location"), + SessionField.Location("Location Type"), + SessionField.Comment("Note"), + SessionField.Tips("Tips"), + SessionField.Blind("Stake") + ) + + val pokerBankrollTracker: CSVDescriptor = SessionCSVDescriptor( + DataSource.POKER_BANKROLL_TRACKER, + true, + SessionField.Start("starttime", dateFormat = "MM/dd/yy HH:mm"), + SessionField.End("endtime", dateFormat = "MM/dd/yy HH:mm"), + SessionField.SessionType("variant"), + SessionField.Buyin("buyin"), + SessionField.CashedOut("cashout"), + SessionField.Rebuy("rebuycosts"), + SessionField.Addon("addoncosts"), + SessionField.Break("breakminutes"), + SessionField.LimitType("limit"), + SessionField.Game("game"), + SessionField.Bankroll("currency"), // same as currency code + SessionField.Location("type"), +// SessionField.Comment("sessionnote"), + SessionField.Tips("expensesfromstack"), + SessionField.SmallBlind("smallblind"), + SessionField.BigBlind("bigblind"), + SessionField.TournamentNumberOfPlayers("player"), + SessionField.TournamentPosition("place"), + SessionField.TournamentName("mttname"), + SessionField.CurrencyCode("currency"), + SessionField.CurrencyRate("exchangerate"), + SessionField.TableSize("tablesize") + ) + + val runGoodTournaments: CSVDescriptor = SessionCSVDescriptor( + DataSource.RUNGOOD, + true, + SessionField.Start("Start Date", dateFormat = "dd/MM/yyyy"), + SessionField.StartTime("Start Time"), + SessionField.End("End Date"), + SessionField.EndTime("End Time"), + SessionField.Buyin("Total Buy-In"), + SessionField.CashedOut("Winnings"), + SessionField.NetResult("Profit"), + SessionField.Break("Break"), + SessionField.LimitType("Limit Type"), + SessionField.Game("Game"), + SessionField.Bankroll("Bankroll"), + SessionField.TableSize("Table Type"), + SessionField.Location("Location"), + SessionField.LocationType("Location Type"), + SessionField.Comment("Notes"), + SessionField.CurrencyCode("Currency"), + SessionField.TournamentName("Event Name"), + SessionField.TournamentNumberOfPlayers("Total Players"), + SessionField.TournamentPosition("Finished Place"), + SessionField.TournamentType("Single-Table/Multi-Table") + + ) + + val runGoodCashGames: CSVDescriptor = SessionCSVDescriptor( + DataSource.RUNGOOD, + false, + SessionField.Start("Start Date", dateFormat = "dd/MM/yyyy"), + SessionField.StartTime("Start Time", dateFormat = "HH:mm"), + SessionField.End("End Date", dateFormat = "dd/MM/yyyy"), + SessionField.EndTime("End Time", dateFormat = "HH:mm"), + SessionField.Buyin("Total Buy-In"), + SessionField.CashedOut("Cashed Out"), + SessionField.NetResult("Profit"), + SessionField.Break("Break"), + SessionField.LimitType("Limit Type"), + SessionField.Game("Game"), + SessionField.Bankroll("Bankroll"), + SessionField.TableSize("Table Type"), + SessionField.Location("Location"), + SessionField.LocationType("Location Type"), + SessionField.Comment("Notes"), + SessionField.CurrencyCode("Currency"), + SessionField.Blind("Stakes", callback = { value -> + // $10/20 + value.drop(1) + val blinds = value.split("/") + if (blinds.size == 2) { + return@Blind Pair(blinds.first().toDouble(), blinds.last().toDouble()) + } else { + return@Blind null + } + }) + ) + + + } + +} \ 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 c70d15bb..54dda264 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 @@ -1,248 +1,26 @@ package net.pokeranalytics.android.util.csv import io.realm.Realm -import io.realm.RealmModel 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.Bankroll import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.model.realm.TransactionType -import net.pokeranalytics.android.model.utils.SessionUtils +import net.pokeranalytics.android.model.utils.DataUtils 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.util.* -/** - * The enumeration of Session fields - */ -sealed class SessionField { - - data class Start( - override var header: String, - override var callback: ((String) -> Date?)? = null, - override val dateFormat: String? = null - ) : DateCSVField - - data class StartTime( - override var header: String, - override var callback: ((String) -> Date?)? = null, - override val dateFormat: String? = null - ) : DateCSVField - - data class End( - override var header: String, - override var callback: ((String) -> Date?)? = null, - override val dateFormat: String? = null - ) : DateCSVField - - data class EndTime( - override var header: String, - override var callback: ((String) -> Date?)? = null, - override val dateFormat: String? = null - ) : DateCSVField - - data class Buyin( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - data class NetResult( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - data class CashedOut( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - data class Break( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - data class Tips( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - data class SmallBlind( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - data class BigBlind( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - data class Rebuy( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - data class Addon( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - - data class Blind(override var header: String, override var callback: ((String) -> Pair?)? = null) : - BlindCSVField - - data class Game(override var header: String) : CSVField - data class Location(override var header: String) : CSVField - data class LocationType(override var header: String) : CSVField - data class Bankroll(override var header: String) : CSVField - data class LimitType(override var header: String) : CSVField - data class Comment(override var header: String) : CSVField - data class SessionType(override var header: String) : CSVField - data class TableSize(override var header: String) : CSVField - data class CurrencyCode(override var header: String) : CSVField - data class TournamentName(override var header: String) : CSVField - data class TournamentType(override var header: String) : CSVField - - data class CurrencyRate( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - data class TournamentPosition( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField - - data class TournamentNumberOfPlayers( - override var header: String, - override var callback: ((String) -> Double?)? = null, - override val numberFormat: String? = null - ) : NumberCSVField -} - /** * A SessionCSVDescriptor is a CSVDescriptor specialized in parsing Session objects */ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean, vararg elements: CSVField) : - DataCSVDescriptor(source, *elements) { - - companion object { - val pokerIncomeCash: CSVDescriptor = SessionCSVDescriptor( - DataSource.POKER_INCOME, - false, - SessionField.Start("Start Time"), - SessionField.End("End Time"), - SessionField.Buyin("Buy In"), - SessionField.CashedOut("Cashed Out"), - SessionField.Break("Break Minutes"), - SessionField.LimitType("Limit Type"), - SessionField.Game("Game"), - SessionField.Bankroll("Bankroll"), - SessionField.Location("Location"), - SessionField.Location("Location Type"), - SessionField.Comment("Note"), - SessionField.Tips("Tips"), - SessionField.Blind("Stake") - ) - - val pokerBankrollTracker: CSVDescriptor = SessionCSVDescriptor( - DataSource.POKER_BANKROLL_TRACKER, - true, - SessionField.Start("starttime", dateFormat = "MM/dd/yy HH:mm"), - SessionField.End("endtime", dateFormat = "MM/dd/yy HH:mm"), - SessionField.SessionType("variant"), - SessionField.Buyin("buyin"), - SessionField.CashedOut("cashout"), - SessionField.Rebuy("rebuycosts"), - SessionField.Addon("addoncosts"), - SessionField.Break("breakminutes"), - SessionField.LimitType("limit"), - SessionField.Game("game"), - SessionField.Bankroll("currency"), // same as currency code - SessionField.Location("type"), -// SessionField.Comment("sessionnote"), - SessionField.Tips("expensesfromstack"), - SessionField.SmallBlind("smallblind"), - SessionField.BigBlind("bigblind"), - SessionField.TournamentNumberOfPlayers("player"), - SessionField.TournamentPosition("place"), - SessionField.TournamentName("mttname"), - SessionField.CurrencyCode("currency"), - SessionField.CurrencyRate("exchangerate"), - SessionField.TableSize("tablesize") - ) - - val runGoodTournaments: CSVDescriptor = SessionCSVDescriptor( - DataSource.RUNGOOD, - true, - SessionField.Start("Start Date", dateFormat = "dd/MM/yyyy"), - SessionField.StartTime("Start Time"), - SessionField.End("End Date"), - SessionField.EndTime("End Time"), - SessionField.Buyin("Total Buy-In"), - SessionField.CashedOut("Winnings"), - SessionField.NetResult("Profit"), - SessionField.Break("Break"), - SessionField.LimitType("Limit Type"), - SessionField.Game("Game"), - SessionField.Bankroll("Bankroll"), - SessionField.TableSize("Table Type"), - SessionField.Location("Location"), - SessionField.LocationType("Location Type"), - SessionField.Comment("Notes"), - SessionField.CurrencyCode("Currency"), - SessionField.TournamentName("Event Name"), - SessionField.TournamentNumberOfPlayers("Total Players"), - SessionField.TournamentPosition("Finished Place"), - SessionField.TournamentType("Single-Table/Multi-Table") - - ) - - val runGoodCashGames: CSVDescriptor = SessionCSVDescriptor( - DataSource.RUNGOOD, - false, - SessionField.Start("Start Date", dateFormat = "dd/MM/yyyy"), - SessionField.StartTime("Start Time", dateFormat = "HH:mm"), - SessionField.End("End Date", dateFormat = "dd/MM/yyyy"), - SessionField.EndTime("End Time", dateFormat = "HH:mm"), - SessionField.Buyin("Total Buy-In"), - SessionField.CashedOut("Cashed Out"), - SessionField.NetResult("Profit"), - SessionField.Break("Break"), - SessionField.LimitType("Limit Type"), - SessionField.Game("Game"), - SessionField.Bankroll("Bankroll"), - SessionField.TableSize("Table Type"), - SessionField.Location("Location"), - SessionField.LocationType("Location Type"), - SessionField.Comment("Notes"), - SessionField.CurrencyCode("Currency"), - SessionField.Blind("Stakes", callback = { value -> - // $10/20 - value.drop(1) - val blinds = value.split("/") - if (blinds.size == 2) { - return@Blind Pair(blinds.first().toDouble(), blinds.last().toDouble()) - } else { - return@Blind null - } - }) - ) - - } + DataCSVDescriptor(source, *elements) { private enum class DataType { TRANSACTION, @@ -264,7 +42,7 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean /** * Parses a [record] and return an optional Session */ - override fun parseData(realm: Realm, record: CSVRecord): RealmModel? { + override fun parseData(realm: Realm, record: CSVRecord): Identifiable? { var dataType: DataType? = null val typeField = fields.firstOrNull { it is SessionField.SessionType } @@ -282,7 +60,7 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean } - fun parseTransaction(realm: Realm, record: CSVRecord): Transaction? { + private fun parseTransaction(realm: Realm, record: CSVRecord): Transaction? { var date: Date? = null var amount: Double? = null @@ -313,24 +91,32 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean if (date != null && amount != null && type != null && currencyCode != null) { - val transaction = realm.copyToRealm(Transaction()) - transaction.date = date!! - transaction.amount = amount!! - transaction.type = type + if (DataUtils.transactionUnicityCheck(realm, date!!, amount!!, type!!)) { - val bankroll = Bankroll.getOrCreate(realm, currencyCode!!, currencyRate = currencyRate) - transaction.bankroll = bankroll + val transaction = realm.copyToRealm(Transaction()) + transaction.date = date!! + transaction.amount = amount!! + transaction.type = type - return transaction + val bankroll = Bankroll.getOrCreate(realm, currencyCode!!, currencyRate = currencyRate) + transaction.bankroll = bankroll + return transaction + } else { + Timber.d("Transaction already exists") + } + } else { + Timber.d("Can't import transaction: date=$date, amount=$amount, type=${type?.name}") } return null } - fun parseSession(realm: Realm, record: CSVRecord): Session? { + private fun parseSession(realm: Realm, record: CSVRecord): Session? { val session = Session.newInstance(realm, this.isTournament) + + var isLive = true var bankrollName: String? = null var currencyCode: String? = null @@ -423,14 +209,17 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean } if (startDate != null && endDate != null && net != null) { // valid session - if (SessionUtils.unicityCheck(realm, startDate, endDate, net)) { + if (DataUtils.sessionCount(realm, startDate, endDate, net) == 1) { // session already in realm, we'd love not put it in Realm before doing the check return session + } else { + Timber.d("Session already exists") } + } else { + Timber.d("Can't import session: sd=$startDate, ed=$endDate, net=$net") } session.deleteFromRealm() return null - } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt new file mode 100644 index 00000000..6f0876af --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt @@ -0,0 +1,122 @@ +package net.pokeranalytics.android.util.csv + +import java.util.* + + +/** + * The enumeration of Session fields + */ +sealed class SessionField { + + data class Start( + override var header: String, + override var callback: ((String) -> Date?)? = null, + override val dateFormat: String? = null + ) : DateCSVField + + data class StartTime( + override var header: String, + override var callback: ((String) -> Date?)? = null, + override val dateFormat: String? = null + ) : DateCSVField + + data class End( + override var header: String, + override var callback: ((String) -> Date?)? = null, + override val dateFormat: String? = null + ) : DateCSVField + + data class EndTime( + override var header: String, + override var callback: ((String) -> Date?)? = null, + override val dateFormat: String? = null + ) : DateCSVField + + data class Buyin( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class NetResult( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class CashedOut( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class Break( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class Tips( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class SmallBlind( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class BigBlind( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class Rebuy( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class Addon( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + + data class Blind(override var header: String, override var callback: ((String) -> Pair?)? = null) : + BlindCSVField + + data class Game(override var header: String) : CSVField + data class Location(override var header: String) : CSVField + data class LocationType(override var header: String) : CSVField + data class Bankroll(override var header: String) : CSVField + data class LimitType(override var header: String) : CSVField + data class Comment(override var header: String) : CSVField + data class SessionType(override var header: String) : CSVField + data class TableSize(override var header: String) : CSVField + data class CurrencyCode(override var header: String) : CSVField + data class TournamentName(override var header: String) : CSVField + data class TournamentType(override var header: String) : CSVField + + data class CurrencyRate( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class TournamentPosition( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField + + data class TournamentNumberOfPlayers( + override var header: String, + override var callback: ((String) -> Double?)? = null, + override val numberFormat: String? = null + ) : NumberCSVField +} diff --git a/app/src/main/res/layout/fragment_import.xml b/app/src/main/res/layout/fragment_import.xml index 3d2e9ce5..67018bcd 100644 --- a/app/src/main/res/layout/fragment_import.xml +++ b/app/src/main/res/layout/fragment_import.xml @@ -5,9 +5,21 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + + + + + - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2e0726ec..d9c9355e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -37,6 +37,7 @@ The filter cannot be deleted because it is currently selected. Custom field The item is used in one or more transactions…Please delete the linked transactions first + Imported Address Naming suggestions diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 94f1afb6..23e128e8 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -353,7 +353,16 @@ - + + + + From 136d1a55a7335e6072247f58a183b27889720080 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 14 Jun 2019 12:14:16 +0200 Subject: [PATCH 034/125] Fixing import issues --- app/src/main/AndroidManifest.xml | 14 ++-- .../android/model/interfaces/Manageable.kt | 13 ++-- .../android/model/interfaces/Timed.kt | 7 +- .../android/model/realm/Bankroll.kt | 5 ++ .../android/model/realm/CustomField.kt | 4 ++ .../android/model/realm/CustomFieldEntry.kt | 4 ++ .../android/model/realm/Filter.kt | 9 +-- .../android/model/realm/Game.kt | 5 ++ .../android/model/realm/Location.kt | 5 ++ .../android/model/realm/ReportSetup.kt | 4 ++ .../android/model/realm/Session.kt | 11 ++- .../android/model/realm/SessionSet.kt | 11 ++- .../android/model/realm/TournamentFeature.kt | 5 ++ .../android/model/realm/TournamentName.kt | 5 ++ .../android/model/realm/Transaction.kt | 5 +- .../android/model/realm/TransactionType.kt | 5 ++ .../android/ui/activity/HomeActivity.kt | 26 +++---- .../android/ui/activity/ImportActivity.kt | 71 +++++++++++++++---- .../android/ui/fragment/GraphFragment.kt | 14 ++-- .../android/ui/graph/GraphUnderlyingEntry.kt | 6 +- .../CustomizableRowRepresentable.kt | 5 +- .../android/util/csv/CSVDescriptor.kt | 29 ++++++-- .../android/util/csv/CSVImporter.kt | 22 +++--- .../android/util/csv/SessionCSVDescriptor.kt | 6 +- 24 files changed, 197 insertions(+), 94 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b9ef5ab9..b7e5f47c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -32,6 +32,13 @@ + + + + @@ -45,13 +52,6 @@ - - - - ) +class ObjectIdentifier(var id: String, var clazz: Class) /** * An interface associate a unique uniqueIdentifier to an object @@ -58,11 +57,15 @@ interface Identifiable : RealmModel { */ var id: String - val identificator: Identificator + /** + * required because "this.class" returns the proxy class, making where queries crash + */ + val realmObjectClass: Class + + val objectIdentifier: ObjectIdentifier get() { - return Identificator(this.id, this::class.java) + return ObjectIdentifier(this.id, this.realmObjectClass) } - } /** diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt index 31ca5fe9..4b4c752f 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt @@ -1,14 +1,9 @@ package net.pokeranalytics.android.model.interfaces import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry -import net.pokeranalytics.android.ui.graph.ObjectIdentifier import java.util.* -interface GraphIdentifiableEntry : GraphUnderlyingEntry, Identifiable { - - val objectIdentifier : ObjectIdentifier - -} +interface GraphIdentifiableEntry : GraphUnderlyingEntry, Identifiable interface Timed : GraphIdentifiableEntry { diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt index 00af3d42..3a5910ef 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt @@ -4,11 +4,13 @@ import android.content.Context import io.realm.Realm import io.realm.RealmObject import io.realm.RealmResults +import io.realm.annotations.Ignore import io.realm.annotations.LinkingObjects import io.realm.annotations.PrimaryKey import io.realm.kotlin.where import net.pokeranalytics.android.R import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.view.RowRepresentable @@ -127,4 +129,7 @@ open class Bankroll : RealmObject(), NameManageable, RowRepresentable { return UserDefaults.currency } + @Ignore + override val realmObjectClass: Class = Bankroll::class.java + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/CustomField.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/CustomField.kt index 2b03ba11..98266561 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/CustomField.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/CustomField.kt @@ -11,6 +11,7 @@ import io.realm.kotlin.where import net.pokeranalytics.android.R import net.pokeranalytics.android.model.Criteria import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource @@ -28,6 +29,9 @@ import kotlin.collections.ArrayList open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDataSource, RowRepresentable { + @Ignore + override val realmObjectClass: Class = CustomField::class.java + /** * The custom field type: a list of items, a number or an amont */ diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/CustomFieldEntry.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/CustomFieldEntry.kt index f4716084..9a98cfc1 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/CustomFieldEntry.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/CustomFieldEntry.kt @@ -12,6 +12,7 @@ import io.realm.kotlin.where import net.pokeranalytics.android.R import net.pokeranalytics.android.exceptions.ModelException import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType @@ -27,6 +28,9 @@ import java.util.Currency open class CustomFieldEntry : RealmObject(), NameManageable, RowRepresentable { + @Ignore + override val realmObjectClass: Class = CustomFieldEntry::class.java + @PrimaryKey override var id = UUID.randomUUID().toString() diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt index 3a506826..25059c97 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt @@ -5,16 +5,14 @@ import io.realm.Realm import io.realm.RealmList import io.realm.RealmObject import io.realm.RealmResults +import io.realm.annotations.Ignore import io.realm.annotations.PrimaryKey import io.realm.kotlin.where import net.pokeranalytics.android.R import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.QueryCondition -import net.pokeranalytics.android.model.interfaces.CountableUsage -import net.pokeranalytics.android.model.interfaces.Deletable -import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus -import net.pokeranalytics.android.model.interfaces.Editable +import net.pokeranalytics.android.model.interfaces.* import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType import net.pokeranalytics.android.ui.interfaces.FilterableType import net.pokeranalytics.android.ui.view.ImageDecorator @@ -32,6 +30,9 @@ import java.util.* */ open class Filter : RealmObject(), RowRepresentable, Editable, Deletable, CountableUsage, ImageDecorator { + @Ignore + override val realmObjectClass: Class = Filter::class.java + companion object { // Create a new instance diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt index 2334baa0..9ee4dcc6 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt @@ -3,10 +3,12 @@ package net.pokeranalytics.android.model.realm import android.content.Context import io.realm.Realm import io.realm.RealmObject +import io.realm.annotations.Ignore import io.realm.annotations.PrimaryKey import io.realm.kotlin.where import net.pokeranalytics.android.R import net.pokeranalytics.android.model.interfaces.CountableUsage +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource @@ -20,6 +22,9 @@ import kotlin.collections.ArrayList open class Game : RealmObject(), NameManageable, StaticRowRepresentableDataSource, RowRepresentable, CountableUsage { + @Ignore + override val realmObjectClass: Class = Game::class.java + companion object { val rowRepresentation : List by lazy { val rows = ArrayList() diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Location.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Location.kt index df4136e4..9f64f7fb 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Location.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Location.kt @@ -4,9 +4,11 @@ import android.content.Context import com.google.android.libraries.places.api.model.Place import io.realm.Realm import io.realm.RealmObject +import io.realm.annotations.Ignore import io.realm.annotations.PrimaryKey import io.realm.kotlin.where import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.view.RowRepresentable @@ -16,6 +18,9 @@ import java.util.* open class Location : RealmObject(), NameManageable, RowRepresentable { + @Ignore + override val realmObjectClass: Class = Location::class.java + @PrimaryKey override var id = UUID.randomUUID().toString() diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/ReportSetup.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/ReportSetup.kt index 2db6f02e..f813dd75 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/ReportSetup.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/ReportSetup.kt @@ -11,6 +11,7 @@ import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.model.Criteria 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.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.util.extensions.findById @@ -19,6 +20,9 @@ import java.util.* open class ReportSetup : RealmObject(), RowRepresentable, Deletable { + @Ignore + override val realmObjectClass: Class = ReportSetup::class.java + @PrimaryKey override var id = UUID.randomUUID().toString() 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 25651110..99e5ed52 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.ComputedStat import net.pokeranalytics.android.calculus.Stat 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.TableSize import net.pokeranalytics.android.model.TournamentType @@ -29,7 +30,6 @@ import net.pokeranalytics.android.model.utils.SessionSetManager import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.UnmanagedRowRepresentableException import net.pokeranalytics.android.ui.fragment.GraphFragment -import net.pokeranalytics.android.ui.graph.ObjectIdentifier import net.pokeranalytics.android.ui.view.* import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.SeparatorRow @@ -422,7 +422,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat this.computableResults?.forEachIndexed { index, computableResult -> computableResult.updateWith(this) if (index > 0) { - throw IllegalStateException("Session cannot have more than one computable result") + throw PAIllegalStateException("Session cannot have more than one computable result") } } this.sessionSet?.computeStats() @@ -1149,10 +1149,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat } - // Timed - - override val objectIdentifier: ObjectIdentifier - get() = ObjectIdentifier(this.id, Session::class.java) - + @Ignore + override val realmObjectClass: Class = Session::class.java } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt index da9976b6..c447de69 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt @@ -4,16 +4,17 @@ import android.content.Context import io.realm.Realm import io.realm.RealmObject import io.realm.RealmResults +import io.realm.annotations.Ignore import io.realm.annotations.LinkingObjects import io.realm.annotations.PrimaryKey import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.StatFormattingException -import net.pokeranalytics.android.util.TextFormat import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.QueryCondition +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.Timed -import net.pokeranalytics.android.ui.graph.ObjectIdentifier import net.pokeranalytics.android.util.NULL_TEXT +import net.pokeranalytics.android.util.TextFormat import java.text.DateFormat import java.util.* @@ -138,10 +139,8 @@ open class SessionSet() : RealmObject(), Timed, Filterable { } } - // Timed - - override val objectIdentifier: ObjectIdentifier - get() = ObjectIdentifier(this.id, SessionSet::class.java) + @Ignore + override val realmObjectClass: Class = SessionSet::class.java } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt index f11f0e73..5a51c448 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt @@ -3,10 +3,12 @@ package net.pokeranalytics.android.model.realm import android.content.Context import io.realm.Realm import io.realm.RealmObject +import io.realm.annotations.Ignore import io.realm.annotations.PrimaryKey import io.realm.kotlin.where import net.pokeranalytics.android.R import net.pokeranalytics.android.model.interfaces.CountableUsage +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource @@ -30,6 +32,9 @@ open class TournamentFeature : RealmObject(), NameManageable, StaticRowRepresent } } + @Ignore + override val realmObjectClass: Class = TournamentFeature::class.java + @PrimaryKey override var id = UUID.randomUUID().toString() diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentName.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentName.kt index cad45445..dadbfa2f 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentName.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentName.kt @@ -3,9 +3,11 @@ package net.pokeranalytics.android.model.realm import android.content.Context import io.realm.Realm import io.realm.RealmObject +import io.realm.annotations.Ignore import io.realm.annotations.PrimaryKey import io.realm.kotlin.where import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource @@ -28,6 +30,9 @@ open class TournamentName : RealmObject(), NameManageable, StaticRowRepresentabl } } + @Ignore + override val realmObjectClass: Class = TournamentName::class.java + @PrimaryKey override var id = UUID.randomUUID().toString() diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt index a3ef5368..bbf95d07 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt @@ -13,7 +13,6 @@ import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.interfaces.* import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.fragment.GraphFragment -import net.pokeranalytics.android.ui.graph.ObjectIdentifier import net.pokeranalytics.android.ui.view.DefaultLegendValues import net.pokeranalytics.android.ui.view.LegendContent import net.pokeranalytics.android.ui.view.RowRepresentable @@ -136,8 +135,8 @@ open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSo // GraphIdentifiableEntry - override val objectIdentifier: ObjectIdentifier - get() = ObjectIdentifier(this.id, Transaction::class.java) + @Ignore + override val realmObjectClass: Class = Transaction::class.java override fun entryTitle(context: Context): String { return DateFormat.getDateInstance(DateFormat.SHORT).format(this.date) diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt index 6c038aa3..92edb9bd 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt @@ -3,9 +3,11 @@ package net.pokeranalytics.android.model.realm import android.content.Context import io.realm.Realm import io.realm.RealmObject +import io.realm.annotations.Ignore import io.realm.annotations.PrimaryKey import net.pokeranalytics.android.R import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.Localizable @@ -52,6 +54,9 @@ open class TransactionType : RealmObject(), NameManageable, StaticRowRepresentab } + @Ignore + override val realmObjectClass: Class = TransactionType::class.java + @PrimaryKey override var id = UUID.randomUUID().toString() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt index e9a540db..5edbd95b 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt @@ -11,6 +11,7 @@ import io.realm.RealmResults import kotlinx.android.synthetic.main.activity_home.* import net.pokeranalytics.android.BuildConfig import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.realm.Currency import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.activity.components.RequestCode @@ -83,6 +84,7 @@ class HomeActivity : PokerAnalyticsActivity() { override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) + setIntent(intent) intent?.let { when (intent.action) { @@ -91,11 +93,11 @@ class HomeActivity : PokerAnalyticsActivity() { if (data != null) { this.requestImportConfirmation(data) } else { - throw IllegalStateException("URI null on import") + throw PAIllegalStateException("URI null on import") } } else -> { - Timber.d("Intent ${intent.action} unmanaged") + Timber.w("Intent ${intent.action} unmanaged") } } } @@ -114,6 +116,16 @@ class HomeActivity : PokerAnalyticsActivity() { } } + // Import + + private fun requestImportConfirmation(uri: Uri) { + + showAlertDialog(context = this, title = R.string.import_confirmation, showCancelButton = true, positiveAction = { + ImportActivity.newInstanceForResult(this, uri) + }) + + } + private fun observeRealmObjects() { val realm = getRealm() @@ -164,14 +176,4 @@ class HomeActivity : PokerAnalyticsActivity() { viewPager.setCurrentItem(index, false) } - // Import - - private fun requestImportConfirmation(uri: Uri) { - - showAlertDialog(context = this, title = R.string.import_confirmation, showCancelButton = true, positiveAction = { - ImportActivity.newInstanceForResult(this, uri) - }) - - } - } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt index fd9fef8c..44427c9d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt @@ -9,6 +9,8 @@ import io.realm.Realm import net.pokeranalytics.android.R import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.activity.components.RequestCode +import net.pokeranalytics.android.ui.activity.components.ResultCode +import net.pokeranalytics.android.ui.extensions.showAlertDialog import net.pokeranalytics.android.ui.fragment.ImportFragment import timber.log.Timber @@ -39,11 +41,15 @@ class ImportActivity : PokerAnalyticsActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.fileURI = intent.getParcelableExtra(ImportActivity.IntentKey.URI.keyName) + Timber.d("//////// data = ${intent?.data}") - setContentView(R.layout.activity_import) - initUI() + intent?.data?.let { + this.fileURI = it + } + setContentView(R.layout.activity_import) +// initUI() + requestImportConfirmation() } override fun onStop() { @@ -51,7 +57,7 @@ class ImportActivity : PokerAnalyticsActivity() { // Updates the main thread instance with newly inserted data val realm = Realm.getDefaultInstance() - realm.refresh() +// realm.refresh() realm.close() } @@ -71,16 +77,57 @@ class ImportActivity : PokerAnalyticsActivity() { } -// private fun requestPermission() { -// if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { -// ActivityCompat.requestPermissions( -// this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), PERMISSION_REQUEST_ACCESS_FINE_LOCATION -// ) +// override fun onNewIntent(intent: Intent?) { +// super.onNewIntent(intent) +// +// Timber.d("++++++ data = ${intent?.data}") +// +// setIntent(intent) +// intent?.let { +// +// when (intent.action) { +// "android.intent.action.VIEW" -> { // import +// val data = it.data +// if (data != null) { +// this.requestImportConfirmation(data) +// } else { +// throw PAIllegalStateException("URI null on import") +// } +// } +// else -> { +// Timber.w("Intent ${intent.action} unmanaged") +// } +// } // } -// } // -// override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { -// super.onRequestPermissionsResult(requestCode, permissions, grantResults) // } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + + when (requestCode) { + RequestCode.IMPORT.value -> { + if (resultCode == ResultCode.IMPORT_UNRECOGNIZED_FORMAT.value) { + showAlertDialog(context = this, message = R.string.unknown_import_format_popup_message, positiveAction = { + finish() + }) + } + } + } + } + + // Import + + private fun requestImportConfirmation() { + + showAlertDialog(context = this, title = R.string.import_confirmation, showCancelButton = true, positiveAction = { + initUI() +// newInstanceForResult(this, uri) + }, negativeAction = { + finish() + }) + + } + + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt index 9570c9cb..18b926a4 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt @@ -14,13 +14,14 @@ import com.github.mikephil.charting.listener.OnChartValueSelectedListener import kotlinx.android.synthetic.main.fragment_graph.* import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.Stat +import net.pokeranalytics.android.model.interfaces.ObjectIdentifier import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.graph.AxisFormatting import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry -import net.pokeranalytics.android.ui.graph.ObjectIdentifier import net.pokeranalytics.android.ui.graph.setStyle import net.pokeranalytics.android.ui.view.LegendView import net.pokeranalytics.android.ui.view.MultiLineLegendView +import timber.log.Timber class GraphFragment : RealmFragment(), OnChartValueSelectedListener { @@ -183,16 +184,21 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener { val identifier = entry.data as ObjectIdentifier getRealm().where(identifier.clazz).equalTo("id", identifier.id).findAll().firstOrNull() } - is GraphUnderlyingEntry -> entry.data as GraphUnderlyingEntry? + is GraphUnderlyingEntry -> entry.data else -> null } - statEntry?.let { + if (statEntry is GraphUnderlyingEntry) { + val groupName = dataSet?.label ?: "" val color = dataSet?.color - val legendValue = it.legendValues(stat, entry, this.style, groupName, requireContext()) + val legendValue = statEntry.legendValues(stat, entry, this.style, groupName, requireContext()) this.legendView.setItemData(legendValue, color) + + } else { + Timber.w("Data $statEntry should implement GraphUnderlyingEntry") } + } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt b/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt index 01d9ead9..e1b0a5a7 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt @@ -3,16 +3,12 @@ package net.pokeranalytics.android.ui.graph import android.content.Context import com.github.mikephil.charting.data.Entry import net.pokeranalytics.android.calculus.Stat -import net.pokeranalytics.android.model.interfaces.GraphIdentifiableEntry +import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.view.DefaultLegendValues import net.pokeranalytics.android.ui.view.LegendContent import net.pokeranalytics.android.util.TextFormat -class ObjectIdentifier(var id: String, var clazz: Class) { - -} - interface GraphUnderlyingEntry { fun entryTitle(context: Context): String diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/CustomizableRowRepresentable.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/CustomizableRowRepresentable.kt index 84d223f6..47255dde 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/CustomizableRowRepresentable.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/CustomizableRowRepresentable.kt @@ -2,7 +2,6 @@ package net.pokeranalytics.android.ui.view.rowrepresentable import android.content.Context import net.pokeranalytics.android.calculus.ComputedStat -import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.ui.fragment.BankrollRowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType @@ -27,7 +26,7 @@ class CustomizableRowRepresentable( var value: String? = null, var computedStat: ComputedStat? = null, var isSelectable: Boolean? = false - ) : RowRepresentable, Identifiable { + ) : RowRepresentable { override fun localizedTitle(context: Context): String { @@ -42,5 +41,5 @@ class CustomizableRowRepresentable( override val viewType: Int = customViewType?.ordinal ?: RowViewType.HEADER_TITLE.ordinal - override var id: String = "" +// override var id: String = "" } 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 847a775c..b462c377 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 @@ -3,7 +3,8 @@ package net.pokeranalytics.android.util.csv import io.realm.Realm import io.realm.kotlin.deleteFromRealm import net.pokeranalytics.android.model.interfaces.Identifiable -import net.pokeranalytics.android.model.interfaces.Identificator +import net.pokeranalytics.android.model.interfaces.ObjectIdentifier +import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.util.extensions.findById import org.apache.commons.csv.CSVRecord import timber.log.Timber @@ -25,7 +26,7 @@ abstract class DataCSVDescriptor(source: DataSource, vararg el /** * List of Realm object identificators */ - val realmModelIds = mutableListOf() + val realmModelIds = mutableListOf() abstract fun parseData(realm: Realm, record: CSVRecord): T? @@ -33,19 +34,33 @@ abstract class DataCSVDescriptor(source: DataSource, vararg el val data = this.parseData(realm, record) data?.let { - this.realmModelIds.add(it.identificator) + Timber.d(">>>>>>> identifier added: ${it.id}") + this.realmModelIds.add(it.objectIdentifier) } return if (data != null) 1 else 0 } override fun cancel(realm: Realm) { + + Timber.d(">>>>>>> Start delete of ${realmModelIds.size}") + realm.executeTransaction { - this.realmModelIds.forEach { identificator -> - realm.findById(identificator.clazz, identificator.id)?.deleteFromRealm() + this.realmModelIds.forEach { identifier -> + val data = realm.findById(identifier.clazz, identifier.id) + if (data is Session) { + data.cleanup() + } + data?.deleteFromRealm() } + this.realmModelIds.clear() } } + override fun save(realm: Realm) { + super.save(realm) + this.realmModelIds.clear() + } + } /** @@ -84,6 +99,10 @@ abstract class CSVDescriptor(var source: DataSource, vararg elements: CSVField) */ abstract fun parse(realm: Realm, record: CSVRecord): Int + open fun save(realm: Realm) { + + } + open fun cancel(realm: Realm) { } 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 17476360..24d36530 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 @@ -186,21 +186,19 @@ open class CSVImporter(istream: InputStream) { return null } -// fun save(realm: Realm) { -// -// this.usedDescriptors.forEach { descriptor -> -// -// if (descriptor is DataCSVDescriptor<*>) { -// realm.executeTransaction { -// realm.copyToRealm(descriptor.realmModels) -// } -// } -// } -// } + fun save(realm: Realm) { + this.parser.close() +// realm.refresh() + + this.currentDescriptor?.save(realm) + this.usedDescriptors.forEach { descriptor -> + descriptor.save(realm) + } + } fun cancel(realm: Realm) { this.parser.close() - realm.refresh() +// realm.refresh() this.currentDescriptor?.cancel(realm) this.usedDescriptors.forEach { descriptor -> 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 54dda264..dda5c860 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 @@ -115,8 +115,6 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean val session = Session.newInstance(realm, this.isTournament) - - var isLive = true var bankrollName: String? = null var currencyCode: String? = null @@ -209,7 +207,8 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean } if (startDate != null && endDate != null && net != null) { // valid session - if (DataUtils.sessionCount(realm, startDate, endDate, net) == 1) { // session already in realm, we'd love not put it in Realm before doing the check + // session already in realm, we'd love not put it in Realm before doing the check + if (DataUtils.sessionCount(realm, startDate, endDate, net) == 1) { return session } else { Timber.d("Session already exists") @@ -218,6 +217,7 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean Timber.d("Can't import session: sd=$startDate, ed=$endDate, net=$net") } + session.cleanup() session.deleteFromRealm() return null } From 6bcdece0571ef2a6b1595cb60ce546362c9e2dc0 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 14 Jun 2019 12:26:36 +0200 Subject: [PATCH 035/125] Fixes refresh issue --- .../android/calculus/bankroll/BankrollReportManager.kt | 1 + .../net/pokeranalytics/android/ui/activity/ImportActivity.kt | 5 ++--- .../net/pokeranalytics/android/ui/fragment/ImportFragment.kt | 1 - .../pokeranalytics/android/util/csv/SessionCSVDescriptor.kt | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt index a6fd8917..2bb69dfb 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt @@ -27,6 +27,7 @@ object BankrollReportManager { init { val realm = Realm.getDefaultInstance() + realm.isAutoRefresh = true computableResults = realm.where(ComputableResult::class.java).findAll() bankrolls = realm.where(Bankroll::class.java).findAll() transactions = realm.where(Transaction::class.java).findAll() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt index 44427c9d..215b21b1 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt @@ -5,7 +5,6 @@ import android.content.Intent import android.net.Uri import android.os.Bundle import androidx.fragment.app.FragmentActivity -import io.realm.Realm import net.pokeranalytics.android.R import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.activity.components.RequestCode @@ -56,9 +55,9 @@ class ImportActivity : PokerAnalyticsActivity() { super.onStop() // Updates the main thread instance with newly inserted data - val realm = Realm.getDefaultInstance() +// val realm = Realm.getDefaultInstance() // realm.refresh() - realm.close() +// realm.close() } private fun initUI() { 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 e8025a10..7232cc85 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 @@ -130,5 +130,4 @@ class ImportFragment : RealmFragment(), ImportDelegate { this.totalCounter.text = this.numberFormatter.format(totalCount) } - } \ 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 dda5c860..fe6e26ed 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 @@ -98,7 +98,7 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean transaction.amount = amount!! transaction.type = type - val bankroll = Bankroll.getOrCreate(realm, currencyCode!!, currencyRate = currencyRate) + val bankroll = Bankroll.getOrCreate(realm, currencyCode!!, currencyCode = currencyCode!!, currencyRate = currencyRate) transaction.bankroll = bankroll return transaction } else { From 44d48bdc1006fe044586082d243dfc481894b2ad Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 14 Jun 2019 12:34:24 +0200 Subject: [PATCH 036/125] Change use of IllegalStateException to PAIllegalStateException --- .../net/pokeranalytics/android/calculus/Calculator.kt | 5 +++-- .../java/net/pokeranalytics/android/calculus/Report.kt | 3 ++- .../main/java/net/pokeranalytics/android/calculus/Stat.kt | 3 ++- .../android/calculus/bankroll/BankrollReport.kt | 2 +- .../java/net/pokeranalytics/android/model/Criteria.kt | 3 ++- .../java/net/pokeranalytics/android/model/realm/Result.kt | 5 +++-- .../net/pokeranalytics/android/model/realm/Session.kt | 8 ++++---- .../pokeranalytics/android/model/realm/TransactionType.kt | 3 ++- .../android/model/utils/SessionSetManager.kt | 5 +++-- .../android/ui/adapter/RowRepresentableDataSource.kt | 7 ++++--- .../android/ui/fragment/DataListFragment.kt | 3 ++- .../pokeranalytics/android/ui/fragment/SessionFragment.kt | 3 ++- .../android/ui/fragment/SubscriptionFragment.kt | 3 ++- .../ui/fragment/components/DeletableItemFragment.kt | 3 ++- .../components/bottomsheet/BottomSheetFragment.kt | 3 ++- .../components/bottomsheet/BottomSheetListFragment.kt | 5 +++-- .../android/ui/fragment/report/AbstractReportFragment.kt | 3 ++- 17 files changed, 41 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt index 2f1726cb..7185f0d9 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt @@ -4,6 +4,7 @@ import android.content.Context import io.realm.Realm import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.Stat.* +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.Criteria import net.pokeranalytics.android.model.combined import net.pokeranalytics.android.model.extensions.hourlyDuration @@ -95,7 +96,7 @@ class Calculator { TABLE -> TableReportActivity::class.java PROGRESS -> ProgressReportActivity::class.java COMPARISON -> ComparisonReportActivity::class.java - else -> throw IllegalStateException("undefined activity for report display") + else -> throw PAIllegalStateException("undefined activity for report display") // MAP -> R.string.map // POLYNOMIAL -> null @@ -378,7 +379,7 @@ class Calculator { } val session = - computable.session ?: throw IllegalStateException("Computing lone ComputableResult") + computable.session ?: throw PAIllegalStateException("Computing lone ComputableResult") results.addEvolutionValue(tSum, stat = NET_RESULT, data = session) results.addEvolutionValue(tSum / index, stat = AVERAGE, data = session) results.addEvolutionValue(index.toDouble(), stat = NUMBER_OF_GAMES, data = session) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt index 63501b46..03698369 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt @@ -5,6 +5,7 @@ import com.github.mikephil.charting.data.* import io.realm.Realm import io.realm.RealmResults import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.interfaces.GraphIdentifiableEntry @@ -440,7 +441,7 @@ class ComputedResults(group: ComputableGroup, shouldManageMultiGroupProgressValu this.computedStat(stat)?.let { return it.format() } ?: run { - throw IllegalStateException("Missing stat in results") + throw PAIllegalStateException("Missing stat in results") } } diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt index ec9e50a7..ba6b27d7 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt @@ -3,6 +3,7 @@ package net.pokeranalytics.android.calculus import android.content.Context import net.pokeranalytics.android.R import net.pokeranalytics.android.exceptions.FormattingException +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.util.NULL_TEXT @@ -127,7 +128,7 @@ enum class Stat(override var uniqueIdentifier: Int) : IntIdentifiable, RowRepres MAXIMUM_DURATION -> R.string.longest_session DAYS_PLAYED -> R.string.days_played TOTAL_BUYIN -> R.string.total_buyin - else -> throw IllegalStateException("Stat ${this.name} name required but undefined") + else -> throw PAIllegalStateException("Stat ${this.name} name required but undefined") } } diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt index 69df9109..ce66fe36 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt @@ -215,7 +215,7 @@ class BankrollReportSetup(val bankrollId: String? = null, val from: Date? = null val query = Query() this.bankrollId?.let { - val bankroll = realm.findById(it) ?: throw IllegalStateException("Bankroll not found with id $it") + val bankroll = realm.findById(it) ?: throw PAIllegalStateException("Bankroll not found with id $it") val bankrollCondition = QueryCondition.AnyBankroll(bankroll) query.add(bankrollCondition) } diff --git a/app/src/main/java/net/pokeranalytics/android/model/Criteria.kt b/app/src/main/java/net/pokeranalytics/android/model/Criteria.kt index fa679d19..67e6f1da 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/Criteria.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/Criteria.kt @@ -4,6 +4,7 @@ import io.realm.Realm import io.realm.Sort import io.realm.kotlin.where import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PokerAnalyticsException import net.pokeranalytics.android.model.Criteria.Bankrolls.comparison import net.pokeranalytics.android.model.Criteria.Blinds.comparison @@ -329,7 +330,7 @@ interface CustomFieldCriteria { var customFieldId: String fun customField(realm: Realm) : CustomField { - return realm.findById(this.customFieldId) ?: throw IllegalStateException("Custom field not found") + return realm.findById(this.customFieldId) ?: throw PAIllegalStateException("Custom field not found") } fun customFieldType(realm: Realm): Int { 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 644d0de3..19394fcd 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 @@ -6,6 +6,7 @@ import io.realm.RealmResults import io.realm.annotations.Ignore import io.realm.annotations.LinkingObjects import io.realm.annotations.RealmClass +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.QueryCondition @@ -52,10 +53,10 @@ open class Result : RealmObject(), Filterable { this.session?.bankroll?.let { bankroll -> if (bankroll.live) { - throw IllegalStateException("Can't set net result on a live bankroll") + throw PAIllegalStateException("Can't set net result on a live bankroll") } } ?: run { - throw IllegalStateException("Session doesn't have any bankroll") + throw PAIllegalStateException("Session doesn't have any bankroll") } field = value 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 99e5ed52..af897af9 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 @@ -500,12 +500,12 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat if (pauseDate != null) { this.breakDuration += Date().time - pauseDate.time } else { - throw IllegalStateException("When resuming, the pause date must be set") + throw PAIllegalStateException("When resuming, the pause date must be set") } this.pauseDate = null } else -> { - throw IllegalStateException("unmanaged session state") + throw PAIllegalStateException("unmanaged session state") } } } @@ -526,7 +526,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat SessionState.STARTED -> { this.pauseDate = Date() } - else -> throw IllegalStateException("Pausing a session in an unmanaged state") + else -> throw PAIllegalStateException("Pausing a session in an unmanaged state") } } } @@ -1100,7 +1100,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat } } ?: run { - throw java.lang.IllegalStateException("Asking for statIds on Session without Result") + throw PAIllegalStateException("Asking for statIds on Session without Result") } } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt index 92edb9bd..b6c7d4e3 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt @@ -6,6 +6,7 @@ import io.realm.RealmObject import io.realm.annotations.Ignore import io.realm.annotations.PrimaryKey import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable @@ -49,7 +50,7 @@ open class TransactionType : RealmObject(), NameManageable, StaticRowRepresentab type?.let { return it } - throw IllegalStateException("Transaction type ${value.name} should exist in database!") + throw PAIllegalStateException("Transaction type ${value.name} should exist in database!") } } diff --git a/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt b/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt index 76cce72c..8efe64ff 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt @@ -3,6 +3,7 @@ package net.pokeranalytics.android.model.utils import io.realm.RealmQuery import io.realm.RealmResults import net.pokeranalytics.android.exceptions.ModelException +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.SessionSet import kotlin.math.max @@ -23,7 +24,7 @@ class SessionSetManager { fun updateTimeline(session: Session) { if (!session.realm.isInTransaction) { - throw IllegalStateException("realm should be in transaction at this point") + throw PAIllegalStateException("realm should be in transaction at this point") } if (session.startDate == null) { @@ -154,7 +155,7 @@ class SessionSetManager { fun removeFromTimeline(session: Session) { if (!session.realm.isInTransaction) { - throw IllegalStateException("realm should be in transaction at this point") + throw PAIllegalStateException("realm should be in transaction at this point") } val sessionSet = session.sessionSet diff --git a/app/src/main/java/net/pokeranalytics/android/ui/adapter/RowRepresentableDataSource.kt b/app/src/main/java/net/pokeranalytics/android/ui/adapter/RowRepresentableDataSource.kt index 26dec55a..51021a62 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/adapter/RowRepresentableDataSource.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/adapter/RowRepresentableDataSource.kt @@ -1,6 +1,7 @@ package net.pokeranalytics.android.ui.adapter import android.content.Context +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.util.TextFormat @@ -42,21 +43,21 @@ interface StaticRowRepresentableDataSource: RowRepresentableDataSource { this.adapterRows()?.let { return it[position] } - throw IllegalStateException("Need to implement Data Source") + throw PAIllegalStateException("Need to implement Data Source") } override fun numberOfRows(): Int { this.adapterRows()?.let { return it.size } - throw IllegalStateException("Need to implement Data Source") + throw PAIllegalStateException("Need to implement Data Source") } override fun viewTypeForPosition(position:Int): Int { this.rowRepresentableForPosition(position)?.let { return it.viewType } - throw IllegalStateException("Need to implement Data Source") + throw PAIllegalStateException("Need to implement Data Source") } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt index 67186d9d..13c4a9fc 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt @@ -13,6 +13,7 @@ import io.realm.Realm import io.realm.RealmResults import kotlinx.android.synthetic.main.fragment_data_list.* import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.interfaces.Deletable import net.pokeranalytics.android.model.interfaces.Identifiable @@ -86,7 +87,7 @@ open class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataS val itemId = item.id deleteItem(dataListAdapter, items, itemId) } else { - throw IllegalStateException("Item with position $position not found") + throw PAIllegalStateException("Item with position $position not found") } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt index 0f1a2da3..335aa4f4 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt @@ -11,6 +11,7 @@ import androidx.recyclerview.widget.DiffUtil import kotlinx.android.synthetic.main.fragment_session.* import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.extensions.SessionState import net.pokeranalytics.android.model.extensions.getState @@ -173,7 +174,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate { sessionHasBeenCustomized = true try { currentSession.updateValue(value, row) - } catch (e: IllegalStateException) { + } catch (e: PAIllegalStateException) { Toast.makeText(context, e.message, Toast.LENGTH_LONG).show() return } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt index 3f26b19d..a5b20860 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt @@ -24,6 +24,7 @@ import com.android.billingclient.api.SkuDetails import com.android.billingclient.api.SkuDetailsResponseListener import kotlinx.android.synthetic.main.fragment_subscription.* import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.fragment.components.ScreenSlidePageFragment @@ -101,7 +102,7 @@ class SubscriptionFragment : PokerAnalyticsFragment(), SkuDetailsResponseListene this.selectedProduct?.let { AppGuard.initiatePurchase(this.requireActivity(), it, this) } ?: run { - throw IllegalStateException("Attempt to initiate purchase while no product has been chosen") + throw PAIllegalStateException("Attempt to initiate purchase while no product has been chosen") } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt index 07595c6d..9136dac1 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt @@ -13,6 +13,7 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.interfaces.Deletable import net.pokeranalytics.android.ui.activity.DataListActivity import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter @@ -126,7 +127,7 @@ abstract class DeletableItemFragment : RealmFragment() { } snackBar?.show() } ?: run { - throw IllegalStateException("mainLayout is not defined") + throw PAIllegalStateException("mainLayout is not defined") } } 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 8657df58..0d437430 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 @@ -15,6 +15,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment import io.realm.RealmModel import kotlinx.android.synthetic.main.fragment_bottom_sheet.* import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.ui.activity.EditableDataActivity import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity @@ -132,7 +133,7 @@ open class BottomSheetFragment : BottomSheetDialogFragment() { SessionRow.TOURNAMENT_NAME -> LiveData.TOURNAMENT_NAME SessionRow.TOURNAMENT_FEATURE -> LiveData.TOURNAMENT_FEATURE TransactionRow.TYPE -> LiveData.TRANSACTION_TYPE - else -> throw IllegalStateException("row $row does not have an associated LiveData value") + else -> throw PAIllegalStateException("row $row does not have an associated LiveData value") } EditableDataActivity.newInstanceForResult( 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 eeece10e..fa5997f7 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 @@ -8,6 +8,7 @@ import io.realm.RealmResults import kotlinx.android.synthetic.main.bottom_sheet_list.* import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.* import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter @@ -39,14 +40,14 @@ open class BottomSheetListFragment : BottomSheetFragment(), LiveRowRepresentable realmData?.let { return it[position] as RowRepresentable } - throw IllegalStateException("Need to implement Data Source") + throw PAIllegalStateException("Need to implement Data Source") } override fun numberOfRows(): Int { realmData?.let { return it.size } - throw IllegalStateException("Need to implement Data Source") + throw PAIllegalStateException("Need to implement Data Source") } override fun viewTypeForPosition(position: Int): Int { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt index 3addaa19..fa900fa2 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt @@ -9,6 +9,7 @@ import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat import kotlinx.android.synthetic.main.fragment_progress_report.* import net.pokeranalytics.android.calculus.Report +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.CustomFieldCriteria import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.realm.ReportSetup @@ -91,7 +92,7 @@ abstract class AbstractReportFragment : DataManagerFragment() { dialog.show() - } ?: throw IllegalStateException("Activity cannot be null") + } ?: throw PAIllegalStateException("Activity cannot be null") } From 84ab42c35ca0d9c0a65035a7e410f3b932309db8 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 14 Jun 2019 17:21:30 +0200 Subject: [PATCH 037/125] Updating import for PBT --- .../android/model/realm/Session.kt | 8 +- .../android/util/csv/CSVDescriptor.kt | 4 +- .../android/util/csv/CSVField.kt | 14 +++- .../android/util/csv/SessionCSVDescriptor.kt | 84 ++++++++++++------- .../android/util/csv/SessionField.kt | 8 ++ 5 files changed, 82 insertions(+), 36 deletions(-) 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 af897af9..293c8fc7 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 @@ -68,7 +68,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat companion object { - fun newInstance(realm: Realm, isTournament: Boolean, bankroll: Bankroll? = null): Session { + fun newInstance(realm: Realm, isTournament: Boolean, bankroll: Bankroll? = null, managed: Boolean = false): Session { val session = Session() session.result = Result() if (bankroll != null) { @@ -78,7 +78,11 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat } session.type = if (isTournament) Session.Type.TOURNAMENT.ordinal else Session.Type.CASH_GAME.ordinal - return realm.copyToRealm(session) + return if (managed) { + realm.copyToRealm(session) + } else { + session + } } fun fieldNameForQueryType(queryCondition: Class < out QueryCondition >): String? { 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 b462c377..36df0fac 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 @@ -34,7 +34,7 @@ abstract class DataCSVDescriptor(source: DataSource, vararg el val data = this.parseData(realm, record) data?.let { - Timber.d(">>>>>>> identifier added: ${it.id}") +// Timber.d(">>>>>>> identifier added: ${it.id}") this.realmModelIds.add(it.objectIdentifier) } return if (data != null) 1 else 0 @@ -42,7 +42,7 @@ abstract class DataCSVDescriptor(source: DataSource, vararg el override fun cancel(realm: Realm) { - Timber.d(">>>>>>> Start delete of ${realmModelIds.size}") +// Timber.d(">>>>>>> Start delete of ${realmModelIds.size}") realm.executeTransaction { this.realmModelIds.forEach { identifier -> diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/CSVField.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/CSVField.kt index 3e7e6659..1202443a 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/CSVField.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/CSVField.kt @@ -31,6 +31,18 @@ interface NumberCSVField: TypedCSVField { } } +interface DataCSVField : TypedCSVField { + + override fun parse(value: String): T? { + + this.callback?.let { + return it(value) + } + return null + } + +} + interface DateCSVField : TypedCSVField { val dateFormat: String? @@ -58,8 +70,8 @@ interface BlindCSVField : TypedCSVField> { val strBlinds = value.split("/") if (strBlinds.size == 2) { - val bb = strBlinds.last().toDouble() val sb = strBlinds.first().toDouble() + val bb = strBlinds.last().toDouble() return Pair(sb, bb) } else { Timber.d("Blinds could not be parsed: $value") 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 fe6e26ed..3fc15506 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 @@ -63,11 +63,14 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean private fun parseTransaction(realm: Realm, record: CSVRecord): Transaction? { var date: Date? = null - var amount: Double? = null var type: TransactionType? = null var currencyCode: String? = null var currencyRate: Double? = null + // Poker Bankroll Tracker specifics + var buyin: Double? = null + var cashedOut: Double? = null + fields.forEach { field -> val index = this.fieldMapping[field] @@ -77,10 +80,8 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean is SessionField.Start -> { date = field.parse(value) } - is SessionField.Buyin -> amount = field.parse(value) - is SessionField.SessionType -> { - type = realm.getOrCreate(value) - } + is SessionField.Buyin -> buyin = field.parse(value) + is SessionField.CashedOut -> cashedOut = field.parse(value) is SessionField.CurrencyCode -> currencyCode = value is SessionField.CurrencyRate -> currencyRate = field.parse(value) else -> { @@ -89,13 +90,23 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean } } + val amount = if (buyin != null && buyin!! > 0) { + type = TransactionType.getByValue(TransactionType.Value.DEPOSIT, realm) + buyin + } else if (cashedOut != null && cashedOut!! > 0) { + type = TransactionType.getByValue(TransactionType.Value.WITHDRAWAL, realm) + cashedOut!! * -1 + } else { + null + } + if (date != null && amount != null && type != null && currencyCode != null) { - if (DataUtils.transactionUnicityCheck(realm, date!!, amount!!, type!!)) { + if (DataUtils.transactionUnicityCheck(realm, date!!, amount, type)) { val transaction = realm.copyToRealm(Transaction()) transaction.date = date!! - transaction.amount = amount!! + transaction.amount = amount transaction.type = type val bankroll = Bankroll.getOrCreate(realm, currencyCode!!, currencyCode = currencyCode!!, currencyRate = currencyRate) @@ -113,7 +124,10 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean private fun parseSession(realm: Realm, record: CSVRecord): Session? { - val session = Session.newInstance(realm, this.isTournament) + val session = Session.newInstance(realm, this.isTournament, managed = false) + + var startDate: Date? = null + var endDate: Date? = null var isLive = true var bankrollName: String? = null @@ -128,19 +142,30 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean val value = record.get(index) when (field) { is SessionField.Start -> { - session.startDate = field.parse(value) + startDate = field.parse(value) } is SessionField.End -> { - session.endDate = field.parse(value) + endDate = field.parse(value) } is SessionField.StartTime -> { - session.startDate?.setHourMinutes(value) + startDate?.setHourMinutes(value) } is SessionField.EndTime -> { - session.endDate?.setHourMinutes(value) + endDate?.setHourMinutes(value) + } + is SessionField.Buyin -> { + val buyin = field.parse(value) + session.result?.buyin = buyin + if (session.type == Session.Type.TOURNAMENT.ordinal) { + session.tournamentEntryFee = buyin + } else {} } - is SessionField.Buyin -> session.result?.buyin = field.parse(value) is SessionField.CashedOut -> session.result?.cashout = field.parse(value) + is SessionField.SessionType -> { + Session.Type.getValueFromString(value)?.let { type -> + session.type = type.ordinal + } + } is SessionField.Addon -> additionalBuyins += field.parse(value) ?: 0.0 is SessionField.Rebuy -> additionalBuyins += field.parse(value) ?: 0.0 is SessionField.Tips -> session.result?.tips = field.parse(value) @@ -152,14 +177,12 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean is SessionField.Game -> { if (value.isNotEmpty()) { session.game = realm.getOrCreate(value) - } else { - } + } else { } } is SessionField.Location -> { if (value.isNotEmpty()) { session.location = realm.getOrCreate(value) - } else { - } + } else { } } is SessionField.Bankroll -> bankrollName = value is SessionField.LimitType -> session.limit = Limit.getInstance(value)?.ordinal @@ -172,14 +195,13 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean is SessionField.SmallBlind -> session.cgSmallBlind = field.parse(value) is SessionField.BigBlind -> session.cgBigBlind = field.parse(value) is SessionField.TableSize -> session.tableSize = TableSize.valueForLabel(value) - is SessionField.SessionType -> { - Session.Type.getValueFromString(value)?.let { type -> - session.type = type.ordinal - } - } is SessionField.TournamentPosition -> session.result?.tournamentFinalPosition = field.parse(value)?.toInt() - is SessionField.TournamentName -> session.tournamentName = realm.getOrCreate(value) + is SessionField.TournamentName -> { + if (value.isNotEmpty()) { + session.tournamentName = realm.getOrCreate(value) + } else { } + } is SessionField.TournamentType -> session.tournamentType = TournamentType.getValueForLabel(value)?.ordinal is SessionField.TournamentNumberOfPlayers -> session.tournamentNumberOfPlayers = @@ -199,26 +221,26 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean session.bankroll = Bankroll.getOrCreate(realm, bankrollName ?: "Import", isLive, currencyCode, currencyRate) - val startDate = session.startDate - val endDate = session.endDate - val net = session.result?.net session.result?.buyin?.let { session.result?.buyin = it + additionalBuyins } + val net = session.result?.net if (startDate != null && endDate != null && net != null) { // valid session // session already in realm, we'd love not put it in Realm before doing the check - if (DataUtils.sessionCount(realm, startDate, endDate, net) == 1) { - return session + val count = DataUtils.sessionCount(realm, startDate!!, endDate!!, net) + if (count == 0) { + val managedSession = realm.copyToRealm(session) + managedSession.startDate = startDate + managedSession.endDate = endDate + return managedSession } else { - Timber.d("Session already exists") + Timber.d("Session already exists(count=$count): sd=$startDate, ed=$endDate, net=$net") } } else { Timber.d("Can't import session: sd=$startDate, ed=$endDate, net=$net") } - session.cleanup() - session.deleteFromRealm() return null } diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt index 6f0876af..1550d399 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt @@ -2,6 +2,14 @@ package net.pokeranalytics.android.util.csv import java.util.* +sealed class TransactionField { + + data class TransactionType( + override var header: String, + override var callback: ((String) -> net.pokeranalytics.android.model.realm.TransactionType?)? = null + ) : DataCSVField + +} /** * The enumeration of Session fields From fe4129cc1af10d0a03ab4d35b1add9dfef71c46b Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 17 Jun 2019 10:47:47 +0200 Subject: [PATCH 038/125] Fixing PBT import --- .../android/util/csv/SessionCSVDescriptor.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 3fc15506..5888d53a 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 @@ -91,11 +91,11 @@ class SessionCSVDescriptor(source: DataSource, private var isTournament: Boolean } val amount = if (buyin != null && buyin!! > 0) { - type = TransactionType.getByValue(TransactionType.Value.DEPOSIT, realm) - buyin - } else if (cashedOut != null && cashedOut!! > 0) { type = TransactionType.getByValue(TransactionType.Value.WITHDRAWAL, realm) - cashedOut!! * -1 + buyin!! * -1 + } else if (cashedOut != null && cashedOut!! > 0) { + type = TransactionType.getByValue(TransactionType.Value.DEPOSIT, realm) + cashedOut } else { null } From 58ac1f336712dde819cddfea501a56e60032fa7e Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 17 Jun 2019 10:54:40 +0200 Subject: [PATCH 039/125] Fixing crash due to missing failed save message for transaction types --- .../android/model/realm/TransactionType.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt index b6c7d4e3..cc00a931 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt @@ -10,6 +10,7 @@ import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable +import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.Localizable import net.pokeranalytics.android.ui.view.RowRepresentable @@ -120,5 +121,13 @@ open class TransactionType : RealmObject(), NameManageable, StaticRowRepresentab return R.string.transaction_relationship_error } + override fun getFailedSaveMessage(status: SaveValidityStatus): Int { + return when (status) { + SaveValidityStatus.DATA_INVALID -> R.string.operation_type_empty_field_error + SaveValidityStatus.ALREADY_EXISTS -> R.string.duplicate_operation_type_error + else -> super.getFailedSaveMessage(status) + } + } + } From 59e33ada31cdd43f35e446f355aa1330bdf97e11 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 17 Jun 2019 11:34:29 +0200 Subject: [PATCH 040/125] Cleanup + test session before import --- .../android/ui/activity/ImportActivity.kt | 28 +++++++------ .../android/ui/fragment/FeedFragment.kt | 42 +++++++++---------- .../ui/view/rowrepresentable/SettingRow.kt | 5 +-- .../util/extensions/RealmExtensions.kt | 10 ++++- 4 files changed, 45 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt index 215b21b1..37e09ce2 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt @@ -4,13 +4,18 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle +import android.widget.Toast import androidx.fragment.app.FragmentActivity +import io.realm.Realm import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.activity.components.RequestCode import net.pokeranalytics.android.ui.activity.components.ResultCode import net.pokeranalytics.android.ui.extensions.showAlertDialog import net.pokeranalytics.android.ui.fragment.ImportFragment +import net.pokeranalytics.android.util.billing.AppGuard +import net.pokeranalytics.android.util.extensions.count import timber.log.Timber class ImportActivity : PokerAnalyticsActivity() { @@ -40,26 +45,14 @@ class ImportActivity : PokerAnalyticsActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - Timber.d("//////// data = ${intent?.data}") - intent?.data?.let { this.fileURI = it } setContentView(R.layout.activity_import) -// initUI() requestImportConfirmation() } - override fun onStop() { - super.onStop() - - // Updates the main thread instance with newly inserted data -// val realm = Realm.getDefaultInstance() -// realm.refresh() -// realm.close() - } - private fun initUI() { val fragmentTransaction = supportFragmentManager.beginTransaction() @@ -119,9 +112,18 @@ class ImportActivity : PokerAnalyticsActivity() { private fun requestImportConfirmation() { + val realm = Realm.getDefaultInstance() + val sessionCount = realm.count(Session::class.java) + realm.close() + + if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG + Toast.makeText(this, "Please subscribe!", Toast.LENGTH_LONG).show() + BillingActivity.newInstance(this) + return + } + showAlertDialog(context = this, title = R.string.import_confirmation, showCancelButton = true, positiveAction = { initUI() -// newInstanceForResult(this, uri) }, negativeAction = { finish() }) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt index cd33cc31..9bae8a99 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt @@ -34,8 +34,6 @@ import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.billing.AppGuard -import java.text.SimpleDateFormat -import java.util.* class FeedFragment : FilterableFragment(), RowRepresentableDelegate { @@ -62,7 +60,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { private lateinit var feedTransactionAdapter: FeedTransactionRowRepresentableAdapter private lateinit var realmSessions: RealmResults private lateinit var realmTransactions: RealmResults - private lateinit var betaLimitDate: Date +// private lateinit var betaLimitDate: Date private var newSessionCreated: Boolean = false private var adapterHasBeenSet: Boolean = false @@ -208,8 +206,8 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { */ private fun initData() { - val sdf = SimpleDateFormat("dd/M/yyyy hh:mm", Locale.getDefault()) - betaLimitDate = sdf.parse("17/7/2019 10:00") +// val sdf = SimpleDateFormat("dd/M/yyyy hh:mm", Locale.getDefault()) +// betaLimitDate = sdf.parse("17/7/2019 10:00") this.currentFilterable = FilterableType.SESSION val viewManager = SmoothScrollLinearLayoutManager(requireContext()) @@ -282,10 +280,11 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { return } - if (Date().after(betaLimitDate)) { - this.showEndOfBetaMessage() - return - } + // Keep commented code for special versions +// if (Date().after(betaLimitDate)) { +// this.showEndOfBetaMessage() +// return +// } SessionActivity.newInstanceforResult(this, isTournament, requestCode = RequestCode.NEW_SESSION.value) newSessionCreated = true @@ -296,13 +295,12 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { */ private fun createNewTransaction() { - if (Date().after(betaLimitDate)) { - this.showEndOfBetaMessage() - return - } +// if (Date().after(betaLimitDate)) { +// this.showEndOfBetaMessage() +// return +// } EditableDataActivity.newInstanceForResult(this, LiveData.TRANSACTION, null, RequestCode.NEW_TRANSACTION.value) -// EditableDataActivity.newInstance(requireContext(), LiveData.TRANSACTION.ordinal) } /** @@ -317,15 +315,15 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { /** * Show end of beta message + * Keep for possible future uses */ - private fun showEndOfBetaMessage() { - Toast.makeText( - context, - "Beta has ended. Thanks a lot for your participation! Please update with the Google Play version to continue using the app", - Toast.LENGTH_LONG - ).show() - } - +// private fun showEndOfBetaMessage() { +// Toast.makeText( +// context, +// "App version has ended. Thanks a lot for using it! Please update with the Google Play version to continue using the app.", +// Toast.LENGTH_LONG +// ).show() +// } // Filter Handler diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt index adda5f89..7de89ea5 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt @@ -37,7 +37,6 @@ enum class SettingRow : RowRepresentable { TERMS_OF_USE, GDPR; - companion object { /** * Return the rows to display for the current session state @@ -46,8 +45,8 @@ enum class SettingRow : RowRepresentable { val rows = ArrayList() rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.information)) - rows.addAll(arrayListOf(VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) -// rows.addAll(arrayListOf(SUBSCRIPTION, VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) +// rows.addAll(arrayListOf(VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) + rows.addAll(arrayListOf(SUBSCRIPTION, VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.follow_us)) rows.addAll(arrayListOf(FOLLOW_US)) diff --git a/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt b/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt index aa15c8e6..817a9a43 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt @@ -1,12 +1,18 @@ package net.pokeranalytics.android.util.extensions -import io.realm.* +import io.realm.Realm +import io.realm.RealmModel +import io.realm.RealmResults +import io.realm.Sort import io.realm.kotlin.where import net.pokeranalytics.android.model.interfaces.CountableUsage import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.realm.* -import net.pokeranalytics.android.ui.interfaces.FilterableType + +fun Realm.count(clazz: Class) : Int { + return this.where(clazz).findAll().size +} fun Realm.findById(clazz: Class, id: String) : T? { return this.where(clazz).equalTo("id", id).findFirst() From 2a2198b52de74d0a12310064b997f2e67337f24e Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 17 Jun 2019 11:58:46 +0200 Subject: [PATCH 041/125] fix lag when opening currencies fragment --- .../android/ui/fragment/CurrenciesFragment.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt index 2fa0c3a7..9e2c6eef 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt @@ -44,15 +44,19 @@ class CurrenciesFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataS ) } + private val availableCurrencyLocales = Locale.getAvailableLocales().mapNotNull { + try { + Currency.getInstance(it) + } catch (e: Exception) { + null + } + } + private val availableCurrencies = this.systemCurrencies.filter { !mostUsedCurrencyCodes.contains(it.currencyCode) }.filter { - Locale.getAvailableLocales().filter { locale -> - try { - Currency.getInstance(locale).currencyCode == it.currencyCode - } catch (e: Exception) { - false - } + availableCurrencyLocales.filter { currencyLocale -> + currencyLocale.currencyCode == it.currencyCode }.isNotEmpty() }.sortedBy { it.displayName From ac8c0fdd549e7da43ff53410bc3665b737479cfd Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 17 Jun 2019 12:03:56 +0200 Subject: [PATCH 042/125] Fixing crash when adding a session --- .../android/model/realm/Session.kt | 2 +- .../model/utils/FavoriteSessionFinder.kt | 22 +++++++-------- .../android/ui/fragment/FeedFragment.kt | 3 +- .../android/util/csv/CSVDescriptor.kt | 28 ++++++++++++------- 4 files changed, 31 insertions(+), 24 deletions(-) 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 293c8fc7..9418a980 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 @@ -68,7 +68,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat companion object { - fun newInstance(realm: Realm, isTournament: Boolean, bankroll: Bankroll? = null, managed: Boolean = false): Session { + fun newInstance(realm: Realm, isTournament: Boolean, bankroll: Bankroll? = null, managed: Boolean = true): Session { val session = Session() session.result = Result() if (bankroll != null) { 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 57a8e17b..b33cae35 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 @@ -71,27 +71,27 @@ class FavoriteSessionFinder { private const val FAVORITE_SIGNIFICANT_SESSIONS = 15L /** - * Copies the favorite session parameters on the [newSession] + * Copies the favorite session parameters on the [session] */ - fun copyParametersFromFavoriteSession(newSession: Session, location: Location?, context: Context) { + fun copyParametersFromFavoriteSession(session: Session, location: Location?, context: Context) { val favoriteSession = - favoriteSession(newSession.type, location, newSession.realm, context) + favoriteSession(session.type, location, session.realm, context) favoriteSession?.let { fav -> - newSession.limit = fav.limit - newSession.game = fav.game - newSession.bankroll = fav.bankroll - newSession.tableSize = fav.tableSize + session.limit = fav.limit + session.game = fav.game + session.bankroll = fav.bankroll + session.tableSize = fav.tableSize - when (newSession.type) { + when (session.type) { Session.Type.CASH_GAME.ordinal -> { - newSession.cgSmallBlind = fav.cgSmallBlind - newSession.cgBigBlind = fav.cgBigBlind + session.cgSmallBlind = fav.cgSmallBlind + session.cgBigBlind = fav.cgBigBlind } Session.Type.TOURNAMENT.ordinal -> { - newSession.tournamentEntryFee = fav.tournamentEntryFee + session.tournamentEntryFee = fav.tournamentEntryFee } } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt index 9bae8a99..1dc63371 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt @@ -6,7 +6,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.Toast import androidx.core.app.ActivityOptionsCompat import androidx.core.view.isVisible import androidx.interpolator.view.animation.FastOutSlowInInterpolator @@ -275,7 +274,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { val sessionCount = this.feedSessionAdapter.realmResults.size if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG - Toast.makeText(context, "Please subscribe!", Toast.LENGTH_LONG).show() +// Toast.makeText(context, "Please subscribe!", Toast.LENGTH_LONG).show() BillingActivity.newInstance(requireContext()) return } 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 36df0fac..5813452f 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 @@ -42,18 +42,26 @@ abstract class DataCSVDescriptor(source: DataSource, vararg el override fun cancel(realm: Realm) { -// Timber.d(">>>>>>> Start delete of ${realmModelIds.size}") - - realm.executeTransaction { - this.realmModelIds.forEach { identifier -> - val data = realm.findById(identifier.clazz, identifier.id) - if (data is Session) { - data.cleanup() - } - data?.deleteFromRealm() + if (realm.isInTransaction) { + this.deleteInsertedFromRealm(realm) + } else { + realm.executeTransaction { + this.deleteInsertedFromRealm(realm) } - this.realmModelIds.clear() } + + } + + private fun deleteInsertedFromRealm(realm: Realm) { + this.realmModelIds.forEach { identifier -> + val data = realm.findById(identifier.clazz, identifier.id) + if (data is Session) { + data.cleanup() + } + data?.deleteFromRealm() + } + this.realmModelIds.clear() + } override fun save(realm: Realm) { From 5af75efe9e9331dede0f8eb934a35548479d970f Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 17 Jun 2019 12:40:17 +0200 Subject: [PATCH 043/125] Subscription refresh + refactoring --- .../android/ui/activity/BillingActivity.kt | 22 ++++++------ .../android/ui/activity/ImportActivity.kt | 2 +- .../android/ui/activity/components/Codes.kt | 4 ++- .../android/ui/fragment/FeedFragment.kt | 2 +- .../android/ui/fragment/SettingsFragment.kt | 36 +++++++++++-------- 5 files changed, 39 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/BillingActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/BillingActivity.kt index 71aafcd9..c60cfd9c 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/BillingActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/BillingActivity.kt @@ -1,18 +1,25 @@ package net.pokeranalytics.android.ui.activity -import android.content.Context +import android.app.Activity import android.content.Intent import android.os.Bundle +import androidx.fragment.app.Fragment import net.pokeranalytics.android.R import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity -import net.pokeranalytics.android.util.billing.AppGuard +import net.pokeranalytics.android.ui.activity.components.RequestCode class BillingActivity : PokerAnalyticsActivity() { companion object { - fun newInstance(context: Context) { - val intent = Intent(context, BillingActivity::class.java) - context.startActivity(intent) + + fun newInstanceForResult(activity: Activity) { + val intent = Intent(activity, BillingActivity::class.java) + activity.startActivityForResult(intent, RequestCode.SUBSCRIPTION.value) + } + + fun newInstanceForResult(fragment: Fragment) { + val intent = Intent(fragment.requireContext(), BillingActivity::class.java) + fragment.startActivityForResult(intent, RequestCode.SUBSCRIPTION.value) } } @@ -21,11 +28,6 @@ class BillingActivity : PokerAnalyticsActivity() { setContentView(R.layout.activity_billing) } - override fun onResume() { - super.onResume() - - } - } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt index 37e09ce2..498a5f86 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt @@ -118,7 +118,7 @@ class ImportActivity : PokerAnalyticsActivity() { if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG Toast.makeText(this, "Please subscribe!", Toast.LENGTH_LONG).show() - BillingActivity.newInstance(this) + BillingActivity.newInstanceForResult(this) return } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt index c8ada486..db99aed0 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/components/Codes.kt @@ -8,7 +8,9 @@ enum class RequestCode(var value: Int) { NEW_SESSION(800), NEW_TRANSACTION(801), NEW_REPORT(802), - IMPORT(900) + IMPORT(900), + SUBSCRIPTION(901), + CURRENCY(902) } enum class ResultCode(var value: Int) { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt index 1dc63371..82db898e 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt @@ -275,7 +275,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { val sessionCount = this.feedSessionAdapter.realmResults.size if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG // Toast.makeText(context, "Please subscribe!", Toast.LENGTH_LONG).show() - BillingActivity.newInstance(requireContext()) + BillingActivity.newInstanceForResult(this) return } 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 125fac2a..364a50fc 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 @@ -18,6 +18,7 @@ import net.pokeranalytics.android.ui.activity.BillingActivity import net.pokeranalytics.android.ui.activity.CurrenciesActivity import net.pokeranalytics.android.ui.activity.DataListActivity import net.pokeranalytics.android.ui.activity.GDPRActivity +import net.pokeranalytics.android.ui.activity.components.RequestCode import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource @@ -57,7 +58,6 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta rows } - const val REQUEST_CODE_CURRENCY: Int = 100 } private lateinit var settingsAdapterRow: RowRepresentableAdapter @@ -73,17 +73,25 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (requestCode == REQUEST_CODE_CURRENCY && resultCode == Activity.RESULT_OK) { - data?.let { - Preferences.setCurrencyCode(data.getStringExtra(CurrenciesFragment.INTENT_CURRENCY_CODE), requireContext()) - val realm = Realm.getDefaultInstance() - realm.executeTransaction { - it.where(Session::class.java).isNull("bankroll.currency.code").findAll().forEach { - it.bankrollHasBeenUpdated() - } - } - realm.close() - settingsAdapterRow.refreshRow(SettingRow.CURRENCY) + + when (requestCode) { + RequestCode.CURRENCY.value -> { + if (resultCode == Activity.RESULT_OK) { + data?.let { + Preferences.setCurrencyCode(data.getStringExtra(CurrenciesFragment.INTENT_CURRENCY_CODE), requireContext()) + val realm = Realm.getDefaultInstance() + realm.executeTransaction { + realm.where(Session::class.java).isNull("bankroll.currency.code").findAll().forEach { session -> + session.bankrollHasBeenUpdated() + } + } + realm.close() + settingsAdapterRow.refreshRow(SettingRow.CURRENCY) + } + } + } + RequestCode.SUBSCRIPTION.value -> { + settingsAdapterRow.refreshRow(SettingRow.SUBSCRIPTION) } } } @@ -105,7 +113,7 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta when (row) { SettingRow.SUBSCRIPTION -> { if (!AppGuard.isProUser) { - BillingActivity.newInstance(requireContext()) + BillingActivity.newInstanceForResult(this) } else { this.openPlaystoreAccount() } @@ -113,7 +121,7 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta SettingRow.RATE_APP -> parentActivity?.openPlayStorePage() SettingRow.CONTACT_US -> parentActivity?.openContactMail(R.string.contact) SettingRow.BUG_REPORT -> parentActivity?.openContactMail(R.string.bug_report_subject, Realm.getDefaultInstance().path) - SettingRow.CURRENCY -> CurrenciesActivity.newInstanceForResult(this@SettingsFragment, REQUEST_CODE_CURRENCY) + SettingRow.CURRENCY -> CurrenciesActivity.newInstanceForResult(this@SettingsFragment, RequestCode.CURRENCY.value) SettingRow.FOLLOW_US -> { when (position) { 0 -> parentActivity?.openUrl(URL.BLOG.value) From d65a76964f447b223b463ba920e659696b1f4b2a Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 17 Jun 2019 12:11:59 +0200 Subject: [PATCH 044/125] wip fix blinds --- .../java/net/pokeranalytics/android/model/realm/Session.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 9418a980..447cd62a 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 @@ -619,7 +619,8 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat if (cgBigBlind == null) return cgBigBlind?.let { bb -> val sb = cgSmallBlind ?: bb / 2.0 - blinds = "${currency.symbol} ${sb.formatted()}/${bb.round()}" + val preFormattedBlinds = "${sb.formatted()}/${bb.round()}" + blinds = bb.toCurrency(currency).replace(Regex.fromLiteral("-?\\d+(\\.\\d+)?"), preFormattedBlinds) } } From c731efd2095d08a54d9aff59b1e3e48b391dfec0 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 17 Jun 2019 13:05:00 +0200 Subject: [PATCH 045/125] fix blinds formatting --- .../android/model/migrations/Patcher.kt | 14 ++++++++++++ .../android/model/realm/Session.kt | 7 +++++- .../android/ui/fragment/CurrenciesFragment.kt | 13 +++-------- .../android/util/Preferences.kt | 22 ++++++++++++------- .../util/extensions/CurrencyExtensions.kt | 11 ++++++++++ .../util/extensions/NumbersExtension.kt | 4 +++- 6 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/net/pokeranalytics/android/util/extensions/CurrencyExtensions.kt 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 8819d996..2f325f92 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 @@ -19,6 +19,9 @@ class Patcher { Preferences.executeOnce(Preferences.Keys.PATCH_TRANSACTION_TYPES_NAMES, context) { patchDefaultTransactionTypes(context) } + Preferences.executeOnce(Preferences.Keys.PATCH_BLINDS_FORMAT, context) { + patchBlindFormat(context) + } } @@ -59,6 +62,17 @@ class Patcher { realm.close() } + private fun patchBlindFormat(context: Context) { + val realm = Realm.getDefaultInstance() + realm.executeTransaction { + val sessions = realm.where(Session::class.java).findAll() + sessions.forEach { session -> + session.formatBlinds() + } + } + realm.close() + } + } } \ No newline at end of file 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 447cd62a..8c7d977f 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 @@ -244,6 +244,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat override var bankroll: Bankroll? = null set(value) { field = value + this.formatBlinds() this.updateRowRepresentation() } @@ -620,7 +621,11 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat cgBigBlind?.let { bb -> val sb = cgSmallBlind ?: bb / 2.0 val preFormattedBlinds = "${sb.formatted()}/${bb.round()}" - blinds = bb.toCurrency(currency).replace(Regex.fromLiteral("-?\\d+(\\.\\d+)?"), preFormattedBlinds) + 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") } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt index 9e2c6eef..bc44a188 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt @@ -17,6 +17,7 @@ import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.SeparatorRow +import net.pokeranalytics.android.util.UserDefaults import java.util.* class CurrenciesFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { @@ -44,19 +45,11 @@ class CurrenciesFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataS ) } - private val availableCurrencyLocales = Locale.getAvailableLocales().mapNotNull { - try { - Currency.getInstance(it) - } catch (e: Exception) { - null - } - } - private val availableCurrencies = this.systemCurrencies.filter { !mostUsedCurrencyCodes.contains(it.currencyCode) }.filter { - availableCurrencyLocales.filter { currencyLocale -> - currencyLocale.currencyCode == it.currencyCode + UserDefaults.availableCurrencyLocales.filter { currencyLocale -> + Currency.getInstance(currencyLocale).currencyCode == it.currencyCode }.isNotEmpty() }.sortedBy { it.displayName 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 6262f7c5..beff0335 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt @@ -27,7 +27,8 @@ class Preferences { ACTIVE_FILTER_ID("ActiveFilterId"), LATEST_PURCHASE("latestPurchase"), PATCH_BREAK("patchBreaks"), - PATCH_TRANSACTION_TYPES_NAMES("patchTransactionTypesNames") + PATCH_TRANSACTION_TYPES_NAMES("patchTransactionTypesNames"), + PATCH_BLINDS_FORMAT("patchBlindFormat") } companion object { @@ -84,14 +85,10 @@ class Preferences { return getString(Keys.CURRENCY_CODE, context) } - private fun getCurrencyLocale(context : Context) : Locale? { + fun getCurrencyLocale(context : Context) : Locale? { getCurrencyCode(context)?.let { currencyCode -> - Locale.getAvailableLocales().filter { - try { - Currency.getInstance(it).currencyCode == currencyCode - } catch (e: Exception) { - false - } + UserDefaults.availableCurrencyLocales.filter { + Currency.getInstance(it).currencyCode == currencyCode }.firstOrNull()?.let { return it } @@ -137,6 +134,15 @@ class UserDefaults private constructor(context: Context) { currency = Preferences.getDefaultCurrency(context) ?: getLocaleCurrency() } + val availableCurrencyLocales = Locale.getAvailableLocales().mapNotNull { + try { + Currency.getInstance(it) + it + } catch (e: Exception) { + null + } + } + /** * Return the locale currency, or en_US if there */ diff --git a/app/src/main/java/net/pokeranalytics/android/util/extensions/CurrencyExtensions.kt b/app/src/main/java/net/pokeranalytics/android/util/extensions/CurrencyExtensions.kt new file mode 100644 index 00000000..baca88f7 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/util/extensions/CurrencyExtensions.kt @@ -0,0 +1,11 @@ +package net.pokeranalytics.android.util.extensions + +import net.pokeranalytics.android.util.UserDefaults +import java.util.* + +val Currency.locale : Locale + get() = + UserDefaults.availableCurrencyLocales.filter { + Currency.getInstance(it).currencyCode == this.currencyCode + }.firstOrNull() ?: Locale.getDefault() + diff --git a/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt b/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt index 39a3f043..cfc80e51 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt @@ -2,6 +2,8 @@ package net.pokeranalytics.android.util.extensions import android.content.Context import net.pokeranalytics.android.R +import net.pokeranalytics.android.util.Preferences +import net.pokeranalytics.android.util.UserDefaults import java.lang.Math.abs import java.math.RoundingMode import java.text.DecimalFormat @@ -50,7 +52,7 @@ fun Double.formatted(): String { fun Double.toCurrency(currency: Currency? = null): String { - val currencyFormatter = NumberFormat.getCurrencyInstance() + val currencyFormatter = NumberFormat.getCurrencyInstance(currency?.locale ?: Locale.getDefault()) currency?.let { currencyFormatter.currency = currency } From f57d6ce2daf68c3ec51cbc1b046cab774554c6d7 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 17 Jun 2019 14:57:45 +0200 Subject: [PATCH 046/125] Fixes refresh issue when updating currency --- .../android/ui/fragment/data/BankrollDataFragment.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt index eb790102..70152730 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt @@ -146,9 +146,11 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS override fun onRowValueChanged(value: Any?, row: RowRepresentable) { super.onRowValueChanged(value, row) - // Clear the value when the currency has been updated - if (row == BankrollRow.CURRENCY) { - this.lastRefreshRateCall = 0 + when (row) { + BankrollRow.CURRENCY -> { // Clear the value when the currency has been updated + this.lastRefreshRateCall = 0 + this.rowRepresentableAdapter.notifyDataSetChanged() + } } updateAdapterUI() From 222561f49cc91fa29c8f432e7388212c3916242c Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 17 Jun 2019 14:59:07 +0200 Subject: [PATCH 047/125] Refactor RequestCode use --- .../android/ui/fragment/data/BankrollDataFragment.kt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt index 70152730..15ad0686 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt @@ -9,6 +9,7 @@ import net.pokeranalytics.android.api.CurrencyConverterApi import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.retrofit.CurrencyConverterValue import net.pokeranalytics.android.ui.activity.CurrenciesActivity +import net.pokeranalytics.android.ui.activity.components.RequestCode import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.fragment.CurrenciesFragment @@ -33,10 +34,6 @@ import java.util.* */ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataSource { - companion object { - const val REQUEST_CODE_CURRENCY: Int = 100 - } - // Return the item as a Bankroll object private val bankroll: Bankroll get() { @@ -67,7 +64,7 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (requestCode == REQUEST_CODE_CURRENCY && resultCode == RESULT_OK) { + if (requestCode == RequestCode.CURRENCY.value && resultCode == RESULT_OK) { data?.let { val currencyCode = it.getStringExtra(CurrenciesFragment.INTENT_CURRENCY_CODE) onRowValueChanged(currencyCode, BankrollRow.CURRENCY) @@ -136,7 +133,7 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { when (row) { BankrollRow.CURRENCY -> CurrenciesActivity.newInstanceForResult(this@BankrollDataFragment, - REQUEST_CODE_CURRENCY + RequestCode.CURRENCY.value ) BankrollRow.REFRESH_RATE -> refreshRate() else -> super.onRowSelected(position, row, fromAction) From 2c0a4c89a898927e6ddcce434a1e947a57366b25 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 17 Jun 2019 15:06:09 +0200 Subject: [PATCH 048/125] formatting currency numbers using the default Locale --- .../pokeranalytics/android/util/extensions/NumbersExtension.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt b/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt index cfc80e51..016edaca 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt @@ -52,7 +52,7 @@ fun Double.formatted(): String { fun Double.toCurrency(currency: Currency? = null): String { - val currencyFormatter = NumberFormat.getCurrencyInstance(currency?.locale ?: Locale.getDefault()) + val currencyFormatter = NumberFormat.getCurrencyInstance(Locale.getDefault()) currency?.let { currencyFormatter.currency = currency } From d357f8c8b4da9cff1d5bf54a74fd7a58a590fb27 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 17 Jun 2019 16:58:55 +0200 Subject: [PATCH 049/125] Added message in subscription window when reaching the max number of sessions + strings update --- .../android/ui/activity/BillingActivity.kt | 26 +++++++++++++++++-- .../android/ui/activity/ImportActivity.kt | 2 +- .../android/ui/fragment/FeedFragment.kt | 2 +- .../android/ui/fragment/SettingsFragment.kt | 2 +- .../ui/fragment/SubscriptionFragment.kt | 19 +++++++++----- app/src/main/res/layout/activity_billing.xml | 17 +++--------- .../main/res/layout/fragment_subscription.xml | 25 +++++++++++++----- app/src/main/res/values/strings.xml | 4 +-- 8 files changed, 64 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/BillingActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/BillingActivity.kt index c60cfd9c..39db989a 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/BillingActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/BillingActivity.kt @@ -7,18 +7,25 @@ import androidx.fragment.app.Fragment import net.pokeranalytics.android.R import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.activity.components.RequestCode +import net.pokeranalytics.android.ui.fragment.SubscriptionFragment class BillingActivity : PokerAnalyticsActivity() { + private enum class IntentKey(val keyName: String) { + SHOW_MESSAGE("showMessage"), + } + companion object { - fun newInstanceForResult(activity: Activity) { + fun newInstanceForResult(activity: Activity, showSessionMessage: Boolean) { val intent = Intent(activity, BillingActivity::class.java) + intent.putExtra(IntentKey.SHOW_MESSAGE.keyName, showSessionMessage) activity.startActivityForResult(intent, RequestCode.SUBSCRIPTION.value) } - fun newInstanceForResult(fragment: Fragment) { + fun newInstanceForResult(fragment: Fragment, showSessionMessage: Boolean) { val intent = Intent(fragment.requireContext(), BillingActivity::class.java) + intent.putExtra(IntentKey.SHOW_MESSAGE.keyName, showSessionMessage) fragment.startActivityForResult(intent, RequestCode.SUBSCRIPTION.value) } } @@ -26,6 +33,21 @@ class BillingActivity : PokerAnalyticsActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_billing) + initUI() + } + + private fun initUI() { + + val fragmentManager = supportFragmentManager + val fragmentTransaction = fragmentManager.beginTransaction() + val fragment = SubscriptionFragment() + + val showSessionMessage = intent.getBooleanExtra(IntentKey.SHOW_MESSAGE.keyName, false) + + fragmentTransaction.add(R.id.container, fragment) + fragmentTransaction.commit() + fragment.setData(showSessionMessage) + } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt index 498a5f86..2a83c802 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt @@ -118,7 +118,7 @@ class ImportActivity : PokerAnalyticsActivity() { if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG Toast.makeText(this, "Please subscribe!", Toast.LENGTH_LONG).show() - BillingActivity.newInstanceForResult(this) + BillingActivity.newInstanceForResult(this, true) return } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt index 82db898e..e860198e 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt @@ -275,7 +275,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { val sessionCount = this.feedSessionAdapter.realmResults.size if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG // Toast.makeText(context, "Please subscribe!", Toast.LENGTH_LONG).show() - BillingActivity.newInstanceForResult(this) + BillingActivity.newInstanceForResult(this, true) return } 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 364a50fc..f2d79b2d 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 @@ -113,7 +113,7 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta when (row) { SettingRow.SUBSCRIPTION -> { if (!AppGuard.isProUser) { - BillingActivity.newInstanceForResult(this) + BillingActivity.newInstanceForResult(this, false) } else { this.openPlaystoreAccount() } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt index a5b20860..7ebb4063 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt @@ -43,6 +43,7 @@ class SubscriptionFragment : PokerAnalyticsFragment(), SkuDetailsResponseListene private var pagerAdapter: ScreenSlidePagerAdapter? = null private var selectedProduct: SkuDetails? = null + private var showSessionMessage = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -54,6 +55,10 @@ class SubscriptionFragment : PokerAnalyticsFragment(), SkuDetailsResponseListene } } + fun setData(showSessionMessage: Boolean) { + this.showSessionMessage = showSessionMessage + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_subscription, container, false) } @@ -89,6 +94,10 @@ class SubscriptionFragment : PokerAnalyticsFragment(), SkuDetailsResponseListene this.title.text = upgradeString } + if (showSessionMessage) { + this.message.text = getString(R.string.iap_session_message) + } + // Pager // The pager adapter, which provides the pages to the view pager widget. @@ -110,7 +119,7 @@ class SubscriptionFragment : PokerAnalyticsFragment(), SkuDetailsResponseListene for (i in 1..count) { val view = View(requireContext()) view.background = requireContext().getDrawable(R.drawable.circle_green) - val layoutParam = LinearLayout.LayoutParams(10.px, 10.px) + val layoutParam = LinearLayout.LayoutParams(8.px, 8.px) layoutParam.setMargins(6.px) this.pageIndicator.addView(view, layoutParam) } @@ -202,12 +211,8 @@ class SubscriptionFragment : PokerAnalyticsFragment(), SkuDetailsResponseListene override fun onPageScrollStateChanged(state: Int) {} override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { - pagerAdapter?.getFragment(position)?.let { - it.updateViewsPosition(-positionOffset * parallax) - } - pagerAdapter?.getFragment(position + 1)?.let { - it.updateViewsPosition((1 - positionOffset) * parallax) - } + pagerAdapter?.getFragment(position)?.updateViewsPosition(-positionOffset * parallax) + pagerAdapter?.getFragment(position + 1)?.updateViewsPosition((1 - positionOffset) * parallax) } override fun onPageSelected(position: Int) { diff --git a/app/src/main/res/layout/activity_billing.xml b/app/src/main/res/layout/activity_billing.xml index 08d1f651..e1701185 100644 --- a/app/src/main/res/layout/activity_billing.xml +++ b/app/src/main/res/layout/activity_billing.xml @@ -1,15 +1,6 @@ - - + android:layout_height="match_parent"> - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_subscription.xml b/app/src/main/res/layout/fragment_subscription.xml index 7791cfb8..e281aa06 100644 --- a/app/src/main/res/layout/fragment_subscription.xml +++ b/app/src/main/res/layout/fragment_subscription.xml @@ -50,37 +50,50 @@ app:layout_constraintTop_toBottomOf="@id/title" tools:text="30 day free trial" /> + + + app:layout_constraintStart_toStartOf="parent" /> Unlimited Track all your poker life by adding as many data as you want Offline first - Poker Analytics is available at all times and the data is yours. Export it at any times. Note: You’re currently in charge of backups, but that will change soon! + Poker Analytics is available at all times and the data is yours. Note: We will soon add exporting capabilities and you’re currently in charge of backups. Thanks for your patience! Private We do not own servers. We do not know anything about your wins and losses. Support @@ -38,6 +38,7 @@ Custom field The item is used in one or more transactions…Please delete the linked transactions first Imported + You\'ve reached the maximum number of free sessions. Please subscribe for unlimited use and don\'t hesitate to tell us how you feel about your current experience! Address Naming suggestions @@ -285,7 +286,6 @@ Net hourly rate Range Export your data to iCloud, get the Pro version, open it, import your data from iCloud. - You\'ve reached the maximum number of sessions. Get a new subscription to get more sessions! iCloud iCloud settings were modified, please wait for synchronization. A backup of your data was found on iCloud, do you want to use it on this device? If yes, the local data from this device will be replaced by the backup and if no, you will keep using the local data from this device and your iCloud account won\'t be modified. From 5da3c7c7eb2ca3a7477646109ec66f589113fd74 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 17 Jun 2019 17:03:59 +0200 Subject: [PATCH 050/125] string changes --- app/src/main/res/values-fr/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f382b4fe..25c20881 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -18,11 +18,11 @@ Illimité Suivez toute votre vie de joueur en ajoutant autant de données que vous le souhaitez Hors ligne avant tout - Poker Analytics est disponible à tout moment et vos données vous appartiennent. Vous êtes pour l\'instant en charge de faire des sauvegarde mais cela changera dans le futur! + Poker Analytics est disponible à tout moment et vos données vous appartiennent. Vous êtes pour l\'instant en charge d'effectuer des sauvegarde mais cela changera dans le futur! Vie privée Nous ne sauvegardons pas vos données, nous ne savons rien de vos gains ni de vos pertes Support - Nous essayons de répondre le plus vite possible, en français ou en anglais ! + Nous essayons de répondre le plus vite possible, en français mais aussi en anglais ! Chargement, veuillez patienter… Choisissez un type de rapport Choisissez une statistique, ou plusieurs From 48db243eb1d25bad546fef8557ea27bf3a35bcac Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 18 Jun 2019 08:09:01 +0200 Subject: [PATCH 051/125] Fixing strings build issue --- app/src/main/res/values-fr/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 25c20881..5c6a4060 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -18,7 +18,7 @@ Illimité Suivez toute votre vie de joueur en ajoutant autant de données que vous le souhaitez Hors ligne avant tout - Poker Analytics est disponible à tout moment et vos données vous appartiennent. Vous êtes pour l\'instant en charge d'effectuer des sauvegarde mais cela changera dans le futur! + Poker Analytics est disponible à tout moment et vos données vous appartiennent. Vous êtes pour l\'instant en charge d\'effectuer des sauvegarde mais cela changera dans le futur! Vie privée Nous ne sauvegardons pas vos données, nous ne savons rien de vos gains ni de vos pertes Support From 492525d67cababcd95bf17576b921df73a5e2b76 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 18 Jun 2019 08:09:18 +0200 Subject: [PATCH 052/125] Disabling subscriptions --- .../android/ui/fragment/FeedFragment.kt | 52 ++++++++++--------- .../ui/view/rowrepresentable/SettingRow.kt | 4 +- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt index e860198e..47825d1d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt @@ -6,6 +6,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.core.app.ActivityOptionsCompat import androidx.core.view.isVisible import androidx.interpolator.view.animation.FastOutSlowInInterpolator @@ -32,7 +33,8 @@ import net.pokeranalytics.android.ui.interfaces.FilterableType import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager import net.pokeranalytics.android.util.Preferences -import net.pokeranalytics.android.util.billing.AppGuard +import java.text.SimpleDateFormat +import java.util.* class FeedFragment : FilterableFragment(), RowRepresentableDelegate { @@ -59,7 +61,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { private lateinit var feedTransactionAdapter: FeedTransactionRowRepresentableAdapter private lateinit var realmSessions: RealmResults private lateinit var realmTransactions: RealmResults -// private lateinit var betaLimitDate: Date + private lateinit var betaLimitDate: Date private var newSessionCreated: Boolean = false private var adapterHasBeenSet: Boolean = false @@ -205,8 +207,8 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { */ private fun initData() { -// val sdf = SimpleDateFormat("dd/M/yyyy hh:mm", Locale.getDefault()) -// betaLimitDate = sdf.parse("17/7/2019 10:00") + val sdf = SimpleDateFormat("dd/M/yyyy hh:mm", Locale.getDefault()) + betaLimitDate = sdf.parse("17/7/2019 10:00") this.currentFilterable = FilterableType.SESSION val viewManager = SmoothScrollLinearLayoutManager(requireContext()) @@ -272,19 +274,19 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { */ private fun createNewSession(isTournament: Boolean) { - val sessionCount = this.feedSessionAdapter.realmResults.size - if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG -// Toast.makeText(context, "Please subscribe!", Toast.LENGTH_LONG).show() - BillingActivity.newInstanceForResult(this, true) - return - } - - // Keep commented code for special versions -// if (Date().after(betaLimitDate)) { -// this.showEndOfBetaMessage() +// val sessionCount = this.feedSessionAdapter.realmResults.size +// if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG +//// Toast.makeText(context, "Please subscribe!", Toast.LENGTH_LONG).show() +// BillingActivity.newInstanceForResult(this, true) // return // } + // Keep commented code for special versions + if (Date().after(betaLimitDate)) { + this.showEndOfBetaMessage() + return + } + SessionActivity.newInstanceforResult(this, isTournament, requestCode = RequestCode.NEW_SESSION.value) newSessionCreated = true } @@ -294,10 +296,10 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { */ private fun createNewTransaction() { -// if (Date().after(betaLimitDate)) { -// this.showEndOfBetaMessage() -// return -// } + if (Date().after(betaLimitDate)) { + this.showEndOfBetaMessage() + return + } EditableDataActivity.newInstanceForResult(this, LiveData.TRANSACTION, null, RequestCode.NEW_TRANSACTION.value) } @@ -316,13 +318,13 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { * Show end of beta message * Keep for possible future uses */ -// private fun showEndOfBetaMessage() { -// Toast.makeText( -// context, -// "App version has ended. Thanks a lot for using it! Please update with the Google Play version to continue using the app.", -// Toast.LENGTH_LONG -// ).show() -// } + private fun showEndOfBetaMessage() { + Toast.makeText( + context, + "App version has ended. Thanks a lot for using it! Please update with the Google Play version to continue using the app.", + Toast.LENGTH_LONG + ).show() + } // Filter Handler diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt index 7de89ea5..d3f89714 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt @@ -45,8 +45,8 @@ enum class SettingRow : RowRepresentable { val rows = ArrayList() rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.information)) -// rows.addAll(arrayListOf(VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) - rows.addAll(arrayListOf(SUBSCRIPTION, VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) + rows.addAll(arrayListOf(VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) +// rows.addAll(arrayListOf(SUBSCRIPTION, VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.follow_us)) rows.addAll(arrayListOf(FOLLOW_US)) From 9b66e767e3e38b94ff2b1db72375a7292df0a195 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 18 Jun 2019 08:09:53 +0200 Subject: [PATCH 053/125] Bumping version + upgrading androidx.core:core-ktx --- app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 5e354191..67b98e43 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,8 +29,8 @@ android { applicationId "net.pokeranalytics.android" minSdkVersion 23 targetSdkVersion 28 - versionCode 39 - versionName "2.0.2" + versionCode 40 + versionName "2.0.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -78,7 +78,7 @@ dependencies { // Android implementation 'androidx.appcompat:appcompat:1.0.2' - implementation 'androidx.core:core-ktx:1.2.0-alpha01' + implementation 'androidx.core:core-ktx:1.2.0-alpha02' implementation 'com.google.android.material:material:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' From 9fe135e17e5b13041fb51c823d8369b1e3fda455 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 18 Jun 2019 08:26:24 +0200 Subject: [PATCH 054/125] disable CSV import --- app/src/main/AndroidManifest.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b7e5f47c..969194d3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,16 +39,16 @@ android:screenOrientation="portrait" android:launchMode="singleTop"> - - - + + + - - - - + + + + - + From 05afd66d73e410c6ad7fa9645a476ce98979e7e4 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 18 Jun 2019 15:43:58 +0200 Subject: [PATCH 055/125] Added ability to duplicate a session --- .../android/model/realm/Session.kt | 18 ++++++++ .../android/ui/activity/SessionActivity.kt | 27 ++++++------ .../FeedSessionRowRepresentableAdapter.kt | 19 +++++--- .../android/ui/fragment/FeedFragment.kt | 43 ++++++++++++++++--- .../android/ui/fragment/SessionFragment.kt | 26 ++++++++--- .../ui/view/ContextMenuRecyclerView.kt | 38 ++++++++++++++++ app/src/main/res/layout/fragment_feed.xml | 3 +- .../layout/row_bottom_sheet_grid_title.xml | 1 + app/src/main/res/layout/row_session_view.xml | 3 +- app/src/main/res/layout/row_title.xml | 2 +- app/src/main/res/layout/row_title_arrow.xml | 2 +- app/src/main/res/layout/row_title_check.xml | 2 +- .../main/res/layout/row_title_icon_arrow.xml | 2 +- app/src/main/res/menu/menu_session.xml | 8 ++++ app/src/main/res/values/styles.xml | 7 ++- 15 files changed, 164 insertions(+), 37 deletions(-) create mode 100644 app/src/main/java/net/pokeranalytics/android/ui/view/ContextMenuRecyclerView.kt create mode 100644 app/src/main/res/menu/menu_session.xml 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 8c7d977f..8944468e 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 @@ -658,6 +658,24 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat } + fun duplicate() : Session { + + val copy = Session.newInstance(this.realm, this.isTournament(), this.bankroll) + + copy.game = this.game + copy.limit = this.limit + copy.cgSmallBlind = this.cgSmallBlind + copy.cgBigBlind = this.cgBigBlind + copy.tournamentEntryFee = this.tournamentEntryFee + copy.tournamentFeatures = this.tournamentFeatures + copy.tournamentName = this.tournamentName + copy.tournamentType = this.tournamentType + copy.tableSize = this.tableSize + copy.numberOfTables = this.numberOfTables + + return copy + } + @Ignore override val viewType: Int = RowViewType.ROW_SESSION.ordinal diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/SessionActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/SessionActivity.kt index e082fb49..602762c9 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/SessionActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/SessionActivity.kt @@ -14,32 +14,32 @@ class SessionActivity: PokerAnalyticsActivity() { enum class IntentKey(val keyName : String) { IS_TOURNAMENT("IS_TOURNAMENT"), + DUPLICATE("DUPLICATE"), SESSION_ID("SESSION_ID"); } companion object { - fun newInstance(context: Context, isTournament: Boolean? = false, sessionId: String? = "") { - val intent = Intent(context, SessionActivity::class.java) - isTournament?.let { - intent.putExtra(IntentKey.IS_TOURNAMENT.keyName, isTournament) - } - sessionId?.let { - intent.putExtra(IntentKey.SESSION_ID.keyName, sessionId) - } + fun newInstance(context: Context, isTournament: Boolean? = false, sessionId: String? = "", duplicate: Boolean = false) { + val intent = this.intent(context, isTournament, sessionId, duplicate) context.startActivity(intent) } - fun newInstanceforResult(fragment: Fragment, isTournament: Boolean? = false, sessionId: String? = "", requestCode: Int) { - val intent = Intent(fragment.requireContext(), SessionActivity::class.java) + fun newInstanceforResult(fragment: Fragment, isTournament: Boolean? = false, sessionId: String? = "", duplicate: Boolean = false, requestCode: Int) { + val intent = this.intent(fragment.requireContext(), isTournament, sessionId, duplicate) + fragment.startActivityForResult(intent, requestCode) + } + + private fun intent(context: Context, isTournament: Boolean? = false, sessionId: String? = "", duplicate: Boolean = false) : Intent { + val intent = Intent(context, SessionActivity::class.java) isTournament?.let { intent.putExtra(IntentKey.IS_TOURNAMENT.keyName, isTournament) } + intent.putExtra(IntentKey.DUPLICATE.keyName, duplicate) sessionId?.let { intent.putExtra(IntentKey.SESSION_ID.keyName, sessionId) } - - fragment.startActivityForResult(intent, requestCode) + return intent } } @@ -62,8 +62,9 @@ class SessionActivity: PokerAnalyticsActivity() { private fun initUI() { val sessionId = intent.getStringExtra(IntentKey.SESSION_ID.keyName) val isTournament = intent.getBooleanExtra(IntentKey.IS_TOURNAMENT.keyName, false) + val duplicate = intent.getBooleanExtra(IntentKey.DUPLICATE.keyName, false) val fragment = sessionFragment as SessionFragment - fragment.setData(isTournament, sessionId) + fragment.setData(isTournament, sessionId, duplicate) } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedSessionRowRepresentableAdapter.kt b/app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedSessionRowRepresentableAdapter.kt index 405167e7..849487ec 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedSessionRowRepresentableAdapter.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedSessionRowRepresentableAdapter.kt @@ -8,7 +8,6 @@ import androidx.appcompat.widget.AppCompatTextView import androidx.recyclerview.widget.RecyclerView import io.realm.RealmResults import kotlinx.android.synthetic.main.row_feed_session.view.* -import net.pokeranalytics.android.R import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.view.BindableHolder import net.pokeranalytics.android.ui.view.RowViewType @@ -43,6 +42,7 @@ class FeedSessionRowRepresentableAdapter( * Display a session view */ inner class RowSessionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { + fun bind(position: Int, row: Session?, adapter: FeedSessionRowRepresentableAdapter) { itemView.sessionRow.setData(row as Session) @@ -50,6 +50,10 @@ class FeedSessionRowRepresentableAdapter( adapter.delegate?.onRowSelected(position, row) } itemView.sessionRow.setOnClickListener(listener) + + itemView.sessionRow.setOnLongClickListener { + itemView.showContextMenu() + } } } @@ -59,7 +63,7 @@ class FeedSessionRowRepresentableAdapter( inner class HeaderTitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { fun bind(title: String) { // Title - itemView.findViewById(R.id.title)?.let { + itemView.findViewById(net.pokeranalytics.android.R.id.title)?.let { it.text = title } } @@ -67,10 +71,10 @@ class FeedSessionRowRepresentableAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return if (viewType == RowViewType.ROW_SESSION.ordinal) { - val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_feed_session, parent, false) + val layout = LayoutInflater.from(parent.context).inflate(net.pokeranalytics.android.R.layout.row_feed_session, parent, false) RowSessionViewHolder(layout) } else { - val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_header_title, parent, false) + val layout = LayoutInflater.from(parent.context).inflate(net.pokeranalytics.android.R.layout.row_header_title, parent, false) HeaderTitleViewHolder(layout) } @@ -104,7 +108,7 @@ class FeedSessionRowRepresentableAdapter( // If the header has no date, it's a pending session return if (sortedHeaders[position] == null) { - context.getString(R.string.pending) + context.getString(net.pokeranalytics.android.R.string.pending) } else { // Else, return the formatted date val realmHeaderPosition = if (pendingRealmResults.size > 0) sortedHeaders.keys.indexOf(position) - 1 else sortedHeaders.keys.indexOf(position) @@ -114,6 +118,11 @@ class FeedSessionRowRepresentableAdapter( return NULL_TEXT } + fun sessionIdForPosition(position: Int): String? { + val session = this.getSessionForPosition(position) + return session?.id + } + /** * Get real index */ diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt index 47825d1d..dc1608ad 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt @@ -3,9 +3,7 @@ package net.pokeranalytics.android.ui.fragment import android.app.Activity.RESULT_OK import android.content.Intent import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.view.* import android.widget.Toast import androidx.core.app.ActivityOptionsCompat import androidx.core.view.isVisible @@ -17,6 +15,7 @@ import io.realm.Sort import io.realm.kotlin.where import kotlinx.android.synthetic.main.fragment_feed.* import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.interfaces.Editable import net.pokeranalytics.android.model.realm.Filter @@ -30,13 +29,14 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.fragment.components.FilterableFragment import net.pokeranalytics.android.ui.interfaces.FilterActivityRequestCode import net.pokeranalytics.android.ui.interfaces.FilterableType +import net.pokeranalytics.android.ui.view.ContextMenuRecyclerView import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager import net.pokeranalytics.android.util.Preferences +import timber.log.Timber import java.text.SimpleDateFormat import java.util.* - class FeedFragment : FilterableFragment(), RowRepresentableDelegate { private enum class Tab { @@ -91,6 +91,35 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { return inflater.inflate(R.layout.fragment_feed, container, false) } + override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) { + super.onCreateContextMenu(menu, v, menuInfo) + + if (v?.id == R.id.recyclerView) { + activity?.menuInflater?.inflate(R.menu.menu_session, menu) + } + + } + + override fun onContextItemSelected(item: MenuItem?): Boolean { + + when (item?.itemId) { + R.id.duplicate -> { + val info = item.menuInfo as ContextMenuRecyclerView.RecyclerViewContextMenuInfo + Timber.d("info = $info") + + val sessionId = this.feedSessionAdapter.sessionIdForPosition(info.position) + if (sessionId != null) { + createNewSession(true, sessionId = sessionId, duplicate = true) + } else { + throw PAIllegalStateException("Session not found for duplicate at position: ${info.position}") + } + } + else -> { } + } + + return true + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initUI() @@ -160,6 +189,8 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { */ private fun initUI() { + registerForContextMenu(this.recyclerView) + disclaimerContainer.isVisible = Preferences.shouldShowDisclaimer(requireContext()) disclaimerDismiss.setOnClickListener { @@ -272,7 +303,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { /** * Create a new cash game */ - private fun createNewSession(isTournament: Boolean) { + private fun createNewSession(isTournament: Boolean, sessionId: String? = null, duplicate: Boolean = false) { // val sessionCount = this.feedSessionAdapter.realmResults.size // if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG @@ -287,7 +318,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { return } - SessionActivity.newInstanceforResult(this, isTournament, requestCode = RequestCode.NEW_SESSION.value) + SessionActivity.newInstanceforResult(this, isTournament, sessionId = sessionId, duplicate = duplicate, requestCode = RequestCode.NEW_SESSION.value) newSessionCreated = true } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt index 335aa4f4..e62eabc5 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt @@ -61,14 +61,28 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate { /** * Set fragment data */ - fun setData(isTournament: Boolean, sessionId: String) { + fun setData(isTournament: Boolean, sessionId: String? = null, duplicate: Boolean) { val realm = getRealm() - val sessionRealm = realm.findById(sessionId) - if (sessionRealm != null) { - currentSession = sessionRealm - sessionHasBeenCustomized = true - } else { + if (sessionId != null) { + + val sessionRealm = realm.findById(sessionId) + if (sessionRealm != null) { + + if (duplicate) { // duplicate session + realm.executeTransaction { + val session = sessionRealm.duplicate() + currentSession = session + } + sessionHasBeenCustomized = false + } else { // show existing session + currentSession = sessionRealm + sessionHasBeenCustomized = true + } + } else { + throw PAIllegalStateException("Session cannot be null here, session id = $sessionId") + } + } else { // create new session realm.executeTransaction { executeRealm -> currentSession = Session.newInstance(executeRealm, isTournament) FavoriteSessionFinder.copyParametersFromFavoriteSession(currentSession, null, requireContext()) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/ContextMenuRecyclerView.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/ContextMenuRecyclerView.kt new file mode 100644 index 00000000..07dbdb18 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/ContextMenuRecyclerView.kt @@ -0,0 +1,38 @@ +package net.pokeranalytics.android.ui.view + +import android.content.Context +import android.util.AttributeSet +import android.view.ContextMenu +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import timber.log.Timber + + +class ContextMenuRecyclerView : RecyclerView { + + constructor(context: Context, attributeSet: AttributeSet?, defStyle: Int) : super(context, attributeSet, defStyle) + constructor(context: Context, attributeSet: AttributeSet?) : super(context, attributeSet) + constructor(context: Context) : super(context) + + private var mContextMenuInfo: RecyclerViewContextMenuInfo? = null + + override fun getContextMenuInfo(): ContextMenu.ContextMenuInfo? { + return mContextMenuInfo + } + + override fun showContextMenuForChild(originalView: View): Boolean { + val longPressPosition = getChildAdapterPosition(originalView) + Timber.d("longPressPosition = $longPressPosition") + if (longPressPosition >= 0) { + val longPressId = adapter!!.getItemId(longPressPosition) + Timber.d("longPressId = $longPressId") + mContextMenuInfo = RecyclerViewContextMenuInfo(longPressPosition, longPressId) + return super.showContextMenuForChild(originalView) + } + return false + } + + class RecyclerViewContextMenuInfo(val position: Int, val id: Long) : ContextMenu.ContextMenuInfo + +} + diff --git a/app/src/main/res/layout/fragment_feed.xml b/app/src/main/res/layout/fragment_feed.xml index 9ee9dc14..b8000803 100644 --- a/app/src/main/res/layout/fragment_feed.xml +++ b/app/src/main/res/layout/fragment_feed.xml @@ -57,7 +57,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/appBar" /> - - + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 23e128e8..c0562ef6 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -17,7 +17,7 @@ @style/PokerAnalyticsTheme.Toolbar @style/PokerAnalyticsTheme.BottomAppBar @style/PokerAnalyticsTheme.EditText - @style/PokerAnalyticsTheme.TextView + @style/PokerAnalyticsTheme.AlertDialog @style/PokerAnalyticsTheme.Chip @style/PokerAnalyticsTheme.TabLayout @@ -83,6 +83,11 @@ @font/roboto + +