Dantotsu/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt
2024-03-05 00:25:40 -06:00

747 lines
No EOL
32 KiB
Kotlin

package ani.dantotsu.profile
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.api.Query
import ani.dantotsu.databinding.FragmentStatisticsBinding
import ani.dantotsu.profile.ChartBuilder.Companion.ChartPacket
import ani.dantotsu.profile.ChartBuilder.Companion.ChartType
import ani.dantotsu.profile.ChartBuilder.Companion.MediaType
import ani.dantotsu.profile.ChartBuilder.Companion.StatType
import com.github.aachartmodel.aainfographics.aachartcreator.AAChartType
import com.xwray.groupie.GroupieAdapter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Locale
class StatsFragment :
Fragment() {
private lateinit var binding: FragmentStatisticsBinding
private var adapter: GroupieAdapter = GroupieAdapter()
private var stats: MutableList<Query.StatisticsUser?> = mutableListOf()
private var type: MediaType = MediaType.ANIME
private var statType: StatType = StatType.COUNT
private lateinit var user: Query.UserProfile
private lateinit var activity: ProfileActivity
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentStatisticsBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity = requireActivity() as ProfileActivity
user = arguments?.getSerializable("user") as Query.UserProfile
binding.statisticList.adapter = adapter
binding.statisticList.setHasFixedSize(true)
binding.statisticList.isNestedScrollingEnabled = false
binding.statisticList.layoutManager = LinearLayoutManager(requireContext())
binding.statisticProgressBar.visibility = View.VISIBLE
binding.compare.visibility = if (user.id == Anilist.userid) View.GONE else View.VISIBLE
binding.sourceType.setAdapter(
ArrayAdapter(
requireContext(),
R.layout.item_dropdown,
MediaType.entries.map { it.name.uppercase(Locale.ROOT).replace("_", " ") }
)
)
binding.sourceFilter.setAdapter(
ArrayAdapter(
requireContext(),
R.layout.item_dropdown,
StatType.entries.map { it.name.uppercase(Locale.ROOT).replace("_", " ") }
)
)
binding.compare.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
activity.lifecycleScope.launch {
if (Anilist.userid != null) {
withContext(Dispatchers.Main) {
binding.statisticProgressBar.visibility = View.VISIBLE
binding.statisticList.visibility = View.GONE
}
val userStats =
Anilist.query.getUserStatistics(Anilist.userid!!)?.data?.user
if (userStats != null) {
stats.add(userStats)
withContext(Dispatchers.Main) {
loadStats(type == MediaType.ANIME)
binding.statisticProgressBar.visibility = View.GONE
binding.statisticList.visibility = View.VISIBLE
}
}
}
}
} else {
stats.removeAll(
stats.filter { it?.id == Anilist.userid }
)
loadStats(type == MediaType.ANIME)
}
}
binding.filterContainer.visibility = View.GONE
activity.lifecycleScope.launch {
stats.clear()
stats.add(Anilist.query.getUserStatistics(user.id)?.data?.user)
withContext(Dispatchers.Main) {
binding.filterContainer.visibility = View.VISIBLE
binding.sourceType.setOnItemClickListener { _, _, i, _ ->
type = MediaType.entries.toTypedArray()[i]
loadStats(type == MediaType.ANIME)
}
binding.sourceFilter.setOnItemClickListener { _, _, i, _ ->
statType = StatType.entries.toTypedArray()[i]
loadStats(type == MediaType.ANIME)
}
loadStats(type == MediaType.ANIME)
binding.statisticProgressBar.visibility = View.GONE
}
}
}
override fun onResume() {
super.onResume()
if (this::binding.isInitialized) {
binding.root.requestLayout()
}
loadStats(type == MediaType.ANIME)
}
private fun loadStats(anime: Boolean) {
binding.statisticProgressBar.visibility = View.VISIBLE
binding.statisticList.visibility = View.GONE
adapter.clear()
loadFormatChart(anime)
loadScoreChart(anime)
loadStatusChart(anime)
loadReleaseYearChart(anime)
loadStartYearChart(anime)
loadLengthChart(anime)
loadGenreChart(anime)
loadTagChart(anime)
loadCountryChart(anime)
loadVoiceActorsChart(anime)
loadStudioChart(anime)
loadStaffChart(anime)
binding.statisticProgressBar.visibility = View.GONE
binding.statisticList.visibility = View.VISIBLE
}
private fun loadFormatChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<String> = if (anime) {
stat?.statistics?.anime?.formats?.map { it.format } ?: emptyList()
} else {
stat?.statistics?.manga?.formats?.map { it.format } ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.formats?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.formats?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.formats?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.formats?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.formats?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.formats?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() && values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val formatChart = ChartBuilder.buildChart(
activity,
ChartType.OneDimensional,
AAChartType.Pie,
statType,
type,
chartPackets,
xAxisName = "Format",
)
adapter.add(ChartItem("Format", formatChart, activity))
}
}
private fun loadStatusChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<String> = if (anime) {
stat?.statistics?.anime?.statuses?.map { it.status } ?: emptyList()
} else {
stat?.statistics?.manga?.statuses?.map { it.status } ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.statuses?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.statuses?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.statuses?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.statuses?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.statuses?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.statuses?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() && values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val statusChart = ChartBuilder.buildChart(
activity,
ChartType.OneDimensional,
AAChartType.Funnel,
statType,
type,
chartPackets,
xAxisName = "Status",
)
adapter.add(ChartItem("Status", statusChart, activity))
}
}
private fun loadScoreChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<Int> = if (anime) {
stat?.statistics?.anime?.scores?.map {
convertScore(
it.score,
stat.mediaListOptions.scoreFormat
)
} ?: emptyList()
} else {
stat?.statistics?.manga?.scores?.map {
convertScore(
it.score,
stat.mediaListOptions.scoreFormat
)
} ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.scores?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.scores?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.scores?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.scores?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.scores?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.scores?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val scoreChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Column,
statType,
type,
chartPackets,
xAxisName = "Score",
)
adapter.add(ChartItem("Score", scoreChart, activity))
}
}
private fun loadLengthChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<String> = if (anime) {
stat?.statistics?.anime?.lengths?.map { it.length ?: "unknown" }
?: emptyList()
} else {
stat?.statistics?.manga?.lengths?.map { it.length ?: "unknown" }
?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.lengths?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.lengths?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.lengths?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.lengths?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.lengths?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.lengths?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val lengthChart = ChartBuilder.buildChart(
activity,
ChartType.OneDimensional,
AAChartType.Pyramid,
statType,
type,
chartPackets,
xAxisName = "Length",
)
adapter.add(ChartItem("Length", lengthChart, activity))
}
}
private fun loadReleaseYearChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<Number> = if (anime) {
stat?.statistics?.anime?.releaseYears?.map { it.releaseYear }
?: emptyList()
} else {
stat?.statistics?.manga?.releaseYears?.map { it.releaseYear }
?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.releaseYears?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.releaseYears?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.releaseYears?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.releaseYears?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.releaseYears?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.releaseYears?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val releaseYearChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Bubble,
statType,
type,
chartPackets,
xAxisName = "Year",
scrollPos = 0.0f
)
adapter.add(ChartItem("Release Year", releaseYearChart, activity))
}
}
private fun loadStartYearChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<Number> = if (anime) {
stat?.statistics?.anime?.startYears?.map { it.startYear } ?: emptyList()
} else {
stat?.statistics?.manga?.startYears?.map { it.startYear } ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.startYears?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.startYears?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.startYears?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.startYears?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.startYears?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.startYears?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val startYearChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Bar,
statType,
type,
chartPackets,
xAxisName = "Year",
)
adapter.add(ChartItem("Start Year", startYearChart, activity))
}
}
private fun loadGenreChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<String> = if (anime) {
stat?.statistics?.anime?.genres?.map { it.genre } ?: emptyList()
} else {
stat?.statistics?.manga?.genres?.map { it.genre } ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.genres?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.genres?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.genres?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.genres?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.genres?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.genres?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val referenceNames = chartPackets.first().names.map { it.toString() }
val standardizedPackets = chartPackets.map { packet ->
val valuesMap = packet.names.map { it.toString() }.zip(packet.statData).toMap()
val standardizedValues = referenceNames.map { name ->
valuesMap[name] ?: 0
}
// Create a new ChartPacket with standardized names and values.
ChartPacket(packet.username, referenceNames, standardizedValues)
}.toMutableList()
chartPackets.clear()
chartPackets.addAll(standardizedPackets)
val genreChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Areaspline,
statType,
type,
chartPackets,
xAxisName = "Genre",
polar = true,
passedCategories = chartPackets[0].names as List<String>,
normalize = true
)
adapter.add(ChartItem("Genre", genreChart, activity))
}
}
private fun loadTagChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<String> = if (anime) {
stat?.statistics?.anime?.tags?.map { it.tag.name } ?: emptyList()
} else {
stat?.statistics?.manga?.tags?.map { it.tag.name } ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.tags?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.tags?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.tags?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.tags?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.tags?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.tags?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val referenceNames = chartPackets.first().names.map { it.toString() }
val standardizedPackets = chartPackets.map { packet ->
val valuesMap = packet.names.map { it.toString() }.zip(packet.statData).toMap()
val standardizedValues = referenceNames.map { name ->
valuesMap[name] ?: 0
}
// Create a new ChartPacket with standardized names and values.
ChartPacket(packet.username, referenceNames, standardizedValues)
}.toMutableList()
chartPackets.clear()
chartPackets.addAll(standardizedPackets)
val tagChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Areaspline,
statType,
type,
chartPackets,
xAxisName = "Tag",
polar = false,
passedCategories = chartPackets[0].names as List<String>,
scrollPos = 0.0f
)
adapter.add(ChartItem("Tag", tagChart, activity))
}
}
private fun loadCountryChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<String> = if (anime) {
stat?.statistics?.anime?.countries?.map { it.country } ?: emptyList()
} else {
stat?.statistics?.manga?.countries?.map { it.country } ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.countries?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.countries?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.countries?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.countries?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.countries?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.countries?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val referenceNames = chartPackets.first().names.map { it.toString() }
val standardizedPackets = chartPackets.map { packet ->
val valuesMap = packet.names.map { it.toString() }.zip(packet.statData).toMap()
val standardizedValues = referenceNames.map { name ->
valuesMap[name] ?: 0
}
// Create a new ChartPacket with standardized names and values.
ChartPacket(packet.username, referenceNames, standardizedValues)
}.toMutableList()
chartPackets.clear()
chartPackets.addAll(standardizedPackets)
val countryChart = ChartBuilder.buildChart(
activity,
ChartType.OneDimensional,
AAChartType.Pie,
statType,
type,
chartPackets,
xAxisName = "Country",
polar = false,
passedCategories = chartPackets[0].names as List<String>,
scrollPos = null
)
adapter.add(ChartItem("Country", countryChart, activity))
}
}
private fun loadVoiceActorsChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<String> = if (anime) {
stat?.statistics?.anime?.voiceActors?.map { it.voiceActor.name.full ?: "unknown" }
?: emptyList()
} else {
stat?.statistics?.manga?.voiceActors?.map { it.voiceActor.name.full ?: "unknown" }
?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.voiceActors?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.voiceActors?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.voiceActors?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.voiceActors?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.voiceActors?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.voiceActors?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val referenceNames = chartPackets.first().names.map { it.toString() }
val standardizedPackets = chartPackets.map { packet ->
val valuesMap = packet.names.map { it.toString() }.zip(packet.statData).toMap()
val standardizedValues = referenceNames.map { name ->
valuesMap[name] ?: 0
}
// Create a new ChartPacket with standardized names and values.
ChartPacket(packet.username, referenceNames, standardizedValues)
}.toMutableList()
chartPackets.clear()
chartPackets.addAll(standardizedPackets)
val voiceActorsChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Column,
statType,
type,
chartPackets,
xAxisName = "Voice Actor",
polar = false,
passedCategories = chartPackets[0].names as List<String>,
scrollPos = 0.0f
)
adapter.add(ChartItem("Voice Actor", voiceActorsChart, activity))
}
}
private fun loadStudioChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<String> = if (anime) {
stat?.statistics?.anime?.studios?.map { it.studio.name } ?: emptyList()
} else {
stat?.statistics?.manga?.studios?.map { it.studio.name } ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.studios?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.studios?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.studios?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.studios?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.studios?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.studios?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val referenceNames = chartPackets.first().names.map { it.toString() }
val standardizedPackets = chartPackets.map { packet ->
val valuesMap = packet.names.map { it.toString() }.zip(packet.statData).toMap()
val standardizedValues = referenceNames.map { name ->
valuesMap[name] ?: 0
}
// Create a new ChartPacket with standardized names and values.
ChartPacket(packet.username, referenceNames, standardizedValues)
}.toMutableList()
chartPackets.clear()
chartPackets.addAll(standardizedPackets)
val studioChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Spline,
statType,
type,
chartPackets,
xAxisName = "Studio",
polar = true,
passedCategories = chartPackets[0].names as List<String>,
scrollPos = null,
normalize = true
)
adapter.add(ChartItem("Studio", studioChart, activity))
}
}
private fun loadStaffChart(anime: Boolean) {
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<String> = if (anime) {
stat?.statistics?.anime?.staff?.map { it.staff.name.full ?: "unknown" }
?: emptyList()
} else {
stat?.statistics?.manga?.staff?.map { it.staff.name.full ?: "unknown" }
?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stat?.statistics?.anime?.staff?.map { it.count }
StatType.TIME -> stat?.statistics?.anime?.staff?.map { it.minutesWatched / 60 }
StatType.AVG_SCORE -> stat?.statistics?.anime?.staff?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stat?.statistics?.manga?.staff?.map { it.count }
StatType.TIME -> stat?.statistics?.manga?.staff?.map { it.chaptersRead }
StatType.AVG_SCORE -> stat?.statistics?.manga?.staff?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
}
}
if (chartPackets.isNotEmpty()) {
val referenceNames = chartPackets.first().names.map { it.toString() }
val standardizedPackets = chartPackets.map { packet ->
val valuesMap = packet.names.map { it.toString() }.zip(packet.statData).toMap()
val standardizedValues = referenceNames.map { name ->
valuesMap[name] ?: 0
}
// Create a new ChartPacket with standardized names and values.
ChartPacket(packet.username, referenceNames, standardizedValues)
}.toMutableList()
chartPackets.clear()
chartPackets.addAll(standardizedPackets)
val staffChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Line,
statType,
type,
chartPackets,
xAxisName = "Staff",
polar = false,
passedCategories = chartPackets[0].names as List<String>,
scrollPos = 0.0f
)
adapter.add(ChartItem("Staff", staffChart, activity))
}
}
private fun convertScore(score: Int, type: String?): Int {
return when (type) {
"POINT_100" -> score
"POINT_10_DECIMAL" -> score
"POINT_10" -> score * 10
"POINT_5" -> score * 20
"POINT_3" -> score * 33
else -> score
}
}
companion object {
fun newInstance(user: Query.UserProfile): StatsFragment {
val args = Bundle().apply {
putSerializable("user", user)
}
return StatsFragment().apply {
arguments = args
}
}
}
}