@ -16,31 +16,49 @@ import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.interfaces.NameManageable
import net.pokeranalytics.android.model.realm.*
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.UserDefaults
import net.pokeranalytics.android.util.extensions.*
import java.text.DateFormatSymbols
import java.text.NumberFormat
import java.util.*
import kotlin.collections.ArrayList
import kotlin.reflect.KClass
/ * *
* Enum describing the way a query should be handled
* Some queries requires a value to be checked upon through equals , in , more , less , between
* /
sealed class QueryCondition : FilterElementRow {
sealed class QueryCondition : RowRepresentable {
companion object {
fun < T : Any > newInstance ( kClass : KClass < T > ) : T {
return try {
kClass . objectInstance ?: kClass . java . newInstance ( )
} catch ( e : Exception ) {
// some object instance can fail due to: java.lang.Class has no zero argument constructor
// We should have just one constructor with a single parameter
val primaryConstructor = kClass . java . declaredConstructors . first ( )
val paramClass = primaryConstructor . parameterTypes . first ( )
val param = when ( paramClass ) {
Int :: class . java -> 0
Double :: class . java -> 0.0
else -> paramClass . newInstance ( )
}
val constructor = kClass . java . getDeclaredConstructor ( paramClass )
constructor . newInstance ( param )
}
}
inline fun < reified T : QueryCondition > more ( ) : T {
return T :: class . java . newInstance ( ) . apply { this . operator = Operator . MORE }
return newInstance ( T :: class ) . apply { this . operator = Operator . MORE }
}
inline fun < reified T : QueryCondition > less ( ) : T {
return T :: class . java . newInstance ( ) . apply { this . operator = Operator . LESS }
return newInstance ( T :: class ) . apply { this . operator = Operator . LESS }
}
inline fun < reified T : QueryCondition > moreOrLess ( ) : ArrayList < T > {
@ -49,8 +67,7 @@ sealed class QueryCondition : FilterElementRow {
fun < T : QueryCondition > valueOf ( name : String ) : T {
val kClass = Class . forName ( " ${QueryCondition::class.qualifiedName} $ $name " ) . kotlin
val instance = kClass . objectInstance ?: kClass . java . newInstance ( )
return instance as T
return newInstance ( kClass ) as T
}
inline fun < reified T : Identifiable > getInstance ( ) : QueryCondition {
@ -125,23 +142,27 @@ sealed class QueryCondition : FilterElementRow {
abstract class ListOfValues < T > : QueryCondition ( ) , Comparable < ListOfValues < T > > where T : Comparable < T > {
abstract var listOfValues : Array List< T >
abstract var listOfValues : Mutable List< T >
abstract fun labelForValue ( value : T , context : Context ) : String
open fun entityName ( context : Context ) : String {
return getDisplayName ( context )
}
override fun getDisplayName ( context : Context ) : String {
fun getDisplayName ( context : Context , values : List < T > ) : String {
val prefix = this . resId ?. let {
context . getString ( it ) + " "
} ?: " "
return when ( listOfV alues. size ) {
return when ( v alues. size ) {
0 -> return NULL _TEXT
1 , 2 -> prefix + listOfValues . map { labelForValue ( it , context ) } . joinToString ( " , " )
else -> " ${listOfValues.size} $prefix ${entityName(context)} "
1 , 2 -> prefix + values . joinToString ( " , " ) { labelForValue ( it , context ) }
else -> " ${values.size} $prefix ${entityName(context)} "
}
}
override fun getDisplayName ( context : Context ) : String {
return getDisplayName ( context , this . listOfValues )
}
override fun compareTo ( other : ListOfValues < T > ) : Int {
@ -151,17 +172,32 @@ sealed class QueryCondition : FilterElementRow {
fun firstValue ( context : Context ) : String ? {
return this . listOfValues . firstOrNull ( ) ?. let { this . labelForValue ( it , context ) }
}
}
abstract class SingleValue < T > ( value : T ) : QueryCondition ( ) where T : Comparable < T > {
// override var listOfValues = mutableListOf<T>()
var singleValue : T = value
abstract fun labelForValue ( value : T , context : Context ) : String
override fun getDisplayName ( context : Context ) : String {
return getDisplayName ( context , singleValue )
}
fun getDisplayName ( context : Context , value : T ) : String {
val prefix = this . resId ?. let {
context . getString ( it ) + " "
} ?: " "
return prefix + labelForValue ( value , context )
}
abstract class SingleValue < T > : ListOfValues < T > ( ) where T : Comparable < T > {
override var listOfValues = ArrayList < T > ( )
abstract var singleValue : T ?
}
abstract class ListOfDouble : ListOfValues < Double > ( ) {
open var sign : Int = 1
override var operator : Operator = Operator . ANY
override var listOfValues : ArrayList < Double > = arrayListOf ( )
override var listOfValues = mutableListOf < Double > ( )
override fun updateValueBy ( filterCondition : FilterCondition ) {
super . updateValueBy ( filterCondition )
listOfValues = filterCondition . getValues ( )
@ -174,7 +210,7 @@ sealed class QueryCondition : FilterElementRow {
abstract class ListOfInt : ListOfValues < Int > ( ) {
override var operator : Operator = Operator . ANY
override var listOfValues : ArrayList < Int > = arrayListOf ( )
override var listOfValues = mutableListOf < Int > ( )
override fun updateValueBy ( filterCondition : FilterCondition ) {
super . updateValueBy ( filterCondition )
listOfValues = filterCondition . getValues ( )
@ -187,7 +223,7 @@ sealed class QueryCondition : FilterElementRow {
abstract class ListOfString : ListOfValues < String > ( ) {
override var operator : Operator = Operator . ANY
override var listOfValues = ArrayList < String > ( )
override var listOfValues = mutableListOf < String > ( )
override fun labelForValue ( value : String , context : Context ) : String {
return value
}
@ -198,46 +234,30 @@ sealed class QueryCondition : FilterElementRow {
}
}
abstract class SingleDate : SingleValue < Date > ( ) {
abstract class SingleDate ( date : Date ) : SingleValue < Date > ( date ) {
override fun labelForValue ( value : Date , context : Context ) : String {
return value . shortDate ( )
}
override var listOfValues = ArrayList < Date > ( )
override var singleValue : Date ?
get ( ) {
return listOfValues . firstOrNull ( )
}
set ( value ) {
listOfValues . removeAll ( this . listOfValues )
value ?. let { listOfValues . add ( it ) }
}
// override var listOfValues = mutableListOf<Date>()
override fun updateValueBy ( filterCondition : FilterCondition ) {
super . updateValueBy ( filterCondition )
singleValue = filterCondition . getValue ( )
}
}
abstract class SingleInt : SingleValue < Int > ( ) {
abstract class SingleInt ( value : Int ) : SingleValue < Int > ( value ) {
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 {
@ -247,7 +267,7 @@ sealed class QueryCondition : FilterElementRow {
return baseId
}
override var filterSectionRow : FilterSectionRow = FilterSectionRow . CashOrTournament
// override var filterSectionRow: FilterSectionRow = FilterSectionRow. CashOrTournament
abstract class QueryDataCondition < T : NameManageable > : ListOfString ( ) {
fun setObject ( dataObject : T ) {
@ -263,7 +283,7 @@ sealed class QueryCondition : FilterElementRow {
val completeLabel = when ( listOfValues . size ) {
0 -> NULL _TEXT
1 , 2 -> {
listOfValues . map { labelForValue ( realm , it ) } . joinToString ( " , " )
listOfValues . joinToString ( " , " ) { labelForValue ( realm , it ) }
}
else -> " ${listOfValues.size} $entityName "
}
@ -281,26 +301,23 @@ sealed class QueryCondition : FilterElementRow {
}
}
interface DateTime {
val showTime : Boolean
}
abstract class DateQuery : SingleDate ( ) , DateTime {
abstract class DateQuery ( date : Date ) : SingleDate ( date ) , DateTime {
override val showTime : Boolean = false
override fun labelForValue ( value : Date , context : Context ) : String {
return singleValue ?. let {
if ( showTime ) {
it . shortTime ( )
return if ( showTime ) {
singleValue . shortTime ( )
} else {
it . shortDate ( )
singleValue . shortDate ( )
}
} ?: NULL _TEXT
}
}
abstract class TimeQuery : DateQuery ( ) {
abstract class TimeQuery ( date : Date ) : DateQuery ( date ) {
override val showTime : Boolean = true
}
@ -343,50 +360,34 @@ sealed class QueryCondition : FilterElementRow {
}
}
class AnyTournamentName ( ) : QueryDataCondition < TournamentName > ( ) {
class AnyTournamentName : QueryDataCondition < TournamentName > ( ) {
override val entity : Class < TournamentName > = TournamentName :: class . java
constructor ( tournamentName : TournamentName ) : this ( ) {
this . setObject ( tournamentName )
}
override fun entityName ( context : Context ) : String {
return context . getString ( R . string . tournament _names )
}
}
class AnyTournamentFeature ( ) : QueryDataCondition < TournamentFeature > ( ) {
class AnyTournamentFeature : QueryDataCondition < TournamentFeature > ( ) {
override val entity : Class < TournamentFeature > = TournamentFeature :: class . java
constructor ( tournamentFeature : TournamentFeature ) : this ( ) {
this . setObject ( tournamentFeature )
}
override fun entityName ( context : Context ) : String {
return context . getString ( R . string . tournament _features )
}
}
class AllTournamentFeature ( ) : QueryDataCondition < TournamentFeature > ( ) {
class AllTournamentFeature : QueryDataCondition < TournamentFeature > ( ) {
override var operator = Operator . ALL
override val entity : Class < TournamentFeature > = TournamentFeature :: class . java
constructor ( tournamentFeature : TournamentFeature ) : this ( ) {
this . setObject ( tournamentFeature )
}
override fun entityName ( context : Context ) : String {
return context . getString ( R . string . tournament _features )
}
}
class AnyLocation ( ) : QueryDataCondition < Location > ( ) {
class AnyLocation : QueryDataCondition < Location > ( ) {
override val entity : Class < Location > = Location :: class . java
constructor ( location : Location ) : this ( ) {
this . setObject ( location )
}
override fun entityName ( context : Context ) : String {
return context . getString ( R . string . locations )
}
@ -440,14 +441,6 @@ sealed class QueryCondition : FilterElementRow {
}
}
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 )
@ -476,13 +469,13 @@ sealed class QueryCondition : FilterElementRow {
}
override fun labelForValue ( value : Int , context : Context ) : String {
val suffix = when ( value % 10 ) {
val suffix = when ( value % 10 ) {
1 -> context . getString ( R . string . ordinal _suffix _first )
2 -> context . getString ( R . string . ordinal _suffix _second )
3 -> context . getString ( R . string . ordinal _suffix _third )
else -> context . getString ( R . string . ordinal _suffix _default )
}
return " $value $suffix " + context . getString ( R . string . position )
return " $value $suffix " + context . getString ( R . string . position )
}
override fun entityName ( context : Context ) : String {
@ -507,19 +500,19 @@ sealed class QueryCondition : FilterElementRow {
}
}
class StartedFromDate : DateQuery ( ) {
class StartedFromDate ( date : Date ) : DateQuery ( date ) {
override var operator = Operator . MORE
}
class StartedToDate : DateQuery ( ) {
class StartedToDate ( date : Date ) : DateQuery ( date ) {
override var operator = Operator . LESS
}
class EndedFromDate : DateQuery ( ) {
class EndedFromDate ( date : Date ) : DateQuery ( date ) {
override var operator = Operator . MORE
}
class EndedToDate : DateQuery ( ) {
class EndedToDate ( date : Date ) : DateQuery ( date ) {
override var operator = Operator . LESS
}
@ -530,23 +523,23 @@ sealed class QueryCondition : FilterElementRow {
}
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 "
return DateFormatSymbols . getInstance ( Locale . getDefault ( ) ) . months [ value ] . capitalize ( )
}
}
class AnyYear ( ) : ListOfInt ( ) {
constructor ( year : Int ) : this ( ) {
listOfValues = arrayListOf ( year )
}
override fun labelForValue ( value : Int , context : Context ) : String {
return " $value "
}
}
object IsWeekDay : TrueQueryCondition ( )
@ -564,7 +557,7 @@ sealed class QueryCondition : FilterElementRow {
}
}
class PastDay : SingleInt ( ) {
class PastDay ( value : Int ) : SingleInt ( value ) {
override var operator = Operator . EQUALS
override val viewType : Int = RowViewType . TITLE _VALUE _CHECK . ordinal
@ -572,16 +565,17 @@ sealed class QueryCondition : FilterElementRow {
return value . toString ( )
}
override fun entityName ( context : Context ) : String {
return this . resId ?. let {
" " + context . getString ( it )
} ?: " "
}
// override fun entityName(context: Context): String {
// return this.resId?.let {
// " " + context.getString(it )
// } ?: " "
// }
}
class Duration : SingleInt ( ) {
class Duration ( value : Int ) : SingleInt ( value ) {
override var operator = Operator . EQUALS
var minutes : Int ?
var minutes : Int
get ( ) {
return singleValue
}
@ -589,12 +583,9 @@ sealed class QueryCondition : FilterElementRow {
singleValue = value
}
val netDuration : Long ?
val netDuration : Long
get ( ) {
minutes ?. let {
return ( it * 60 * 1000 ) . toLong ( )
}
return null
return ( singleValue * 60 * 1000 ) . toLong ( )
}
override val viewType : Int = RowViewType . TITLE _VALUE _CHECK . ordinal
@ -609,22 +600,12 @@ sealed class QueryCondition : FilterElementRow {
object EndDateNotNull : NotNullQueryCondition ( )
object BigBlindNotNull : NotNullQueryCondition ( )
class StartedFromTime ( ) : TimeQuery ( ) {
class StartedFromTime ( date : Date ) : TimeQuery ( date ) {
override var operator = Operator . MORE
constructor ( date : Date ) : this ( ) {
singleValue = date
}
}
class EndedToTime ( ) : TimeQuery ( ) {
class EndedToTime ( date : Date ) : TimeQuery ( date ) {
override var operator = Operator . LESS
constructor ( date : Date ) : this ( ) {
singleValue = date
}
}
interface CustomFieldRelated {
@ -639,12 +620,8 @@ sealed class QueryCondition : FilterElementRow {
}
}
class CustomFieldQuery ( ) : QueryDataCondition < CustomField > ( ) {
class CustomFieldQuery : QueryDataCondition < CustomField > ( ) {
override var entity : Class < CustomField > = CustomField :: class . java
constructor ( customField : CustomField ) : this ( ) {
this . setObject ( customField )
}
}
open class CustomFieldNumberQuery ( ) : ListOfDouble ( ) , CustomFieldRelated {
@ -666,7 +643,9 @@ sealed class QueryCondition : FilterElementRow {
val completeLabel = when ( listOfValues . size ) {
0 -> return NULL _TEXT
1 , 2 -> {
return name + prefix + listOfValues . map { labelForValue ( it , context ) } . joinToString ( " , " )
return name + prefix + listOfValues . joinToString ( " , " ) {
labelForValue ( it , context )
}
}
else -> " ${listOfValues.size} $prefix $name "
}
@ -762,16 +741,13 @@ sealed class QueryCondition : FilterElementRow {
. 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 )
calendar . add ( Calendar . DAY _OF _YEAR , - singleValue )
return realmQuery . greaterThanOrEqualTo ( fieldName , calendar . time . startOfDay ( ) ) . and ( )
. lessThanOrEqualTo ( fieldName , startDate . endOfDay ( ) )
}
return realmQuery
}
is DuringThisWeek -> {
val calendar = Calendar . getInstance ( )
calendar . set ( Calendar . HOUR _OF _DAY , 0 )
@ -800,30 +776,22 @@ sealed class QueryCondition : FilterElementRow {
}
is StartedFromTime -> {
val calendar = Calendar . getInstance ( )
singleValue ?. let {
calendar . time = it
calendar . time = singleValue
realmQuery . greaterThanOrEqualTo ( fieldName , calendar . hourMinute ( ) )
if ( otherQueryCondition is EndedToTime ) {
otherQueryCondition . singleValue ?. let { endTime ->
calendar . time = endTime
calendar . time = otherQueryCondition . singleValue
realmQuery . lessThanOrEqualTo ( fieldName , calendar . hourMinute ( ) )
}
}
}
return realmQuery
}
is EndedToTime -> {
val calendar = Calendar . getInstance ( )
singleValue ?. let { date ->
calendar . time = date
calendar . time = singleValue
realmQuery . lessThanOrEqualTo ( fieldName , calendar . hourMinute ( ) )
if ( otherQueryCondition is StartedFromTime ) {
otherQueryCondition . singleValue ?. let { startTime ->
calendar . time = startTime
calendar . time = otherQueryCondition . singleValue
realmQuery . greaterThanOrEqualTo ( fieldName , calendar . hourMinute ( ) )
}
}
}
return realmQuery
}
}
@ -846,14 +814,8 @@ sealed class QueryCondition : FilterElementRow {
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 SingleDate -> realmQuery . equalTo ( fieldName , singleValue )
is SingleInt -> realmQuery . equalTo ( fieldName , singleValue )
is ListOfInt -> realmQuery . equalTo ( fieldName , listOfValues . first ( ) )
is ListOfDouble -> realmQuery . equalTo ( fieldName , listOfValues . first ( ) * sign )
is ListOfString -> realmQuery . equalTo ( fieldName , listOfValues . first ( ) )
@ -862,20 +824,11 @@ sealed class QueryCondition : FilterElementRow {
}
Operator . MORE -> {
when ( this ) {
is SingleDate -> realmQuery . greaterThanOrEqualTo (
fieldName ,
singleValue ?. startOfDay ( ) ?: throw PokerAnalyticsException . FilterElementExpectedValueMissing
)
is Duration -> realmQuery . greaterThan (
fieldName ,
netDuration ?: throw PokerAnalyticsException . FilterElementExpectedValueMissing
)
is SingleDate -> realmQuery . greaterThanOrEqualTo ( fieldName , singleValue . startOfDay ( ) )
is Duration -> realmQuery . greaterThan ( fieldName , netDuration )
is TournamentFinalPosition -> realmQuery . greaterThanOrEqualTo ( fieldName , listOfValues . first ( ) )
is TournamentNumberOfPlayer -> realmQuery . greaterThanOrEqualTo ( fieldName , listOfValues . first ( ) )
is SingleInt -> realmQuery . greaterThan (
fieldName ,
singleValue ?: throw PokerAnalyticsException . FilterElementExpectedValueMissing
)
is SingleInt -> realmQuery . greaterThan ( fieldName , singleValue )
is ListOfInt -> realmQuery . greaterThan ( fieldName , listOfValues . first ( ) )
is NetAmountLost -> realmQuery . lessThan ( fieldName , listOfValues . first ( ) * - 1 )
is ListOfDouble -> realmQuery . greaterThan ( fieldName , listOfValues . first ( ) * sign )
@ -884,20 +837,11 @@ sealed class QueryCondition : FilterElementRow {
}
Operator . LESS -> {
when ( this ) {
is SingleDate -> realmQuery . lessThanOrEqualTo (
fieldName ,
singleValue ?. endOfDay ( ) ?: throw PokerAnalyticsException . FilterElementExpectedValueMissing
)
is Duration -> realmQuery . lessThan (
fieldName ,
netDuration ?: throw PokerAnalyticsException . FilterElementExpectedValueMissing
)
is SingleDate -> realmQuery . lessThanOrEqualTo ( fieldName , singleValue . endOfDay ( ) )
is Duration -> realmQuery . lessThan ( fieldName , netDuration )
is TournamentFinalPosition -> realmQuery . lessThanOrEqualTo ( fieldName , listOfValues . first ( ) )
is TournamentNumberOfPlayer -> realmQuery . lessThanOrEqualTo ( fieldName , listOfValues . first ( ) )
is SingleInt -> realmQuery . lessThan (
fieldName ,
singleValue ?: throw PokerAnalyticsException . FilterElementExpectedValueMissing
)
is SingleInt -> realmQuery . lessThan ( fieldName , singleValue )
is ListOfInt -> realmQuery . lessThan ( fieldName , listOfValues . first ( ) )
is NetAmountLost -> {
realmQuery . greaterThan ( fieldName , listOfValues . first ( ) * - 1 )
@ -947,6 +891,7 @@ sealed class QueryCondition : FilterElementRow {
}
}
override val viewType : Int
get ( ) {
return when ( this ) {