feature/top10
Laurent 7 years ago
commit ca1b652bb3
  1. 218
      app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt
  2. 1
      app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt
  3. 47
      app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt
  4. 45
      app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt
  5. 23
      app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt
  6. 1
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  7. 85
      app/src/main/java/net/pokeranalytics/android/ui/fragment/FilterDetailsFragment.kt
  8. 8
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt
  9. 88
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt
  10. 38
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt
  11. 20
      app/src/main/java/net/pokeranalytics/android/util/extensions/NumbersExtension.kt
  12. 37
      app/src/main/res/layout/bottom_sheet_game_list.xml
  13. 1
      app/src/main/res/layout/row_title_value_check.xml
  14. 2
      app/src/main/res/values/strings.xml

@ -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<Session>(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<Session>(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<Session>(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<Session>(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<Session>(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<Session>(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<Session>(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<Session>(realm, arrayListOf(QueryCondition.THIS_WEEK))
Assert.assertEquals(1, sessions.size)
Assert.assertTrue(sessions.containsAll(arrayListOf(s1)))
}
@Test
fun testStartedFomDateFilter() {

@ -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")
data class FilterElementTypeMissing(val filterElementRow: FilterElementRow) : PokerAnalyticsException(message = "filter element '$filterElementRow' type is missing")
data class QueryValueMapMissingKeys(val missingKeys: List<String>) : PokerAnalyticsException(message = "valueMap does not contain $missingKeys")
data class UnknownQueryTypeForRow(val filterElementRow: FilterElementRow) : PokerAnalyticsException(message = "no filter type for $filterElementRow")
}

@ -6,11 +6,10 @@ 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
/**
@ -68,6 +67,9 @@ 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),
CURRENCY,
CURRENCY_CODE,
@ -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

@ -40,6 +40,7 @@ open class Filter : RealmObject() {
return realm.where<Filter>().equalTo("id", filterId).findFirst()
}
<<<<<<< HEAD
@TestOnly
inline fun <reified T : Filterable> queryOn(realm: Realm, queries: List<QueryCondition>): RealmResults<T> {
var realmQuery = realm.where<T>()
@ -50,6 +51,17 @@ open class Filter : RealmObject() {
return realmQuery.findAll()
}
}
=======
@TestOnly
inline fun <reified T : Filterable> queryOn(realm: Realm, queries: List<QueryCondition>): RealmResults<T> {
var realmQuery = realm.where<T>()
queries.forEach {
realmQuery = it.filter<T>(realmQuery)
}
return realmQuery.findAll()
}
}
>>>>>>> d92e2a30b3498d0b6d57197c93b188e100151f1c
@PrimaryKey
var id = UUID.randomUUID().toString()
@ -77,7 +89,6 @@ open class Filter : RealmObject() {
it.filterSectionRow == section
}
.apply {
if (this.size == 1) {
filterConditions.add(FilterCondition(this.first()))
} else {
@ -85,7 +96,6 @@ open class Filter : RealmObject() {
casted.addAll(this)
filterConditions.add(FilterCondition(casted))
}
}
}
}
@ -107,6 +117,37 @@ open class Filter : RealmObject() {
return filterElementRow.contains(filtered)
}
/**
* 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().getFilterConditionValue(filterElementRow)
}
return null
}
inline fun <reified T : Filterable> results(): RealmResults<T> {
var realmQuery = realm.where<T>()
this.filterConditions.map {

@ -16,6 +16,10 @@ open class FilterCondition() : RealmObject() {
}
constructor(filterElementRows: ArrayList<FilterElementRow>) : 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<Double>().apply {
this.addAll(filterElementRows.map {
(it as FilterElementRow.PastDays).lastDays.toDouble()
})
}
}
else -> null
}
@ -157,4 +168,16 @@ open class FilterCondition() : RealmObject() {
val year: Int
get() = numericValues?.first()?.toInt() ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
/**
* Return the value associated with the given [filterElementRow]
*/
fun getFilterConditionValue(filterElementRow: FilterElementRow): Any? {
return when (filterElementRow) {
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(filterElementRow)
}
}
}

@ -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
}
}

@ -19,13 +19,18 @@ 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.NULL_TEXT
import net.pokeranalytics.android.util.extensions.shortDate
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 +69,24 @@ 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.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 ""
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 -> {
@ -88,7 +108,6 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta
selectedRows.add(row)
}
}
}
}
@ -111,6 +130,16 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta
rowRepresentableAdapter.refreshRow(row)
}
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.TimeFilterElementRow -> row.minutes.toMinutes(requireContext())
else -> super.stringForRow(row)
}
}
override fun isSelected(row: RowRepresentable): Boolean {
return selectedRows.contains(row)
}
@ -118,7 +147,40 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta
override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
super.onRowValueChanged(value, row)
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.PastDays -> row.lastDays = if (value != null && value is String) value.toInt() else 0
is FilterElementRow.TimeFilterElementRow -> {
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 +217,6 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta
*/
private fun initData() {
Timber.d("initData")
primaryKey?.let {
currentFilter = Filter.getFilterBydId(getRealm(), it)
}
@ -169,8 +229,13 @@ open class FilterDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresenta
this.rowsForFilterSubcategoryRow.clear()
this.rows.addAll(it.filterElements)
currentFilter?.filterConditions?.forEach {
Timber.d(it.toString())
}
this.rows.forEach { element ->
if (element is FilterElementRow && currentFilter?.contains(element) == true) {
currentFilter?.setSavedValueForElement(element)
this.selectedRows.add(element)
}
}
@ -187,12 +252,20 @@ 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")
}
val realm = getRealm()
realm.beginTransaction()
currentFilter?.createOrUpdateFilterConditions(selectedRows)
realm.commitTransaction()
currentFilter?.filterConditions?.forEach {
Timber.d("Condition: $it")
}
finishActivityWithResult(currentFilter?.id)
}

@ -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)

@ -1,17 +1,23 @@
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.text.DateFormatSymbols
import java.util.*
sealed class FilterElementRow : RowRepresentable {
// Objects
object Cash : FilterElementRow()
object Tournament : FilterElementRow()
object Live : FilterElementRow()
@ -25,6 +31,15 @@ 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() {
val id: String = data.id
val name: String = (data as RowRepresentable).getDisplayName()
@ -40,7 +55,17 @@ sealed class FilterElementRow : RowRepresentable {
}
}
open class SingleValueFilterElementRow(val value: Int) : 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 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()
@ -57,8 +82,7 @@ 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()
lateinit var filterSectionRow: FilterSectionRow
@ -85,10 +109,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
@ -99,12 +120,18 @@ 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)
}
}
fun contains(filterConditions: List<FilterCondition>): Boolean {
return when (this) {
is SingleValueFilterElementRow -> filterConditions.any {
it.values.contains(this.value)
}
is DataFilterElementRow -> filterConditions.any {
it.ids.contains(this.id)
}
@ -133,13 +160,10 @@ 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 ResultMoreThan -> R.string.more_than
is ResultLessThan -> R.string.less_than
is MoreFilterElementRow, is MoreTimeFilterElementRow -> R.string.more_than
is LessFilterElementRow, is LessTimeFilterElementRow -> R.string.less_than
else -> null
}
}
@ -147,13 +171,51 @@ sealed class FilterElementRow : RowRepresentable {
override val viewType: Int
get() {
return when (this) {
is ResultMoreThan -> RowViewType.TITLE_VALUE_CHECK.ordinal
is PastDays,
is From, is To,
is DurationMoreThan, is DurationLessThan -> RowViewType.TITLE_VALUE_CHECK.ordinal
else -> RowViewType.TITLE_CHECK.ordinal
}
}
override val bottomSheetType: BottomSheetType
get() {
return when (this) {
is PastDays -> BottomSheetType.EDIT_TEXT
is DurationMoreThan, is DurationLessThan -> BottomSheetType.DOUBLE_EDIT_TEXT
else -> BottomSheetType.NONE
}
}
override fun editingDescriptors(map: Map<String, Any?>): ArrayList<RowRepresentableEditDescriptor>? {
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
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 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()

@ -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<FilterElementRow.Year>()
val realm = Realm.getDefaultInstance()
val distinctYears = realm.where<Session>().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<FilterElementRow.Day>()
DateFormatSymbols.getInstance(Locale.getDefault()).weekdays.forEachIndexed { index, day ->
if (day.isNotEmpty()) {
daysOfWeek.add(Day(index))
}
}
daysOfWeek
}
MONTH_OF_YEAR -> {
val months = arrayListOf<FilterElementRow.Month>()
DateFormatSymbols.getInstance(Locale.getDefault()).months.forEachIndexed { index, month ->
if (month.isNotEmpty()) {
months.add(Month(index))
}
}
months
}
GAME -> {
val games = arrayListOf<FilterElementRow.Game>()
@ -126,7 +154,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, DurationLessThan)
RANGE -> arrayListOf(From(Date()), To(Date()))
VALUE -> arrayListOf()

@ -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
}

@ -8,9 +8,9 @@
<FrameLayout
android:id="@+id/chips"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
@ -22,41 +22,8 @@
android:layout_gravity="center"
android:orientation="horizontal"
app:chipSpacingHorizontal="16dp"
app:singleSelection="true">
<!--
<com.google.android.material.chip.Chip
android:id="@+id/chip1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NL" />
<com.google.android.material.chip.Chip
android:id="@+id/chip2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PL" />
<com.google.android.material.chip.Chip
android:id="@+id/chip3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="FL" />
<com.google.android.material.chip.Chip
android:id="@+id/chip4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SL" />
<com.google.android.material.chip.Chip
android:id="@+id/chip5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ML" />
-->
app:singleSelection="true" />
</com.google.android.material.chip.ChipGroup>
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView

@ -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"

@ -3,6 +3,8 @@
<!-- Not translated -->
<string name="session_missing_start_date">Please set a start date for the session</string>
<string name="hour">Hour</string>
<string name="minute">Minute</string>
<!--<string name="session_missing_end_date">Please set the end date for the session</string>-->
<!--<string name="default_error_message">Sorry, something went wrong...please contact us!</string>-->

Loading…
Cancel
Save