Lab 2

class State {
    private final Shop shop;
    private final String text;

    State(Shop shop) {
        this.shop = shop;
        this.text = "";
    }
    
    State(Shop shop, String text) {
        this.shop = shop;
        this.text = text;
    }

    State next(Customer customer) {
        String newtext = this.text + customer + " arrives\n";
        return this.shop.findServer(customer)
            .map(server -> {
                    Shop updatedShop = this.shop.update(server.serve(customer));
                    String updatedtext = newtext + customer + " served by " + server + "\n";
                    return new State(updatedShop, updatedtext);
            })
            .orElse(new State(this.shop, newtext));
    }

    @Override
    public String toString() {
        return this.text;
    }
}

Lab 3

class State {
    private final Shop shop;
    private final PQ<Event> pq;
    private final String log;

    State(PQ<Event> pq, Shop shop) {
        this.pq = pq;
        this.shop = shop;
        this.log = "";
    }

    State(PQ<Event> pq, Shop shop, String log) {
        this.pq = pq;
        this.shop = shop;
        this.log = log;
    }

    boolean isEmpty() {
        return this.pq.isEmpty();
    }

    State next() {
        Pair<Maybe<Event>, PQ<Event>> polled = this.pq.poll();
        PQ<Event> remainingPQ = polled.u();
        Pair<Maybe<Event>, Shop> result = polled.t()
            .map(event -> event.next(this.shop))
            .orElse(new Pair<>(Maybe.empty(), this.shop));
        PQ<Event> newPQ = result.t()
            .map(e -> remainingPQ.add(e))
            .orElse(remainingPQ);
        String newLog = polled.t()
            .map(event -> this.log + event.toString() + "\n")
            .orElse(this.log);
        return new State(newPQ, result.u(), newLog);
    }

    @Override
    public String toString() {
        return this.log;
    }
}