// Purpose.  Decorator design pattern lab
//
// Problem.  Inheritance is being used to produce lots of incremental
// customizations.  This is fine - until all the potential permutations of
// options gets out of hand.  Another limitation is the static nature of
// inheritance.  For any particular combination of options to be useable,
// the class hierarchy must explicitly implement that combination.  It would
// be much better if all the individual "options" could each be represented
// by their own class, and, the client could dynamically compose her
// peculiar list of options at run-time.
//
// Assignment.
// o Add an abstract base class Expression with the single pure virtual
//   function evaluate().
// o Function should inherit from Expression (but otherwise remain unchanged).
// o Add a base class Decorator that inherits from Expression.
// o Add an Expression* data member to Decorator (this will be used to remember
//   the "core" object that this Decorator instance is "wrapping").
// o Decorator needs a constructor to initialize this Expression* data member.
// o Decorator's evaluate() should do nothing more than delegate to the
//   Expression* data member.
// o LowCut and HighCut should now inherit from Decorator instead of Function.
// o Eliminate MiddlePass.
// o Add an Expression* parameter to LowCut's and HighCut's constructors (this
//   is the "core" object that this "onion skin" is going to be wrapping).
// o Use a member initialization list to communicate the Expression* parameter
//   to the Decorator base class.
// o LowCut's and HighCut's evaluate() should now call base class Decorator's
//   evaluate() instead of Function's (Function is no longer serving as a base
//   class).
// o Now that LowCut and HighCut no longer have an "isa" relationship to
//   Function (they are now "embellishments" for a core object of type
//   Function), the "lc" and "hc" local variables in main() must have a
//   Function* at the "core" of their constructor arguments.  This could be
//   done with an inline dynamic allocation (new Function).
// o The MiddlePass class no longer exists.  Therefore, the "mp" local variable
//   in main() will be configured by using a layering of "decorator" objects on
//   a "core" object.

#include <iostream.h>
#include <stdlib.h>
#include <time.h>

class Function {
public:
   Function() {
      time_t t;
      srand((unsigned) time(&t)); }
   virtual int evaluate() {
      return rand() % 30; }
};

class LowCut : virtual public Function {
public:
   LowCut( int min ) {
      minimum_ = min; }
   int evaluate() {
      int temp = Function::evaluate();
      if (temp < minimum_) return minimum_;
      return temp; }
protected:
   int  minimum_;
};


class HighCut : virtual public Function {
public:
   HighCut( int max ) {
      maximum_ = max; }
   int evaluate() {
      int temp = Function::evaluate();
      if (temp > maximum_) return maximum_;
      return temp; }
protected:
   int  maximum_;
};

class MiddlePass : public LowCut, public HighCut {
public:
   MiddlePass( int min, int max ) : LowCut(min), HighCut(max) { }
   int evaluate() {
      int temp = LowCut::evaluate();
      if (temp > maximum_) return maximum_;
      return temp; }
};

void main( void )
{
   LowCut      lc( 7 );
   HighCut     hc( 23 );
   MiddlePass  mp( 10, 20 );
   int         i;

   for (i=0; i < 25; i++) cout << lc.evaluate() << " "; cout << endl;
   for (i=0; i < 25; i++) cout << hc.evaluate() << " "; cout << endl;
   for (i=0; i < 25; i++) cout << mp.evaluate() << " "; cout << endl;
}

// 27 18 7 13 19 13 22 16 22 16 17 11 13 13 10 20 22 7 8 23 14 7 29 7 15
// 2 22 23 15 8 16 7 18 7 10 6 21 6 19 3 23 0 20 5 13 23 3 2 6 1
// 18 19 20 20 12 10 14 14 13 14 20 20 20 10 12 18 10 11 10 18 20 20 10 10 10
//
// 11 19 26 27 7 7 25 15 10 9 23 8 10 13 20 18 14 7 7 17 7 7 7 22 25
// 11 4 6 23 22 10 15 23 22 2 12 19 19 12 13 18 6 15 6 1 13 1 10 14 23
// 18 20 20 20 10 20 17 10 20 15 20 17 10 16 10 10 10 17 20 20 11 14 20 10 10
//
// 7 7 11 29 27 7 11 16 27 15 10 26 27 7 11 28 17 7 7 13 11 20 26 21 29
// 22 23 23 23 3 13 17 13 12 0 23 23 3 11 14 23 13 4 0 23 9 22 23 14 14
// 10 10 10 10 10 10 10 10 19 14 14 10 13 10 11 14 20 16 20 20 20 10 18 18 10