diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5776f99f..714f4e26 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -176,6 +176,11 @@
android:launchMode="singleTop"
android:screenOrientation="portrait" />
+
+
= listOf()
) {
constructor(
@@ -252,8 +251,16 @@ class Calculator {
// Timber.d("$$$ buyin = ${it.ratedBuyin} $$$ net result = ${it.ratedNet}")
// }
- val sum = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble()
- results.addStat(NET_RESULT, sum)
+ var ratedNet = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble()
+ if (options.includedTransactions.isNotEmpty()) {
+ for (transactionType in options.includedTransactions) {
+ val transactions = computableGroup.transactions(realm, transactionType, options.shouldSortValues)
+ val transactionRatedAmount = transactions.sum(Transaction.Field.RATED_AMOUNT.identifier).toDouble()
+ ratedNet += transactionRatedAmount
+ }
+ }
+
+ results.addStat(NET_RESULT, ratedNet)
val totalHands = computables.sum(ComputableResult.Field.ESTIMATED_HANDS.identifier).toDouble()
results.addStat(HANDS_PLAYED, totalHands)
@@ -288,7 +295,7 @@ class Calculator {
Stat.netBBPer100Hands(bbSum, totalHands)?.let { netBB100 ->
results.addStat(NET_BB_PER_100_HANDS, netBB100)
}
- Stat.returnOnInvestment(sum, totalBuyin)?.let { roi ->
+ Stat.returnOnInvestment(ratedNet, totalBuyin)?.let { roi ->
results.addStat(ROI, roi)
}
@@ -305,7 +312,7 @@ class Calculator {
var average = 0.0 // also used for standard deviation later
if (computables.size > 0) {
- average = sum / computables.size.toDouble()
+ average = ratedNet / computables.size.toDouble()
val winRatio = winningSessionCount.toDouble() / computables.size.toDouble()
val itmRatio = winningSessionCount.toDouble() / computables.size.toDouble()
val avgBuyin = totalBuyin / computables.size.toDouble()
@@ -425,9 +432,9 @@ class Calculator {
}
}
- val shouldIterateOverSets = computableGroup.conditions.isNotEmpty() ||
- options.progressValues != Options.ProgressValues.NONE ||
- options.computeDaysPlayed
+ val shouldIterateOverSets = computableGroup.conditions.isNotEmpty()
+ || options.progressValues != Options.ProgressValues.NONE
+ || options.computeDaysPlayed
// Session Set
if (shouldIterateOverSets) {
@@ -525,7 +532,7 @@ class Calculator {
var hourlyRate = 0.0
if (gHourlyDuration != null) {
- hourlyRate = sum / gHourlyDuration
+ hourlyRate = ratedNet / gHourlyDuration
if (sessionSets.size > 0) {
val avgDuration = gHourlyDuration / sessionSets.size
results.addStat(HOURLY_RATE, hourlyRate)
diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt b/app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt
index 5cd8937d..d0ce49c6 100644
--- a/app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt
+++ b/app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt
@@ -4,15 +4,14 @@ import io.realm.Realm
import io.realm.RealmResults
import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.QueryCondition
-import net.pokeranalytics.android.model.realm.ComputableResult
-import net.pokeranalytics.android.model.realm.Filter
-import net.pokeranalytics.android.model.realm.SessionSet
+import net.pokeranalytics.android.model.realm.*
+import timber.log.Timber
/**
* A sessionGroup of computable items identified by a name
*/
-class ComputableGroup(var query: Query, var displayedStats: List? = null) {
+class ComputableGroup(val query: Query, var displayedStats: List? = null) {
/**
* A subgroup used to compute stat variation
@@ -85,6 +84,17 @@ class ComputableGroup(var query: Query, var displayedStats: List? = null)
return sets
}
+ /**
+ * Retrieves the transactions on the relative [realm] filtered with the provided [conditions]
+ */
+ fun transactions(realm: Realm, transactionType: TransactionType, sorted: Boolean = false): RealmResults {
+ val query = this.query.copy()
+ query.add(QueryCondition.AnyTransactionType(transactionType))
+ val sortedField = if (sorted) "date" else null
+ Timber.d("query = ${query.defaultName}")
+ return Filter.queryOn(realm, query, sortedField)
+ }
+
/**
* Nullifies used Realm results
*/
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 c86980ed..e0c7a276 100644
--- a/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt
+++ b/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt
@@ -17,7 +17,7 @@ sealed class PokerAnalyticsException(message: String) : Exception(message) {
// object FilterElementUnknownSectionName: PokerAnalyticsException(message = "No filterElement section name was found to identify the queryCondition")
// object FilterMissingEntity: PokerAnalyticsException(message = "This queryWith has no entity initialized")
// object FilterUnhandledEntity : PokerAnalyticsException(message = "This entity is not filterable")
- object QueryValueMapUnknown: PokerAnalyticsException(message = "fieldName is missing")
+class QueryValueMapUnknown(message: String = "fieldName is missing"): PokerAnalyticsException(message)
class QueryTypeUnhandled(clazz: String) :
PokerAnalyticsException(message = "queryWith type not handled: $clazz")
class ComparisonCriteriaUnhandled(criteria: Criteria) :
diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt
index 8a8b583f..307c80ab 100644
--- a/app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt
+++ b/app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt
@@ -11,6 +11,10 @@ fun List.mapFirstCondition() : List {
class Query {
+ constructor(query: Query) {
+ this._conditions.addAll(query.conditions)
+ }
+
constructor(vararg elements: QueryCondition?) {
if (elements.isNotEmpty()) {
this.add(elements.filterNotNull())
@@ -100,6 +104,11 @@ class Query {
return this
}
+ fun copy(): Query {
+ return Query(this)
+ }
+
+
/*
Returns the first object Id of any QueryCondition
*/
diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt
index 8354a29c..ec7318eb 100644
--- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt
+++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt
@@ -23,6 +23,7 @@ import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.UserDefaults
import net.pokeranalytics.android.util.extensions.*
+import timber.log.Timber
import java.text.DateFormatSymbols
import java.text.NumberFormat
import java.util.*
@@ -747,9 +748,16 @@ sealed class QueryCondition : RowRepresentable {
): RealmQuery {
val fieldName = FilterHelper.fieldNameForQueryType(this::class.java)
- if (BuildConfig.DEBUG) {
- fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
+// if (BuildConfig.DEBUG) {
+// val className = T::class.java
+// fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown("fieldName missing for $this, class = $className")
+// }
+
+ if (fieldName == null) {
+ val className = T::class.java
+ Timber.w("Possible missing filter configuration for $this in class $className")
}
+
fieldName ?: return realmQuery
when (this) {
diff --git a/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt b/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt
index 8ca95a3e..91d61f5e 100644
--- a/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt
+++ b/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt
@@ -292,11 +292,11 @@ class PokerAnalyticsMigration : RealmMigration {
// Migrate to version 13
if (currentVersion == 12) {
Timber.d("*** Running migration ${currentVersion + 1}")
- schema.get("Transaction")?.let { tts ->
- tts.addField("transferRate", Double::class.java)
+ schema.get("Transaction")?.let { ts ->
+ ts.addField("transferRate", Double::class.java)
.setNullable("transferRate", true)
schema.get("Bankroll")?.let { bs ->
- tts.addRealmObjectField("destination", bs)
+ ts.addRealmObjectField("destination", bs)
} ?: throw PAIllegalStateException("Bankroll schema not found")
}
@@ -314,6 +314,21 @@ class PokerAnalyticsMigration : RealmMigration {
currentVersion++
}
+ // Migrate to version 14
+ if (currentVersion == 13) {
+ Timber.d("*** Running migration ${currentVersion + 1}")
+ schema.get("Transaction")?.let { ts ->
+ ts.addField("ratedAmount", Double::class.java)
+ } ?: throw PAIllegalStateException("Transaction schema not found")
+
+ //transactionTypeIds
+ schema.get("UserConfig")?.let { ucs ->
+ ucs.addField("transactionTypeIds", String::class.java).setRequired("transactionTypeIds", true)
+ } ?: throw PAIllegalStateException("UserConfig schema not found")
+
+ currentVersion++
+ }
+
}
override fun equals(other: Any?): Boolean {
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 6f8362a5..094dca1d 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
@@ -73,6 +73,14 @@ open class Transaction : RealmObject(), RowRepresentable, RowUpdatable, Manageab
// The amount of the transaction
override var amount: Double = 0.0
+ set(value) {
+ field = value
+ val rate = this.bankroll?.currency?.rate ?: 1.0
+ this.ratedAmount = rate * value
+ }
+
+ // The amount of the transaction
+ var ratedAmount: Double = 0.0
// The date of the transaction
override var date: Date = Date()
@@ -102,6 +110,10 @@ open class Transaction : RealmObject(), RowRepresentable, RowUpdatable, Manageab
@Ignore
override val viewType: Int = RowViewType.ROW_TRANSACTION.ordinal
+ enum class Field(val identifier: String) {
+ RATED_AMOUNT("ratedAmount")
+ }
+
val displayAmount: Double
get() { // for transfers we want to show a positive value (in the feed for instance)
return if (this.destination == null) { this.amount } else { abs(this.amount) }
diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/UserConfig.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/UserConfig.kt
index 5b95e626..96094c1f 100644
--- a/app/src/main/java/net/pokeranalytics/android/model/realm/UserConfig.kt
+++ b/app/src/main/java/net/pokeranalytics/android/model/realm/UserConfig.kt
@@ -3,6 +3,8 @@ package net.pokeranalytics.android.model.realm
import io.realm.Realm
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
+import net.pokeranalytics.android.util.UUID_SEPARATOR
+import net.pokeranalytics.android.util.extensions.findById
import java.util.*
open class UserConfig : RealmObject() {
@@ -25,4 +27,15 @@ open class UserConfig : RealmObject() {
var onlineDealtHandsPerHour: Int = 500
+ var transactionTypeIds: String = ""
+
+ fun setTransactionTypeIds(transactionTypes: Set) {
+ this.transactionTypeIds = transactionTypes.joinToString(UUID_SEPARATOR) { it.id }
+ }
+
+ fun transactionTypes(realm: Realm): List {
+ val ids = this.transactionTypeIds.split(UUID_SEPARATOR)
+ return ids.mapNotNull { realm.findById(it) }
+ }
+
}
\ No newline at end of file
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 6b8d81f9..c2c48e5f 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
@@ -2,11 +2,13 @@ package net.pokeranalytics.android.ui.fragment
import android.app.Activity
import android.content.Intent
+import android.content.res.ColorStateList
+import android.os.Build
import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
+import android.view.*
+import androidx.appcompat.widget.Toolbar
import io.realm.Realm
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
@@ -19,16 +21,14 @@ import net.pokeranalytics.android.databinding.FragmentStatsBinding
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.realm.ComputableResult
-import net.pokeranalytics.android.model.realm.Filter
-import net.pokeranalytics.android.model.realm.Result
-import net.pokeranalytics.android.model.realm.UserConfig
+import net.pokeranalytics.android.model.realm.*
import net.pokeranalytics.android.ui.fragment.components.FilterableFragment
import net.pokeranalytics.android.ui.fragment.components.RealmAsyncListener
import net.pokeranalytics.android.ui.fragment.report.ComposableTableReportFragment
import net.pokeranalytics.android.ui.modules.filter.FilterActivityRequestCode
import net.pokeranalytics.android.ui.modules.filter.FilterableType
import net.pokeranalytics.android.ui.modules.filter.FiltersActivity
+import net.pokeranalytics.android.ui.modules.settings.TransactionFilterActivity
import timber.log.Timber
import java.util.*
@@ -36,6 +36,8 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
private lateinit var tableReportFragment: ComposableTableReportFragment
+ private var transactionFilterMenuItem: MenuItem? = null
+
companion object {
/**
@@ -73,6 +75,7 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
addRealmChangeListener(this, UserConfig::class.java)
addRealmChangeListener(this, ComputableResult::class.java)
+ addRealmChangeListener(this, Transaction::class.java)
}
private fun initUI() {
@@ -83,27 +86,41 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
this.tableReportFragment = fragment
}
-// override val observedEntities: List> = listOf(ComputableResult::class.java)
-
-// override fun entitiesChanged(clazz: Class, results: RealmResults) {
-// Timber.d("Entities changes, launch stats computation, size = ${results.size}")
-// val cr = results as RealmResults
-// cr.forEach {
-// Timber.d("### buyin = ${it.ratedBuyin} ### net result = ${it.ratedNet}")
-// }
-// this.launchStatComputation()
-// }
-
-// override fun convertReportIntoRepresentables(report: Report): ArrayList {
-// val rows: ArrayList = ArrayList()
-// report.results.forEach { result ->
-// rows.add(CustomizableRowRepresentable(title = result.group.name))
-// result.group.stats?.forEach { stat ->
-// rows.add(StatRow(stat, result.computedStat(stat), result.group.name))
-// }
-// }
-// return rows
-// }
+ override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+ super.onCreateOptionsMenu(menu, inflater)
+ view?.findViewById(R.id.toolbar)?.let { toolbar ->
+ toolbar.menu.removeItem(R.id.menu_item_transaction_filter)
+ transactionFilterMenuItem = toolbar.menu?.add(0, R.id.menu_item_transaction_filter, 1, R.string.filter)
+ transactionFilterMenuItem?.setIcon(R.drawable.baseline_payment_24)
+ transactionFilterMenuItem?.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
+ setTransactionFilterItemColor()
+ }
+ }
+
+ private fun setTransactionFilterItemColor() {
+ context?.let {
+ val userConfig = UserConfig.getConfiguration(getRealm())
+ val color = if (userConfig.transactionTypeIds.isNotEmpty()) R.color.red else R.color.white
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ this.transactionFilterMenuItem?.iconTintList = ColorStateList.valueOf(it.getColor(color))
+ }
+ }
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.menu_item_transaction_filter -> {
+ showTransactionFilter()
+ }
+ }
+ return super.onOptionsItemSelected(item)
+ }
+
+ private fun showTransactionFilter() {
+ context?.let {
+ TransactionFilterActivity.newInstance(it)
+ }
+ }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
@@ -130,18 +147,11 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
// Business
override fun asyncListenedEntityChange(realm: Realm) {
-
if (isAdded) { // Fixes: java.lang.IllegalStateException Fragment StatisticsFragment{9d3e5ec} not attached to a context.
launchStatComputation()
}
-// val report = createSessionGroupsAndStartCompute(realm)
-// tableReportFragment.report = report
-//
-// GlobalScope.launch(Dispatchers.Main) {
-// tableReportFragment.showResults()
-// }
-
+ setTransactionFilterItemColor()
}
/**
@@ -149,7 +159,7 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
*/
private fun launchStatComputation() {
- GlobalScope.launch(coroutineContext) {
+ CoroutineScope(coroutineContext).launch {
val async = GlobalScope.async {
val s = Date()
@@ -238,6 +248,8 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
computedStats.addAll(tStats)
options.stats = computedStats
+ options.includedTransactions = UserConfig.getConfiguration(realm).transactionTypes(realm)
+
return Calculator.computeGroups(realm, listOf(allSessionGroup, cgSessionGroup, tSessionGroup), options)
}
diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/FilterableFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/FilterableFragment.kt
index 81fab871..ccfcd16c 100644
--- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/FilterableFragment.kt
+++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/FilterableFragment.kt
@@ -27,8 +27,7 @@ import net.pokeranalytics.android.util.Preferences
* - Listen for INTENT_FILTER_UPDATE_FILTER_UI
* -
*/
-open class FilterableFragment : RealmFragment(),
- FilterHandler {
+open class FilterableFragment : RealmFragment(), FilterHandler {
override var currentFilterable: FilterableType = FilterableType.ALL
set(value) {
@@ -83,7 +82,7 @@ open class FilterableFragment : RealmFragment(),
super.onCreateOptionsMenu(menu, inflater)
view?.findViewById(R.id.toolbar)?.let { toolbar ->
toolbar.menu.removeItem(R.id.menu_item_filter)
- filterMenuItem = toolbar.menu?.add(0, R.id.menu_item_filter, 0, R.string.filter)
+ filterMenuItem = toolbar.menu?.add(0, R.id.menu_item_filter, 10, R.string.filter)
filterMenuItem?.setIcon(R.drawable.ic_outline_filter_list)
filterMenuItem?.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
}
diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt
index a9de0bbb..a61491e3 100644
--- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt
+++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt
@@ -76,18 +76,6 @@ open class RealmFragment : BaseFragment() {
this.observedRealmResults.add(results)
}
-// fun listenRealmChanges(listener: RealmAsyncListener, clazz: Class) {
-//
-// this.changeListener = listener
-//
-// this.realmResults = this.realm.where(clazz).findAllAsync()
-// this.realmResults?.addChangeListener { t, _ ->
-// Timber.d("Realm changes: ${realmResults?.size}, $this")
-// this.changeListener?.asyncListenedEntityChange(t.realm)
-// }
-//
-// }
-
override fun onDestroyView() {
super.onDestroyView()
diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/DealtHandsPerHourFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/DealtHandsPerHourFragment.kt
index 2a874ad9..060bef31 100644
--- a/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/DealtHandsPerHourFragment.kt
+++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/DealtHandsPerHourFragment.kt
@@ -34,7 +34,7 @@ class DealtHandsPerHourFragment : RealmFragment() {
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menu.clear()
- inflater.inflate(R.menu.toolbar_dealt_hands_per_hour, menu)
+ inflater.inflate(R.menu.toolbar_save, menu)
super.onCreateOptionsMenu(menu, inflater)
}
diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterActivity.kt
new file mode 100644
index 00000000..8de5539f
--- /dev/null
+++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterActivity.kt
@@ -0,0 +1,25 @@
+package net.pokeranalytics.android.ui.modules.settings
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import net.pokeranalytics.android.R
+import net.pokeranalytics.android.ui.activity.components.BaseActivity
+
+class TransactionFilterActivity : BaseActivity() {
+
+ companion object {
+
+ fun newInstance(context: Context) {
+ val intent = Intent(context, TransactionFilterActivity::class.java)
+ context.startActivity(intent)
+ }
+
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_transaction_filter)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterFragment.kt
new file mode 100644
index 00000000..85f82ac2
--- /dev/null
+++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterFragment.kt
@@ -0,0 +1,132 @@
+package net.pokeranalytics.android.ui.modules.settings
+
+import android.content.Context
+import android.os.Bundle
+import android.view.*
+import androidx.lifecycle.ViewModelProvider
+import androidx.recyclerview.widget.LinearLayoutManager
+import io.realm.kotlin.where
+import net.pokeranalytics.android.R
+import net.pokeranalytics.android.databinding.FragmentTransactionFilterBinding
+import net.pokeranalytics.android.model.realm.TransactionType
+import net.pokeranalytics.android.model.realm.UserConfig
+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.RealmFragment
+import net.pokeranalytics.android.ui.view.RowRepresentable
+import net.pokeranalytics.android.ui.view.RowViewType
+
+class TransactionFilterFragment : RealmFragment(), StaticRowRepresentableDataSource,
+ RowRepresentableDelegate {
+
+ private var _binding: FragmentTransactionFilterBinding? = null
+ private val binding get() = _binding!!
+
+ private lateinit var model: TransactionFilterViewModel
+
+ private lateinit var rowRepresentableAdapter: RowRepresentableAdapter
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ this.model = activity?.run {
+ ViewModelProvider(this).get(TransactionFilterViewModel::class.java)
+ } ?: throw Exception("Invalid Activity")
+
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ super.onCreateView(inflater, container, savedInstanceState)
+ _binding = FragmentTransactionFilterBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ initUI()
+ initData()
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+ menu.clear()
+ inflater.inflate(R.menu.toolbar_save, menu)
+ super.onCreateOptionsMenu(menu, inflater)
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.save -> save()
+ }
+ return true
+ }
+
+ private fun initUI() {
+ setDisplayHomeAsUpEnabled(true)
+
+ val viewManager = LinearLayoutManager(requireContext())
+ this.binding.recyclerView.apply {
+ setHasFixedSize(true)
+ layoutManager = viewManager
+ }
+
+ this.rowRepresentableAdapter = RowRepresentableAdapter(this, this)
+ this.binding.recyclerView.adapter = rowRepresentableAdapter
+
+ }
+
+ private fun initData() {
+ val transactionTypes = getRealm().where()
+ .notEqualTo("kind", TransactionType.Value.DEPOSIT.uniqueIdentifier)
+ .notEqualTo("kind", TransactionType.Value.WITHDRAWAL.uniqueIdentifier)
+ .notEqualTo("kind", TransactionType.Value.TRANSFER.uniqueIdentifier)
+ .notEqualTo("kind", TransactionType.Value.STACKING_INCOMING.uniqueIdentifier)
+ .notEqualTo("kind", TransactionType.Value.STACKING_OUTGOING.uniqueIdentifier)
+ .sort("name")
+ .findAll()
+ this.model.transactionTypes = transactionTypes
+
+ val userConfig = UserConfig.getConfiguration(this.getRealm())
+ this.model.selectedTransactionTypes = userConfig.transactionTypes(getRealm()).toMutableSet()
+
+ }
+
+ private fun save() {
+ getRealm().executeTransaction { realm ->
+ val userConfig = UserConfig.getConfiguration(realm)
+ userConfig.setTransactionTypeIds(this.model.selectedTransactionTypes)
+ realm.copyToRealmOrUpdate(userConfig)
+ }
+ this.activity?.finish()
+ }
+
+ override fun adapterRows(): List {
+ return this.model.transactionTypes.map { TransactionTypeSwitchRow(it) }
+ }
+
+ override fun boolForRow(row: RowRepresentable): Boolean {
+ val transactionTypeRow = row as TransactionTypeSwitchRow
+ return this.model.selectedTransactionTypes.contains(transactionTypeRow.transactionType)
+ }
+
+ override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
+ val isChecked = value as Boolean
+ val transactionTypeRow = row as TransactionTypeSwitchRow
+ this.model.selectTransactionType(transactionTypeRow.transactionType, isChecked)
+ }
+
+}
+
+class TransactionTypeSwitchRow(val transactionType: TransactionType) : RowRepresentable {
+
+ override fun getDisplayName(context: Context): String {
+ return transactionType.name
+ }
+
+ override val viewType: Int = RowViewType.TITLE_SWITCH.identifier
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterViewModel.kt
new file mode 100644
index 00000000..864d7f93
--- /dev/null
+++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterViewModel.kt
@@ -0,0 +1,19 @@
+package net.pokeranalytics.android.ui.modules.settings
+
+import androidx.lifecycle.ViewModel
+import net.pokeranalytics.android.model.realm.TransactionType
+
+class TransactionFilterViewModel : ViewModel() {
+
+ lateinit var transactionTypes: List
+
+ var selectedTransactionTypes: MutableSet = mutableSetOf()
+
+ fun selectTransactionType(transactionType: TransactionType, selected: Boolean) {
+ when(selected) {
+ true -> this.selectedTransactionTypes.add(transactionType)
+ false -> this.selectedTransactionTypes.remove(transactionType)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/pokeranalytics/android/util/Global.kt b/app/src/main/java/net/pokeranalytics/android/util/Global.kt
index 85ffc3b2..400362d5 100644
--- a/app/src/main/java/net/pokeranalytics/android/util/Global.kt
+++ b/app/src/main/java/net/pokeranalytics/android/util/Global.kt
@@ -4,3 +4,4 @@ const val NULL_TEXT: String = "--"
const val RANDOM_PLAYER: String = "☺︎"
const val FFMPEG_DESCRIPTOR_FILE = "descriptor.txt"
const val BLIND_SEPARATOR: String = "/"
+const val UUID_SEPARATOR: String = ","
diff --git a/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt b/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt
index 4fe2ac29..853ffa13 100644
--- a/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt
+++ b/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt
@@ -47,7 +47,7 @@ class Preferences {
PATCH_NEGATIVE_LIMITS("negativeLimits"),
PATCH_STAKES("patchStakes"),
CLEAN_BLINDS_FILTERS("deleteBlindsFilters"),
- SHOW_INAPP_BADGES("showInAppBadges"),
+ SHOW_IN_APP_BADGES("showInAppBadges"),
LAST_CALENDAR_BADGE_DATE("lastCalendarBadgeDate")
}
@@ -101,6 +101,18 @@ class Preferences {
companion object {
+ fun setStringSet(key: PreferenceKey, value: MutableSet, context: Context) {
+ val preferences = PreferenceManager.getDefaultSharedPreferences(context)
+ val editor = preferences.edit()
+ editor.putStringSet(key.identifier, value)
+ editor.apply()
+ }
+
+ fun getStringSet(key: Keys, context: Context): MutableSet? {
+ val preferences = PreferenceManager.getDefaultSharedPreferences(context)
+ return preferences.getStringSet(key.identifier, null)
+ }
+
fun setString(key: PreferenceKey, value: String, context: Context) {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val editor = preferences.edit()
@@ -232,14 +244,6 @@ class Preferences {
}
}
-// fun executeOnceInThread(key: Keys, context: Context, executable: () -> Unit) {
-//
-// if (!getBoolean(key, context)) {
-// Thread { executable.invoke() }
-// setBoolean(key, true, context)
-// }
-// }
-
fun setResultCaptureType(bankroll: Bankroll, type: ResultCaptureType, context: Context) {
val key = "${Keys.BANKROLL_RESULT_CAPTURE_TYPE}${bankroll.id}"
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
@@ -307,11 +311,11 @@ class Preferences {
}
fun showInAppBadges(context: Context): Boolean {
- return getBoolean(Keys.SHOW_INAPP_BADGES, context, true)
+ return getBoolean(Keys.SHOW_IN_APP_BADGES, context, true)
}
fun setShowInAppBadges(context: Context, show: Boolean) {
- setBoolean(Keys.SHOW_INAPP_BADGES, show, context)
+ setBoolean(Keys.SHOW_IN_APP_BADGES, show, context)
}
fun lastCalendarBadgeDate(context: Context): Long {
diff --git a/app/src/main/res/drawable-xxhdpi/baseline_payment_24.xml b/app/src/main/res/drawable-xxhdpi/baseline_payment_24.xml
new file mode 100644
index 00000000..9c0fb1f1
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/baseline_payment_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_transaction_filter.xml b/app/src/main/res/layout/activity_transaction_filter.xml
new file mode 100644
index 00000000..207e1b65
--- /dev/null
+++ b/app/src/main/res/layout/activity_transaction_filter.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml
index e1d3e396..dce49f7f 100644
--- a/app/src/main/res/layout/fragment_settings.xml
+++ b/app/src/main/res/layout/fragment_settings.xml
@@ -1,7 +1,6 @@
@@ -25,33 +24,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_transaction_filter.xml b/app/src/main/res/layout/fragment_transaction_filter.xml
new file mode 100644
index 00000000..9e8cb033
--- /dev/null
+++ b/app/src/main/res/layout/fragment_transaction_filter.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/toolbar_dealt_hands_per_hour.xml b/app/src/main/res/menu/toolbar_save.xml
similarity index 100%
rename from app/src/main/res/menu/toolbar_dealt_hands_per_hour.xml
rename to app/src/main/res/menu/toolbar_save.xml
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 382fc861..6771e517 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -787,5 +787,6 @@
]]>
+ Filtre de transactions
diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml
index 6e5acd9b..38d38849 100644
--- a/app/src/main/res/values/ids.xml
+++ b/app/src/main/res/values/ids.xml
@@ -1,4 +1,5 @@
+
\ 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 cbc792c5..e71cbbd6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -831,5 +831,6 @@
This screen will show where you perform the best when you\'ll have more data. You also can create custom reports using the top right button.
+ Transaction Filter