Overloading Constructors for Updates

class Pet {
    private final String name;
    private final String gender;
    private final int age;

    Pet(String name) {
        this.name = name;
        this.gender = "Unknown";
        this.age = 0;
    }

    Pet(String name, String gender) {
        this.name = name;
        this.gender = gender;
        this.age = 0;
    }
}

Polymorphism and Overriding to making things simpler

This is so tedious.

class Payment { }

class Card extends Payment { }

class Cash extends Payment { }

class BankTransfer extends Payment { }

void processPayment(List<Payment> payments) {
    for (Payment payment : payments) {
        if (payment instanceof Cash) {
            System.out.println("Dig wallet for cash...");
        } else if (payment instanceof Card) {
            System.out.println("swipe some cards...");
        } else if (payment instanceof BankTransfer) {
            System.out.println("Getting account number...");
        }
    }
}

Do this instead. Override the method for different classes based on how you want different classes to behave. Define the method in the super class, override in the rest. Only for interface add public.

abstract class Payment {
    abstract void pay();
}

class Card extends Payment {
    @Override
    void pay() {
        System.out.println("swipe some cards...");
    }
}

class Cash extends Payment {
    @Override
    void pay() {
        System.out.println("Dig wallet for cash...");
    }
}

class BankTransfer extends Payment {
    @Override
    void pay() {
        System.out.println("Getting account number...");
    }
}

void processPayment(List<Payment> payments) {
    for (Payment payment : payments) {
        payment.pay();
    }
}

Comparable Interface - One natural ordering

Lets objects create an order within.

int compareTo(T obj)
# negative integer (less than)
# zero (equal to)
# positive integer (greater than) than obj.

Less than means A comes before B in ascending order sorting.
class Person implements Comparable<Person> {
// sort by age in ascending order, breaking ties using name  
	public int compareTo(Person otherPerson) {
		if (this.age == otherPerson.age) {
			return this.name.compareTo(otherPerson.name);
		}
		return Integer.compare(this.age, otherPerson.age);
	}
}

Other ways:
Double.compare(this.time, other.time)

Data Hiding

Always declare class and instance variables as private. Use the final keyword for instance variables.

Having next() for these kind of event changing / A β†’ B

Like how we used next() in State to process the Customer interactions, you will need to implement a next() to process Events.

The next() method should return the new Event as well as an updated Shop in a Pair<Maybe<Event>, Shop>, or Maybe<Pair<Event, Shop>>. The decision is up to you, consider and plan your design carefully.

Calling next on an ArriveEvent would either lead to a ServeEvent or LeaveEvent, and next on Serve β†’ Done

pair.t() is the Maybe<Event>, pair().u() is the updated Shop

Priority Queues

Elements in the PQ are NOT necessarily sorted in order. A PQ only guarantees that the first element is the highest priority one.

Implementation

PQ<Person> pq = new PQ<Person>();

// Get the first element (removed from the PQ)
Pair<Maybe<Person>, PQ<Person>> pair = pq.poll();
Maybe<Person> person = pair.t();
pq = pair.u();

// Add a new element
// Reassignment due to immutability
PQ<Person> pq = pq.add(new Person());

// Check whether the PQ is empty
boolean isEmpty = pq.isEmpty();

Java PriorityQueue returns null when empty, Immutable PQ returns a Maybe.empty. Java PriorityQueue allows you to mutate it without needing to reassign the variable. Immutable PQ returns a Pair object when polled, first item being a Maybe storing the item removed from PQ, second item storing the modified PQ.

Expected output using the new PQ


1. Cool way to print all the scenarios

jshell> InfList.<Event>of(arriveEvent, serveEvent, leaveEvent, doneEvent). // InfList<Event>
   ...> map(event -> event.toString() + "\n"). // InfList<String>
   ...> reduce((x, y) -> x + y). // Maybe<String>
   ...> ifPresent(x -> System.out.println(x))
1.0 customer 1 arrives
1.0 customer 1 serve by server 1
1.0 customer 1 leaves
3.0 customer 1 done

2. Using super class toString method and adding on

@Override
public String toString() {
return super.toString() + " arrives";
}

3. Using super in methods

// From Event Class
Event(Customer cust, double time) {
	this.cust = cust;
	this.time = time;
}

ArriveEvent(Customer customer, double time) {
  super(customer, time);
}

This is essentially calling Event(customer, time);

4. Using a mix of super() to get initial data and adding new data

ServeEvent(ArriveEvent arriveEvent, Server server) {
	super(arriveEvent); // Using super to get initial data
	this.event = arriveEvent;
	this.server = serve; // Augmenting other data
}

// From Event Class
Event(Event event) {
	this.cust = event.cust;
	this.time = event.time;
}

// This initiates the cust and time variables using the initial cust and time variables from the event.

5. If can’t compare due to private access, create a new internal compareTo method

// In Event Class
public int compareTo(Event other) {
    int timeCompare = Double.compare(this.time, other.time);
    if (timeCompare != 0) {
        return timeCompare;
    }
    return this.cust.compareTo(other.cust);
}

// In Customer Class
class Customer implements Comparable<Customer> { // ... public int compareTo(Customer other) { return Integer.compare(this.id, other.id); } }

6. Pair

record Pair<T,U>(T t, U u) {}

Pair<Event, Shop> next(Shop shop) {         
	return ...
}

new Pair<>(firstValue, secondValue)

7. Passing this

class ArriveEvent extends Event {
	...
	// If I want to reference arriveEvent, I can just use THIS
	...
}

8. Using Maybe with Pair

Pair(Maybe<Event>, shop) next(Shop shop) {
	return new Pair<>(Maybe.of(someEvent), shop)
}

Notice the difference between
Maybe<Event> a type
Maybe.of(Event) a value, creating an instance of Maybe<Event> 

9. Need to specify type

return shop.findServer(this.cust)
    .map(server -> new Pair<Maybe<Event>, Shop>(Maybe.<Event>of(new ServeEvent(this, server)), shop.update(server.serve(this.cust))))
    .orElse(new Pair<Maybe<Event>, Shop>(Maybe.<Event>of(new LeaveEvent(this)), shop));
    
If the code is bugging out, make it more specific.
Still figuring out why this is an issue.

10. How to get around private access

  1. Redeclare the field by doing
private final VarType var

// In the constructor redudantly
this.var = var

Make sure to only include redeclarations in classes that use it.
Some may already get it from super...
  1. Add a method that computes it without exposing the raw field
// In Server class, which has private serviceTime
public double getCompletionTime(Customer customer) {
    return customer.serveTill(this.serviceTime);
}

11. Unwrapping a container like Maybe / Optional

Maybe<Event> maybeEvent = ...; 
maybeEvent.map(event -> event.next(shop))

// map applies a function to the value inside the Maybe if it's present.

12. State needs log

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;
    }
}

Additional notes

Don’t use getters Name it well nex() method?

String

String.format("%s is %d years old with GPA %.2f", name, age, gpa)

super(…) Telling the compiler go to the super class See how the parent class intiliased

ArriveEvent(Customer cust, double time) { supeer(cust, time) }

@Override public string toString() { return super.toString() + …

If A extend B, then A contains the variables from B A extends B only if A is a subset, not because it contains similar variables

cant write method body in interface exception: static method body

no class variables interface variables are public static final