From e8750d60cd4f953366fe781c67aa1a288053f82e Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 14:25:00 +0200 Subject: [PATCH 01/19] Clean imports --- .../net/pokeranalytics/android/model/filter/QueryCondition.kt | 2 -- 1 file changed, 2 deletions(-) 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 0ad656f7..43608d54 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 @@ -6,9 +6,7 @@ import net.pokeranalytics.android.exceptions.PokerAnalyticsException import net.pokeranalytics.android.model.realm.FilterCondition import net.pokeranalytics.android.model.realm.FilterElementBlind import net.pokeranalytics.android.model.realm.Session -import java.time.* import java.util.* -import java.time.temporal.TemporalQueries.zoneId From 344228d83fef157b39c32573b23a5934ef3bcc33 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 15:18:11 +0200 Subject: [PATCH 02/19] Clean code --- .../res/layout/bottom_sheet_game_list.xml | 39 ++----------------- 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/app/src/main/res/layout/bottom_sheet_game_list.xml b/app/src/main/res/layout/bottom_sheet_game_list.xml index 7f5a61b1..ec47ed64 100644 --- a/app/src/main/res/layout/bottom_sheet_game_list.xml +++ b/app/src/main/res/layout/bottom_sheet_game_list.xml @@ -8,9 +8,9 @@ @@ -22,41 +22,8 @@ android:layout_gravity="center" android:orientation="horizontal" app:chipSpacingHorizontal="16dp" - app:singleSelection="true"> - - - - + app:singleSelection="true" /> + Date: Tue, 9 Apr 2019 15:18:27 +0200 Subject: [PATCH 03/19] Improve UI --- .../components/bottomsheet/BottomSheetListGameFragment.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt index 160e0cc1..919acd05 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt @@ -3,6 +3,7 @@ package net.pokeranalytics.android.ui.fragment.components.bottomsheet import android.os.Bundle import android.view.LayoutInflater import android.view.View +import androidx.core.view.get import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.chip.Chip import io.realm.RealmResults @@ -13,6 +14,7 @@ import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorExcep import net.pokeranalytics.android.model.Limit import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.util.extensions.px /** * Bottom Sheet List Game Fragment @@ -73,6 +75,8 @@ class BottomSheetListGameFragment : BottomSheetListFragment() { val chip = Chip(requireContext()) chip.id = it.ordinal chip.text = it.shortName + chip.chipStartPadding = 8f.px + chip.chipEndPadding = 8f.px chip.isChecked = it.ordinal == limit chipGroup.addView(chip) } @@ -81,6 +85,10 @@ class BottomSheetListGameFragment : BottomSheetListFragment() { values[0] = i } + if (limit == null) { + (chipGroup[0] as Chip).isChecked = true + } + val viewManager2 = LinearLayoutManager(requireContext()) dataAdapter = RowRepresentableAdapter(this, this) From 75e573c01a5bdcaeba8cf517ad5bda97f9d0a775 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 15:19:55 +0200 Subject: [PATCH 04/19] Add toMinutes methods --- .../util/extensions/NumbersExtension.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 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 77287988..88330925 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 @@ -1,5 +1,7 @@ package net.pokeranalytics.android.util.extensions +import android.content.Context +import net.pokeranalytics.android.R import java.text.DecimalFormat import java.text.NumberFormat import java.util.* @@ -35,6 +37,23 @@ fun Double.formattedHourlyDuration() : String { return (this * 1000 * 3600).toLong().toMinutes() } +// Return the time from minutes to hours:minutes +fun Int.toMinutes(context: Context) : String { + val hours = this / 60 + val minutesLeft = this % 60 + var duration = "" + + if (hours < 1) { + duration += "$minutesLeft ${context.getString(if (minutesLeft > 1) R.string.mins else R.string.min)}" + } else { + duration += hours.toString() + duration += ":" + duration += if (minutesLeft < 10) "0$minutesLeft" else minutesLeft.toString() + } + + return duration +} + // Return the time from milliseconds to hours:minutes fun Long.toMinutes() : String { val totalMinutes = this / (1000 * 60) @@ -45,5 +64,4 @@ fun Long.toMinutes() : String { duration += ":" duration += if (minutesLeft < 10) "0$minutesLeft" else minutesLeft.toString() return duration - } \ No newline at end of file From 5b42082aa06fd01602c3e20a009bbe5c521c3d5d Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Tue, 9 Apr 2019 15:40:14 +0200 Subject: [PATCH 05/19] add dynamic date queryCondition and unitTests --- .../filter/DateFilterInstrumentedUnitTest.kt | 218 ++++++++++++++++++ .../android/model/filter/QueryCondition.kt | 41 +++- .../android/model/realm/Session.kt | 1 + 3 files changed, 258 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt index 7f347618..2fd4b380 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt @@ -8,6 +8,7 @@ import net.pokeranalytics.android.model.realm.FilterCondition import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow +import net.pokeranalytics.android.util.extensions.startOfDay import org.junit.Assert import org.junit.Test import org.junit.runner.RunWith @@ -150,6 +151,223 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { } } + @Test + fun testTodayFilter() { + + val realm = this.mockRealm + realm.beginTransaction() + + val s1 = Session.testInstance(100.0, false) + + val cal = Calendar.getInstance() + cal.time = Date() + cal.add(Calendar.HOUR_OF_DAY, -72) + Session.testInstance(100.0, false, cal.time) + + realm.commitTransaction() + + Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 2) + + val sessions = Filter.queryOn(realm, arrayListOf(QueryCondition.TODAY)) + + Assert.assertEquals(1, sessions.size) + sessions[0]?.run { + Assert.assertEquals(s1.id, this.id) + } + } + + @Test + fun testTodayNoonFilter() { + + val realm = this.mockRealm + realm.beginTransaction() + + val cal = Calendar.getInstance() + cal.time = Date().startOfDay() + val s1 = Session.testInstance(100.0, false, cal.time) + + cal.add(Calendar.HOUR_OF_DAY, -72) + Session.testInstance(100.0, false, cal.time) + + realm.commitTransaction() + + Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 2) + + val sessions = Filter.queryOn(realm, arrayListOf(QueryCondition.TODAY)) + + Assert.assertEquals(1, sessions.size) + sessions[0]?.run { + Assert.assertEquals(s1.id, this.id) + } + } + + + @Test + fun testYesterdayFilter() { + + val realm = this.mockRealm + realm.beginTransaction() + val cal = Calendar.getInstance() + cal.time = Date() + cal.add(Calendar.HOUR_OF_DAY, -24) + val s1 = Session.testInstance(100.0, false, cal.time) + + Session.testInstance(100.0, false) + + cal.add(Calendar.HOUR_OF_DAY, -72) + Session.testInstance(100.0, false, cal.time) + + realm.commitTransaction() + + Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 3) + + val sessions = Filter.queryOn(realm, arrayListOf(QueryCondition.YESTERDAY)) + + Assert.assertEquals(1, sessions.size) + sessions[0]?.run { + Assert.assertEquals(s1.id, this.id) + } + } + + @Test + fun testYesterdayNoonFilter() { + + val realm = this.mockRealm + realm.beginTransaction() + val cal = Calendar.getInstance() + cal.time = Date() + cal.add(Calendar.HOUR_OF_DAY, -24) + val s1 = Session.testInstance(100.0, false, cal.time.startOfDay()) + + Session.testInstance(100.0, false) + + cal.add(Calendar.HOUR_OF_DAY, -72) + Session.testInstance(100.0, false, cal.time) + + realm.commitTransaction() + + Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 3) + + val sessions = Filter.queryOn(realm, arrayListOf(QueryCondition.YESTERDAY)) + + Assert.assertEquals(1, sessions.size) + sessions[0]?.run { + Assert.assertEquals(s1.id, this.id) + } + } + + @Test + fun testTodayAndYesterdayFilter() { + + val realm = this.mockRealm + realm.beginTransaction() + val cal = Calendar.getInstance() + cal.time = Date() + cal.add(Calendar.HOUR_OF_DAY, -24) + val s1 = Session.testInstance(100.0, false, cal.time) + + val s2 = Session.testInstance(100.0, false) + + cal.add(Calendar.HOUR_OF_DAY, -72) + Session.testInstance(100.0, false, cal.time) + + realm.commitTransaction() + + Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 3) + + val sessions = Filter.queryOn(realm, arrayListOf(QueryCondition.TODAY_AND_YESTERDAY)) + + Assert.assertEquals(2, sessions.size) + Assert.assertTrue(sessions.containsAll(arrayListOf(s1,s2))) + } + + @Test + fun testThisYear() { + + val realm = this.mockRealm + realm.beginTransaction() + val s1 = Session.testInstance(100.0, false) + + val cal = Calendar.getInstance() + cal.time = Date() + cal.add(Calendar.HOUR_OF_DAY, -24) + val s2 = Session.testInstance(100.0, false, cal.time) + + cal.add(Calendar.HOUR_OF_DAY, -72) + val s3 = Session.testInstance(100.0, false, cal.time) + + cal.add(Calendar.YEAR, -4) + Session.testInstance(100.0, false, cal.time) + + cal.add(Calendar.YEAR, -1) + Session.testInstance(100.0, false, cal.time) + + realm.commitTransaction() + + Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 5) + + val sessions = Filter.queryOn(realm, arrayListOf(QueryCondition.THIS_YEAR)) + + Assert.assertEquals(3, sessions.size) + Assert.assertTrue(sessions.containsAll(arrayListOf(s1,s2, s3))) + } + + @Test + fun testThisMonth() { + + val realm = this.mockRealm + realm.beginTransaction() + val s1 = Session.testInstance(100.0, false) + + val cal = Calendar.getInstance() + cal.time = Date() + cal.set(Calendar.DAY_OF_MONTH, 1) + cal.time = cal.time.startOfDay() + val s2 = Session.testInstance(100.0, false, cal.time) + + cal.add(Calendar.HOUR_OF_DAY, -1) + Session.testInstance(100.0, false, cal.time) + + cal.add(Calendar.MONTH, -1) + Session.testInstance(100.0, false, cal.time) + + cal.add(Calendar.YEAR, -1) + Session.testInstance(100.0, false, cal.time) + + realm.commitTransaction() + + Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 5) + + val sessions = Filter.queryOn(realm, arrayListOf(QueryCondition.THIS_MONTH)) + + Assert.assertEquals(2, sessions.size) + Assert.assertTrue(sessions.containsAll(arrayListOf(s1,s2))) + } + + @Test + fun testThisWeek() { + + val realm = this.mockRealm + realm.beginTransaction() + val s1 = Session.testInstance(100.0, false) + + val cal = Calendar.getInstance() + cal.time = Date() + cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1) + cal.time = cal.time.startOfDay() + cal.add(Calendar.HOUR_OF_DAY, -1) + Session.testInstance(100.0, false, cal.time) + + realm.commitTransaction() + + Assert.assertTrue(realm.where(Session::class.java).findAll().count() == 2) + + val sessions = Filter.queryOn(realm, arrayListOf(QueryCondition.THIS_WEEK)) + + Assert.assertEquals(1, sessions.size) + Assert.assertTrue(sessions.containsAll(arrayListOf(s1))) + } + @Test fun testStartedFomDateFilter() { 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 0ad656f7..c3f2e6aa 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 @@ -6,6 +6,8 @@ import net.pokeranalytics.android.exceptions.PokerAnalyticsException import net.pokeranalytics.android.model.realm.FilterCondition import net.pokeranalytics.android.model.realm.FilterElementBlind import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.util.extensions.endOfDay +import net.pokeranalytics.android.util.extensions.startOfDay import java.time.* import java.util.* import java.time.temporal.TemporalQueries.zoneId @@ -242,8 +244,43 @@ enum class QueryCondition(var operator: Operator? = null) { } query.`in`(fieldName, arrayOf(Calendar.SATURDAY, Calendar.SUNDAY)) } - TODAY, YESTERDAY, TODAY_AND_YESTERDAY, THIS_WEEK, THIS_MONTH, THIS_YEAR -> { - realmQuery + TODAY -> { + val startDate = Date() + realmQuery.between(fieldName, startDate.startOfDay(), startDate.endOfDay()) + } + TODAY_AND_YESTERDAY-> { + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.add(Calendar.HOUR_OF_DAY, -24) + realmQuery.between(fieldName, calendar.time.startOfDay(), startDate.endOfDay()) + } + YESTERDAY -> { + val calendar = Calendar.getInstance() + calendar.time = Date() + calendar.add(Calendar.HOUR_OF_DAY, -24) + realmQuery.between(fieldName, calendar.time.startOfDay(), calendar.time.endOfDay()) + } + THIS_WEEK -> { + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, Calendar.SUNDAY) + realmQuery.between(fieldName, calendar.time.startOfDay(), startDate.endOfDay()) + } + THIS_MONTH -> { + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.set(Calendar.DAY_OF_MONTH, 1) + realmQuery.between(fieldName, calendar.time.startOfDay(), startDate.endOfDay()) + } + THIS_YEAR -> { + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.set(Calendar.DAY_OF_YEAR, 1) + realmQuery.between(fieldName, calendar.time.startOfDay(), startDate.endOfDay()) } else -> { throw PokerAnalyticsException.QueryTypeUnhandled 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 a2bc23e0..076649d4 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 @@ -90,6 +90,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat DAY_OF_WEEK, WEEK_END, WEEK_DAY -> "dayOfWeek" MONTH -> "month" YEAR -> "year" + TODAY, YESTERDAY, TODAY_AND_YESTERDAY, THIS_YEAR, THIS_MONTH, THIS_WEEK -> "startDate" else -> null } } From d2f8d2e78d0f953e331c9d1c89bf391d058471c8 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 15:45:13 +0200 Subject: [PATCH 06/19] Add hour --- app/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a3d7ff6b..6b6f9a3e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,6 +3,7 @@ Please set a start date for the session + Hour From 9c0987e2e13e941c35a1e13ed03d7425359fe4aa Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 15:45:41 +0200 Subject: [PATCH 07/19] Add minute --- app/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6b6f9a3e..5e551563 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4,6 +4,7 @@ Please set a start date for the session Hour + Minute From 3b795f488565be8b1dbddec631227efb4f5c67a9 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 15:46:01 +0200 Subject: [PATCH 08/19] Improve Filters, work in progres --- .../android/model/filter/QueryCondition.kt | 4 +- .../ui/fragment/FilterDetailsFragment.kt | 52 ++++++++++++++++--- .../view/rowrepresentable/FilterElementRow.kt | 50 +++++++++++++++--- .../view/rowrepresentable/FilterSectionRow.kt | 2 +- 4 files changed, 90 insertions(+), 18 deletions(-) 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 43608d54..9abdfe1c 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 @@ -9,8 +9,6 @@ import net.pokeranalytics.android.model.realm.Session import java.util.* - - /** * Enum describing the way a query should be handled * Some queries requires a value to be checked upon through equals, in, more, less, between @@ -66,6 +64,8 @@ enum class QueryCondition(var operator: Operator? = null) { THIS_WEEK, THIS_MONTH, THIS_YEAR, + MORE_THAN_DURATION(Operator.MORE), + LESS_THAN_DURATION(Operator.LESS), CURRENCY, CURRENCY_CODE, 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 84476e86..e059aa6d 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 @@ -24,8 +24,10 @@ import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow +import net.pokeranalytics.android.util.extensions.toMinutes import timber.log.Timber import java.util.* +import kotlin.collections.ArrayList open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { @@ -64,9 +66,11 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta Timber.d("Row: $row") when (row) { - is FilterElementRow.ResultMoreThan -> { - val data = row.editingDescriptors(mapOf("defaultValue" to "")) - BottomSheetFragment.create(fragmentManager, row, this, data, null) + is FilterElementRow.DurationMoreThan -> { + 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)) + BottomSheetFragment.create(fragmentManager, row, this, data, true) } else -> { @@ -88,7 +92,6 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta selectedRows.add(row) } } - } } @@ -111,6 +114,13 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta rowRepresentableAdapter.refreshRow(row) } + override fun stringForRow(row: RowRepresentable): String { + return when (row) { + is FilterElementRow.DurationMoreThan -> row.minutes.toMinutes(requireContext()) + else -> super.stringForRow(row) + } + } + override fun isSelected(row: RowRepresentable): Boolean { return selectedRows.contains(row) } @@ -118,7 +128,37 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta override fun onRowValueChanged(value: Any?, row: RowRepresentable) { super.onRowValueChanged(value, row) Timber.d("onRowValueChanged: $row $value") - selectedRows.add(row as FilterElementRow) + + when (row) { + is FilterElementRow.DurationMoreThan -> { + if (value is ArrayList<*>) { + val hours = try { + (value[0] as String? ?: "0").toInt() + } catch (e: Exception) { + 0 + } + val minutes = try { + (value[1] as String? ?: "0").toInt() + } catch (e: Exception) { + 0 + } + + row.minutes = hours * 60 + minutes + } else { + row.minutes = 0 + } + } + } + + //TODO: Update management like in onRowSelected + if (value != null) { + if (!selectedRows.contains(row)) { + selectedRows.add(row as FilterElementRow) + } + } else { + selectedRows.remove(row as FilterElementRow) + } + rowRepresentableAdapter.refreshRow(row) } @@ -155,8 +195,6 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta */ private fun initData() { - Timber.d("initData") - primaryKey?.let { currentFilter = Filter.getFilterBydId(getRealm(), it) } 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 f183236b..e35af122 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 @@ -1,12 +1,15 @@ package net.pokeranalytics.android.ui.view.rowrepresentable import android.content.Context +import android.text.InputType import net.pokeranalytics.android.R import net.pokeranalytics.android.exceptions.PokerAnalyticsException import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.model.realm.FilterCondition +import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.RowViewType import java.util.* @@ -40,6 +43,10 @@ sealed class FilterElementRow : RowRepresentable { } } + open class QuantityFilterElementRow : FilterElementRow() + open class MoreFilterElementRow : QuantityFilterElementRow() + open class LessFilterElementRow : QuantityFilterElementRow() + open class SingleValueFilterElementRow(val value: Int) : FilterElementRow() data class Blind(var sb: Double? = null, var bb: Double? = null, var code: String? = null) : FilterElementRow() @@ -57,8 +64,11 @@ sealed class FilterElementRow : RowRepresentable { data class TournamentName(val tournamentName: Manageable) : DataFilterElementRow(tournamentName) data class AllTournamentFeature(val tournamentFeature: Manageable) : DataFilterElementRow(tournamentFeature) data class AnyTournamentFeature(val tournamentFeature: Manageable) : DataFilterElementRow(tournamentFeature) - data class ResultMoreThan(var value: Double) : FilterElementRow() - data class ResultLessThan(var value: Double) : FilterElementRow() + + data class ResultMoreThan(var value: Double) : MoreFilterElementRow() + data class ResultLessThan(var value: Double) : LessFilterElementRow() + data class DurationMoreThan(var minutes: Int) : MoreFilterElementRow() + data class DurationLessThan(var minutes: Int) : LessFilterElementRow() lateinit var filterSectionRow: FilterSectionRow @@ -85,9 +95,9 @@ sealed class FilterElementRow : RowRepresentable { is CurrentWeek -> QueryCondition.THIS_WEEK is CurrentMonth -> QueryCondition.THIS_MONTH is CurrentYear -> QueryCondition.THIS_YEAR - /* - is PastDays -> R.string.period_in_days - */ + /* + is PastDays -> R.string.period_in_days + */ is Limit -> QueryCondition.LIMIT is TableSize -> QueryCondition.TABLE_SIZE @@ -99,6 +109,8 @@ sealed class FilterElementRow : RowRepresentable { is AllTournamentFeature -> QueryCondition.ALL_TOURNAMENT_FEATURES is ResultMoreThan -> QueryCondition.MORE_THAN_NET_RESULT is ResultLessThan -> QueryCondition.LESS_THAN_NET_RESULT + is DurationMoreThan -> QueryCondition.MORE_THAN_DURATION + is DurationLessThan -> QueryCondition.LESS_THAN_DURATION else -> throw PokerAnalyticsException.UnknownQueryTypeForRow(this) } } @@ -138,8 +150,8 @@ sealed class FilterElementRow : RowRepresentable { is Day -> R.string.day_of_the_week is PastDays -> R.string.period_in_days is Blind -> R.string.blinds - is ResultMoreThan -> R.string.more_than - is ResultLessThan -> R.string.less_than + is ResultMoreThan, is DurationMoreThan -> R.string.more_than + is ResultLessThan, is DurationLessThan -> R.string.less_than else -> null } } @@ -147,11 +159,33 @@ sealed class FilterElementRow : RowRepresentable { override val viewType: Int get() { return when (this) { - is ResultMoreThan -> RowViewType.TITLE_VALUE_CHECK.ordinal + is DurationMoreThan, is DurationLessThan -> RowViewType.TITLE_VALUE_CHECK.ordinal else -> RowViewType.TITLE_CHECK.ordinal } } + override val bottomSheetType: BottomSheetType + get() { + return when (this) { + is DurationMoreThan, is DurationLessThan -> BottomSheetType.DOUBLE_EDIT_TEXT + else -> BottomSheetType.NONE + } + } + + override fun editingDescriptors(map: Map): ArrayList? { + return when (this) { + is DurationMoreThan, is DurationLessThan -> { + val hours: String? by map + val minutes: String? by map + arrayListOf( + RowRepresentableEditDescriptor(hours, R.string.hour, inputType = InputType.TYPE_CLASS_NUMBER), + RowRepresentableEditDescriptor(minutes, R.string.minute, inputType = InputType.TYPE_CLASS_NUMBER) + ) + } + else -> super.editingDescriptors(map) + } + } + override fun getDisplayName(): String { return when (this) { is DataFilterElementRow -> this.name diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt index 19f4ed1d..d87a4d97 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt @@ -126,7 +126,7 @@ enum class FilterSectionRow(override val resId: Int?) : RowRepresentable { MULTI_PLAYER -> arrayListOf() - SESSION_DURATION -> arrayListOf(ResultMoreThan(0.0), ResultLessThan(0.0)) + SESSION_DURATION -> arrayListOf(DurationMoreThan(0), DurationLessThan(0)) RANGE -> arrayListOf(From(Date()), To(Date())) VALUE -> arrayListOf() From 77376ac163bcd50cb230cdb0f64990f1ee80cea4 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 16:13:04 +0200 Subject: [PATCH 09/19] Improve UI --- app/src/main/res/layout/row_title_value_check.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/layout/row_title_value_check.xml b/app/src/main/res/layout/row_title_value_check.xml index 683e9169..a498f549 100644 --- a/app/src/main/res/layout/row_title_value_check.xml +++ b/app/src/main/res/layout/row_title_value_check.xml @@ -26,6 +26,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="16dp" + android:ellipsize="none" android:gravity="end" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/check" From acd3a2c4d1d2bdedd07840a454f9c3aba2c9c3d5 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 16:13:38 +0200 Subject: [PATCH 10/19] Improve date management for filters --- .../android/ui/fragment/FilterDetailsFragment.kt | 9 +++++++++ .../android/ui/view/rowrepresentable/FilterElementRow.kt | 6 ++++-- 2 files changed, 13 insertions(+), 2 deletions(-) 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 e059aa6d..f7d0a8e8 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 @@ -19,11 +19,13 @@ 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.bottomsheet.BottomSheetFragment +import net.pokeranalytics.android.ui.helpers.DateTimePickerManager import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow +import net.pokeranalytics.android.util.extensions.shortDate import net.pokeranalytics.android.util.extensions.toMinutes import timber.log.Timber import java.util.* @@ -66,6 +68,9 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta Timber.d("Row: $row") when (row) { + is FilterElementRow.From -> DateTimePickerManager.create(requireContext(), row, this, row.date, onlyDate = true) + is FilterElementRow.To -> DateTimePickerManager.create(requireContext(), row, this, row.date, onlyDate = true) + is FilterElementRow.DurationMoreThan -> { val hours = if (row.minutes / 60 > 0) (row.minutes / 60).toString() else "" val minutes = if (row.minutes % 60 > 0) (row.minutes % 60).toString() else "" @@ -116,6 +121,8 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta override fun stringForRow(row: RowRepresentable): String { return when (row) { + is FilterElementRow.From -> row.date.shortDate() + is FilterElementRow.To -> row.date.shortDate() is FilterElementRow.DurationMoreThan -> row.minutes.toMinutes(requireContext()) else -> super.stringForRow(row) } @@ -130,6 +137,8 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta Timber.d("onRowValueChanged: $row $value") when (row) { + is FilterElementRow.From -> row.date = if (value != null && value is Date) value else Date() + is FilterElementRow.To -> row.date = if (value != null && value is Date) value else Date() is FilterElementRow.DurationMoreThan -> { if (value is ArrayList<*>) { val hours = try { 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 e35af122..e604d94b 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 @@ -111,6 +111,7 @@ sealed class FilterElementRow : RowRepresentable { is ResultLessThan -> QueryCondition.LESS_THAN_NET_RESULT is DurationMoreThan -> QueryCondition.MORE_THAN_DURATION is DurationLessThan -> QueryCondition.LESS_THAN_DURATION + else -> throw PokerAnalyticsException.UnknownQueryTypeForRow(this) } } @@ -150,8 +151,8 @@ sealed class FilterElementRow : RowRepresentable { is Day -> R.string.day_of_the_week is PastDays -> R.string.period_in_days is Blind -> R.string.blinds - is ResultMoreThan, is DurationMoreThan -> R.string.more_than - is ResultLessThan, is DurationLessThan -> R.string.less_than + is MoreFilterElementRow -> R.string.more_than + is LessFilterElementRow -> R.string.less_than else -> null } } @@ -159,6 +160,7 @@ sealed class FilterElementRow : RowRepresentable { override val viewType: Int get() { return when (this) { + is From, is To, is DurationMoreThan, is DurationLessThan -> RowViewType.TITLE_VALUE_CHECK.ordinal else -> RowViewType.TITLE_CHECK.ordinal } From 30c2b100c445f08a1e28c188db94eb10cb2e12e6 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 18:06:09 +0200 Subject: [PATCH 11/19] Improve date filters --- .../android/model/filter/QueryCondition.kt | 1 + .../view/rowrepresentable/FilterElementRow.kt | 22 +++++++----- .../view/rowrepresentable/FilterSectionRow.kt | 36 ++++++++++++++++--- 3 files changed, 47 insertions(+), 12 deletions(-) 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 14b9bad9..d0c90f6b 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 @@ -67,6 +67,7 @@ enum class QueryCondition(var operator: Operator? = null) { THIS_WEEK, THIS_MONTH, THIS_YEAR, + PAST_DAYS, MORE_THAN_DURATION(Operator.MORE), LESS_THAN_DURATION(Operator.LESS), 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 e604d94b..ddbcfa2a 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 @@ -11,6 +11,7 @@ import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheet import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.RowViewType +import java.text.DateFormatSymbols import java.util.* sealed class FilterElementRow : RowRepresentable { @@ -28,6 +29,8 @@ sealed class FilterElementRow : RowRepresentable { object Weekday : FilterElementRow() object Weekend : FilterElementRow() + open class SingleValueFilterElementRow(val value: Int) : FilterElementRow() + open class DataFilterElementRow(data: Manageable) : FilterElementRow() { val id: String = data.id val name: String = (data as RowRepresentable).getDisplayName() @@ -47,7 +50,6 @@ sealed class FilterElementRow : RowRepresentable { open class MoreFilterElementRow : QuantityFilterElementRow() open class LessFilterElementRow : QuantityFilterElementRow() - open class SingleValueFilterElementRow(val value: Int) : FilterElementRow() data class Blind(var sb: Double? = null, var bb: Double? = null, var code: String? = null) : FilterElementRow() data class From(var date: Date = Date()) : FilterElementRow() @@ -95,10 +97,7 @@ sealed class FilterElementRow : RowRepresentable { is CurrentWeek -> QueryCondition.THIS_WEEK is CurrentMonth -> QueryCondition.THIS_MONTH is CurrentYear -> QueryCondition.THIS_YEAR - /* - is PastDays -> R.string.period_in_days - */ - + is PastDays -> QueryCondition.PAST_DAYS is Limit -> QueryCondition.LIMIT is TableSize -> QueryCondition.TABLE_SIZE is Game -> QueryCondition.GAME @@ -118,6 +117,9 @@ sealed class FilterElementRow : RowRepresentable { fun contains(filterConditions: List): Boolean { return when (this) { + is SingleValueFilterElementRow -> filterConditions.any { + it.values.contains(this.value) + } is DataFilterElementRow -> filterConditions.any { it.ids.contains(this.id) } @@ -146,9 +148,6 @@ sealed class FilterElementRow : RowRepresentable { is Online -> R.string.online is Weekday -> R.string.week_days is Weekend -> R.string.weekend - is Year -> R.string.year - is Month -> R.string.month_of_the_year - is Day -> R.string.day_of_the_week is PastDays -> R.string.period_in_days is Blind -> R.string.blinds is MoreFilterElementRow -> R.string.more_than @@ -190,6 +189,13 @@ sealed class FilterElementRow : RowRepresentable { override fun getDisplayName(): String { return when (this) { + is SingleValueFilterElementRow -> { + when (this) { + is Day -> DateFormatSymbols.getInstance(Locale.getDefault()).weekdays[this.value] + is Month -> DateFormatSymbols.getInstance(Locale.getDefault()).months[this.value] + else -> "${this.value}" + } + } is DataFilterElementRow -> this.name is StaticDataFilterElementRow -> this.name else -> super.getDisplayName() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt index d87a4d97..29b1801d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt @@ -8,6 +8,7 @@ import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow.* +import java.text.DateFormatSymbols import java.util.* enum class FilterSectionRow(override val resId: Int?) : RowRepresentable { @@ -91,11 +92,38 @@ enum class FilterSectionRow(override val resId: Int?) : RowRepresentable { CurrentYear ) FIXED_DATE -> arrayListOf(From(), To()) - DURATION -> arrayListOf() + DURATION -> arrayListOf(PastDays()) + YEAR -> { + val years = arrayListOf() + val realm = Realm.getDefaultInstance() + val distinctYears = realm.where().distinct("year").findAll().sort("year", Sort.DESCENDING) + distinctYears.forEach { session -> + session.year?.let { year -> + years.add(Year(year)) + } + } + realm.close() + years + } WEEKDAYS_OR_WEEKEND -> arrayListOf(Weekday, Weekend) - DAY_OF_WEEK -> arrayListOf() - MONTH_OF_YEAR -> arrayListOf() - YEAR -> arrayListOf() + DAY_OF_WEEK -> { + val daysOfWeek = arrayListOf() + DateFormatSymbols.getInstance(Locale.getDefault()).weekdays.forEachIndexed { index, day -> + if (day.isNotEmpty()) { + daysOfWeek.add(Day(index)) + } + } + daysOfWeek + } + MONTH_OF_YEAR -> { + val months = arrayListOf() + DateFormatSymbols.getInstance(Locale.getDefault()).months.forEachIndexed { index, month -> + if (month.isNotEmpty()) { + months.add(Month(index)) + } + } + months + } GAME -> { val games = arrayListOf() From e5a454c4bd3416f85e7c69d7838dee2976025c09 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 18:06:24 +0200 Subject: [PATCH 12/19] Add getValue methods --- .../android/model/realm/Filter.kt | 121 ++++++++++-------- .../android/model/realm/FilterCondition.kt | 11 ++ 2 files changed, 77 insertions(+), 55 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 9ccaa0a0..f3569573 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 @@ -39,15 +39,15 @@ open class Filter : RealmObject() { return realm.where().equalTo("id", filterId).findFirst() } - @TestOnly - inline fun queryOn(realm: Realm, queries: List): RealmResults { - var realmQuery = realm.where() - queries.forEach { - realmQuery = it.filter(realmQuery) - } - return realmQuery.findAll() - } - } + @TestOnly + inline fun queryOn(realm: Realm, queries: List): RealmResults { + var realmQuery = realm.where() + queries.forEach { + realmQuery = it.filter(realmQuery) + } + return realmQuery.findAll() + } + } @PrimaryKey var id = UUID.randomUUID().toString() @@ -59,59 +59,70 @@ open class Filter : RealmObject() { // for MutableRealmInteger, see https://realm.io/docs/java/latest/#counters val usageCount: MutableRealmInteger = MutableRealmInteger.valueOf(0) - var filterConditions: RealmList = RealmList() - private set - - fun createOrUpdateFilterConditions(filterConditionRows: ArrayList) { - filterConditions.clear() - filterConditionRows - .map { - it.filterSectionRow - } - .distinct() - .forEach { section -> - filterConditionRows - .filter { - it.filterSectionRow == section - } - .apply { - - if (this.size == 1) { - filterConditions.add(FilterCondition(this.first())) - } else { - val casted = arrayListOf() - casted.addAll(this) - filterConditions.add(FilterCondition(casted)) - } + var filterConditions: RealmList = RealmList() + private set + + fun createOrUpdateFilterConditions(filterConditionRows: ArrayList) { + filterConditions.clear() + filterConditionRows + .map { + it.filterSectionRow + } + .distinct() + .forEach { section -> + filterConditionRows + .filter { + it.filterSectionRow == section + } + .apply { + if (this.size == 1) { + filterConditions.add(FilterCondition(this.first())) + } else { + val casted = arrayListOf() + casted.addAll(this) + filterConditions.add(FilterCondition(casted)) + } } } } - fun countBy(filterCategoryRow: FilterCategoryRow) : Int { - val sections = filterCategoryRow.filterSectionRows - return filterConditions.count { - sections.contains(FilterSectionRow.valueOf(it.sectionName ?: throw PokerAnalyticsException.FilterElementUnknownSectionName)) - } - } - - fun contains(filterElementRow:FilterElementRow) : Boolean { - val filtered = filterConditions.filter { - it.filterName == filterElementRow.filterName - } - if (filtered.isEmpty()) { - return false - } - return filterElementRow.contains(filtered) - } + fun countBy(filterCategoryRow: FilterCategoryRow): Int { + val sections = filterCategoryRow.filterSectionRows + return filterConditions.count { + sections.contains(FilterSectionRow.valueOf(it.sectionName ?: throw PokerAnalyticsException.FilterElementUnknownSectionName)) + } + } + + fun contains(filterElementRow: FilterElementRow): Boolean { + val filtered = filterConditions.filter { + it.filterName == filterElementRow.filterName + } + if (filtered.isEmpty()) { + return false + } + return filterElementRow.contains(filtered) + } + + fun getValueForElement(filterElementRow: FilterElementRow): Any? { + val filtered = filterConditions.filter { + it.filterName == filterElementRow.filterName + } + + if (filtered.isNotEmpty()) { + return filtered.first().getValue(filterElementRow) + } + + return null + } inline fun results(): RealmResults { - var realmQuery = realm.where() - this.filterConditions.map { - it.queryCondition - }.forEach { - realmQuery = it.filter(realmQuery) - } + var realmQuery = realm.where() + this.filterConditions.map { + it.queryCondition + }.forEach { + realmQuery = it.filter(realmQuery) + } return realmQuery.findAll() } 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 be7aa78c..b9eb4d09 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 @@ -157,4 +157,15 @@ open class FilterCondition() : RealmObject() { val year: Int get() = numericValues?.first()?.toInt() ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing + + /** + * Return the value associated with the given filter element row + */ + fun getValue(filterElementRow: FilterElementRow): Any? { + return when (filterElementRow) { + is From, is To -> dateValue + else -> null + } + } + } From 8e37a1151af2e099ca2b001c4e5f7626ea33806a Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Tue, 9 Apr 2019 18:06:29 +0200 Subject: [PATCH 13/19] Add logs --- .../ui/fragment/FilterDetailsFragment.kt | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) 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 f7d0a8e8..a5087055 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 @@ -216,8 +216,20 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta this.rowsForFilterSubcategoryRow.clear() this.rows.addAll(it.filterElements) - this.rows.forEach {element -> + currentFilter?.filterConditions?.forEach { + Timber.d(it.toString()) + } + + this.rows.forEach { element -> if (element is FilterElementRow && currentFilter?.contains(element) == true) { + + /* + when (element) { + is FilterElementRow.From -> element.date = currentFilter?.getValueForElement(element) as Date? ?: Date() + is FilterElementRow.To -> element.date = currentFilter?.getValueForElement(element) as Date? ?: Date() + } + */ + this.selectedRows.add(element) } } @@ -235,11 +247,20 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta //TODO: Save currentFilter details data Timber.d("Save data for filter: ${currentFilter?.id}") + selectedRows?.forEach { + Timber.d("Selected rows: $it") + } + val realm = getRealm() realm.beginTransaction() currentFilter?.createOrUpdateFilterConditions(selectedRows) realm.commitTransaction() + currentFilter?.filterConditions?.forEach { + Timber.d("Condition: $it") + } + + finishActivityWithResult(currentFilter?.id) } From d1600dd055162eb03059fda92f993e668f311d05 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Wed, 10 Apr 2019 10:01:22 +0200 Subject: [PATCH 14/19] Add exception for missing filter element type --- .../java/net/pokeranalytics/android/exceptions/Exceptions.kt | 1 + 1 file changed, 1 insertion(+) 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 057a0b7d..1ba11cd2 100644 --- a/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt +++ b/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt @@ -17,6 +17,7 @@ sealed class PokerAnalyticsException(message: String) : Exception(message) { object QueryTypeUnhandled: PokerAnalyticsException(message = "filter type not handled") object QueryValueMapUnexpectedValue: PokerAnalyticsException(message = "valueMap null not expected") object FilterElementExpectedValueMissing : PokerAnalyticsException(message = "filter is empty or null") + object FilterElementTypeMissing : PokerAnalyticsException(message = "filter element type is missing") data class QueryValueMapMissingKeys(val missingKeys: List) : PokerAnalyticsException(message = "valueMap does not contain $missingKeys") data class UnknownQueryTypeForRow(val filterElementRow: FilterElementRow) : PokerAnalyticsException(message = "no filter type for $filterElementRow") } \ No newline at end of file From 80cfa5605c964cef010ae5368b595726182d5aab Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Wed, 10 Apr 2019 10:01:50 +0200 Subject: [PATCH 15/19] Improve date filters management --- .../android/model/realm/Filter.kt | 24 ++++++++++++++++--- .../android/model/realm/FilterCondition.kt | 20 ++++++++++++---- .../ui/fragment/FilterDetailsFragment.kt | 19 +++++++-------- .../view/rowrepresentable/FilterElementRow.kt | 8 +++++++ 4 files changed, 54 insertions(+), 17 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 f3569573..3fb2e5c5 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 @@ -82,7 +82,6 @@ open class Filter : RealmObject() { casted.addAll(this) filterConditions.add(FilterCondition(casted)) } - } } } @@ -104,13 +103,32 @@ open class Filter : RealmObject() { return filterElementRow.contains(filtered) } - fun getValueForElement(filterElementRow: FilterElementRow): Any? { + /** + * Set the saved value in the filter for the given [filterElementRow] + */ + fun setSavedValueForElement(filterElementRow: FilterElementRow) { + when (filterElementRow) { + is FilterElementRow.PastDays -> { + val values = getSavedValueForElement(filterElementRow) as Array<*> + if (values.isNotEmpty() && values.first() is Int) { + filterElementRow.lastDays = values.first() as Int + } + } + is FilterElementRow.From -> filterElementRow.date = getSavedValueForElement(filterElementRow) as Date? ?: Date() + is FilterElementRow.To -> filterElementRow.date = getSavedValueForElement(filterElementRow) as Date? ?: Date() + } + } + + /** + * Get the saved value for the given [filterElementRow] + */ + private fun getSavedValueForElement(filterElementRow: FilterElementRow): Any? { val filtered = filterConditions.filter { it.filterName == filterElementRow.filterName } if (filtered.isNotEmpty()) { - return filtered.first().getValue(filterElementRow) + return filtered.first().getFilterConditionValue(filterElementRow) } return null 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 b9eb4d09..4b8b5fdd 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 @@ -16,6 +16,10 @@ open class FilterCondition() : RealmObject() { } constructor(filterElementRows: ArrayList) : this(filterElementRows.first().filterName, filterElementRows.first().filterSectionRow.name) { + + + + val filterName : String = this.filterName ?: throw PokerAnalyticsException.FilterElementUnknownName this.stringValues = when (QueryCondition.valueOf(filterName)) { QueryCondition.GAME, QueryCondition.BANKROLL, QueryCondition.TOURNAMENT_NAME, QueryCondition.ALL_TOURNAMENT_FEATURES, QueryCondition.ANY_TOURNAMENT_FEATURES, QueryCondition.LOCATION -> { @@ -72,6 +76,13 @@ open class FilterCondition() : RealmObject() { }) } } + QueryCondition.PAST_DAYS -> { + RealmList().apply { + this.addAll(filterElementRows.map { + (it as FilterElementRow.PastDays).lastDays.toDouble() + }) + } + } else -> null } @@ -159,12 +170,13 @@ open class FilterCondition() : RealmObject() { /** - * Return the value associated with the given filter element row + * Return the value associated with the given [filterElementRow] */ - fun getValue(filterElementRow: FilterElementRow): Any? { + fun getFilterConditionValue(filterElementRow: FilterElementRow): Any? { return when (filterElementRow) { - is From, is To -> dateValue - else -> null + is From, is To -> date + is PastDays -> values + else -> throw PokerAnalyticsException.FilterElementTypeMissing } } 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 a5087055..93631905 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 @@ -25,6 +25,7 @@ import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow +import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.extensions.shortDate import net.pokeranalytics.android.util.extensions.toMinutes import timber.log.Timber @@ -70,7 +71,11 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta when (row) { is FilterElementRow.From -> DateTimePickerManager.create(requireContext(), row, this, row.date, onlyDate = true) is FilterElementRow.To -> DateTimePickerManager.create(requireContext(), row, this, row.date, onlyDate = true) - + is FilterElementRow.PastDays -> { + val pastDays = if (row.lastDays > 0) row.lastDays.toString() else "" + val data = row.editingDescriptors(mapOf("pastDays" to pastDays)) + BottomSheetFragment.create(fragmentManager, row, this, data, true) + } is FilterElementRow.DurationMoreThan -> { val hours = if (row.minutes / 60 > 0) (row.minutes / 60).toString() else "" val minutes = if (row.minutes % 60 > 0) (row.minutes % 60).toString() else "" @@ -121,6 +126,7 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta override fun stringForRow(row: RowRepresentable): String { return when (row) { + is FilterElementRow.PastDays -> if (row.lastDays > 0) row.lastDays.toString() else NULL_TEXT is FilterElementRow.From -> row.date.shortDate() is FilterElementRow.To -> row.date.shortDate() is FilterElementRow.DurationMoreThan -> row.minutes.toMinutes(requireContext()) @@ -139,6 +145,7 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta when (row) { is FilterElementRow.From -> row.date = if (value != null && value is Date) value else Date() is FilterElementRow.To -> row.date = if (value != null && value is Date) value else Date() + is FilterElementRow.PastDays -> row.lastDays = if (value != null && value is String) value.toInt() else 0 is FilterElementRow.DurationMoreThan -> { if (value is ArrayList<*>) { val hours = try { @@ -222,14 +229,7 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta this.rows.forEach { element -> if (element is FilterElementRow && currentFilter?.contains(element) == true) { - - /* - when (element) { - is FilterElementRow.From -> element.date = currentFilter?.getValueForElement(element) as Date? ?: Date() - is FilterElementRow.To -> element.date = currentFilter?.getValueForElement(element) as Date? ?: Date() - } - */ - + currentFilter?.setSavedValueForElement(element) this.selectedRows.add(element) } } @@ -246,7 +246,6 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta private fun saveData() { //TODO: Save currentFilter details data Timber.d("Save data for filter: ${currentFilter?.id}") - selectedRows?.forEach { Timber.d("Selected rows: $it") } 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 ddbcfa2a..6340ff63 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 @@ -159,6 +159,7 @@ sealed class FilterElementRow : RowRepresentable { override val viewType: Int get() { return when (this) { + is PastDays, is From, is To, is DurationMoreThan, is DurationLessThan -> RowViewType.TITLE_VALUE_CHECK.ordinal else -> RowViewType.TITLE_CHECK.ordinal @@ -168,6 +169,7 @@ sealed class FilterElementRow : RowRepresentable { override val bottomSheetType: BottomSheetType get() { return when (this) { + is PastDays -> BottomSheetType.EDIT_TEXT is DurationMoreThan, is DurationLessThan -> BottomSheetType.DOUBLE_EDIT_TEXT else -> BottomSheetType.NONE } @@ -175,6 +177,12 @@ sealed class FilterElementRow : RowRepresentable { override fun editingDescriptors(map: Map): ArrayList? { return when (this) { + is PastDays -> { + val pastDays: String? by map + arrayListOf( + RowRepresentableEditDescriptor(pastDays, R.string.period_in_days, inputType = InputType.TYPE_CLASS_NUMBER) + ) + } is DurationMoreThan, is DurationLessThan -> { val hours: String? by map val minutes: String? by map From 807a73ba0ce5c0a1c51bbce758e79f50635bce46 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Wed, 10 Apr 2019 10:15:03 +0200 Subject: [PATCH 16/19] Improve exception --- .../java/net/pokeranalytics/android/exceptions/Exceptions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1ba11cd2..f1ff2e51 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 QueryTypeUnhandled: PokerAnalyticsException(message = "filter type not handled") object QueryValueMapUnexpectedValue: PokerAnalyticsException(message = "valueMap null not expected") object FilterElementExpectedValueMissing : PokerAnalyticsException(message = "filter is empty or null") - object FilterElementTypeMissing : PokerAnalyticsException(message = "filter element type is missing") + data class FilterElementTypeMissing(val filterElementRow: FilterElementRow) : PokerAnalyticsException(message = "filter element '$filterElementRow' type is missing") data class QueryValueMapMissingKeys(val missingKeys: List) : PokerAnalyticsException(message = "valueMap does not contain $missingKeys") data class UnknownQueryTypeForRow(val filterElementRow: FilterElementRow) : PokerAnalyticsException(message = "no filter type for $filterElementRow") } \ No newline at end of file From 2160c469a82f07ef38e46e6c550c6e88f196b396 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Wed, 10 Apr 2019 10:15:18 +0200 Subject: [PATCH 17/19] Fix bug when getting value for date --- .../net/pokeranalytics/android/model/realm/FilterCondition.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 4b8b5fdd..db893d78 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 @@ -174,9 +174,9 @@ open class FilterCondition() : RealmObject() { */ fun getFilterConditionValue(filterElementRow: FilterElementRow): Any? { return when (filterElementRow) { - is From, is To -> date + is From, is To -> dateValue //TODO: Probably change by 'date' (doesn't work now because the value isn't correctly saved is PastDays -> values - else -> throw PokerAnalyticsException.FilterElementTypeMissing + else -> throw PokerAnalyticsException.FilterElementTypeMissing(filterElementRow) } } From 78cb6a8dfe3d8f2c2d827c9ae8861ba8fb1c7644 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Wed, 10 Apr 2019 10:48:28 +0200 Subject: [PATCH 18/19] Improve Duration filters --- .../ui/fragment/FilterDetailsFragment.kt | 10 ++++++++-- .../view/rowrepresentable/FilterElementRow.kt | 20 ++++++++++++------- .../view/rowrepresentable/FilterSectionRow.kt | 2 +- 3 files changed, 22 insertions(+), 10 deletions(-) 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 93631905..303333e4 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 @@ -82,6 +82,12 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) BottomSheetFragment.create(fragmentManager, row, this, data, true) } + is FilterElementRow.DurationLessThan -> { + 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)) + BottomSheetFragment.create(fragmentManager, row, this, data, true) + } else -> { val oldRows = ArrayList() @@ -129,7 +135,7 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta is FilterElementRow.PastDays -> if (row.lastDays > 0) row.lastDays.toString() else NULL_TEXT is FilterElementRow.From -> row.date.shortDate() is FilterElementRow.To -> row.date.shortDate() - is FilterElementRow.DurationMoreThan -> row.minutes.toMinutes(requireContext()) + is FilterElementRow.TimeFilterElementRow -> row.minutes.toMinutes(requireContext()) else -> super.stringForRow(row) } } @@ -146,7 +152,7 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta is FilterElementRow.From -> row.date = if (value != null && value is Date) value else Date() is FilterElementRow.To -> row.date = if (value != null && value is Date) value else Date() is FilterElementRow.PastDays -> row.lastDays = if (value != null && value is String) value.toInt() else 0 - is FilterElementRow.DurationMoreThan -> { + is FilterElementRow.TimeFilterElementRow -> { if (value is ArrayList<*>) { val hours = try { (value[0] as String? ?: "0").toInt() 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 6340ff63..f3c046e6 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 @@ -46,9 +46,15 @@ sealed class FilterElementRow : RowRepresentable { } } - open class QuantityFilterElementRow : FilterElementRow() + open class QuantityFilterElementRow(var value: Double = 0.0) : FilterElementRow() + open class TimeFilterElementRow : QuantityFilterElementRow() { + var minutes = value.toInt() + } + open class MoreFilterElementRow : QuantityFilterElementRow() open class LessFilterElementRow : QuantityFilterElementRow() + open class MoreTimeFilterElementRow : TimeFilterElementRow() + open class LessTimeFilterElementRow : TimeFilterElementRow() data class Blind(var sb: Double? = null, var bb: Double? = null, var code: String? = null) : FilterElementRow() @@ -67,10 +73,10 @@ sealed class FilterElementRow : RowRepresentable { data class AllTournamentFeature(val tournamentFeature: Manageable) : DataFilterElementRow(tournamentFeature) data class AnyTournamentFeature(val tournamentFeature: Manageable) : DataFilterElementRow(tournamentFeature) - data class ResultMoreThan(var value: Double) : MoreFilterElementRow() - data class ResultLessThan(var value: Double) : LessFilterElementRow() - data class DurationMoreThan(var minutes: Int) : MoreFilterElementRow() - data class DurationLessThan(var minutes: Int) : LessFilterElementRow() + object ResultMoreThan : MoreFilterElementRow() + object ResultLessThan : LessFilterElementRow() + object DurationMoreThan : MoreTimeFilterElementRow() + object DurationLessThan : LessTimeFilterElementRow() lateinit var filterSectionRow: FilterSectionRow @@ -150,8 +156,8 @@ sealed class FilterElementRow : RowRepresentable { is Weekend -> R.string.weekend is PastDays -> R.string.period_in_days is Blind -> R.string.blinds - is MoreFilterElementRow -> R.string.more_than - is LessFilterElementRow -> R.string.less_than + is MoreFilterElementRow, is MoreTimeFilterElementRow -> R.string.more_than + is LessFilterElementRow, is LessTimeFilterElementRow -> R.string.less_than else -> null } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt index 29b1801d..7158d301 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt @@ -154,7 +154,7 @@ enum class FilterSectionRow(override val resId: Int?) : RowRepresentable { MULTI_PLAYER -> arrayListOf() - SESSION_DURATION -> arrayListOf(DurationMoreThan(0), DurationLessThan(0)) + SESSION_DURATION -> arrayListOf(DurationMoreThan, DurationLessThan) RANGE -> arrayListOf(From(Date()), To(Date())) VALUE -> arrayListOf() From d92e2a30b3498d0b6d57197c93b188e100151f1c Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Wed, 10 Apr 2019 10:50:41 +0200 Subject: [PATCH 19/19] Clean code --- .../ui/view/rowrepresentable/FilterElementRow.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) 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 f3c046e6..0dd9a3fa 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 @@ -16,6 +16,8 @@ import java.util.* sealed class FilterElementRow : RowRepresentable { + // Objects + object Cash : FilterElementRow() object Tournament : FilterElementRow() object Live : FilterElementRow() @@ -29,6 +31,13 @@ sealed class FilterElementRow : RowRepresentable { object Weekday : FilterElementRow() object Weekend : FilterElementRow() + object ResultMoreThan : MoreFilterElementRow() + object ResultLessThan : LessFilterElementRow() + object DurationMoreThan : MoreTimeFilterElementRow() + object DurationLessThan : LessTimeFilterElementRow() + + // Subclasses + open class SingleValueFilterElementRow(val value: Int) : FilterElementRow() open class DataFilterElementRow(data: Manageable) : FilterElementRow() { @@ -56,6 +65,7 @@ sealed class FilterElementRow : RowRepresentable { open class MoreTimeFilterElementRow : TimeFilterElementRow() open class LessTimeFilterElementRow : TimeFilterElementRow() + // Data classes data class Blind(var sb: Double? = null, var bb: Double? = null, var code: String? = null) : FilterElementRow() data class From(var date: Date = Date()) : FilterElementRow() @@ -73,10 +83,6 @@ sealed class FilterElementRow : RowRepresentable { data class AllTournamentFeature(val tournamentFeature: Manageable) : DataFilterElementRow(tournamentFeature) data class AnyTournamentFeature(val tournamentFeature: Manageable) : DataFilterElementRow(tournamentFeature) - object ResultMoreThan : MoreFilterElementRow() - object ResultLessThan : LessFilterElementRow() - object DurationMoreThan : MoreTimeFilterElementRow() - object DurationLessThan : LessTimeFilterElementRow() lateinit var filterSectionRow: FilterSectionRow