package net.pokeranalytics.android.model import io.realm.Realm import io.realm.Sort import io.realm.kotlin.where import net.pokeranalytics.android.exceptions.PokerAnalyticsException import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.realm.* import java.util.* sealed class Criteria { abstract class RealmCriteria : Criteria() { inline fun comparison(): List { return compare < QueryCondition.QueryDataCondition, T >() } } abstract class SimpleCriteria(private val conditions:List): Criteria() { fun comparison(): List { return conditions } } abstract class StaticCriteria : Criteria() { inline fun comparison(): List { QueryCondition.distinct()?.let { val values = it.mapNotNull { session -> when (this) { is Limits -> session.limit is TournamentTypes -> session.tournamentType is TableSizes -> session.tableSize //is TournamentFees -> session.tournamentEntryFee 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 TableSizes: StaticCriteria() object TournamentTypes: StaticCriteria() object monthOfYear: SimpleCriteria(List(12) { index -> QueryCondition.MONTH().apply { intValue = index } }) object dayOfWeek: SimpleCriteria(List(7) { index -> QueryCondition.DAY_OF_WEEK().apply { intValue = index } }) object SessionType: SimpleCriteria(listOf(QueryCondition.CASH, QueryCondition.TOURNAMENT)) object BankrollType: SimpleCriteria(listOf(QueryCondition.LIVE, QueryCondition.ONLINE)) object dayPeriod: SimpleCriteria(listOf(QueryCondition.WEEK_DAY, QueryCondition.WEEK_END)) object Year: Criteria() object Blinds: Criteria() //object TournamentFees: StaticCriteria() 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() is TableSizes -> comparison() is Year -> { val years = arrayListOf() val calendar = Calendar.getInstance() calendar.time = Date() val yearNow = calendar.get(Calendar.YEAR) val realm = Realm.getDefaultInstance() realm.where().sort("year", Sort.ASCENDING).findFirst()?.year?.let { for (index in 0..(yearNow - it)) { years.add(QueryCondition.YEAR().apply { intValue = yearNow - index }) } } realm.close() years } is Blinds -> { val blinds = arrayListOf() val realm = Realm.getDefaultInstance() realm.where().distinct("blinds", "bankroll.currency.code").findAll().sort("cgSmallBlind", Sort.ASCENDING).map { it.blinds?.let { stake -> blinds.add(QueryCondition.BLIND().apply { blind = stake hasDefaultCurrency = it.hasDefaultCurrency }) } } realm.close() blinds } 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.StaticDataQueryCondition > compare(values:List): List { val objects = arrayListOf() values.forEach { objects.add((S::class.java.newInstance()).apply { intValues = arrayListOf(it) }) } return objects } } fun List.combined(): List> { val comparatorList = ArrayList>() this.forEach { comparatorList.add(it.queryConditions) } return getCombinations(comparatorList) } private fun getCombinations(lists: List>): List> { var combinations: MutableSet> = LinkedHashSet() var newCombinations: MutableSet> var index = 0 // extract each of the integers in the first list // and add each to ints as a new list if (lists.isNotEmpty()) { for (i in lists[0]) { val newList = ArrayList() newList.add(i) combinations.add(newList) } index++ } while (index < lists.size) { val nextList = lists[index] newCombinations = LinkedHashSet() for (first in combinations) { for (second in nextList) { val newList = ArrayList() newList.addAll(first) newList.add(second) newCombinations.add(newList) } } combinations = newCombinations index++ } return combinations.toList() } }