This examples models a gas station and cars that arrive at the station for
refueling.

The gas station has a limited number of fuel pumps and a fuel tank that is
shared between the fuel pumps. The gas station is thus modeled as
Resource. The shared fuel tank is modeled
with a Container.

Vehicles arriving at the gas station first request a fuel pump from the
station. Once they acquire one, they try to take the desired amount of fuel
from the fuel pump. They leave when they are done.

The gas stations fuel level is reqularly monitored by gas station control.
When the level drops below a certain threshold, a tank truck is called to
refuel the gas station itself.

"""Gas Station Refueling exampleCovers:- Resources: Resource- Resources: Container- Waiting for other processesScenario: A gas station has a limited number of gas pumps that share a common fuel reservoir. Cars randomly arrive at the gas station, request one of the fuel pumps and start refueling from that reservoir. A gas station control process observes the gas station's fuel level and calls a tank truck for refueling if the station's level drops below a threshold."""importitertoolsimportrandomimportsimpyRANDOM_SEED=42GAS_STATION_SIZE=200# litersTHRESHOLD=10# Threshold for calling the tank truck (in %)FUEL_TANK_SIZE=50# litersFUEL_TANK_LEVEL=[5,25]# Min/max levels of fuel tanks (in liters)REFUELING_SPEED=2# liters / secondTANK_TRUCK_TIME=300# Seconds it takes the tank truck to arriveT_INTER=[30,300]# Create a car every [min, max] secondsSIM_TIME=1000# Simulation time in secondsdefcar(name,env,gas_station,fuel_pump):"""A car arrives at the gas station for refueling. It requests one of the gas station's fuel pumps and tries to get the desired amount of gas from it. If the stations reservoir is depleted, the car has to wait for the tank truck to arrive. """fuel_tank_level=random.randint(*FUEL_TANK_LEVEL)print('%s arriving at gas station at %.1f'%(name,env.now))withgas_station.request()asreq:start=env.now# Request one of the gas pumpsyieldreq# Get the required amount of fuelliters_required=FUEL_TANK_SIZE-fuel_tank_levelyieldfuel_pump.get(liters_required)# The "actual" refueling process takes some timeyieldenv.timeout(liters_required/REFUELING_SPEED)print('%s finished refueling in %.1f seconds.'%(name,env.now-start))defgas_station_control(env,fuel_pump):"""Periodically check the level of the *fuel_pump* and call the tank truck if the level falls below a threshold."""whileTrue:iffuel_pump.level/fuel_pump.capacity*100<THRESHOLD:# We need to call the tank truck now!print('Calling tank truck at %d'%env.now)# Wait for the tank truck to arrive and refuel the stationyieldenv.process(tank_truck(env,fuel_pump))yieldenv.timeout(10)# Check every 10 secondsdeftank_truck(env,fuel_pump):"""Arrives at the gas station after a certain delay and refuels it."""yieldenv.timeout(TANK_TRUCK_TIME)print('Tank truck arriving at time %d'%env.now)ammount=fuel_pump.capacity-fuel_pump.levelprint('Tank truck refuelling %.1f liters.'%ammount)yieldfuel_pump.put(ammount)defcar_generator(env,gas_station,fuel_pump):"""Generate new cars that arrive at the gas station."""foriinitertools.count():yieldenv.timeout(random.randint(*T_INTER))env.process(car('Car %d'%i,env,gas_station,fuel_pump))# Setup and start the simulationprint('Gas Station refuelling')random.seed(RANDOM_SEED)# Create environment and start processesenv=simpy.Environment()gas_station=simpy.Resource(env,2)fuel_pump=simpy.Container(env,GAS_STATION_SIZE,init=GAS_STATION_SIZE)env.process(gas_station_control(env,fuel_pump))env.process(car_generator(env,gas_station,fuel_pump))# Execute!env.run(until=SIM_TIME)