
#include <iostream.h>
#include <math.h>

class State {
  public:
    virtual int updateAndCheckTransitions() = 0;
    virtual void enter() = 0;
    virtual void exit() = 0;

	/*** Add any global variables here as static state variables */
	static int water;


  };

/***** Initialize any static global variables */

int State::water = 3;



/*** Replace these with classes for your states ***************/

// This class represents the state in which the flower
// is closed for the night. It transitions to Morning
// when it is light out.
class Night: public State {
  public:
    Night();  
    void enter();
    void exit();
    int updateAndCheckTransitions();
  };

// This class represents the state in which the flower
// is open and facing east. It transitions to Afternoon
// when the sun is to the west.
class Morning: public State {
  public:
    Morning(); 
    void enter();
    void exit();
    int updateAndCheckTransitions();
  };

// This class represents the state in which the flower
// is open and facing west. It transitions to Night
// when it is no longer light for a time.
class Afternoon: public State {
  public:
    Afternoon(); 
    void enter();
    void exit();
    int updateAndCheckTransitions();
  private:
	int count; // How many turns has it been dark (for timeout)
  };

/********** Method definitions for Night class ***************/

Night::Night() {
  }

void Night::enter() {
  cout << "The flower is closed.\n";
  }

// At each cycle ask whether light out
int Night::updateAndCheckTransitions(){
  int light;
  cout << "Is it light out? (1 or 0) ";
  cin >> light;
  if (!light) {
    cout << "The flower is still closed.\n";
	return 0;
    }
  else {
    return 1;
    } 
  }

void Night::exit() {
  cout << "Dawn is breaking...\n";
  }

/********** Method definitions for Morning class ***************/

Morning::Morning() {
  }

void Morning::enter() {
  cout << "The flower is open!\n";
  }

// Prompt for the current sun position.
// If the sun is past 90 degrees, there is a chance
// of going to the Afternoon state. 
int Morning::updateAndCheckTransitions() {
  int degrees;
  cout << "The flower is facing east.\n";
  cout << "Enter current position of sun in degrees:  ";
  cin >> degrees;
  // If the sun is below 90 degrees, it is still morning
  if (degrees < 90) return 1;

  // If the sun is above 110 degrees, it is definitely afternoon (state 2)
  if (degrees >110) return 2;

  // If the sun is between 90 and 110, there is a chance that the flower 
  // will turn west. This chance is proportional to how close to 110 the sun is.
  else {
	// This will change the degrees to a number between 0 and 20.
    int earlyAfternoon = degrees - 90;  

    // Get a random number between 0 and 20.
    int randomNumber = random() % 20;

    if (randomNumber < earlyAfternoon) {
      return 2;  // Go to afternoon
      }
    else {
      return 1;  // Stay in morning
      }
    }
  }

void Morning::exit() {
  cout << "The flower is turning...\n";
  }

/********** Method definitions for Afternoon class ***************/

Afternoon::Afternoon() {
  }

void Afternoon::enter() {
  cout << "The flower is now facing west\n";
  count = 0;
  }

// Prompt for whether it is still light and whether it is raining.
int Afternoon::updateAndCheckTransitions() { 
  int light, raining;
  cout << "The flower is open and facing west.\n";

  // If it is raining, increment the static water level (using the
  // static water variable). If the flower was wilting before, it no
  // longer is.
  cout << "Is it raining? (1 or 0)";
  cin >> raining;
  if (raining) {
	  if (water == 0) cout << "The flower is no longer wilting.\n";
	  water+=5;
  }

  // Otherwise, decrement the water level. If it is 0, the flower
  // will wilt.
  else {
	  if (water > 0) water--;
	  if (water <= 0) cout << "The flower is wilting!\n";
  }

  cout << "Is it still light out? (1 or 0) ";
  cin >> light;
  if (light) count = 0; // Reset count if light

  // To keep the flower from closing if a cloud passes, don't
  // close until it has been dark at least 3 turns in a row.
  if (!light) count++;
  if (count == 3) return 0;
  else return 2;
  }

void Afternoon::exit() {
  cout << "The flower is closing...\n";
  }

/**** Main driver for FSM ****************************/
int main() {

  /* IMPORTANT! Change the 3 to the number of states you have ***/
  State *states[3];

  /* IMPORTANT! Modify this code to create each of your states ***/
  states[0] = new Night;
  states[1] = new Morning;
  states[2] = new Afternoon;

  /**** End of code to modify ****/

  int currentState = 0;
  int nextState;  

  states[0]->enter();
  while(1) {
    nextState = states[currentState]->updateAndCheckTransitions();
    if (nextState != currentState) {
      states[currentState]->exit();
      currentState = nextState;
      states[currentState]->enter();
      }
    }
  }

    

    
