Merge branch 'master' into dev

dev^2
Razmig Sarkissian 6 years ago
commit 7653ea86ce
  1. 4
      app/build.gradle
  2. 1
      app/proguard-rules.pro
  3. 34
      app/src/main/java/net/pokeranalytics/android/calculus/ComputedStat.kt
  4. 45
      app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt
  5. 3
      app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt
  6. 2
      app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt
  7. 6
      app/src/main/java/net/pokeranalytics/android/model/realm/ComputableResult.kt
  8. 2
      app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt
  9. 2
      app/src/main/java/net/pokeranalytics/android/ui/activity/FiltersActivity.kt
  10. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt
  11. 58
      app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt
  12. 16
      app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt
  13. 3
      app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt
  14. 18
      app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt
  15. 2
      app/src/main/java/net/pokeranalytics/android/ui/view/LegendView.kt
  16. 5
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt
  17. 4
      app/src/main/java/net/pokeranalytics/android/util/FakeDataManager.kt
  18. 6
      app/src/main/java/net/pokeranalytics/android/util/billing/AppGuard.kt

@ -29,8 +29,8 @@ android {
applicationId "net.pokeranalytics.android"
minSdkVersion 23
targetSdkVersion 28
versionCode 49
versionName "2.1.3"
versionCode 50
versionName "2.1.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

@ -29,6 +29,7 @@
-dontwarn javax.**
-dontwarn io.realm.**
-keep class net.pokeranalytics.android.model.** { *; }
-keep class net.pokeranalytics.android.ui.fragment.** { *; }
# Retrofit

@ -0,0 +1,34 @@
package net.pokeranalytics.android.calculus
import net.pokeranalytics.android.util.TextFormat
import java.util.*
/**
* ComputedStat contains a [stat] and their associated [value]
*/
class ComputedStat(var stat: Stat, var value: Double, var secondValue: Double? = null, var currency: Currency? = null) {
constructor(stat: Stat, value: Double, previousValue: Double?) : this(stat, value) {
if (previousValue != null) {
this.variation = (value - previousValue) / previousValue
}
}
/**
* The value used to get evolution dataset
*/
var progressValue: Double? = null
/**
* The variation of the stat
*/
var variation: Double? = null
/**
* Formats the value of the stat to be suitable for display
*/
fun format(): TextFormat {
return this.stat.format(this.value, this.secondValue, this.currency)
}
}

@ -86,7 +86,7 @@ enum class Stat(override var uniqueIdentifier: Int) : IntIdentifiable, RowRepres
return netBB / numberOfHands * 100
}
fun riskOfRuin(hourlyRate: Double, hourlyStandardDeviation: Double, bankrollValue: Double) : Double? {
fun riskOfRuin(hourlyRate: Double, hourlyStandardDeviation: Double, bankrollValue: Double): Double? {
if (bankrollValue <= 0.0) {
return null
@ -243,13 +243,24 @@ enum class Stat(override var uniqueIdentifier: Int) : IntIdentifiable, RowRepres
}
}
val legendHideRightValue: Boolean
get() {
return when (this) {
AVERAGE, NUMBER_OF_SETS, NUMBER_OF_GAMES, WIN_RATIO,
HOURLY_DURATION, AVERAGE_HOURLY_DURATION -> true
else -> false
}
}
/**
* Returns if the stat has a significant value to display in a progress graph
*/
val graphSignificantIndividualValue: Boolean
get() {
return when (this) {
WIN_RATIO, NUMBER_OF_SETS, NUMBER_OF_GAMES, STANDARD_DEVIATION, HOURLY_DURATION -> false
AVERAGE, WIN_RATIO, NUMBER_OF_SETS, NUMBER_OF_GAMES,
STANDARD_DEVIATION, HOURLY_DURATION -> false
else -> true
}
}
@ -302,33 +313,3 @@ enum class Stat(override var uniqueIdentifier: Int) : IntIdentifiable, RowRepres
override val viewType: Int = RowViewType.TITLE_VALUE.ordinal
}
/**
* ComputedStat contains a [stat] and their associated [value]
*/
class ComputedStat(var stat: Stat, var value: Double, var secondValue: Double? = null, var currency: Currency? = null) {
constructor(stat: Stat, value: Double, previousValue: Double?) : this(stat, value) {
if (previousValue != null) {
this.variation = (value - previousValue) / previousValue
}
}
/**
* The value used to get evolution dataset
*/
var progressValue: Double? = null
/**
* The variation of the stat
*/
var variation: Double? = null
/**
* Formats the value of the stat to be suitable for display
*/
fun format(): TextFormat {
return this.stat.format(this.value, this.secondValue, this.currency)
}
}

@ -15,10 +15,9 @@ class BankrollCalculator {
fun computeReport(realm: Realm, setup: BankrollReportSetup) : BankrollReport {
//val realm = Realm.getDefaultInstance()
val report = BankrollReport(setup)
realm.refresh() // fixes an issue where a newly created bankroll is not found, throwing an exception
val bankrolls: List<Bankroll> =
if (setup.bankrollId != null) {
val bankroll = realm.findById<Bankroll>(setup.bankrollId) ?: throw PAIllegalStateException("Bankroll not found with id=${setup.bankrollId}")

@ -27,7 +27,6 @@ object BankrollReportManager {
init {
val realm = Realm.getDefaultInstance()
realm.isAutoRefresh = true
computableResults = realm.where(ComputableResult::class.java).findAll()
bankrolls = realm.where(Bankroll::class.java).findAll()
transactions = realm.where(Transaction::class.java).findAll()
@ -60,6 +59,7 @@ object BankrollReportManager {
fun reportForBankroll(bankrollId: String?, handler: (BankrollReport) -> Unit) {
Timber.d("Request bankroll report for bankrollId = $bankrollId")
// if the report exists, return it
val existingReport: BankrollReport? = this.reports[bankrollId]
if (existingReport != null) {

@ -20,14 +20,10 @@ open class ComputableResult() : RealmObject(), Filterable {
var bbPer100Hands: BB = 0.0
// var sessionSet: SessionSet? = null
var session: Session? = null
fun updateWith(session: Session) {
// this.sessionSet = session.sessionSet
val rate = session.bankroll?.currency?.rate ?: 1.0
session.result?.let { result ->
@ -50,7 +46,7 @@ open class ComputableResult() : RealmObject(), Filterable {
IS_POSITIVE("isPositive"),
RATED_BUYIN("ratedBuyin"),
ESTIMATED_HANDS("estimatedHands"),
BB_PER100HANDS("bbPer100Hands")
// BB_PER100HANDS("bbPer100Hands")
}
companion object {

@ -67,10 +67,10 @@ class EditableDataActivity : PokerAnalyticsActivity() {
LiveData.TRANSACTION_TYPE.ordinal -> TransactionTypeDataFragment()
else -> EditableDataFragment()
}
fragment.setData(dataType, primaryKey)
fragmentTransaction.add(R.id.container, fragment)
fragmentTransaction.commit()
fragment.setData(dataType, primaryKey)
}
}

@ -64,9 +64,9 @@ class FiltersActivity : PokerAnalyticsActivity() {
val filterableType = FilterableType.valueByIdentifier(uniqueIdentifier)
fragment = FiltersFragment()
fragment.setData(filterId, filterableType)
fragmentTransaction.add(R.id.container, fragment)
fragmentTransaction.commit()
fragment.setData(filterId, filterableType)
fragment.updateMostUsedFiltersVisibility(!hideMostUsedFilters)
}

@ -25,6 +25,7 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.util.extensions.findById
import timber.log.Timber
class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate {
@ -111,6 +112,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc
private fun updateUI() {
this.updateMenuUI()
Timber.d("BankrollDetailsFragment > updateUI > reportForBankroll")
BankrollReportManager.reportForBankroll(this.bankrollId) { bankrollReport ->
this.initRows(bankrollReport)
this.bankrollAdapter.notifyDataSetChanged()

@ -8,7 +8,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.mikephil.charting.data.LineDataSet
import io.realm.RealmObject
import io.realm.RealmResults
import kotlinx.android.synthetic.main.fragment_bankroll.*
import kotlinx.coroutines.Dispatchers
@ -36,6 +35,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.BankrollMainRow
import net.pokeranalytics.android.ui.view.rowrepresentable.BankrollTotalRow
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.util.extensions.sorted
import timber.log.Timber
import java.util.*
import kotlin.collections.ArrayList
@ -60,8 +60,6 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
private var rows: ArrayList<RowRepresentable> = ArrayList()
private var bankrollRowRepresentables: HashMap<String?, List<BankrollRowRepresentable>> = HashMap()
private var lastItemClickedPosition: Int = 0
private var deletedRow: RowRepresentable? = null
private lateinit var bankrolls: RealmResults<Bankroll>
@ -106,26 +104,6 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
}
override fun adapterRows(): List<RowRepresentable>? {
return rows
}
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
lastItemClickedPosition = position
when (row) {
is BankrollGraphRow -> {
val lineDataSet = row.dataSet as LineDataSet
GraphActivity.newInstance(requireContext(), listOf(lineDataSet), title = getString(R.string.bankroll))
}
is BankrollRowRepresentable -> {
BankrollReportManager.reportForBankroll(row.bankrollId) { bankrollReport ->
BankrollDetailsActivity.newInstanceForResult(this, bankrollReport, RequestCode.BANKROLL_DETAILS.value)
}
}
}
}
// Business
/**
* Init data
@ -133,8 +111,17 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
private fun initData() {
this.bankrolls = getRealm().sorted()
this.bankrolls.addChangeListener { _, _ ->
this.createRowRepresentables()
}
this.createRowRepresentables()
}
private fun createRowRepresentables() {
rows.clear()
bankrollRowRepresentables.clear()
// Virtual bankroll
val graphRow = BankrollGraphRow()
@ -148,13 +135,13 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.bankrolls))
bankrolls.forEach { bankroll ->
Timber.d("Creating row for br : ${bankroll.id}, name= ${bankroll.name}, isManaged = ${bankroll.isManaged()}, isValid = ${bankroll.isValid}")
val row = BankrollTotalRow(bankroll.id, bankroll.name)
rows.add(row)
bankrollRowRepresentables[bankroll.id] = listOf(row)
}
dataListAdapter.notifyDataSetChanged()
}
/**
@ -184,17 +171,22 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
}
}
override fun updateUIAfterDeletion(itemId: String, itemPosition: Int) {
lastItemClickedPosition = rows.indexOfFirst { if (it is BankrollRowRepresentable) it.bankrollId == itemId else false }
deletedRow = rows.find { if (it is BankrollRowRepresentable) it.bankrollId == itemId else false }
rows.removeAt(lastItemClickedPosition)
dataListAdapter.notifyItemRemoved(lastItemClickedPosition)
override fun adapterRows(): List<RowRepresentable>? {
return rows
}
override fun updateUIAfterUndoDeletion(newItem: RealmObject) {
deletedRow?.let { row ->
rows.add(lastItemClickedPosition, row)
dataListAdapter.notifyDataSetChanged() // update both virtual + ex-deleted
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
when (row) {
is BankrollGraphRow -> {
val lineDataSet = row.dataSet as LineDataSet
GraphActivity.newInstance(requireContext(), listOf(lineDataSet), title = getString(R.string.bankroll))
}
is BankrollRowRepresentable -> {
Timber.d("BankrollFragment > onRowSelected > reportForBankroll")
BankrollReportManager.reportForBankroll(row.bankrollId) { bankrollReport ->
BankrollDetailsActivity.newInstanceForResult(this, bankrollReport, RequestCode.BANKROLL_DETAILS.value)
}
}
}
}

@ -56,6 +56,14 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource,
private var isUpdating = false
private var showMostUsedFiltersLayout = true
/**
* Set fragment data
*/
fun setData(primaryKey: String?, filterableType: FilterableType) {
this.primaryKey = primaryKey
this.filterableType = filterableType
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_filters, container, false)
@ -289,14 +297,6 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource,
activity?.finish()
}
/**
* Set fragment data
*/
fun setData(primaryKey: String?, filterableType: FilterableType) {
this.primaryKey = primaryKey
this.filterableType = filterableType
}
/**
* Update the most used filters visibility
*/

@ -21,6 +21,7 @@ import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry
import net.pokeranalytics.android.ui.graph.setStyle
import net.pokeranalytics.android.ui.view.LegendView
import net.pokeranalytics.android.ui.view.MultiLineLegendView
import net.pokeranalytics.android.util.extensions.findById
import timber.log.Timber
@ -182,7 +183,7 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
val statEntry = when (entry.data) {
is ObjectIdentifier -> {
val identifier = entry.data as ObjectIdentifier
getRealm().where(identifier.clazz).equalTo("id", identifier.id).findAll().firstOrNull()
getRealm().findById(identifier.clazz, identifier.id)
}
is GraphUnderlyingEntry -> entry.data
else -> null

@ -3,7 +3,6 @@ package net.pokeranalytics.android.ui.graph
import android.content.Context
import com.github.mikephil.charting.data.Entry
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.view.DefaultLegendValues
import net.pokeranalytics.android.ui.view.LegendContent
@ -23,16 +22,13 @@ interface GraphUnderlyingEntry {
): LegendContent {
val leftName = stat.localizedTitle(context)
return when (stat) {
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.WIN_RATIO, Stat.HOURLY_DURATION, Stat.AVERAGE_HOURLY_DURATION -> {
val totalStatValue = stat.format(entry.y.toDouble(), currency = null)
DefaultLegendValues(this.entryTitle(context), totalStatValue, leftName = leftName)
}
else -> {
val entryValue = this.formattedValue(stat)
val totalStatValue = stat.format(entry.y.toDouble(), currency = null)
DefaultLegendValues(this.entryTitle(context), entryValue, totalStatValue, leftName = leftName)
}
val totalStatValue = stat.format(entry.y.toDouble(), currency = null)
return if (stat.legendHideRightValue) {
DefaultLegendValues(this.entryTitle(context), totalStatValue, leftName = leftName)
} else {
val entryValue = this.formattedValue(stat)
DefaultLegendValues(this.entryTitle(context), entryValue, totalStatValue, leftName = leftName)
}
}

@ -108,9 +108,11 @@ open class LegendView : FrameLayout {
this.title.text = content.title.capitalize()
this.stat1Value.setTextFormat(content.leftFormat, context)
content.rightFormat?.let {
this.stat2Value.setTextFormat(it, context)
}
content.leftName?.let { name ->
this.stat1Name.text = name
}

@ -38,6 +38,7 @@ import net.pokeranalytics.android.ui.graph.AxisFormatting
import net.pokeranalytics.android.ui.graph.setStyle
import net.pokeranalytics.android.ui.view.rowrepresentable.*
import net.pokeranalytics.android.util.extensions.longDate
import timber.log.Timber
/**
* An interface used to factor the configuration of RecyclerView.ViewHolder
@ -142,6 +143,7 @@ enum class RowViewType(private var layoutRes: Int) {
*/
@SuppressWarnings("ResourceType")
inner class RowViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
when (row) {
@ -153,6 +155,7 @@ enum class RowViewType(private var layoutRes: Int) {
it.text = row.localizedTitle(itemView.context)
}
Timber.d("RowViewHolder > bind > reportForBankroll")
BankrollReportManager.reportForBankroll(row.bankrollId) { report ->
itemView.findViewById<AppCompatTextView>(R.id.title)?.let {
@ -411,6 +414,7 @@ enum class RowViewType(private var layoutRes: Int) {
when (row) {
is BankrollGraphRow -> {
Timber.d("GraphViewHolder > bind > reportForBankroll")
BankrollReportManager.reportForBankroll(row.bankrollId) { report ->
val dataSet = report.lineDataSet(itemView.context)
row.dataSet = dataSet
@ -441,6 +445,7 @@ enum class RowViewType(private var layoutRes: Int) {
if (row is BankrollRowRepresentable) {
Timber.d("LegendDefaultViewHolder > bind > reportForBankroll")
BankrollReportManager.reportForBankroll(row.bankrollId) { report ->
itemView.findViewById<AppCompatTextView>(R.id.stat1Value)?.let {

@ -20,9 +20,9 @@ class FakeDataManager {
*/
fun createFakeSessions(numberOfSessions: Int = 1000, callback: ((success: Boolean) -> Unit)? = null) {
val buyinList = arrayListOf(100.0, 200.0, 300.0, 500.0, 1000.0, 2000.0)
val buyinList = arrayListOf(100.0, 200.0, 300.0, 500.0, 1000.0, 2000.0, 3000.0)
val resultsList = arrayListOf(
-2500.0, -2000.0, -1500.0, -1000.0, -500.0, 200.0, 1000.0, 1500.0, 2500.0, 3000.0
0.0, 50.0, 100.0, 200.0, 1000.0, 1500.0, 2500.0, 3000.0
)
val commitFrequency = 100

@ -2,6 +2,8 @@ package net.pokeranalytics.android.util.billing
import android.app.Activity
import android.content.Context
import android.os.Handler
import android.os.Looper
import com.android.billingclient.api.*
import net.pokeranalytics.android.BuildConfig
import net.pokeranalytics.android.R
@ -208,7 +210,9 @@ object AppGuard : PurchasesUpdatedListener {
this._isProUser = true
this.purchaseDelegate?.let {
it.purchaseDidSucceed(purchase)
Handler(Looper.getMainLooper()).post {
it.purchaseDidSucceed(purchase)
}
this.purchaseDelegate = null
}
}

Loading…
Cancel
Save