parent
5b1bb4a631
commit
89526e63ba
@ -0,0 +1,84 @@ |
||||
package net.pokeranalytics.android.calcul |
||||
|
||||
import android.content.Context |
||||
import com.github.mikephil.charting.data.* |
||||
import net.pokeranalytics.android.R |
||||
import net.pokeranalytics.android.calculus.ComputedResults |
||||
import net.pokeranalytics.android.calculus.Point |
||||
import net.pokeranalytics.android.calculus.Stat |
||||
import net.pokeranalytics.android.ui.graph.DataSetFactory |
||||
import kotlin.math.abs |
||||
|
||||
|
||||
// MPAndroidChart |
||||
|
||||
fun ComputedResults.defaultStatEntries(stat: Stat, context: Context): DataSet<out Entry> { |
||||
return when (stat) { |
||||
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.HOURLY_DURATION -> this.barEntries(stat, context = context) |
||||
Stat.STANDARD_DEVIATION -> this.distributionEntries(stat, context) |
||||
else -> this.singleLineEntries(stat, context) |
||||
} |
||||
} |
||||
|
||||
fun ComputedResults.singleLineEntries(stat: Stat, context: Context): LineDataSet { |
||||
val entries = mutableListOf<Entry>() |
||||
this.evolutionValues[stat]?.let { points -> |
||||
points.forEachIndexed { index, p -> |
||||
entries.add(Entry(index.toFloat(), p.y.toFloat(), p.data)) |
||||
} |
||||
} |
||||
return DataSetFactory.lineDataSetInstance(entries, this.group.query.getName(context), context) |
||||
} |
||||
|
||||
fun ComputedResults.durationEntries(stat: Stat, context: Context): LineDataSet { |
||||
val entries = mutableListOf<Entry>() |
||||
this.evolutionValues[stat]?.let { points -> |
||||
points.forEach { p -> |
||||
entries.add(Entry(p.x.toFloat(), p.y.toFloat(), p.data)) |
||||
} |
||||
} |
||||
return DataSetFactory.lineDataSetInstance(entries, stat.name, context) |
||||
} |
||||
|
||||
private fun ComputedResults.barEntries(stat: Stat, context: Context): BarDataSet { |
||||
|
||||
val entries = mutableListOf<BarEntry>() |
||||
this.evolutionValues[stat]?.let { points -> |
||||
points.forEach { p -> |
||||
entries.add(BarEntry(p.x.toFloat(), p.y.toFloat(), p.data)) |
||||
} |
||||
} |
||||
return DataSetFactory.barDataSetInstance(entries, stat.name, context) |
||||
} |
||||
|
||||
private fun ComputedResults.distributionEntries(stat: Stat, context: Context): BarDataSet { |
||||
|
||||
val colors = mutableListOf<Int>() |
||||
val entries = mutableListOf<BarEntry>() |
||||
this.evolutionValues[stat]?.let { points -> |
||||
|
||||
val negative = mutableListOf<Point>() |
||||
val positive = mutableListOf<Point>() |
||||
|
||||
points.sortByDescending { it.y } |
||||
points.forEach { |
||||
if (it.y < 0) { |
||||
negative.add(it) |
||||
} else { |
||||
positive.add(it) |
||||
} |
||||
} |
||||
|
||||
negative.forEachIndexed { index, p -> |
||||
entries.add(BarEntry(index.toFloat(), abs(p.y.toFloat()), p.data)) |
||||
colors.add(context.getColor(R.color.red)) |
||||
} |
||||
positive.forEachIndexed { index, p -> |
||||
val x = negative.size + index.toFloat() |
||||
entries.add(BarEntry(x, p.y.toFloat(), p.data)) |
||||
colors.add(context.getColor(R.color.green)) |
||||
} |
||||
|
||||
} |
||||
return DataSetFactory.barDataSetInstance(entries, stat.name, context, colors) |
||||
} |
||||
@ -0,0 +1,64 @@ |
||||
package net.pokeranalytics.android.calcul |
||||
|
||||
import android.content.Context |
||||
import com.github.mikephil.charting.data.BarDataSet |
||||
import com.github.mikephil.charting.data.BarEntry |
||||
import com.github.mikephil.charting.data.Entry |
||||
import com.github.mikephil.charting.data.LineDataSet |
||||
import net.pokeranalytics.android.calculus.Report |
||||
import net.pokeranalytics.android.calculus.Stat |
||||
import net.pokeranalytics.android.ui.graph.DataSetFactory |
||||
import net.pokeranalytics.android.util.ColorUtils |
||||
|
||||
|
||||
/** |
||||
* Returns the list of entries corresponding to the provided [stat] |
||||
* One value will be returned by result |
||||
*/ |
||||
fun Report.lineEntries(stat: Stat? = null, context: Context): LineDataSet { |
||||
val entries = mutableListOf<Entry>() |
||||
val statToUse = stat ?: this.options.stats.firstOrNull() |
||||
val statName = statToUse?.name ?: "" |
||||
|
||||
statToUse?.let { |
||||
this.results.forEachIndexed { index, results -> |
||||
results.computedStat(it)?.progressValue?.let { progressValue -> |
||||
entries.add(Entry(index.toFloat(), progressValue.toFloat(), results)) |
||||
} |
||||
} |
||||
} |
||||
|
||||
return DataSetFactory.lineDataSetInstance(entries, statName, context) |
||||
} |
||||
|
||||
fun Report.barEntries(stat: Stat? = null, context: Context): BarDataSet { |
||||
val entries = mutableListOf<BarEntry>() |
||||
val statToUse = stat ?: options.stats.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) |
||||
} |
||||
} |
||||
} |
||||
|
||||
val label = statToUse?.name ?: "" |
||||
return DataSetFactory.barDataSetInstance(entries, label, context) |
||||
} |
||||
|
||||
fun Report.multiLineEntries(context: Context): List<LineDataSet> { |
||||
val dataSets = mutableListOf<LineDataSet>() |
||||
|
||||
options.stats.forEach { stat -> |
||||
this.results.forEachIndexed { index, result -> |
||||
val ds = result.singleLineEntries(stat, context) |
||||
ds.color = ColorUtils.almostRandomColor(index, context) |
||||
dataSets.add(ds) |
||||
} |
||||
} |
||||
|
||||
return dataSets |
||||
} |
||||
@ -0,0 +1,90 @@ |
||||
package net.pokeranalytics.android.calculus |
||||
|
||||
import io.realm.Realm |
||||
import io.realm.RealmResults |
||||
import net.pokeranalytics.android.model.filter.Query |
||||
import net.pokeranalytics.android.model.filter.QueryCondition |
||||
import net.pokeranalytics.android.model.realm.ComputableResult |
||||
import net.pokeranalytics.android.model.realm.Filter |
||||
import net.pokeranalytics.android.model.realm.SessionSet |
||||
|
||||
|
||||
/** |
||||
* A sessionGroup of computable items identified by a name |
||||
*/ |
||||
class ComputableGroup(var query: Query, var stats: List<Stat>? = null) { |
||||
|
||||
/** |
||||
* A subgroup used to compute stat variation |
||||
*/ |
||||
var comparedGroup: ComputableGroup? = null |
||||
|
||||
/** |
||||
* The computed statIds of the comparable sessionGroup |
||||
*/ |
||||
var comparedComputedResults: ComputedResults? = null |
||||
|
||||
/** |
||||
* A list of _conditions to get |
||||
*/ |
||||
val conditions: List<QueryCondition> |
||||
get() { |
||||
return this.query.conditions |
||||
} |
||||
|
||||
/** |
||||
* The list of endedSessions to compute |
||||
*/ |
||||
private var _computables: RealmResults<ComputableResult>? = null |
||||
|
||||
/** |
||||
* Retrieves the computables on the relative [realm] filtered with the provided [conditions] |
||||
*/ |
||||
fun computables(realm: Realm, sorted: Boolean = false): RealmResults<ComputableResult> { |
||||
|
||||
// if computables exists and is valid (previous realm not closed) |
||||
this._computables?.let { |
||||
if (it.isValid) { |
||||
return it |
||||
} |
||||
} |
||||
|
||||
val sortedField = if (sorted) "session.startDate" else null |
||||
val computables = Filter.queryOn<ComputableResult>(realm, this.query, sortedField) |
||||
this._computables = computables |
||||
return computables |
||||
} |
||||
|
||||
/** |
||||
* The list of sets to compute |
||||
*/ |
||||
private var _sessionSets: RealmResults<SessionSet>? = null |
||||
|
||||
/** |
||||
* Retrieves the session sets on the relative [realm] filtered with the provided [conditions] |
||||
*/ |
||||
fun sessionSets(realm: Realm, sorted: Boolean = false): RealmResults<SessionSet> { |
||||
// if computables exists and is valid (previous realm not closed) |
||||
this._sessionSets?.let { |
||||
if (it.isValid) { |
||||
return it |
||||
} |
||||
} |
||||
|
||||
val sortedField = if (sorted) SessionSet.Field.START_DATE.identifier else null |
||||
val sets = Filter.queryOn<SessionSet>(realm, this.query, sortedField) |
||||
this._sessionSets = sets |
||||
return sets |
||||
} |
||||
|
||||
fun cleanup() { |
||||
this._computables = null |
||||
this._sessionSets = null |
||||
} |
||||
|
||||
val isEmpty: Boolean |
||||
get() { |
||||
return this._computables?.isEmpty() ?: true |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue