libretto.examples.supermarket.Customers.scala Maven / Gradle / Ivy
The newest version!
package libretto.examples.supermarket
import libretto.scaletto.StarterKit.*
import libretto.examples.supermarket.money.*
import scala.concurrent.duration.*
object Customers {
def apply(supermarket: SupermarketInterface): Customers[supermarket.type] =
new Customers(supermarket)
}
class Customers[SupermarketImpl <: SupermarketInterface](
val supermarket: SupermarketImpl,
) {
import supermarket.{*, given}
import supermarket.goods.*
/** Blueprint for customer behavior. A customer gets access to a supermarket and runs to completion ([[Done]]). */
def behavior(who: String): Supermarket -⚬ Done = {
def getCoins: Done -⚬ (Coin |*| (Coin |*| Coin)) =
printLine(s"🪙 $who is forging 3 coins") > λ { trigger =>
val (trigger1 |*| (trigger2 |*| trigger3)) = forkMap(id, fork)(trigger)
forgeCoin(trigger1) |*| (forgeCoin(trigger2) |*| forgeCoin(trigger3))
}
def useTP = delayUsing[ToiletPaper](randomDelay) > useToiletPaper
def drink = delayUsing[Beer ](randomDelay) > drinkBeer
λ { (supermarket: $[Supermarket]) =>
val ((shopping) |*| (basketObtained)) =
enterAndObtainBasket(supermarket) |> basketReadiness.signalDone
val logged: $[Done] =
when(basketObtained) {
printLine(s"$who obtained a shopping basket")
}
val (shopping1 |*| beerAdded) =
shopping |> addBeerToBasket > addBeerToBasket > basketReadiness.signalDone
val logged1: $[Done] =
when(join(logged |*| beerAdded)) {
printLine(s"$who added 2 beers to the basket")
}
val (shopping2 |*| tpAdded) =
shopping1 |> addToiletPaperToBasket > basketReadiness.signalDone
val logged2: $[Done] =
when(join(logged1 |*| tpAdded)) {
printLine(s"$who added toilet paper to the basket")
}
val (coin1 |*| (coin2 |*| coin3)) =
when(logged2) { getCoins }
val (tp |*| shopping3) =
payForToiletPaper(coin1 |*| shopping2)
val (beer1 |*| shopping4) =
payForBeer(coin2 |*| shopping3)
val (beer2 |*| shopping5) =
payForBeer(coin3 |*| shopping4)
val (shopping6 |*| paid) =
shopping5 |> basketReadiness.signalDone
val logged3: $[Done] =
when(paid) {
printLine(s"$who paid for the purchase")
}
val shoppingFinished: $[Done] =
(returnBasketAndLeave(shopping6) |*| logged3) |> elimFst >
printLine(s"$who returned the basket")
val beer1Drunk: $[Done] =
drink(beer1 waitFor shoppingFinished) |> printLine(s"🍺 $who drank the 1st beer")
val beer2Drunk: $[Done] =
drink(beer2 waitFor beer1Drunk) |> printLine(s"🍺 $who drank the 2nd beer")
useTP(tp waitFor beer2Drunk) |> printLine(s"🧻 $who used the toilet paper")
}
}
private def randomDelay: Done -⚬ Done =
constVal(()) > mapVal(_ => (scala.util.Random.nextDouble * 1000 + 100).toInt.millis) > delay
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy