This guide shows you how to add personalized user statistics and general taco trivia to the TacoTracker app.
- Understanding Fact Types
- User Stats Facts (Personalized)
- General Trivia Facts
- Where to Display Facts
- Examples & Ideas
Personalized statistics based on the user's data:
- "You've eaten 247 tacos!"
- "Your most common protein is chicken"
- "You eat tacos most often on Tuesdays"
Calculated dynamically from meal data.
Universal taco knowledge:
- "The word 'taco' appeared in English in 1905"
- "Tacos al pastor were inspired by Lebanese shawarma"
- "Americans eat 4.5 billion tacos per year"
Static list that rotates randomly.
User stats are calculated on-demand from meal data. They live in your ViewModels and repositories.
User stats are typically calculated in:
- StatsScreen.kt - Main statistics display
- HomeScreen.kt - Quick stats on dashboard
- SaveSuccessScreen.kt - Post-meal summary
Let's add a stat showing which month the user ate the most spicy tacos.
File: app/src/main/java/com/dinorawrger/tacotracker/ui/StatsScreen.kt
Add a helper function to calculate the stat:
/**
* Find the month with the most spicy tacos.
*
* @return Pair of (month name, spicy taco count) or null if no spicy tacos
*/
private fun findSpiciestMonth(meals: List<MealWithTacos>): Pair<String, Int>? {
val spicyKeywords = listOf("jalapeรฑo", "habanero", "serrano", "chipotle",
"hot sauce", "spicy", "picante", "ghost pepper")
val calendar = Calendar.getInstance()
val monthFormat = SimpleDateFormat("MMMM", Locale.getDefault()) // "January", "February", etc.
// Group meals by month, count spicy tacos
val tacosByMonth = meals
.groupBy { meal ->
calendar.timeInMillis = meal.meal.eatenAtEpochMillis
monthFormat.format(calendar.time)
}
.mapValues { (_, mealsInMonth) ->
mealsInMonth
.flatMap { it.tacos }
.count { taco ->
taco.ingredients.any { ingredient ->
spicyKeywords.any { keyword ->
ingredient.name.contains(keyword, ignoreCase = true)
}
}
}
}
.filter { it.value > 0 } // Only months with spicy tacos
// Find month with most spicy tacos
return tacosByMonth.maxByOrNull { it.value }?.toPair()
}In your StatsScreen composable:
@Composable
fun StatsScreen(meals: List<MealWithTacos>) {
// ... existing stats ...
// Calculate spiciest month
val spiciestMonth = remember(meals) { findSpiciestMonth(meals) }
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.padding(16.dp)
) {
// ... existing UI ...
// Spiciest month card
spiciestMonth?.let { (month, count) ->
StatCard(
title = "๐ถ๏ธ Spiciest Month",
value = month,
subtitle = "$count spicy tacos"
)
}
}
}
/**
* Reusable stat card component.
*/
@Composable
private fun StatCard(
title: String,
value: String,
subtitle: String? = null
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(
text = title,
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = value,
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.padding(vertical = 4.dp)
)
subtitle?.let {
Text(
text = it,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
}Done! The stat now appears on your stats screen. ๐
// Most common location
private fun findTopLocation(meals: List<MealWithTacos>): String? {
return meals
.groupBy { it.meal.location.trim().lowercase() }
.filter { it.key.isNotBlank() }
.maxByOrNull { it.value.size }
?.key
?.replaceFirstChar { it.titlecase() }
}// Percentage of meals that are breakfast
private fun calculateBreakfastPercentage(meals: List<MealWithTacos>): Int {
if (meals.isEmpty()) return 0
val breakfastCount = meals.count {
it.meal.mealType.equals("Breakfast", ignoreCase = true)
}
return (breakfastCount * 100 / meals.size)
}// Average tacos per meal
private fun calculateAverageTacosPerMeal(meals: List<MealWithTacos>): Double {
if (meals.isEmpty()) return 0.0
val totalTacos = meals.sumOf { it.meal.totalTacos }
return totalTacos.toDouble() / meals.size
}// Most active day of week
private fun findMostActiveDayOfWeek(meals: List<MealWithTacos>): String? {
val calendar = Calendar.getInstance()
val dayFormat = SimpleDateFormat("EEEE", Locale.getDefault()) // "Monday", "Tuesday", etc.
return meals
.groupBy { meal ->
calendar.timeInMillis = meal.meal.eatenAtEpochMillis
dayFormat.format(calendar.time)
}
.maxByOrNull { it.value.size }
?.key
}// Longest streak of consecutive days with tacos
private fun calculateLongestStreak(meals: List<MealWithTacos>): Int {
if (meals.isEmpty()) return 0
val calendar = Calendar.getInstance()
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
// Get unique dates (ignore time)
val dates = meals
.map { meal ->
calendar.timeInMillis = meal.meal.eatenAtEpochMillis
dateFormat.format(calendar.time)
}
.distinct()
.sorted()
var maxStreak = 1
var currentStreak = 1
for (i in 1 until dates.size) {
val prevDate = dateFormat.parse(dates[i - 1])!!
val currDate = dateFormat.parse(dates[i])!!
val daysBetween = ((currDate.time - prevDate.time) / (1000 * 60 * 60 * 24)).toInt()
if (daysBetween == 1) {
currentStreak++
maxStreak = maxOf(maxStreak, currentStreak)
} else {
currentStreak = 1
}
}
return maxStreak
}// Total tacos in the last 30 days
private fun calculateLast30Days(meals: List<MealWithTacos>): Int {
val thirtyDaysAgo = System.currentTimeMillis() - (30L * 24 * 60 * 60 * 1000)
return meals
.filter { it.meal.eatenAtEpochMillis >= thirtyDaysAgo }
.sumOf { it.meal.totalTacos }
}General trivia facts are static strings that rotate randomly. Perfect for loading screens, home screen widgets, or "did you know?" sections.
File: app/src/main/java/com/dinorawrger/tacotracker/data/TacoFacts.kt (CREATE NEW)
package com.dinorawrger.tacotracker.data
/**
* Collection of taco trivia, history, and culinary facts.
*/
object TacoFacts {
/**
* Categories of facts for organization.
*/
enum class Category {
HISTORY,
CULINARY,
CULTURAL,
STATISTICS,
FUN
}
/**
* Single fact with optional category.
*/
data class Fact(
val text: String,
val category: Category = Category.FUN
)
/**
* All available facts.
* Add new facts to this list!
*/
private val allFacts = listOf(
// HISTORY
Fact(
"The word 'taco' first appeared in English text in 1905.",
Category.HISTORY
),
Fact(
"Tacos have been eaten in Mexico for thousands of years, dating back to the Aztecs.",
Category.HISTORY
),
Fact(
"The first known mention of tacos in Mexico City dates to the 18th century.",
Category.HISTORY
),
Fact(
"Tacos al pastor were inspired by Lebanese immigrants who brought shawarma to Mexico.",
Category.HISTORY
),
// CULINARY
Fact(
"Authentic Mexican tacos are typically served on small corn tortillas, not flour.",
Category.CULINARY
),
Fact(
"The perfect taco should be eaten in 2-3 bites - any more and it's too big!",
Category.CULINARY
),
Fact(
"Traditional tacos are topped with cilantro and onions, not lettuce and cheese.",
Category.CULINARY
),
Fact(
"Corn tortillas are naturally gluten-free and have been made the same way for millennia.",
Category.CULINARY
),
Fact(
"The spiciest pepper commonly used in tacos is the habanero, which can reach 350,000 Scoville units.",
Category.CULINARY
),
// CULTURAL
Fact(
"In Mexico, tacos are often eaten for breakfast, not just lunch or dinner.",
Category.CULTURAL
),
Fact(
"Taco Tuesday became popular in the US in the 1980s as a restaurant promotion.",
Category.CULTURAL
),
Fact(
"Mexico City has over 20,000 taco stands - more than any other city in the world.",
Category.CULTURAL
),
Fact(
"October 4th is National Taco Day in the United States.",
Category.CULTURAL
),
// STATISTICS
Fact(
"Americans eat approximately 4.5 billion tacos per year.",
Category.STATISTICS
),
Fact(
"The average American eats about 14 tacos per year.",
Category.STATISTICS
),
Fact(
"Carne asada is the most popular taco filling in the United States.",
Category.STATISTICS
),
// FUN
Fact(
"The world's largest taco weighed 1,654 pounds and was made in Mexicali in 2003.",
Category.FUN
),
Fact(
"A taco emoji (๐ฎ) was added to Unicode in 2015 after a popular petition.",
Category.FUN
),
Fact(
"The taco shell as we know it was invented in the 1940s in California.",
Category.FUN
),
Fact(
"There are over 40 different types of tacos recognized in Mexican cuisine.",
Category.FUN
),
Fact(
"The word 'taco' literally means 'plug' or 'wad' in Spanish.",
Category.FUN
),
Fact(
"Fish tacos originated in Baja California and became popular worldwide in the 1980s.",
Category.FUN
)
)
/**
* Get a random fact.
*/
fun getRandom(): Fact = allFacts.random()
/**
* Get a random fact from a specific category.
*/
fun getRandomByCategory(category: Category): Fact? {
return allFacts.filter { it.category == category }.randomOrNull()
}
/**
* Get all facts.
*/
fun getAll(): List<Fact> = allFacts
/**
* Get all facts from a category.
*/
fun getAllByCategory(category: Category): List<Fact> {
return allFacts.filter { it.category == category }
}
}Example: Add to Home Screen
File: app/src/main/java/com/dinorawrger/tacotracker/ui/HomeScreen.kt
@Composable
fun HomeScreen(
meals: List<MealWithTacos>,
onNewEntry: () -> Unit,
onViewHistory: () -> Unit,
onViewStats: () -> Unit,
onViewFavorites: () -> Unit
) {
// Get a random fact (changes each time screen recomposes)
val randomFact = remember { TacoFacts.getRandom() }
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.padding(16.dp)
) {
// ... existing home screen content ...
// Fact of the day card
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.secondaryContainer
)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "๐ก",
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.padding(end = 8.dp)
)
Text(
text = "Did You Know?",
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSecondaryContainer
)
}
Spacer(modifier = Modifier.height(8.dp))
Text(
text = randomFact.text,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSecondaryContainer
)
}
}
}
}Example: Rotating Facts
For a fact that changes periodically (like daily):
@Composable
fun DailyFact() {
// Get fact based on day of year (changes daily)
val dayOfYear = remember {
Calendar.getInstance().get(Calendar.DAY_OF_YEAR)
}
val dailyFact = remember(dayOfYear) {
val allFacts = TacoFacts.getAll()
allFacts[dayOfYear % allFacts.size]
}
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.tertiaryContainer
)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "๐ฎ Taco Fact of the Day",
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onTertiaryContainer
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = dailyFact.text,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onTertiaryContainer
)
}
}
}Just add new Fact() objects to the allFacts list in TacoFacts.kt:
private val allFacts = listOf(
// ... existing facts ...
Fact(
"Your new amazing taco fact here!",
Category.FUN
),
Fact(
"Another interesting fact about tacos!",
Category.HISTORY
)
)// Quick stats + daily fact
Column {
QuickStatsCard(meals)
DailyFact()
}// Show fact while data loads
if (isLoading) {
LoadingWithFact()
}
@Composable
fun LoadingWithFact() {
val fact = remember { TacoFacts.getRandom() }
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalAlignment = Arrangement.Center
) {
CircularProgressIndicator()
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Did you know?",
style = MaterialTheme.typography.titleMedium
)
Text(
text = fact.text,
style = MaterialTheme.typography.bodyMedium,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 32.dp, vertical = 8.dp)
)
}
}// Show fact after logging a meal
SaveSuccessScreen(
summary = summary,
fact = TacoFacts.getRandom(),
// ... other params
)// End of stats with fun fact
Column {
// ... all your stats ...
Divider(modifier = Modifier.padding(vertical = 16.dp))
Text(
text = "๐ Taco Trivia",
style = MaterialTheme.typography.titleMedium
)
TacoFacts.getAll().take(3).forEach { fact ->
TriviaItem(fact)
}
}// "About" section with random fact
Section("About Taco Tracker") {
Text("Version 1.0")
Spacer(modifier = Modifier.height(8.dp))
Text(
text = TacoFacts.getRandom().text,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}- "You've tried 15 different locations"
- "You've eaten tacos on 42 different days"
- "You've consumed 1,247 tacos total"
- "That's enough tortillas to cover a basketball court!"
- "You've eaten more tacos this month than last month"
- "Your taco consumption is 23% above average"
- "You eat tacos most often at 12:30 PM"
- "Your favorite day for tacos is Tuesday"
- "You prefer corn tortillas 73% of the time"
- "Your most common ingredient is cilantro"
- "Your taco consumption is trending up this month!"
- "You've had a 7-day taco streak!"
- "You've eaten tacos 3 weeks in a row"
- "If you stacked all your tacos, they'd be X feet tall"
- "You've eaten enough tacos to feed X people"
- "Your tacos contain enough calories to run X miles"
- Origins of different taco styles
- Evolution of tortilla-making
- How tacos came to different countries
- Famous taco moments in history
- Proper taco assembly techniques
- Regional variations
- Traditional vs modern ingredients
- Cooking methods and equipment
- Taco traditions and celebrations
- Regional Mexican taco culture
- Taco etiquette and customs
- Famous taco destinations
- Consumption data
- Popular ingredients
- Market trends
- Restaurant statistics
- World records
- Celebrity taco stories
- Taco memes and internet culture
- Unusual taco varieties
- Build and run app
- Navigate to where you added facts
- Verify formatting looks good
- Check that facts rotate correctly
// Add temporary logging to test user stats
println("๐ Spiciest Month: ${findSpiciestMonth(meals)}")
println("๐ Top Location: ${findTopLocation(meals)}")- Empty meal list (no data yet)
- Single meal
- Unusual data (all same location, etc.)
@Composable
fun FactCard(
emoji: String,
title: String,
fact: String,
backgroundColor: Color = MaterialTheme.colorScheme.secondaryContainer
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
colors = CardDefaults.cardColors(containerColor = backgroundColor)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = emoji,
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.padding(end = 12.dp)
)
Column {
Text(
text = title,
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSecondaryContainer
)
Text(
text = fact,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSecondaryContainer
)
}
}
}
}// Large number with label
"${totalTacos.format()} tacos eaten"
// Percentage
"${percentage}% of meals"
// Top item
"#1: $topLocation ($count visits)"
// Date range
"Since ${startDate.format()}"You now have both personalized user stats and general taco trivia in your app!
Mix and match these throughout your app to create delightful moments of discovery! ๐ฎโจ