// arrival.cc: the Arrival class.

#include <math.h>
#include "event.h"
#include "evlist.h"
#include "random.h"
#include "car.h"
#include "carqueue.h"
#include "stats.h"
#include "pump.h"
#include "pstand.h"
#include "main.h"
#include "arrival.h"

// doesCarBalk:
//
// The probability that a car leaves without buying gas (i.e., balks) grows
// larger as the queue length gets larger, and grows smaller when the car
// requires a greater number of litres of gas, so that:
// (1) there is no balking if the queue length is zero, and
// (2) otherwise, the probability of NOT balking is
//      (40 + litres)/(25 * (3 + queueLength))
int Arrival::doesCarBalk (double litres, int queueLength) {
   return queueLength > 0 && (sim->balkingStream->nextDouble()
      > (sim->balkA + litres) / (sim->balkB * (sim->balkC + queueLength)));
}

double Arrival::interarrivalTime () {
   return - sim->meanInterarrivalTime
         * log (sim->arrivalStream->nextDouble());
}

void Arrival::makeItHappen () {
   // Create and initialize a new auto record.
   Car *arrivingCar = new Car ();
   sim->stats->countArrival();
   const double litres = arrivingCar->getLitresNeeded();
   if (doesCarBalk (litres, sim->carQueue->getQueueSize())) {
      sim->stats->accumBalk (litres);
      delete arrivingCar;
   }
   else {
      arrivingCar->setArrivalTime (sim->simulationTime);
      if (sim->pumpStand->aPumpIsAvailable())
         sim->pumpStand->takeAvailablePump()->startService (arrivingCar);
      else
         sim->carQueue->insert (arrivingCar);
   }
   
   // Schedule the next arrival, reusing the current event object.
   setTime (sim->simulationTime + interarrivalTime());
   sim->eventList->insert (this);   
}

