# Travis Scrimshaw
# simulator.py - Executable file to run the simulator
# Notes: turnSpeed is measured in radians

from classes import *
import random as Rand
import numpy as N
import pylab as P
import visual as V
import functions as F
import string as Str

birdList = []
initPos = []
initVel = []
turnSpeed = []
initHunger = []
foodPer = []
initEnergy = []
sizes = []
agg = []
maxSpeed = []
numKilled = 0
startTime = 0.0

# Set the default values
numPerches, size, orbitSize, food, maxFood, X, Y, Z, numBirds, iX, iY, iZ, r, ts, rts, h, rh, fp, \
  rfp, e, re, si, rsi, a, ra, s, rs, ms, rms, timeStep = F.DefaultValues()

# Set the default params
dispPath, type = F.DefaultParams()

feeder = Feeder(numPerches, size, orbitSize, food, maxFood, X, Y, Z)

for i in range(0, numBirds):
	initPos.append(Vector(iX + r*(.5-Rand.random())*2, iY + r*(.5-Rand.random())*2, iZ + r*(.5-Rand.random())*2))
	initVel.append(Vector(s*(.5-Rand.random())*2, s*(.5-Rand.random())*2, s*(.5-Rand.random())*2))
	turnSpeed.append(ts + rts*(0.5-Rand.random())*2)
	initHunger.append(h + rh*(0.5-Rand.random())*2)
	foodPer.append(fp + rfp*(0.5-Rand.random())*2)
	initEnergy.append(e + re*(0.5-Rand.random())*2)
	sizes.append(si + rsi*(0.5-Rand.random())*2)
	agg.append(a + ra*(0.5-Rand.random())*2)
	maxSpeed.append(ms + rms*(0.5-Rand.random())*2)
# For

# Set up the bird list
for i in range(0, numBirds):
	birdList.append(Bird(i, feeder, initPos[i], initVel[i], turnSpeed[i], initHunger[i], foodPer[i], initEnergy[i], maxSpeed[i], sizes[i], agg[i]))
# For

poll = ' '

while poll != 'q':
	print "[R]eset simulation"
	print "[C]ontinue simulation"
	print "[P]rint data"
	# print "[H]istogram"
	print "[V]isual"
	print "[O]ptions"
	print "[Q]uit"
	poll = Str.lower(raw_input("Which option do you want: "))

	# Print all the hunger percentage of the birds
	if poll == 'p':
		for bird in birdList:
			print bird
		# For
		print `numKilled` + " birds have been killed."
	# If

	# Reset the simulation
	if poll == 'r':
		birdList = []
		initPos = []
		initVel = []
		turnSpeed = []
		initHunger = []
		foodPer = []
		initEnergy = []
		maxSpeed = []
		sizes = []
		agg = []
		numKilled = 0
		startTime = 0

		for i in range(0, numBirds):
			initPos.append(Vector(iX + r*(.5-Rand.random())*2, iY + r*(.5-Rand.random())*2, iZ + r*(.5-Rand.random())*2))
			initVel.append(Vector(s*(.5-Rand.random())*2, s*(.5-Rand.random())*2, s*(.5-Rand.random())*2))
			turnSpeed.append(ts + rts*(0.5-Rand.random())*2)
			initHunger.append(h + rh*(0.5-Rand.random())*2)
			foodPer.append(fp + rfp*(0.5-Rand.random())*2)
			initEnergy.append(e + re*(0.5-Rand.random())*2)
			sizes.append(si + rsi*(0.5-Rand.random())*2)
			agg.append(a + ra*(0.5-Rand.random())*2)
			maxSpeed.append(ms + rms*(0.5-Rand.random())*2)
		# For

		# (Re) Set up the bird list
		for i in range(0, numBirds):
			birdList.append(Bird(i, feeder, initPos[i], initVel[i], turnSpeed[i], initHunger[i], \
			foodPer[i], initEnergy[i], maxSpeed[i], sizes[i], agg[i]))
		# For
	# If

	# Visual simulation
	if poll == 'v':
		# Set up the visual part
		V.scene.title = "Birds"
		V.scene.center = V.vector(feeder.pos.vec)
		V.scene.background = (1, 1, 1)
		V.scene.forward = (0, 1, -0.5)
		V.scene.height = 600
		V.scene.width = 600

		# Draw axes
		V.curve(pos = [ (-25, 0, 0), (25, 0, 0) ], color = (0, 0, 0), radius = 0.2)
		V.curve(pos = [ (0, -25, 0), (0, 25, 0) ], color = (0, 0, 0), radius = 0.2)
		V.curve(pos = [ (0, 0, -25), (0, 0, 25) ], color = (0, 0, 0), radius = 0.2)

		feederBall = V.sphere(pos=feeder.pos.vec, radius=feeder.size, color=V.color.red)
		birdLine = []
		birdBall = []
		#birdAvoid = []
		#birdTarget = []
		#birdNewVel = []
		for bird in birdList:
			if dispPath == True:
				birdLine.append(V.curve( color = V.color.red, radius=0.1 ))
			# If
			birdBall.append(V.sphere(pos=bird.pos.vec, radius=bird.size, color=(0, 0, 1.0/(bird.ID+1)**.2)))
			#birdAvoid.append(V.curve(pos=[(0,0,0), (0,0,0)], color = V.color.red, radius=.1))
			#birdTarget.append(V.curve(pos=[(0,0,0), (0,0,0)], color = V.color.green, radius=.07))
			#birdNewVel.append(V.curve(pos=[(0,0,0), (0,0,0)], color = V.color.black, radius=.05))
		# For

		while 1:
			V.rate(1/timeStep)
			feeder.regenerage("infinite", timeStep, numBirds)
			for bird in birdList:
				retVal = bird.eval(timeStep, birdList)
				if retVal == False:
					birdList.remove(bird)
					numKilled += 1
				else:
					if bird.hunger <= 0:
						birdBall[bird.ID].color = V.color.green
					else:
						birdBall[bird.ID].color = V.color.blue
					# If
					if dispPath == True:
						birdLine[bird.ID].append(pos=bird.pos.vec, color=(0, 0, 1.0/(bird.ID+1)**.2))
					# If
					birdBall[bird.ID].pos = bird.pos.vec
					#birdAvoid[bird.ID].pos[0] = bird.pos.vec
					#birdAvoid[bird.ID].pos[1] = (bird.pos + bird.avoid).vec
					#birdTarget[bird.ID].pos[0] = bird.pos.vec
					#birdTarget[bird.ID].pos[1] = (bird.pos + bird.target).vec
					#birdNewVel[bird.ID].pos[0] = bird.pos.vec
					#birdNewVel[bird.ID].pos[1] = (bird.pos + bird.newVel).vec
			# For
		# While
		startTime += endTime
	# If

	# Continue the simulation
	if poll == 'c':
		endTime = float(raw_input("How long do you want the simulation to run: "))

		for curTime in N.arange(startTime, startTime + endTime, timeStep):
			feeder.regenerage("infinite", timeStep, numBirds)

			for bird in birdList:
				retVal = bird.eval(timeStep, birdList)
				if retVal == False:
					birdList.remove(bird)
					numKilled += 1
			# For
		# For
	# If

	# Change options
	if poll == 'o':
		polling = ' '
		while polling != 'q':
			print "Options to change: "
			print `numPerches` + " - number of perches - [np]"
			print `size` + " - size of the feeder - [fs]"
			print `orbitSize` + " - orbit size of the feeder - [os]"
			print `food` + " - inital food of the feeder - [f]"
			print `maxFood` + " - maximum food of the feeder - [mf]"
			print `X` + ", " + `Y` + ", " + `Z` + ", " + " - position of the feeder - [fpos]"
			print `numBirds` + " - number of birds - [nb]"
			print `iX` + ", " + `iY` + ", " + `iZ` + ", " + " - center position of the birds - [bpos]"
			print `r` + " - inital range of the birds - [r]"
			print `ts` + " - average turn speed of the birds - [ts]"
			print `rts` + " - range of the turn speeds of the birds - [rts]"
			print `h` + " - inital hunger of the birds - [h]"
			print `rh` + " - range of the inital hunger of the birds - [rh]"
			print `fp` + " - average food percentage of the birds - [fp]"
			print `rfp` + " - range of the food percentage of the birds - [rfp]"
			print `e` + " - average inital energy of the birds - [e]"
			print `re` + " - range of inital energy of the birds - [re]"
			print `si` + " - average size of the birds - [si]"
			print `rsi` + " - range of the size of the birds - [rsi]"
			print `a` + " - average aggression of the birds - [a]"
			print `ra` + " - range of aggression of the birds - [ra]"
			print `s` + " - average speed of the birds - [s]"
			print `rs` + " - range of speeds of the birds - [rs]"
			print `ms` + " - average maximum speed of the birds - [ms]"
			print `rms` + " - range of maximum speed of the birds - [rms]"
			print `timeStep` + " - integration timestep - [t]"
			print "Return back to the main menu - [q]"
			polling = Str.lower(raw_input("Which option would you like to do: "))

			if polling == 'np':
				numPerches = float(raw_input("How many perches: "))
			elif polling == 'fs':
				size = float(raw_input("Size of the feeder: "))
			elif polling == 'os':
				orbitSize = float(raw_input("Orbit size for the feeder: "))
			elif polling == 'f':
				food = float(raw_input("Inital food of the feeder: "))
			elif polling == 'mf':
				maxFood = float(raw_input("Maximum food of the feeder: "))
			elif polling == 'fpos':
				X = float(raw_input("X position of the feeder: "))
				Y = float(raw_input("Y position of the feeder: "))
				Z = float(raw_input("Z position of the feeder: "))
			elif polling == 'nb':
				numBirds = int(raw_input("How many birds: "))
			elif polling == 'bpos':
				iX = float(raw_input("Center X of the birds: "))
				iY = float(raw_input("Center Y of the birds: "))
				iZ = float(raw_input("Center Z of the birds: "))
			elif polling == 'r':
				r = float(raw_input("Inital range of the birds: "))
			elif polling == 'ts':
				ts = float(raw_input("Average turn speed of the birds: "))
			elif polling == 'rts':
				rts = float(raw_input("Range of the turn speeds of the birds: "))
			elif polling == 'h':
				h = float(raw_input("Average inital hunger of the birds: "))
			elif polling == 'rh':
				rh = float(raw_input("Range of the inital hunger of the birds: "))
			elif polling == 'fp':
				fp = float(raw_input("Average food percentage of the birds: "))
			elif polling == 'rfp':
				rfp = float(raw_input("Range of the food percentage of the birds: "))
			elif polling == 'e':
				e = float(raw_input("Average inital energy of the birds: "))
			elif polling == 're':
				re = float(raw_input("Range of the inital energy of the birds: "))
			elif polling == 'si':
				si = float(raw_input("Average size of the birds: "))
			elif polling == 'rsi':
				rsi = float(raw_input("Range of the sizes of the birds: "))
			elif polling == 'a':
				a = float(raw_input("Average aggression of the birds: "))
			elif polling == 'ra':
				ra = float(raw_input("Range of aggression of the birds: "))
			elif polling == 's':
				s = float(raw_input("Average speed of the birds: "))
			elif polling == 'rs':
				rs = float(raw_input("Range of the speeds of the birds: "))
			elif polling == 'ms':
				ms = float(raw_input("Average maximum speed of the birds: "))
			elif polling == 'rms':
				rms = float(raw_input("Range of the maximum speeds of the birds: ")) 
			elif polling == 't':
				timeStep = float(raw_input("Time step: "))
			# If-Else
		# While
	# If
# While
