Back to Freecodecamp

Step 20

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

latest4.6 KB
Original Source

--description--

You have a list of lists of strings. Join the inner lists to have a list of strings.

It should look like this:

py
[
    "     ∙       ",
    "  ∙∙∙ ∙∙∙    ",
    " ∙       ∙   ",
    "∙         ∙  ",
    "           ∙ ",
    "            ∙",
    "             ",
]

--hints--

The method should return the correct value.

js
({
    test: () => {
        runPython(`
expected = [
    "     ∙       ",
    "  ∙∙∙ ∙∙∙    ",
    " ∙       ∙   ",
    "∙         ∙  ",
    "           ∙ ",
    "            ∙",
    "             ",
]
ball = Projectile(10, 3, 45)
print(ball)
coordinates = ball.calculate_all_coordinates()
graph = Graph(coordinates)
actual = graph.create_trajectory()
assert actual == expected, "matrix has wrong value"
        `)
    }
})

create_trajectory() should calculate the correct output for different instances.

js
({
    test: () => {
        runPython(`
expected = [
    "  ∙∙∙∙∙        ",
    "∙∙     ∙       ",
    "        ∙∙     ",
    "          ∙    ",
    "           ∙   ",
    "               ",
    "            ∙  ",
    "             ∙ ",
    "               ",
    "              ∙",
    "               ",
]
ball = Projectile(9, 9, 30)
print(ball)
coordinates = ball.calculate_all_coordinates()
graph = Graph(coordinates)
actual = graph.create_trajectory()
assert actual == expected, "matrix has wrong value"
        `)
    }
})

--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: {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()))
        ]

    @property
    def height(self):
        return self.__height

    @property
    def angle(self):
        return round(math.degrees(self.__angle))

    @property
    def speed(self):
        return self.__speed

    @height.setter
    def height(self, n):
        self.__height = n

    @angle.setter
    def angle(self, n):
        self.__angle = math.radians(n)

    @speed.setter
    def speed(self, s):
       self.__speed = s
    
    def __repr__(self):
        return f'{self.__class__}({self.speed}, {self.height}, {self.angle})'

class Graph:
    __slots__ = ('__coordinates')

    def __init__(self, coord):
        self.__coordinates = coord

    def __repr__(self):
        return f"Graph({self.__coordinates})"

    def create_coordinates_table(self):
        table = '\n  x      y\n'
        for x, y in self.__coordinates:
            table += f'{x:>3}{y:>7.2f}\n'

        return table

--fcc-editable-region--
    def create_trajectory(self):
        
        rounded_coords = [(round(x), round(y)) for x,y in self.__coordinates]
        
        x_max = max(rounded_coords, key=lambda i: i[0])[0]
        y_max = max(rounded_coords, key=lambda j: j[1])[1]
        
        matrix_list = [[' ' for _ in range(x_max + 1)] for _ in range(y_max + 1)]
        
        for (x, y) in rounded_coords:
            matrix_list[-y-1][x] = PROJECTILE

        return matrix_list

--fcc-editable-region--

ball = Projectile(10, 3, 45)
print(ball)
coordinates = ball.calculate_all_coordinates()
graph = Graph(coordinates)
for row in graph.create_trajectory():
    print(row)