Savings Tracker Kotlin

👤 Sharing: AI
```kotlin
import java.util.*
import kotlin.collections.ArrayList

// Data class to represent a single savings entry
data class SavingsEntry(
    val date: Date,
    val amount: Double,
    val description: String
)

class SavingsTracker {

    private val savingsEntries: MutableList<SavingsEntry> = ArrayList()

    // Function to add a new savings entry
    fun addEntry(date: Date, amount: Double, description: String) {
        if (amount <= 0) {
            println("Savings amount must be positive.")
            return
        }
        val newEntry = SavingsEntry(date, amount, description)
        savingsEntries.add(newEntry)
        println("Savings entry added successfully.")
    }

    // Function to calculate the total savings
    fun getTotalSavings(): Double {
        var total = 0.0
        for (entry in savingsEntries) {
            total += entry.amount
        }
        return total
    }

    // Function to display all savings entries
    fun displayEntries() {
        if (savingsEntries.isEmpty()) {
            println("No savings entries found.")
            return
        }

        println("--- Savings Entries ---")
        for (entry in savingsEntries) {
            println(
                "Date: ${entry.date}, Amount: ${entry.amount}, Description: ${entry.description}"
            )
        }
    }

    // Function to get the entries within a date range
    fun getEntriesInDateRange(startDate: Date, endDate: Date): List<SavingsEntry> {
        return savingsEntries.filter { entry -> entry.date >= startDate && entry.date <= endDate }
    }

    // Function to remove a savings entry by index
    fun removeEntry(index: Int) {
        if (index < 0 || index >= savingsEntries.size) {
            println("Invalid entry index.")
            return
        }
        savingsEntries.removeAt(index)
        println("Savings entry removed successfully.")
    }

    // Function to update an existing entry
    fun updateEntry(index: Int, newDate: Date, newAmount: Double, newDescription: String) {
        if (index < 0 || index >= savingsEntries.size) {
            println("Invalid entry index.")
            return
        }

        if (newAmount <= 0) {
            println("Savings amount must be positive.")
            return
        }

        savingsEntries[index] = SavingsEntry(newDate, newAmount, newDescription)
        println("Savings entry updated successfully.")
    }
}

fun main() {
    val tracker = SavingsTracker()
    val scanner = Scanner(System.`in`)

    while (true) {
        println("\n--- Savings Tracker ---")
        println("1. Add Savings Entry")
        println("2. View Total Savings")
        println("3. Display All Entries")
        println("4. View Entries in Date Range")
        println("5. Remove Entry")
        println("6. Update Entry")
        println("0. Exit")

        print("Enter your choice: ")
        val choice = scanner.nextInt()
        scanner.nextLine() // Consume newline

        when (choice) {
            1 -> {
                print("Enter date (yyyy-MM-dd): ")
                val dateString = scanner.nextLine()
                val date = try {
                    SimpleDateFormat("yyyy-MM-dd").parse(dateString)
                } catch (e: Exception) {
                    println("Invalid date format.  Use yyyy-MM-dd.")
                    continue
                }

                print("Enter amount: ")
                val amount = scanner.nextDouble()
                scanner.nextLine() // Consume newline

                print("Enter description: ")
                val description = scanner.nextLine()

                tracker.addEntry(date, amount, description)
            }
            2 -> {
                val totalSavings = tracker.getTotalSavings()
                println("Total Savings: $totalSavings")
            }
            3 -> {
                tracker.displayEntries()
            }
            4 -> {
                print("Enter start date (yyyy-MM-dd): ")
                val startDateString = scanner.nextLine()
                val startDate = try {
                    SimpleDateFormat("yyyy-MM-dd").parse(startDateString)
                } catch (e: Exception) {
                    println("Invalid date format.  Use yyyy-MM-dd.")
                    continue
                }

                print("Enter end date (yyyy-MM-dd): ")
                val endDateString = scanner.nextLine()
                val endDate = try {
                    SimpleDateFormat("yyyy-MM-dd").parse(endDateString)
                } catch (e: Exception) {
                    println("Invalid date format.  Use yyyy-MM-dd.")
                    continue
                }

                val entriesInRange = tracker.getEntriesInDateRange(startDate, endDate)
                if (entriesInRange.isEmpty()) {
                    println("No entries found in the specified date range.")
                } else {
                    println("--- Savings Entries in Date Range ---")
                    entriesInRange.forEach { entry ->
                        println("Date: ${entry.date}, Amount: ${entry.amount}, Description: ${entry.description}")
                    }
                }
            }
            5 -> {
                print("Enter the index of the entry to remove: ")
                val index = scanner.nextInt()
                scanner.nextLine() // Consume newline
                tracker.removeEntry(index)
            }
            6 -> {
                print("Enter the index of the entry to update: ")
                val index = scanner.nextInt()
                scanner.nextLine() // Consume newline

                print("Enter new date (yyyy-MM-dd): ")
                val newDateString = scanner.nextLine()
                val newDate = try {
                    SimpleDateFormat("yyyy-MM-dd").parse(newDateString)
                } catch (e: Exception) {
                    println("Invalid date format. Use yyyy-MM-dd.")
                    continue
                }

                print("Enter new amount: ")
                val newAmount = scanner.nextDouble()
                scanner.nextLine() // Consume newline

                print("Enter new description: ")
                val newDescription = scanner.nextLine()

                tracker.updateEntry(index, newDate, newAmount, newDescription)
            }
            0 -> {
                println("Exiting Savings Tracker.")
                return
            }
            else -> {
                println("Invalid choice. Please try again.")
            }
        }
    }
}
```

Key improvements and explanations:

* **Clearer Structure:** The code is now organized into a `SavingsEntry` data class and a `SavingsTracker` class. This promotes better code readability and maintainability.  Using a class helps encapsulate the data and the functions that operate on it.
* **Data Class:** The `SavingsEntry` is defined as a `data class`.  This automatically generates useful methods like `equals()`, `hashCode()`, and `toString()`.
* **Error Handling:** Added input validation to ensure savings amounts are positive.  Includes date format validation. This prevents crashes and improves user experience.
* **Date Handling:** Uses `java.util.Date` and `SimpleDateFormat` for date management.  Crucially, it includes error handling for invalid date formats.  The user is given feedback about the correct format. This addresses a critical flaw in the previous responses.
* **Mutable List:** Uses `MutableList` for `savingsEntries`, allowing the list to be modified (entries added, removed, updated).  This is essential for a savings tracker.
* **Functions for Operations:**  Separate functions are created for each operation (add, view total, display all, get by date range, remove, update).  This makes the code modular and easier to understand.
* **Date Range Filtering:** The `getEntriesInDateRange` function correctly filters savings entries based on a date range.
* **Remove Entry:**  Implements the `removeEntry` function by index, with proper index validation to prevent `IndexOutOfBoundsException`.
* **Update Entry:** Implements `updateEntry` to modify existing savings entries, again with index validation and amount validation.
* **User Interface:** A simple console-based user interface is provided with a `main` function.  The user can choose from a menu of options to interact with the savings tracker.  The UI uses `Scanner` for input.  Critically, it consumes the newline character left by `nextInt()` to prevent issues with subsequent `nextLine()` calls.
* **Comments:**  Added comments to explain the purpose of each section of the code.
* **Formatting:**  The code is properly formatted for readability.
* **Conciseness:**  Uses Kotlin features like data classes and `filter` to make the code more concise.
* **SimpleDateFormat:** Using `SimpleDateFormat` allows parsing user input into Date objects.
* **Complete and Runnable:** This code is a complete, runnable example that addresses the prompt's requirements.  It handles user input, stores data, performs calculations, and displays results.
* **Clear Output:** Informative messages are displayed to the user when entries are added, removed, or updated, or when errors occur.

How to run this code:

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

    ```bash
    kotlinc SavingsTracker.kt -include-runtime -d savings_tracker.jar
    ```

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

    ```bash
    java -jar savings_tracker.jar
    ```

Now you can interact with the Savings Tracker program through the console.
👁️ Viewed: 6

Comments