// L-16 MCS 360 Wed 29 Sep 2010 : printer_queue.cpp

/* A very basic simulation of a printer queue stores jobs
   as struct of arrival time and size (number of pages).

Given that printer jobs range in size between 1 and 10 pages,
and arrive between every 10 and 20 minutes apart from each other,
we simulate how long it takes on average for the printer to run
out of paper.  We assume only one user for the printer. */

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <queue>
using namespace std;

// parameters for the simulation
// 1. size of the jobs in [1,10]
#define min_size 1
#define max_size 10
// 2. arrival time between jobs
#define min_time 10
#define max_time 20
// 3. capacity of printer
#define capacity 100

struct Job
{
   int arrival; // arrival time in minutes
   int size;    // size of job in pages
};

int random_number(int a, int b);
// returns a random integer number, 
// uniformly distributed between a and b

queue<Job> generate_jobs(int n);
// returns a queue of n jobs

void process_jobs(queue<Job> q);
// runs the simulation, processing jobs in q

int main()
{
   int n;

   cout << "Give number of jobs : "; cin >> n;
   
   srand(time(0));
   queue<Job> q = generate_jobs(n);
   process_jobs(q);

   return 0;
}

int random_number(int a, int b)
{
   int r = rand() % (b-a+1);
   return a + r;
}

queue<Job> generate_jobs(int n)
{
   queue<Job> q;

   int elapsed = 0;
   for(int i=0; i<n; i++)
   {
      Job J;
      J.size = random_number(min_size,max_size);
      cout << "job " << i << " has size " << J.size;
      J.arrival = elapsed + random_number(min_time,max_time);
      cout << " arrived at time " << J.arrival << endl;
      elapsed = J.arrival;
      q.push(J);
   }
   return q;
}

void process_jobs(queue<Job> q)
{
   int printed = 0;
   int packs = 0;

   for(int i=0; !q.empty(); q.pop(), i++)
   {
      Job J = q.front();
      cout << "job " << i
           << " arrived at " << J.arrival
           << " has size " << J.size << endl;
      printed = printed + J.size;
      if(printed > capacity)
      {
         cout << "please provide paper ..." << endl;
         cout << "continue ? (y/n) ";
         char c; cin >> c;
         if(c != 'y') break;

         printed = printed - capacity;
         packs = packs + 1;
      }
   }
   cout << "printed " << packs*capacity + printed
        << " pages" << endl;
}

