feat: length / year graph
This commit is contained in:
parent
a9f8d223e9
commit
93fa29829f
1 changed files with 123 additions and 13 deletions
|
@ -25,13 +25,13 @@ import com.github.aachartmodel.aainfographics.aachartcreator.aa_toAAOptions
|
||||||
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AADataLabels
|
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AADataLabels
|
||||||
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAItemStyle
|
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAItemStyle
|
||||||
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAMarker
|
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAMarker
|
||||||
|
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAPlotOptions
|
||||||
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAStyle
|
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAStyle
|
||||||
import com.github.aachartmodel.aainfographics.aatools.AAColor
|
import com.github.aachartmodel.aainfographics.aatools.AAColor
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
class StatsFragment(private val user: Query.UserProfile, private val activity: ProfileActivity) :
|
class StatsFragment(private val user: Query.UserProfile, private val activity: ProfileActivity) :
|
||||||
Fragment() {
|
Fragment() {
|
||||||
|
@ -39,6 +39,7 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
|
||||||
private var stats: Query.StatisticsResponse? = null
|
private var stats: Query.StatisticsResponse? = null
|
||||||
private var type: MediaType = MediaType.ANIME
|
private var type: MediaType = MediaType.ANIME
|
||||||
private var statType: StatType = StatType.COUNT
|
private var statType: StatType = StatType.COUNT
|
||||||
|
private var primaryColor: Int = 0
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
@ -52,6 +53,14 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
val typedValue = TypedValue()
|
||||||
|
activity.theme.resolveAttribute(
|
||||||
|
com.google.android.material.R.attr.colorPrimary,
|
||||||
|
typedValue,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
primaryColor = typedValue.data
|
||||||
|
|
||||||
binding.sourceType.setAdapter(
|
binding.sourceType.setAdapter(
|
||||||
ArrayAdapter(
|
ArrayAdapter(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
|
@ -127,6 +136,33 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
|
||||||
binding.scoreChartView.visibility = View.GONE
|
binding.scoreChartView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val lengthChartModel = getLengthChartModel(anime)
|
||||||
|
if (lengthChartModel != null) {
|
||||||
|
binding.lengthChartView.visibility = View.VISIBLE
|
||||||
|
val aaOptions = buildOptions(lengthChartModel)
|
||||||
|
binding.lengthChartView.aa_drawChartWithChartOptions(aaOptions)
|
||||||
|
} else {
|
||||||
|
binding.lengthChartView.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
val releaseYearChartModel = getReleaseYearChartModel(anime)
|
||||||
|
if (releaseYearChartModel != null) {
|
||||||
|
binding.releaseYearChartView.visibility = View.VISIBLE
|
||||||
|
val aaOptions = buildOptions(releaseYearChartModel, false, """
|
||||||
|
function () {
|
||||||
|
return 'Year: ' +
|
||||||
|
this.x +
|
||||||
|
'<br/> ' +
|
||||||
|
' ${getTypeName()} ' +
|
||||||
|
this.y
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
binding.releaseYearChartView.aa_drawChartWithChartOptions(aaOptions)
|
||||||
|
} else {
|
||||||
|
binding.releaseYearChartView.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildOptions(
|
private fun buildOptions(
|
||||||
|
@ -188,7 +224,7 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
|
||||||
}
|
}
|
||||||
if (names.isEmpty() || values.isEmpty())
|
if (names.isEmpty() || values.isEmpty())
|
||||||
return null
|
return null
|
||||||
val primaryColor = getBaseColor(activity)
|
val primaryColor = primaryColor
|
||||||
val palette = generateColorPalette(primaryColor, names.size)
|
val palette = generateColorPalette(primaryColor, names.size)
|
||||||
return AAChartModel()
|
return AAChartModel()
|
||||||
.chartType(AAChartType.Pie)
|
.chartType(AAChartType.Pie)
|
||||||
|
@ -220,7 +256,6 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
|
||||||
}
|
}
|
||||||
if (names.isEmpty() || values.isEmpty())
|
if (names.isEmpty() || values.isEmpty())
|
||||||
return null
|
return null
|
||||||
val primaryColor = getBaseColor(activity)
|
|
||||||
val palette = generateColorPalette(primaryColor, names.size)
|
val palette = generateColorPalette(primaryColor, names.size)
|
||||||
return AAChartModel()
|
return AAChartModel()
|
||||||
.chartType(AAChartType.Pyramid)
|
.chartType(AAChartType.Pyramid)
|
||||||
|
@ -252,7 +287,6 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
|
||||||
}
|
}
|
||||||
if (names.isEmpty() || values.isEmpty())
|
if (names.isEmpty() || values.isEmpty())
|
||||||
return null
|
return null
|
||||||
val primaryColor = getBaseColor(activity)
|
|
||||||
val palette = generateColorPalette(primaryColor, names.size)
|
val palette = generateColorPalette(primaryColor, names.size)
|
||||||
return AAChartModel()
|
return AAChartModel()
|
||||||
.chartType(AAChartType.Column)
|
.chartType(AAChartType.Column)
|
||||||
|
@ -266,6 +300,74 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
|
||||||
.series(getElements(names, values, palette))
|
.series(getElements(names, values, palette))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getLengthChartModel(anime: Boolean): AAChartModel? {
|
||||||
|
val names: List<String> = if (anime) {
|
||||||
|
stats?.data?.user?.statistics?.anime?.lengths?.mapNotNull { it.length } ?: emptyList()
|
||||||
|
} else {
|
||||||
|
stats?.data?.user?.statistics?.manga?.lengths?.mapNotNull { it.length } ?: emptyList()
|
||||||
|
}
|
||||||
|
val values: List<Number> = if (anime) {
|
||||||
|
when (statType) {
|
||||||
|
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.lengths?.map { it.count }
|
||||||
|
StatType.TIME -> stats?.data?.user?.statistics?.anime?.lengths?.map { it.minutesWatched / 60 }
|
||||||
|
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.lengths?.map { it.meanScore }
|
||||||
|
} ?: emptyList()
|
||||||
|
} else {
|
||||||
|
when (statType) {
|
||||||
|
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.lengths?.map { it.count }
|
||||||
|
StatType.TIME -> stats?.data?.user?.statistics?.manga?.lengths?.map { it.chaptersRead }
|
||||||
|
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.lengths?.map { it.meanScore }
|
||||||
|
} ?: emptyList()
|
||||||
|
}
|
||||||
|
//clear nulls from names
|
||||||
|
if (names.isEmpty() || values.isEmpty())
|
||||||
|
return null
|
||||||
|
val palette = generateColorPalette(primaryColor, names.size)
|
||||||
|
return AAChartModel()
|
||||||
|
.chartType(AAChartType.Pie)
|
||||||
|
.title("Length")
|
||||||
|
.subtitle(getTypeName())
|
||||||
|
.zoomType(AAChartZoomType.XY)
|
||||||
|
.dataLabelsEnabled(true)
|
||||||
|
.series(getElements(names, values, palette))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getReleaseYearChartModel(anime: Boolean): AAChartModel? {
|
||||||
|
val names: List<Number> = if (anime) {
|
||||||
|
stats?.data?.user?.statistics?.anime?.releaseYears?.map { it.releaseYear } ?: emptyList()
|
||||||
|
} else {
|
||||||
|
stats?.data?.user?.statistics?.manga?.releaseYears?.map { it.releaseYear } ?: emptyList()
|
||||||
|
}
|
||||||
|
val values: List<Number> = if (anime) {
|
||||||
|
when (statType) {
|
||||||
|
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.releaseYears?.map { it.count }
|
||||||
|
StatType.TIME -> stats?.data?.user?.statistics?.anime?.releaseYears?.map { it.minutesWatched / 60 }
|
||||||
|
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.releaseYears?.map { it.meanScore }
|
||||||
|
} ?: emptyList()
|
||||||
|
} else {
|
||||||
|
when (statType) {
|
||||||
|
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.releaseYears?.map { it.count }
|
||||||
|
StatType.TIME -> stats?.data?.user?.statistics?.manga?.releaseYears?.map { it.chaptersRead }
|
||||||
|
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.releaseYears?.map { it.meanScore }
|
||||||
|
} ?: emptyList()
|
||||||
|
}
|
||||||
|
//clear nulls from names
|
||||||
|
if (names.isEmpty() || values.isEmpty())
|
||||||
|
return null
|
||||||
|
val palette = generateColorPalette(primaryColor, names.size)
|
||||||
|
val hexColorsArray: Array<Any> = palette.map { String.format("#%06X", 0xFFFFFF and it) }.toTypedArray()
|
||||||
|
return AAChartModel()
|
||||||
|
.chartType(AAChartType.Bubble)
|
||||||
|
.title("Release Year")
|
||||||
|
.subtitle(getTypeName())
|
||||||
|
.zoomType(AAChartZoomType.XY)
|
||||||
|
.dataLabelsEnabled(false)
|
||||||
|
.yAxisTitle(getTypeName())
|
||||||
|
.stacking(AAChartStackingType.Normal)
|
||||||
|
.series(getElementsSimple(names, values))
|
||||||
|
.colorsTheme(hexColorsArray)
|
||||||
|
}
|
||||||
|
|
||||||
enum class StatType {
|
enum class StatType {
|
||||||
COUNT, TIME, MEAN_SCORE
|
COUNT, TIME, MEAN_SCORE
|
||||||
}
|
}
|
||||||
|
@ -312,19 +414,28 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
|
||||||
statDataElements.add(element)
|
statDataElements.add(element)
|
||||||
}
|
}
|
||||||
return arrayOf(
|
return arrayOf(
|
||||||
AASeriesElement().name("Score")
|
AASeriesElement().name("Score").color(primaryColor)
|
||||||
.data(statDataElements.toTypedArray())
|
.data(statDataElements.toTypedArray())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getBaseColor(context: Context): Int {
|
private fun getElementsSimple(
|
||||||
val typedValue = TypedValue()
|
names: List<Number>,
|
||||||
context.theme.resolveAttribute(
|
statData: List<Number>
|
||||||
com.google.android.material.R.attr.colorPrimary,
|
): Array<Any> {
|
||||||
typedValue,
|
val statValues = mutableListOf<Array<Number>>()
|
||||||
true
|
for (i in statData.indices) {
|
||||||
|
statValues.add(arrayOf(names[i], statData[i], statData[i]))
|
||||||
|
}
|
||||||
|
val sorted = statValues.sortedBy { it[0] as Int }
|
||||||
|
return arrayOf(
|
||||||
|
AASeriesElement().name("Score")
|
||||||
|
.data(sorted.toTypedArray())
|
||||||
|
.dataLabels(AADataLabels()
|
||||||
|
.enabled(false)
|
||||||
|
)
|
||||||
|
.colorByPoint(true)
|
||||||
)
|
)
|
||||||
return typedValue.data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setColors(aaOptions: AAOptions) {
|
private fun setColors(aaOptions: AAOptions) {
|
||||||
|
@ -352,7 +463,6 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
|
||||||
0.9f
|
0.9f
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val primaryColor = getBaseColor(activity)
|
|
||||||
|
|
||||||
|
|
||||||
aaOptions.chart?.backgroundColor(backgroundStyle.color)
|
aaOptions.chart?.backgroundColor(backgroundStyle.color)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue