diff --git a/app/build.gradle b/app/build.gradle index a60e3a05..e633f19c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -121,7 +121,7 @@ dependencies { testImplementation 'com.android.support.test:rules:1.0.2' //testImplementation 'androidx.test.espresso:espresso-core:3.1.0' - + implementation "com.ibm.icu:icu4j:53.1" } apply plugin: 'com.google.gms.google-services' \ No newline at end of file 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 6f5baf3c..b9bed8d4 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 @@ -71,8 +71,10 @@ class Query { val queryLast = this.conditions.filter { it is QueryCondition.Last }.firstOrNull() - queryLast?.let { - return realmQuery.limit((it as QueryCondition.Last).singleValue.toLong()) + queryLast?.let {qc -> + (qc as QueryCondition.Last).singleValue?.let { + return realmQuery.limit(it.toLong()) + } } return realmQuery } 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 7ed57873..2b93ce3c 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 @@ -1,6 +1,7 @@ package net.pokeranalytics.android.model.filter import android.content.Context +import com.ibm.icu.text.RuleBasedNumberFormat import io.realm.Realm import io.realm.RealmQuery import io.realm.RealmResults @@ -128,13 +129,13 @@ sealed class QueryCondition : FilterElementRow { abstract class SingleValue: ListOfValues() where T:Comparable { override var listOfValues = ArrayList() - abstract var singleValue : T + abstract var singleValue : T? } abstract class ListOfDouble: ListOfValues() { open var sign: Int = 1 override var operator: Operator = Operator.ANY - override var listOfValues = arrayListOf(0.0) + override var listOfValues : ArrayList = arrayListOf() override fun updateValueBy(filterCondition: FilterCondition) { super.updateValueBy(filterCondition) listOfValues = filterCondition.getValues() @@ -149,7 +150,7 @@ sealed class QueryCondition : FilterElementRow { abstract class ListOfInt: ListOfValues() { override var operator: Operator = Operator.ANY - override var listOfValues = arrayListOf(0) + override var listOfValues : ArrayList = arrayListOf() override fun updateValueBy(filterCondition: FilterCondition) { super.updateValueBy(filterCondition) listOfValues = filterCondition.getValues() @@ -182,11 +183,11 @@ sealed class QueryCondition : FilterElementRow { override var listOfValues = ArrayList() - override var singleValue: Date - get() { return listOfValues.firstOrNull() ?: Date() } + override var singleValue: Date? + get() { return listOfValues.firstOrNull() } set(value) { listOfValues.removeAll(this.listOfValues) - listOfValues.add(value) + value?.let { listOfValues.add(it) } } override fun updateValueBy(filterCondition: FilterCondition) { @@ -203,11 +204,11 @@ sealed class QueryCondition : FilterElementRow { return prefix+value.toString() } - override var singleValue: Int - get() { return listOfValues.firstOrNull() ?: 0 } + override var singleValue: Int? + get() { return listOfValues.firstOrNull() } set(value) { listOfValues.removeAll(this.listOfValues) - listOfValues.add(value) + value?.let { listOfValues.add(it) } } override fun updateValueBy(filterCondition: FilterCondition) { @@ -389,8 +390,8 @@ sealed class QueryCondition : FilterElementRow { val prefix = this.resId?.let { context.getString(it) + " " } ?: "" - //TODO add a int helper to display 1st, 2nd, 3rd, 4th, etc. - return prefix + value.toString() + val nf = RuleBasedNumberFormat(Locale.getDefault(), RuleBasedNumberFormat.ORDINAL) + return prefix + nf.format(value) } } @@ -471,9 +472,9 @@ sealed class QueryCondition : FilterElementRow { class Duration: SingleInt() { override var operator = Operator.EQUALS - var minutes:Int + var minutes:Int? get() { return singleValue } - set(value) { listOfValues = arrayListOf(value) } + set(value) { singleValue = value } override val viewType: Int = RowViewType.TITLE_VALUE_CHECK.ordinal override val bottomSheetType: BottomSheetType = BottomSheetType.DOUBLE_EDIT_TEXT @@ -482,14 +483,14 @@ sealed class QueryCondition : FilterElementRow { class StartedFromTime(startTime:Date = Date().startOfDay()): TimeQuery() { override var operator = Operator.MORE init { - this.listOfValues = arrayListOf(startTime) + this.listOfValues = arrayListOf() } } class EndedToTime(endTime:Date = Date().endOfDay()): TimeQuery() { override var operator = Operator.LESS init { - this.listOfValues = arrayListOf(endTime) + this.listOfValues = arrayListOf() } } @@ -550,11 +551,14 @@ sealed class QueryCondition : FilterElementRow { return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and().lessThanOrEqualTo(fieldName, calendar.time.endOfDay()) } is PastDay -> { - val startDate = Date() - val calendar = Calendar.getInstance() - calendar.time = startDate - calendar.add(Calendar.DAY_OF_YEAR, -singleValue) - return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and().lessThanOrEqualTo(fieldName, startDate.endOfDay()) + singleValue?.let { + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.add(Calendar.DAY_OF_YEAR, -it) + return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and().lessThanOrEqualTo(fieldName, startDate.endOfDay()) + } + return realmQuery } is DuringThisWeek -> { val startDate = Date() @@ -602,8 +606,8 @@ sealed class QueryCondition : FilterElementRow { return when (operator) { Operator.EQUALS -> { when (this) { - is SingleDate -> realmQuery.equalTo(fieldName, singleValue) - is SingleInt -> realmQuery.equalTo(fieldName, singleValue) + is SingleDate -> realmQuery.equalTo(fieldName, singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) + is SingleInt -> realmQuery.equalTo(fieldName, singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) is ListOfInt -> realmQuery.equalTo(fieldName, listOfValues.first()) is ListOfDouble -> realmQuery.equalTo(fieldName, listOfValues.first() * sign) is ListOfString -> realmQuery.equalTo(fieldName, listOfValues.first()) @@ -612,8 +616,8 @@ sealed class QueryCondition : FilterElementRow { } Operator.MORE -> { when (this) { - is SingleDate -> realmQuery.greaterThanOrEqualTo(fieldName, singleValue) - is SingleInt -> realmQuery.greaterThanOrEqualTo(fieldName, singleValue) + is SingleDate -> realmQuery.greaterThanOrEqualTo(fieldName, singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) + is SingleInt -> realmQuery.greaterThanOrEqualTo(fieldName, singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) is ListOfInt -> realmQuery.greaterThanOrEqualTo(fieldName, listOfValues.first()) is ListOfDouble -> realmQuery.greaterThanOrEqualTo(fieldName, listOfValues.first() * sign) else -> realmQuery @@ -621,8 +625,8 @@ sealed class QueryCondition : FilterElementRow { } Operator.LESS -> { when (this) { - is SingleDate -> realmQuery.lessThanOrEqualTo(fieldName, singleValue) - is SingleInt -> realmQuery.lessThanOrEqualTo(fieldName, singleValue) + is SingleDate -> realmQuery.lessThanOrEqualTo(fieldName, singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) + is SingleInt -> realmQuery.lessThanOrEqualTo(fieldName, singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) is ListOfInt -> realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first()) is ListOfDouble -> realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first() * sign) else -> realmQuery diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt index d0ca264d..432de572 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt @@ -19,8 +19,8 @@ open class FilterCondition() : RealmObject() { this.filterName ?: throw PokerAnalyticsException.FilterElementUnknownName this.operator = row.operator.ordinal when (row) { - is QueryCondition.SingleInt -> this.setValue(row.singleValue) - is QueryCondition.SingleDate -> this.setValue(row.singleValue) + is QueryCondition.SingleInt -> this.setValue(row.singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) + is QueryCondition.SingleDate -> this.setValue(row.singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) is QueryCondition.ListOfDouble -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfDouble).listOfValues }) is QueryCondition.ListOfInt -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfInt).listOfValues }) is QueryCondition.ListOfString -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfString).listOfValues }) 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 b5cff020..6e114f1e 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 @@ -21,6 +21,7 @@ import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment import net.pokeranalytics.android.ui.helpers.DateTimePickerManager import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow @@ -78,14 +79,20 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataS when (row) { is QueryCondition.DateQuery -> DateTimePickerManager.create(requireContext(), row, this, row.singleValue, onlyDate = !row.showTime, onlyTime = row.showTime) is QueryCondition.Duration -> { - val hours = if (row.minutes / 60 > 0) (row.minutes / 60).toString() else "" - val minutes = if (row.minutes % 60 > 0) (row.minutes % 60).toString() else "" - val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) + var hours: String? = null + var minutes: String? = null + row.minutes?.let { + hours = if (it / 60 > 0) (it / 60).toString() else null + minutes = if (it % 60 > 0) (it % 60).toString() else null + } + val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) BottomSheetFragment.create(fragmentManager, row, this, data, true) } - is QueryCondition.ListOfValues<*> -> { - val valueAsString = row.listOfValues.firstOrNull()?.toString() ?: "" + var valueAsString: String? = null + row.listOfValues.firstOrNull()?.let { + valueAsString = row.listOfValues.firstOrNull()?.toString() + } val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) BottomSheetFragment.create(fragmentManager, row, this, data, true) } @@ -93,12 +100,12 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataS } override fun stringForRow(row: RowRepresentable): String { - return when (row) { - is QueryCondition.DateQuery -> if (row.showTime) row.singleValue.shortTime() else row.singleValue.shortDate() - is QueryCondition.Duration -> row.minutes.toMinutes(requireContext()) - is QueryCondition.ListOfValues<*> -> row.listOfValues.firstOrNull()?.toString() ?: NULL_TEXT + return when (row) { + is QueryCondition.DateQuery -> if (row.showTime) row.singleValue?.shortTime() else row.singleValue?.shortDate() + is QueryCondition.Duration -> row.minutes?.toMinutes(requireContext()) + is QueryCondition.ListOfValues<*> -> row.listOfValues.firstOrNull()?.toString() else -> super.stringForRow(row) - } + }?: NULL_TEXT } override fun isSelected(row: RowRepresentable): Boolean { @@ -110,28 +117,39 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataS Timber.d("onRowValueChanged: $row $value") when (row) { - is QueryCondition.DateQuery -> row.singleValue = if (value != null && value is Date) value else Date() + is QueryCondition.DateQuery -> row.singleValue = if (value != null && value is Date) value else null is QueryCondition.Duration -> { if (value is ArrayList<*>) { - val hours = try { - (value[0] as String? ?: "0").toInt() + val hours: Int? = try { + (value[0] as String?)?.toInt() } catch (e: Exception) { - 0 + null } val minutes = try { - (value[1] as String? ?: "0").toInt() + (value[1] as String?)?.toInt() } catch (e: Exception) { - 0 + null } - - row.minutes = hours * 60 + minutes + if (hours != null && minutes != null) { + row.minutes = hours * 60 + minutes + } + if (hours != null) { + row.minutes = hours * 60 + } + if (minutes != null) { + row.minutes = minutes + } } else { - row.minutes = 0 + row.minutes = null } } - is QueryCondition.SingleInt -> row.singleValue = if (value != null && value is String) value.toInt() else 0 - is QueryCondition.ListOfDouble-> row.listOfValues = arrayListOf(if (value != null && value is String) value.toDouble() else 0.0) - is QueryCondition.ListOfInt-> row.listOfValues = arrayListOf(if (value != null && value is String) value.toInt() else 0) + is QueryCondition.SingleInt -> row.singleValue = if (value != null && value is String) value.toInt() else null + is QueryCondition.ListOfDouble-> row.listOfValues = arrayListOf().apply { + if (value != null && value is String) this.add(value.toDouble()) + } + is QueryCondition.ListOfInt-> row.listOfValues = arrayListOf().apply { + if (value != null && value is String) this.add(value.toInt()) + } } // Remove the row before updating the selected rows list