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.NameManageable import net.pokeranalytics.android.model.realm.* import java.util.* import kotlin.collections.ArrayList fun List.combined(): List> { val comparatorList = ArrayList>() this.forEach { comparatorList.add(it.queryConditions) } return getCombinations(comparatorList) } fun List>.upToNow(): List> { val calendar = Calendar.getInstance() calendar.time = Date() val currentYear = calendar.get(Calendar.YEAR) val currentMonth = calendar.get(Calendar.MONTH) val realm = Realm.getDefaultInstance() val firstSession = realm.where().sort("year", Sort.ASCENDING).findFirst() realm.close() val firstYear = firstSession?.year ?: currentYear val firstMonth = firstSession?.month ?: currentMonth val toRemove = this.filter { list -> list.any { it is QueryCondition.AnyYear && it.listOfValues.first() == currentYear } }.filter { list -> list.any { it is QueryCondition.AnyMonthOfYear && it.listOfValues.first() > currentMonth } } val toRemoveBefore = this.filter { list -> list.any { it is QueryCondition.AnyYear && it.listOfValues.first() == firstYear } }.filter { list -> list.any { it is QueryCondition.AnyMonthOfYear && it.listOfValues.first() < firstMonth } } return this.filter{ list -> var keep = true toRemove.forEach { if (list.containsAll(it)) { keep = false } } firstSession?.let { toRemoveBefore.forEach { if (list.containsAll(it)) { keep = false } } } keep } } fun getCombinations(lists: List>): List> { var combinations: LinkedHashSet> = LinkedHashSet() var newCombinations: LinkedHashSet> 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() } sealed class Criteria { abstract class RealmCriteria : Criteria() { inline fun comparison(): List { return compare, T>() .sorted() } } abstract class SimpleCriteria(private val conditions:List): Criteria() { fun comparison(): List { return conditions } } abstract class ListCriteria : Criteria() { inline fun , reified S:Comparable> comparison(): List { QueryCondition.distinct()?.let { val values = it.mapNotNull { session -> when (this) { is Limits -> if (session.limit is S) { session.limit as S } else throw PokerAnalyticsException.QueryValueMapUnexpectedValue is TournamentTypes -> if (session.tournamentType is S) { session.tournamentType as S } else throw PokerAnalyticsException.QueryValueMapUnexpectedValue is TableSizes -> if (session.tableSize is S) { session.tableSize as S } else throw PokerAnalyticsException.QueryValueMapUnexpectedValue is TournamentFees -> if (session.tournamentEntryFee is S) { session.tournamentEntryFee as S } else throw PokerAnalyticsException.QueryValueMapUnexpectedValue is Blinds -> if (session.blinds is S) { session.blinds as S } else throw PokerAnalyticsException.QueryValueMapUnexpectedValue else -> null } }.distinct() return compareList(values = values).sorted() } return listOf() } } object Bankrolls: RealmCriteria() object Games: RealmCriteria() object TournamentNames: RealmCriteria() object Locations: RealmCriteria() object TournamentFeatures: RealmCriteria() object Limits: ListCriteria() object TableSizes: ListCriteria() object TournamentTypes: ListCriteria() object MonthsOfYear: SimpleCriteria(List(12) { index -> QueryCondition.AnyMonthOfYear().apply { listOfValues = arrayListOf(index)} }) object DaysOfWeek: SimpleCriteria(List(7) { index -> QueryCondition.AnyDayOfWeek().apply { listOfValues = arrayListOf(index + 1) } }) object SessionTypes: SimpleCriteria(listOf(QueryCondition.IsCash, QueryCondition.IsTournament)) object BankrollTypes: SimpleCriteria(listOf(QueryCondition.IsLive, QueryCondition.IsOnline)) object DayPeriods: SimpleCriteria(listOf(QueryCondition.IsWeekDay, QueryCondition.IsWeekEnd)) object Years: ListCriteria() object Blinds: ListCriteria() object TournamentFees: ListCriteria() object Cash: SimpleCriteria(listOf(QueryCondition.IsCash)) object Tournament: SimpleCriteria(listOf(QueryCondition.IsTournament)) 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 TournamentFees -> comparison() is Years -> { 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.AnyYear().apply { listOfValues = arrayListOf(yearNow - index) }) } } realm.close() years.sorted() } is Blinds -> comparison() else -> throw PokerAnalyticsException.QueryTypeUnhandled } } companion object { inline fun < reified S : QueryCondition.QueryDataCondition, reified T : NameManageable > 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.ListOfValues, T:Any > compareList(values:List): List { val objects = arrayListOf() values.forEach { objects.add((S::class.java.newInstance()).apply { listOfValues = arrayListOf(it) }) } return objects } } }