import java.util.* ;

/**
 * Java code for M250 Prsntn 2018J Exam Solutions
 * M250Prsntn2018JExamQA.java
 * @author Sharon Dawes, Phil Molyneux
 * @version 1.0
 */

class Performer {
  private String equityName ;
  private double payRate ;
  private Branch branch ;
  public static double minPayRate ;
  
  public Performer(String aName) {
    super() ;
    equityName = aName ;  
    branch = null ;
    payRate = Performer.minPayRate ;
    /* or */ 
    // payRate = minPayRate ; 
  }
  
  public double getPayRate() {
    return payRate ;
  }
  
  public void setPayRate(double aPayRate) {
    payRate = aPayRate ;
  }
  
  public Branch getBranch() {
    return branch ;
  }
  
  public void setBranch(Branch aBranch) {
    branch = aBranch ;
  }
  
  public String getEquityName() {
    return equityName ;
  }
  
  public boolean isInSameBranchAs(Performer p) {
    return branch.equals(p.getBranch()) ;
    /* or */ 
    // return getBranch().equals(p.getBranch()) ;
  }
  
  public String getFirstName() {
    int spaceIndex = equityName.indexOf(" ") ; 
    /* or */ 
    // int spaceIndex = equityName.indexOf(' ') ;
    return equityName.substring(0,spaceIndex) ;
  }
  
  @Override
  public boolean equals(Object obj) {
    Performer pfmr = (Performer) obj ;
    return equityName.equals(pfmr.equityName) ;
  }
  
  // @Override
  // public boolean equals(Object obj) {
  //   if (obj == this) {
  //     return true ;
  //   }
  //   if (!(obj instanceof Performer)) {
  //     return false ;
  //   }
  //   Performer pfmr = (Performer) obj ;
  //   return equityName.equals(pfmr.equityName) ;
  // }
  
  public String toString() {
    return ("An instance of class " + this.getClass().getName()
           + ": equityName = " + this.getEquityName()
           + ", branch = " + this.getBranch()
           + ", payRate = " + this.getPayRate()
           ) ;
  }

}

class Branch {
  private String name ;
  private String address ;
  
  public Branch(String aName, String anAddress) {
    name = aName ;
    address = anAddress ;
  }
  
  public String getName() {
    return name ;
  }
  
  public String getAddress() {
    return address ;
  }
  
  public void setAddress(String anAddress) {
    address = anAddress ;    
  }
  
  @Override
  public boolean equals(Object obj) {
    if (obj == this) {
      return true ;
    }
    if (!(obj instanceof Branch)) {
      return false ;
    }
    Branch bnch = (Branch) obj ;
    return name.equals(bnch.name) ;
  }
  
  public String toString() {
    return ("An instance of class " + this.getClass().getName()
           + ": name = " + this.getName()
           + ", address = " + this.getAddress()
           ) ;
  }
  
}

interface Drivable {
  void accelerate() ;
  void brake() ;
  void stop() ;
}

class Vehicle implements Drivable {
  private int speed ;
  
  public Vehicle() {
    super() ;
    speed = 0 ;
  }
  
  public void accelerate() {
    speed = speed + 1 ;
  }
  
  public void brake() {
    if (speed > 0) {
      speed = speed - 1 ;
    }
  }
  
  public void stop() {
    while (speed > 0) {
      speed = speed - 1 ;
    }
  }

  public int getSpeed() {// required later
    return speed ;
  }

  public void setSpeed(int spd) {// required later
    speed = spd ;
  }
  
}

class Car extends Vehicle {
  private int maxSpeed ;
  private int increment ;
  public static int count = 0 ; // Q2(c)(iii)
  
  public Car() {
    super() ;
    Car.count = Car.count + 1 ; // Q2(c)(iii)
  }
  
  @Override
  public void accelerate() {
    if ((getSpeed() + increment) <= maxSpeed) {
      super.setSpeed(super.getSpeed() + increment) ;
    }
  }
}

class CaravanSite {
  // provided
  private String siteName ;
  private int maxVans ;
  
  private List<Booking> bookings ;
  
  public CaravanSite(String aName, int aMaxVans) {
    super() ;
    siteName = aName ;
    maxVans = aMaxVans ;
    bookings = new ArrayList<>() ;
  }
  
  public int addBooking(Booking aBooking) {
    if (bookings.size() < maxVans) {
      bookings.add(aBooking) ;
    }
    else {
      System.out.println("No space") ;
    }
    return maxVans - bookings.size() ;
  }
  
  public void orderBookings() {
    Collections.sort(bookings) ;
  }
  
  public List<Booking> getBookings() {
    return bookings ;
  }
  
}

class Booking implements Comparable<Booking> {
  // provided
  private String makeAndModel ;
  private String owner ;
  private int estArrivalHour ;
  
  public Booking(String aMandM
                ,String anOwner
                ,int anHour) {
    super() ;
    makeAndModel = aMandM ;
    owner = anOwner ;
    estArrivalHour = anHour ;
  }

  public String getMakeAndModel() {
    return makeAndModel ;
  }
  
  public String getOwner() {
    return owner ;
  }
  
  public int getEstArrivalHour() {
    return estArrivalHour ;
  }

  public int compareTo(Booking aBooking) {
    return estArrivalHour - aBooking.estArrivalHour ;
    /* or */
    // Integer.compare(estArrivalHour,
    //                aBooking.estArrivalHour)
  }
  
  @Override
  public boolean equals(Object obj) {
    Booking bkg = (Booking) obj ;
    return makeAndModel.equals(bkg.makeAndModel)
        && owner.equals(bkg.owner) ;
  }
  
  @Override
  public int hashCode() {
    return (20 + makeAndModel.hashCode())
         * owner.hashCode() ;
  }

}

class CaravanClub {
  private Map<Integer,Set<Booking>> arrByTime ;
  
  public CaravanClub() {
    arrByTime = new HashMap<>() ;
  }
  
  public void addSite(CaravanSite aSite) {
    for (Booking aBooking : aSite.getBookings()) {
      Integer hour = aBooking.getEstArrivalHour() ;
      if (!(arrByTime.containsKey(hour))) {
        arrByTime.put(hour, new HashSet<>()) ;
      }
      arrByTime.get(hour).add(aBooking) ;
    }
  }

}

class M250Prsntn2018JExamQA {
  public static void main(String[] args) {
    System.out.println("Java code for M250Prsntn2018JExamQA") ;
  }
  
  public static void m250Prsntn2018JExamQ1b() {
    Branch b1;                                       // 1
    b1 = new Branch("Kent", "The Alexander Centre"); // 2
    Branch b2;                                       // 3
    b2 = new Branch("Dorset", "Wessex fm Studios");  // 4
    Performer.minPayRate = 9.50;                     // 5
    Performer p1 = new Performer("Happy Bunny");     // 6
    Performer p2 = new Performer("Silly Sausage");   // 7
    p1.setPayRate(10.00);                            // 8
    p2.setPayRate(20.00);                            // 9
    p1.setBranch(b1);                                // 10
    p2.setBranch(b1);                                // 11
    System.out.println(p1.isInSameBranchAs(p2));     // 12
    
  }
  
}
  
