feat: genre graph

This commit is contained in:
rebelonion 2024-03-03 01:25:45 -06:00
parent 93fa29829f
commit 945d5886ea

View file

@ -22,11 +22,14 @@ import com.github.aachartmodel.aainfographics.aachartcreator.AADataElement
import com.github.aachartmodel.aainfographics.aachartcreator.AAOptions import com.github.aachartmodel.aainfographics.aachartcreator.AAOptions
import com.github.aachartmodel.aainfographics.aachartcreator.AASeriesElement import com.github.aachartmodel.aainfographics.aachartcreator.AASeriesElement
import com.github.aachartmodel.aainfographics.aachartcreator.aa_toAAOptions import com.github.aachartmodel.aainfographics.aachartcreator.aa_toAAOptions
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAArea
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAChart
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.AAPlotOptions
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAStyle import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAStyle
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAYAxis
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
@ -163,6 +166,46 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
binding.releaseYearChartView.visibility = View.GONE binding.releaseYearChartView.visibility = View.GONE
} }
val startYearChartModel = getStartYearChartModel(anime)
if (startYearChartModel != null) {
binding.startYearChartView.visibility = View.VISIBLE
val aaOptions = buildOptions(startYearChartModel, false, """
function () {
return 'Year: ' +
this.x +
'<br/> ' +
' ${getTypeName()} ' +
this.y
}
""".trimIndent()
)
binding.startYearChartView.aa_drawChartWithChartOptions(aaOptions)
} else {
binding.startYearChartView.visibility = View.GONE
}
val genreChartModel = getGenreChartModel(anime)
if (genreChartModel.first != null) {
binding.genreChartView.visibility = View.VISIBLE
val aaOptions = buildOptions(genreChartModel.first!!, true, """
function () {
return 'Genre: ' +
this.x +
'<br/> ' +
' ${getTypeName()} ' +
this.y
}
""".trimIndent()
)
val min = genreChartModel.second.first
val max = genreChartModel.second.second
aaOptions.yAxis = AAYAxis().min(min).max(max).tickInterval(if (max > 100) 20 else 10)
binding.genreChartView.aa_drawChartWithChartOptions(aaOptions)
} else {
binding.genreChartView.visibility = View.GONE
}
} }
private fun buildOptions( private fun buildOptions(
@ -302,9 +345,9 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
private fun getLengthChartModel(anime: Boolean): AAChartModel? { private fun getLengthChartModel(anime: Boolean): AAChartModel? {
val names: List<String> = if (anime) { val names: List<String> = if (anime) {
stats?.data?.user?.statistics?.anime?.lengths?.mapNotNull { it.length } ?: emptyList() stats?.data?.user?.statistics?.anime?.lengths?.map { it.length?: "unknown" } ?: emptyList()
} else { } else {
stats?.data?.user?.statistics?.manga?.lengths?.mapNotNull { it.length } ?: emptyList() stats?.data?.user?.statistics?.manga?.lengths?.map { it.length?: "unknown" } ?: emptyList()
} }
val values: List<Number> = if (anime) { val values: List<Number> = if (anime) {
when (statType) { when (statType) {
@ -351,7 +394,6 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.releaseYears?.map { it.meanScore } StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.releaseYears?.map { it.meanScore }
} ?: emptyList() } ?: emptyList()
} }
//clear nulls from names
if (names.isEmpty() || values.isEmpty()) if (names.isEmpty() || values.isEmpty())
return null return null
val palette = generateColorPalette(primaryColor, names.size) val palette = generateColorPalette(primaryColor, names.size)
@ -368,6 +410,79 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
.colorsTheme(hexColorsArray) .colorsTheme(hexColorsArray)
} }
private fun getStartYearChartModel(anime: Boolean): AAChartModel? {
val names: List<Number> = if (anime) {
stats?.data?.user?.statistics?.anime?.startYears?.map { it.startYear } ?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.startYears?.map { it.startYear } ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.startYears?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.anime?.startYears?.map { it.minutesWatched / 60 }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.startYears?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.startYears?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.manga?.startYears?.map { it.chaptersRead }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.startYears?.map { it.meanScore }
} ?: emptyList()
}
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.Bar)
.title("Start Year")
.subtitle(getTypeName())
.zoomType(AAChartZoomType.XY)
.dataLabelsEnabled(false)
.yAxisTitle(getTypeName())
.stacking(AAChartStackingType.Normal)
.series(getElementsSimple(names, values))
.colorsTheme(hexColorsArray)
}
private fun getGenreChartModel(anime: Boolean): Pair<AAChartModel?, Pair<Int, Int>> {
val names: List<String> = if (anime) {
stats?.data?.user?.statistics?.anime?.genres?.map { it.genre } ?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.genres?.map { it.genre } ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.genres?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.anime?.genres?.map { it.minutesWatched / 60 }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.genres?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.genres?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.manga?.genres?.map { it.chaptersRead }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.genres?.map { it.meanScore }
} ?: emptyList()
}
if (names.isEmpty() || values.isEmpty())
return Pair(null, Pair(0, 0))
val palette = generateColorPalette(primaryColor, names.size)
val hexColorsArray: Array<Any> = palette.map { String.format("#%06X", 0xFFFFFF and it) }.toTypedArray()
return Pair(AAChartModel()
.chartType(AAChartType.Area)
.title("Genre")
.subtitle(getTypeName())
.zoomType(AAChartZoomType.XY)
.dataLabelsEnabled(false)
.legendEnabled(false)
.yAxisTitle(getTypeName())
.stacking(AAChartStackingType.Normal)
.series(getElementsSimple(names, values))
.colorsTheme(hexColorsArray)
.categories(names.toTypedArray()),
Pair(values.minOf { it.toInt() }, values.maxOf { it.toInt() }))
}
enum class StatType { enum class StatType {
COUNT, TIME, MEAN_SCORE COUNT, TIME, MEAN_SCORE
} }
@ -409,6 +524,7 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
.backgroundColor(AAColor.rgbaColor(255, 255, 255, 0.0f)) .backgroundColor(AAColor.rgbaColor(255, 255, 255, 0.0f))
) )
} else { } else {
element.x(i)
element.name(names[i] as String) element.name(names[i] as String)
} }
statDataElements.add(element) statDataElements.add(element)
@ -420,17 +536,16 @@ class StatsFragment(private val user: Query.UserProfile, private val activity: P
} }
private fun getElementsSimple( private fun getElementsSimple(
names: List<Number>, names: List<Any>,
statData: List<Number> statData: List<Any>
): Array<Any> { ): Array<Any> {
val statValues = mutableListOf<Array<Number>>() val statValues = mutableListOf<Array<Any>>()
for (i in statData.indices) { for (i in statData.indices) {
statValues.add(arrayOf(names[i], statData[i], statData[i])) statValues.add(arrayOf(names[i], statData[i], statData[i]))
} }
val sorted = statValues.sortedBy { it[0] as Int }
return arrayOf( return arrayOf(
AASeriesElement().name("Score") AASeriesElement().name("Score")
.data(sorted.toTypedArray()) .data(statValues.toTypedArray())
.dataLabels(AADataLabels() .dataLabels(AADataLabels()
.enabled(false) .enabled(false)
) )