Compute sum and ratio in stats

This commit is contained in:
fgerber 2024-04-09 16:51:00 +02:00
parent 6aef6dabb2
commit fd0ae64c0d
7 changed files with 103 additions and 50 deletions

View File

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

View File

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

View File

@ -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<StatsListAdapter.StatsViewHolder>() {
private var locMode: String = WORLD
private lateinit var ctx: Context
private var countMode: Boolean = true
private var initialSum: Int = 0
private val wwwTotal: List<GeoLoc> = World.WWW.children.toList()
private val countryTotal: List<GeoLoc> = World.WWW.children.flatMap { it.children }
private val stateTotal: List<GeoLoc> = 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<Int, Groups.Group>
private var countMode: Boolean = true
private var locMode: String = "World"
private lateinit var wwwCount: List<GeoLoc>
private lateinit var countryCount: List<GeoLoc>
private lateinit var stateCount: List<GeoLoc>
fun bind(entry: Pair<Int, Groups.Group>) {
fun bind(entry: Pair<Int, Groups.Group>): 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
}
}
}

View File

@ -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<Int, Group>) {
return grps.keys.toList().indexOf(key)
}
fun forEach(action: (Map.Entry<Int, Group>) -> Unit) {
grps.forEach { action(it) }
}
class EmptyGroup : Group(0, "")
@Serializable
@ -76,7 +75,7 @@ class Groups(val id: Int, private val grps: HashMap<Int, Group>) {
val key: Int,
val name: String,
@Serializable(with = Theme.ColorDrawableSerializer::class) val color: ColorDrawable = ColorDrawable(
Color.TRANSPARENT
Color.GRAY
)
)

View File

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

View File

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

View File

@ -36,4 +36,5 @@
<string name="cancel">Cancel</string>
<string name="ok">Ok</string>
<string name="total">Total</string>
<string name="uncategorized">Uncategorized</string>
</resources>