#!/usr/bin/env python

# UMachRep.py

# Two machines, but sometimes break down.  Up time is distributed
# U(0,10), and repair time is distributed U(0,C).  There is only one
# repairperson, and she is not summoned until both machines are down.
# We find the mean cycle time, where a cycle is defined to be the time
# between summons to the repairperson.  We simulate for 1000 cycles, for
# various values of C.

from SimPy.Simulation import *
from random import Random,uniform

class G:  
   Rnd = Random(12345)
   RepairPerson = Resource(1)
   Output = []

class MachineClass(Process):
   MachineList = None  # list of all objects of this class
   NCycles = 0
   StartCurrCycle = 0.0
   TotalCycleTime = 0.0  # total up time for all machines
   NUp = 0  # number of machines currently up
   def __init__(self):
      Process.__init__(self)  
      MachineClass.MachineList.append(self)
      MachineClass.NUp += 1  # start in up mode
   def Run(self):
      while 1:
         yield hold,self,G.Rnd.uniform(0,10)
         MachineClass.NUp -= 1
         if MachineClass.NUp == 1:
            yield passivate,self
         elif G.RepairPerson.n == 1:
            MachineClass.TotalCycleTime += now() - MachineClass.StartCurrCycle
            MachineClass.NCycles += 1
            if MachineClass.NCycles == 1000:
               Mean = MachineClass.TotalCycleTime/MachineClass.NCycles
               G.Output.append(Mean)
               stopSimulation()
            StartCurrCycle = now()
            reactivate(MachineClass.MachineList[1-self.ID])
         yield request,self,G.RepairPerson
         yield hold,self,G.Rnd.uniform(0,MachineClass.C)
         MachineClass.NUp += 1
         yield release,self,G.RepairPerson

def main():
   NCVals = int(sys.argv[1])
   FlNCV = float(NCVals)
   for I in range(NCVals):
      C = I/FlNCV
      initialize()  
      MachineClass.MachineList = []
      for I in range(2):
         M = MachineClass()
         activate(M,M.Run())
      MaxSimtime = 10000.0
      simulate(until=MaxSimtime)
   print G.Output

if __name__ == '__main__':  main()
