Here's the complete guide for adding new medal tracks to your system!
This guide shows you how to add new progressive medal tracks (Bronze โ Silver โ Gold โ Platinum) to the TacoTracker app.
- Understanding the Medal System
- Step-by-Step: Adding a New Track
- Example: Weekend Warrior Track
- Testing Your New Track
- Common Patterns & Tips
Every track has 4 progressive tiers:
- ๐ฅ Bronze - Easy to achieve, gets users started
- ๐ฅ Silver - Moderate effort, regular users
- ๐ฅ Gold - Significant achievement, dedicated users
- ๐ Platinum - Ultimate goal, hardcore fans
User logs tacos โ Repository calculates progress โ Unlocks new tiers โ Shows celebration
Achievement.kt- Define the track and tier requirementsAchievementRepository.kt- Calculate current progress- No other files need changes! ๐
Open app/src/main/java/com/dinorawrger/tacotracker/data/Achievement.kt
Add your new track to the AchievementTrack sealed class:
sealed class AchievementTrack(
val id: String,
val title: String,
val description: String,
val emoji: String,
private val bronzeReq: TierRequirement,
private val silverReq: TierRequirement,
private val goldReq: TierRequirement,
private val platinumReq: TierRequirement
) {
// ... existing tracks ...
// โญ ADD YOUR NEW TRACK HERE:
data object YourTrackName : AchievementTrack(
id = "your_track_id", // Unique ID (lowercase, underscores)
title = "Your Track Title", // Display name
description = "What this tracks", // Short description
emoji = "๐ฏ", // Fun emoji icon
bronzeReq = TierRequirement(
description = "Do X 10 times", // What user needs to do
targetValue = 10 // The number to reach
),
silverReq = TierRequirement(
description = "Do X 25 times",
targetValue = 25
),
goldReq = TierRequirement(
description = "Do X 50 times",
targetValue = 50
),
platinumReq = TierRequirement(
description = "Do X 100 times",
targetValue = 100
)
)
// Don't forget the getAll() function at the bottom!
companion object {
fun getAll(): List<AchievementTrack> = listOf(
TacoVolume,
TacoTuesday,
Explorer,
// ... other tracks ...
YourTrackName // โญ ADD IT HERE TOO!
)
}
}Open app/src/main/java/com/dinorawrger/tacotracker/data/AchievementRepository.kt
Find the calculateCurrentValue() function and add your case:
private fun calculateCurrentValue(
track: AchievementTrack,
allMeals: List<MealWithTacos>,
allFavorites: List<FavoriteMeal>
): Int = when (track) {
// ... existing cases ...
// โญ ADD YOUR CALCULATION HERE:
is AchievementTrack.YourTrackName -> {
// Write code to calculate current progress
// Examples below!
allMeals.count { /* your condition */ }
}
}Let's add a complete track for tacos eaten on weekends!
data object WeekendWarrior : AchievementTrack(
id = "weekend_warrior",
title = "Weekend Warrior",
description = "Tacos consumed on Saturdays and Sundays",
emoji = "๐",
bronzeReq = TierRequirement(
description = "Eat 25 tacos on weekends",
targetValue = 25
),
silverReq = TierRequirement(
description = "Eat 50 tacos on weekends",
targetValue = 50
),
goldReq = TierRequirement(
description = "Eat 100 tacos on weekends",
targetValue = 100
),
platinumReq = TierRequirement(
description = "Eat 250 tacos on weekends",
targetValue = 250
)
)companion object {
fun getAll(): List<AchievementTrack> = listOf(
TacoVolume,
TacoTuesday,
Explorer,
Adventurer,
Carnivore,
Herbivore,
BreakfastChampion,
Perfectionist,
Collector,
NightOwl,
WeekendWarrior // โญ Add here
)
}is AchievementTrack.WeekendWarrior -> {
// Count tacos from meals on Saturday or Sunday
val calendar = Calendar.getInstance()
allMeals
.filter { mealWithTacos ->
calendar.timeInMillis = mealWithTacos.meal.eatenAtEpochMillis
val dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)
dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY
}
.sumOf { it.meal.totalTacos }
}Done! ๐ The track will automatically appear in the Achievements screen!
Build โ Clean Project
Build โ Rebuild
Run app
Your new track should appear in the grid!
- Go to New Entry
- Log meals that match your criteria
- Return to Achievements
- Progress should update!
- When you hit a threshold, celebration dialog should appear
- Tap the medal card to see detail screen
- All 4 tiers should show with correct status
is AchievementTrack.TacoVolume -> {
allMeals.sumOf { it.meal.totalTacos }
}is AchievementTrack.BreakfastChampion -> {
allMeals
.filter { it.meal.mealType.equals("Breakfast", ignoreCase = true) }
.sumOf { it.meal.totalTacos }
}is AchievementTrack.Explorer -> {
allMeals
.map { it.meal.location.trim().lowercase() }
.filter { it.isNotBlank() }
.distinct()
.size
}is AchievementTrack.Carnivore -> {
val meatKeywords = listOf("beef", "chicken", "pork", "steak", "carnitas", "barbacoa")
allMeals
.flatMap { it.tacos }
.count { taco ->
taco.ingredients.any { ingredient ->
meatKeywords.any { keyword ->
ingredient.name.contains(keyword, ignoreCase = true)
}
}
}
}is AchievementTrack.TacoTuesday -> {
val calendar = Calendar.getInstance()
allMeals
.filter { mealWithTacos ->
calendar.timeInMillis = mealWithTacos.meal.eatenAtEpochMillis
calendar.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY
}
.sumOf { it.meal.totalTacos }
}is AchievementTrack.SpeedRunner -> {
// Tracks most tacos in a single meal
allMeals.maxOfOrNull { it.meal.totalTacos } ?: 0
}is AchievementTrack.Collector -> {
allFavorites.size
}- Progressive difficulty: Bronze easy โ Platinum challenging
- Clear criteria: Users understand what to track
- Achievable Bronze: Get users started quickly (10-25 tacos)
- Ambitious Platinum: Real dedication required (100-500 tacos)
- Interesting patterns: Reveal habits (time, location, ingredients)
- Binary achievements: Either you have it or you don't
- Impossible Platinum: No one will reach it
- Too easy Bronze: Everyone gets it immediately
- Confusing metrics: Users don't understand progress
- Require missing features: Don't track things you don't store
Based on typical usage patterns:
| Tier | Easy Track | Medium Track | Hard Track |
|---|---|---|---|
| ๐ฅ Bronze | 10-25 | 5-15 | 3-10 |
| ๐ฅ Silver | 50-75 | 25-40 | 15-25 |
| ๐ฅ Gold | 100-150 | 50-75 | 30-50 |
| ๐ Platinum | 250-500 | 100-200 | 75-150 |
Easy tracks: Total volume (tacos, meals)
Medium tracks: Specific categories (breakfast, locations)
Hard tracks: Rare events (perfect meals, streaks)
- Did you add it to
getAll()? - Clean and rebuild the project
- Check for typos in track ID
- Check your calculation logic returns correct Int
- Log test data that matches your criteria
- Add debug logging:
println("Progress: $value")
- Make sure
idis unique (no duplicates) - Check track is in
getAll()list
- Verify your filter conditions are correct
- Check data types (Int vs Long)
- Test calculation with known data
Your new medal track is live! Users will:
- See it in the Achievements grid
- Watch progress update as they log tacos
- Get celebration dialogs when unlocking tiers
- View all tier details in the detail screen
No database migrations needed! The track evaluates dynamically from existing meal data.
Happy tracking! ๐ฎ๐