feat: compare user stats

This commit is contained in:
rebelonion 2024-03-04 22:55:29 -06:00
parent d181dcf837
commit 5279b0cd65
13 changed files with 745 additions and 472 deletions

View file

@ -15,19 +15,19 @@ import ani.dantotsu.databinding.FragmentStatisticsBinding
import ani.dantotsu.profile.ChartBuilder.Companion.ChartType
import ani.dantotsu.profile.ChartBuilder.Companion.StatType
import ani.dantotsu.profile.ChartBuilder.Companion.MediaType
import ani.dantotsu.profile.ChartBuilder.Companion.ChartPacket
import com.github.aachartmodel.aainfographics.aachartcreator.AAChartType
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAYAxis
import com.xwray.groupie.GroupieAdapter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Locale
class StatsFragment() :
class StatsFragment :
Fragment() {
private lateinit var binding: FragmentStatisticsBinding
private var adapter: GroupieAdapter = GroupieAdapter()
private var stats: Query.StatisticsResponse? = null
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
@ -52,25 +52,55 @@ class StatsFragment() :
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) }
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) }
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 = Anilist.query.getUserStatistics(user.id)
stats.clear()
stats.add(Anilist.query.getUserStatistics(user.id)?.data?.user)
withContext(Dispatchers.Main) {
binding.filterContainer.visibility = View.VISIBLE
binding.sourceType.setOnItemClickListener { _, _, i, _ ->
@ -116,99 +146,114 @@ class StatsFragment() :
}
private fun loadFormatChart(anime: Boolean) {
val names: List<String> = if (anime) {
stats?.data?.user?.statistics?.anime?.formats?.map { it.format } ?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.formats?.map { it.format } ?: emptyList()
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))
}
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.formats?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.anime?.formats?.map { it.minutesWatched / 60 }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.formats?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.formats?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.manga?.formats?.map { it.chaptersRead }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.formats?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
if (chartPackets.isNotEmpty()) {
val formatChart = ChartBuilder.buildChart(
activity,
ChartType.OneDimensional,
AAChartType.Pie,
statType,
type,
names,
values
chartPackets,
)
adapter.add(ChartItem("Format", formatChart, activity))
}
}
private fun loadStatusChart(anime: Boolean) {
val names: List<String> = if (anime) {
stats?.data?.user?.statistics?.anime?.statuses?.map { it.status } ?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.statuses?.map { it.status } ?: emptyList()
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))
}
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.statuses?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.anime?.statuses?.map { it.minutesWatched / 60 }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.statuses?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.statuses?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.manga?.statuses?.map { it.chaptersRead }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.statuses?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
if (chartPackets.isNotEmpty()) {
val statusChart = ChartBuilder.buildChart(
activity,
ChartType.OneDimensional,
AAChartType.Funnel,
statType,
type,
names,
values
chartPackets
)
adapter.add(ChartItem("Status", statusChart, activity))
}
}
private fun loadScoreChart(anime: Boolean) {
val names: List<Int> = if (anime) {
stats?.data?.user?.statistics?.anime?.scores?.map { it.score } ?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.scores?.map { it.score } ?: emptyList()
val chartPackets = mutableListOf<ChartPacket>()
stats.forEach { stat ->
val names: List<Int> = if (anime) {
stat?.statistics?.anime?.scores?.map { it.score } ?: emptyList()
} else {
stat?.statistics?.manga?.scores?.map { it.score } ?: 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))
}
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.scores?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.anime?.scores?.map { it.minutesWatched / 60 }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.scores?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.scores?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.manga?.scores?.map { it.chaptersRead }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.scores?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
if (chartPackets.isNotEmpty()) {
val scoreChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Column,
statType,
type,
names,
values,
chartPackets,
xAxisName = "Score",
)
adapter.add(ChartItem("Score", scoreChart, activity))
@ -216,35 +261,40 @@ class StatsFragment() :
}
private fun loadLengthChart(anime: Boolean) {
val names: List<String> = if (anime) {
stats?.data?.user?.statistics?.anime?.lengths?.map { it.length ?: "unknown" }
?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.lengths?.map { it.length ?: "unknown" }
?: emptyList()
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))
}
}
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()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
if (chartPackets.isNotEmpty()) {
val lengthChart = ChartBuilder.buildChart(
activity,
ChartType.OneDimensional,
AAChartType.Pyramid,
statType,
type,
names,
values,
chartPackets,
xAxisName = "Length",
)
adapter.add(ChartItem("Length", lengthChart, activity))
@ -252,35 +302,40 @@ class StatsFragment() :
}
private fun loadReleaseYearChart(anime: Boolean) {
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 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))
}
}
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()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
if (chartPackets.isNotEmpty()) {
val releaseYearChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Bubble,
statType,
type,
names,
values,
chartPackets,
xAxisName = "Year",
)
adapter.add(ChartItem("Release Year", releaseYearChart, activity))
@ -288,33 +343,38 @@ class StatsFragment() :
}
private fun loadStartYearChart(anime: Boolean) {
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 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))
}
}
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.isNotEmpty() || values.isNotEmpty()) {
if (chartPackets.isNotEmpty()) {
val startYearChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Bar,
statType,
type,
names,
values,
chartPackets,
xAxisName = "Year",
)
adapter.add(ChartItem("Start Year", startYearChart, activity))
@ -322,112 +382,160 @@ class StatsFragment() :
}
private fun loadGenreChart(anime: Boolean) {
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 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))
}
}
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.isNotEmpty() || values.isNotEmpty()) {
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,
names,
values,
chartPackets,
xAxisName = "Genre",
polar = true,
categories = names
passedCategories = chartPackets[0].names as List<String>,
)
adapter.add(ChartItem("Genre", genreChart, activity))
}
}
private fun loadTagChart(anime: Boolean) {
val names: List<String> = if (anime) {
stats?.data?.user?.statistics?.anime?.tags?.map { it.tag.name } ?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.tags?.map { it.tag.name } ?: emptyList()
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))
}
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.tags?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.anime?.tags?.map { it.minutesWatched / 60 }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.tags?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.tags?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.manga?.tags?.map { it.chaptersRead }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.tags?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
val min = values.minOf { it.toInt() }
val max = values.maxOf { it.toInt() }
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,
names,
values,
chartPackets,
xAxisName = "Tag",
polar = false,
categories = names,
passedCategories = chartPackets[0].names as List<String>,
scrollPos = 0.0f
)
tagChart.yAxis = AAYAxis().min(min).max(max).tickInterval(if (max > 100) 20 else 10)
adapter.add(ChartItem("Tag", tagChart, activity))
}
}
private fun loadCountryChart(anime: Boolean) {
val names: List<String> = if (anime) {
stats?.data?.user?.statistics?.anime?.countries?.map { it.country } ?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.countries?.map { it.country } ?: emptyList()
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))
}
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.countries?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.anime?.countries?.map { it.minutesWatched / 60 }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.countries?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.countries?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.manga?.countries?.map { it.chaptersRead }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.countries?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
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,
names,
values,
chartPackets,
xAxisName = "Country",
polar = false,
categories = names,
passedCategories = chartPackets[0].names as List<String>,
scrollPos = null
)
adapter.add(ChartItem("Country", countryChart, activity))
@ -435,116 +543,167 @@ class StatsFragment() :
}
private fun loadVoiceActorsChart(anime: Boolean) {
val names: List<String> = if (anime) {
stats?.data?.user?.statistics?.anime?.voiceActors?.map { it.voiceActor.name.full?:"unknown" } ?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.voiceActors?.map { it.voiceActor.name.full?:"unknown" } ?: emptyList()
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))
}
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.voiceActors?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.anime?.voiceActors?.map { it.minutesWatched / 60 }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.voiceActors?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.voiceActors?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.manga?.voiceActors?.map { it.chaptersRead }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.voiceActors?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
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,
names,
values,
chartPackets,
xAxisName = "Voice Actor",
polar = false,
categories = names,
passedCategories = chartPackets[0].names as List<String>,
scrollPos = 0.0f
)
adapter.add(ChartItem("Voice Actor", voiceActorsChart, activity))
}
}
private fun loadStaffChart(anime: Boolean) {
val names: List<String> = if (anime) {
stats?.data?.user?.statistics?.anime?.staff?.map { it.staff.name.full?:"unknown" } ?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.staff?.map { it.staff.name.full?:"unknown" } ?: emptyList()
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.staff?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.anime?.staff?.map { it.minutesWatched / 60 }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.staff?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.staff?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.manga?.staff?.map { it.chaptersRead }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.staff?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
val staffChart = ChartBuilder.buildChart(
activity,
ChartType.TwoDimensional,
AAChartType.Line,
statType,
type,
names,
values,
xAxisName = "Staff",
polar = false,
categories = names,
scrollPos = 0.0f
)
adapter.add(ChartItem("Staff", staffChart, activity))
}
}
private fun loadStudioChart(anime: Boolean) {
val names: List<String> = if (anime) {
stats?.data?.user?.statistics?.anime?.studios?.map { it.studio.name } ?: emptyList()
} else {
stats?.data?.user?.statistics?.manga?.studios?.map { it.studio.name } ?: emptyList()
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))
}
}
val values: List<Number> = if (anime) {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.anime?.studios?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.anime?.studios?.map { it.minutesWatched / 60 }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.anime?.studios?.map { it.meanScore }
} ?: emptyList()
} else {
when (statType) {
StatType.COUNT -> stats?.data?.user?.statistics?.manga?.studios?.map { it.count }
StatType.TIME -> stats?.data?.user?.statistics?.manga?.studios?.map { it.chaptersRead }
StatType.MEAN_SCORE -> stats?.data?.user?.statistics?.manga?.studios?.map { it.meanScore }
} ?: emptyList()
}
if (names.isNotEmpty() || values.isNotEmpty()) {
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,
names.take(15),
values.take(15),
chartPackets,
xAxisName = "Studio",
polar = true,
categories = names,
passedCategories = chartPackets[0].names as List<String>,
scrollPos = null
)
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))
}
}
companion object {
fun newInstance(user: Query.UserProfile): StatsFragment {
val args = Bundle().apply {