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 0015672a..db9c8813 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 @@ -35,854 +35,939 @@ import kotlin.collections.ArrayList sealed class QueryCondition : FilterElementRow { - companion object { - inline fun < reified T:QueryCondition> more():T { return T::class.java.newInstance().apply { this.operator = Operator.MORE } } - inline fun < reified T:QueryCondition> less():T { return T::class.java.newInstance().apply { this.operator = Operator.LESS } } - inline fun < reified T:QueryCondition> moreOrLess():ArrayList { return arrayListOf(more(), less()) } - - fun valueOf(name:String) : T { - val kClass = Class.forName("${QueryCondition::class.qualifiedName}$$name").kotlin - val instance = kClass.objectInstance ?: kClass.java.newInstance() - return instance as T - } - - inline fun getInstance(): QueryCondition { - return when (T::class.java) { - Bankroll::class.java -> AnyBankroll() - Game::class.java -> AnyGame() - Location::class.java -> AnyLocation() - TransactionType::class.java -> AnyTransactionType() - TournamentName::class.java -> AnyTournamentName() - TournamentFeature::class.java -> AllTournamentFeature() - else -> throw PokerAnalyticsException.QueryTypeUnhandled - } - } - - inline fun < reified T: Filterable, reified S: QueryCondition, reified U:Comparable>distinct(): RealmResults? { - FilterHelper.fieldNameForQueryType(S::class.java)?.let { - val realm = Realm.getDefaultInstance() - - val distincts = when (T::class) { - String::class, Int::class -> realm.where().distinct(it).findAll().sort(it, Sort.ASCENDING) - else -> realm.where().isNotNull(it).findAll().sort(it, Sort.ASCENDING) - } - - realm.close() - return distincts - } - return null - } - } - - enum class Operator { - ANY, - ALL, - MORE, - LESS, - EQUALS, - TRUE, - ; - } - - val baseId = this::class.simpleName ?: throw PokerAnalyticsException.FilterElementUnknownName - - val groupId: String - get() { - when (this.operator) { - Operator.MORE, Operator.LESS -> return "${this.operator.name.toLowerCase().capitalize()}$baseId" - } - return baseId - } - - val id: List get() { - when (this.operator) { - Operator.MORE, Operator.LESS -> return listOf("$baseId+${this.operator.name}") - } - - return when (this) { - is SingleValue<*> -> listOf(baseId) - is ListOfValues<*> -> { - if (listOfValues.isEmpty()) { return listOf(baseId) } - this.listOfValues.map{ "$baseId+$it" } - } - else -> listOf(baseId) - } - } - - abstract var operator: Operator - - abstract class ListOfValues: QueryCondition(), Comparable> where T:Comparable { - - abstract var listOfValues: ArrayList - abstract fun labelForValue(value:T, context: Context): String - - open fun entityName(context: Context): String { - return getDisplayName(context) - } - - override fun getDisplayName(context: Context): String { - val prefix = this.resId?.let { - context.getString(it)+" " - } ?: "" - - return when (listOfValues.size) { - 0 -> return NULL_TEXT - 1,2 -> prefix+ listOfValues.map { labelForValue(it, context) }.joinToString(", ") - else -> "${listOfValues.size} $prefix ${entityName(context)}" - } - } - - override fun compareTo(other: ListOfValues): Int { - return listOfValues.sorted().first().compareTo(other.listOfValues.sorted().first()) - } - - fun firstValue(context:Context): String? { - return this.listOfValues.firstOrNull()?.let { this.labelForValue(it, context) } - } - } - - abstract class SingleValue: ListOfValues() where T:Comparable { - override var listOfValues = ArrayList() - abstract var singleValue : T? - } - - abstract class ListOfDouble: ListOfValues() { - open var sign: Int = 1 - override var operator: Operator = Operator.ANY - override var listOfValues : ArrayList = arrayListOf() - override fun updateValueBy(filterCondition: FilterCondition) { - super.updateValueBy(filterCondition) - listOfValues = filterCondition.getValues() - } - override fun labelForValue(value: Double, context: Context): String { - return value.toCurrency(UserDefaults.currency) - } - } - - abstract class ListOfInt: ListOfValues() { - override var operator: Operator = Operator.ANY - override var listOfValues : ArrayList = arrayListOf() - override fun updateValueBy(filterCondition: FilterCondition) { - super.updateValueBy(filterCondition) - listOfValues = filterCondition.getValues() - } - override fun labelForValue(value: Int, context: Context): String { - return value.toString() - } - } - - abstract class ListOfString: ListOfValues() { - override var operator: Operator = Operator.ANY - override var listOfValues = ArrayList() - override fun labelForValue(value: String, context: Context): String { return value } - override fun updateValueBy(filterCondition: FilterCondition) { - super.updateValueBy(filterCondition) - listOfValues = filterCondition.getValues() - } - } - - abstract class SingleDate: SingleValue() { - override fun labelForValue(value: Date, context: Context): String { - return value.shortDate() - } - - override var listOfValues = ArrayList() - - override var singleValue: Date? - get() { return listOfValues.firstOrNull() } - set(value) { - listOfValues.removeAll(this.listOfValues) - value?.let { listOfValues.add(it) } - } - - override fun updateValueBy(filterCondition: FilterCondition) { - super.updateValueBy(filterCondition) - singleValue = filterCondition.getValue() - } - } - - abstract class SingleInt: SingleValue() { - override fun labelForValue(value: Int, context: Context): String { - return value.toString() - } - - override var singleValue: Int? - get() { return listOfValues.firstOrNull() } - set(value) { - listOfValues.removeAll(this.listOfValues) - value?.let { listOfValues.add(it) } - } - - override fun updateValueBy(filterCondition: FilterCondition) { - super.updateValueBy(filterCondition) - singleValue = filterCondition.getValue() - } - } - - override fun getDisplayName(context: Context): String { - this.resId?.let { - return context.getString(it) - } - return baseId - } - - override var filterSectionRow: FilterSectionRow = FilterSectionRow.CashOrTournament - - abstract class QueryDataCondition < T: NameManageable > : ListOfString() { - fun setObject(dataObject: T) { - this.listOfValues.removeAll(this.listOfValues) - this.listOfValues.add(dataObject.id) - } - - abstract val entity : Class - - override fun getDisplayName(context: Context): String { - val realm = Realm.getDefaultInstance() - val entityName = entityName(realm) - val completeLabel = when (listOfValues.size) { - 0 -> NULL_TEXT - 1,2 -> { - listOfValues.map { labelForValue(realm, it) }.joinToString(", ") - } - else -> "${listOfValues.size} $entityName" - } - realm.close() - return completeLabel - } - - open fun entityName(realm: Realm): String { - return baseId - } - - private fun labelForValue(realm:Realm, value:String): String { - val query = realm.where(entity) - return query.equalTo("id", value).findFirst()?.name ?: NULL_TEXT - } - } - - - interface DateTime { - val showTime: Boolean - } - - abstract class DateQuery: SingleDate(), DateTime { - override val showTime: Boolean = false - - override fun labelForValue(value: Date, context: Context): String { - return singleValue?.let { - if (showTime) { - it.shortTime() - } else { - it.shortDate() - } - } ?: NULL_TEXT - } - } - - abstract class TimeQuery: DateQuery() { - override val showTime: Boolean = true - } - - abstract class TrueQueryCondition: QueryCondition() { - override var operator: Operator = Operator.TRUE - } - - object IsLive : TrueQueryCondition() - - object IsCash : TrueQueryCondition() - - object IsOnline : TrueQueryCondition() - - object IsTournament : TrueQueryCondition() - - class AnyBankroll(): QueryDataCondition() { - override var entity: Class = Bankroll::class.java - constructor(bankroll: Bankroll): this() { - this.setObject(bankroll) - } - } - - class AnyGame(): QueryDataCondition() { - override val entity: Class = Game::class.java - constructor(game: Game): this() { - this.setObject(game) - } - } - - class AnyTournamentName(): QueryDataCondition() { - override val entity: Class = TournamentName::class.java - constructor(tournamentName: TournamentName): this() { - this.setObject(tournamentName) - } - } - - class AnyTournamentFeature(): QueryDataCondition() { - override val entity: Class = TournamentFeature::class.java - constructor(tournamentFeature: TournamentFeature): this() { - this.setObject(tournamentFeature) - } - } - - class AllTournamentFeature(): QueryDataCondition() { - override var operator = Operator.ALL - override val entity: Class = TournamentFeature::class.java - constructor(tournamentFeature: TournamentFeature): this() { - this.setObject(tournamentFeature) - } - } - - class AnyLocation(): QueryDataCondition() { - override val entity: Class = Location::class.java - constructor(location: Location): this() { - this.setObject(location) - } - } - - class AnyTransactionType(): QueryDataCondition() { - override val entity: Class = TransactionType::class.java - constructor(transactionType: TransactionType): this() { - this.setObject(transactionType) - } - } - - class AnyLimit: ListOfInt() { - override fun labelForValue(value: Int, context: Context): String { - return Limit.values()[value].getDisplayName(context) - } - } - - class AnyTableSize: ListOfInt() { - override fun labelForValue(value: Int, context: Context): String { - return TableSize(value).getDisplayName(context) - } - } - - class AnyTournamentType: ListOfInt() { - override fun labelForValue(value: Int, context: Context): String { - return TournamentType.values()[value].getDisplayName(context) - } - } - - class AnyBlind: ListOfString() - - object Last: SingleInt() { - override var operator = Operator.EQUALS - override fun getDisplayName(context: Context): String { - //TODO update string "last %i" - return "${context.getString(R.string.last_i_records)} $singleValue" - } - } - - class NumberOfTable: ListOfInt() { - override fun labelForValue(value: Int, context: Context): String { - return value.toString()+" "+context.getString(R.string.tables) - } - - override fun entityName(context: Context): String { - return "" - } - } - - class NumberOfRebuy(): ListOfDouble() { - constructor(operator: Operator, numberOfRebuy: Double) : this() { - this.operator = operator - this.listOfValues = arrayListOf(numberOfRebuy) - } - - override fun labelForValue(value: Double, context: Context): String { - return value.toString() - } - } - - class TournamentFinalPosition(): ListOfInt() { - constructor(operator: Operator, finalPosition: Int) : this() { - this.operator = operator - this.listOfValues = arrayListOf(finalPosition) - } - - override fun labelForValue(value: Int, context: Context): String { - val nf = RuleBasedNumberFormat(Locale.getDefault(), RuleBasedNumberFormat.ORDINAL) - return nf.format(value)+" "+context.getString(R.string.position) - } - - override fun entityName(context: Context): String { - return "" - } - } - - open class NetAmount: ListOfDouble() - - class NetAmountWon: NetAmount() - class NetAmountLost: NetAmount() { override var sign: Int = -1 } - - class TournamentNumberOfPlayer: ListOfInt() { - override fun labelForValue(value: Int, context: Context): String { - return value.toString()+" "+context.getString(R.string.number_of_players) - } - - override fun entityName(context: Context): String { - return "" - } - } - - class StartedFromDate: DateQuery() { override var operator = Operator.MORE } - class StartedToDate: DateQuery() { override var operator = Operator.LESS } - class EndedFromDate: DateQuery() { override var operator = Operator.MORE } - class EndedToDate: DateQuery() { override var operator = Operator.LESS } - - class AnyDayOfWeek: ListOfInt() { - override fun labelForValue(value: Int, context: Context): String { - return DateFormatSymbols.getInstance(Locale.getDefault()).weekdays[value].capitalize() - } - } - - class AnyMonthOfYear(): ListOfInt() { - override fun labelForValue(value: Int, context: Context): String { - return DateFormatSymbols.getInstance(Locale.getDefault()).months[value].capitalize() - } - - constructor(month:Int) : this() { - listOfValues = arrayListOf(month) - } - } - - class AnyYear(): ListOfInt() { - override fun labelForValue(value: Int, context: Context): String { - return "$value" - } - - constructor(year:Int) : this() { - listOfValues = arrayListOf(year) - } - } - - object IsWeekDay: TrueQueryCondition() - object IsWeekEnd: TrueQueryCondition() - object IsToday: TrueQueryCondition() - object WasYesterday: TrueQueryCondition() - object WasTodayAndYesterday: TrueQueryCondition() - object DuringThisWeek: TrueQueryCondition() - object DuringThisMonth: TrueQueryCondition() - object DuringThisYear: TrueQueryCondition() - - class TournamentFee: ListOfDouble() { - override fun labelForValue(value: Double, context: Context): String { - return value.toCurrency(UserDefaults.currency) - } - } - - class PastDay: SingleInt() { - override var operator = Operator.EQUALS - override val viewType: Int = RowViewType.TITLE_VALUE_CHECK.ordinal - - override fun labelForValue(value: Int, context: Context): String { - return value.toString() - } - - override fun entityName(context: Context): String { - return this.resId?.let { - " "+context.getString(it) - } ?: "" - } - } - - class Duration: SingleInt() { - override var operator = Operator.EQUALS - var minutes:Int? - get() { return singleValue } - set(value) { singleValue = value } - - val netDuration: Long? - get() { - minutes?.let { - return (it*60*1000).toLong() - } - return null - } - - override val viewType: Int = RowViewType.TITLE_VALUE_CHECK.ordinal - override val bottomSheetType: BottomSheetType = BottomSheetType.DOUBLE_EDIT_TEXT - - override fun labelForValue(value: Int, context: Context): String { - return value.toMinutes(context) - } - } - - class StartedFromTime(): TimeQuery() { - override var operator = Operator.MORE - constructor(date:Date): this() { - singleValue = date - } - - - } - - class EndedToTime(): TimeQuery() { - override var operator = Operator.LESS - constructor(date:Date): this() { - singleValue = date - } - - } - - interface CustomFieldRelated { - var customFieldId : String - - fun customFieldName(realm: Realm): String { - val query = realm.where(CustomField::class.java) - val name = query.equalTo("id", customFieldId).findFirst()?.name - return name?.let { - "$it " - } ?: run { "" } - } - } - - class CustomFieldQuery() : QueryDataCondition() { - override var entity: Class = CustomField::class.java - constructor(customField: CustomField): this() { - this.setObject(customField) - } - } - - open class CustomFieldNumberQuery() : ListOfDouble(), CustomFieldRelated { - override var customFieldId : String = "" - override var operator: Operator = Operator.EQUALS - constructor(customFieldId: String, value: Double): this() { - this.listOfValues = arrayListOf(value) - this.customFieldId = customFieldId - } - - override fun getDisplayName(context: Context): String { - val realm = Realm.getDefaultInstance() - val name = customFieldName(realm) - val prefix = this.resId?.let { - context.getString(it)+" " - } ?: "" - - val completeLabel = when (listOfValues.size) { - 0 -> return NULL_TEXT - 1,2 -> { - return name+prefix+listOfValues.map { labelForValue(it, context) }.joinToString(", ") - } - else -> "${listOfValues.size} $prefix $name" - } - realm.close() - return completeLabel - } - - override fun labelForValue(value: Double, context: Context): String { - return NumberFormat.getInstance().format(value) - } - - override fun updateValueBy(filterCondition: FilterCondition) { - super.updateValueBy(filterCondition) - listOfValues = filterCondition.getValues() - customFieldId = filterCondition.stringValue ?: throw PokerAnalyticsException.QueryValueMapUnexpectedValue - } - } - - class CustomFieldAmountQuery : CustomFieldNumberQuery() { - override fun labelForValue(value: Double, context: Context): String { - return value.toCurrency(UserDefaults.currency) - } - } - - class CustomFieldListQuery() : QueryDataCondition(), CustomFieldRelated { - override var entity: Class = CustomFieldEntry::class.java - override var customFieldId : String = "" - constructor(customFieldEntry: CustomFieldEntry): this() { - this.setObject(customFieldEntry) - this.customFieldId = customFieldEntry.customField?.id ?: throw PokerAnalyticsException.QueryValueMapUnexpectedValue - } - - override fun entityName(realm: Realm): String { - return customFieldName(realm) - } - - override fun updateValueBy(filterCondition: FilterCondition) { - super.updateValueBy(filterCondition) - listOfValues = filterCondition.getValues() - customFieldId = filterCondition.stringValue ?: throw PokerAnalyticsException.QueryValueMapUnexpectedValue - } - } - - /** - * 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] - */ - inline fun queryWith(realmQuery: RealmQuery, otherQueryCondition:QueryCondition? = null): RealmQuery { - val fieldName = FilterHelper.fieldNameForQueryType(this::class.java) - if (BuildConfig.DEBUG) { - fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown - } - fieldName ?: return realmQuery - - when (this) { - //is Between -> realmQuery.between(fieldName, leftValue, rightValue) - //is BetweenLeftExclusive -> realmQuery.greaterThan(fieldName, leftValue).and().lessThanOrEqualTo(fieldName, rightValue) - //is BetweenRightExclusive -> realmQuery.greaterThanOrEqualTo(fieldName, leftValue).and().lessThan(fieldName, rightValue) - is IsLive, is IsOnline -> return realmQuery.equalTo(fieldName, this == IsLive) - is IsCash -> return realmQuery.equalTo(fieldName, Session.Type.CASH_GAME.ordinal) - is IsTournament -> return realmQuery.equalTo(fieldName, Session.Type.TOURNAMENT.ordinal) - is IsWeekEnd, is IsWeekDay -> { - var query = realmQuery - if (this == IsWeekDay) { - query = realmQuery.not() - } - return query.`in`(fieldName, arrayOf(Calendar.SATURDAY, Calendar.SUNDAY)) - } - is IsToday -> { - val startDate = Date() - return realmQuery.greaterThanOrEqualTo(fieldName, startDate.startOfDay()).and().lessThanOrEqualTo(fieldName, startDate.endOfDay()) - } - is WasTodayAndYesterday -> { - val startDate = Date() - val calendar = Calendar.getInstance() - calendar.time = startDate - calendar.add(Calendar.HOUR_OF_DAY, -24) - return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and().lessThanOrEqualTo(fieldName, startDate.endOfDay()) - } - is WasYesterday -> { - val calendar = Calendar.getInstance() - calendar.time = Date() - calendar.add(Calendar.HOUR_OF_DAY, -24) - return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and().lessThanOrEqualTo(fieldName, calendar.time.endOfDay()) - } - is PastDay -> { - singleValue?.let { - val startDate = Date() - val calendar = Calendar.getInstance() - calendar.time = startDate - calendar.add(Calendar.DAY_OF_YEAR, -it) - return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and().lessThanOrEqualTo(fieldName, startDate.endOfDay()) - } - return realmQuery - } - is DuringThisWeek -> { - val startDate = Date() - val calendar = Calendar.getInstance() - calendar.time = startDate - calendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, Calendar.SUNDAY) - return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and().lessThanOrEqualTo(fieldName, startDate.endOfDay()) - } - is DuringThisMonth -> { - val startDate = Date() - val calendar = Calendar.getInstance() - calendar.time = startDate - calendar.set(Calendar.DAY_OF_MONTH, 1) - return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and().lessThanOrEqualTo(fieldName, startDate.endOfDay()) - } - is DuringThisYear -> { - val startDate = Date() - val calendar = Calendar.getInstance() - calendar.time = startDate - calendar.set(Calendar.DAY_OF_YEAR, 1) - return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and().lessThanOrEqualTo(fieldName, startDate.endOfDay()) - } - is StartedFromTime -> { - val calendar = Calendar.getInstance() - singleValue?.let { - calendar.time = it - realmQuery.greaterThanOrEqualTo(fieldName, calendar.hourMinute()) - if (otherQueryCondition is EndedToTime) { - otherQueryCondition.singleValue?.let {endTime -> - calendar.time = endTime - realmQuery.lessThanOrEqualTo(fieldName, calendar.hourMinute()) - } - } - } - return realmQuery - } - is EndedToTime -> { - val calendar = Calendar.getInstance() - singleValue?.let { - calendar.time = singleValue - realmQuery.lessThanOrEqualTo(fieldName, calendar.hourMinute()) - if (otherQueryCondition is StartedFromTime) { - otherQueryCondition.singleValue?.let { startTime -> - calendar.time = startTime - realmQuery.greaterThanOrEqualTo(fieldName, calendar.hourMinute()) - } - } - } - return realmQuery - } - } - - if (this is CustomFieldRelated) { - FilterHelper.fieldNameForQueryType(CustomFieldQuery::class.java)?.let { - realmQuery.equalTo(it, customFieldId) - } - } - - if (this is ListOfValues<*>) { - if (this.listOfValues.isEmpty()) { - if (BuildConfig.DEBUG) { - throw PokerAnalyticsException.FilterElementExpectedValueMissing - } - return realmQuery - } - } - - return when (operator) { - Operator.EQUALS -> { - when (this) { - is SingleDate -> realmQuery.equalTo(fieldName, singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) - is SingleInt -> realmQuery.equalTo(fieldName, singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) - is ListOfInt -> realmQuery.equalTo(fieldName, listOfValues.first()) - is ListOfDouble -> realmQuery.equalTo(fieldName, listOfValues.first() * sign) - is ListOfString -> realmQuery.equalTo(fieldName, listOfValues.first()) - else -> realmQuery - } - } - Operator.MORE -> { - when (this) { - is SingleDate -> realmQuery.greaterThanOrEqualTo(fieldName, singleValue?.startOfDay()?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) - is Duration -> realmQuery.greaterThanOrEqualTo(fieldName, netDuration?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) - is SingleInt -> realmQuery.greaterThanOrEqualTo(fieldName, singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) - is ListOfInt -> realmQuery.greaterThanOrEqualTo(fieldName, listOfValues.first()) - is NetAmountLost -> realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first() * -1) - is ListOfDouble -> realmQuery.greaterThanOrEqualTo(fieldName, listOfValues.first() * sign) - else -> realmQuery - } - } - Operator.LESS -> { - when (this) { - is SingleDate -> realmQuery.lessThanOrEqualTo(fieldName, singleValue?.endOfDay()?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) - is Duration -> realmQuery.lessThanOrEqualTo(fieldName, netDuration?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) - is SingleInt -> realmQuery.lessThanOrEqualTo(fieldName, singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) - is ListOfInt -> realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first()) - is NetAmountLost -> { - realmQuery.greaterThanOrEqualTo(fieldName, listOfValues.first() * -1) - realmQuery.lessThan(fieldName, 0.0) - } - is NetAmountWon -> { - realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first()) - realmQuery.greaterThan(fieldName, 0.0) - } - is ListOfDouble -> realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first() * sign) - else -> realmQuery - } - } - Operator.ALL -> { - when (this) { - is ListOfInt -> { - listOfValues.forEach { realmQuery.equalTo(fieldName, it) } - realmQuery - } - is ListOfDouble -> { - listOfValues.forEach { realmQuery.equalTo(fieldName, it * sign) } - realmQuery - } - is ListOfString -> { - listOfValues.forEach { realmQuery.equalTo(fieldName, it) } - realmQuery - } - else -> realmQuery - } - } - Operator.ANY -> { - when (this) { - is ListOfInt -> realmQuery.`in`(fieldName, listOfValues.toTypedArray()) - is ListOfDouble -> realmQuery.`in`(fieldName, listOfValues.toTypedArray()) - is ListOfString -> realmQuery.`in`(fieldName, listOfValues.toTypedArray()) - else -> realmQuery - } - } - else -> realmQuery - } - } - - open fun updateValueBy(filterCondition: FilterCondition) { - filterCondition.operator?.let { - this.operator = Operator.values()[it] - } - } - - override val viewType: Int - get() { - return when (this) { - is PastDay -> RowViewType.TITLE_VALUE_CHECK.ordinal - else -> { - when (this.operator) { - Operator.MORE -> RowViewType.TITLE_VALUE_CHECK.ordinal - Operator.LESS -> RowViewType.TITLE_VALUE_CHECK.ordinal - else -> RowViewType.TITLE_CHECK.ordinal - } - } - } - } - - override val bottomSheetType: BottomSheetType - get() { - return when (this) { - is PastDay -> BottomSheetType.EDIT_TEXT - else -> { - when (this.operator) { - Operator.MORE -> BottomSheetType.EDIT_TEXT - Operator.LESS -> BottomSheetType.EDIT_TEXT - else -> BottomSheetType.NONE - } - } - } - } - - override val resId: Int? - get() { - return when (this) { - is IsCash -> R.string.cash_game - is IsTournament -> R.string.tournament - is IsToday -> R.string.today - is WasYesterday -> R.string.yesterday - is WasTodayAndYesterday -> R.string.yesterday_and_today - is DuringThisWeek -> R.string.current_week - is DuringThisMonth -> R.string.current_month - is DuringThisYear -> R.string.current_year - is StartedFromDate -> R.string.from - is StartedFromTime -> R.string.from_hour_ - is EndedToDate -> R.string.to - is EndedToTime -> R.string.to_hour_ - is IsLive -> R.string.live - is IsOnline -> R.string.online - is IsWeekDay -> R.string.week_days - is IsWeekEnd -> R.string.weekend - is PastDay -> R.string.period_in_days - is TournamentNumberOfPlayer -> { - when (this.operator) { - Operator.MORE -> R.string.minimum - Operator.LESS -> R.string.maximum - else -> null - } - } - is NetAmountWon -> { - when (this.operator) { - Operator.MORE -> R.string.won_amount_more_than - Operator.LESS -> R.string.won_amount_less_than - else -> null - } - } - is NetAmountLost -> { - when (this.operator) { - Operator.MORE -> R.string.lost_amount_more_than - Operator.LESS -> R.string.lost_amount_less_than - else -> null - } - } - is TournamentFinalPosition -> { - when (this.operator) { - Operator.MORE -> R.string.minimum - Operator.LESS -> R.string.maximum - else -> null - } - } - else -> { - when (this.operator) { - Operator.MORE -> R.string.more_than - Operator.LESS -> R.string.less_than - else -> null - } - } - } - } + companion object { + inline fun more(): T { + return T::class.java.newInstance().apply { this.operator = Operator.MORE } + } + + inline fun less(): T { + return T::class.java.newInstance().apply { this.operator = Operator.LESS } + } + + inline fun moreOrLess(): ArrayList { + return arrayListOf(more(), less()) + } + + fun valueOf(name: String): T { + val kClass = Class.forName("${QueryCondition::class.qualifiedName}$$name").kotlin + val instance = kClass.objectInstance ?: kClass.java.newInstance() + return instance as T + } + + inline fun getInstance(): QueryCondition { + return when (T::class.java) { + Bankroll::class.java -> AnyBankroll() + Game::class.java -> AnyGame() + Location::class.java -> AnyLocation() + TransactionType::class.java -> AnyTransactionType() + TournamentName::class.java -> AnyTournamentName() + TournamentFeature::class.java -> AllTournamentFeature() + else -> throw PokerAnalyticsException.QueryTypeUnhandled + } + } + + inline fun > distinct(): RealmResults? { + FilterHelper.fieldNameForQueryType(S::class.java)?.let { + val realm = Realm.getDefaultInstance() + + val distincts = when (T::class) { + String::class, Int::class -> realm.where().distinct(it).findAll().sort(it, Sort.ASCENDING) + else -> realm.where().isNotNull(it).findAll().sort(it, Sort.ASCENDING) + } + + realm.close() + return distincts + } + return null + } + } + + enum class Operator { + ANY, + ALL, + MORE, + LESS, + EQUALS, + TRUE, + ; + } + + val baseId = this::class.simpleName ?: throw PokerAnalyticsException.FilterElementUnknownName + + val groupId: String + get() { + when (this.operator) { + Operator.MORE, Operator.LESS -> return "${this.operator.name.toLowerCase().capitalize()}$baseId" + } + return baseId + } + + val id: List + get() { + when (this.operator) { + Operator.MORE, Operator.LESS -> return listOf("$baseId+${this.operator.name}") + } + + return when (this) { + is SingleValue<*> -> listOf(baseId) + is ListOfValues<*> -> { + if (listOfValues.isEmpty()) { + return listOf(baseId) + } + this.listOfValues.map { "$baseId+$it" } + } + else -> listOf(baseId) + } + } + + abstract var operator: Operator + + abstract class ListOfValues : QueryCondition(), Comparable> where T : Comparable { + + abstract var listOfValues: ArrayList + abstract fun labelForValue(value: T, context: Context): String + + open fun entityName(context: Context): String { + return getDisplayName(context) + } + + override fun getDisplayName(context: Context): String { + val prefix = this.resId?.let { + context.getString(it) + " " + } ?: "" + + return when (listOfValues.size) { + 0 -> return NULL_TEXT + 1, 2 -> prefix + listOfValues.map { labelForValue(it, context) }.joinToString(", ") + else -> "${listOfValues.size} $prefix ${entityName(context)}" + } + } + + override fun compareTo(other: ListOfValues): Int { + return listOfValues.sorted().first().compareTo(other.listOfValues.sorted().first()) + } + + fun firstValue(context: Context): String? { + return this.listOfValues.firstOrNull()?.let { this.labelForValue(it, context) } + } + } + + abstract class SingleValue : ListOfValues() where T : Comparable { + override var listOfValues = ArrayList() + abstract var singleValue: T? + } + + abstract class ListOfDouble : ListOfValues() { + open var sign: Int = 1 + override var operator: Operator = Operator.ANY + override var listOfValues: ArrayList = arrayListOf() + override fun updateValueBy(filterCondition: FilterCondition) { + super.updateValueBy(filterCondition) + listOfValues = filterCondition.getValues() + } + + override fun labelForValue(value: Double, context: Context): String { + return value.toCurrency(UserDefaults.currency) + } + } + + abstract class ListOfInt : ListOfValues() { + override var operator: Operator = Operator.ANY + override var listOfValues: ArrayList = arrayListOf() + override fun updateValueBy(filterCondition: FilterCondition) { + super.updateValueBy(filterCondition) + listOfValues = filterCondition.getValues() + } + + override fun labelForValue(value: Int, context: Context): String { + return value.toString() + } + } + + abstract class ListOfString : ListOfValues() { + override var operator: Operator = Operator.ANY + override var listOfValues = ArrayList() + override fun labelForValue(value: String, context: Context): String { + return value + } + + override fun updateValueBy(filterCondition: FilterCondition) { + super.updateValueBy(filterCondition) + listOfValues = filterCondition.getValues() + } + } + + abstract class SingleDate : SingleValue() { + override fun labelForValue(value: Date, context: Context): String { + return value.shortDate() + } + + override var listOfValues = ArrayList() + + override var singleValue: Date? + get() { + return listOfValues.firstOrNull() + } + set(value) { + listOfValues.removeAll(this.listOfValues) + value?.let { listOfValues.add(it) } + } + + override fun updateValueBy(filterCondition: FilterCondition) { + super.updateValueBy(filterCondition) + singleValue = filterCondition.getValue() + } + } + + abstract class SingleInt : SingleValue() { + override fun labelForValue(value: Int, context: Context): String { + return value.toString() + } + + override var singleValue: Int? + get() { + return listOfValues.firstOrNull() + } + set(value) { + listOfValues.removeAll(this.listOfValues) + value?.let { listOfValues.add(it) } + } + + override fun updateValueBy(filterCondition: FilterCondition) { + super.updateValueBy(filterCondition) + singleValue = filterCondition.getValue() + } + } + + override fun getDisplayName(context: Context): String { + this.resId?.let { + return context.getString(it) + } + return baseId + } + + override var filterSectionRow: FilterSectionRow = FilterSectionRow.CashOrTournament + + abstract class QueryDataCondition : ListOfString() { + fun setObject(dataObject: T) { + this.listOfValues.removeAll(this.listOfValues) + this.listOfValues.add(dataObject.id) + } + + abstract val entity: Class + + override fun getDisplayName(context: Context): String { + val realm = Realm.getDefaultInstance() + val entityName = entityName(realm) + val completeLabel = when (listOfValues.size) { + 0 -> NULL_TEXT + 1, 2 -> { + listOfValues.map { labelForValue(realm, it) }.joinToString(", ") + } + else -> "${listOfValues.size} $entityName" + } + realm.close() + return completeLabel + } + + open fun entityName(realm: Realm): String { + return baseId + } + + private fun labelForValue(realm: Realm, value: String): String { + val query = realm.where(entity) + return query.equalTo("id", value).findFirst()?.name ?: NULL_TEXT + } + } + + + interface DateTime { + val showTime: Boolean + } + + abstract class DateQuery : SingleDate(), DateTime { + override val showTime: Boolean = false + + override fun labelForValue(value: Date, context: Context): String { + return singleValue?.let { + if (showTime) { + it.shortTime() + } else { + it.shortDate() + } + } ?: NULL_TEXT + } + } + + abstract class TimeQuery : DateQuery() { + override val showTime: Boolean = true + } + + abstract class TrueQueryCondition : QueryCondition() { + override var operator: Operator = Operator.TRUE + } + + object IsLive : TrueQueryCondition() + + object IsCash : TrueQueryCondition() + + object IsOnline : TrueQueryCondition() + + object IsTournament : TrueQueryCondition() + + class AnyBankroll() : QueryDataCondition() { + override var entity: Class = Bankroll::class.java + + constructor(bankroll: Bankroll) : this() { + this.setObject(bankroll) + } + } + + class AnyGame() : QueryDataCondition() { + override val entity: Class = Game::class.java + + constructor(game: Game) : this() { + this.setObject(game) + } + } + + class AnyTournamentName() : QueryDataCondition() { + override val entity: Class = TournamentName::class.java + + constructor(tournamentName: TournamentName) : this() { + this.setObject(tournamentName) + } + } + + class AnyTournamentFeature() : QueryDataCondition() { + override val entity: Class = TournamentFeature::class.java + + constructor(tournamentFeature: TournamentFeature) : this() { + this.setObject(tournamentFeature) + } + } + + class AllTournamentFeature() : QueryDataCondition() { + override var operator = Operator.ALL + override val entity: Class = TournamentFeature::class.java + + constructor(tournamentFeature: TournamentFeature) : this() { + this.setObject(tournamentFeature) + } + } + + class AnyLocation() : QueryDataCondition() { + override val entity: Class = Location::class.java + + constructor(location: Location) : this() { + this.setObject(location) + } + } + + class AnyTransactionType() : QueryDataCondition() { + override val entity: Class = TransactionType::class.java + + constructor(transactionType: TransactionType) : this() { + this.setObject(transactionType) + } + } + + class AnyLimit : ListOfInt() { + override fun labelForValue(value: Int, context: Context): String { + return Limit.values()[value].getDisplayName(context) + } + } + + class AnyTableSize : ListOfInt() { + override fun labelForValue(value: Int, context: Context): String { + return TableSize(value).getDisplayName(context) + } + } + + class AnyTournamentType : ListOfInt() { + override fun labelForValue(value: Int, context: Context): String { + return TournamentType.values()[value].getDisplayName(context) + } + } + + class AnyBlind : ListOfString() + + object Last : SingleInt() { + override var operator = Operator.EQUALS + override fun getDisplayName(context: Context): String { + //TODO update string "last %i" + return "${context.getString(R.string.last_i_records)} $singleValue" + } + } + + class NumberOfTable : ListOfInt() { + override fun labelForValue(value: Int, context: Context): String { + return value.toString() + " " + context.getString(R.string.tables) + } + + override fun entityName(context: Context): String { + return "" + } + } + + class NumberOfRebuy() : ListOfDouble() { + constructor(operator: Operator, numberOfRebuy: Double) : this() { + this.operator = operator + this.listOfValues = arrayListOf(numberOfRebuy) + } + + override fun labelForValue(value: Double, context: Context): String { + return value.toString() + } + } + + class TournamentFinalPosition() : ListOfInt() { + constructor(operator: Operator, finalPosition: Int) : this() { + this.operator = operator + this.listOfValues = arrayListOf(finalPosition) + } + + override fun labelForValue(value: Int, context: Context): String { + val nf = RuleBasedNumberFormat(Locale.getDefault(), RuleBasedNumberFormat.ORDINAL) + return nf.format(value) + " " + context.getString(R.string.position) + } + + override fun entityName(context: Context): String { + return "" + } + } + + open class NetAmount : ListOfDouble() + + class NetAmountWon : NetAmount() + class NetAmountLost : NetAmount() { + override var sign: Int = -1 + } + + class TournamentNumberOfPlayer : ListOfInt() { + override fun labelForValue(value: Int, context: Context): String { + return value.toString() + " " + context.getString(R.string.number_of_players) + } + + override fun entityName(context: Context): String { + return "" + } + } + + class StartedFromDate : DateQuery() { + override var operator = Operator.MORE + } + + class StartedToDate : DateQuery() { + override var operator = Operator.LESS + } + + class EndedFromDate : DateQuery() { + override var operator = Operator.MORE + } + + class EndedToDate : DateQuery() { + override var operator = Operator.LESS + } + + class AnyDayOfWeek : ListOfInt() { + override fun labelForValue(value: Int, context: Context): String { + return DateFormatSymbols.getInstance(Locale.getDefault()).weekdays[value].capitalize() + } + } + + class AnyMonthOfYear() : ListOfInt() { + override fun labelForValue(value: Int, context: Context): String { + return DateFormatSymbols.getInstance(Locale.getDefault()).months[value].capitalize() + } + + constructor(month: Int) : this() { + listOfValues = arrayListOf(month) + } + } + + class AnyYear() : ListOfInt() { + override fun labelForValue(value: Int, context: Context): String { + return "$value" + } + + constructor(year: Int) : this() { + listOfValues = arrayListOf(year) + } + } + + object IsWeekDay : TrueQueryCondition() + object IsWeekEnd : TrueQueryCondition() + object IsToday : TrueQueryCondition() + object WasYesterday : TrueQueryCondition() + object WasTodayAndYesterday : TrueQueryCondition() + object DuringThisWeek : TrueQueryCondition() + object DuringThisMonth : TrueQueryCondition() + object DuringThisYear : TrueQueryCondition() + + class TournamentFee : ListOfDouble() { + override fun labelForValue(value: Double, context: Context): String { + return value.toCurrency(UserDefaults.currency) + } + } + + class PastDay : SingleInt() { + override var operator = Operator.EQUALS + override val viewType: Int = RowViewType.TITLE_VALUE_CHECK.ordinal + + override fun labelForValue(value: Int, context: Context): String { + return value.toString() + } + + override fun entityName(context: Context): String { + return this.resId?.let { + " " + context.getString(it) + } ?: "" + } + } + + class Duration : SingleInt() { + override var operator = Operator.EQUALS + var minutes: Int? + get() { + return singleValue + } + set(value) { + singleValue = value + } + + val netDuration: Long? + get() { + minutes?.let { + return (it * 60 * 1000).toLong() + } + return null + } + + override val viewType: Int = RowViewType.TITLE_VALUE_CHECK.ordinal + override val bottomSheetType: BottomSheetType = BottomSheetType.DOUBLE_EDIT_TEXT + + override fun labelForValue(value: Int, context: Context): String { + return value.toMinutes(context) + } + } + + class StartedFromTime() : TimeQuery() { + override var operator = Operator.MORE + + constructor(date: Date) : this() { + singleValue = date + } + + + } + + class EndedToTime() : TimeQuery() { + override var operator = Operator.LESS + + constructor(date: Date) : this() { + singleValue = date + } + + } + + interface CustomFieldRelated { + var customFieldId: String + + fun customFieldName(realm: Realm): String { + val query = realm.where(CustomField::class.java) + val name = query.equalTo("id", customFieldId).findFirst()?.name + return name?.let { + "$it " + } ?: run { "" } + } + } + + class CustomFieldQuery() : QueryDataCondition() { + override var entity: Class = CustomField::class.java + + constructor(customField: CustomField) : this() { + this.setObject(customField) + } + } + + open class CustomFieldNumberQuery() : ListOfDouble(), CustomFieldRelated { + + override var customFieldId: String = "" + override var operator: Operator = Operator.EQUALS + + constructor(customFieldId: String, value: Double) : this() { + this.listOfValues = arrayListOf(value) + this.customFieldId = customFieldId + } + + override fun getDisplayName(context: Context): String { + val realm = Realm.getDefaultInstance() + val name = customFieldName(realm) + val prefix = this.resId?.let { + context.getString(it) + " " + } ?: "" + + val completeLabel = when (listOfValues.size) { + 0 -> return NULL_TEXT + 1, 2 -> { + return name + prefix + listOfValues.map { labelForValue(it, context) }.joinToString(", ") + } + else -> "${listOfValues.size} $prefix $name" + } + realm.close() + return completeLabel + } + + override fun labelForValue(value: Double, context: Context): String { + return NumberFormat.getInstance().format(value) + } + + override fun updateValueBy(filterCondition: FilterCondition) { + super.updateValueBy(filterCondition) + listOfValues = filterCondition.getValues() + customFieldId = filterCondition.stringValue ?: throw PokerAnalyticsException.QueryValueMapUnexpectedValue + } + } + + class CustomFieldAmountQuery : CustomFieldNumberQuery() { + override fun labelForValue(value: Double, context: Context): String { + return value.toCurrency(UserDefaults.currency) + } + } + + class CustomFieldListQuery() : QueryDataCondition(), CustomFieldRelated { + override var entity: Class = CustomFieldEntry::class.java + override var customFieldId: String = "" + + constructor(customFieldEntry: CustomFieldEntry) : this() { + this.setObject(customFieldEntry) + this.customFieldId = + customFieldEntry.customField?.id ?: throw PokerAnalyticsException.QueryValueMapUnexpectedValue + } + + override fun entityName(realm: Realm): String { + return customFieldName(realm) + } + + override fun updateValueBy(filterCondition: FilterCondition) { + super.updateValueBy(filterCondition) + listOfValues = filterCondition.getValues() + customFieldId = filterCondition.stringValue ?: throw PokerAnalyticsException.QueryValueMapUnexpectedValue + } + } + + /** + * 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] + */ + inline fun queryWith( + realmQuery: RealmQuery, + otherQueryCondition: QueryCondition? = null + ): RealmQuery { + val fieldName = FilterHelper.fieldNameForQueryType(this::class.java) + if (BuildConfig.DEBUG) { + fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown + } + fieldName ?: return realmQuery + + when (this) { + //is Between -> realmQuery.between(fieldName, leftValue, rightValue) + //is BetweenLeftExclusive -> realmQuery.greaterThan(fieldName, leftValue).and().lessThanOrEqualTo(fieldName, rightValue) + //is BetweenRightExclusive -> realmQuery.greaterThanOrEqualTo(fieldName, leftValue).and().lessThan(fieldName, rightValue) + is IsLive, is IsOnline -> return realmQuery.equalTo(fieldName, this == IsLive) + is IsCash -> return realmQuery.equalTo(fieldName, Session.Type.CASH_GAME.ordinal) + is IsTournament -> return realmQuery.equalTo(fieldName, Session.Type.TOURNAMENT.ordinal) + is IsWeekEnd, is IsWeekDay -> { + var query = realmQuery + if (this == IsWeekDay) { + query = realmQuery.not() + } + return query.`in`(fieldName, arrayOf(Calendar.SATURDAY, Calendar.SUNDAY)) + } + is IsToday -> { + val startDate = Date() + return realmQuery.greaterThanOrEqualTo(fieldName, startDate.startOfDay()).and() + .lessThanOrEqualTo(fieldName, startDate.endOfDay()) + } + is WasTodayAndYesterday -> { + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.add(Calendar.HOUR_OF_DAY, -24) + return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and() + .lessThanOrEqualTo(fieldName, startDate.endOfDay()) + } + is WasYesterday -> { + val calendar = Calendar.getInstance() + calendar.time = Date() + calendar.add(Calendar.HOUR_OF_DAY, -24) + return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and() + .lessThanOrEqualTo(fieldName, calendar.time.endOfDay()) + } + is PastDay -> { + singleValue?.let { + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.add(Calendar.DAY_OF_YEAR, -it) + return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and() + .lessThanOrEqualTo(fieldName, startDate.endOfDay()) + } + return realmQuery + } + is DuringThisWeek -> { + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, Calendar.SUNDAY) + return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and() + .lessThanOrEqualTo(fieldName, startDate.endOfDay()) + } + is DuringThisMonth -> { + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.set(Calendar.DAY_OF_MONTH, 1) + return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and() + .lessThanOrEqualTo(fieldName, startDate.endOfDay()) + } + is DuringThisYear -> { + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.set(Calendar.DAY_OF_YEAR, 1) + return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and() + .lessThanOrEqualTo(fieldName, startDate.endOfDay()) + } + is StartedFromTime -> { + val calendar = Calendar.getInstance() + singleValue?.let { + calendar.time = it + realmQuery.greaterThanOrEqualTo(fieldName, calendar.hourMinute()) + if (otherQueryCondition is EndedToTime) { + otherQueryCondition.singleValue?.let { endTime -> + calendar.time = endTime + realmQuery.lessThanOrEqualTo(fieldName, calendar.hourMinute()) + } + } + } + return realmQuery + } + is EndedToTime -> { + val calendar = Calendar.getInstance() + singleValue?.let { + calendar.time = singleValue + realmQuery.lessThanOrEqualTo(fieldName, calendar.hourMinute()) + if (otherQueryCondition is StartedFromTime) { + otherQueryCondition.singleValue?.let { startTime -> + calendar.time = startTime + realmQuery.greaterThanOrEqualTo(fieldName, calendar.hourMinute()) + } + } + } + return realmQuery + } + } + + if (this is CustomFieldRelated) { + FilterHelper.fieldNameForQueryType(CustomFieldQuery::class.java)?.let { + realmQuery.equalTo(it, customFieldId) + } + } + + if (this is ListOfValues<*>) { + if (this.listOfValues.isEmpty()) { + if (BuildConfig.DEBUG) { + throw PokerAnalyticsException.FilterElementExpectedValueMissing + } + return realmQuery + } + } + + return when (operator) { + Operator.EQUALS -> { + when (this) { + is SingleDate -> realmQuery.equalTo( + fieldName, + singleValue ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing + ) + is SingleInt -> realmQuery.equalTo( + fieldName, + singleValue ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing + ) + is ListOfInt -> realmQuery.equalTo(fieldName, listOfValues.first()) + is ListOfDouble -> realmQuery.equalTo(fieldName, listOfValues.first() * sign) + is ListOfString -> realmQuery.equalTo(fieldName, listOfValues.first()) + else -> realmQuery + } + } + Operator.MORE -> { + when (this) { + is SingleDate -> realmQuery.greaterThanOrEqualTo( + fieldName, + singleValue?.startOfDay() ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing + ) + is Duration -> realmQuery.greaterThanOrEqualTo( + fieldName, + netDuration ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing + ) + is SingleInt -> realmQuery.greaterThanOrEqualTo( + fieldName, + singleValue ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing + ) + is ListOfInt -> realmQuery.greaterThanOrEqualTo(fieldName, listOfValues.first()) + is NetAmountLost -> realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first() * -1) + is ListOfDouble -> realmQuery.greaterThanOrEqualTo(fieldName, listOfValues.first() * sign) + else -> realmQuery + } + } + Operator.LESS -> { + when (this) { + is SingleDate -> realmQuery.lessThanOrEqualTo( + fieldName, + singleValue?.endOfDay() ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing + ) + is Duration -> realmQuery.lessThanOrEqualTo( + fieldName, + netDuration ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing + ) + is SingleInt -> realmQuery.lessThanOrEqualTo( + fieldName, + singleValue ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing + ) + is ListOfInt -> realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first()) + is NetAmountLost -> { + realmQuery.greaterThanOrEqualTo(fieldName, listOfValues.first() * -1) + realmQuery.lessThan(fieldName, 0.0) + } + is NetAmountWon -> { + realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first()) + realmQuery.greaterThan(fieldName, 0.0) + } + is ListOfDouble -> realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first() * sign) + else -> realmQuery + } + } + Operator.ALL -> { + when (this) { + is ListOfInt -> { + listOfValues.forEach { realmQuery.equalTo(fieldName, it) } + realmQuery + } + is ListOfDouble -> { + listOfValues.forEach { realmQuery.equalTo(fieldName, it * sign) } + realmQuery + } + is ListOfString -> { + listOfValues.forEach { realmQuery.equalTo(fieldName, it) } + realmQuery + } + else -> realmQuery + } + } + Operator.ANY -> { + when (this) { + is ListOfInt -> realmQuery.`in`(fieldName, listOfValues.toTypedArray()) + is ListOfDouble -> realmQuery.`in`(fieldName, listOfValues.toTypedArray()) + is ListOfString -> realmQuery.`in`(fieldName, listOfValues.toTypedArray()) + else -> realmQuery + } + } + else -> realmQuery + } + } + + open fun updateValueBy(filterCondition: FilterCondition) { + filterCondition.operator?.let { + this.operator = Operator.values()[it] + } + } + + override val viewType: Int + get() { + return when (this) { + is PastDay -> RowViewType.TITLE_VALUE_CHECK.ordinal + else -> { + when (this.operator) { + Operator.MORE -> RowViewType.TITLE_VALUE_CHECK.ordinal + Operator.LESS -> RowViewType.TITLE_VALUE_CHECK.ordinal + else -> RowViewType.TITLE_CHECK.ordinal + } + } + } + } + + override val bottomSheetType: BottomSheetType + get() { + return when (this) { + is PastDay -> BottomSheetType.EDIT_TEXT + else -> { + when (this.operator) { + Operator.MORE -> BottomSheetType.EDIT_TEXT + Operator.LESS -> BottomSheetType.EDIT_TEXT + else -> BottomSheetType.NONE + } + } + } + } + + override val resId: Int? + get() { + return when (this) { + is IsCash -> R.string.cash_game + is IsTournament -> R.string.tournament + is IsToday -> R.string.today + is WasYesterday -> R.string.yesterday + is WasTodayAndYesterday -> R.string.yesterday_and_today + is DuringThisWeek -> R.string.current_week + is DuringThisMonth -> R.string.current_month + is DuringThisYear -> R.string.current_year + is StartedFromDate -> R.string.from + is StartedFromTime -> R.string.from_hour_ + is EndedToDate -> R.string.to + is EndedToTime -> R.string.to_hour_ + is IsLive -> R.string.live + is IsOnline -> R.string.online + is IsWeekDay -> R.string.week_days + is IsWeekEnd -> R.string.weekend + is PastDay -> R.string.period_in_days + is TournamentNumberOfPlayer -> { + when (this.operator) { + Operator.MORE -> R.string.minimum + Operator.LESS -> R.string.maximum + else -> null + } + } + is NetAmountWon -> { + when (this.operator) { + Operator.MORE -> R.string.won_amount_more_than + Operator.LESS -> R.string.won_amount_less_than + else -> null + } + } + is NetAmountLost -> { + when (this.operator) { + Operator.MORE -> R.string.lost_amount_more_than + Operator.LESS -> R.string.lost_amount_less_than + else -> null + } + } + is TournamentFinalPosition -> { + when (this.operator) { + Operator.MORE -> R.string.minimum + Operator.LESS -> R.string.maximum + else -> null + } + } + else -> { + when (this.operator) { + Operator.MORE -> R.string.more_than + Operator.LESS -> R.string.less_than + else -> null + } + } + } + } } \ No newline at end of file