diff --git a/app/src/main/java/net/pokeranalytics/android/model/Criteria.kt b/app/src/main/java/net/pokeranalytics/android/model/Criteria.kt new file mode 100644 index 00000000..15b751e3 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/model/Criteria.kt @@ -0,0 +1,90 @@ +package net.pokeranalytics.android.model + +import io.realm.Realm +import io.realm.RealmResults +import io.realm.Sort +import io.realm.kotlin.where +import net.pokeranalytics.android.exceptions.PokerAnalyticsException +import net.pokeranalytics.android.model.filter.FilterHelper +import net.pokeranalytics.android.model.filter.QueryCondition +import net.pokeranalytics.android.model.interfaces.Identifiable +import net.pokeranalytics.android.model.realm.* + +sealed class Criteria { + abstract class RealmCriteria : Criteria() { + inline fun comparison(): List { + return compare < QueryCondition.QueryDataCondition, T >() + } + } + + abstract class SimpleCriteria(private val condition:QueryCondition): Criteria() { + fun comparison(): List { + return listOf(condition) + } + } + + abstract class StaticCriteria : Criteria() { + inline fun comparison(): List { + QueryCondition.distinct()?.let { + val values = it.mapNotNull { session -> + when (this) { + is Limits -> session.limit + else -> null + } + } + return compare(values) + } + return listOf() + } + } + + object Bankrolls: RealmCriteria() + object Games: RealmCriteria() + object TournamentNames: RealmCriteria() + object Locations: RealmCriteria() + object TournamentFeatures: RealmCriteria() + object Limits: StaticCriteria() + object TournamentTypes : StaticCriteria() + + object Tournament : SimpleCriteria(QueryCondition.TOURNAMENT) + + val queryConditions: List + get() { + return when (this) { + is Bankrolls -> comparison() + is Games -> comparison() + is TournamentFeatures-> comparison() + is TournamentNames-> comparison() + is Locations -> comparison() + is SimpleCriteria -> comparison() + is Limits -> comparison() + is TournamentTypes -> comparison() + else -> throw PokerAnalyticsException.QueryTypeUnhandled + } + } + + companion object { + inline fun < reified S : QueryCondition.QueryDataCondition, reified T : Identifiable > compare(): List { + val objects = arrayListOf() + val realm = Realm.getDefaultInstance() + realm.where().findAll().forEach { + objects.add((QueryCondition.getInstance() as S).apply { + setObject(it) + }) + } + realm.close() + return objects + } + + inline fun < reified S : QueryCondition.SingleValueQueryCondition > compare(values:List): List { + val objects = arrayListOf() + values.forEach { + objects.add((S::class.java.newInstance()).apply { + setValue(it) + }) + } + return objects + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/comparison/Comparator.kt b/app/src/main/java/net/pokeranalytics/android/model/comparison/Comparator.kt index 7273fddc..7501a1fc 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/comparison/Comparator.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/comparison/Comparator.kt @@ -4,6 +4,8 @@ import io.realm.Realm import io.realm.Sort import io.realm.kotlin.where import net.pokeranalytics.android.exceptions.PokerAnalyticsException +import net.pokeranalytics.android.model.Criteria +import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.realm.* import java.util.* @@ -36,7 +38,7 @@ enum class Comparator { TOURNAMENT_ENTRY_FEE -> { val fees = arrayListOf() val realm = Realm.getDefaultInstance() - val fieldName = Session.fieldNameForQueryType(QueryCondition.BETWEEN_TOURNAMENT_FEE()) + val fieldName = Session.fieldNameForQueryType(QueryCondition.BETWEEN_TOURNAMENT_FEE::class.java)!! realm.where().distinct(fieldName).findAll().sort(fieldName, Sort.ASCENDING).map { it.tournamentEntryFee?.let { fee -> fees.add(QueryCondition.BETWEEN_TOURNAMENT_FEE().apply { between(fee, fee) }) @@ -77,51 +79,11 @@ enum class Comparator { realm.close() blinds } - GAME -> { - val objects = arrayListOf() - val realm = Realm.getDefaultInstance() - realm.where().findAll().forEach { - objects.add(QueryCondition.GAME().apply { setObjectId(it.id)}) - } - realm.close() - objects - } - BANKROLL -> { - val objects = arrayListOf() - val realm = Realm.getDefaultInstance() - realm.where().findAll().forEach { - objects.add(QueryCondition.BANKROLL().apply { setObjectId(it.id)}) - } - realm.close() - objects - } - LOCATION -> { - val objects = arrayListOf() - val realm = Realm.getDefaultInstance() - realm.where().findAll().forEach { - objects.add(QueryCondition.LOCATION().apply { setObjectId(it.id)}) - } - realm.close() - objects - } - TOURNAMENT_NAME -> { - val objects = arrayListOf() - val realm = Realm.getDefaultInstance() - realm.where().findAll().forEach { - objects.add(QueryCondition.TOURNAMENT_NAME().apply { setObjectId(it.id)}) - } - realm.close() - objects - } - TOURNAMENT_FEATURE -> { - val objects = arrayListOf() - val realm = Realm.getDefaultInstance() - realm.where().findAll().forEach { - objects.add(QueryCondition.ANY_TOURNAMENT_FEATURES().apply { setObjectId(it.id)}) - } - realm.close() - objects - } + BANKROLL -> Criteria.Bankrolls.queryConditions + GAME -> Criteria.Games.queryConditions + TOURNAMENT_NAME-> Criteria.TournamentNames.queryConditions + TOURNAMENT_FEATURE-> Criteria.TournamentFeatures.queryConditions + LOCATION-> Criteria.Locations.queryConditions LIMIT_TYPE -> { val limits = arrayListOf() val realm = Realm.getDefaultInstance() diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt index dd202e69..4ada37f8 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt @@ -56,7 +56,7 @@ class FilterHelper { companion object { - inline fun fieldNameForQueryType(queryCondition: QueryCondition): String? { + inline fun fieldNameForQueryType(queryCondition: Class< out QueryCondition>): String? { return when (T::class.java) { Session::class.java -> Session.fieldNameForQueryType(queryCondition) diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt index 9d39f9ed..503bf509 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt @@ -1,9 +1,12 @@ package net.pokeranalytics.android.model.filter +import io.realm.* +import io.realm.internal.Table +import io.realm.kotlin.where import io.realm.RealmQuery import net.pokeranalytics.android.exceptions.PokerAnalyticsException -import net.pokeranalytics.android.model.realm.FilterCondition -import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.model.interfaces.Identifiable +import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.util.extensions.endOfDay import net.pokeranalytics.android.util.extensions.startOfDay import java.util.* @@ -33,10 +36,12 @@ inline fun List.queryWith(query: RealmQ sealed class QueryCondition(var operator: Operator? = null) { - abstract class QueryDataCondition : QueryCondition() - fun setObjectId(id:String) { - this.valueMap = mapOf("ids" to id) + abstract class QueryDataCondition < T: Identifiable> : QueryCondition() { + fun setObject(dataObject:T) { + this.valueMap = mapOf("ids" to arrayListOf(dataObject.id)) } + } + class MoreQueryCondition : QueryCondition(Operator.MORE) class LessQueryCondition : QueryCondition(Operator.LESS) @@ -47,6 +52,25 @@ sealed class QueryCondition(var operator: Operator? = null) { val instance = kClass.objectInstance ?: kClass.java.newInstance() return instance as QueryCondition } + + inline fun getInstance(): QueryCondition { + return when (T::class.java) { + is Bankroll -> BANKROLL() + else -> throw PokerAnalyticsException.QueryTypeUnhandled + } + } + + inline fun < reified T: Filterable, reified S: QueryCondition>distinct(): RealmResults? { + FilterHelper.fieldNameForQueryType(S::class.java)?.let { + val realm = Realm.getDefaultInstance() + val distincts = realm.where().distinct(it).findAll().sort(it, Sort.ASCENDING) + realm.close() + return distincts + } + return null + } + + } val name: String = this::class.simpleName ?: throw PokerAnalyticsException.FilterElementUnknownName @@ -60,29 +84,35 @@ sealed class QueryCondition(var operator: Operator? = null) { ; } + open class SingleValueQueryCondition : QueryCondition() { + fun setValue(value:Int) { + this.valueMap = mapOf("values" to arrayListOf(value)) + } + } + object LIVE : QueryCondition() object CASH : QueryCondition() object ONLINE : QueryCondition() object TOURNAMENT: QueryCondition() - class BANKROLL: QueryDataCondition() - class GAME: QueryCondition() - class TOURNAMENT_NAME: QueryCondition() - class ANY_TOURNAMENT_FEATURES: QueryCondition() - class ALL_TOURNAMENT_FEATURES: QueryCondition() - class LOCATION: QueryCondition() - class LIMIT: QueryCondition() { + class BANKROLL: QueryDataCondition() + class GAME: QueryDataCondition() + class TOURNAMENT_NAME: QueryDataCondition() + class ANY_TOURNAMENT_FEATURES: QueryDataCondition() + class ALL_TOURNAMENT_FEATURES: QueryDataCondition() + class LOCATION: QueryDataCondition() + class LIMIT: SingleValueQueryCondition() { fun setLimitType(limitType: Int) { this.valueMap = mapOf("values" to limitType) } } - class TABLE_SIZE: QueryCondition() { + class TABLE_SIZE: SingleValueQueryCondition() { fun setNumberOfPlayer(numberOfPlayer: Int) { this.valueMap = mapOf("values" to numberOfPlayer) } } - class TOURNAMENT_TYPE: QueryCondition() { + class TOURNAMENT_TYPE: SingleValueQueryCondition() { fun setTournamentType(tournamentType:Int) { this.valueMap = mapOf("values" to tournamentType) } @@ -204,7 +234,7 @@ sealed class QueryCondition(var operator: Operator? = null) { * providing a base RealmQuery [realmQuery], the method is able to attached the corresponding query and returns the newly formed [RealmQuery] */ inline fun queryWith(realmQuery: RealmQuery): RealmQuery { - val fieldName = FilterHelper.fieldNameForQueryType(this) + val fieldName = FilterHelper.fieldNameForQueryType(this::class.java) fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown when (operator) { Operator.LESS -> { diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt index fd3aa17a..513040e9 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt @@ -56,8 +56,11 @@ open class ComputableResult() : RealmObject(), Computable, Filterable { companion object { - fun fieldNameForQueryType(queryCondition: QueryCondition): String? { - return "session." + Session.fieldNameForQueryType(queryCondition) + fun fieldNameForQueryType(queryCondition: Class < out QueryCondition >): String? { + Session.fieldNameForQueryType(queryCondition)?.let { + return "session.$it" + } + return null } } 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 934528ee..49a3b80c 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 @@ -63,33 +63,33 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat return realm.copyToRealm(session) } - fun fieldNameForQueryType(queryCondition: QueryCondition): String? { - return when (queryCondition) { - LIVE, ONLINE -> "bankroll.live" - CASH, TOURNAMENT -> "type" - is BANKROLL -> "bankroll.id" - is GAME -> "game.id" - is TOURNAMENT_NAME -> "tournamentName.id" - is ANY_TOURNAMENT_FEATURES, is ALL_TOURNAMENT_FEATURES -> "tournamentFeatures.id" - is LOCATION -> "location.id" - is LIMIT -> "limit" - is TABLE_SIZE -> "tableSize" - is TOURNAMENT_TYPE -> "tournamentType" - is BLIND -> "blinds" - is COMMENT -> "comment" - is BETWEEN_NUMBER_OF_TABLE, is MORE_NUMBER_OF_TABLE, is LESS_NUMBER_OF_TABLE -> "numberOfTable" - is MORE_THAN_NET_RESULT, is LESS_THAN_NET_RESULT -> "computableResults.ratedNet" - is MORE_THAN_BUY_IN, is LESS_THAN_BUY_IN -> "result.buyin" - is MORE_THAN_CASH_OUT, is LESS_THAN_CASH_OUT -> "result.cashout" - is MORE_THAN_TIPS, is LESS_THAN_TIPS -> "result.tips" - is MORE_THAN_NUMBER_OF_PLAYER, is LESS_THAN_NUMBER_OF_PLAYER, is BETWEEN_NUMBER_OF_PLAYER -> "tournamentNumberOfPlayers" - is MORE_THAN_TOURNAMENT_FEE, is LESS_THAN_TOURNAMENT_FEE, is BETWEEN_TOURNAMENT_FEE -> "tournamentEntryFee" - is STARTED_FROM_DATE, is STARTED_TO_DATE -> "startDate" - is ENDED_FROM_DATE, is ENDED_TO_DATE -> "endDate" - is DAY_OF_WEEK, is WEEK_END, is WEEK_DAY -> "dayOfWeek" - is MONTH -> "month" - is YEAR -> "year" - TODAY, YESTERDAY, TODAY_AND_YESTERDAY, THIS_YEAR, THIS_MONTH, THIS_WEEK -> "startDate" + fun fieldNameForQueryType(queryCondition: Class < out QueryCondition >): String? { + return when (queryCondition) { + LIVE::class.java, ONLINE::class.java -> "bankroll.live" + CASH::class.java, TOURNAMENT::class.java -> "type" + BANKROLL::class.java -> "bankroll.id" + GAME::class.java -> "game.id" + TOURNAMENT_NAME::class.java -> "tournamentName.id" + ANY_TOURNAMENT_FEATURES::class.java, ALL_TOURNAMENT_FEATURES::class.java -> "tournamentFeatures.id" + LOCATION::class.java -> "location.id" + LIMIT::class.java -> "limit" + TABLE_SIZE::class.java -> "tableSize" + TOURNAMENT_TYPE::class.java -> "tournamentType" + BLIND::class.java -> "blinds" + COMMENT::class.java -> "comment" + BETWEEN_NUMBER_OF_TABLE::class.java, MORE_NUMBER_OF_TABLE::class.java, LESS_NUMBER_OF_TABLE::class.java -> "numberOfTable" + MORE_THAN_NET_RESULT::class.java, LESS_THAN_NET_RESULT::class.java -> "computableResults.ratedNet" + MORE_THAN_BUY_IN::class.java, LESS_THAN_BUY_IN::class.java -> "result.buyin" + MORE_THAN_CASH_OUT::class.java, LESS_THAN_CASH_OUT::class.java -> "result.cashout" + MORE_THAN_TIPS::class.java, LESS_THAN_TIPS::class.java -> "result.tips" + MORE_THAN_NUMBER_OF_PLAYER::class.java, LESS_THAN_NUMBER_OF_PLAYER::class.java, BETWEEN_NUMBER_OF_PLAYER::class.java -> "tournamentNumberOfPlayers" + MORE_THAN_TOURNAMENT_FEE::class.java, LESS_THAN_TOURNAMENT_FEE::class.java, BETWEEN_TOURNAMENT_FEE::class.java -> "tournamentEntryFee" + STARTED_FROM_DATE::class.java, STARTED_TO_DATE::class.java -> "startDate" + ENDED_FROM_DATE::class.java, ENDED_TO_DATE::class.java -> "endDate" + DAY_OF_WEEK::class.java, WEEK_END::class.java, WEEK_DAY::class.java -> "dayOfWeek" + MONTH::class.java -> "month" + YEAR::class.java -> "year" + TODAY::class.java, YESTERDAY::class.java, TODAY_AND_YESTERDAY::class.java, THIS_YEAR::class.java, THIS_MONTH::class.java, THIS_WEEK::class.java -> "startDate" else -> null } } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt index 51a0bc1c..80d3ed20 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt @@ -102,8 +102,11 @@ open class SessionSet() : RealmObject(), Timed, Filterable { return realm.copyToRealm(sessionSet) } - fun fieldNameForQueryType(queryCondition: QueryCondition): String? { - return "sessions." + Session.fieldNameForQueryType(queryCondition) + fun fieldNameForQueryType(queryCondition: Class < out QueryCondition >): String? { + Session.fieldNameForQueryType(queryCondition)?.let { + return "sessions.$it" + } + return null } }