-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathTask.scala
122 lines (114 loc) · 4.82 KB
/
Task.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import java.nio.file.{Files, Path}
import scala.jdk.CollectionConverters.*
import cats.effect.{IO, IOApp}
import cats.syntax.all.*
object Task extends IOApp.Simple:
/**
* The main function of our console application.
* It should parse the adoption center CSV file and then call the mainMenu function.
*/
override def run: IO[Unit] =
for {
lines <- read(Dog.FilePath)
shelter = lines.map(Dog.fromLine)
_ <- mainMenu(shelter)
} yield ()
/**
* This function just reads the input file.
* @param path -- the path to the input file
* @return lines of the input file
*/
private def read(path: Path): IO[List[String]] =
IO { Files.readAllLines(path).asScala.toList }
/**
* Displays the menu, explaining available options.
*/
private def displayMenu: IO[Unit] = IO.println (
"""
|Welcome to the Virtual Dog Adoption Center!
|------------------------------------------
|1. View all available dogs
|2. Adopt a dog
|3. Surrender a dog
|4. Exit
|Please select an option (1-4):
|""".stripMargin
)
/**
* Main application loop.
* It should display the menu, prompt the user to input an option they want to do, and execute that action.
* If the user inputs "4", the application loop should be stopped, and the shelter saved into the file.
* @param shelter -- a list of the available dogs
*/
def mainMenu(shelter: List[Dog]): IO[Unit] = for {
_ <- displayMenu
choice <- IO.readLine
newShelter <- choice match {
case "1" => viewDogs(shelter) *> IO.pure(shelter)
case "2" => adoptDog(shelter)
case "3" => surrenderDog(shelter)
case "4" => exitShelter(shelter, Dog.FilePath) *> IO.pure(shelter)
case _ => IO.println("Invalid option. Please try again.") *> IO.pure(shelter)
}
_ <- if (choice != "4") mainMenu(newShelter) else IO.unit
} yield ()
/**
* Thanks the user for visiting, and store the current state of the shelter in the file.
* @param shelter -- a list of the dogs available at the end of the session.
* @param path -- a path to the file storing the data about the shelter.
*/
private def exitShelter(shelter: List[Dog], path: Path): IO[Unit] = for {
_ <- IO.println("Thank you for visiting!")
_ <- IO { Files.deleteIfExists(path)
Files.createFile(path)
Files.writeString(path, shelter.sortBy(_.id).map(_.toLine).mkString("\n"))
}
} yield ()
/**
* Views all the dogs in the shelter.
* If the list is empty, explain that there are no dogs available to adopt
* @param shelter -- a list of the available dogs
*/
private def viewDogs(shelter: List[Dog]): IO[Unit] = for {
_ <-
if (shelter.isEmpty)
IO.println("No dogs are currently available for adoption.")
else
shelter.traverse_ { dog => IO.println(dog.toString()) }
} yield ()
/**
* Surrenders a dog to the shelter.
* It should prompt the user to input the dog's name, breed, and favorite toy.
* The dog should be assigned a new unique identifier before adding to the list.
* The function yields `newShelter`, which describes the shelter after surrendering the dog.
* @param shelter -- a list of the available dogs
*/
private def surrenderDog(shelter: List[Dog]): IO[List[Dog]] = for {
_ <- IO.print("Enter dog's name: ")
name <- IO.readLine
_ <- IO.print("Enter dog's breed: ")
breed <- IO.readLine
_ <- IO.print("Enter dog's favorite toy: ")
favoriteToy <- IO.readLine
newId = if (shelter.isEmpty) 1 else shelter.map(_.id).max + 1
newDog = Dog(newId, name, breed, favoriteToy)
newShelter = newDog :: shelter
_ <- IO.println(s"Dog ${newDog.name} has been surrendered with ID ${newDog.id}.")
} yield newShelter
/**
* Adopt a dog from the shelter.
* Should prompt the user to input the dog's identifier.
* If the ID doesn't exist, report the error to the user and exit to the main loop.
* Otherwise, congratulate the user on adoption and remove the dog from the shelter.
* The function yields `newShelter`, which describes the shelter after adopting the dog.
*
* @param shelter -- a list of the available dogs
*/
private def adoptDog(shelter: List[Dog]): IO[List[Dog]] = for {
_ <- IO.print("Enter the ID of the dog you wish to adopt: ")
idInput <- IO.readLine
id <- IO.fromOption(idInput.toIntOption)(new NumberFormatException("Invalid ID input"))
(dog, newShelter) = shelter.partition(_.id == id)
_ <- if (dog.isEmpty) IO.println("No dog found with the provided ID.")
else IO.println(s"Congratulations! You have adopted ${dog.head.name}.")
} yield newShelter