From fd0ae64c0d42ad7dea6bf4aa8920ae0fddcf0f3b Mon Sep 17 00:00:00 2001 From: fgerber Date: Tue, 9 Apr 2024 16:51:00 +0200 Subject: [PATCH] Compute sum and ratio in stats --- .../net/helcel/beans/activity/StatActivity.kt | 18 ++-- .../activity/adapter/GeolocListAdapter.kt | 9 +- .../activity/adapter/StatsListAdapter.kt | 100 +++++++++++++----- .../java/net/helcel/beans/helper/Groups.kt | 9 +- .../java/net/helcel/beans/helper/Settings.kt | 14 +++ app/src/main/res/layout/activity_stat.xml | 2 +- app/src/main/res/values/en.xml | 1 + 7 files changed, 103 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/net/helcel/beans/activity/StatActivity.kt b/app/src/main/java/net/helcel/beans/activity/StatActivity.kt index 827b3a2..58b23e6 100644 --- a/app/src/main/java/net/helcel/beans/activity/StatActivity.kt +++ b/app/src/main/java/net/helcel/beans/activity/StatActivity.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment +import androidx.preference.PreferenceManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.adapter.FragmentStateAdapter @@ -12,28 +13,31 @@ import com.google.android.material.tabs.TabLayoutMediator import net.helcel.beans.R import net.helcel.beans.activity.adapter.StatsListAdapter import net.helcel.beans.databinding.ActivityStatBinding +import net.helcel.beans.helper.Settings import net.helcel.beans.helper.Theme.createActionBar -private val MODE_LIST = listOf("World", "Country", "Region") +const val WORLD = "Continents" +const val COUNTRY = "Countries" +const val REGION = "Regions" +private val MODE_LIST = listOf(WORLD, COUNTRY, REGION) class StatActivity : AppCompatActivity() { - private lateinit var _binding: ActivityStatBinding - private var activeMode: String = "World" + private var activeMode: String = WORLD override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) _binding = ActivityStatBinding.inflate(layoutInflater) setContentView(_binding.root) createActionBar(this, getString(R.string.action_stat)) - + _binding.stats.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) - val adapter = StatsListAdapter(_binding.stats) + val adapter = StatsListAdapter(_binding.stats, _binding.name) _binding.stats.adapter = adapter _binding.pager.adapter = object : FragmentStateAdapter(supportFragmentManager, lifecycle) { - override fun getItemCount(): Int = 3 + override fun getItemCount(): Int = if (Settings.isRegional(applicationContext)) 3 else 2 override fun createFragment(position: Int): Fragment = Fragment() } TabLayoutMediator(_binding.tab, _binding.pager) { tab, position -> @@ -46,7 +50,7 @@ class StatActivity : AppCompatActivity() { adapter.refreshMode(activeMode) } }) - adapter.refreshMode(activeMode) + //adapter.refreshMode(activeMode) } override fun onOptionsItemSelected(item: MenuItem): Boolean { diff --git a/app/src/main/java/net/helcel/beans/activity/adapter/GeolocListAdapter.kt b/app/src/main/java/net/helcel/beans/activity/adapter/GeolocListAdapter.kt index f2f1212..c17f3e5 100644 --- a/app/src/main/java/net/helcel/beans/activity/adapter/GeolocListAdapter.kt +++ b/app/src/main/java/net/helcel/beans/activity/adapter/GeolocListAdapter.kt @@ -153,14 +153,7 @@ class GeolocListAdapter( val numerator = geoLoc.children.map { Data.visits.getVisited(it) != NO_GROUP }.count { it } val denominator = geoLoc.children.size - _binding.count.text = when (Settings.getStatPref(ctx)) { - ctx.getString(R.string.percentages) -> ctx.getString( - R.string.percentage, - (100 * (numerator.toFloat() / denominator.toFloat())).toInt() - ) - - else -> ctx.getString(R.string.rate, numerator, denominator) - } + _binding.count.text = Settings.getStats(ctx, numerator, denominator) } private fun refresh(geoLoc: GeoLoc) { diff --git a/app/src/main/java/net/helcel/beans/activity/adapter/StatsListAdapter.kt b/app/src/main/java/net/helcel/beans/activity/adapter/StatsListAdapter.kt index 3687dd5..ec86001 100644 --- a/app/src/main/java/net/helcel/beans/activity/adapter/StatsListAdapter.kt +++ b/app/src/main/java/net/helcel/beans/activity/adapter/StatsListAdapter.kt @@ -1,40 +1,80 @@ package net.helcel.beans.activity.adapter +import android.annotation.SuppressLint +import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.textview.MaterialTextView +import net.helcel.beans.R +import net.helcel.beans.activity.COUNTRY +import net.helcel.beans.activity.REGION +import net.helcel.beans.activity.WORLD import net.helcel.beans.countries.GeoLoc import net.helcel.beans.countries.World import net.helcel.beans.databinding.ItemListGroupBinding +import net.helcel.beans.helper.AUTO_GROUP import net.helcel.beans.helper.Data import net.helcel.beans.helper.Groups +import net.helcel.beans.helper.Settings import net.helcel.beans.helper.Theme.getContrastColor -class StatsListAdapter(private val stats: RecyclerView) : +class StatsListAdapter(private val stats: RecyclerView, private val total: MaterialTextView) : RecyclerView.Adapter() { + private var locMode: String = WORLD + private lateinit var ctx: Context + private var countMode: Boolean = true + private var initialSum: Int = 0 + + private val wwwTotal: List = World.WWW.children.toList() + private val countryTotal: List = World.WWW.children.flatMap { it.children } + private val stateTotal: List = World.WWW.children.flatMap{ it.children.flatMap { itt -> itt.children } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StatsViewHolder { + ctx = parent.context val binding = - ItemListGroupBinding.inflate(LayoutInflater.from(parent.context), parent, false) - + ItemListGroupBinding.inflate(LayoutInflater.from(ctx), parent, false) return StatsViewHolder(binding) } override fun onBindViewHolder(holder: StatsViewHolder, pos: Int) { - holder.bind(Data.groups.getGroupFromPos(pos)) + initialSum += if (pos == itemCount - 1) { + holder.bind(Pair(AUTO_GROUP, Groups.Group(AUTO_GROUP, ctx.getString(R.string.uncategorized)))) + } else { + holder.bind(Data.groups.getGroupFromPos(pos)) + } + total.text = Settings.getStats(ctx, initialSum, getTotal()) } override fun getItemCount(): Int { - return Data.groups.size() + return Data.groups.size() + 1 + } + + private fun getTotal(): Int { + return if (countMode) { + when (locMode) { + WORLD -> wwwTotal.size + COUNTRY -> countryTotal.size + REGION -> stateTotal.size + else -> 0 + } + } else { + when (locMode) { + WORLD -> wwwTotal.sumOf { it.area } + COUNTRY -> countryTotal.sumOf { it.area } + REGION -> stateTotal.sumOf { it.area } + else -> 0 + } + } } fun refreshMode(mode: String) { - for (i in 0 until itemCount) { - val viewHolder = stats.findViewHolderForAdapterPosition(i) as? StatsViewHolder + val sum = (0 until itemCount).map { + val viewHolder = stats.findViewHolderForAdapterPosition(it) as? StatsViewHolder viewHolder?.refresh(mode) - } - + }.reduce { acc, i -> acc?.plus((i ?: 0)) } + total.text = Settings.getStats(ctx, sum, getTotal()) } inner class StatsViewHolder( @@ -42,13 +82,12 @@ class StatsListAdapter(private val stats: RecyclerView) : ) : RecyclerView.ViewHolder(_binding.root) { private lateinit var data: Pair - private var countMode: Boolean = true - private var locMode: String = "World" private lateinit var wwwCount: List private lateinit var countryCount: List private lateinit var stateCount: List - fun bind(entry: Pair) { + + fun bind(entry: Pair): Int { data = entry _binding.groupColor.text = entry.second.name @@ -60,10 +99,10 @@ class StatsListAdapter(private val stats: RecyclerView) : _binding.groupColor.setOnClickListener { countMode = !countMode - refresh(locMode) + refreshMode(locMode) } compute() - refresh(locMode) + return refresh(locMode) } private fun compute() { @@ -77,24 +116,27 @@ class StatsListAdapter(private val stats: RecyclerView) : .flatten().flatten() } - fun refresh(mode: String) { + fun refresh(mode: String): Int { locMode = mode - if (countMode) { - _binding.name.text = when (locMode) { - "World" -> wwwCount.size - "Country" -> countryCount.size - "Region" -> stateCount.size - else -> "?" - }.toString() + return if (countMode) { + val count = when (locMode) { + WORLD -> wwwCount.size + COUNTRY -> countryCount.size + REGION -> stateCount.size + else -> -1 + } + _binding.name.text = count.toString() + count } else { - _binding.name.text = when (locMode) { - "World" -> wwwCount.sumOf { it.area } - "Country" -> countryCount.sumOf { it.area } - "Region" -> stateCount.sumOf { it.area } - else -> "?" - }.toString() + val area = when (locMode) { + WORLD -> wwwCount.sumOf { it.area } + COUNTRY -> countryCount.sumOf { it.area } + REGION -> stateCount.sumOf { it.area } + else -> -1 + } + _binding.name.text = area.toString() + area } - } } diff --git a/app/src/main/java/net/helcel/beans/helper/Groups.kt b/app/src/main/java/net/helcel/beans/helper/Groups.kt index 850ebe9..60e88c6 100644 --- a/app/src/main/java/net/helcel/beans/helper/Groups.kt +++ b/app/src/main/java/net/helcel/beans/helper/Groups.kt @@ -2,11 +2,14 @@ package net.helcel.beans.helper import android.graphics.Color import android.graphics.drawable.ColorDrawable +import androidx.core.content.ContextCompat import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.Serializable import kotlinx.serialization.Serializer import kotlinx.serialization.json.Json +import net.helcel.beans.R import java.io.InputStream +import kotlin.coroutines.coroutineContext import kotlin.random.Random @@ -65,10 +68,6 @@ class Groups(val id: Int, private val grps: HashMap) { return grps.keys.toList().indexOf(key) } - fun forEach(action: (Map.Entry) -> Unit) { - grps.forEach { action(it) } - } - class EmptyGroup : Group(0, "") @Serializable @@ -76,7 +75,7 @@ class Groups(val id: Int, private val grps: HashMap) { val key: Int, val name: String, @Serializable(with = Theme.ColorDrawableSerializer::class) val color: ColorDrawable = ColorDrawable( - Color.TRANSPARENT + Color.GRAY ) ) diff --git a/app/src/main/java/net/helcel/beans/helper/Settings.kt b/app/src/main/java/net/helcel/beans/helper/Settings.kt index d5fe22c..3263a8f 100644 --- a/app/src/main/java/net/helcel/beans/helper/Settings.kt +++ b/app/src/main/java/net/helcel/beans/helper/Settings.kt @@ -44,4 +44,18 @@ object Settings { else -> false } } + + fun getStats(ctx: Context, numerator: Int?, denominator: Int?): String { + if (numerator == null || denominator == null || denominator == 0) { + return "" + } + return when (getStatPref(ctx)) { + ctx.getString(R.string.percentages) -> ctx.getString( + R.string.percentage, + (100 * (numerator.toFloat() / denominator.toFloat())).toInt() + ) + + else -> ctx.getString(R.string.rate, numerator, denominator) + } + } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_stat.xml b/app/src/main/res/layout/activity_stat.xml index aabba15..50f6f5a 100644 --- a/app/src/main/res/layout/activity_stat.xml +++ b/app/src/main/res/layout/activity_stat.xml @@ -49,7 +49,7 @@ android:gravity="start|center_vertical" android:paddingStart="20dp" android:paddingEnd="52dp" - android:text="TODO" + android:text="" android:textColor="?attr/colorOnPrimary" app:layout_constraintBottom_toBottomOf="@id/group_color" app:layout_constraintEnd_toEndOf="@id/group_color" diff --git a/app/src/main/res/values/en.xml b/app/src/main/res/values/en.xml index 005b675..1d446ad 100644 --- a/app/src/main/res/values/en.xml +++ b/app/src/main/res/values/en.xml @@ -36,4 +36,5 @@ Cancel Ok Total + Uncategorized \ No newline at end of file