Separate graph logic from calculus

kmm
Laurent 5 years ago
parent 88019aba41
commit 76bfea4fab
  1. 14
      app/src/main/java/net/pokeranalytics/android/calculus/Report.kt
  2. 10
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  3. 9
      app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt
  4. 7
      app/src/main/java/net/pokeranalytics/android/ui/activity/GraphActivity.kt
  5. 5
      app/src/main/java/net/pokeranalytics/android/ui/adapter/ComparisonChartPagerAdapter.kt
  6. 7
      app/src/main/java/net/pokeranalytics/android/ui/adapter/ReportPagerAdapter.kt
  7. 29
      app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt
  8. 9
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ProgressReportFragment.kt
  9. 16
      app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt
  10. 15
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/CustomFieldDataFragment.kt
  11. 8
      app/src/main/java/net/pokeranalytics/android/ui/view/LegendView.kt
  12. 4
      app/src/main/java/net/pokeranalytics/android/ui/view/MultiLineLegendView.kt
  13. 4
      app/src/main/java/net/pokeranalytics/android/ui/viewmodel/GraphViewModel.kt

@ -1,10 +1,10 @@
package net.pokeranalytics.android.calculus
import android.content.Context
import com.github.mikephil.charting.data.Entry
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.interfaces.GraphIdentifiableEntry
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry
import net.pokeranalytics.android.ui.view.DefaultLegendValues
import net.pokeranalytics.android.ui.view.LegendContent
@ -242,18 +242,18 @@ class ComputedResults(group: ComputableGroup,
override fun legendValues(
stat: Stat,
entry: Entry,
style: GraphFragment.Style,
total: Double,
style: Graph.Style,
groupName: String,
context: Context
): LegendContent {
when (style) {
GraphFragment.Style.BAR -> {
Graph.Style.BAR -> {
return when (stat) {
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.WIN_RATIO -> {
val totalStatValue = stat.textFormat(entry.y.toDouble(), currency = null)
val totalStatValue = stat.textFormat(total, currency = null)
DefaultLegendValues(this.entryTitle(context), totalStatValue)
}
else -> {
@ -267,12 +267,12 @@ class ComputedResults(group: ComputableGroup,
return when (stat) {
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.WIN_RATIO -> {
val totalStatValue = stat.textFormat(entry.y.toDouble(), currency = null)
val totalStatValue = stat.textFormat(total, currency = null)
DefaultLegendValues(this.entryTitle(context), totalStatValue)
}
else -> {
val entryValue = this.formattedValue(stat)
val totalStatValue = stat.textFormat(entry.y.toDouble(), currency = null)
val totalStatValue = stat.textFormat(total, currency = null)
DefaultLegendValues(this.entryTitle(context), entryValue, totalStatValue)
}
}

@ -1,7 +1,6 @@
package net.pokeranalytics.android.model.realm
import android.content.Context
import com.github.mikephil.charting.data.Entry
import io.realm.Realm
import io.realm.RealmList
import io.realm.RealmObject
@ -31,6 +30,7 @@ import net.pokeranalytics.android.model.utils.CrashLogging
import net.pokeranalytics.android.model.utils.SessionSetManager
import net.pokeranalytics.android.ui.adapter.UnmanagedRowRepresentableException
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.view.*
import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow
import net.pokeranalytics.android.util.NULL_TEXT
@ -896,14 +896,14 @@ open class Session : RealmObject(), Savable, Editable, RowRepresentable, Timed,
override fun legendValues(
stat: Stat,
entry: Entry,
style: GraphFragment.Style,
total: Double,
style: Graph.Style,
groupName: String,
context: Context
): LegendContent {
when (style) {
GraphFragment.Style.MULTILINE -> {
Graph.Style.MULTILINE -> {
val secondTitle = stat.localizedTitle(context)
val entryValue = this.formattedValue(stat)
@ -929,7 +929,7 @@ open class Session : RealmObject(), Savable, Editable, RowRepresentable, Timed,
DefaultLegendValues(this.entryTitle(context), left, right)
}
else -> {
super<Timed>.legendValues(stat, entry, style, groupName, context)
super<Timed>.legendValues(stat, total, style, groupName, context)
}
}
}

@ -1,7 +1,6 @@
package net.pokeranalytics.android.model.realm
import android.content.Context
import com.github.mikephil.charting.data.Entry
import io.realm.Realm
import io.realm.RealmObject
import io.realm.annotations.Ignore
@ -12,7 +11,7 @@ import net.pokeranalytics.android.model.filter.Filterable
import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.interfaces.*
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.view.DefaultLegendValues
import net.pokeranalytics.android.ui.view.LegendContent
import net.pokeranalytics.android.ui.view.RowRepresentable
@ -163,14 +162,14 @@ open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSo
override fun legendValues(
stat: Stat,
entry: Entry,
style: GraphFragment.Style,
total: Double,
style: Graph.Style,
groupName: String,
context: Context
): LegendContent {
val entryValue = this.formattedValue(stat)
val totalStatValue = stat.textFormat(entry.y.toDouble(), currency = null)
val totalStatValue = stat.textFormat(total, currency = null)
val leftName = context.getString(R.string.amount)
return DefaultLegendValues(this.entryTitle(context), entryValue, totalStatValue, leftName = leftName)
}

@ -11,6 +11,7 @@ import net.pokeranalytics.android.databinding.ActivityGraphBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.ui.activity.components.BaseActivity
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.viewmodel.GraphViewModel
import net.pokeranalytics.android.ui.viewmodel.ViewModelHolder
@ -25,7 +26,7 @@ class GraphActivity : BaseActivity(), ViewModelHolder {
private var lineDataSets: List<LineDataSet>? = null
private var barDataSets: List<BarDataSet>? = null
private var style: GraphFragment.Style? = null
private var style: Graph.Style? = null
private var activityTitle: String? = null
/***
@ -33,7 +34,7 @@ class GraphActivity : BaseActivity(), ViewModelHolder {
*/
fun newLineInstance(context: Context, lineDataSets: List<LineDataSet>, title: String? = null) {
this.lineDataSets = lineDataSets
this.style = GraphFragment.Style.LINE
this.style = Graph.Style.LINE
this.activityTitle = title
val intent = Intent(context, GraphActivity::class.java)
@ -45,7 +46,7 @@ class GraphActivity : BaseActivity(), ViewModelHolder {
*/
fun newBarInstance(context: Context, barDataSets: List<BarDataSet>, title: String? = null) {
this.barDataSets = barDataSets
this.style = GraphFragment.Style.BAR
this.style = Graph.Style.BAR
this.activityTitle = title
val intent = Intent(context, GraphActivity::class.java)

@ -10,6 +10,7 @@ import net.pokeranalytics.android.ui.modules.calendar.CalendarFragment
import net.pokeranalytics.android.ui.modules.feed.FeedFragment
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.fragment.components.BaseFragment
import net.pokeranalytics.android.ui.graph.Graph
import java.lang.ref.WeakReference
/**
@ -21,8 +22,8 @@ class ComparisonChartPagerAdapter(val context: Context, fragmentManager: Fragmen
override fun getItem(position: Int): BaseFragment {
return when (position) {
0 -> GraphFragment.newInstance(GraphFragment.Style.BAR)
1 -> GraphFragment.newInstance(GraphFragment.Style.MULTILINE)
0 -> GraphFragment.newInstance(Graph.Style.BAR)
1 -> GraphFragment.newInstance(Graph.Style.MULTILINE)
2 -> CalendarFragment.newInstance()
else -> FeedFragment.newInstance()
}

@ -8,6 +8,7 @@ import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.fragment.components.BaseFragment
import net.pokeranalytics.android.ui.fragment.report.ComposableTableReportFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.viewmodel.ReportHolder
/**
@ -19,8 +20,8 @@ class ReportPagerAdapter(private val context: Context,
override fun getItem(position: Int): BaseFragment {
return when (position) {
0 -> GraphFragment.newInstance(style = GraphFragment.Style.BAR)
1 -> GraphFragment.newInstance(style = GraphFragment.Style.MULTILINE)
0 -> GraphFragment.newInstance(Graph.Style.BAR)
1 -> GraphFragment.newInstance(Graph.Style.MULTILINE)
2 -> {
val report = this.reportHolder.report
ComposableTableReportFragment.newInstance(report)
@ -33,7 +34,7 @@ class ReportPagerAdapter(private val context: Context,
return 3
}
override fun getPageTitle(position: Int): CharSequence? {
override fun getPageTitle(position: Int): CharSequence {
return when(position) {
0 -> context.getString(R.string.bars)
1 -> context.getString(R.string.lines)

@ -18,6 +18,7 @@ import net.pokeranalytics.android.databinding.FragmentGraphBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.interfaces.ObjectIdentifier
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry
import net.pokeranalytics.android.ui.graph.setStyle
import net.pokeranalytics.android.ui.view.LegendView
@ -37,18 +38,12 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
return this.graphDataProvider.stat
}
enum class Style {
LINE,
BAR,
MULTILINE,
}
companion object {
/**
* Create new instance
*/
fun newInstance(style: Style): GraphFragment {
fun newInstance(style: Graph.Style): GraphFragment {
val fragment = GraphFragment()
val bundle = Bundle()
bundle.putSerializable(BundleKey.STYLE.value, style.ordinal)
@ -58,7 +53,7 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
}
private var style: Style = Style.LINE
private var style: Graph.Style = Graph.Style.LINE
private lateinit var legendView: LegendView
@ -69,7 +64,7 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
// Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentGraphBinding.inflate(inflater, container, false)
return binding.root
@ -89,7 +84,7 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
private fun initData() {
val styleOrdinal = this.arguments?.getInt(BundleKey.STYLE.value) ?: throw PAIllegalStateException("Missing style key in bundle")
this.style = Style.values()[styleOrdinal]
this.style = Graph.Style.values()[styleOrdinal]
this.graphDataProvider = (requireActivity() as ViewModelHolder).model as GraphDataProvider
}
@ -100,14 +95,14 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
private fun initUI() {
this.legendView = when (this.style) {
Style.MULTILINE -> MultiLineLegendView(requireContext())
Graph.Style.MULTILINE -> MultiLineLegendView(requireContext())
else -> LegendView(requireContext())
}
this.binding.legendContainer.addView(this.legendView)
}
fun reload(style: Style) {
fun reload(style: Graph.Style) {
this.style = style
if (isAdded && !isDetached) {
loadGraph()
@ -122,11 +117,11 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
this.binding.chartContainer.removeAllViews()
this.chartView = when (this.style) {
Style.LINE, Style.MULTILINE -> {
Graph.Style.LINE, Graph.Style.MULTILINE -> {
val dataSets = when (this.style) {
Style.LINE -> listOf(this.graphDataProvider.lineDataSet(requireContext()))
Style.MULTILINE -> this.graphDataProvider.multiLineDataSet(requireContext())
Graph.Style.LINE -> listOf(this.graphDataProvider.lineDataSet(requireContext()))
Graph.Style.MULTILINE -> this.graphDataProvider.multiLineDataSet(requireContext())
else -> throw PAIllegalStateException("Cannot happen")
}
@ -146,7 +141,7 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
lineChart
}
Style.BAR -> {
Graph.Style.BAR -> {
val dataSets = listOf(this.graphDataProvider.barDataSet(requireContext()))
@ -209,7 +204,7 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
val groupName = dataSet?.label ?: ""
val color = dataSet?.color
val legendValue = statEntry.legendValues(stat, entry, this.style, groupName, requireContext())
val legendValue = statEntry.legendValues(stat, entry.y.toDouble(), this.style, groupName, requireContext())
this.legendView.setItemData(legendValue, color)
} else {

@ -31,6 +31,7 @@ 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.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
import timber.log.Timber
import java.util.*
@ -42,7 +43,7 @@ class ProgressReportFragment : AbstractReportFragment() {
/**
* Creates new instance
*/
fun newInstance(style: GraphFragment.Style? = null): ProgressReportFragment {
fun newInstance(style: Graph.Style? = null): ProgressReportFragment {
val fragment = ProgressReportFragment()
val bundle = Bundle()
style?.let {
@ -86,7 +87,7 @@ class ProgressReportFragment : AbstractReportFragment() {
val chipGroup = binding.chipGroup
val fragmentManager = parentActivity?.supportFragmentManager
val fragmentTransaction = fragmentManager?.beginTransaction()
this.graphFragment = GraphFragment.newInstance(GraphFragment.Style.LINE)
this.graphFragment = GraphFragment.newInstance(Graph.Style.LINE)
fragmentTransaction?.add(R.id.graphContainer, this.graphFragment)
fragmentTransaction?.commit()
@ -207,11 +208,11 @@ class ProgressReportFragment : AbstractReportFragment() {
when (ds) {
is LineDataSet -> {
this.reportViewModel.setLineDataSet(ds)
graphFragment.reload(GraphFragment.Style.LINE)
graphFragment.reload(Graph.Style.LINE)
}
is BarDataSet -> {
this.reportViewModel.setBarDataSet(ds)
graphFragment.reload(GraphFragment.Style.BAR)
graphFragment.reload(Graph.Style.BAR)
}
else -> throw PAIllegalStateException("unmanaged data set")
}

@ -1,13 +1,19 @@
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.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.view.DefaultLegendValues
import net.pokeranalytics.android.ui.view.LegendContent
import net.pokeranalytics.android.util.TextFormat
interface Graph {
enum class Style {
LINE,
BAR,
MULTILINE,
}
}
interface GraphUnderlyingEntry {
fun entryTitle(context: Context): String
@ -15,14 +21,14 @@ interface GraphUnderlyingEntry {
fun legendValues(
stat: Stat,
entry: Entry,
style: GraphFragment.Style,
total: Double,
style: Graph.Style,
groupName: String,
context: Context
): LegendContent {
val leftName = stat.localizedTitle(context)
val totalStatValue = stat.textFormat(entry.y.toDouble(), currency = null)
val totalStatValue = stat.textFormat(total, currency = null)
return if (stat.legendHideRightValue) {
DefaultLegendValues(this.entryTitle(context), totalStatValue, leftName = leftName)

@ -10,18 +10,14 @@ import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.chip.ChipGroup
import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentBankrollDetailsBinding
import net.pokeranalytics.android.databinding.FragmentCalendarDetailsBinding
import net.pokeranalytics.android.databinding.FragmentCustomViewBinding
import net.pokeranalytics.android.model.realm.CustomField
import net.pokeranalytics.android.model.realm.CustomFieldEntry
import net.pokeranalytics.android.ui.activity.components.BaseActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.extensions.ChipGroupExtension
import net.pokeranalytics.android.ui.extensions.px
import net.pokeranalytics.android.ui.extensions.showAlertDialog
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomFieldRow
@ -107,7 +103,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
private var _binding: FragmentCustomViewBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentCustomViewBinding.inflate(inflater, container, false)
return binding.root
@ -227,16 +223,16 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
when (customField.sortCondition) {
CustomField.Sort.DEFAULT.uniqueIdentifier -> binding.sortDefault.isChecked = true
CustomField.Sort.ASCENDING.uniqueIdentifier -> binding.sortAscending.isChecked = true
CustomField.Sort.DESCENDING.uniqueIdentifier -> sortDescending.isChecked = true
CustomField.Sort.DESCENDING.uniqueIdentifier -> binding.sortDescending.isChecked = true
}
addItem.setOnClickListener {
binding.addItem.setOnClickListener {
val customFieldEntry = customField.addEntry()
rowRepresentableAdapter.notifyDataSetChanged()
onRowSelected(-1, customFieldEntry)
}
sortChoices.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() {
binding.sortChoices.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() {
override fun onCheckedChanged(group: ChipGroup, checkedId: Int) {
super.onCheckedChanged(group, checkedId)
@ -252,7 +248,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
}
if (customField.sortCondition == CustomField.Sort.DEFAULT.uniqueIdentifier) {
itemTouchHelper.attachToRecyclerView(recyclerView)
itemTouchHelper.attachToRecyclerView(binding.recyclerView)
} else {
itemTouchHelper.attachToRecyclerView(null)
}
@ -275,6 +271,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
* Update UI
*/
private fun updateUI() {
val bottomBar = binding.bottomBar
if (customField.type == CustomField.Type.LIST.uniqueIdentifier) {
bottomBar.animate().translationY(0f.px)
.setInterpolator(FastOutSlowInInterpolator())

@ -10,7 +10,7 @@ import androidx.core.view.isVisible
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.extensions.setTextFormat
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.util.TextFormat
interface LegendContent
@ -84,15 +84,15 @@ open class LegendView : FrameLayout {
/**
* Set the stat data to the view
*/
open fun prepareWithStat(stat: Stat, counter: Int? = null, style: GraphFragment.Style) {
open fun prepareWithStat(stat: Stat, counter: Int? = null, style: Graph.Style) {
when (style) {
GraphFragment.Style.BAR -> {
Graph.Style.BAR -> {
this.stat1Name.text = stat.localizedTitle(context)
this.stat2Name.text = context.getString(R.string.sessions)
this.counter.isVisible = false
}
GraphFragment.Style.LINE -> {
Graph.Style.LINE -> {
if (stat.graphSignificantIndividualValue) {
this.stat1Name.text = stat.localizedTitle(context)
this.stat2Name.text = stat.cumulativeLabelResId(context)

@ -6,7 +6,7 @@ import android.view.View
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.extensions.setTextFormat
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.util.TextFormat
data class MultilineLegendValues(
@ -29,7 +29,7 @@ class MultiLineLegendView(context: Context) : LegendView(context = context) {
return R.layout.layout_legend_color
}
override fun prepareWithStat(stat: Stat, counter: Int?, style: GraphFragment.Style) {
override fun prepareWithStat(stat: Stat, counter: Int?, style: Graph.Style) {
}
override fun setItemData(content: LegendContent, color: Int?) {

@ -7,7 +7,7 @@ import com.github.mikephil.charting.data.LineDataSet
import net.pokeranalytics.android.calculus.AxisFormatting
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
open class GraphViewModel : ViewModel(), GraphDataProvider {
@ -19,7 +19,7 @@ open class GraphViewModel : ViewModel(), GraphDataProvider {
/***
* The graph style
*/
var style: GraphFragment.Style? = null
var style: Graph.Style? = null
/***
* The displayed stat

Loading…
Cancel
Save