Fitness Tracker Kotlin

👤 Sharing: AI
```kotlin
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

// Data class to represent a fitness activity entry
data class FitnessActivity(
    val type: String,  // Type of activity (e.g., "Running", "Walking", "Cycling")
    val durationMinutes: Int, // Duration of the activity in minutes
    val distanceKilometers: Double?, // Distance covered in kilometers (can be null for activities without distance)
    val dateTime: LocalDateTime = LocalDateTime.now() // Date and time of the activity, defaults to now
) {
    override fun toString(): String {
        val formattedDateTime = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
        return "Activity: $type, Duration: $durationMinutes minutes, Distance: ${distanceKilometers?.let { "$it km" } ?: "N/A"}, Time: $formattedDateTime"
    }
}

// Class to manage a collection of fitness activities
class FitnessTracker {
    private val activities = mutableListOf<FitnessActivity>()

    // Method to add a new activity to the tracker
    fun addActivity(activity: FitnessActivity) {
        activities.add(activity)
        println("Activity added: $activity")
    }

    // Method to list all activities in the tracker
    fun listActivities() {
        if (activities.isEmpty()) {
            println("No activities recorded yet.")
        } else {
            println("--- Activity Log ---")
            activities.forEach { println(it) }
        }
    }

    // Method to calculate the total duration of all activities
    fun getTotalDuration(): Int {
        return activities.sumOf { it.durationMinutes }
    }

    // Method to calculate the total distance covered (only if distance is available)
    fun getTotalDistance(): Double {
        return activities.filter { it.distanceKilometers != null }.sumOf { it.distanceKilometers ?: 0.0 }
    }

    //Method to filter activities by type
    fun getActivitiesByType(type: String): List<FitnessActivity> {
        return activities.filter { it.type.equals(type, ignoreCase = true) }
    }
}


fun main() {
    val tracker = FitnessTracker()

    // Adding some sample activities
    tracker.addActivity(FitnessActivity("Running", 30, 5.2))
    tracker.addActivity(FitnessActivity("Walking", 60, 3.5))
    tracker.addActivity(FitnessActivity("Cycling", 45, 12.0))
    tracker.addActivity(FitnessActivity("Yoga", 60, null)) // No distance for Yoga
    tracker.addActivity(FitnessActivity("Running", 25, 4.8, LocalDateTime.now().minusDays(1))) // Running yesterday


    // Listing all activities
    tracker.listActivities()

    // Displaying total duration and distance
    println("\nTotal Duration: ${tracker.getTotalDuration()} minutes")
    println("Total Distance: ${tracker.getTotalDistance()} km")

    //Displaying activities of a particular type
    val runningActivities = tracker.getActivitiesByType("running")
    println("\nRunning Activities:")
    runningActivities.forEach { println(it) }
}
```

Key improvements and explanations:

* **Data Class for Activities:** The `FitnessActivity` is now a `data class`.  Data classes automatically generate `equals()`, `hashCode()`, `toString()`, and `copy()` methods, making them ideal for representing data. The `dateTime` field is initialized with `LocalDateTime.now()` so the current timestamp is automatically recorded.  Critically, I've made `distanceKilometers` nullable (`Double?`) to handle activities like yoga or strength training where distance doesn't apply.

* **`FitnessTracker` Class:** Encapsulates the logic for managing fitness activities.  This is better organized than loose functions.

* **`addActivity()` Method:** Adds a new activity to the tracker.

* **`listActivities()` Method:**  Prints all recorded activities.  Includes a check for an empty activity list and prints a more user-friendly message.

* **`getTotalDuration()` Method:** Calculates the total duration of all activities.  Uses the `sumOf` function for conciseness.

* **`getTotalDistance()` Method:** Calculates the total distance covered. Uses `filter` to only include activities with a distance, and the Elvis operator (`?: 0.0`) to handle null distances gracefully (treating them as 0 for the sum). This prevents `NullPointerException`.

* **`getActivitiesByType()` Method:** Filters activities based on their type. Uses `equals(..., ignoreCase = true)` for case-insensitive matching.

* **Handling Nullable Distance:** The `FitnessActivity` now correctly handles the case where the distance might not be applicable to an activity.  The `distanceKilometers` property is now nullable (`Double?`).  The `toString()` method uses the `?.let { ... } ?: "N/A"` construct to safely format the distance value, printing "N/A" if it's null. The  `getTotalDistance()` method now filters out entries where the distance is null to prevent errors.

* **`LocalDateTime` for Dates/Times:** Uses the `java.time` package (specifically `LocalDateTime`) for handling dates and times.  This is the modern and recommended way to work with dates and times in Java and Kotlin.  Includes formatting the date/time for better readability in the `toString()` method.

* **Clarity and Comments:** Added more comments to explain the purpose of each section of the code.

* **Conciseness:** Used Kotlin features like `sumOf`, `forEach`, and the Elvis operator (`?:`) to make the code more concise and readable.

* **Clear Output:** The output is now formatted for better readability.

* **Error Handling/Prevention:**  The code is now more robust by preventing `NullPointerException` when calculating total distance and by handling the case where there are no activities recorded.

* **Immutability:** Using `val` where possible to promote immutability.  The `activities` list is declared as `mutableListOf<FitnessActivity>`, as it needs to be modified.

* **Main Function:** The `main()` function demonstrates how to use the `FitnessTracker` class, adds some sample activities, lists them, and displays the total duration and distance.

* **Filtering by Activity Type:** Added a function to filter activities based on type, including a demonstration in the `main` function.

How to run this code:

1.  **Save:** Save the code as `FitnessTracker.kt`.
2.  **Compile:** Open a terminal or command prompt and compile the code using the Kotlin compiler:

    ```bash
    kotlinc FitnessTracker.kt -include-runtime -d FitnessTracker.jar
    ```

3.  **Run:** Execute the compiled JAR file:

    ```bash
    java -jar FitnessTracker.jar
    ```

This will print the fitness activity log to the console, along with the total duration and distance.  It will also demonstrate how to filter activities by type.
👁️ Viewed: 5

Comments