feat: length / year graph

This commit is contained in:
rebelonion 2024-03-03 00:01:56 -06:00
parent a9f8d223e9
commit 93fa29829f

View file

@ -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)