Esempio n. 1
0
def parse_input(input_data):
    lines = input_data.split("\n")

    parts = lines[0].split()
    facility_count = int(parts[0])
    customer_count = int(parts[1])

    facilities = []
    for i in range(1, facility_count + 1):
        parts = lines[i].split()
        facilities.append(
            Facility(
                index=i - 1,
                setup_cost=float(parts[0]),
                capacity=int(parts[1]),
                location=Point(float(parts[2]), float(parts[3])),
            ))

    customers = []
    for i in range(facility_count + 1, facility_count + 1 + customer_count):
        parts = lines[i].split()
        customers.append(
            Customer(
                index=i - 1 - facility_count,
                demand=int(parts[0]),
                location=Point(float(parts[1]), float(parts[2])),
            ))

    return customers, facilities
Esempio n. 2
0
 def __init__(self):
     self.velocity = Vector()
     self.pos = Point()
     self.mass = 1
     self.dampingBase = 8  # base deaccleration
     self.maxVelocity = 5
     self.acceleration = 15
     self.string = False
Esempio n. 3
0
def validate_polygon(polygons):

    print(polygons)
    for index, polygon in enumerate(polygons):
        dots = []
        last_segments = []
        for ii in range(len(polygon[0])):
            dot = Point(polygon[0][ii], polygon[1][ii])
            dots.append(dot)
        print(dots)
        if len(dots) < 4:
            return 1, index
        for ii in range(len(dots)-1):
            segment = (dots[ii], dots[ii+1])
            if len(last_segments) > 0:
                for ind, seg in enumerate(last_segments):
                    if ii - ind == 1:
                        break
                    if intersect_segments(seg[0], seg[1], segment[0], segment[1]):
                        return 2, index
            last_segments.append(segment)

    return 0, 0
Esempio n. 4
0
    def codify(self, latitude=None, longitude=None, country_strings=(),
               region_strings=(), verbose=False, limit=5, **ignored):
        try:
            latitude = float(latitude)
            assert(-90.0 <= latitude <= 90.0)
        except:
            latitude = None
        try:
            longitude = float(longitude)
            assert(-180.0 <= longitude <= 180.0)
        except:
            longitude = None
        try:
            assert(isinstance(country_strings, Container) and
                   not isinstance(country_strings, basestring))
            country_strings = tuple(country for country in country_strings
                                    if isinstance(country, basestring))
        except:
            country_strings = ()
        try:
            assert(isinstance(region_strings, Container) and
                   not isinstance(region_strings, basestring))
            region_strings = tuple(region for region in region_strings
                                   if isinstance(region, basestring))
        except:
            region_strings = ()

        if verbose:
            if latitude is not None and longitude is not None:
                print u'Lat / Lon: %+08.3f / %+08.3f' % (latitude, longitude)
            else:
                print u'Lat / Lon:   None   /   None  '
            print u'Country Strings: %s' % u', '.join(country_strings)
            print u'Region  Strings: %s' % u', '.join(region_strings)

        country_code = None
        region_code = None

        if verbose:
            runtime = time()
        contains_calls = 0
        distance_calls = 0

        if (self.__country_tree is not None and
                latitude is not None and longitude is not None):
            ndist = nnode = None
            point = Point(longitude, latitude)
            for cnode in self.__country_tree.find_approximate_nearest(
                    latitude, longitude):

                ccode = cnode.ccode
                cpoly = self._country_geocode[ccode]

                contains_calls += 1
                if contains(cpoly, point):
                    if ccode in self.__region_trees:
                        ctree = self.__region_trees[ccode]
                        for rnode in ctree.find_approximate_nearest(
                                latitude, longitude):
                            if rnode.ccode != ccode:
                                continue
                            rcode = rnode.rcode

                            if rcode not in self._region_geocode[ccode]:
                                continue
                            rpoly = self._region_geocode[ccode][rcode]

                            contains_calls += 1
                            if contains(rpoly, point):
                                country_code = ccode
                                region_code = rcode
                                break

                        if region_code is None:
                            for rnode in self.__region_trees[ccode]:
                                rcode = rnode.rcode
                                rpoly = self._region_geocode[ccode][rcode]
                                distance_calls += 1
                                if nnode is None:
                                    ndist = distance(rpoly, point)
                                    nnode = rnode
                                else:
                                    rdist = distance(rpoly, point)
                                    if rdist < ndist:
                                        ndist = rdist
                                        nnode = rnode
                        else:
                            break
                    else:
                        country_code = ccode
                        region_code = None
                else:
                    distance_calls += 1
                    if nnode is None:
                        ndist = distance(cpoly, point)
                        nnode = cnode
                    else:
                        cdist = distance(cpoly, point)
                        if cdist < ndist:
                            ndist = cdist
                            nnode = cnode

                if country_code is not None:
                    if verbose:
                        print u'GeoCode determined by intersection.'
                        print u'Time: %f seconds.' % (time() - runtime)
                        print u'Cont: %d polygons.' % contains_calls
                        print u'Dist: %d polygons.' % distance_calls
                        print self.translate(country_code, region_code)
                        print
                    break

            if country_code is None and nnode is not None:
                country_code = nnode.ccode
                region_code = getattr(nnode, 'rcode', None)
                if verbose:
                    print u'GeoCode determined by proximity.'
                    print u'Time: %f seconds.' % (time() - runtime)
                    print u'Cont: %d polygons.' % contains_calls
                    print u'Dist: %d polygons.' % distance_calls
                    print self.translate(country_code, region_code)
                    print

        if (self._country_fuzzies is not None and
            self._region_fuzzies is not None and
            country_code is None and (
                any(country_strings) or any(region_strings))):
            best_conf = self._fuzzy_treshold
            for country in country_strings:
                _, code, conf = self._country_fuzzies.get_stored_tuple(country)
                if conf > best_conf:
                    country_code, region_code = code, None
            for region in region_strings:
                _, tup_, conf = self._region_fuzzies.get_stored_tuple(region)
                if conf > best_conf:
                    country_code, region_code = tup_
            if verbose:
                print u'GeoCode determined by fuzzy set comparison.'
                print u'Time: %f seconds.' % (time() - runtime)
                print u'Cont: %d polygons.' % contains_calls
                print u'Dist: %d polygons.' % distance_calls
                print self.translate(country_code, region_code)
                print

        return country_code, region_code
Esempio n. 5
0
 def drawPoints(self):
     return (self.pos, self.pos + Point(self.width, 0),
             self.pos + Point(self.width, -self.thickness),
             self.pos + Point(0, -self.thickness))
Esempio n. 6
0
 def __init__(self):
     self.pos = Point()
     self.width = 0.7
     self.thickness = 0.1
Esempio n. 7
0
def main():
	pygame.init()
	SCREEN_WIDTH = 800
	SCREEN_HEIGHT = 600
	SCALE = 80	# pixels per meter
	WIDTH = SCREEN_WIDTH/SCALE
	HEIGHT = SCREEN_HEIGHT/SCALE

	SCREEN_CENTRE = Point(WIDTH/2, HEIGHT/2)
	CENTRE = SCREEN_CENTRE/SCALE

	DISPLAY = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
	CLOCK = pygame.time.Clock()
	totalTime = 0

	GRAVITY = 9.81

	helper = Helper(DISPLAY, SCALE, WIDTH, HEIGHT)
	drawPos = helper.drawPos
	worldPos = helper.worldPos
	drawVector = helper.drawVector

	personImage = pygame.image.load(os.getcwd()+"/person.jpg")
	personRect = personImage.get_rect()
	personImage = pygame.transform.scale(personImage, (int(personRect.width*(int(1.8*SCALE)/personRect.height)), int(1.8*SCALE)))

	moveData = {
		"lastPos": Point(),
		"currentPos": Point(CENTRE.x, 0),
		"lastScreenMousePos": Point(),
		"mouseHeld": False,
		"lastVelocity": Vector()
	}
	mouseVelocity = Vector()

	mouseBall = Ball()
	mouseBall.moveable = False

	tickerPoints = []
	MAX_TICKER_POINTS = 100
	TICKER_PERIOD = 0.02
	timeSinceLastTicker = 0

	ball = Ball()
	ball.setPos(Point(WIDTH/2, HEIGHT/2))

	string = String()
	string.setConnections(mouseBall, ball)
	string.active = False

	while True:
		DISPLAY.fill(WHITE)
		deltaT = CLOCK.get_time()/1000
		totalTime += deltaT

		moveData["lastPos"] = Point(moveData["currentPos"])
		if not moveData["lastScreenMousePos"] == Point(pygame.mouse.get_pos()):
			moveData["currentPos"] = Point(worldPos(Point(pygame.mouse.get_pos())))

		moveData["lastScreenMousePos"] = Point(pygame.mouse.get_pos())

		heldKeys = pygame.key.get_pressed()
		for e in pygame.event.get():
			if e.type == pygame.QUIT:
				pygame.quit()

			elif e.type == pygame.KEYDOWN:
				heldKeys = pygame.key.get_pressed()
				if (heldKeys[pygame.K_RCTRL] or heldKeys[pygame.K_LCTRL]) and\
					(heldKeys[pygame.K_w] or heldKeys[pygame.K_q]):
					pygame.quit()
				if (heldKeys[pygame.K_SPACE]):
					mouseBallDist = moveData["currentPos"].distance(ball.pos)
					if mouseBallDist > 0:
						string.toggle()
						string.length = mouseBallDist

			elif e.type == pygame.MOUSEBUTTONDOWN:
				if e.button == 1:
					moveData["mouseHeld"] = True

			elif e.type == pygame.MOUSEBUTTONUP:
				if e.button == 1:
					moveData["mouseHeld"] = False

		keyboardMoveSpeed = 1
		if heldKeys[pygame.K_a]:
			moveData["currentPos"] = moveData["currentPos"] - Point(keyboardMoveSpeed*deltaT, 0)
		elif heldKeys[pygame.K_d]:
			moveData["currentPos"] = moveData["currentPos"] + Point(keyboardMoveSpeed*deltaT, 0)
		if heldKeys[pygame.K_w]:
			moveData["currentPos"] = moveData["currentPos"] + Point(0, keyboardMoveSpeed*deltaT)
		elif heldKeys[pygame.K_s]:
			moveData["currentPos"] = moveData["currentPos"] - Point(0, keyboardMoveSpeed*deltaT)

		if deltaT > 0:
			moveData["lastVelocity"] = Vector(mouseBall.velocity)
			mouseVelocity = Vector(((moveData["currentPos"]-moveData["lastPos"])/deltaT).pos())
			mouseAcceleration = (mouseVelocity - moveData["lastVelocity"])/deltaT
		else:
			mouseVelocity = Vector()
			mouseAcceleration = Vector()
		mouseBall.setPos(moveData["currentPos"])
		mouseBall.setVelocity(mouseVelocity)


		#gravity adjustment
		if heldKeys[pygame.K_i]:
			GRAVITY = min(30.0,GRAVITY+0.1)
		elif heldKeys[pygame.K_k]:
			GRAVITY  = max(0.0,GRAVITY-0.1)

		#ball radius
		if heldKeys[pygame.K_o]:
			ball.radius = min(4.0,ball.radius+0.01)
		elif heldKeys[pygame.K_l]:
			ball.radius = max(0.1,ball.radius-0.01)

		#string length
		if heldKeys[pygame.K_u]:
			string.length = min(8.0,string.length+0.01)
		elif heldKeys[pygame.K_j]:
			string.length = max(0.01,string.length-0.01)


		#reset all
		if heldKeys[pygame.K_r]:
			GRAVITY = 9.81
			ball.radius = 0.1
			string.length = 2.0



		if ball.bottom <= 0:
			if ball.velocity.y < 0:
				ball.accelerate(Vector((0, -ball.velocity.y-ball.velocity.y*ball.cor)))
		else:
			ball.accelerate(Vector((0, -GRAVITY))*deltaT)
			#print(ball.velocity)

		if ball.left <= 0:
			if ball.velocity.x < 0:
				ball.accelerate(Vector((-ball.velocity.x-ball.velocity.x*ball.cor, 0)))

		if ball.right >= WIDTH:
			if ball.velocity.x > 0:
				ball.accelerate(Vector((-ball.velocity.x-ball.velocity.x*ball.cor, 0)))

		string.applyTension(deltaT)
		
		if moveData["mouseHeld"]:
			ball.setPos(moveData["currentPos"])
			ball.setVelocity(mouseBall.velocity)
			ball.setInEquilibrium()
		else:
			ball.move(deltaT)

		string.correctPositions()

		# === DRAW

		# draw person
		DISPLAY.blit(personImage, (-(1/3)*personImage.get_rect().width, SCREEN_HEIGHT-personImage.get_rect().height))

		# draw ticker tape
		if not moveData["mouseHeld"]:
			timeSinceLastTicker += deltaT
			if timeSinceLastTicker >= TICKER_PERIOD:
				tickerPoints.append(Point(ball.pos))
				if len(tickerPoints) > MAX_TICKER_POINTS:
					del tickerPoints[0]
				timeSinceLastTicker = 0
		else:
			tickerPoints = []

		for p in tickerPoints:
			pygame.draw.circle(DISPLAY, BLUE, drawPos(p), 2, 2)

		# draw mouse velocity vector
		drawVector(mouseBall.velocity, moveData["currentPos"], 20, False, BLUE)

		# velocity vector is scaled so it can be more easily comprehended
		drawVector(ball.velocity, ball.pos, 10, False, GREEN, 1)

		# draw ball
		pygame.draw.circle(DISPLAY, RED, drawPos(ball.pos), int(ball.radius*SCALE), 1)

		if string.active:
			pygame.draw.line(DISPLAY, GREEN, drawPos(ball.pos), drawPos(moveData["currentPos"]), 1)

		font = pygame.font.SysFont("monospace", 15)
		# render text
		fps = font.render("{}fps".format(int(CLOCK.get_fps())), 1, BLACK)
		DISPLAY.blit(fps, (10, 10))
		ballVelLabel = font.render("Ball velocity: {:.2f}ms-1".format(ball.velocity.mag), 1, BLACK)
		DISPLAY.blit(ballVelLabel, (10, 30))
		mouseVelLabel = font.render("Mouse velocity: {:.2f}ms-1".format(mouseBall.velocity.mag), 1, BLACK)
		DISPLAY.blit(mouseVelLabel, (10, 50))
		gravityVelLabel = font.render("Gravity: {:.2f}ms-2".format(GRAVITY), 1, BLACK)
		DISPLAY.blit(gravityVelLabel, (10, 70))
		diameterVelLabel = font.render("Ball diameter: {:.2f}m".format(ball.radius*2), 1, BLACK)
		DISPLAY.blit(diameterVelLabel, (10, 90))
		stringVelLabel = font.render("String length: {:.2f}m".format(string.length), 1, BLACK)
		DISPLAY.blit(stringVelLabel, (10, 110))


		#control prompts
		stringConnect = font.render("Connect string:           SPACE", 1, BLACK)
		DISPLAY.blit(stringConnect, (SCREEN_WIDTH-stringConnect.get_rect().width-10, 10))
		stringControl = font.render("String length +/-:        U/J", 1, BLACK)
		DISPLAY.blit(stringControl, (SCREEN_WIDTH-stringConnect.get_rect().width-10, 30))
		gravityControl = font.render("Gravity +/-:              I/K", 1, BLACK)
		DISPLAY.blit(gravityControl, (SCREEN_WIDTH-stringConnect.get_rect().width-10, 50))
		diameterControl = font.render("Ball diameter +/-:        O/L", 1, BLACK)
		DISPLAY.blit(diameterControl, (SCREEN_WIDTH-stringConnect.get_rect().width-10, 70))
		resetAllControl = font.render("Reset all:                R", 1, BLACK)
		DISPLAY.blit(resetAllControl, (SCREEN_WIDTH-stringConnect.get_rect().width-10, 90))
		pygame.display.update()
		CLOCK.tick(120)
Esempio n. 8
0
def main():
    pygame.init()
    SCREEN_WIDTH = 800
    SCREEN_HEIGHT = 600
    SCALE = 80  # pixels per meter
    WIDTH = SCREEN_WIDTH / SCALE
    HEIGHT = SCREEN_HEIGHT / SCALE

    SCREEN_CENTRE = Point(WIDTH / 2, HEIGHT / 2)
    CENTRE = SCREEN_CENTRE / SCALE

    DISPLAY = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    CLOCK = pygame.time.Clock()
    totalTime = 0

    #waves = [
    #Wave(0.5, 1, 0.5, Point(SCREEN_CENTRE), 10, RED),
    #Wave(-1, 1, 1, Point(SCREEN_CENTRE), 10, BLUE),
    #Wave(0.25, 0.75, 0.25, Point(SCREEN_CENTRE), 10, GREEN)]

    waves = [
        Wave(1, 1, 0.25, Point(SCREEN_CENTRE), 20, RED),
        Wave(1, 1, 0.24, Point(SCREEN_CENTRE), 20, BLUE)
    ]

    hp = Helper(DISPLAY, SCALE, WIDTH, HEIGHT)

    while True:
        DISPLAY.fill(WHITE)
        deltaT = CLOCK.get_time() / 1000
        totalTime += deltaT

        heldKeys = pygame.key.get_pressed()
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                pygame.quit()

            elif e.type == pygame.KEYDOWN:
                heldKeys = pygame.key.get_pressed()
                if (heldKeys[pygame.K_RCTRL] or heldKeys[pygame.K_LCTRL]) and\
                 (heldKeys[pygame.K_w] or heldKeys[pygame.K_q]):
                    pygame.quit()

        # === DRAW

        yVals = {}

        for w in waves:
            step = 0.02
            xTrans = math.pi / w.wavelength
            amp = w.amplitude
            myXVals = []
            for i in [
                    x * step
                    for x in (range(0, -int(w.length / step) -
                                    1, -1) if w.velocity > 0 else range(
                                        0,
                                        int(w.length / step) + 1))
            ]:
                yVal = amp * math.sin(i * xTrans)
                xVal = float(
                    Decimal(w.pos.x + i).quantize(Decimal('.1'),
                                                  rounding=ROUND_DOWN))
                if xVal not in myXVals:
                    if xVal in yVals.keys():
                        yVals[xVal].append(yVal)
                    else:
                        yVals[xVal] = [yVal]
                    myXVals.append(xVal)

                pygame.draw.line(
                    DISPLAY, w.colour,
                    hp.drawPos(w.pos + Point(i, yVal + HEIGHT / 4)),
                    hp.drawPos(w.pos + Point(
                        i + step,
                        amp * math.sin((i + step) * xTrans) + HEIGHT / 4)))

        last = ["NaN", 0]
        for i in sorted(yVals.keys()):
            vs = yVals[i]
            if len(vs) < 2:
                continue

            tot = sum(vs)
            if last[0] != "NaN":
                pygame.draw.line(
                    DISPLAY, PURPLE,
                    hp.drawPos(Point(last[1], HEIGHT / 4 + last[0])),
                    hp.drawPos(Point(i, HEIGHT / 4 + tot)))

            last = [tot, i]

        for w in waves:
            w.move(deltaT)

        pygame.display.update()
        CLOCK.tick(120)
Esempio n. 9
0
 def test_point(self):
     p = Point(1, 2)
     self.assertEqual(p.x, 1)
     self.assertEqual(p.y, 2)
Esempio n. 10
0
 def test_circle(self):
     c1 = Circle(Point(3, 4), 1)
     c2 = Circle(Point(6, 8), 1)
     overlap = circles_overlap(c1, c2)
     self.assertFalse(overlap)
Esempio n. 11
0
 def distance_function2(self):
     p1 = Point(1, 0)
     p2 = Point(5, 0)
     dist = distance(p1, p2)
     self.assertEqual(dist, 4)
Esempio n. 12
0
 def distance_function(self):
     p1 = Point(1, 2)
     p2 = Point(5, 6)
     dist = distance(p1, p2)
     self.assertAlmostEqual(dist, 5.6568542)
Esempio n. 13
0
 def test_circle2(self):
     c1 = Circle(Point(5, 6), 3)
     self.assertEqual(c1.center.x, 5)
     self.assertEqual(c1.center.y, 6)
     self.assertEqual(c1.radius, 3)
Esempio n. 14
0
 def test_circle(self):
     c = Circle(Point(3, 4), 2)
     self.assertEqual(c.center.x, 3)
     self.assertEqual(c.center.y, 4)
     self.assertEqual(c.radius, 2)
Esempio n. 15
0
 def test_point2(self):
     p1 = Point(3, 4)
     self.assertEqual(p1.x, 3)
     self.assertEqual(p1.y, 4)
Esempio n. 16
0
def main():
    pygame.init()
    SCREEN_WIDTH = 800
    SCREEN_HEIGHT = 600
    SCALE = 80  # pixels per meter
    WIDTH = SCREEN_WIDTH / SCALE
    HEIGHT = SCREEN_HEIGHT / SCALE

    SCREEN_CENTRE = Point(WIDTH / 2, HEIGHT / 2)
    CENTRE = SCREEN_CENTRE / SCALE

    DISPLAY = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    CLOCK = pygame.time.Clock()
    totalTime = 0

    GRAVITY = 9.81

    helper = Helper(DISPLAY, SCALE, WIDTH, HEIGHT)
    drawPos = helper.drawPos
    worldPos = helper.worldPos
    drawVector = helper.drawVector

    personImage = pygame.image.load(os.getcwd() + "/person.jpg")
    personRect = personImage.get_rect()
    personImage = pygame.transform.scale(
        personImage,
        (int(personRect.width *
             (int(1.8 * SCALE) / personRect.height)), int(1.8 * SCALE)))

    moveData = {
        "lastPos": Point(),
        "currentPos": Point(CENTRE.x, 0),
        "lastScreenMousePos": Point(),
        "mouseHeld": False,
        "lastVelocity": Vector()
    }
    mouseVelocity = Vector()

    tickerPoints = []
    MAX_TICKER_POINTS = 100
    TICKER_PERIOD = 0.02
    timeSinceLastTicker = 0

    mouseBall = Ball()
    mouseBall.moveable = False

    ball = Ball()
    ball.setPos(Point(WIDTH / 2, HEIGHT / 2))
    balls = [ball]

    ballMouseString = String()
    ballMouseString.setConnections(mouseBall, ball)
    ballMouseString.active = True
    size = 1
    ballMouseString.length = size
    strings = [ballMouseString]
    for i in range(1):
        a = Ball()
        a.setPos(Point(WIDTH / 2, HEIGHT / 4))
        balls.append(a)
        st = String()
        st.setConnections(balls[i], balls[i + 1])
        st.length = size
        st.active = True
        strings.append(st)

    drawBalls = True

    print(len(balls))
    print(len(strings))
    '''ball2 = Ball()
	ball2.setPos(Point(WIDTH/2, HEIGHT/4))
	#ball2.mass = 0.5
	balls.append(ball2)
	ball3 = Ball()
	ball3.setPos(Point(WIDTH/2, HEIGHT/4))
	#ball3.mass = 1
	balls.append(ball3)'''
    '''ballString1 = String()
	ballString1.setConnections(ball, ball2)
	ballString1.length = 1
	ballString1.active = True
	ballString2 = String()
	ballString2.setConnections(ball2, ball3)
	ballString2.length = 1
	ballString2.active = True
	strings = [ballMouseString, ballString1, ballString2]'''

    while True:
        DISPLAY.fill(WHITE)
        deltaT = CLOCK.get_time() / 1000
        totalTime += deltaT

        moveData["lastPos"] = Point(moveData["currentPos"])
        if not moveData["lastScreenMousePos"] == Point(pygame.mouse.get_pos()):
            moveData["currentPos"] = Point(
                worldPos(Point(pygame.mouse.get_pos())))

        moveData["lastScreenMousePos"] = Point(pygame.mouse.get_pos())

        heldKeys = pygame.key.get_pressed()
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                pygame.quit()

            elif e.type == pygame.KEYDOWN:
                heldKeys = pygame.key.get_pressed()
                if (heldKeys[pygame.K_RCTRL] or heldKeys[pygame.K_LCTRL]) and\
                 (heldKeys[pygame.K_w] or heldKeys[pygame.K_q]):
                    pygame.quit()
                if (heldKeys[pygame.K_SPACE]):
                    mouseBallDist = moveData["currentPos"].distance(
                        balls[0].pos)
                    if mouseBallDist > 0:
                        strings[0].length = mouseBallDist
                        strings[0].toggle()

            elif e.type == pygame.MOUSEBUTTONDOWN:
                if e.button == 1:
                    moveData["mouseHeld"] = True

            elif e.type == pygame.MOUSEBUTTONUP:
                if e.button == 1:
                    moveData["mouseHeld"] = False

        keyboardMoveSpeed = 1
        if heldKeys[pygame.K_a]:
            moveData["currentPos"] = moveData["currentPos"] - Point(
                keyboardMoveSpeed * deltaT, 0)
        elif heldKeys[pygame.K_d]:
            moveData["currentPos"] = moveData["currentPos"] + Point(
                keyboardMoveSpeed * deltaT, 0)
        if heldKeys[pygame.K_w]:
            moveData["currentPos"] = moveData["currentPos"] + Point(
                0, keyboardMoveSpeed * deltaT)
        elif heldKeys[pygame.K_s]:
            moveData["currentPos"] = moveData["currentPos"] - Point(
                0, keyboardMoveSpeed * deltaT)

        if deltaT > 0:
            moveData["lastVelocity"] = Vector(mouseVelocity)
            mouseVelocity = Vector(
                ((moveData["currentPos"] - moveData["lastPos"]) /
                 deltaT).pos())
            mouseAcceleration = (mouseVelocity -
                                 moveData["lastVelocity"]) / deltaT
        else:
            mouseVelocity = Vector()
            mouseAcceleration = Vector()
        mouseBall.setVelocity(mouseVelocity)
        mouseBall.setPos(moveData["currentPos"])

        for i in range(len(balls)):
            b = balls[i]
            if b.bottom <= 0:
                if b.velocity.y < 0:
                    b.accelerate(
                        Vector((0, -b.velocity.y - b.velocity.y * b.cor)))
            else:
                b.accelerate(Vector((0, -GRAVITY)) * deltaT)

            if b.left <= 0:
                if b.velocity.x < 0:
                    ball.accelerate(
                        Vector((-b.velocity.x - b.velocity.x * b.cor, 0)))

            if b.right >= WIDTH:
                if b.velocity.x > 0:
                    ball.accelerate(
                        Vector((-b.velocity.x - b.velocity.x * b.cor, 0)))

        for s in strings:
            s.applyTension(deltaT)
            #drawVector(s.applyTension(), s.connections[1].pos, 1)

        if moveData["mouseHeld"]:
            balls[0].setPos(mouseBall.pos)
            balls[0].setVelocity(mouseBall.velocity)
            balls[0].setInEquilibrium()
            balls[0].moveable = False
        else:
            balls[0].moveable = True

        for i in range(len(balls)):
            if i == 0 and moveData["mouseHeld"]:
                continue

            b = balls[i]
            b.move(deltaT)

            if b.velocity.mag > 10000:
                b.velocity = Vector()

        for s in strings:
            s.correctPositions()

        # === DRAW

        # draw person
        DISPLAY.blit(personImage,
                     (-(1 / 3) * personImage.get_rect().width,
                      SCREEN_HEIGHT - personImage.get_rect().height))

        # draw ticker tape
        if not moveData["mouseHeld"] and False:
            timeSinceLastTicker += deltaT
            if timeSinceLastTicker >= TICKER_PERIOD:
                tickerPoints.append(Point(ball.pos))
                if len(tickerPoints) > MAX_TICKER_POINTS:
                    del tickerPoints[0]
                timeSinceLastTicker = 0
        else:
            tickerPoints = []

        for p in tickerPoints:
            pygame.draw.circle(DISPLAY, BLUE, drawPos(p), 2, 2)

        # draw mouse velocity vector
        drawVector(mouseBall.velocity, mouseBall.pos, 20, False, BLUE)

        # velocity vector is scaled so it can be more easily comprehended
        for b in balls:
            if not drawBalls: break
            drawVector(b.velocity, b.pos, 10, False, GREEN, 1)

        # draw ball
        for b in balls:
            if not drawBalls: break
            pygame.draw.circle(DISPLAY, RED, drawPos(b.pos),
                               int(ball.radius * SCALE), 1)

        for s in strings:
            if s.active:
                pygame.draw.line(DISPLAY, GREEN, drawPos(s.connections[0].pos),
                                 drawPos(s.connections[1].pos), 1)

        font = pygame.font.SysFont("monospace", 15)
        # render text
        fps = font.render("{}fps".format(int(CLOCK.get_fps())), 1, BLACK)
        DISPLAY.blit(fps, (10, 10))
        ballVelLabel = font.render(
            "Ball velocity: {:.2f}ms-1".format(ball.velocity.mag), 1, BLACK)
        DISPLAY.blit(ballVelLabel, (10, 30))
        mouseVelLabel = font.render(
            "Mouse velocity: {:.2f}ms-1".format(mouseVelocity.mag), 1, BLACK)
        DISPLAY.blit(mouseVelLabel, (10, 50))

        pygame.display.update()
        CLOCK.tick(120)