Skip to content

Instantly share code, notes, and snippets.

@rubcuadra
Last active February 15, 2018 15:46
Show Gist options
  • Save rubcuadra/4b7801665e8b67b9e5af527aa18fcafc to your computer and use it in GitHub Desktop.
Save rubcuadra/4b7801665e8b67b9e5af527aa18fcafc to your computer and use it in GitHub Desktop.
from random import randint,sample,random
from time import sleep
import os, platform
MAX_VELOCITY = 9
MAX_CARS_PER_ROAD=10 #Can change this, always < ROAD_SIZE
P_RANDOM_STOP = 0.15 #Probab Car reduces velocity randomly
MAX_ROA = 1.0 #Rate of Appearance
EMPTY_CHAR = '.'
WAIT_BETWEEN_SIMULATIONS = 1 #Seconds
def cleanConsole():
try:
if platform.system() == "Windows":
os.system('cls')
else:
os.system('clear')
except:
pass
class Car:
def __init__(self, velocity, xPosition,yPosition, coordinator):
self.velocity = velocity
self.updatePos(yPosition,xPosition)
self.coordinator = coordinator
def changeSpeed(self):
ncr = self.nextCarInRange() #Check next car position whitin our range(velocity)
if ncr == 0: #We can accelerate, no cars
if self.velocity < MAX_VELOCITY:
self.velocity+=1
else: #Slow down and finish
self.velocity = ncr - 1
#Probability of slowing down 1 Only if car is moving
if self.velocity>0 and random()<P_RANDOM_STOP:
self.velocity -= 1
# print "RED: [%s,%s]"%(self.y,self.x)
def updatePos(self,y,x):
self.y = y
self.x = x
def move(self):
if self.velocity == 0: return #No need to move
self.coordinator.setInPlace(self,self.y,self.x+self.velocity)
#Si regresa 0 entonces si nos podemos mover,
#Si regresa cualquier otro numero entonces no, es la posicion del prox coche
def nextCarInRange(self):
for i in range(self.velocity+1):
if not self.coordinator.isAvailable(self.y,self.x+i+1): #Solo avanzan en X
return i+1 #Nos regresa la distancia hacia el proximo Coche
return 0
def __str__(self):
return str(self.velocity)
class Playground:
def __init__(self, ROAD_DISTANCE, NUM_ROADS, NEW_CARS_APPEARANCE_PROBABILITY=0):
self.ROAD_DISTANCE = ROAD_DISTANCE
self.NUM_ROADS = NUM_ROADS
self.NEW_CARS_APPEARANCE_PROBABILITY = NEW_CARS_APPEARANCE_PROBABILITY
self.velocities = 0 #Summed velocities
self.totalCars = 0
self.initPlayground()
self.printPlayground()
def initPlayground(self):
emptyRoad = [EMPTY_CHAR]*self.ROAD_DISTANCE
emptyAvenue = [ emptyRoad[:] for _ in range(self.NUM_ROADS) ]
for i in range(self.NUM_ROADS):
#CALCULATE INITIAL CARS POSITIONS
cars_pos = sample( range(0,self.ROAD_DISTANCE), randint(1,MAX_CARS_PER_ROAD) )
#ADD EACH VELOCITY to THE CORRESPONDING CELL
for val in cars_pos:
emptyAvenue[i][val] = Car( randint(0,MAX_VELOCITY) , val,i, self)
self.totalCars += 1
self.avenue = emptyAvenue
def isAvailable(self,y,x):
if y >= self.NUM_ROADS or x >= self.ROAD_DISTANCE:
return True
return self.avenue[y][x] == EMPTY_CHAR
def setInPlace(self,car,y,x): #ys mayores haran que truene o car.y/car.x wrong coordinates
if x >= self.ROAD_DISTANCE: #The car left the road
self.avenue[car.y][car.x] = EMPTY_CHAR
self.totalCars -= 1
return #Maybe add another car
if self.avenue[y][x] != EMPTY_CHAR: #DEBUG ERRORS
print "ERR: [%s,%s] %s -> [%s,%s]"%(car.y,car.x,car.velocity,y,x)
self.avenue[y][x] = car #Move to new position
self.avenue[car.y][car.x] = EMPTY_CHAR #Delete old position
car.updatePos(y,x) #Update, succesfull movement
def carsActions(self):
self.velocities = 0.0 #Hack, usaremos para average speed
#Primero que todos cambien velocidad
for road in self.avenue:
for car in road:
if car != EMPTY_CHAR:
car.changeSpeed()
self.velocities += float(car.velocity) #Temporal
#Despues que todos se muevan
for road in self.avenue:
for car in reversed(road): #Mover de derecha a izq
if car != EMPTY_CHAR:
car.move()
def dispatchCars(self):
for i,road in enumerate(self.avenue):
#If we can add & % tells us to add
if road[0]==EMPTY_CHAR and random()<self.NEW_CARS_APPEARANCE_PROBABILITY:
road[0] = Car( randint(0,MAX_VELOCITY) ,0,i, self)
self.totalCars += 1
def showMenu(self):
c = "r"
while c != "q":
self.printPlayground()
c = raw_input("Press the key for any action:\n\tq\tExit\n\tw\t-ROA\n\te\t+ROA\n\tr\tResume\nYour Choice: ")
if c == "w":
self.decreaseTraffic()
elif c == "e":
self.increaseTraffic()
elif c == "r" or c == "q":
break
else:
print "Wrong Input"
if c == "r":
self.startSimulation()
else:
print "Bye!"
def startSimulation(self):
try:
while True:
self.carsActions() #Accelerate/Move
self.dispatchCars() #Appear New Cars
self.printPlayground()
sleep(WAIT_BETWEEN_SIMULATIONS)
except KeyboardInterrupt:
self.showMenu()
def printPlayground(self):
cleanConsole()
print
for road in self.avenue:
for cell in road:
print cell,
print
print
self.printStats()
def printStats(self):
print "Number of Roads: %s, Road Size: %s"%(self.NUM_ROADS,self.ROAD_DISTANCE)
print "Cars rate of appearance: %s"%self.NEW_CARS_APPEARANCE_PROBABILITY
print "Probability car reduces speed randomly: %s"%P_RANDOM_STOP
print "Number of Cars %s"%self.totalCars
print "Average Velocity %s"%(0 if self.totalCars<=0 else self.velocities/float(self.totalCars))
print "\nPress 'Ctrl + C' for more\n"
def increaseTraffic(self):
self.NEW_CARS_APPEARANCE_PROBABILITY+=0.05
if self.NEW_CARS_APPEARANCE_PROBABILITY>MAX_ROA: self.NEW_CARS_APPEARANCE_PROBABILITY = MAX_ROA
def decreaseTraffic(self):
self.NEW_CARS_APPEARANCE_PROBABILITY-=0.05
if self.NEW_CARS_APPEARANCE_PROBABILITY<0.05: self.NEW_CARS_APPEARANCE_PROBABILITY = 0
if __name__=="__main__":
pg = Playground(100,30)
pg.showMenu()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment