Integrate criterias + query in Options

dev
Laurent 7 years ago
parent dd2fd46c46
commit d3189ea360
  1. 50
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  2. 10
      app/src/main/java/net/pokeranalytics/android/calculus/Report.kt
  3. 7
      app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt
  4. 45
      app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarFragment.kt
  5. 13
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt
  6. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt
  7. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/TableReportFragment.kt

@ -24,10 +24,12 @@ class Calculator {
* The options used for calculations or display * The options used for calculations or display
*/ */
class Options( class Options(
display: Display = Display.TABLE, var display: Display = Display.TABLE,
evolutionValues: EvolutionValues = EvolutionValues.NONE, var evolutionValues: EvolutionValues = EvolutionValues.NONE,
stats: List<Stat> = listOf(), var stats: List<Stat> = listOf(),
aggregationType: AggregationType? = null var criterias: List<Criteria> = listOf(),
var query: Query = Query(),
var aggregationType: AggregationType? = null
) { ) {
/** /**
@ -50,17 +52,12 @@ class Calculator {
TIMED TIMED
} }
var display: Display = display
var evolutionValues: EvolutionValues = evolutionValues
var displayedStats: List<Stat> = stats
var aggregationType: AggregationType? = aggregationType
/** /**
* This function determines whether the standard deviation should be computed * This function determines whether the standard deviation should be computed
*/ */
val computeStandardDeviation: Boolean val computeStandardDeviation: Boolean
get() { get() {
this.displayedStats.forEach { this.stats.forEach {
if (it == STANDARD_DEVIATION_BB_PER_100_HANDS || it == STANDARD_DEVIATION || it == STANDARD_DEVIATION_HOURLY) { if (it == STANDARD_DEVIATION_BB_PER_100_HANDS || it == STANDARD_DEVIATION || it == STANDARD_DEVIATION_HOURLY) {
return true return true
} }
@ -70,7 +67,7 @@ class Calculator {
val computeLongestStreak: Boolean val computeLongestStreak: Boolean
get() { get() {
return this.displayedStats.contains(LONGEST_STREAKS) return this.stats.contains(LONGEST_STREAKS)
} }
val shouldSortValues: Boolean val shouldSortValues: Boolean
get() { get() {
@ -78,19 +75,19 @@ class Calculator {
} }
val computeLocationsPlayed: Boolean val computeLocationsPlayed: Boolean
get() { get() {
return this.displayedStats.contains(LOCATIONS_PLAYED) return this.stats.contains(LOCATIONS_PLAYED)
} }
val computeDaysPlayed: Boolean val computeDaysPlayed: Boolean
get() { get() {
return this.displayedStats.contains(DAYS_PLAYED) return this.stats.contains(DAYS_PLAYED)
} }
val shouldManageMultiGroupProgressValues: Boolean val shouldManageMultiGroupProgressValues: Boolean
get() { get() {
if (this.aggregationType != null) { return if (this.aggregationType != null) {
return this.aggregationType == AggregationType.MONTH || this.aggregationType == AggregationType.YEAR this.aggregationType == AggregationType.MONTH || this.aggregationType == AggregationType.YEAR
} else { } else {
return false false
} }
} }
@ -107,36 +104,31 @@ class Calculator {
): Report { ): Report {
val options = Options(evolutionValues = Options.EvolutionValues.STANDARD, aggregationType = aggregationType) val options = Options(evolutionValues = Options.EvolutionValues.STANDARD, aggregationType = aggregationType)
options.displayedStats = listOf(stat) options.stats = listOf(stat)
if (aggregationType == AggregationType.DURATION) { if (aggregationType == AggregationType.DURATION) {
options.evolutionValues = Options.EvolutionValues.TIMED options.evolutionValues = Options.EvolutionValues.TIMED
} }
stats?.let { stats?.let {
options.displayedStats = stats options.stats = stats
} }
return when (aggregationType) { return when (aggregationType) {
AggregationType.SESSION, AggregationType.DURATION -> this.computeGroups(realm, listOf(group), options) AggregationType.SESSION, AggregationType.DURATION -> this.computeGroups(realm, listOf(group), options)
AggregationType.MONTH, AggregationType.YEAR -> { AggregationType.MONTH, AggregationType.YEAR -> {
this.computeStatsWithCriterias(realm, aggregationType.criterias, group.query, options) this.computeStats(realm, options)
} }
} }
} }
fun computeStatsWithCriterias( fun computeStats(realm: Realm, options: Options = Options()): Report {
realm: Realm,
criterias: List<Criteria> = listOf(),
query: Query = Query(),
options: Options = Options()
): Report {
val computableGroups: MutableList<ComputableGroup> = mutableListOf() val computableGroups: MutableList<ComputableGroup> = mutableListOf()
criterias.combined().forEach { comparatorQuery -> options.criterias.combined().forEach { comparatorQuery ->
comparatorQuery.merge(query) comparatorQuery.merge(options.query)
val group = ComputableGroup(comparatorQuery) val group = ComputableGroup(comparatorQuery)
computableGroups.add(group) computableGroups.add(group)
@ -144,7 +136,7 @@ class Calculator {
} }
if (computableGroups.size == 0) { if (computableGroups.size == 0) {
val group = ComputableGroup(query) val group = ComputableGroup(options.query)
computableGroups.add(group) computableGroups.add(group)
} }
@ -339,7 +331,7 @@ class Calculator {
var gBBSum: Double? = null var gBBSum: Double? = null
var maxDuration: Double? = null var maxDuration: Double? = null
if (computableGroup.conditions.size == 0) { // SessionSets are fine if (computableGroup.conditions.isEmpty()) { // SessionSets are fine
gHourlyDuration = gHourlyDuration =
sessionSets.sum(SessionSet.Field.NET_DURATION.identifier).toDouble() / 3600000 // (milliseconds to hours) sessionSets.sum(SessionSet.Field.NET_DURATION.identifier).toDouble() / 3600000 // (milliseconds to hours)
gBBSum = sessionSets.sum(SessionSet.Field.BB_NET.identifier).toDouble() gBBSum = sessionSets.sum(SessionSet.Field.BB_NET.identifier).toDouble()

@ -44,7 +44,7 @@ class Report(var options: Calculator.Options) {
*/ */
fun lineEntries(stat: Stat? = null, context: Context): LineDataSet { fun lineEntries(stat: Stat? = null, context: Context): LineDataSet {
val entries = mutableListOf<Entry>() val entries = mutableListOf<Entry>()
val statToUse = stat ?: options.displayedStats.firstOrNull() val statToUse = stat ?: options.stats.firstOrNull()
val statName = statToUse?.name ?: "" val statName = statToUse?.name ?: ""
statToUse?.let { statToUse?.let {
@ -60,7 +60,7 @@ class Report(var options: Calculator.Options) {
fun barEntries(stat: Stat? = null, context: Context): BarDataSet { fun barEntries(stat: Stat? = null, context: Context): BarDataSet {
val entries = mutableListOf<BarEntry>() val entries = mutableListOf<BarEntry>()
val statToUse = stat ?: options.displayedStats.firstOrNull() val statToUse = stat ?: options.stats.firstOrNull()
statToUse?.let { statToUse?.let {
this._results.forEachIndexed { index, results -> this._results.forEachIndexed { index, results ->
@ -79,7 +79,7 @@ class Report(var options: Calculator.Options) {
fun multiLineEntries(context: Context): List<LineDataSet> { fun multiLineEntries(context: Context): List<LineDataSet> {
val dataSets = mutableListOf<LineDataSet>() val dataSets = mutableListOf<LineDataSet>()
options.displayedStats.forEach { stat -> options.stats.forEach { stat ->
this._results.forEachIndexed { index, result -> this._results.forEachIndexed { index, result ->
val ds = result.singleLineEntries(stat, context) val ds = result.singleLineEntries(stat, context)
ds.color = ColorUtils.almostRandomColor(index, context) ds.color = ColorUtils.almostRandomColor(index, context)
@ -106,7 +106,7 @@ class ComputableGroup(query: Query, stats: List<Stat>? = null) {
/** /**
* The display name of the group * The display name of the group
*/ */
var name: String = "" val name: String
get() { get() {
return this.query.name return this.query.name
} }
@ -114,7 +114,7 @@ class ComputableGroup(query: Query, stats: List<Stat>? = null) {
/** /**
* A list of _conditions to get * A list of _conditions to get
*/ */
var conditions: List<QueryCondition> = listOf() val conditions: List<QueryCondition>
get() { get() {
return this.query.conditions return this.query.conditions
} }

@ -196,8 +196,11 @@ class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable
// } // }
val requiredStats: List<Stat> = listOf(Stat.LOCATIONS_PLAYED, Stat.LONGEST_STREAKS, Stat.DAYS_PLAYED, Stat.STANDARD_DEVIATION_HOURLY) val requiredStats: List<Stat> = listOf(Stat.LOCATIONS_PLAYED, Stat.LONGEST_STREAKS, Stat.DAYS_PLAYED, Stat.STANDARD_DEVIATION_HOURLY)
val options = Calculator.Options(evolutionValues = Calculator.Options.EvolutionValues.STANDARD, stats = requiredStats) val options = Calculator.Options(
val report = Calculator.computeStatsWithCriterias(realm, listOf(), query, options) evolutionValues = Calculator.Options.EvolutionValues.STANDARD,
stats = requiredStats,
query = query)
val report = Calculator.computeStats(realm, options)
Timber.d("Report take: ${System.currentTimeMillis() - startDate.time}ms") Timber.d("Report take: ${System.currentTimeMillis() - startDate.time}ms")

@ -36,7 +36,8 @@ import java.util.*
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class CalendarFragment : SessionObserverFragment(), CoroutineScope, StaticRowRepresentableDataSource, RowRepresentableDelegate { class CalendarFragment : SessionObserverFragment(), CoroutineScope, StaticRowRepresentableDataSource,
RowRepresentableDelegate {
enum class TimeFilter { enum class TimeFilter {
MONTH, YEAR MONTH, YEAR
@ -94,7 +95,12 @@ class CalendarFragment : SessionObserverFragment(), CoroutineScope, StaticRowRep
TimeFilter.MONTH -> { TimeFilter.MONTH -> {
val date = datesForRows[row] val date = datesForRows[row]
sortedMonthlyReports[datesForRows[row]]?.let { sortedMonthlyReports[datesForRows[row]]?.let {
CalendarDetailsActivity.newInstance(requireContext(), it, sessionTypeCondition, date?.getMonthAndYear()) CalendarDetailsActivity.newInstance(
requireContext(),
it,
sessionTypeCondition,
date?.getMonthAndYear()
)
} }
} }
TimeFilter.YEAR -> { TimeFilter.YEAR -> {
@ -235,8 +241,8 @@ class CalendarFragment : SessionObserverFragment(), CoroutineScope, StaticRowRep
val monthlyReports: HashMap<Date, ComputedResults> = HashMap() val monthlyReports: HashMap<Date, ComputedResults> = HashMap()
val yearlyReports: HashMap<Date, ComputedResults> = HashMap() val yearlyReports: HashMap<Date, ComputedResults> = HashMap()
val requiredStats: List<Stat> = listOf(Stat.LOCATIONS_PLAYED, Stat.LONGEST_STREAKS, Stat.DAYS_PLAYED, Stat.STANDARD_DEVIATION_HOURLY ) val requiredStats: List<Stat> =
val options = Calculator.Options(evolutionValues = Calculator.Options.EvolutionValues.STANDARD, stats = requiredStats) listOf(Stat.LOCATIONS_PLAYED, Stat.LONGEST_STREAKS, Stat.DAYS_PLAYED, Stat.STANDARD_DEVIATION_HOURLY)
// Compute data per AnyYear and AnyMonthOfYear // Compute data per AnyYear and AnyMonthOfYear
@ -249,15 +255,23 @@ class CalendarFragment : SessionObserverFragment(), CoroutineScope, StaticRowRep
} }
monthlyQueries.forEach { query -> monthlyQueries.forEach { query ->
val report = Calculator.computeStatsWithCriterias(realm, query = query, options = options) val options = Calculator.Options(
evolutionValues = Calculator.Options.EvolutionValues.STANDARD,
stats = requiredStats,
query = query
)
val report = Calculator.computeStats(realm, options = options)
report.results.forEach { computedResults -> report.results.forEach { computedResults ->
if (!computedResults.isEmpty) { if (!computedResults.isEmpty) {
// Set date data // Set date data
query.conditions.forEach { condition -> query.conditions.forEach { condition ->
when (condition) { when (condition) {
is QueryCondition.AnyYear -> calendar.set(Calendar.YEAR, condition.listOfValues.first()) is QueryCondition.AnyYear -> calendar.set(Calendar.YEAR, condition.listOfValues.first())
is QueryCondition.AnyMonthOfYear -> calendar.set(Calendar.MONTH, condition.listOfValues.first()) is QueryCondition.AnyMonthOfYear -> calendar.set(
} Calendar.MONTH,
condition.listOfValues.first()
)
}
} }
monthlyReports[calendar.time] = computedResults monthlyReports[calendar.time] = computedResults
@ -275,14 +289,19 @@ class CalendarFragment : SessionObserverFragment(), CoroutineScope, StaticRowRep
} }
yearConditions.forEach { query -> yearConditions.forEach { query ->
val report = Calculator.computeStatsWithCriterias(realm, query = query, options = options) val options = Calculator.Options(
evolutionValues = Calculator.Options.EvolutionValues.STANDARD,
stats = requiredStats,
query = query
)
val report = Calculator.computeStats(realm, options = options)
report.results.forEach { computedResults -> report.results.forEach { computedResults ->
if (!computedResults.isEmpty) { if (!computedResults.isEmpty) {
// Set date data // Set date data
query.conditions.forEach { condition -> query.conditions.forEach { condition ->
when (condition) { when (condition) {
is QueryCondition.AnyYear -> calendar.set(Calendar.YEAR, condition.listOfValues.first()) is QueryCondition.AnyYear -> calendar.set(Calendar.YEAR, condition.listOfValues.first())
} }
} }
yearlyReports[calendar.time] = computedResults yearlyReports[calendar.time] = computedResults
} }

@ -105,9 +105,9 @@ class ReportsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSour
/** /**
* Launch computation * Launch computation
*/ */
private fun launchComputation(criteria: List<Criteria>, reportName: String) { private fun launchComputation(criteriaList: List<Criteria>, reportName: String) {
if (criteria.combined().size < 2) { if (criteriaList.combined().size < 2) {
Toast.makeText(context, R.string.less_then_2_values_for_display, Toast.LENGTH_LONG).show() Toast.makeText(context, R.string.less_then_2_values_for_display, Toast.LENGTH_LONG).show()
return return
} }
@ -120,10 +120,13 @@ class ReportsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSour
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
val requiredStats: List<Stat> = listOf(Stat.NET_RESULT) val requiredStats: List<Stat> = listOf(Stat.NET_RESULT)
val options = Calculator.Options(evolutionValues = Calculator.Options.EvolutionValues.STANDARD, stats = requiredStats) val options = Calculator.Options(
evolutionValues = Calculator.Options.EvolutionValues.STANDARD,
stats = requiredStats,
criterias = criteriaList
)
val report = Calculator.computeStatsWithCriterias(realm, criteria, options = options) val report = Calculator.computeStats(realm, options = options)
// val report = Calculator.computeStatsWithComparators(realm, criteria = criteria, options = options)
Timber.d("launchComputation: ${System.currentTimeMillis() - startDate.time}ms") Timber.d("launchComputation: ${System.currentTimeMillis() - startDate.time}ms")

@ -137,7 +137,7 @@ class StatisticsFragment : TableReportFragment() {
computedStats.addAll(allStats) computedStats.addAll(allStats)
computedStats.addAll(cgStats) computedStats.addAll(cgStats)
computedStats.addAll(tStats) computedStats.addAll(tStats)
options.displayedStats = computedStats options.stats = computedStats
return Calculator.computeGroups(realm, listOf(allSessionGroup, cgSessionGroup, tSessionGroup), options) return Calculator.computeGroups(realm, listOf(allSessionGroup, cgSessionGroup, tSessionGroup), options)
} }

@ -135,7 +135,7 @@ open class TableReportFragment : SessionObserverFragment(), StaticRowRepresentab
open fun convertReportIntoRepresentables(report: Report): ArrayList<RowRepresentable> { open fun convertReportIntoRepresentables(report: Report): ArrayList<RowRepresentable> {
val rows: ArrayList<RowRepresentable> = ArrayList() val rows: ArrayList<RowRepresentable> = ArrayList()
report.options.displayedStats.forEach {stat -> report.options.stats.forEach {stat ->
rows.add(CustomizableRowRepresentable(title = stat.localizedTitle(requireContext()))) rows.add(CustomizableRowRepresentable(title = stat.localizedTitle(requireContext())))
report.results.forEach { report.results.forEach {
val title = it.group.name val title = it.group.name

Loading…
Cancel
Save