Project: Todo App
Step 1: Set Up Your Scala Project
First, ensure you have Scala and SBT (Scala Build Tool) installed on your machine. You can check by running the following commands:
scala -version
sbt -version
If you don't have them installed, follow the installation instructions from the official Scala website.
Next, in IntelliJ create a new SBT project
Step 2: Define the To-Do App Structure
Create a Scala object to hold your application logic. You can do this by creating a new file in the src/main/scala directory. Let's call it TodoApp.scala.
import scala.io.StdIn.readLine
import scala.collection.mutable.ListBuffer
object TodoApp:
case class Task(id: Int, description: String)
val tasks: ListBuffer[Task] = ListBuffer.empty
var nextId: Int = 1
def main(args: Array[String]): Unit =
var continue = true
while (continue)
println("\nTODO App")
println("1. Add Task")
println("2. List Tasks")
println("3. Delete Task")
println("4. Exit")
print("Choose an option: ")
readLine() match {
case "1" => addTask()
case "2" => listTasks()
case "3" => deleteTask()
case "4" => continue = false
case _ => println("Invalid option. Please try again.")
def addTask(): Unit =
print("Enter task description: ")
val description = readLine()
tasks += Task(nextId, description)
nextId += 1
println(s"Task added with id $nextId")
def listTasks(): Unit =
if tasks.isEmpty {
println("No tasks available.")
} else {
tasks.foreach(task => println(s"${task.id}. ${task.description}"))
}
def deleteTask(): Unit =
print("Enter task id to delete: ")
val id = readLine().toInt
val taskIndex = tasks.indexWhere(_.id == id)
if taskIndex != -1 {
tasks.remove(taskIndex)
println(s"Task with id $id deleted.")
} else {
println(s"Task with id $id not found.")
}
}
Step 3: Running Your Application
To run your application, use SBT:
sbt run
This command compiles and runs your Scala application. You should see the menu and be able to interact with your to-do list by adding, listing, and deleting tasks.
Explanation
- Task Case Class: This defines a simple structure to hold task data.
- tasks ListBuffer: A mutable list to hold the tasks.
- nextId: A counter to assign unique IDs to tasks.
- main Method: This is the entry point of the application. It shows the menu and reads user input.
- addTask, listTasks, deleteTask Methods: These methods handle adding, listing, and deleting tasks respectively.
Add Priority
To add a priority to each task and sort the list based on priority, we need to modify the Task case class and the listTasks method. We will also adjust the addTask method to accept priority input from the user.
Here's the updated code for the TodoApp:
import scala.io.StdIn.readLine
import scala.collection.mutable.ListBuffer
object TodoApp:
case class Task(id: Int, description: String, priority: Int)
val tasks: ListBuffer[Task] = ListBuffer.empty
var nextId: Int = 1
def main(args: Array[String]): Unit =
var continue = true
while (continue)
println("\nTODO App")
println("1. Add Task")
println("2. List Tasks")
println("3. Delete Task")
println("4. Exit")
print("Choose an option: ")
readLine() match
case "1" => addTask()
case "2" => listTasks()
case "3" => deleteTask()
case "4" => continue = false
case _ => println("Invalid option. Please try again.")
def addTask(): Unit =
print("Enter task description: ")
val description = readLine()
print("Enter task priority (1=High, 2=Medium, 3=Low): ")
val priority = readLine().toInt
tasks += Task(nextId, description, priority)
nextId += 1
println(s"Task added with id $nextId and priority $priority")
def listTasks(): Unit =
if tasks.isEmpty {
println("No tasks available.")
} else {
println("Tasks (sorted by priority):")
val sortedTasks = tasks.sortBy(_.priority)
sortedTasks.foreach(task => println(s"${task.id}. [Priority: ${task.priority}] ${task.description}"))
}
def deleteTask(): Unit =
print("Enter task id to delete: ")
val id = readLine().toInt
val taskIndex = tasks.indexWhere(_.id == id)
if taskIndex != -1 {
tasks.remove(taskIndex)
println(s"Task with id $id deleted.")
} else {
println(s"Task with id $id not found.")
}
Explanation of Changes
- Task Case Class: Added a new field
priorityto theTaskcase class. - addTask Method: Now asks the user to input a priority level for the task.
- listTasks Method: Sorts tasks by their priority before printing. Lower numbers represent higher priority (1=High, 2=Medium, 3=Low).
Add User
To add a User case class and allow associating tasks with specific users, we need to make some adjustments to our application. We'll introduce a user management system where users can be added, and tasks can be associated with users. This will include methods to add users, list users, and associate tasks with users.
Here is the updated code:
import scala.io.StdIn.readLine
import scala.collection.mutable.{ListBuffer, Map}
object TodoApp:
case class Task(id: Int, description: String, priority: Int, userId: Int)
case class User(id: Int, name: String)
val tasks: ListBuffer[Task] = ListBuffer.empty
val users: ListBuffer[User] = ListBuffer.empty
var nextTaskId: Int = 1
var nextUserId: Int = 1
def main(args: Array[String]): Unit =
var continue = true
while (continue)
println("\nTODO App")
println("1. Add User")
println("2. List Users")
println("3. Add Task")
println("4. List Tasks")
println("5. Delete Task")
println("6. Exit")
print("Choose an option: ")
readLine() match
case "1" => addUser()
case "2" => listUsers()
case "3" => addTask()
case "4" => listTasks()
case "5" => deleteTask()
case "6" => continue = false
case _ => println("Invalid option. Please try again.")
def addUser(): Unit =
print("Enter user name: ")
val name = readLine()
users += User(nextUserId, name)
println(s"User added with id $nextUserId and name $name")
nextUserId += 1
def listUsers(): Unit =
if users.isEmpty then
println("No users available.")
else
println("Users:")
users.foreach(user => println(s"${user.id}. ${user.name}"))
def addTask(): Unit =
print("Enter task description: ")
val description = readLine()
print("Enter task priority (1=High, 2=Medium, 3=Low): ")
val priority = readLine().toInt
print("Enter user id: ")
val userId = readLine().toInt
if users.exists(_.id == userId) then
tasks += Task(nextTaskId, description, priority, userId)
println(s"Task added with id $nextTaskId, priority $priority, assigned to user $userId")
nextTaskId += 1
else
println(s"User with id $userId does not exist.")
def listTasks(): Unit =
if tasks.isEmpty then
println("No tasks available.")
else
println("Tasks (sorted by priority):")
val sortedTasks = tasks.sortBy(_.priority)
sortedTasks.foreach(task => {
val user = users.find(_.id == task.userId).map(_.name).getOrElse("Unknown User")
println(s"${task.id}. [Priority: ${task.priority}] ${task.description} (Assigned to: $user)")
})
def deleteTask(): Unit =
print("Enter task id to delete: ")
val id = readLine().toInt
val taskIndex = tasks.indexWhere(_.id == id)
if taskIndex != -1 then
tasks.remove(taskIndex)
println(s"Task with id $id deleted.")
else
println(s"Task with id $id not found.")
Explanation of Changes
- User Case Class: Added a
Usercase class withidandnamefields. - Task Case Class: Added a
userIdfield to associate tasks with a specific user. - users ListBuffer: A mutable list to hold the users.
- nextUserId: A counter to assign unique IDs to users.
- addUser Method: Allows adding a new user.
- listUsers Method: Lists all users.
- addTask Method: Now asks for a
userIdto assign the task to a specific user. - listTasks Method: Displays tasks with associated user names.