#!/usr/bin/env python
### MMC.py simulation of an M/M/c/FCFS/inft/infty queue
from __future__ import generators
from SimPy.Simulation import *
from SimPy.Monitor import *
from random import Random,expovariate,uniform
import unittest

"""Simulation of an M/M/c queue

Jobs arrive at random into a c-server queue with
exponential service-time distribution. Simulate to
determine the average  number and the average time
in the system.

- c = Number of servers = 3
- rate = Arrival rate = 2.0
- stime = mean service time = 1.0

"""
__version__='$Revision: 1.0 $ $Date: 2004-05-15 11:09:34+02 $' ## MMC 1 gav 2002 Sept 17"

class Generator(Process):
    """ generates Jobs at random """
    def __init__(self,maxNumber,rate,stime):
        Process.__init__(self)
        self.name = "gen"
        self.rate = rate
        self.maxNumber =maxNumber
        self.stime=stime

    def execute(self):
        ##print "%7.4f %s starts"%(now(), self.name)
        for i in range(self.maxNumber):
            L = Job("Job "+`i`,self.stime)
            activate(L,L.execute(),delay=0)
            yield hold,self,grv.expovariate(self.rate)
 

class Job(Process):
    """ Jobs request a gatekeeper and hold it for an exponential time """
    jrv = Random(777999)
    def __init__(self,name,stime):
        Process.__init__(self)
        self.name = name
        self.stime=stime
        self.arrTime= now()
        
    def execute(self):       
        global NoInSystem
        self.trace("Hello World")
        NoInSystem +=1
        m.accum(NoInSystem)
        yield request,self,server
        self.trace("At last    ")
        t = Job.jrv.expovariate(1.0/self.stime)
        msT.tally(t)
        yield hold,self,t
        yield release,self,server
        NoInSystem -=1
        m.accum(NoInSystem)
        mT.tally(now()-self.arrTime)
        self.trace("Geronimo   ")
       
    def trace(self,message):
        if TRACING:
            print "%7.4f %6s %10s (%2d)"%(now(),self.name,message,NoInSystem)
TRACING = 1

print __version__
c = 3
stime = 1.0
rate = 2.0
print "%2d servers, %6.4f arrival rate,%6.4f mean service time"%(c,rate,stime)
grv = Random(333555)
NoInSystem = 0
m=Monitor()
mT=Monitor()
msT=Monitor()
server=Resource(c,name='Gatekeeper')
initialize()
g = Generator(maxNumber=10,rate=rate,stime=stime)
activate(g,g.execute(),delay=0)
simulate(until=3000.0)
##scheduler(till=3000.0)
##print now()
print "Average number in the system is %6.4f"%(m.timeAverage(),)
print "Average time in the system is   %6.4f"%(mT.mean(),)
print "Actual average service-time is  %6.4f"%(msT.mean(),)

