Back to Freecodecamp

Step 9

curriculum/challenges/english/blocks/learn-encapsulation-by-building-a-projectile-trajectory-calculator/6634fa2417d7194b0c9425f9.md

latest3.5 KB
Original Source

--description--

Now create the two getters for __height and __angle. Remember that for the angle, the value is given to the class in degrees, but is saved internally in radians, so have the getter return the degrees value. You can use math.degrees, and the round function for this.

--hints--

You should define a height method.

js
({test: () => assert(runPython(`
_Node(_code).find_class('Projectile').has_function('height')
`))})

Your height method should have a single parameter, self.

js
({test: () => assert(runPython(`
_Node(_code).find_class('Projectile').find_function('height').has_args('self')
`))})

Your height method should have a @property decorator.

js
({test: () => assert(runPython(`
_Node(_code).find_class('Projectile').find_function('height').has_decorators('property')
`))})

Your height method should return the value of the private attribute __height.

js
({test: () => assert(runPython(`
a = Projectile(22, 23, 24)
a.height == 23
`))})

You should define an angle method.

js
({test: () => assert(runPython(`
_Node(_code).find_class('Projectile').has_function('angle')
`))})

Your angle method should have a @property decorator.

js
({test: () => assert(runPython(`
_Node(_code).find_class('Projectile').find_function('angle').has_decorators('property')
`))})

Your angle method should have a single parameter, self.

js
({test: () => assert(runPython(`
_Node(_code).find_class('Projectile').find_function('angle').has_args('self')
`))})

Your angle method should return the value of the private attribute __angle converted to degrees.

js
({test: () => assert(runPython(`
a = Projectile(22, 23, 24)
a.angle == 24
`))})

--seed--

--seed-contents--

py
import math

GRAVITATIONAL_ACCELERATION = 9.81
PROJECTILE = "∙"
x_axis_tick = "T"
y_axis_tick = "⊣"

class Projectile:
    __slots__ = ('__speed', '__height', '__angle')

    def __init__(self, speed, height, angle):
        self.__speed = speed
        self.__height = height
        self.__angle = math.radians(angle)
        
    def __str__(self):
        return f'''
Projectile details:
speed: {self.__speed} m/s
height: {self.__height} m
angle: {round(math.degrees(self.__angle))}°
displacement: {round(self.__calculate_displacement(), 1)} m
'''

    def __calculate_displacement(self):
        horizontal_component = self.__speed * math.cos(self.__angle)
        vertical_component = self.__speed * math.sin(self.__angle)
        squared_component = vertical_component**2
        gh_component = 2 * GRAVITATIONAL_ACCELERATION * self.__height
        sqrt_component = math.sqrt(squared_component + gh_component)
        
        return horizontal_component * (vertical_component + sqrt_component) / GRAVITATIONAL_ACCELERATION
        
    def __calculate_y_coordinate(self, x):
        height_component = self.__height
        angle_component = math.tan(self.__angle) * x
        acceleration_component = GRAVITATIONAL_ACCELERATION * x ** 2 / (
                2 * self.__speed ** 2 * math.cos(self.__angle) ** 2)
        y_coordinate = height_component + angle_component - acceleration_component

        return y_coordinate
    
    def calculate_all_coordinates(self):
        return [
            (x, self.__calculate_y_coordinate(x))
            for x in range(math.ceil(self.__calculate_displacement()))
        ]

--fcc-editable-region--
    @property
    def speed(self):
        return self.__speed

    
--fcc-editable-region--

ball = Projectile(10, 3, 45)
print(ball)
coordinates = ball.calculate_all_coordinates()