/*
--- CSU213 Fall 2006 Lecture Notes ---------
Copyright 2006 Viera K. Proulx

Lecture 2: September 7, 2006
Part 2: Containment in Unions

Managing ITunes
---------------
*/

/*
 Of course, we do not have just individual songs. 
 Our collection consists of many songs - we really do not know how many.

 Recall from the last lecture:
 -----------------------------
 ;; A Song is (make-song String String Number Number)
 (define-struct song (Title Artist size price))

 ;; Examples:
 (define help (make-song "Help" "Beatles"  3178852 0.99))
 (define hc (make-song "Hotel California" "Eagles" 4405515 0.99))

 Recall from HtDP:
 -----------------
 In HtDP the definition for a list of songs combined the union 
 and the containment:

 ;; A List of Songs is one of
 ;; -- empty
 ;; -- (cons Song [List of Songs])

 where 'cons' just constructs a special type of struct 
 that contains the fields 'first' and 'rest' and comes 
 with its own predicates and selectors - just as we have seen
 with the struct-s we defined ourselves

 ;; Examples:
 (define songs1 (cons help empty))
 (define songs2 (cons hc songs1))
*/

/*
            +--------+               
            | ISongs |<-------------+
            +--------+              |
            +--------+              |
                |                   |
               / \                  |
               ---                  |
                |                   |
       ------------------           |
       |                |           |
  +---------+    +-------------+    |
  | MTSongs |    | ConsSongs   |    |
  +---------+    +-------------+    |
  +---------+  +-| Song first  |    |
               | | ISongs rest |-+  |
               | +-------------+ |  |
               |                 |  |
               v                 +--+
      +---------------+
      | Song          |
      +---------------+
      | String title  |
      | String artist |
      | int size      |
      | double price  |
      +---------------+

*/

// to represent a list of songs in an ITunes collection
interface ISongs {
}

// to represent an empty list of songs
class MTSongs implements ISongs {

  MTSongs() {
  }
}

// to represent a nonempty list of songs
class ConsSongs implements ISongs {
  Song first;
  ISongs rest;

  ConsSongs(Song first, ISongs rest) {
    this.first = first;
    this.rest = rest;
  }
}


/*
;; A Song is (make-song String String Number Number)
(define-struct song (Title Artist size price))

;; Examples:
(define help (make-song "Help" "Beatles"  3178852 0.99))
(define hc (make-song "Hotel California" "Eagles" 4405515 0.99))
*/

/*
+---------------+
| Song          |
+---------------+
| String title  |
| String artist |
| int size      |
| double price  |
+---------------+

*/

// to represent an ITunes song recording
class Song {
  String title;
  String artist;
  int size;
  double price;

  Song(String title, String artist, int size, double price) {
    this.title = title;
    this.artist = artist;
    this.size = size;
    this.price = price;
  }
}

class ExamplesSongs {
  ExamplesSongs(){}

  Song help = new Song("help", "Beatles", 3178852, 0.99);
  Song hc = new Song("Hotel California", "Eagles", 4405515, 0.99);

  ISongs mtsongs = new MTSongs();
  ISongs songs1 = new ConsSongs(this.help, this.mtsongs);
  ISongs songs2 = new ConsSongs(this.hc, this.songs1);
}


// Playing a Game - crossing a minefield
// -------------------------------------

/*
;; A Player is (make-player String Posn)
(define-struct player (name position))
;; A Mine is represented by a Posn

;; Examples:
(define john (make-player "John" (make-posn 50 50)))
(define mine1 (make-posn 20 50))
(define mine2 (make-posn 50 40))
;; ...
*/

/*
+-----------------+
| Player          |
+-----------------+
| String name     |
| CartPt position |
+-----------------+ 

*/

// to represent a player in a minefield crossing game
class Player {
  String name;
  CartPt position;

  Player(String name, CartPt position) {
    this.name = name;
    this.position = position;
  }
}

/*
 We have no idea how many mines are in the minefield
 Again, we need to make a list of all mines

 ;; A Minefield is one of
 ;; -- empty
 ;; -- (cons Posn Minefield)

 (in Java we repace Posn with CartPt)
*/

/*
              +------------+                 
              | IMinefield |<---------------+
              +------------+                |
              +------------+                |
                    |                       |
                   / \                      |
                   ---                      |
                    |                       |
         ----------------------             |
         |                    |             |
  +-------------+    +-----------------+    |
  | MTMinefield |    | ConsMinefield   |    |
  +-------------+    +-----------------+    |
  +-------------+  +-| CartPt first    |    |
                   | | IMinefield rest |-+  |
                   | +-----------------+ |  |
                   |                     |  |
                   v                     +--+
              +--------+
              | CartPt |
              +--------+
              | int x  |
              | int y  |
              +--------+
*/

// to represent a mine field
interface IMinefield {
}

// to represent an empty minefield
class MTMinefield implements IMinefield {

  MTMinefield() {
  }
}

// to represent a nonempty minefield
class ConsMinefield implements IMinefield {
  CartPt first;
  IMinefield rest;

  ConsMinefield(CartPt first, IMinefield rest) {
    this.first = first;
    this.rest = rest;
  }
}


/*
+--------+
| CartPt |
+--------+
| int x  |
| int y  |
+--------+

*/

// to represent a Cartesian point
class CartPt {
  int x;
  int y;

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

class ExamplesMinefields{
  ExamplesMinefields() {}

  Player john = new Player("John", new CartPt(50, 50));
  CartPt mine1 = new CartPt(20, 50);
  CartPt mine2 = new CartPt(50, 40);

  IMinefield mtfield = new MTMinefield();
  IMinefield field1 = new ConsMinefield(this.mine1, this.mtfield);
  IMinefield field2 = new ConsMinefield(this.mine2, this.field1);
}