diff --git a/app/build.gradle b/app/build.gradle index 4c62fa11..d1cb2743 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,7 +35,7 @@ android { buildTypes { release { - minifyEnabled false + minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' applicationVariants.all { variant -> variant.outputs.all { output -> diff --git a/app/src/androidTest/java/net/pokeranalytics/android/performanceTests/PerfsInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/performanceTests/PerfsInstrumentedUnitTest.kt index 8cfd42ac..7246cfa7 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/performanceTests/PerfsInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/performanceTests/PerfsInstrumentedUnitTest.kt @@ -53,7 +53,7 @@ class PerfsInstrumentedUnitTest : RealmInstrumentedUnitTest() { Timber.d("computableResults: ${computableResults.size}") Timber.d("sets: ${sets.size}") - val stats: List = listOf(Stat.NETRESULT, Stat.AVERAGE) + val stats: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() @@ -62,7 +62,7 @@ class PerfsInstrumentedUnitTest : RealmInstrumentedUnitTest() { val results: ComputedResults = Calculator.compute(realm, group, options) Timber.d("*** ended in ${System.currentTimeMillis() - start} milliseconds") - val sum = results.computedStat(Stat.NETRESULT) + val sum = results.computedStat(Stat.NET_RESULT) Timber.d("*** NET RESULT: ${sum?.value}") val average = results.computedStat(Stat.AVERAGE) diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt index 5c27d92c..202ee39d 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/StatsInstrumentedUnitTest.kt @@ -81,7 +81,7 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { val results: ComputedResults = Calculator.compute(realm, group, options) val delta = 0.01 - val sum = results.computedStat(Stat.NETRESULT) + val sum = results.computedStat(Stat.NET_RESULT) if (sum != null) { assertEquals(200.0, sum.value, delta) } else { @@ -250,7 +250,7 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { } - val stats: List = listOf(Stat.NETRESULT, Stat.AVERAGE) + val stats: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() @@ -317,7 +317,7 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { realm.commitTransaction() - val stats: List = listOf(Stat.NETRESULT, Stat.AVERAGE) + val stats: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() @@ -400,7 +400,7 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { realm.commitTransaction() - val stats: List = listOf(Stat.NETRESULT, Stat.AVERAGE) + val stats: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() @@ -420,7 +420,7 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { s1.deleteFromRealm() } - val stats2: List = listOf(Stat.NETRESULT, Stat.AVERAGE) + val stats2: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group2 = ComputableGroup("test", listOf(), stats2) val results2: ComputedResults = Calculator.compute(realm, group2, options) @@ -545,7 +545,7 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { s1.endDate = null } - val stats: List = listOf(Stat.NETRESULT, Stat.AVERAGE) + val stats: List = listOf(Stat.NET_RESULT, Stat.AVERAGE) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() @@ -597,12 +597,12 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { } - val stats: List = listOf(Stat.NETRESULT) + val stats: List = listOf(Stat.NET_RESULT) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() val results: ComputedResults = Calculator.compute(realm, group, options) - val netResult = results.computedStat(Stat.NETRESULT) + val netResult = results.computedStat(Stat.NET_RESULT) assertEquals(250.0, netResult?.value) } @@ -633,12 +633,12 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { } - val stats: List = listOf(Stat.NETRESULT) + val stats: List = listOf(Stat.NET_RESULT) val group = ComputableGroup("test", listOf(), stats) val options = Calculator.Options() val results: ComputedResults = Calculator.compute(realm, group, options) - val netResult = results.computedStat(Stat.NETRESULT) + val netResult = results.computedStat(Stat.NET_RESULT) assertEquals(250.0, netResult?.value) println("currency set rate real test starts here") @@ -654,7 +654,7 @@ class StatsInstrumentedUnitTest : SessionInstrumentedUnitTest() { val updatedGroup = ComputableGroup("test", listOf(), stats) val updatedResults: ComputedResults = Calculator.compute(realm, updatedGroup, options) - val updatedNetResult = updatedResults.computedStat(Stat.NETRESULT) + val updatedNetResult = updatedResults.computedStat(Stat.NET_RESULT) assertEquals(650.0, updatedNetResult?.value) } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 37e6961f..8ef69191 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -49,6 +49,11 @@ android:launchMode="singleTop" android:screenOrientation="portrait" /> + + = listOf() + stats: List = listOf(), + aggregationType: AggregationType? = null ) { /** @@ -53,6 +54,7 @@ class Calculator { var display: Display = display var evolutionValues: EvolutionValues = evolutionValues var displayedStats: List = stats + var aggregationType: AggregationType? = aggregationType /** * This function determines whether the standard deviation should be computed @@ -80,21 +82,37 @@ class Calculator { return this.displayedStats.contains(DAYS_PLAYED) } + val shouldManageMultiGroupProgressValues: Boolean + get() { + if (this.aggregationType != null) { + return this.aggregationType == AggregationType.MONTH || this.aggregationType == AggregationType.YEAR + } else { + return false + } + } + } companion object { fun computeStatsWithEvolutionByAggregationType( realm: Realm, + stat: Stat, group: ComputableGroup, - aggregationType: AggregationType + aggregationType: AggregationType, + stats: List? = null ): Report { - val options = Options(evolutionValues = Options.EvolutionValues.STANDARD) + val options = Options(evolutionValues = Options.EvolutionValues.STANDARD, aggregationType = aggregationType) + options.displayedStats = listOf(stat) if (aggregationType == AggregationType.DURATION) { options.evolutionValues = Options.EvolutionValues.TIMED } + stats?.let { + options.displayedStats = stats + } + return when (aggregationType) { AggregationType.SESSION, AggregationType.DURATION -> this.computeGroups(realm, listOf(group), options) AggregationType.MONTH -> { @@ -116,6 +134,8 @@ class Calculator { ): Report { val computableGroups: MutableList = mutableListOf() + + var previousGroup: ComputableGroup? = null comparators.combined().forEach { comparatorConditions -> val allConditions = mutableListOf() @@ -123,8 +143,10 @@ class Calculator { allConditions.addAll(comparatorConditions) val group = ComputableGroup(allConditions.name(), allConditions) + group.comparedGroup = previousGroup computableGroups.add(group) + previousGroup = group } if (computableGroups.size == 0) { @@ -140,7 +162,7 @@ class Calculator { */ fun computeGroups(realm: Realm, groups: List, options: Options): Report { - val report = Report() + val report = Report(options) groups.forEach { group -> val s = Date() @@ -151,7 +173,7 @@ class Calculator { val results: ComputedResults = this.compute(realm, group, options = options) // Computes the compared sessionGroup if existing - val comparedGroup = group.comparedComputables + val comparedGroup = group.comparedGroup if (comparedGroup != null) { val comparedResults = this.compute(realm, comparedGroup, options = options) group.comparedComputedResults = comparedResults @@ -175,29 +197,70 @@ class Calculator { */ fun compute(realm: Realm, computableGroup: ComputableGroup, options: Options): ComputedResults { + val results = ComputedResults(computableGroup, options.shouldManageMultiGroupProgressValues) + val computables = computableGroup.computables(realm) Timber.d(">>>> Start computing group ${computableGroup.name}, ${computables.size} computables") + results.addStat(NUMBER_OF_GAMES, computables.size.toDouble()) if (options.computeLongestStreak) { computables.sort("session.startDate") } - val results = ComputedResults(computableGroup) - val sum = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble() + results.addStat(NET_RESULT, sum) + val totalHands = computables.sum(ComputableResult.Field.ESTIMATED_HANDS.identifier).toDouble() + results.addStat(HANDS_PLAYED, totalHands) + val bbSum = computables.sum(ComputableResult.Field.BB_NET.identifier).toDouble() + results.addStat(BB_NET_RESULT, bbSum) + val bbSessionCount = computables.sum(ComputableResult.Field.HAS_BIG_BLIND.identifier).toInt() + results.addStat(BB_SESSION_COUNT, bbSessionCount.toDouble()) + val winningSessionCount = computables.sum(ComputableResult.Field.IS_POSITIVE.identifier).toInt() + results.addStat(WINNING_SESSION_COUNT, winningSessionCount.toDouble()) + val totalBuyin = computables.sum(ComputableResult.Field.RATED_BUYIN.identifier).toDouble() + results.addStat(TOTAL_BUYIN, totalBuyin) val maxNetResult = computables.max(ComputableResult.Field.RATED_NET.identifier)?.toDouble() + maxNetResult?.let { + results.addStat(MAXIMUM_NETRESULT, it) + } + val minNetResult = computables.min(ComputableResult.Field.RATED_NET.identifier)?.toDouble() + minNetResult?.let { + results.addStat(MINIMUM_NETRESULT, it) + } + + Stat.netBBPer100Hands(bbSum, totalHands)?.let { netBB100 -> + results.addStat(NET_BB_PER_100_HANDS, netBB100) + } + Stat.returnOnInvestment(sum, totalBuyin)?.let { roi -> + results.addStat(ROI, roi) + } if (options.computeLocationsPlayed) { results.addStat(LOCATIONS_PLAYED, computables.distinctBy { it.session?.location?.id }.size.toDouble()) } + var average = 0.0 // also used for standard deviation later + if (computables.size > 0) { + average = sum / computables.size.toDouble() + val winRatio = winningSessionCount.toDouble() / computables.size.toDouble() + val avgBuyin = totalBuyin / computables.size.toDouble() + + results.addStats( + setOf( + ComputedStat(AVERAGE, average), + ComputedStat(WIN_RATIO, winRatio), + ComputedStat(AVERAGE_BUYIN, avgBuyin) + ) + ) + } + val shouldIterateOverComputables = (options.evolutionValues == Options.EvolutionValues.STANDARD || options.computeLongestStreak) @@ -242,7 +305,7 @@ class Calculator { val session = computable.session ?: throw IllegalStateException("Computing lone ComputableResult") - results.addEvolutionValue(tSum, stat = NETRESULT, data = session) + results.addEvolutionValue(tSum, stat = NET_RESULT, data = session) results.addEvolutionValue(tSum / index, stat = AVERAGE, data = session) results.addEvolutionValue(index.toDouble(), stat = NUMBER_OF_GAMES, data = session) results.addEvolutionValue(tBBSum / tBBSessionCount, stat = AVERAGE_NET_BB, data = session) @@ -275,6 +338,7 @@ class Calculator { } val sessionSets = computableGroup.sessionSets(realm) + results.addStat(NUMBER_OF_SETS, sessionSets.size.toDouble()) var gHourlyDuration: Double? = null var gBBSum: Double? = null @@ -343,7 +407,7 @@ class Calculator { } Options.EvolutionValues.TIMED -> { - results.addEvolutionValue(tRatedNetSum, tHourlyDuration, NETRESULT, sessionSet) + results.addEvolutionValue(tRatedNetSum, tHourlyDuration, NET_RESULT, sessionSet) results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, sessionSet) results.addEvolutionValue( tIndex.toDouble(), @@ -389,23 +453,7 @@ class Calculator { } - var average = 0.0 var hourlyRate = 0.0 - - if (computables.size > 0) { - average = sum / computables.size.toDouble() - val winRatio = winningSessionCount.toDouble() / computables.size.toDouble() - val avgBuyin = totalBuyin / computables.size - - results.addStats( - setOf( - ComputedStat(AVERAGE, average), - ComputedStat(WIN_RATIO, winRatio), - ComputedStat(AVERAGE_BUYIN, avgBuyin) - ) - ) - } - if (gHourlyDuration != null) { hourlyRate = sum / gHourlyDuration @@ -424,29 +472,6 @@ class Calculator { results.addStat(AVERAGE_NET_BB, gBBSum / bbSessionCount) } - // Create stats - results.addStats( - setOf( - ComputedStat(NETRESULT, sum), - ComputedStat(NUMBER_OF_SETS, sessionSets.size.toDouble()), - ComputedStat(NUMBER_OF_GAMES, computables.size.toDouble()), - ComputedStat(HANDS_PLAYED, totalHands) - ) - ) - - Stat.returnOnInvestment(sum, totalBuyin)?.let { roi -> - results.addStat(ROI, roi) - } - Stat.netBBPer100Hands(bbSum, totalHands)?.let { netBB100 -> - results.addStat(NET_BB_PER_100_HANDS, netBB100) - } - - maxNetResult?.let { max -> - results.addStat(MAXIMUM_NETRESULT, max) - } - minNetResult?.let { min -> - results.addStat(MINIMUM_NETRESULT, min) - } maxDuration?.let { maxd -> results.addStat(MAXIMUM_DURATION, maxd) // (milliseconds to hours) } @@ -489,7 +514,6 @@ class Calculator { } - } class SSStats(sessionSet: SessionSet, conditions: List) { // Session Set Stats diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt index b0e813a6..6ffaa8ad 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Report.kt @@ -14,59 +14,64 @@ import net.pokeranalytics.android.model.realm.SessionSet /** * The class returned after performing calculation in the Calculator object */ -class Report() { +class Report(var options: Calculator.Options) { + /** + * The mutable list of ComputedResults, one for each group of data + */ private var _results: MutableList = mutableListOf() val results: List = this._results -// private var groups: MutableList = mutableListOf() -// -// var options: Calculator.Options = options -// -// fun addGroup(group: ComputableGroup) { -// this.groups.add(group) -// } -// -// fun addGroups(groups: Collection) { -// this.groups.addAll(groups) -// } - + /** + * Adds a new result to the list of ComputedResults + */ fun addResults(result: ComputedResults) { this._results.add(result) } + /** + * Returns the list of entries corresponding to the provided [stat] + * One value will be returned by result + */ fun lineEntries(stat: Stat): List { val entries = mutableListOf() this._results.forEachIndexed { index, results -> - val cs = results.computedStat(stat) - cs?.let { computedStat -> - entries.add(Entry(index.toFloat(), computedStat.value.toFloat(), results)) + results.computedStat(stat)?.progressValue?.let { evoValue -> + entries.add(Entry(index.toFloat(), evoValue.toFloat(), results)) } } return entries } - fun barEntries(stat: Stat): List { + fun barEntries(stat: Stat? = null): List { val entries = mutableListOf() - - this._results.forEachIndexed { index, results -> - val cs = results.computedStat(stat) - cs?.let { computedStat -> - val barEntry = BarEntry(index.toFloat(), computedStat.value.toFloat(), results) - entries.add(barEntry) + val statToUse = stat ?: options.displayedStats.firstOrNull() + + statToUse?.let { + this._results.forEachIndexed { index, results -> + val cs = results.computedStat(it) + cs?.let { computedStat -> + val barEntry = BarEntry(index.toFloat(), computedStat.value.toFloat(), results) + entries.add(barEntry) + } } } + return entries } - fun multiLineEntries(stat: Stat): List> { + fun multiLineEntries(): List> { val entries = mutableListOf>() - this._results.forEach { result -> - val entryList = result.singleLineEntries(stat) - entries.add(entryList) + + options.displayedStats.forEach { stat -> + this._results.forEach { result -> + val entryList = result.singleLineEntries(stat) + entries.add(entryList) + } } + return entries } @@ -138,7 +143,7 @@ class ComputableGroup(name: String, conditions: List = listOf(), /** * A subgroup used to compute stat variation */ - var comparedComputables: ComputableGroup? = null + var comparedGroup: ComputableGroup? = null /** * The computed stats of the comparable sessionGroup @@ -157,7 +162,7 @@ class ComputableGroup(name: String, conditions: List = listOf(), } -class ComputedResults(group: ComputableGroup) : StatEntry { +class ComputedResults(group: ComputableGroup, shouldManageMultiGroupProgressValues: Boolean = false) : StatEntry { /** * The session group used to computed the stats @@ -170,6 +175,8 @@ class ComputedResults(group: ComputableGroup) : StatEntry { // The map containing all evolution numericValues for all stats private var _evolutionValues: MutableMap> = mutableMapOf() + private var shouldManageMultiGroupProgressValues = shouldManageMultiGroupProgressValues + fun allStats(): Collection { return this._computedStats.values } @@ -198,13 +205,109 @@ class ComputedResults(group: ComputableGroup) : StatEntry { } fun addStat(stat: Stat, value: Double, secondValue: Double? = null) { - this._computedStats[stat] = ComputedStat(stat, value, secondValue = secondValue) + val computedStat = ComputedStat(stat, value, secondValue = secondValue) + this.addComputedStat(computedStat) } fun addStats(computedStats: Set) { computedStats.forEach { - this._computedStats[it.stat] = it + this.addComputedStat(it) + } + } + + /** + * Adds a [computedStat] to the list of stats + * Also computes evolution values using the previously computed values + */ + private fun addComputedStat(computedStat: ComputedStat) { + + if (this.shouldManageMultiGroupProgressValues) { + + computedStat.progressValue = computedStat.value // useful for first occurence, otherwise overridden + + // Computes the evolution value for the stat + this.group.comparedComputedResults?.let { result -> + + result.computedStat(computedStat.stat)?.let { previousComputedStat -> + + val previousValue = previousComputedStat.progressValue ?: previousComputedStat.value + when (computedStat.stat) { + Stat.NET_RESULT, Stat.DURATION, Stat.BB_NET_RESULT, Stat.BB_SESSION_COUNT, + Stat.WINNING_SESSION_COUNT, Stat.TOTAL_BUYIN, Stat.HANDS_PLAYED -> { + computedStat.progressValue = previousValue + computedStat.value + } + else -> {} + } + } + } } + + this._computedStats[computedStat.stat] = computedStat + + } + + fun consolidateEvolutionStat() { + + val netResult = this.computedStat(Stat.NET_RESULT)?.secondValue + val bbNetResult = this.computedStat(Stat.BB_NET_RESULT)?.secondValue + val duration = this.computedStat(Stat.DURATION)?.secondValue + val numberOfGames = this.computedStat(Stat.NUMBER_OF_GAMES)?.secondValue + val numberOfSets = this.computedStat(Stat.NUMBER_OF_SETS)?.secondValue + val handsPlayed = this.computedStat(Stat.HANDS_PLAYED)?.secondValue + val winningCount = this.computedStat(Stat.WINNING_SESSION_COUNT)?.secondValue + val bbSessionCount = this.computedStat(Stat.BB_SESSION_COUNT)?.secondValue + val totalBuyin = this.computedStat(Stat.TOTAL_BUYIN)?.secondValue + + this.allStats().forEach { computedStat -> + when (computedStat.stat) { + Stat.HOURLY_RATE -> { + if (netResult != null && duration != null) { + computedStat.secondValue = netResult / duration + } + } + Stat.AVERAGE -> { + if (netResult != null && numberOfGames != null) { + computedStat.secondValue = netResult / numberOfGames + } + } + Stat.AVERAGE_DURATION -> { + if (duration != null && numberOfSets != null) { + computedStat.secondValue = duration / numberOfSets + } + } + Stat.NET_BB_PER_100_HANDS -> { + if (bbNetResult != null && handsPlayed != null) { + computedStat.secondValue = Stat.netBBPer100Hands(bbNetResult, handsPlayed) + } + } + Stat.HOURLY_RATE_BB -> { + if (bbNetResult != null && duration != null) { + computedStat.secondValue = bbNetResult / duration + } + } + Stat.AVERAGE_NET_BB -> { + if (bbNetResult != null && bbSessionCount != null) { + computedStat.secondValue = bbNetResult / bbSessionCount + } + } + Stat.WIN_RATIO -> { + if (winningCount != null && numberOfGames != null) { + computedStat.secondValue = winningCount / numberOfGames + } + } + Stat.AVERAGE_BUYIN -> { + if (totalBuyin != null && numberOfGames != null) { + computedStat.secondValue = totalBuyin / numberOfGames + } + } + Stat.ROI -> { + if (totalBuyin != null && netResult != null) { + computedStat.secondValue = Stat.returnOnInvestment(netResult, totalBuyin) + } + } + } + } + } fun computedStat(stat: Stat): ComputedStat? { @@ -222,6 +325,9 @@ class ComputedResults(group: ComputableGroup) : StatEntry { } fun finalize(options: Calculator.Options) { + + this.consolidateEvolutionStat() + if (options.evolutionValues != Calculator.Options.EvolutionValues.NONE) { // Sort points as a distribution @@ -234,13 +340,6 @@ class ComputedResults(group: ComputableGroup) : StatEntry { } } - /** - * Returns the number of computed stats - */ - fun numberOfStats(): Int { - return this._computedStats.size - } - // MPAndroidChart fun defaultStatEntries(stat: Stat): List { @@ -289,8 +388,9 @@ class ComputedResults(group: ComputableGroup) : StatEntry { override val entryTitle: String = this.group.name override fun formattedValue(stat: Stat, context: Context): TextFormat { - this.computedStat(stat)?.let { - return it.format(context) + this.computedStat(stat)?.progressValue?.let { + return stat.format(it, context = context) +// return it.format(context) } ?: run { throw IllegalStateException("Missing stat in results") } diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt index 51ddc180..4e1aea9b 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt @@ -55,7 +55,8 @@ enum class AggregationType { */ enum class Stat : RowRepresentable { - NETRESULT, + NET_RESULT, + BB_NET_RESULT, HOURLY_RATE, AVERAGE, NUMBER_OF_SETS, @@ -77,7 +78,10 @@ enum class Stat : RowRepresentable { MAXIMUM_NETRESULT, MINIMUM_NETRESULT, MAXIMUM_DURATION, - DAYS_PLAYED + DAYS_PLAYED, + WINNING_SESSION_COUNT, + BB_SESSION_COUNT, + TOTAL_BUYIN, ; /** @@ -111,7 +115,8 @@ enum class Stat : RowRepresentable { override val resId: Int? get() { return when (this) { - NETRESULT -> R.string.net_result + NET_RESULT -> R.string.net_result + BB_NET_RESULT -> R.string.total_net_result_bb_ HOURLY_RATE -> R.string.average_hour_rate AVERAGE -> R.string.average NUMBER_OF_SETS -> R.string.number_of_sessions @@ -134,6 +139,7 @@ enum class Stat : RowRepresentable { MINIMUM_NETRESULT -> R.string.min_net_result MAXIMUM_DURATION -> R.string.longest_session DAYS_PLAYED -> R.string.days_played + else -> throw IllegalStateException("Stat ${this.name} name required but undefined") } } @@ -149,7 +155,7 @@ enum class Stat : RowRepresentable { when (this) { // Amounts + red/green - NETRESULT, HOURLY_RATE, AVERAGE, MAXIMUM_NETRESULT, MINIMUM_NETRESULT -> { + NET_RESULT, HOURLY_RATE, AVERAGE, MAXIMUM_NETRESULT, MINIMUM_NETRESULT -> { val color = if (value >= this.threshold) R.color.green else R.color.red return TextFormat(value.toCurrency(currency), color) } @@ -193,7 +199,9 @@ enum class Stat : RowRepresentable { val resId = when (this) { AVERAGE, AVERAGE_DURATION, NET_BB_PER_100_HANDS, HOURLY_RATE_BB, AVERAGE_NET_BB, ROI, WIN_RATIO, HOURLY_RATE -> R.string.average - NETRESULT, DURATION -> R.string.total + NUMBER_OF_SETS -> R.string.number_of_sessions + NUMBER_OF_GAMES -> R.string.number_of_records + NET_RESULT, DURATION -> R.string.total STANDARD_DEVIATION -> R.string.net_result STANDARD_DEVIATION_HOURLY -> R.string.hour_rate_without_pauses STANDARD_DEVIATION_BB_PER_100_HANDS -> R.string.net_result_bb_per_100_hands @@ -217,7 +225,7 @@ enum class Stat : RowRepresentable { val aggregationTypes: List get() { return when (this) { - NETRESULT -> listOf(AggregationType.SESSION, AggregationType.MONTH, AggregationType.YEAR, AggregationType.DURATION) + NET_RESULT -> listOf(AggregationType.SESSION, AggregationType.MONTH, AggregationType.YEAR, AggregationType.DURATION) NUMBER_OF_GAMES, NUMBER_OF_SETS -> listOf(AggregationType.MONTH, AggregationType.YEAR) else -> listOf(AggregationType.SESSION, AggregationType.MONTH, AggregationType.YEAR) } @@ -239,6 +247,14 @@ enum class Stat : RowRepresentable { } } + val shouldShowNumberOfSessions: Boolean + get() { + return when (this) { + NUMBER_OF_GAMES, NUMBER_OF_SETS -> false + else -> true + } + } + override val viewType: Int = RowViewType.TITLE_VALUE.ordinal } @@ -253,6 +269,11 @@ class ComputedStat(var stat: Stat, var value: Double, var secondValue: Double? = } } + /** + * The value used to get evolution dataset + */ + var progressValue: Double? = null + /** * The variation of the stat */ diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt index 49a3b80c..9d983688 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt @@ -583,7 +583,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat CustomizableRowRepresentable( RowViewType.HEADER_TITLE_AMOUNT_BIG, title = getFormattedDuration(), - computedStat = ComputedStat(Stat.NETRESULT, result?.net ?: 0.0, currency = currency) + computedStat = ComputedStat(Stat.NET_RESULT, result?.net ?: 0.0, currency = currency) ) ) rows.add(SeparatorRow()) @@ -593,7 +593,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat CustomizableRowRepresentable( RowViewType.HEADER_TITLE_AMOUNT_BIG, resId = R.string.pause, - computedStat = ComputedStat(Stat.NETRESULT, result?.net ?: 0.0, currency = currency) + computedStat = ComputedStat(Stat.NET_RESULT, result?.net ?: 0.0, currency = currency) ) ) rows.add(SeparatorRow()) @@ -603,7 +603,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat CustomizableRowRepresentable( RowViewType.HEADER_TITLE_AMOUNT_BIG, title = getFormattedDuration(), - computedStat = ComputedStat(Stat.NETRESULT, result?.net ?: 0.0, currency = currency) + computedStat = ComputedStat(Stat.NET_RESULT, result?.net ?: 0.0, currency = currency) ) ) rows.add( @@ -926,7 +926,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat this.result?.let { result -> val value: Double? = when (stat) { - Stat.NETRESULT, Stat.AVERAGE, Stat.STANDARD_DEVIATION -> result.net + Stat.NET_RESULT, Stat.AVERAGE, Stat.STANDARD_DEVIATION -> result.net Stat.NUMBER_OF_GAMES, Stat.NUMBER_OF_SETS -> 1.0 Stat.AVERAGE_BUYIN -> result.buyin Stat.ROI -> { diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt index 80d3ed20..562724b8 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt @@ -120,7 +120,7 @@ open class SessionSet() : RealmObject(), Timed, Filterable { override fun formattedValue(stat: Stat, context: Context) : TextFormat { return when (stat) { - Stat.NETRESULT, Stat.AVERAGE -> stat.format(this.ratedNet, currency = null, context = context) + Stat.NET_RESULT, Stat.AVERAGE -> stat.format(this.ratedNet, currency = null, context = context) Stat.DURATION, Stat.AVERAGE_DURATION -> stat.format(this.netDuration.toDouble(), currency = null, context = context) Stat.HOURLY_RATE -> stat.format(this.hourlyRate, currency = null, context = context) Stat.HANDS_PLAYED -> stat.format(this.estimatedHands, currency = null, context = context) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt index 5c0041e9..610a948c 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt @@ -73,6 +73,7 @@ class HomeActivity : PokerAnalyticsActivity() { } override fun onCreateOptionsMenu(menu: Menu?): Boolean { + menu?.clear() menuInflater.inflate(R.menu.toolbar_home, menu) this.homeMenu = menu //TODO: Change queryWith button visibility diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/ReportDetailsActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/ReportDetailsActivity.kt new file mode 100644 index 00000000..be1b5dd1 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/ReportDetailsActivity.kt @@ -0,0 +1,55 @@ +package net.pokeranalytics.android.ui.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import net.pokeranalytics.android.R +import net.pokeranalytics.android.calculus.Report +import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity +import net.pokeranalytics.android.ui.fragment.ReportDetailsFragment + + + +class ReportDetailsActivity : PokerAnalyticsActivity() { + + companion object { + + // Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects + private var report: Report? = null + private var reportTitle: String = "" + + /** + * Default constructor + */ + fun newInstance(context: Context, report: Report, reportTitle: String) { + //parameters = GraphParameters(stat, group, report) + this.report = report + this.reportTitle = reportTitle + val intent = Intent(context, ReportDetailsActivity::class.java) + context.startActivity(intent) + } + + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_report_details) + initUI() + } + + /** + * Init UI + */ + private fun initUI() { + + report?.let { + val fragmentTransaction = supportFragmentManager.beginTransaction() + val reportDetailsFragment = ReportDetailsFragment.newInstance(it, reportTitle) + fragmentTransaction.add(R.id.reportDetailsContainer, reportDetailsFragment) + fragmentTransaction.commit() + + report = null + } + } + +} diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/StatisticDetailsActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/StatisticDetailsActivity.kt index e7fa885e..f5c838d3 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/StatisticDetailsActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/StatisticDetailsActivity.kt @@ -8,9 +8,12 @@ import net.pokeranalytics.android.calculus.ComputableGroup import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity -import net.pokeranalytics.android.ui.fragment.GraphParameters +import net.pokeranalytics.android.ui.fragment.StatisticDetailsFragment +class StatisticsDetailsParameters(var stat: Stat, var computableGroup: ComputableGroup, var report: Report) { +} + class StatisticDetailsActivity : PokerAnalyticsActivity() { private enum class IntentKey(val keyName: String) { @@ -21,14 +24,14 @@ class StatisticDetailsActivity : PokerAnalyticsActivity() { companion object { // Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects - var parameters: GraphParameters? = null - var displayAggregationChoices: Boolean = true + private var parameters: StatisticsDetailsParameters? = null + private var displayAggregationChoices: Boolean = true /** * Default constructor */ fun newInstance(context: Context, stat: Stat, group: ComputableGroup, report: Report, displayAggregationChoices: Boolean = true) { - parameters = GraphParameters(stat, group, report) + parameters = StatisticsDetailsParameters(stat, group, report) this.displayAggregationChoices = displayAggregationChoices val intent = Intent(context, StatisticDetailsActivity::class.java) context.startActivity(intent) @@ -47,6 +50,16 @@ class StatisticDetailsActivity : PokerAnalyticsActivity() { */ private fun initUI() { + val fragmentTransaction = supportFragmentManager.beginTransaction() + val statisticDetailsFragment = StatisticDetailsFragment() + fragmentTransaction.add(R.id.statisticDetailsContainer, statisticDetailsFragment) + fragmentTransaction.commit() + + parameters?.let { + statisticDetailsFragment.setData(it.stat, it.computableGroup, it.report, displayAggregationChoices) + parameters = null + } + } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/adapter/HomePagerAdapter.kt b/app/src/main/java/net/pokeranalytics/android/ui/adapter/HomePagerAdapter.kt index 5e504fb1..e1b32d35 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/adapter/HomePagerAdapter.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/adapter/HomePagerAdapter.kt @@ -17,12 +17,6 @@ class HomePagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAda override fun getItem(position: Int): PokerAnalyticsFragment { return when (position) { - //CLEAN - /* - 0 -> HistoryFragment.newInstance() - 1 -> StatsFragment.newInstance() - 2 -> SettingsFragment.newInstance() - */ 0 -> HistoryFragment.newInstance() 1 -> StatsFragment.newInstance() 2 -> CalendarFragment.newInstance() @@ -33,7 +27,7 @@ class HomePagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAda } override fun getCount(): Int { - return 5//3 + return 5 } override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { @@ -49,12 +43,6 @@ class HomePagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAda override fun getItemPosition(obj: Any): Int { return when (obj) { - //CLEAN - /* - HistoryFragment::class.java -> 0 - StatsFragment::class.java -> 1 - SettingsFragment::class.java -> 2 - */ HistoryFragment::class.java -> 0 StatsFragment::class.java -> 1 CalendarFragment::class.java -> 2 diff --git a/app/src/main/java/net/pokeranalytics/android/ui/adapter/ReportPagerAdapter.kt b/app/src/main/java/net/pokeranalytics/android/ui/adapter/ReportPagerAdapter.kt new file mode 100644 index 00000000..dcd058fa --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/adapter/ReportPagerAdapter.kt @@ -0,0 +1,69 @@ +package net.pokeranalytics.android.ui.adapter + +import android.content.Context +import android.util.SparseArray +import android.view.ViewGroup +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentStatePagerAdapter +import androidx.viewpager.widget.PagerAdapter +import net.pokeranalytics.android.R +import net.pokeranalytics.android.calculus.Report +import net.pokeranalytics.android.ui.fragment.GraphFragment +import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment +import java.lang.ref.WeakReference + +/** + * Home Adapter + */ +class ReportPagerAdapter(val context: Context, val fragmentManager: FragmentManager, val report: Report) : FragmentStatePagerAdapter(fragmentManager) { + + var weakReferences = SparseArray>() + + override fun getItem(position: Int): PokerAnalyticsFragment { + return when (position) { + 0 -> GraphFragment.newInstance(report) + 1 -> GraphFragment.newInstance(report) + 2 -> GraphFragment.newInstance(report) + else -> GraphFragment.newInstance() + } + } + + override fun getCount(): Int { + return 3 + } + + override fun getPageTitle(position: Int): CharSequence? { + return when(position) { + 0 -> context.getString(R.string.bar) + 1 -> context.getString(R.string.line) + 2 -> context.getString(R.string.table) + else -> "" + } + } + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + super.destroyItem(container, position, `object`) + weakReferences.remove(position) + } + + override fun instantiateItem(container: ViewGroup, position: Int): Any { + val fragment = super.instantiateItem(container, position) as PokerAnalyticsFragment + weakReferences.put(position, WeakReference(fragment)) + return fragment + } + + override fun getItemPosition(obj: Any): Int { + return PagerAdapter.POSITION_UNCHANGED + } + + /** + * Return the fragment at the position key + */ + fun getFragment(key: Int): PokerAnalyticsFragment? { + if (weakReferences.get(key) != null) { + return weakReferences.get(key).get() + } + return null + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt index bead1e0e..1741e0eb 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt @@ -52,7 +52,7 @@ class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable private var sessionTypeCondition: QueryCondition? = null private var rowRepresentables: ArrayList = ArrayList() - //private var stat: Stat = Stat.NETRESULT + //private var stat: Stat = Stat.NET_RESULT //private var entries: List = ArrayList() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -183,14 +183,14 @@ class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable rowRepresentables.clear() rowRepresentables.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.net_result)) - rowRepresentables.add(GraphRow(report, Stat.NETRESULT)) - rowRepresentables.add(StatDoubleRow(it.computedStat(Stat.NETRESULT), it.computedStat(Stat.HOURLY_RATE))) + rowRepresentables.add(GraphRow(report, Stat.NET_RESULT)) + rowRepresentables.add(StatDoubleRow(it.computedStat(Stat.NET_RESULT), it.computedStat(Stat.HOURLY_RATE))) rowRepresentables.add(StatDoubleRow(it.computedStat(Stat.LOCATIONS_PLAYED), it.computedStat(Stat.LONGEST_STREAKS))) rowRepresentables.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.distribution)) - rowRepresentables.add(GraphRow(report, Stat.NETRESULT)) + rowRepresentables.add(GraphRow(report, Stat.NET_RESULT)) rowRepresentables.add(StatDoubleRow(it.computedStat(Stat.WIN_RATIO), it.computedStat(Stat.MAXIMUM_NETRESULT))) rowRepresentables.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.volume)) - rowRepresentables.add(GraphRow(report, Stat.NETRESULT)) + rowRepresentables.add(GraphRow(report, Stat.NET_RESULT)) rowRepresentables.add(StatDoubleRow(it.computedStat(Stat.DURATION), it.computedStat(Stat.AVERAGE_DURATION))) rowRepresentables.add(StatDoubleRow(it.computedStat(Stat.DAYS_PLAYED), it.computedStat(Stat.MAXIMUM_DURATION))) } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarFragment.kt index bf7e3c8f..6dcc9294 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarFragment.kt @@ -68,7 +68,7 @@ class CalendarFragment : SessionObserverFragment(), CoroutineScope, StaticRowRep private var sessionTypeCondition: QueryCondition? = null private var currentTimeFilter: TimeFilter = TimeFilter.MONTH - private var currentStat = Stat.NETRESULT + private var currentStat = Stat.NET_RESULT // Life Cycle @@ -132,7 +132,7 @@ class CalendarFragment : SessionObserverFragment(), CoroutineScope, StaticRowRep tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { override fun onTabSelected(tab: TabLayout.Tab) { when (tab.position) { - 0 -> currentStat = Stat.NETRESULT + 0 -> currentStat = Stat.NET_RESULT 1 -> currentStat = Stat.HOURLY_RATE 2 -> currentStat = Stat.NUMBER_OF_GAMES 3 -> currentStat = Stat.WIN_RATIO @@ -297,12 +297,12 @@ class CalendarFragment : SessionObserverFragment(), CoroutineScope, StaticRowRep /* Timber.d("========== YEAR x MONTH") sortedMonthlyReports.keys.forEach { - Timber.d("$it => ${sortedMonthlyReports[it]?.computedStat(Stat.NETRESULT)?.value}") + Timber.d("$it => ${sortedMonthlyReports[it]?.computedStat(Stat.NET_RESULT)?.value}") } Timber.d("========== YEARLY") sortedYearlyReports.keys.forEach { - Timber.d("$it => ${sortedYearlyReports[it]?.computedStat(Stat.NETRESULT)?.value}") + Timber.d("$it => ${sortedYearlyReports[it]?.computedStat(Stat.NET_RESULT)?.value}") } */ diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ComparisonChartFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ComparisonChartFragment.kt index eb2d3041..5ae08654 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ComparisonChartFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ComparisonChartFragment.kt @@ -10,10 +10,10 @@ import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.adapter.ComparisonChartPagerAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource +import net.pokeranalytics.android.ui.extensions.toast import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.MoreTabRow -import net.pokeranalytics.android.ui.extensions.toast class ComparisonChartFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { @@ -55,6 +55,7 @@ class ComparisonChartFragment : PokerAnalyticsFragment(), StaticRowRepresentable } override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + menu?.clear() inflater?.inflate(R.menu.toolbar_comparison_chart, menu) this.comparisonChartMenu = menu super.onCreateOptionsMenu(menu, inflater) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt index 9b0123c7..f5d78f5a 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt @@ -52,6 +52,7 @@ open class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDele } override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + menu?.clear() inflater?.inflate(R.menu.toolbar_editable_data, menu) this.editableMenu = menu updateMenuUI() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt index 88a45a50..499b52aa 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt @@ -71,6 +71,7 @@ open class FiltersFragment : PokerAnalyticsFragment(), StaticRowRepresentableDat } override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + menu?.clear() inflater?.inflate(R.menu.toolbar_editable_data, menu) this.filterMenu = menu updateMenuUI() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt index d44e822e..69fe9938 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt @@ -4,34 +4,25 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.core.view.isVisible import com.github.mikephil.charting.charts.BarChart import com.github.mikephil.charting.charts.BarLineChartBase import com.github.mikephil.charting.charts.LineChart import com.github.mikephil.charting.data.* import com.github.mikephil.charting.highlight.Highlight import com.github.mikephil.charting.listener.OnChartValueSelectedListener -import com.google.android.material.chip.Chip -import com.google.android.material.chip.ChipGroup -import io.realm.Realm import kotlinx.android.synthetic.main.fragment_evograph.* -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.* import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity -import net.pokeranalytics.android.ui.extensions.ChipGroupExtension -import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.graph.PALineDataSet import net.pokeranalytics.android.ui.graph.setStyle import net.pokeranalytics.android.ui.view.LegendView import timber.log.Timber -import java.util.* import kotlin.coroutines.CoroutineContext -class GraphParameters(var stat: Stat, var computableGroup: ComputableGroup, var report: Report) { - -} class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, CoroutineScope { @@ -40,8 +31,13 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co /** * Create new instance */ - fun newInstance(): GraphFragment { + fun newInstance(report: Report? = null): GraphFragment { val fragment = GraphFragment() + + report?.let { + fragment.selectedReport = it + } + val bundle = Bundle() fragment.arguments = bundle return fragment @@ -49,15 +45,12 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co } private lateinit var parentActivity: PokerAnalyticsActivity - private lateinit var computableGroup: ComputableGroup private lateinit var selectedReport: Report private lateinit var legendView: LegendView private lateinit var chartView: BarLineChartBase<*> - private var stat: Stat = Stat.NETRESULT - private var reports: MutableMap = hashMapOf() - private var aggregationTypes: List = listOf() - private var displayAggregationChoices: Boolean = true + private var stat: Stat = Stat.NET_RESULT + private var aggregationType: AggregationType = AggregationType.SESSION override val coroutineContext: CoroutineContext get() = Dispatchers.Main @@ -70,6 +63,7 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initUI() + loadGraph() } // OnChartValueSelectedListener @@ -79,7 +73,6 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co override fun onValueSelected(e: Entry?, h: Highlight?) { e?.let { entry -> - val statEntry = when (entry.data) { is ObjectIdentifier -> { val identifier = entry.data as ObjectIdentifier @@ -88,12 +81,11 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co is StatEntry -> entry.data as StatEntry? else -> null } - statEntry?.let { val formattedDate = it.entryTitle val entryValue = it.formattedValue(this.stat, requireContext()) - val totalStatValue = this.stat.format(e.y.toDouble(), currency = null, context = requireContext()) + val totalStatValue = this.stat.format(entry.y.toDouble(), currency = null, context = requireContext()) this.legendView.setItemData(this.stat, formattedDate, entryValue, totalStatValue) } @@ -105,6 +97,7 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co * Init UI */ private fun initUI() { + Timber.d("initUI") parentActivity = activity as PokerAnalyticsActivity parentActivity.title = stat.localizedTitle(requireContext()) @@ -119,78 +112,24 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co this.chartView.setStyle(false, requireContext()) this.chartContainer.addView(this.chartView) - - this.loadGraph(this.aggregationTypes.first(), this.selectedReport) - - this.aggregationTypes.forEach { type -> - val chip = Chip(requireContext()) - chip.id = type.ordinal - chip.text = requireContext().getString(type.resId) - chip.chipStartPadding = 8f.px - chip.chipEndPadding = 8f.px - this.chipGroup.addView(chip) - } - - this.chipGroup.isVisible = displayAggregationChoices - this.chipGroup.check(this.stat.aggregationTypes.first().ordinal) - - this.chipGroup.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() { - override fun onCheckedChanged(group: ChipGroup, checkedId: Int) { - super.onCheckedChanged(group, checkedId) - val aggregationType = aggregationTypes[checkedId] - - reports[aggregationType]?.let { - loadGraph(aggregationType, it) - } ?: run { - launchStatComputation(aggregationType) - } - - } - }) - } - private fun launchStatComputation(aggregationType: AggregationType) { - - GlobalScope.launch(coroutineContext) { - - var r: Report? = null - val test = GlobalScope.async { - val s = Date() - Timber.d(">>> start...") - - val realm = Realm.getDefaultInstance() - - val report = Calculator.computeStatsWithEvolutionByAggregationType(realm, computableGroup, aggregationType) - reports[aggregationType] = report - - r = report - - realm.close() - - val e = Date() - val duration = (e.time - s.time) / 1000.0 - Timber.d(">>> ended in $duration seconds") - - } - test.await() + /** + * Load graph + */ + private fun loadGraph() { + Timber.d("loadGraph") - if (!isDetached) { - r?.let { - loadGraph(aggregationType, it) + val graphEntries = when (aggregationType) { + AggregationType.SESSION, AggregationType.DURATION -> selectedReport.results.firstOrNull()?.defaultStatEntries(stat) + AggregationType.MONTH, AggregationType.YEAR -> { + when (this.stat) { + Stat.NUMBER_OF_GAMES, Stat.NUMBER_OF_SETS -> selectedReport.barEntries(this.stat) + else -> selectedReport.lineEntries(this.stat) } } } - } - - fun loadGraph(aggregationType: AggregationType, report: Report) { - - val graphEntries = when (aggregationType) { - AggregationType.SESSION, AggregationType.DURATION -> report.results.firstOrNull()?.defaultStatEntries(stat) - AggregationType.MONTH, AggregationType.YEAR -> report.lineEntries(this.stat) - } - graphEntries?.let { entries -> this.legendView.prepareWithStat(this.stat, entries.size) @@ -228,15 +167,16 @@ class GraphFragment : PokerAnalyticsFragment(), OnChartValueSelectedListener, Co /** * Set data */ - fun setData(stat: Stat, group: ComputableGroup, report: Report, displayAggregationChoices: Boolean = true) { - this.stat = stat - this.computableGroup = group + fun setData(report: Report, aggregationType: AggregationType) { + Timber.d("setData") - this.aggregationTypes = stat.aggregationTypes - this.reports[this.aggregationTypes.first()] = report this.selectedReport = report - this.displayAggregationChoices = displayAggregationChoices + this.aggregationType = aggregationType + this.stat = report.options.displayedStats.first() + if (isAdded && !isDetached) { + loadGraph() + } } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportDetailsFragment.kt new file mode 100644 index 00000000..64475656 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportDetailsFragment.kt @@ -0,0 +1,92 @@ +package net.pokeranalytics.android.ui.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.google.android.material.tabs.TabLayout +import kotlinx.android.synthetic.main.fragment_report_details.* +import kotlinx.android.synthetic.main.fragment_statistic_details.toolbar +import net.pokeranalytics.android.R +import net.pokeranalytics.android.calculus.AggregationType +import net.pokeranalytics.android.calculus.Report +import net.pokeranalytics.android.calculus.Stat +import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity +import net.pokeranalytics.android.ui.adapter.ReportPagerAdapter +import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment + +class ReportDetailsFragment : PokerAnalyticsFragment() { + + companion object { + fun newInstance(report: Report?, reportTitle: String): ReportDetailsFragment { + val fragment = ReportDetailsFragment() + fragment.reportTitle = reportTitle + report?.let { + fragment.selectedReport = it + } + val bundle = Bundle() + fragment.arguments = bundle + return fragment + + } + } + + private lateinit var parentActivity: PokerAnalyticsActivity + private lateinit var selectedReport: Report + + private var reports: MutableMap = hashMapOf() + private var stat: Stat = Stat.NET_RESULT + private var displayAggregationChoices: Boolean = true + private var reportTitle: String = "" + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_report_details, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initUI() + } + + /** + * Init UI + */ + private fun initUI() { + + parentActivity = activity as PokerAnalyticsActivity + + // Avoid a bug during setting the title + toolbar.title = "" + + parentActivity.setSupportActionBar(toolbar) + parentActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true) + setHasOptionsMenu(true) + + toolbar.title = reportTitle + + val reportPagerAdapter = ReportPagerAdapter(requireContext(), parentActivity.supportFragmentManager, selectedReport) + viewPager.adapter = reportPagerAdapter + viewPager.offscreenPageLimit = 3 + + tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + override fun onTabSelected(tab: TabLayout.Tab) { + viewPager.setCurrentItem(tab.position, false) + } + + override fun onTabUnselected(tab: TabLayout.Tab) { + } + + override fun onTabReselected(tab: TabLayout.Tab) { + } + }) + } + + + /** + * Set data + */ + fun setData(report: Report) { + this.selectedReport = report + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt index b8b5738a..ec862ad2 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt @@ -5,8 +5,16 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager +import io.realm.Realm import kotlinx.android.synthetic.main.fragment_stats.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import net.pokeranalytics.android.R +import net.pokeranalytics.android.calculus.Calculator +import net.pokeranalytics.android.calculus.Stat +import net.pokeranalytics.android.model.comparison.Comparator +import net.pokeranalytics.android.ui.activity.ReportDetailsActivity import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource @@ -14,6 +22,8 @@ import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.ReportRow import timber.log.Timber +import java.util.* +import kotlin.collections.ArrayList class ReportsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { @@ -59,12 +69,9 @@ class ReportsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSour override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { super.onRowSelected(position, row, fromAction) - Timber.d("row: $row") - when (row) { - ReportRow.DAY_OF_WEEKS -> { - //TODO: Open ComparisonChartActivity with correct data - //TODO: Calcul report before or after - } + if (row is ReportRow) { + val reportName = row.localizedTitle(requireContext()) + launchComputation(row.comparators, reportName) } } @@ -93,5 +100,29 @@ class ReportsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSour } } + /** + * Launch computation + */ + private fun launchComputation(comparators: List, reportName: String) { + + GlobalScope.launch { + + val startDate = Date() + val realm = Realm.getDefaultInstance() + + val requiredStats: List = listOf(Stat.NET_RESULT) + val options = Calculator.Options(evolutionValues = Calculator.Options.EvolutionValues.STANDARD, stats = requiredStats) + val report = Calculator.computeStatsWithComparators(realm, comparators = comparators, options = options) + + Timber.d("launchComputation: ${System.currentTimeMillis() - startDate.time}ms") + + launch(Dispatchers.Main) { + if (!isDetached) { + ReportDetailsActivity.newInstance(requireContext(), report, reportName) + } + } + } + } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt index 346396de..c1a8d738 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt @@ -63,6 +63,7 @@ class SessionFragment : PokerAnalyticsFragment(), RowRepresentableDelegate { } override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + menu?.clear() inflater?.inflate(R.menu.toolbar_session, menu) this.sessionMenu = menu updateMenuUI() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticDetailsFragment.kt index 8ea97620..37ac6e25 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticDetailsFragment.kt @@ -6,13 +6,25 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.github.mikephil.charting.data.Entry +import androidx.core.view.isVisible +import com.google.android.material.chip.Chip +import com.google.android.material.chip.ChipGroup +import io.realm.Realm import kotlinx.android.synthetic.main.fragment_statistic_details.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import net.pokeranalytics.android.R -import net.pokeranalytics.android.calculus.Stat -import net.pokeranalytics.android.ui.activity.StatisticDetailsActivity +import net.pokeranalytics.android.calculus.* import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity +import net.pokeranalytics.android.ui.extensions.ChipGroupExtension +import net.pokeranalytics.android.ui.extensions.hideWithAnimation +import net.pokeranalytics.android.ui.extensions.px +import net.pokeranalytics.android.ui.extensions.showWithAnimation import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment +import timber.log.Timber +import java.util.* + class StatisticDetailsFragment : PokerAnalyticsFragment() { @@ -24,9 +36,13 @@ class StatisticDetailsFragment : PokerAnalyticsFragment() { } private lateinit var parentActivity: PokerAnalyticsActivity + private lateinit var computableGroup: ComputableGroup + private lateinit var graphFragment: GraphFragment + private lateinit var selectedReport: Report - private var stat: Stat = Stat.NETRESULT - private var entries: List = ArrayList() + private var reports: MutableMap = hashMapOf() + private var stat: Stat = Stat.NET_RESULT + private var displayAggregationChoices: Boolean = true override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_statistic_details, container, false) @@ -51,29 +67,99 @@ class StatisticDetailsFragment : PokerAnalyticsFragment() { parentActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true) setHasOptionsMenu(true) - toolbar.title = stat.localizedTitle(requireContext()) val fragmentManager = parentActivity.supportFragmentManager val fragmentTransaction = fragmentManager.beginTransaction() - val fragment = GraphFragment() + graphFragment = GraphFragment() - fragmentTransaction.add(R.id.container, fragment) + fragmentTransaction.add(R.id.graphContainer, graphFragment) fragmentTransaction.commit() - StatisticDetailsActivity.parameters?.let { - fragment.setData(it.stat, it.computableGroup, it.report, StatisticDetailsActivity.displayAggregationChoices) - StatisticDetailsActivity.parameters = null - } ?: run { - throw Exception("Missing graph parameters") + + stat.aggregationTypes.firstOrNull()?.let { aggregationType -> + reports[aggregationType]?.let { report -> + graphFragment.setData(report, aggregationType) + } } + + toolbar.title = stat.localizedTitle(requireContext()) + val aggregationTypes = stat.aggregationTypes + + aggregationTypes.forEachIndexed { index, type -> + val chip = Chip(requireContext()) + chip.id = index + chip.text = requireContext().getString(type.resId) + chip.chipStartPadding = 8f.px + chip.chipEndPadding = 8f.px + this.chipGroup.addView(chip) + } + + this.chipGroup.isVisible = displayAggregationChoices + this.chipGroup.check(0) + + this.chipGroup.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() { + override fun onCheckedChanged(group: ChipGroup, checkedId: Int) { + super.onCheckedChanged(group, checkedId) + val aggregationType = aggregationTypes[checkedId] + + reports[aggregationType]?.let { report -> + graphFragment.setData(report, aggregationType) + } ?: run { + launchStatComputation(aggregationType) + } + + } + }) } + /** + * Launch stat computation + */ + private fun launchStatComputation(aggregationType: AggregationType) { + + graphContainer.hideWithAnimation() + progressBar.showWithAnimation() + + //TODO: Create loader here + Timber.d("launchStatComputation: $aggregationType") + + GlobalScope.launch { + + val s = Date() + Timber.d(">>> start...") + + val realm = Realm.getDefaultInstance() + + val report = Calculator.computeStatsWithEvolutionByAggregationType(realm, stat, computableGroup, aggregationType) + reports[aggregationType] = report + + realm.close() + + val e = Date() + val duration = (e.time - s.time) / 1000.0 + Timber.d(">>> ended in $duration seconds") + + launch(Dispatchers.Main) { + graphFragment.setData(report, aggregationType) + progressBar.hideWithAnimation() + graphContainer.showWithAnimation() + } + } + } + + /** * Set data */ - fun setData(stat: Stat, entries: List) { + fun setData(stat: Stat, computableGroup: ComputableGroup, report: Report, displayAggregationChoices: Boolean) { this.stat = stat - this.entries = entries + this.computableGroup = computableGroup + this.selectedReport = report + this.displayAggregationChoices = displayAggregationChoices + + stat.aggregationTypes.firstOrNull()?.let { + reports[it] = report + } } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt index 2f302352..2d28347e 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt @@ -137,14 +137,12 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc GlobalScope.launch(coroutineContext) { - var r = Report() val test = GlobalScope.async { val s = Date() Timber.d(">>> start...") val realm = Realm.getDefaultInstance() - r = createSessionGroupsAndStartCompute(realm) - report = r + report = createSessionGroupsAndStartCompute(realm) realm.close() val e = Date() @@ -155,7 +153,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc test.await() if (!isDetached) { - showResults(r) + showResults() } } @@ -164,7 +162,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc private fun createSessionGroupsAndStartCompute(realm: Realm): Report { val allStats: List = listOf( - Stat.NETRESULT, + Stat.NET_RESULT, Stat.HOURLY_RATE, Stat.AVERAGE, Stat.NUMBER_OF_SETS, @@ -173,7 +171,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc ) val allSessionGroup = ComputableGroup(stringAll, listOf(), allStats) val cgStats: List = listOf( - Stat.NETRESULT, + Stat.NET_RESULT, Stat.HOURLY_RATE, Stat.NET_BB_PER_100_HANDS, Stat.HOURLY_RATE_BB, @@ -185,7 +183,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc ) val cgSessionGroup = ComputableGroup(stringCashGame, listOf(QueryCondition.CASH), cgStats) val tStats: List = - listOf(Stat.NETRESULT, Stat.HOURLY_RATE, Stat.ROI, Stat.WIN_RATIO, Stat.NUMBER_OF_GAMES, Stat.AVERAGE_BUYIN) + listOf(Stat.NET_RESULT, Stat.HOURLY_RATE, Stat.ROI, Stat.WIN_RATIO, Stat.NUMBER_OF_GAMES, Stat.AVERAGE_BUYIN) val tSessionGroup = ComputableGroup(stringTournament, listOf(QueryCondition.TOURNAMENT), tStats) Timber.d(">>>>> Start computations...") @@ -198,9 +196,11 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc } - private fun showResults(report: Report) { - this.rowRepresentables = this.convertReportIntoRepresentables(report) - statsAdapter.notifyDataSetChanged() + private fun showResults() { + report?.let { + this.rowRepresentables = this.convertReportIntoRepresentables(it) + statsAdapter.notifyDataSetChanged() + } } private fun convertReportIntoRepresentables(report: Report): ArrayList { @@ -239,7 +239,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc GlobalScope.launch(coroutineContext) { - var report = Report() + var report: Report? = null val test = GlobalScope.async { val s = Date() Timber.d(">>> start...") @@ -247,7 +247,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc val realm = Realm.getDefaultInstance() val aggregationType = stat.aggregationTypes.first() - report = Calculator.computeStatsWithEvolutionByAggregationType(realm, computableGroup, aggregationType) + report = Calculator.computeStatsWithEvolutionByAggregationType(realm, stat, computableGroup, aggregationType) realm.close() @@ -259,7 +259,9 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc test.await() if (!isDetached) { - StatisticDetailsActivity.newInstance(requireContext(), stat, computableGroup, report) + report?.let { + StatisticDetailsActivity.newInstance(requireContext(), stat, computableGroup, it) + } } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/LegendView.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/LegendView.kt index 3d94b2a3..f2cce401 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/LegendView.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/LegendView.kt @@ -57,7 +57,9 @@ class LegendView : FrameLayout { this.stat2Name.isVisible = false } - this.counter.text = "$counter ${context.getString(R.string.sessions)}" + val counterText = "$counter ${context.getString(R.string.sessions)}" + this.counter.text = counterText + this.counter.isVisible = stat.shouldShowNumberOfSessions } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/HomeViewPager.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/NoPagingViewPager.kt similarity index 81% rename from app/src/main/java/net/pokeranalytics/android/ui/view/HomeViewPager.kt rename to app/src/main/java/net/pokeranalytics/android/ui/view/NoPagingViewPager.kt index 2802f2fb..bb7eac22 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/HomeViewPager.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/NoPagingViewPager.kt @@ -6,9 +6,9 @@ import android.view.MotionEvent import androidx.viewpager.widget.ViewPager /** - * Poker Analytics ViewPager + * ViewPager with paging disabled */ -class HomeViewPager(context: Context, attrs: AttributeSet) : ViewPager(context, attrs) { +class NoPagingViewPager(context: Context, attrs: AttributeSet) : ViewPager(context, attrs) { var enablePaging: Boolean = false diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt index 362a83fb..3fb91cac 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt @@ -149,7 +149,7 @@ class SessionRowView : FrameLayout { rowHistorySession.infoTitle.isVisible = false val result = session.result?.net ?: 0.0 - val formattedStat = ComputedStat(Stat.NETRESULT, result, currency = session.currency).format(context) + val formattedStat = ComputedStat(Stat.NET_RESULT, result, currency = session.currency).format(context) rowHistorySession.gameResult.setTextFormat(formattedStat, context) } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt index 6ccb8219..aa3182b4 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt @@ -63,7 +63,7 @@ class TransactionRowView : FrameLayout { rowTransaction.transactionSubtitle.text = subtitle // Amount - val formattedStat = ComputedStat(Stat.NETRESULT, transaction.amount).format(context) + val formattedStat = ComputedStat(Stat.NET_RESULT, transaction.amount).format(context) rowTransaction.transactionAmount.setTextFormat(formattedStat, context) } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/ReportRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/ReportRow.kt index 12209607..15abef1c 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/ReportRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/ReportRow.kt @@ -1,6 +1,7 @@ package net.pokeranalytics.android.ui.view.rowrepresentable import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.comparison.Comparator import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType @@ -15,7 +16,7 @@ enum class ReportRow : RowRepresentable { LOCATIONS, NUMBER_OF_TABLES, TOURNAMENT_TYPES, - VARIANT; + GAME; companion object { @@ -40,9 +41,24 @@ enum class ReportRow : RowRepresentable { LOCATIONS -> R.string.locations NUMBER_OF_TABLES -> R.string.number_of_tables TOURNAMENT_TYPES -> R.string.tournament_type_complete - VARIANT -> R.string.variant + GAME -> R.string.game } } override val viewType: Int = RowViewType.TITLE_ARROW.ordinal + + val comparators: List + get() { + return when (this) { + BLINDS -> listOf(Comparator.BLIND) + BUY_IN -> listOf(Comparator.TOURNAMENT_ENTRY_FEE) + DAY_OF_WEEKS -> listOf(Comparator.DAY_OF_WEEK) + GENERAL -> listOf(Comparator.CASH, Comparator.LIVE) + LOCATIONS -> listOf(Comparator.LOCATION) + NUMBER_OF_TABLES -> listOf() //TODO + TOURNAMENT_TYPES -> listOf(Comparator.TOURNAMENT_TYPE) + GAME -> listOf(Comparator.GAME) + } + } + } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index d5788e1c..4f76f96f 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -15,7 +15,7 @@ app:layout_constraintTop_toTopOf="parent" app:title="@string/app_name" /> - + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistic_details.xml b/app/src/main/res/layout/activity_statistic_details.xml index 62d1cb20..401d6f55 100644 --- a/app/src/main/res/layout/activity_statistic_details.xml +++ b/app/src/main/res/layout/activity_statistic_details.xml @@ -1,15 +1,7 @@ - + android:id="@+id/statisticDetailsContainer"> - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_calendar_details.xml b/app/src/main/res/layout/fragment_calendar_details.xml index 3eda6595..cd88754a 100644 --- a/app/src/main/res/layout/fragment_calendar_details.xml +++ b/app/src/main/res/layout/fragment_calendar_details.xml @@ -64,10 +64,24 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@+id/recyclerView" + app:layout_constraintTop_toBottomOf="@+id/appBar" tools:alpha="1" tools:visibility="visible" /> + + - - - - - - + app:layout_constraintTop_toBottomOf="@+id/legendContainer" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_report_details.xml b/app/src/main/res/layout/fragment_report_details.xml new file mode 100644 index 00000000..73ad6108 --- /dev/null +++ b/app/src/main/res/layout/fragment_report_details.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_statistic_details.xml b/app/src/main/res/layout/fragment_statistic_details.xml index 44e1e283..952dc2da 100644 --- a/app/src/main/res/layout/fragment_statistic_details.xml +++ b/app/src/main/res/layout/fragment_statistic_details.xml @@ -14,13 +14,54 @@ app:layout_constraintTop_toTopOf="parent" tools:title="@string/app_name" /> + + + + + + + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 58c93d7e..d58f7de3 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,7 +1,7 @@ -