/*
--- CSU213 Spring 2005 Lecture Notes ---------
Copyright 2005 Viera K. Proulx

Lecture 15: How do we compare ... the code
*/

/*
;                                       
;                                       
;                                       
;   ;    ;;;;                           
;   ;   ;    ;                          
;   ;   ;                               
;   ;   ;      ;;;    ; ;;  ;;     ;;;  
;   ;    ;;   ;   ;   ;;  ;;  ;   ;   ; 
;   ;      ;      ;   ;   ;   ;  ;    ; 
;   ;       ;  ;;;;   ;   ;   ;  ;;;;;; 
;   ;       ; ;   ;   ;   ;   ;  ;      
;   ;   ;   ; ;   ;   ;   ;   ;   ;     
;   ;    ;;;   ;;;;;  ;   ;   ;    ;;;; 
;                                       
;                                       
;                                       
*/
interface ISame{
  // determine whether this object is the same as the given one
   boolean same(Object obj);
}

/*
;                                                 
;                                                 
;                                                 
;   ;;;;;  ;                                      
;   ;    ;                                        
;   ;    ;            ;                           
;   ;    ; ;    ;;;  ;;;;  ;   ;   ; ;   ;;;      
;   ;    ; ;   ;   ;  ;    ;   ;   ;;   ;   ;     
;   ;;;;;  ;  ;       ;    ;   ;   ;   ;    ;     
;   ;      ;  ;       ;    ;   ;   ;   ;;;;;;     
;   ;      ;  ;       ;    ;   ;   ;   ;          
;   ;      ;   ;   ;  ;    ;  ;;   ;    ;         
;   ;      ;    ;;;    ;;   ;; ;   ;     ;;;;     
;                                                 
;                                                 
;                                                 
*/
// to represent a picture file
class Picture implements ISame {
  String title;
  int width;
  int height;

  Picture(String title, int width, int height) {
    this.title = title;
    this.width = width;
    this.height = height;
  }

  // determine whether this picture is the same as the given object
  boolean same(Object obj){
    return this.title.equals(((Picture)obj).title)
        && this.width == ((Picture)obj).width
        && this.height == ((Picture)obj).height;
  }
}

/*
;                                  
;                                  
;                                  
;   ;                              
;   ;                              
;   ;   ;                          
;   ;  ;;;;   ;;;   ; ;;  ;;       
;   ;   ;    ;   ;  ;;  ;;  ;      
;   ;   ;   ;    ;  ;   ;   ;      
;   ;   ;   ;;;;;;  ;   ;   ;      
;   ;   ;   ;       ;   ;   ;      
;   ;   ;    ;      ;   ;   ;      
;   ;    ;;   ;;;;  ;   ;   ;      
;                                  
;                                  
;                                  
*/
// to represent a salad item
class Item implements ISame {
  String name;
  int pieces;
  int price;

  Item(String name, int pieces, int price) {
    this.name = name;
    this.pieces = pieces;
    this.price = price;
  }

  // determine whether this item is the same as the given object
  boolean same(Object obj){
    return this.name.equals(((Item)obj).name)
        && this.pieces == ((Item)obj).pieces
        && this.price == ((Item)obj).price;
  }
}

/*
;                                                            
;                                                            
;                                                            
;    ;;;;                                                    
;   ;    ;                                                   
;   ;                                                ;       
;   ;       ;;;    ;; ;   ; ;;  ;;     ;;;   ; ;;   ;;;;     
;    ;;    ;   ;  ;  ;;   ;;  ;;  ;   ;   ;  ;;  ;   ;       
;      ;  ;    ; ;    ;   ;   ;   ;  ;    ;  ;   ;   ;       
;       ; ;;;;;; ;    ;   ;   ;   ;  ;;;;;;  ;   ;   ;       
;       ; ;      ;    ;   ;   ;   ;  ;       ;   ;   ;       
;   ;   ;  ;      ;  ;;   ;   ;   ;   ;      ;   ;   ;       
;    ;;;    ;;;;   ;; ;   ;   ;   ;    ;;;;  ;   ;    ;;     
;                     ;                                      
;                ;    ;                                      
;                 ;;;;                                       
*/
// to represent a segment of a road trip
class Segment implements ISame {
  String from;
  String to;
  int miles;
  int gallons;
  int price;

  Segment(String from, String to, int miles, int gallons, int price) {
    this.from = from;
    this.to = to;
    this.miles = miles;
    this.gallons = gallons;
    this.price = price;
  }

  // determine whether this segment is the same as the given object
  boolean same(Object obj){
    return this.from.equals(((Segment)obj).from)
        && this.to.equals(((Segment)obj).to)
        && this.miles == ((Segment)obj).miles
        && this.gallons == ((Segment)obj).gallons
        && this.price == ((Segment)obj).price;
  }
}

/*
;                                                    
;                                                    
;                                                    
;      ;     ;                ;;;;    ;       ;      
;      ;     ;               ;    ;   ;              
;     ; ;    ;              ;      ;  ;              
;     ; ;    ;       ;;;    ;      ;  ; ;;    ;      
;    ;   ;   ;      ;   ;   ;      ;  ;;  ;   ;      
;    ;   ;   ;     ;     ;  ;      ;  ;    ;  ;      
;   ;;;;;;;  ;     ;     ;  ;      ;  ;    ;  ;      
;   ;     ;  ;     ;     ;  ;      ;  ;    ;  ;      
;   ;     ;  ;      ;   ;    ;    ;   ;;  ;   ;      
;  ;       ; ;;;;;;  ;;;      ;;;;    ; ;;    ;      
;                                             ;      
;                                             ;      
;                                           ;;       
*/
// to represent a list of objects
abstract class ALoObj implements ISame{

  // determine whether this list contains the given object
  abstract boolean contains(Object o);

  // determine whether this list of objects is the same as the given Object
  boolean same(Object obj){
    return this.sameLoObj((ALoObj) obj);
  }

  // determine whether this list of objects is the same as the given list of objects
  abstract boolean sameLoObj(ALoObj alist);

  // determine whether this list of objects is the same as the given empty list of objects
  boolean sameMTLoObj(MTLoObj mtlist){ return false; }

  // determine whether this list of objects is the same as the given nonempty list of objects
  boolean sameConsLoObj(ConsLoObj conslist){ return false; } 
}

/*
;                                                              
;                                                              
;                                                              
;   ;       ; ;;;;;;;  ;                ;;;;    ;       ;      
;   ;;     ;;    ;     ;               ;    ;   ;              
;   ;;     ;;    ;     ;              ;      ;  ;              
;   ; ;   ; ;    ;     ;       ;;;    ;      ;  ; ;;    ;      
;   ; ;   ; ;    ;     ;      ;   ;   ;      ;  ;;  ;   ;      
;   ;  ; ;  ;    ;     ;     ;     ;  ;      ;  ;    ;  ;      
;   ;  ; ;  ;    ;     ;     ;     ;  ;      ;  ;    ;  ;      
;   ;   ;   ;    ;     ;     ;     ;  ;      ;  ;    ;  ;      
;   ;   ;   ;    ;     ;      ;   ;    ;    ;   ;;  ;   ;      
;   ;       ;    ;     ;;;;;;  ;;;      ;;;;    ; ;;    ;      
;                                                       ;      
;                                                       ;      
;                                                     ;;       
*/
// to represent an empty list of objects
class MTLoObj extends ALoObj {
  MTLoObj() {}

  // determine whether this list contains the given object
  boolean contains(Object o){ return false; }

  // determine whether this empty list of objects is the same as the given list of objects
  boolean sameLoObj(ALoObj alist){
    return alist.sameMTLoObj(this);
  }

  // determine whether this empty list of objects is the same as the given empty list of objects
  boolean sameMTLoObj(MTLoObj mtlist){ return true; }
}

/*
;                                                                           
;                                                                           
;                                                                           
;     ;;;;                          ;                ;;;;    ;       ;      
;    ;    ;                         ;               ;    ;   ;              
;   ;                               ;              ;      ;  ;              
;   ;         ;;;    ; ;;     ;;;   ;       ;;;    ;      ;  ; ;;    ;      
;   ;        ;   ;   ;;  ;   ;      ;      ;   ;   ;      ;  ;;  ;   ;      
;   ;       ;     ;  ;   ;   ;;     ;     ;     ;  ;      ;  ;    ;  ;      
;   ;       ;     ;  ;   ;    ;;    ;     ;     ;  ;      ;  ;    ;  ;      
;   ;       ;     ;  ;   ;      ;   ;     ;     ;  ;      ;  ;    ;  ;      
;    ;    ;  ;   ;   ;   ;      ;   ;      ;   ;    ;    ;   ;;  ;   ;      
;     ;;;;    ;;;    ;   ;   ;;;    ;;;;;;  ;;;      ;;;;    ; ;;    ;      
;                                                                    ;      
;                                                                    ;      
;                                                                  ;;       
*/
// to represent a nonempty list of objects
class ConsLoObj extends ALoObj {
  Object first;
  ALoObj rest;

  ConsLoObj(Object first, ALoObj rest) {
    this.first = first;
    this.rest = rest;
  }

  // determine whether this list contains the given object
  boolean contains(Object o){
    return ((ISame)this.first).same(o)
        || this.rest.contains(o);
  }

  // determine whether this nonempty list of objects is the same as the given list of objects
  boolean sameLoObj(ALoObj alist){
    return alist.sameConsLoObj(this);
  }
  
  // determine whether this nonempty list of objects is the same 
  // as the given nonempty list of objects
  boolean sameConsLoObj(ConsLoObj conslist){
    return ((ISame)this.first).same(conslist.first)
        && this.rest.same(conslist.rest);
  }
}

/*
;                                                                  
;                                                                  
;                                                                  
;   ;;;;;;                                    ;                    
;   ;                                         ;                    
;   ;                                         ;                    
;   ;     ;     ;  ;;;    ; ;;  ;;    ; ;;    ;    ;;;    ;;;      
;   ;;;;;  ;   ;  ;   ;   ;;  ;;  ;   ;;  ;   ;   ;   ;  ;         
;   ;       ; ;       ;   ;   ;   ;   ;    ;  ;  ;    ;  ;;        
;   ;        ;     ;;;;   ;   ;   ;   ;    ;  ;  ;;;;;;   ;;       
;   ;       ; ;   ;   ;   ;   ;   ;   ;    ;  ;  ;          ;      
;   ;      ;   ;  ;   ;   ;   ;   ;   ;;  ;   ;   ;         ;      
;   ;;;;;;;     ;  ;;;;;  ;   ;   ;   ; ;;    ;    ;;;;  ;;;       
;                                     ;                            
;                                     ;                            
;                                     ;                            
*/

class Examples{
  Examples() {}

  // picture files
  Picture snow  = new Picture("Snow.gif", 400, 200);
  Picture beach = new Picture("Beach.gif", 200, 300);
  Picture bluff = new Picture("Bluff.gif", 200, 600);

  // salad items
  Item tom = new Item("tomato", 3, 50);
  Item pep = new Item("pepper", 2, 60);
  Item rad = new Item("raddish", 6, 10);

  // trip segments
  Segment b2n = new Segment("Boston", "NYC", 200, 10, 210);
  Segment n2t = new Segment("NYC", "Trenton", 120, 5, 200);
  Segment t2p = new Segment("Trenton", "Philly", 80, 2, 180);


  // test the method same in the class Picture:
  boolean testSameP1 = snow.same(new Picture("Snow.gif", 400, 200)) == true;
  boolean testSameP2 = beach.same(new Picture("Snow.gif", 400, 200)) == false;

  // test the method same in the class Item:
  boolean testSameI1 = tom.same(new Item("tomato", 3, 50)) == true;
  boolean testSameI2 = tom.same(rad) == false;

  // test the method same in the class Segment:
  boolean testSameS1 = b2n.same(new Segment("Boston", "NYC", 200, 10, 210)) == true;
  boolean testSameS2 = b2n.same(t2p) == false;

  // an empty list of anything...
  ALoObj mtlist = new MTLoObj();

  // list of pictures
  ALoObj objPictures = new ConsLoObj(snow, 
                         new ConsLoObj(beach,
                           new ConsLoObj(bluff, 
                             new MTLoObj())));

  // list of salad items
  ALoObj objSalad = new ConsLoObj(tom, 
                      new ConsLoObj(pep,
                        new ConsLoObj(rad, 
                          new MTLoObj())));

  // a list of trip segments
  ALoObj objTrip = new ConsLoObj(b2n, 
                     new ConsLoObj(n2t,
                       new ConsLoObj(t2p, 
                         new MTLoObj())));


  // test the method contains for the list of pictures
  boolean testContainsP1 = objPictures.contains(snow) == true;
  boolean testContainsP2 = objPictures.contains(new Picture("Lake", 200, 200)) == false;

  boolean testContainsI1 = objSalad.contains(pep) == true;
  boolean testContainsI2 = objSalad.contains(new Item("Olive", 10, 10)) == false;

  boolean testContainsS1 = objTrip.contains(t2p) == true;
  boolean testContainsS2 = objTrip.contains(new Segment("DC", "Norfolk", 150, 8, 180)) == false;


  boolean testSameLP1 = objPictures.same(new ConsLoObj(snow, 
                                           new ConsLoObj(beach,
                                             new ConsLoObj(bluff, 
                                               new MTLoObj())))) == true;
  boolean testSameLP2 = objPictures.same(new ConsLoObj(snow, new MTLoObj())) == false;

  boolean testSameLI1 = objSalad.same(new ConsLoObj(tom, 
                                        new ConsLoObj(pep,
                                          new ConsLoObj(rad, 
                                            new MTLoObj())))) == true;
  boolean testSameLI2 = objSalad.same(new ConsLoObj(tom, new MTLoObj())) == false;

  boolean testSameLS1 = objTrip.same(new ConsLoObj(b2n, 
                                       new ConsLoObj(n2t,
                                         new ConsLoObj(t2p, 
                                           new MTLoObj())))) == true;
  boolean testSameLS2 = objTrip.same(new ConsLoObj(b2n, new MTLoObj())) == false;

}

