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 de02cb45..c9698a76 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 @@ -5,6 +5,7 @@ import io.realm.RealmQuery 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.* @@ -38,7 +39,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) }) @@ -79,51 +80,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 a7a7f467..91b4f312 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 @@ -51,7 +51,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 cf5dac46..fa1ae1e9 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,12 +1,13 @@ package net.pokeranalytics.android.model.filter -import io.realm.RealmQuery +import io.realm.* import io.realm.internal.Table +import io.realm.kotlin.where import net.pokeranalytics.android.exceptions.PokerAnalyticsException import net.pokeranalytics.android.model.Limit import net.pokeranalytics.android.model.TableSize -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.* @@ -24,10 +25,12 @@ fun List.name() : String { 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) @@ -38,6 +41,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 @@ -51,29 +73,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) } @@ -195,7 +223,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 filter(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..04589945 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,7 +56,7 @@ open class ComputableResult() : RealmObject(), Computable, Filterable { companion object { - fun fieldNameForQueryType(queryCondition: QueryCondition): String? { + fun fieldNameForQueryType(queryCondition: Class < out QueryCondition >): String? { return "session." + Session.fieldNameForQueryType(queryCondition) } 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 81a4d522..c594b099 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 @@ -62,33 +62,33 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat return realm.copyToRealm(session) } - fun fieldNameForQueryType(queryCondition: QueryCondition): String? { + fun fieldNameForQueryType(queryCondition: Class < out 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" + LIVE::class, ONLINE::class -> "bankroll.live" + CASH::class, TOURNAMENT::class -> "type" + BANKROLL::class -> "bankroll.id" + GAME::class -> "game.id" + TOURNAMENT_NAME::class -> "tournamentName.id" + ANY_TOURNAMENT_FEATURES::class, ALL_TOURNAMENT_FEATURES::class -> "tournamentFeatures.id" + LOCATION::class -> "location.id" + LIMIT::class -> "limit" + TABLE_SIZE::class -> "tableSize" + TOURNAMENT_TYPE::class -> "tournamentType" + BLIND::class -> "blinds" + COMMENT::class -> "comment" + BETWEEN_NUMBER_OF_TABLE::class, MORE_NUMBER_OF_TABLE::class, LESS_NUMBER_OF_TABLE::class -> "numberOfTable" + MORE_THAN_NET_RESULT::class, LESS_THAN_NET_RESULT::class -> "computableResults.ratedNet" + MORE_THAN_BUY_IN::class, LESS_THAN_BUY_IN::class -> "result.buyin" + MORE_THAN_CASH_OUT::class, LESS_THAN_CASH_OUT::class -> "result.cashout" + MORE_THAN_TIPS::class, LESS_THAN_TIPS::class -> "result.tips" + MORE_THAN_NUMBER_OF_PLAYER::class, LESS_THAN_NUMBER_OF_PLAYER::class, BETWEEN_NUMBER_OF_PLAYER::class -> "tournamentNumberOfPlayers" + MORE_THAN_TOURNAMENT_FEE::class, LESS_THAN_TOURNAMENT_FEE::class, BETWEEN_TOURNAMENT_FEE::class -> "tournamentEntryFee" + STARTED_FROM_DATE::class, STARTED_TO_DATE::class -> "startDate" + ENDED_FROM_DATE::class, ENDED_TO_DATE::class -> "endDate" + DAY_OF_WEEK::class, WEEK_END::class, WEEK_DAY::class -> "dayOfWeek" + MONTH::class -> "month" + YEAR::class -> "year" + TODAY::class, YESTERDAY::class, TODAY_AND_YESTERDAY::class, THIS_YEAR::class, THIS_MONTH::class, THIS_WEEK::class -> "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 8842e1d7..6f6a4eee 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 @@ -120,7 +120,7 @@ open class SessionSet() : RealmObject(), Timed, Filterable { return realm.copyToRealm(sessionSet) } - fun fieldNameForQueryType(queryCondition: QueryCondition): String? { + fun fieldNameForQueryType(queryCondition: Class < out QueryCondition >): String? { return "sessions." + Session.fieldNameForQueryType(queryCondition) }