Merge branch 'dev' of gitlab.com:stax-river/poker-analytics into dev

feature/top10
Aurelien Hubert 7 years ago
commit c8b622fca2
  1. 15
      app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/ExceptionFilterInstrumentedTest.kt
  2. 3
      app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt
  3. 41
      app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt
  4. 27
      app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt
  5. 51
      app/src/main/java/net/pokeranalytics/android/model/filter/QueryType.kt
  6. 25
      app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt
  7. 33
      app/src/main/java/net/pokeranalytics/android/model/realm/FilterElement.kt
  8. 4
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt

@ -2,7 +2,7 @@ package net.pokeranalytics.android.unitTests.filter
import androidx.test.ext.junit.runners.AndroidJUnit4
import net.pokeranalytics.android.components.BaseFilterInstrumentedUnitTest
import net.pokeranalytics.android.exceptions.FilterValueMapException
import net.pokeranalytics.android.exceptions.PokerAnalyticsException
import net.pokeranalytics.android.model.filter.QueryType
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.FilterElement
@ -13,7 +13,7 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class ExceptionFilterInstrumentedTest: BaseFilterInstrumentedUnitTest() {
@Test(expected = FilterValueMapException::class)
@Test(expected = PokerAnalyticsException.FilterElementExpectedValueMissing::class)
fun testValueKeyFilterException() {
val filter = QueryType.STARTED_FROM_DATE
val filterElement = FilterElement()
@ -27,15 +27,8 @@ class ExceptionFilterInstrumentedTest: BaseFilterInstrumentedUnitTest() {
)
}
@Test(expected = FilterValueMapException::class)
@Test(expected = PokerAnalyticsException.FilterElementUnknownName::class)
fun testFilterException() {
val realm = this.mockRealm
val filter = QueryType.BLINDS
filter.updateValueMap(FilterElement())
Filter.queryOn(
realm,
Session,
arrayListOf(filter)
)
FilterElement().queryType
}
}

@ -2,6 +2,7 @@ package net.pokeranalytics.android.unitTests.filter
import androidx.test.ext.junit.runners.AndroidJUnit4
import net.pokeranalytics.android.components.BaseFilterInstrumentedUnitTest
import net.pokeranalytics.android.exceptions.PokerAnalyticsException
import net.pokeranalytics.android.model.filter.QueryType
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.Session
@ -37,7 +38,7 @@ class RealmFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() {
val filterComponent = filter.filterElements.first()
filterComponent?.let {
Assert.assertEquals(QueryType.CASH, QueryType.valueOf(it.filterName))
Assert.assertEquals(QueryType.CASH, QueryType.valueOf(it.filterName ?: throw PokerAnalyticsException.FilterElementUnknownName))
} ?: run {
Assert.fail()
}

@ -1,25 +1,22 @@
package net.pokeranalytics.android.exceptions
class ModelException(message: String) : Exception(message) {
}
class FormattingException(message: String) : Exception(message) {
}
class RowRepresentableEditDescriptorException(message: String) : Exception(message) {
}
class FilterValueMapException(message: String) : Exception(message) {
init {
println("FilterValueMapException(): $message")
}
}
class FilterMissingEntityException(message: String) : Exception(message)
class FilterUnhandledEntityException(message : String) : Exception(message)
class ConfigurationException(message: String) : Exception(message) {
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow
class ModelException(message: String) : Exception(message)
class FormattingException(message: String) : Exception(message)
class RowRepresentableEditDescriptorException(message: String) : Exception(message)
class ConfigurationException(message: String) : Exception(message)
sealed class PokerAnalyticsException(message: String) : Exception(message) {
object FilterElementUnknownName : PokerAnalyticsException(message = "No filterElement name was found to identify the queryType")
object FilterElementUnknownSectionName: PokerAnalyticsException(message = "No filterElement section name was found to identify the queryType")
object FilterMissingEntity: PokerAnalyticsException(message = "This filter has no entity initialized")
object FilterUnhandledEntity : PokerAnalyticsException(message = "This entity is not filterable")
object QueryValueMapUnknown: PokerAnalyticsException(message = "fieldName is missing")
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 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")
}

@ -1,6 +1,7 @@
package net.pokeranalytics.android.model.filter
import io.realm.RealmObject
import io.realm.RealmModel
import net.pokeranalytics.android.model.realm.Session
/**
* We want to be able to store filters in the database:
@ -28,15 +29,37 @@ import io.realm.RealmObject
*
*/
class UnmanagedFilterField(message: String) : Exception(message) {
}
/**
* Companion-level Interface to indicate an RealmObject class can be filtered and to provide all the fieldNames (eg: parameter's path) needed to be query on.
*/
interface Filterable {
interface Filterable : RealmModel {
/**
* return the path of the parameter used in the [QueryType] related to this entity
*/
fun fieldNameForQueryType(queryType: QueryType) : String?
}
class FilterHelper {
companion object {
inline fun <reified T : Filterable> fieldNameForQueryType(queryType: QueryType) : String? {
when (T::class) {
is Session -> {
Session.fieldNameForQueryType(queryType)
}
}
throw UnmanagedFilterField("Filterable type fields are not defined")
}
}
}
//

@ -1,12 +1,10 @@
package net.pokeranalytics.android.model.filter
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.RealmQuery
import net.pokeranalytics.android.exceptions.FilterValueMapException
import net.pokeranalytics.android.model.realm.FilterElementBlind
import net.pokeranalytics.android.exceptions.PokerAnalyticsException
import net.pokeranalytics.android.model.realm.FilterElement
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.FilterElementBlind
import java.util.*
@ -16,7 +14,7 @@ import java.util.*
* To handle that, the enum has a public [valueMap] variable
* A new type should also set the expected numericValues required in the [filterValuesExpectedKeys]
*/
enum class QueryType(private var subType:SubType? = null) {
enum class QueryType(var subType:SubType? = null) {
LIVE,
CASH,
ONLINE,
@ -68,7 +66,7 @@ enum class QueryType(private var subType:SubType? = null) {
;
private enum class SubType {
enum class SubType {
BETWEEN,
MORE,
LESS;
@ -98,15 +96,16 @@ enum class QueryType(private var subType:SubType? = null) {
* main method of the enum
* providing a base RealmQuery [realmQuery], the method is able to attached the corresponding query and returns the newly formed [RealmQuery]
*/
fun filter(realmQuery: RealmQuery<out RealmObject>, filterable: Filterable): RealmQuery<out RealmObject> {
inline fun <reified T : Filterable> filter(realmQuery: RealmQuery<T>): RealmQuery<T> {
when {
this == BLINDS -> {
val smallBlindFieldName = filterable.fieldNameForQueryType(SMALL_BLIND)
val bigBlindFieldName = filterable.fieldNameForQueryType(BIG_BLIND)
val currencyCodeFieldName = filterable.fieldNameForQueryType(CURRENCY_CODE)
smallBlindFieldName ?: throw FilterValueMapException("fieldName is missing")
bigBlindFieldName ?: throw FilterValueMapException("fieldName is missing")
currencyCodeFieldName ?: throw FilterValueMapException("fieldName is missing")
val smallBlindFieldName = FilterHelper.fieldNameForQueryType<T>(SMALL_BLIND)
val bigBlindFieldName = FilterHelper.fieldNameForQueryType<T>(BIG_BLIND)
val currencyCodeFieldName = FilterHelper.fieldNameForQueryType<T>(CURRENCY_CODE)
smallBlindFieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
bigBlindFieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
currencyCodeFieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
val blinds: RealmList<FilterElementBlind> by valueMap
blinds.forEachIndexed { index, blind ->
@ -137,12 +136,10 @@ enum class QueryType(private var subType:SubType? = null) {
}
return realmQuery
}
this == ONLINE -> return LIVE.filter(realmQuery.not(), filterable)
this == TOURNAMENT -> return CASH.filter(realmQuery.not(), filterable)
this == WEEK_DAY -> return WEEK_END.filter(realmQuery.not(), filterable)
else -> {
val fieldName = filterable.fieldNameForQueryType(this)
fieldName ?: throw FilterValueMapException("fieldName is missing")
val fieldName = FilterHelper.fieldNameForQueryType<T>(this)
fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
this.subType?.let { subType ->
return when (subType) {
@ -163,8 +160,8 @@ enum class QueryType(private var subType:SubType? = null) {
}
return when (this) {
LIVE -> realmQuery.equalTo(fieldName, true)
CASH -> realmQuery.equalTo(fieldName, Session.Type.CASH_GAME.ordinal)
LIVE, ONLINE -> realmQuery.equalTo(fieldName, this == LIVE)
CASH, TOURNAMENT -> realmQuery.equalTo(fieldName, this.ordinal)
ALL_TOURNAMENT_FEATURES -> {
val ids: Array<String> by valueMap
ids.forEach {
@ -212,11 +209,13 @@ enum class QueryType(private var subType:SubType? = null) {
val year: Int by valueMap
realmQuery.equalTo(fieldName, year)
}
WEEK_END -> {
realmQuery.`in`(fieldName, arrayOf(Calendar.SATURDAY, Calendar.SUNDAY))
WEEK_END, WEEK_DAY -> {
var query = realmQuery.`in`(fieldName, arrayOf(Calendar.SATURDAY, Calendar.SUNDAY))
if (this == WEEK_DAY) { query.not() }
query
}
else -> {
throw FilterValueMapException("filter type not handled")
throw PokerAnalyticsException.QueryTypeUnhandled
}
}
}
@ -267,7 +266,7 @@ enum class QueryType(private var subType:SubType? = null) {
valueMap = mapOf("year" to filterElement.year)
}
else -> {
throw FilterValueMapException("filter type not handled")
throw PokerAnalyticsException.QueryValueMapUnexpectedValue
}
}
}
@ -278,10 +277,10 @@ enum class QueryType(private var subType:SubType? = null) {
field?.let { map ->
val missingKeys = map.keys.filter { !valueMapExceptedKeys.contains(it) }
if (map.keys.size == valueMapExceptedKeys.size && missingKeys.isNotEmpty()) {
throw FilterValueMapException("valueMap does not contain $missingKeys")
throw PokerAnalyticsException.QueryValueMapMissingKeys(missingKeys)
}
} ?: run {
throw FilterValueMapException("valueMap null not expected")
throw PokerAnalyticsException.QueryValueMapUnexpectedValue
}
}
return field

@ -2,8 +2,9 @@ package net.pokeranalytics.android.model.realm
import io.realm.*
import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.exceptions.FilterMissingEntityException
import net.pokeranalytics.android.exceptions.FilterUnhandledEntityException
import net.pokeranalytics.android.exceptions.PokerAnalyticsException
import io.realm.kotlin.where
import net.pokeranalytics.android.model.filter.Filterable
import net.pokeranalytics.android.model.filter.QueryType
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow
@ -38,7 +39,7 @@ open class Filter(entity:Filterable) : RealmObject() {
fun filterableClass(entity: Filterable): FilterableClass {
return when (entity) {
is Session.Companion -> SESSION
else -> throw FilterUnhandledEntityException("this entity is not filterable")
else -> throw PokerAnalyticsException.FilterUnhandledEntity
}
}
}
@ -64,11 +65,10 @@ open class Filter(entity:Filterable) : RealmObject() {
companion object {
@TestOnly
fun queryOn(realm: Realm, entity: Filterable, queries:List<QueryType>): RealmResults<*> {
val realmEntity : Class < out RealmObject > = FilterableClass.filterableClass(entity).relatedEntity
var realmQuery : RealmQuery<out RealmObject> = realm.where(realmEntity)
inline fun <reified T : Filterable> queryOn(realm: Realm, queries: List<QueryType>): RealmResults<T> {
var realmQuery = realm.where<T>()
queries.forEach {
realmQuery = (it.filter(realmQuery, entity))
realmQuery = (it.filter<T>(realmQuery))
}
return realmQuery.findAll()
}
@ -116,7 +116,7 @@ open class Filter(entity:Filterable) : RealmObject() {
fun countBy(filterCategoryRow: FilterCategoryRow) : Int {
val sections = filterCategoryRow.filterSectionRows
return filterElements.count {
sections.contains(FilterSectionRow.valueOf(it.sectionName))
sections.contains(FilterSectionRow.valueOf(it.sectionName ?: throw PokerAnalyticsException.FilterElementUnknownSectionName))
}
}
@ -130,16 +130,15 @@ open class Filter(entity:Filterable) : RealmObject() {
return filterElementRow.contains(filtered)
}
fun results(): RealmResults<*> {
val filterableClass : FilterableClass = this.filterableClass ?: throw FilterMissingEntityException("this filter has no entity initialized")
val realmEntity : Class < out RealmObject > = filterableClass.relatedEntity
var realmQuery : RealmQuery<out RealmObject> = realm.where(realmEntity)
inline fun <reified T : Filterable> results(): RealmResults<T> {
var realmQuery : RealmQuery<T> = realm.where<T>()
this.filterElements.map {
it.queryType
}.forEach {
realmQuery = (it.filter(realmQuery, filterableClass.filterable))
realmQuery = it.filter(realmQuery)
}
return realmQuery.findAll()
}
}

@ -2,7 +2,7 @@ package net.pokeranalytics.android.model.realm
import io.realm.RealmList
import io.realm.RealmObject
import net.pokeranalytics.android.exceptions.FilterValueMapException
import net.pokeranalytics.android.exceptions.PokerAnalyticsException
import net.pokeranalytics.android.model.filter.QueryType
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow.*
@ -17,7 +17,8 @@ open class FilterElement() : RealmObject() {
}
constructor(filterElementRows: ArrayList<FilterElementRow>) : this(filterElementRows.first().filterName, filterElementRows.first().filterSectionRow.name) {
this.stringValues = when (QueryType.valueOf(this.filterName)) {
val filterName : String = this.filterName ?: throw PokerAnalyticsException.FilterElementUnknownName
this.stringValues = when (QueryType.valueOf(filterName)) {
QueryType.GAME, QueryType.BANKROLL, QueryType.TOURNAMENT_NAME, QueryType.ALL_TOURNAMENT_FEATURES, QueryType.ANY_TOURNAMENT_FEATURES, QueryType.LOCATION -> {
RealmList<String>().apply {
this.addAll(filterElementRows.map {
@ -86,11 +87,11 @@ open class FilterElement() : RealmObject() {
}
}
var filterName : String = ""
var sectionName : String = ""
var filterName : String? = null
var sectionName : String? = null
val queryType : QueryType
get() = QueryType.valueOf(filterName)
get() = QueryType.valueOf(this.filterName ?: throw PokerAnalyticsException.FilterElementUnknownName)
.apply {
this.updateValueMap(this@FilterElement)
}
@ -101,7 +102,7 @@ open class FilterElement() : RealmObject() {
private var blindValues : RealmList<FilterElementBlind>? = null
val ids : Array<String>
get() = stringValues?.toTypedArray()?: throw FilterValueMapException("filter type not handled")
get() = stringValues?.toTypedArray()?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val blinds : RealmList<FilterElementBlind>
get() {
@ -109,44 +110,44 @@ open class FilterElement() : RealmObject() {
if (it.isNotEmpty()) {
return it
} else {
throw FilterValueMapException("filter is empty or null")
throw PokerAnalyticsException.FilterElementExpectedValueMissing
}
}
throw FilterValueMapException("filter is empty or null")
throw PokerAnalyticsException.FilterElementExpectedValueMissing
}
val date : Date
get() = dateValue?: throw FilterValueMapException("filter type not handled")
get() = dateValue?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val values : Array<Int>
get() = numericValues?.map {
it.toInt()
}?.toTypedArray()?: throw FilterValueMapException("filter type not handled")
}?.toTypedArray()?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val value : Double
get() = numericValues?.first()?: throw FilterValueMapException("filter type not handled")
get() = numericValues?.first()?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val leftValue : Double
get() = numericValues?.first()?: throw FilterValueMapException("filter type not handled")
get() = numericValues?.first()?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val rightValue : Double
get() = numericValues?.last()?: throw FilterValueMapException("filter type not handled")
get() = numericValues?.last()?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val dayOfWeek : Int
get() = numericValues?.first()?.toInt()?: throw FilterValueMapException("filter type not handled")
get() = numericValues?.first()?.toInt()?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val month : Int
get() = numericValues?.first()?.toInt()?: throw FilterValueMapException("filter type not handled")
get() = numericValues?.first()?.toInt()?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
val year : Int
get() = numericValues?.first()?.toInt()?: throw FilterValueMapException("filter type not handled")
get() = numericValues?.first()?.toInt()?: throw PokerAnalyticsException.FilterElementExpectedValueMissing
}

@ -1,7 +1,7 @@
package net.pokeranalytics.android.ui.view.rowrepresentable
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.FilterValueMapException
import net.pokeranalytics.android.exceptions.PokerAnalyticsException
import net.pokeranalytics.android.model.filter.QueryType
import net.pokeranalytics.android.model.interfaces.Manageable
import net.pokeranalytics.android.model.realm.FilterElement
@ -88,7 +88,7 @@ sealed class FilterElementRow : RowRepresentable {
is AllTournamentFeature -> QueryType.ALL_TOURNAMENT_FEATURES
is ResultMoreThan -> QueryType.MORE_THAN_NET_RESULT
is ResultLessThan -> QueryType.LESS_THAN_NET_RESULT
else -> throw FilterValueMapException("no filter type for $this") //TODO create exception
else -> throw PokerAnalyticsException.UnknownQueryTypeForRow(this)
}
}

Loading…
Cancel
Save