//===================================================== file = tracesim.c =====
//=  A simple trace-driven single-server queueing simulation                  =
//=============================================================================
//=  Notes:                                                                   =
//=    1) This program is adapted from "Figure 1.6" in Simulating Computer    =
//=       Systems, Techniques and Tools by M. H. MacDougall (1987)            =
//=    2) Input to stdin is the trace file which is a list of delta           =
//=       time-stamps to be used for interarrival times                       =
//=    3) Service times as assumed to be deterministic (of value Ta)          =
//=---------------------------------------------------------------------------=
//=  Build: gcc tracesim.c, bcc32 tracesim.c, cl tracesim.c                   =
//=---------------------------------------------------------------------------=
//=  Execute: tracesim < trace.dat                                            =
//=---------------------------------------------------------------------------=
//=  History: KJC (03/09/98) - Genesis                                        =
//=============================================================================

//----- Include files ---------------------------------------------------------
#include <stdio.h>             // Needed for printf() and feof()
#include <stdlib.h>            // Needed for exit()

//----- Constants -------------------------------------------------------------
#define INFINITY   1.0e30      // Infinity time

//===== Main program ==========================================================
void main(void)
{
  double   Ta;                 // Mean time between arrivals (from trace)
  double   Ts = 1.00;          // Mean service time
  unsigned long int K = 10;    // Buffer capacity
  char     instring[80];       // Input string

  double   time = 0.0;         // Simulation time
  double   t1 = 0.0;           // Time for next event #1 (arrival)
  double   t2 = INFINITY;      // Time for next event #2 (departure)
  unsigned long int n = 0;     // Number of customers in the system

  unsigned long int a = 0;     // Number of arrivals
  unsigned long int loss = 0;  // Number of lost customers
  unsigned long int c = 0;     // Number of service completions
  double   b = 0.0;            // Total busy time
  double   s = 0.0;            // Area of number of customers in system
  double   tn = time;          // Variable for "last event time"
  double   tb;                 // Variable for "last start of busy time"
  double   x;                  // Throughput
  double   u;                  // Utilization
  double   l;                  // Mean number in the system
  double   w;                  // Mean residence time

  // Main simulation loop
  while (!feof(stdin))
  {
    if (t1 < t2)                 // *** Event #1 (arrival)
    {
      a++;
      time = t1;
      s = s + n * (time - tn);   // Update area under "s" curve
      if (n <= K)                // Check if can take this customer
        n++;
      else
        loss++;
      tn = time;                 // tn = "last event time" for next event
      scanf("%s \n", instring);
      Ta = atof(instring);
      t1 = time + Ta;
      if (n == 1)
      {
        tb = time;               // Set "last start of busy time"
        t2 = time + Ts;
      }
    }
    else                         // *** Event #2 (departure)
    {
      time = t2;
      s = s + n * (time - tn);   // Update area under "s" curve
      n--;
      tn = time;                 // tn = "last event time" for next event
      c++;                       // Increment number of completions
      if (n > 0)
        t2 = time + Ts;
      else
      {
        t2 = INFINITY;
        b = b + time - tb;      // Update busy time sum if empty
      }
    }
  }

  x = c / time;   // Compute throughput rate
  u = b / time;   // Compute server utilization
  l = s / time;   // Compute mean number in system
  w = l / x;      // Compute mean residence or system time

  // Output results
  printf("=============================================================== \n");
  printf("=       *** Results from 'trace/D/1/K' simulation ***           \n");
  printf("=============================================================== \n");
  printf("=  Total simulated time         = %3.4f sec  \n", time);
  printf("=============================================================== \n");
  printf("=  INPUTS: \n");
  printf("=    Mean service time          = %f sec      \n", Ts);
  printf("=    Buffer size                = %ld cust    \n", K);
  printf("=============================================================== \n");
  printf("=  OUTPUTS: \n");
  printf("=    Number of arrivals         = %ld cust    \n", a);
  printf("=    Percentage lost            = %f %%       \n", 100.0 * loss / a);
  printf("=    Throughput rate            = %f cust/sec \n", x);
  printf("=    Server utilization         = %f %%       \n", 100.0 * u);
  printf("=    Mean number in system      = %f cust     \n", l);
  printf("=    Mean residence time        = %f sec      \n", w);
  printf("=============================================================== \n");
}

