// Programmer:		Gregory A. Perkins
// Class:			CS 66
// Due:				3 March 1997

// This program accepts the probability that a player will win a racquetball service
// on his/her serve for two players.  It then prompts the user to enter the number of
// games to play.  Upon completion, the program displays the number of games won by
// each player and the number of shutouts achieved by each player.

// rball2.cc -- structuring racquetball simulation using classes.
// by: John Zelle (2/27/97)
// Code for SimStat class has been excised.

#include 
#include 
#include 

//==========================> RBallGame Class <============================
class RBallGame
{
public:
  
  RBallGame(float Aprob, float Bprob);
  int isOver();
  void doRally();
  int Ascore();
  int Bscore();

private:
  int serverWins(float prob);
  float _Aprob;
  float _Bprob;
  int _Ascore;
  int _Bscore;
  int _Aserving;
};

//==========================> RBallGame Implementation <===================

//=================> Constructor <======================
RBallGame::RBallGame( float A, float B)
{
  _Aprob = A;
  _Bprob = B;
  _Ascore = _Bscore = 0;
  _Aserving = 1;
}

//==================> Ascore() <==========================
int
RBallGame::Ascore()
{
  return _Ascore;
}

//=================> Bscore() <===========================
int
RBallGame::Bscore()
{
  return _Bscore;
}

//================> isOver() <============================
int
RBallGame::isOver()
{
  return   (_Ascore >= 21) 
        || (_Bscore >= 21)
        || ((_Ascore == 11) && (_Bscore == 0))
        || ((_Bscore == 11) && (_Ascore == 0));
}

//================> doRally() <=========================
void
RBallGame::doRally()
{
  if (_Aserving)
    { 
      if (serverWins(_Aprob))
          _Ascore++;
      else
          _Aserving = 0;
    }
  else
    {
      if (serverWins(_Bprob))
          _Bscore++;
      else
          _Aserving = 1;
    }
}

//================> severWins() <========================
int 
RBallGame::serverWins(float Prob)
{
  return (rand() <= Prob * RAND_MAX);
}

//===============================> SimStats Class <=======================
class SimStats
{
	// CLASSINV:  _aWins >= 0 &&
	//            _bWins >= 0 &&
	//            _aShuts >= 0 &&
	// 			  _bShuts >= 0
	
	public:
		SimStats();
		void Update(RBallGame aGame);
		// POST:	(if player A won the game ==> _aWins += 1 &&
		//          if it was a shutout ==> _aShuts += 1)  ||
		//			(if player B won the game ==> _bWins += 1 &&
		//			if it was a shutout ==> _bShuts += 1)
		
		void PrintSummary();
		// POST:    Player A's wins and shutouts displayed to std output device
		//   		Player B's wins and shutouts displayed to std output device
		
	private:
		int _aWins;				//  Player A wins
		int _bWins;				//  Player B wins
		int _aShuts;			//  Player A shutouts
		int _bShuts;			//  Player B shutouts
};

//====================>  SimStats Implementation <========================

//====================>  Constructor  <===================================
SimStats::SimStats()
{
	_aWins = _bWins = 0;			//  Initialize Player A & B wins to zero
	_aShuts = _bShuts = 0;			//  Initialize Player A & B shutouts to zero
}

//====================>  Update()  <======================================
void SimStats::Update(RBallGame aGame)
{
	if (aGame.Ascore() > aGame.Bscore())		//  if player A won the game
	{
		_aWins++;								//  increment player A score by one
		
		if (aGame.Bscore() == 0)				//  if it was a shutout
			_aShuts++;							//  increment player A shutouts by one
	}
	else										//  if player B won the game
	{
		_bWins++;								// increment player B score by one
		
		if (aGame.Ascore() == 0)				//  if it was a shutout
			_bShuts++;							//  increment player B shutouts by one
	}
	
	return;
}

//======================>  PrintSummary()  <==============================
void SimStats::PrintSummary()
{
	cout << "Player A won "					//  Player A
		 << _aWins							//  display wins
		 << " game(s)."
		 << endl
		 << _aShuts							//  display shutouts
		 << " of them were shutouts."
		 << endl
		 << endl
		 << "Player B won "					//  Player B
		 << _bWins							//  display wins
		 << " game(s)."
		 << endl
		 << _bShuts							//  display shutouts
		 << " of them were shutouts."
		 << endl;
		 
	return;
}

//====================================> main <==================================

void getInputs( float& Aprob, float& Bprob, int& numGames );

void main()
{ 
  srand(clock());								//  seed the random number generator

  float Aprob, Bprob;
  int numGames;
  SimStats stats;

  getInputs( Aprob, Bprob, numGames);
  for(int i = 0; i < numGames; i++)
    { 
      RBallGame theGame(Aprob, Bprob);
      while ( !theGame.isOver() )
	       theGame.doRally();
      stats.Update(theGame);
    }
  stats.PrintSummary();
}

//==============================> getInputs <==================
void
getInputs( float& A, float& B, int& N )
{
  cout << "Enter A prob: ";
  cin >> A;
  cout << "Enter B prob: ";
  cin >> B;
  cout << "\nHow many games> ";
  cin >> N;
}