# Ryan Martin
# macid: abcd123
# student number: #######
# November 23, 2011
#
#
# This is a solution for Major Assignment 5 (Lab 11) on Tuesday.

class particle1D:

    def __init__(self, m, r0, v0, a0):
        self.m = float(m)
        self.r = float(r0)
        self.v = float(v0)
        self.a = float(a0)

    def getM(self):
        return self.m

    def getR(self):
        return self.r
    
    def getV(self):
        return self.v
    
    def getA(self):
        return self.a

    def update(self, delta_t):
        self.r = self.r + self.v * delta_t + 0.5 * self.a * delta_t**2
        self.v = self.v + self.a * delta_t

    def isOnGround(self):
        if self.r <= 0:
            return True

        return False

    def bounce(self, damp):
        self.v = -1 * self.v + damp

def runBounceSim(p, cycles, delta_t, damp):
    result = [p.getR()]    

    for i in range(cycles):
        p.update(delta_t)

        if p.isOnGround():
            p.bounce(damp)

        result.append(p.getR())

    return result


'''
Design Question

Since we are approximating time using the interval delta_t,
it is unlikely that r will ever precisely equal zero since
that would require a precise time value. As delta_t 
approaches zero, our chances of actually 'hitting the ground'
are better, but it is still more likely that we will overshoot
zero and proceed into the r < 0 range  (In fact, even with an
infinitely small value of delta_t, the limited precision of
floating point numbers makes it even more unlikely to ever 
reach zero exactly). Hence, we use r <= 0 for our
'ground' check.
'''
##Note: This format is used by our automated marking system.
##You will see that, for inputs, the class/function/method name is
##given with the corresponding inputs to that class/function/method
##listed right after it. The expected outputs are the state
##variables of the object after calling the function/method.
'''
Testing Report

TUE = {'test1': 
       {'inputs': ['particle1D', [1, 0, 2, 0], 'update', [0.1]],
       'outputs': [testingClass(1, 0.2, 2, 0)]},
       'test2':
       {'inputs': ['particle1D', [2.5, -1.5, -1.5, 2], 'update', [0.2]],
       'outputs': [testingClass(2.5, -1.76, -1.1, 2.0)]},
       'test3':
       {'inputs': ['particle1D', [1, 2, -1, 0], 'bounce', [-0.5]],
       'outputs': [testingClass(1, 2, 0.5, 0)]},
       'test4':
       {'inputs': ['particle1D', [1,-1,0,0], 'isOnGround', []],
       'outputs': [True]},
       'test5':
       {'inputs': ['runBounceSim', [('particle1D', [5, 1, 0, -5]), 10, 0.1, -0.5]],
       'outputs': [[1.0, 0.975, 0.8999999999999999, 0.7749999999999999, 0.5999999999999999, 0.37499999999999983, 0.09999999999999983, -0.22500000000000023, 0.04999999999999981, 0.2749999999999998, 0.4499999999999998]]}}
'''