Merge branch 'dev' of gitlab.com:stax-river/poker-analytics into dev

dev
Aurelien Hubert 7 years ago
commit 1099a44b98
  1. 71
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  2. 47
      app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt
  3. 1
      app/src/main/java/net/pokeranalytics/android/ui/activity/components/PokerAnalyticsActivity.kt
  4. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt
  5. 4
      app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarFragment.kt
  6. 48
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt
  7. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt
  8. 4
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt
  9. 7
      app/src/main/res/layout/activity_import.xml
  10. 8
      app/src/main/res/layout/activity_new_data.xml
  11. 8
      app/src/main/res/layout/fragment_import.xml
  12. 1
      app/src/main/res/values/colors.xml

@ -27,11 +27,11 @@ import kotlin.math.min
class Calculator { class Calculator {
/** /**
* The options used for calculations or display * The options used for calculations and display
*/ */
class Options( class Options(
var display: Display = Display.TABLE, var display: Display = Display.TABLE,
evolutionValues: EvolutionValues = EvolutionValues.NONE, progressValues: ProgressValues = ProgressValues.NONE,
var stats: List<Stat> = listOf(), var stats: List<Stat> = listOf(),
var criterias: List<Criteria> = listOf(), var criterias: List<Criteria> = listOf(),
query: Query = Query(), query: Query = Query(),
@ -41,14 +41,20 @@ class Calculator {
var reportSetupId: String? = null var reportSetupId: String? = null
) { ) {
var evolutionValues: EvolutionValues = evolutionValues /**
* Specifies whether progress values should be added and their kind
*/
var progressValues: ProgressValues = progressValues
get() { get() {
if (field == EvolutionValues.NONE && this.display == Display.PROGRESS) { if (field == ProgressValues.NONE && this.display == Display.PROGRESS) {
return EvolutionValues.STANDARD return ProgressValues.STANDARD
} }
return field return field
} }
/**
* The query used to filter data
*/
private var _query: Query = query private var _query: Query = query
init { init {
@ -56,14 +62,14 @@ class Calculator {
throw IllegalStateException("Can't specify a query with conditions AND a filter") throw IllegalStateException("Can't specify a query with conditions AND a filter")
} }
when (this.aggregationType) { this.aggregationType?.let {
AggregationType.MONTH -> this.criterias = listOf(Criteria.AllMonthsUpToNow) this.criterias = it.criterias
AggregationType.YEAR -> this.criterias = listOf(Criteria.Years)
else -> {}
} }
} }
/**
* The query used, either filter query or the provided query
*/
val query: Query val query: Query
get() { get() {
this.filter?.let { this.filter?.let {
@ -73,7 +79,7 @@ class Calculator {
} }
/** /**
* The way the statIds are going to be displayed * The way the computed stats are going to be displayed
*/ */
enum class Display : RowRepresentable { enum class Display : RowRepresentable {
TABLE, TABLE,
@ -105,13 +111,12 @@ class Calculator {
} }
} }
} }
/** /**
* The type of evolution numericValues * The type of evolution numericValues
*/ */
enum class EvolutionValues { enum class ProgressValues {
NONE, NONE,
STANDARD, STANDARD,
TIMED TIMED
@ -130,23 +135,37 @@ class Calculator {
return false return false
} }
/**
* Whether the longest streaks should be computed
*/
val computeLongestStreak: Boolean val computeLongestStreak: Boolean
get() { get() {
return this.stats.contains(LONGEST_STREAKS) return this.stats.contains(LONGEST_STREAKS)
} }
/**
* Whether the values should be sorted
*/
val shouldSortValues: Boolean val shouldSortValues: Boolean
get() { get() {
return this.evolutionValues != EvolutionValues.NONE || this.computeLongestStreak return this.progressValues != ProgressValues.NONE || this.computeLongestStreak
} }
/**
* Whether the number of locations played should be computed
*/
val computeLocationsPlayed: Boolean val computeLocationsPlayed: Boolean
get() { get() {
return this.stats.contains(LOCATIONS_PLAYED) return this.stats.contains(LOCATIONS_PLAYED)
} }
/**
* Whether the number of days played should be computed
*/
val computeDaysPlayed: Boolean val computeDaysPlayed: Boolean
get() { get() {
return this.stats.contains(DAYS_PLAYED) return this.stats.contains(DAYS_PLAYED)
} }
/**
* Whether progress values should be managed at the group level
*/
val shouldManageMultiGroupProgressValues: Boolean val shouldManageMultiGroupProgressValues: Boolean
get() { get() {
return if (this.aggregationType != null) { return if (this.aggregationType != null) {
@ -178,13 +197,15 @@ class Calculator {
stats: List<Stat>? = null stats: List<Stat>? = null
): Report { ): Report {
val options = Options(display = Options.Display.PROGRESS, val options = Options(
evolutionValues = Options.EvolutionValues.STANDARD, display = Options.Display.PROGRESS,
progressValues = Options.ProgressValues.STANDARD,
stats = listOf(stat), stats = listOf(stat),
aggregationType = aggregationType) aggregationType = aggregationType
)
if (aggregationType == AggregationType.DURATION) { if (aggregationType == AggregationType.DURATION) {
options.evolutionValues = Options.EvolutionValues.TIMED options.progressValues = Options.ProgressValues.TIMED
} }
stats?.let { stats?.let {
@ -227,7 +248,7 @@ class Calculator {
val report = Report(options) val report = Report(options)
groups.forEach { group -> groups.forEach { group ->
// val s = Date() // val s = Date()
// Clean existing computables / sessionSets if group is reused // Clean existing computables / sessionSets if group is reused
group.cleanup() group.cleanup()
@ -325,7 +346,7 @@ class Calculator {
} }
val shouldIterateOverComputables = val shouldIterateOverComputables =
(options.evolutionValues == Options.EvolutionValues.STANDARD || options.computeLongestStreak) (options.progressValues == Options.ProgressValues.STANDARD || options.computeLongestStreak)
// Computable Result // Computable Result
if (shouldIterateOverComputables) { if (shouldIterateOverComputables) {
@ -419,7 +440,7 @@ class Calculator {
} }
val shouldIterateOverSets = computableGroup.conditions.isNotEmpty() || val shouldIterateOverSets = computableGroup.conditions.isNotEmpty() ||
options.evolutionValues != Options.EvolutionValues.NONE || options.progressValues != Options.ProgressValues.NONE ||
options.computeDaysPlayed options.computeDaysPlayed
// Session Set // Session Set
@ -450,8 +471,8 @@ class Calculator {
tHourlyRateBB = tBBSum / tHourlyDuration tHourlyRateBB = tBBSum / tHourlyDuration
daysSet.add(sessionSet.startDate.startOfDay()) daysSet.add(sessionSet.startDate.startOfDay())
when (options.evolutionValues) { when (options.progressValues) {
Options.EvolutionValues.STANDARD -> { Options.ProgressValues.STANDARD -> {
results.addEvolutionValue(tHourlyRate, stat = HOURLY_RATE, data = sessionSet) results.addEvolutionValue(tHourlyRate, stat = HOURLY_RATE, data = sessionSet)
results.addEvolutionValue(tIndex.toDouble(), stat = NUMBER_OF_SETS, data = sessionSet) results.addEvolutionValue(tIndex.toDouble(), stat = NUMBER_OF_SETS, data = sessionSet)
results.addEvolutionValue( results.addEvolutionValue(
@ -472,7 +493,7 @@ class Calculator {
} }
} }
Options.EvolutionValues.TIMED -> { Options.ProgressValues.TIMED -> {
results.addEvolutionValue(tRatedNetSum, tHourlyDuration, NET_RESULT, sessionSet) results.addEvolutionValue(tRatedNetSum, tHourlyDuration, NET_RESULT, sessionSet)
results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, sessionSet) results.addEvolutionValue(tHourlyRate, tHourlyDuration, HOURLY_RATE, sessionSet)
results.addEvolutionValue( results.addEvolutionValue(

@ -1,7 +1,9 @@
package net.pokeranalytics.android.ui.activity package net.pokeranalytics.android.ui.activity
import android.Manifest import android.Manifest
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.os.PersistableBundle import android.os.PersistableBundle
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
@ -9,14 +11,36 @@ import io.realm.Realm
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.fragment.ImportFragment import net.pokeranalytics.android.ui.fragment.ImportFragment
import net.pokeranalytics.android.util.csv.CSVImporter
import timber.log.Timber import timber.log.Timber
class ImportActivity : PokerAnalyticsActivity() { class ImportActivity : PokerAnalyticsActivity() {
enum class IntentKey(val keyName: String) {
FILE_PATH("filepath")
}
companion object {
/**
* Create a new instance for result
*/
fun newInstance(context: Context, filePath: String) {
context.startActivity(getIntent(context, filePath))
}
private fun getIntent(context: Context, filePath: String) : Intent {
val intent = Intent(context, ImportActivity::class.java)
intent.putExtra(ImportActivity.IntentKey.FILE_PATH.keyName, filePath)
return intent
}
}
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState) super.onCreate(savedInstanceState, persistentState)
setContentView(R.layout.activity_import)
initUI() initUI()
} }
@ -24,6 +48,7 @@ class ImportActivity : PokerAnalyticsActivity() {
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
// Updates the main thread instance with newly inserted data
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
realm.refresh() realm.refresh()
realm.close() realm.close()
@ -34,20 +59,19 @@ class ImportActivity : PokerAnalyticsActivity() {
val fragmentTransaction = supportFragmentManager.beginTransaction() val fragmentTransaction = supportFragmentManager.beginTransaction()
val fragment = ImportFragment() val fragment = ImportFragment()
val filePath = intent.getStringExtra(ImportActivity.IntentKey.FILE_PATH.keyName)
fragment.setData(filePath)
fragmentTransaction.add(R.id.container, fragment) fragmentTransaction.add(R.id.container, fragment)
fragmentTransaction.commit() fragmentTransaction.commit()
} }
private fun csv() { private fun requestPermission() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
val path = "sdcard/Download/RunGoodSessions1.csv" ActivityCompat.requestPermissions(
val csv = CSVImporter(path) this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), PERMISSION_REQUEST_ACCESS_FINE_LOCATION
csv.start() )
}
ActivityCompat.requestPermissions(
this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), PERMISSION_REQUEST_ACCESS_FINE_LOCATION
)
} }
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent?) {
@ -61,7 +85,6 @@ class ImportActivity : PokerAnalyticsActivity() {
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults) super.onRequestPermissionsResult(requestCode, permissions, grantResults)
} }
} }

@ -20,6 +20,7 @@ open class PokerAnalyticsActivity : AppCompatActivity() {
companion object { companion object {
const val PERMISSION_REQUEST_ACCESS_FINE_LOCATION = 1000 const val PERMISSION_REQUEST_ACCESS_FINE_LOCATION = 1000
const val PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 1001
const val PLAY_SERVICES_RESOLUTION_REQUEST = 2000 const val PLAY_SERVICES_RESOLUTION_REQUEST = 2000
} }

@ -188,7 +188,7 @@ 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( val options = Calculator.Options(
evolutionValues = Calculator.Options.EvolutionValues.STANDARD, progressValues = Calculator.Options.ProgressValues.STANDARD,
stats = requiredStats, stats = requiredStats,
query = query query = query
) )

@ -261,7 +261,7 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
monthlyQueries.forEach { query -> monthlyQueries.forEach { query ->
val options = Calculator.Options( val options = Calculator.Options(
evolutionValues = Calculator.Options.EvolutionValues.STANDARD, progressValues = Calculator.Options.ProgressValues.STANDARD,
stats = requiredStats, stats = requiredStats,
query = query query = query
) )
@ -295,7 +295,7 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
yearConditions.forEach { query -> yearConditions.forEach { query ->
val options = Calculator.Options( val options = Calculator.Options(
evolutionValues = Calculator.Options.EvolutionValues.STANDARD, progressValues = Calculator.Options.ProgressValues.STANDARD,
stats = requiredStats, stats = requiredStats,
query = query query = query
) )

@ -1,11 +1,59 @@
package net.pokeranalytics.android.ui.fragment package net.pokeranalytics.android.ui.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.util.csv.CSVImporter
import timber.log.Timber
import java.util.*
import kotlin.coroutines.CoroutineContext
class ImportFragment : RealmFragment() { class ImportFragment : RealmFragment() {
val coroutineContext: CoroutineContext
get() = Dispatchers.Main
private lateinit var filePath: String
fun setData(path: String) {
this.filePath = path
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_import, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
this.startImport()
}
fun startImport() {
GlobalScope.launch(coroutineContext) {
val test = GlobalScope.async {
val s = Date()
Timber.d(">>> start...")
val csv = CSVImporter(filePath)
csv.start()
val e = Date()
val duration = (e.time - s.time) / 1000.0
Timber.d(">>> Import ended in $duration seconds")
}
test.await()
}
}
} }

@ -170,7 +170,7 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc
val requiredStats: List<Stat> = listOf(Stat.NET_RESULT) val requiredStats: List<Stat> = listOf(Stat.NET_RESULT)
val options = Calculator.Options( val options = Calculator.Options(
display = Calculator.Options.Display.COMPARISON, display = Calculator.Options.Display.COMPARISON,
evolutionValues = Calculator.Options.EvolutionValues.STANDARD, progressValues = Calculator.Options.ProgressValues.STANDARD,
stats = requiredStats, stats = requiredStats,
criterias = criteriaList criterias = criteriaList
) )

@ -56,11 +56,11 @@ abstract class AbstractReportFragment : DataManagerFragment() {
val nameEditText = view.findViewById<EditText>(R.id.reportName) val nameEditText = view.findViewById<EditText>(R.id.reportName)
builder.setView(view) builder.setView(view)
// Add action buttons // Add action buttons
.setPositiveButton(R.string.save) { dialog, id -> .setPositiveButton(R.string.save) { dialog, _ ->
saveReport(nameEditText.text.toString()) saveReport(nameEditText.text.toString())
dialog.dismiss() dialog.dismiss()
} }
.setNegativeButton(R.string.cancel) { dialog, id -> .setNegativeButton(R.string.cancel) { dialog, _ ->
dialog.cancel() dialog.cancel()
} }

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>

@ -27,7 +27,7 @@
android:transitionName="newButtonTransition" android:transitionName="newButtonTransition"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
android:background="@color/gray_darker" android:background="@color/kaki_darker"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@ -57,7 +57,7 @@
style="@style/PokerAnalyticsTheme.TextView.RowTitle" style="@style/PokerAnalyticsTheme.TextView.RowTitle"
android:layout_width="160dp" android:layout_width="160dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="20dp" android:layout_marginStart="16dp"
android:text="@string/new_cash_game" android:text="@string/new_cash_game"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />
@ -88,7 +88,7 @@
style="@style/PokerAnalyticsTheme.TextView.RowTitle" style="@style/PokerAnalyticsTheme.TextView.RowTitle"
android:layout_width="160dp" android:layout_width="160dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="20dp" android:layout_marginStart="16dp"
android:text="@string/new_tournament" android:text="@string/new_tournament"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />
@ -121,7 +121,7 @@
style="@style/PokerAnalyticsTheme.TextView.RowTitle" style="@style/PokerAnalyticsTheme.TextView.RowTitle"
android:layout_width="160dp" android:layout_width="160dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="20dp" android:layout_marginStart="16dp"
android:text="@string/new_operation" android:text="@string/new_operation"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>

@ -30,6 +30,7 @@
<color name="kaki_medium">#57815a</color> <color name="kaki_medium">#57815a</color>
<color name="kaki_light">#657d60</color> <color name="kaki_light">#657d60</color>
<color name="kaki_lighter">#9bae8d</color> <color name="kaki_lighter">#9bae8d</color>
<color name="kaki_darker">#283227</color>
<color name="red">#FF5F57</color> <color name="red">#FF5F57</color>

Loading…
Cancel
Save