Skip to content

Commit

Permalink
Merge pull request #177 from ST10204902/WorkoutXPCalculator
Browse files Browse the repository at this point in the history
the users XP and level is saved to the database when they complete a …
  • Loading branch information
ST10195824 authored Nov 1, 2024
2 parents 4e5eb9c + 2145eb2 commit cbf6a62
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class UserManagerTest {
name = "Test User",
catName = "Test Cat",
milkCoins = "0",
experiencePoints = "0",
experiencePoints = 0,
backgroundURI = "test background uri",
catURI = "test cat uri",
userRoutines = emptyMap(),
Expand Down Expand Up @@ -112,7 +112,7 @@ class UserManagerTest {

@Test
fun updateExperiencePoints_withValidPoints_updatesExperiencePoints() = runBlocking {
val newExperiencePoints = "100"
val newExperiencePoints = 100
UserManager.updateExperiencePoints(newExperiencePoints)
val updatedUser = UserManager.user
assertNotNull("User should not be null", updatedUser)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ class AuthManager(val auth: FirebaseAuth = FirebaseAuth.getInstance()) {
"",
"",
"",
"",
"",
0,
0,
"",
"",
"",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ object UserManager {
userID = userId,
name = "",
catName = "",
experiencePoints = "",
experiencePoints = 0,
backgroundURI = "",
level = "",
level = 0,
token = "",
catURI = "",
milkCoins = "",
Expand Down Expand Up @@ -192,7 +192,7 @@ object UserManager {
* Updates the user's experience points
* @param newPoints The new experience points to update the user with
*/
fun updateExperiencePoints(newPoints: String) {
fun updateExperiencePoints(newPoints: Int) {
if (userIsLoggedIn()) {
_userFlow.update { user ->
user?.copy(experiencePoints = newPoints)
Expand All @@ -212,6 +212,16 @@ object UserManager {
}
}

fun updateLevel(newLevel: Int) {
if (userIsLoggedIn()) {
_userFlow.update { user ->
user?.copy(level = newLevel)
}
} else {
Log.e("UserManager.updateLevel", "User is not logged in")
}
}

/**
* Updates the user's background URI
* @param newURI The new background URI to update the user with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ data class User(
val name: String = "",
val catName: String = "",
val milkCoins: String = "",
val experiencePoints: String = "",
val level: String = "",
val experiencePoints: Int = 0,
val level: Int = 0,
val token: String = "",
val backgroundURI: String = "",
val catURI: String = "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import za.co.varsitycollege.st10204902.purrsonaltrainer.adapters.OnSetsUpdatedLi
import za.co.varsitycollege.st10204902.purrsonaltrainer.adapters.WorkoutExercisesAdapter
import za.co.varsitycollege.st10204902.purrsonaltrainer.backend.UserManager
import za.co.varsitycollege.st10204902.purrsonaltrainer.databinding.ActivityStartEmptyWorkoutBinding
import za.co.varsitycollege.st10204902.purrsonaltrainer.models.User
import za.co.varsitycollege.st10204902.purrsonaltrainer.models.UserRoutine
import za.co.varsitycollege.st10204902.purrsonaltrainer.models.UserWorkout
import za.co.varsitycollege.st10204902.purrsonaltrainer.models.WorkoutExercise
Expand All @@ -24,6 +25,7 @@ import za.co.varsitycollege.st10204902.purrsonaltrainer.services.ExerciseAddedLi
import za.co.varsitycollege.st10204902.purrsonaltrainer.services.RoutineBuilder
import za.co.varsitycollege.st10204902.purrsonaltrainer.services.RoutineConverter
import za.co.varsitycollege.st10204902.purrsonaltrainer.services.SlideUpPopup
import za.co.varsitycollege.st10204902.purrsonaltrainer.services.WorkoutXPCalculator
import za.co.varsitycollege.st10204902.purrsonaltrainer.services.navigateTo
import java.text.SimpleDateFormat
import java.time.Duration
Expand Down Expand Up @@ -74,14 +76,17 @@ class StartEmptyWorkoutActivity : AppCompatActivity(), ExerciseAddedListener, On

binding.doneButton.setOnClickListener {
// Update workout in database
saveUserWorkout()
val workout = saveUserWorkout()


// UI stuffs (Anneme)
binding.doneButton.setBackgroundResource(R.drawable.svg_green_bblbtn_clicked)
Handler(Looper.getMainLooper()).postDelayed({
binding.doneButton.background = binding.doneButton.background
}, 400)

val calculator = WorkoutXPCalculator()
val xp = calculator.calculateXP(workout)
calculator.updateUserLevelAndXP(xp)
UserManager.resetWorkoutInProgress()

// Navigating back to home activity
Expand All @@ -92,7 +97,7 @@ class StartEmptyWorkoutActivity : AppCompatActivity(), ExerciseAddedListener, On
/**
* Saves the current workout to the UserManager.
*/
private fun saveUserWorkout() {
private fun saveUserWorkout(): UserWorkout {
val newWorkout = UserWorkout(
workoutID = boundWorkout!!.workoutID,
workoutExercises = RoutineBuilder.exercises, // using RoutineBuilder for exercises
Expand All @@ -103,8 +108,11 @@ class StartEmptyWorkoutActivity : AppCompatActivity(), ExerciseAddedListener, On
color = boundWorkout!!.color
)



UserManager.updateUserWorkout(boundWorkout!!.workoutID, newWorkout)
UserManager.updateWorkoutInProgress(newWorkout.workoutID)
return newWorkout
}

/**
Expand Down Expand Up @@ -175,6 +183,7 @@ class StartEmptyWorkoutActivity : AppCompatActivity(), ExerciseAddedListener, On
binding.workoutTitle.text = boundWorkout!!.name
} else {
binding.workoutTitle.text = "Empty Workout"

}
setTitleColor(boundWorkout!!.color)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package za.co.varsitycollege.st10204902.purrsonaltrainer.services

import za.co.varsitycollege.st10204902.purrsonaltrainer.backend.UserManager
import za.co.varsitycollege.st10204902.purrsonaltrainer.models.User
import za.co.varsitycollege.st10204902.purrsonaltrainer.models.UserWorkout
import za.co.varsitycollege.st10204902.purrsonaltrainer.models.WorkoutExercise

Expand Down Expand Up @@ -29,9 +31,14 @@ class WorkoutXPCalculator {
"neck" to 2.0
)


private val defaultWeighting = 1.0
private lateinit var userWorkout: UserWorkout

// Scaling factors per milestone
private val scalingFactors = listOf(1.0, 1.3, 1.5, 1.8, 2.0, 2.5, 3.0, 4.0)
private val baseXP = 7000
private val totalLevels = 69

private var currentLevel = 1

/**
* Calculates the amount of XP a user earns from a workout.
Expand All @@ -40,14 +47,10 @@ class WorkoutXPCalculator {
* @return The calculated XP as an integer.
*/
fun calculateXP(userWorkout: UserWorkout): Int {
this.userWorkout = userWorkout
var totalXP = 0

for ((_, exercise) in userWorkout.workoutExercises) {
val setXP = getXPPerExercise(exercise)
totalXP += setXP
totalXP += getXPPerSet(exercise)
}

return totalXP
}

Expand All @@ -57,20 +60,49 @@ class WorkoutXPCalculator {
* @param exercise The exercise details.
* @return The calculated XP for the set.
*/
private fun getXPPerExercise(exercise: WorkoutExercise): Int {
val muscleWeighting =
muscleGroupWeightings.getOrDefault(exercise.category, defaultWeighting)
var totalXP = 0
for ((_, set) in exercise.sets) {

if (set.weight == null || set.weight == 0)
{
set.weight = userWorkout.bodyWeight
}
if (set.completed) {
totalXP += (set.weight!! * set.reps!! * muscleWeighting).toInt()
}
private fun getXPPerSet(exercise: WorkoutExercise): Int {
val muscleWeighting = muscleGroupWeightings.getOrDefault(exercise.category, defaultWeighting)
var setXP = 0
for (set in exercise.sets.values) {
if (set.weight != null || set.reps != null) {
setXP += (set.weight!! * set.reps!! * muscleWeighting).toInt()
}
return totalXP
}
}
return setXP
}

/**
* Calculates the XP requirements for each level.
*
* @return A list of XP requirements for each level.
*/
private fun calculateXPRequirements(): List<Int> {
val xpRequirements = mutableListOf(0) // Level 1 starts at 0 XP
for (level in 2..totalLevels) {
val milestoneIndex = (level - 1) / 10
val scalingFactor = scalingFactors[minOf(milestoneIndex, scalingFactors.size - 1)]
val previousXP = xpRequirements.last()
val newXP = previousXP + (baseXP * scalingFactor).toInt()
xpRequirements.add(newXP)
}
return xpRequirements
}

/**
* Updates the user's level and remaining XP after earning XP from a workout.
*
* @param totalXP The total XP earned from the workout.
*/
fun updateUserLevelAndXP(totalXP: Int) {
val user = UserManager.user!!
val xpRequirements = calculateXPRequirements()
var accumulatedXP = user.experiencePoints + totalXP
UserManager.updateExperiencePoints(accumulatedXP)
// Determine the new level and remaining XP
while (currentLevel < totalLevels && accumulatedXP >= xpRequirements[currentLevel]) {
accumulatedXP -= xpRequirements[currentLevel]
currentLevel++
}
UserManager.updateLevel(currentLevel)
}
}

0 comments on commit cbf6a62

Please sign in to comment.