Skip to content

Instantly share code, notes, and snippets.

@benkio
Last active March 12, 2022 09:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benkio/baa4fe1d50751cd602c4175f1bb39f4d to your computer and use it in GitHub Desktop.
Save benkio/baa4fe1d50751cd602c4175f1bb39f4d to your computer and use it in GitHub Desktop.
#!/usr/bin/env scala-cli
// to import stuff
// using lib "com.lihaoyi::os-lib:0.7.8"
// args is the command line input
using lib "org.typelevel::cats-core:2.7.0"
import cats.data.{StateT, NonEmptyList}
import cats.syntax.all._
import java.time.LocalTime
type ThrowableOr[A] = Either[Throwable, A]
object TableReservationSystem {
final case class ReservationId(tableNumber: Int, hour: LocalTime)
final case class Reservation(id: ReservationId, name: String)
final case class Reservations(reservations: List[Reservation]) {
def insert(reservation: Reservation): ThrowableOr[Reservations] =
if (reservations.exists(r => r.id == reservation.id))
Left(new TableAlreadyReservedException(reservation))
else Right(Reservations(reservations :+ reservation))
}
final class TableAlreadyReservedException(
reservation: Reservation
) extends RuntimeException(
s"${reservation.name} cannot be added because table number ${reservation.id.tableNumber} is already reserved for the ${reservation.id.hour}"
)
val emptyReservationSystem: Reservations = Reservations(List.empty)
def insertBooking(
reservation: Reservation
): StateT[ThrowableOr, Reservations, Unit] =
StateT.modifyF[ThrowableOr, Reservations](_.insert(reservation))
def processBookings(
bookings: NonEmptyList[Reservation]
): ThrowableOr[Reservations] =
bookings
.traverse_(insertBooking)
.runS(emptyReservationSystem)
}
val bookings = NonEmptyList.of(
TableReservationSystem.Reservation(
TableReservationSystem
.ReservationId(tableNumber = 1, hour = LocalTime.parse("10:00:00")),
name = "Gandalf"
),
TableReservationSystem.Reservation(
TableReservationSystem
.ReservationId(tableNumber = 2, hour = LocalTime.parse("10:00:00")),
name = "Legolas"
),
TableReservationSystem.Reservation(
TableReservationSystem
.ReservationId(tableNumber = 1, hour = LocalTime.parse("12:00:00")),
name = "Frodo"
),
TableReservationSystem.Reservation(
TableReservationSystem
.ReservationId(tableNumber = 2, hour = LocalTime.parse("12:00:00")),
name = "Bilbo"
),
TableReservationSystem.Reservation(
TableReservationSystem
.ReservationId(tableNumber = 3, hour = LocalTime.parse("13:00:00")),
name = "Elrond"
),
TableReservationSystem.Reservation(
TableReservationSystem
.ReservationId(tableNumber = 1, hour = LocalTime.parse("16:00:00")),
name = "Sauron"
),
TableReservationSystem.Reservation(
TableReservationSystem
.ReservationId(tableNumber = 2, hour = LocalTime.parse("16:00:00")),
name = "Aragorn"
),
TableReservationSystem.Reservation(
TableReservationSystem
.ReservationId(tableNumber = 2, hour = LocalTime.parse("18:00:00")),
name = "Gollum"
)
)
println(TableReservationSystem.processBookings(bookings))
println(
TableReservationSystem.processBookings(
bookings :+ TableReservationSystem.Reservation(
TableReservationSystem
.ReservationId(tableNumber = 1, hour = LocalTime.parse("16:00:00")),
name = "Saruman"
)
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment