/*
Date: Fri, 18 Feb 2005 21:56:28 +0000 (UTC)
From: John B. Clements <clements@ccs.neu.edu>
Newsgroups: ccs.courses.csu213
Subject: lecture code 2005-02-17
*/

// a tile in a Carcassonne map 
class Tile {
 Posn p;
 Follower f;
 String description;
                 
 Tile(Posn p, Follower f, String description) {
  this.p = p;
  this.f = f;
  this.description = description;
 }
}
 
 // a Carcassonne follower 
class Follower {
 String color;
 String name;
 
 Follower(String color, String name) {
  this.color = color;
  this.name = name;
 }
}

// Cartesian coordinates
class Posn {
  int x;
  int y;


  Posn(int x, int y) {
    this.x = x;
    this.y = y;
  }
}

// interface for a Map operation
interface IGetSomething {
  Object poke(Object in);
}

// interface for a Sort operation
interface ISortSomething {
  boolean bigger(Object a, Object b);
}

// represents a class that compares two posns
class ComparePosns implements ISortSomething{
  boolean bigger(Object a, Object b){
    return ((Math.sqrt ((((Posn)a).x * ((Posn)a).x) +   
            (((Posn)a).y  *  ((Posn)a).y))) >
        (Math.sqrt(((Posn) b).x * ((Posn) b).x) + (((Posn) b).y * ((Posn) b).y)));
         
  }
}

abstract class LObjects_2 {
   // get something from each item on this list
   abstract LObjects_2 get(IGetSomething x);
   // sorts a list of objects
   abstract LObjects_2 sort(ISortSomething f);
   // insert an element into a sorted list
   abstract LObjects_2 insert(ISortSomething f, Object x);
}

class ConsO_2 extends LObjects_2 {
  Object first;
  LObjects_2 rest;

  ConsO_2(Object first, LObjects_2 rest) {
    this.first = first;
    this.rest = rest;
  }

   LObjects_2 get(IGetSomething x) { 
    return new ConsO_2(  x.poke(this.first), this.rest.get(x) ); 
   }

   LObjects_2 sort(ISortSomething f){
     f
     this.first
     this.rest.sort()
   }

   LObjects_2 insert(ISortSomething f, Object x){
     f
     x
     this.first
     this.rest.insert(...)
   }
}

class Mt_2 extends LObjects_2 {

 Mt_2() { }

 LObjects_2 get(IGetSomething x) { 
     return this; // which is the empty list 
   }

 LObjects_2 sort(ISortSomething f){
   }

 LObjects_2 insert(ISortSomething f, Object x){
   f
   x}
}

class Examples_2 {
  LObjects_2 lot = // a list of tiles 
        new ConsO_2(new Tile(new Posn(1,2),new Follower("green","mf"),"castle"),
                  new ConsO_2(new Tile(new Posn(7,8),new Follower("red","mf"),"castle"),
                            new ConsO_2(new Tile(new Posn(-1,2),new
Follower("red","jc"),"road"),
                                      new Mt_2())));
  LObjects_2 lof = // a list of followers
        new ConsO_2(new Follower("green","mf"),
                  new ConsO_2(new Follower("red","mf"),
                            new ConsO_2(new Follower("red","jc"),
                                      new Mt_2())));

  LObjects_2 lop = // a list of posns
        new ConsO_2(new Posn(2,2),
                  new ConsO_2(new Posn(7,8),
                            new ConsO_2(new Posn(-1,2),
                                      new Mt_2())));

 // LObjects_2 lof_computed = // use the get method now:
//      lot.get(new GetFollower());

  //LObjects_2 lop_computed =  
//      lot.get(new GetPosn());

  LObjects_2 test = this.lop.sort(new ComparePosns());
  // should get back:
  LObjects_2 test_result = new Cons0_2(new Posn(-1,2),new Cons0_2(new Posn(2,2),
                                                                  new Cons0_2(new
Posn(7,8),
                                                                              new
Mt_2())));

  LObjects_2 s3 = new Cons0_2(new Posn(-1,2),
                              new Cons0_2(new Posn(2,2),
                                          new Cons0_2(new Posn(7,8),
                                                      new Mt_2()))).insert(new Posn(5,5));
  // should be
  LObjects_2 s4 = new Cons0_2(new Posn(-1,2),
                              new Cons0_2(new Posn(2,2),
                                          new Cons0_2(new Posn(5,5),
                                          new Cons0_2(new Posn(7,8),
                                                      new Mt_2()))));
}



