├── main.py ├── shape_calculator.py ├── README.md └── test_module.py /main.py: -------------------------------------------------------------------------------- 1 | # This entrypoint file to be used in development. Start by reading README.md 2 | import shape_calculator 3 | from unittest import main 4 | 5 | 6 | rect = shape_calculator.Rectangle(5, 10) 7 | print(rect.get_area()) 8 | rect.set_width(3) 9 | print(rect.get_perimeter()) 10 | print(rect) 11 | 12 | sq = shape_calculator.Square(9) 13 | print(sq.get_area()) 14 | sq.set_side(4) 15 | print(sq.get_diagonal()) 16 | print(sq) 17 | 18 | 19 | # Run unit tests automatically 20 | main(module='test_module', exit=False) -------------------------------------------------------------------------------- /shape_calculator.py: -------------------------------------------------------------------------------- 1 | class Rectangle: 2 | 3 | def __init__(self, width, height): 4 | self.width = width 5 | self.height = height 6 | 7 | def __str__(self): 8 | return f"Rectangle(width={self.width}, height={self.height})" 9 | 10 | def set_width(self, width): 11 | self.width = width 12 | 13 | def set_height(self, height): 14 | self.height = height 15 | 16 | def get_area(self): 17 | return self.width * self.height 18 | 19 | def get_perimeter(self): 20 | return 2 * (self.width + self.height) 21 | 22 | def get_diagonal(self): 23 | return (self.width**2 + self.height**2)**0.5 24 | 25 | def get_picture(self): 26 | if self.width > 50 or self.height > 50: 27 | return "Too big for picture." 28 | rectangle = ("*" * self.width + "\n") * self.height 29 | return rectangle 30 | 31 | def get_amount_inside(self, shape): 32 | max_width = self.width // shape.width 33 | max_height = self.height // shape.height 34 | return max_width * max_height 35 | 36 | 37 | class Square(Rectangle): 38 | 39 | def __init__(self, length): 40 | super().__init__(length, length) 41 | 42 | def __str__(self): 43 | return f"Square(side={self.width})" 44 | 45 | def set_side(self, side): 46 | self.width = side 47 | self.height = side 48 | 49 | # These two methods are not required since Square inherits from Rectangle and 50 | # the inherited set_width and set_height methods work the same way as set_side. 51 | # Keeping them for consistency and clarity. 52 | def set_width(self, side): 53 | self.width = side 54 | self.height = side 55 | 56 | def set_height(self, side): 57 | self.width = side 58 | self.height = side 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Live: https://replit.com/@hawshemi/polygon-area-calculator-freecodecamp 2 | 3 | ## Project Description 4 | 5 | ### Assignment 6 | 7 | In this project, you will use object-oriented programming to create a Rectangle class and a Square class. The Square class should be a subclass of Rectangle and inherit methods and attributes. 8 | 9 | #### Rectangle class 10 | When a Rectangle object is created, it should be initialized with `width` and `height` attributes. The class should also contain the following methods: 11 | * `set_width` 12 | * `set_height` 13 | * `get_area`: Returns area (`width * height`) 14 | * `get_perimeter`: Returns perimeter (`2 * width + 2 * height`) 15 | * `get_diagonal`: Returns diagonal (`(width ** 2 + height ** 2) ** .5`) 16 | * `get_picture`: Returns a string that represents the shape using lines of "\*". The number of lines should be equal to the height and the number of "\*" in each line should be equal to the width. There should be a new line (`\n`) at the end of each line. If the width or height is larger than 50, this should return the string: "Too big for picture.". 17 | * `get_amount_inside`: Takes another shape (square or rectangle) as an argument. Returns the number of times the passed-in shape could fit inside the shape (with no rotations). For instance, a rectangle with a width of 4 and a height of 8 could fit in two squares with sides of 4. 18 | 19 | Additionally, if an instance of a Rectangle is represented as a string, it should look like: `Rectangle(width=5, height=10)` 20 | 21 | #### Square class 22 | The Square class should be a subclass of Rectangle. When a Square object is created, a single side length is passed in. The `__init__` method should store the side length in both the `width` and `height` attributes from the Rectangle class. 23 | 24 | The Square class should be able to access the Rectangle class methods but should also contain a `set_side` method. If an instance of a Square is represented as a string, it should look like: `Square(side=9)` 25 | 26 | Additionally, the `set_width` and `set_height` methods on the Square class should set both the width and height. 27 | 28 | #### Usage example 29 | ```py 30 | rect = shape_calculator.Rectangle(10, 5) 31 | print(rect.get_area()) 32 | rect.set_height(3) 33 | print(rect.get_perimeter()) 34 | print(rect) 35 | print(rect.get_picture()) 36 | 37 | sq = shape_calculator.Square(9) 38 | print(sq.get_area()) 39 | sq.set_side(4) 40 | print(sq.get_diagonal()) 41 | print(sq) 42 | print(sq.get_picture()) 43 | 44 | rect.set_height(8) 45 | rect.set_width(16) 46 | print(rect.get_amount_inside(sq)) 47 | ``` 48 | That code should return: 49 | ``` 50 | 50 51 | 26 52 | Rectangle(width=10, height=3) 53 | ********** 54 | ********** 55 | ********** 56 | 57 | 81 58 | 5.656854249492381 59 | Square(side=4) 60 | **** 61 | **** 62 | **** 63 | **** 64 | 65 | 8 66 | ``` 67 | 68 | The unit tests for this project are in `test_module.py`. 69 | 70 |
71 | 72 | [FreeCodeCamp](https://www.freecodecamp.org/learn/scientific-computing-with-python/scientific-computing-with-python-projects/polygon-area-calculator) 73 | -------------------------------------------------------------------------------- /test_module.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import shape_calculator 3 | 4 | 5 | class UnitTests(unittest.TestCase): 6 | maxDiff = None 7 | def setUp(self): 8 | self.rect = shape_calculator.Rectangle(3, 6) 9 | self.sq = shape_calculator.Square(5) 10 | 11 | def test_subclass(self): 12 | actual = issubclass(shape_calculator.Square, shape_calculator.Rectangle) 13 | expected = True 14 | self.assertEqual(actual, expected, 'Expected Square class to be a subclass of the Rectangle class.') 15 | 16 | def test_distinct_classes(self): 17 | actual = shape_calculator.Square is not shape_calculator.Rectangle 18 | expected = True 19 | self.assertEqual(actual, expected, 'Expected Square class to be a distinct class from the Rectangle class.') 20 | 21 | def test_square_is_square_and_rectangle(self): 22 | actual = isinstance(self.sq, shape_calculator.Square) and isinstance(self.sq, shape_calculator.Rectangle) 23 | expected = True 24 | self.assertEqual(actual, expected, 'Expected square object to be an instance of the Square class and the Rectangle class.') 25 | 26 | def test_rectangle_string(self): 27 | actual = str(self.rect) 28 | expected = "Rectangle(width=3, height=6)" 29 | self.assertEqual(actual, expected, 'Expected string representation of rectangle to be "Rectangle(width=3, height=6)"') 30 | 31 | def test_square_string(self): 32 | actual = str(self.sq) 33 | expected = "Square(side=5)" 34 | self.assertEqual(actual, expected, 'Expected string representation of square to be "Square(side=5)"') 35 | 36 | def test_area(self): 37 | actual = self.rect.get_area() 38 | expected = 18 39 | self.assertEqual(actual, expected, 'Expected area of rectangle to be 18') 40 | actual = self.sq.get_area() 41 | expected = 25 42 | self.assertEqual(actual, expected, 'Expected area of square to be 25') 43 | 44 | 45 | def test_perimeter(self): 46 | actual = self.rect.get_perimeter() 47 | expected = 18 48 | self.assertEqual(actual, expected, 'Expected perimeter of rectangle to be 18') 49 | actual = self.sq.get_perimeter() 50 | expected = 20 51 | self.assertEqual(actual, expected, 'Expected perimeter of square to be 20') 52 | 53 | def test_diagonal(self): 54 | actual = self.rect.get_diagonal() 55 | expected = 6.708203932499369 56 | self.assertEqual(actual, expected, 'Expected diagonal of rectangle to be 6.708203932499369') 57 | actual = self.sq.get_diagonal() 58 | expected = 7.0710678118654755 59 | self.assertEqual(actual, expected, 'Expected diagonal of square to be 7.0710678118654755') 60 | 61 | def test_set_attributes(self): 62 | self.rect.set_width(7) 63 | self.rect.set_height(8) 64 | self.sq.set_side(2) 65 | actual = str(self.rect) 66 | expected = "Rectangle(width=7, height=8)" 67 | self.assertEqual(actual, expected, 'Expected string representation of rectangle after setting new values to be "Rectangle(width=7, height=8)"') 68 | actual = str(self.sq) 69 | expected = "Square(side=2)" 70 | self.assertEqual(actual, expected, 'Expected string representation of square after setting new values to be "Square(side=2)"') 71 | self.sq.set_width(4) 72 | actual = str(self.sq) 73 | expected = "Square(side=4)" 74 | self.assertEqual(actual, expected, 'Expected string representation of square after setting width to be "Square(side=4)"') 75 | 76 | def test_rectangle_picture(self): 77 | self.rect.set_width(7) 78 | self.rect.set_height(3) 79 | actual = self.rect.get_picture() 80 | expected = "*******\n*******\n*******\n" 81 | self.assertEqual(actual, expected, 'Expected rectangle picture to be different.') 82 | 83 | def test_square_picture(self): 84 | self.sq.set_side(2) 85 | actual = self.sq.get_picture() 86 | expected = "**\n**\n" 87 | self.assertEqual(actual, expected, 'Expected square picture to be different.') 88 | 89 | def test_big_picture(self): 90 | self.rect.set_width(51) 91 | self.rect.set_height(3) 92 | actual = self.rect.get_picture() 93 | expected = "Too big for picture." 94 | self.assertEqual(actual, expected, 'Expected message: "Too big for picture."') 95 | 96 | def test_get_amount_inside(self): 97 | self.rect.set_height(10) 98 | self.rect.set_width(15) 99 | actual = self.rect.get_amount_inside(self.sq) 100 | expected = 6 101 | self.assertEqual(actual, expected, 'Expected `get_amount_inside` to return 6.') 102 | 103 | def test_get_amount_inside_two_rectangles(self): 104 | rect2 = shape_calculator.Rectangle(4, 8) 105 | actual = rect2.get_amount_inside(self.rect) 106 | expected = 1 107 | self.assertEqual(actual, expected, 'Expected `get_amount_inside` to return 1.') 108 | 109 | def test_get_amount_inside_none(self): 110 | rect2 = shape_calculator.Rectangle(2, 3) 111 | actual = rect2.get_amount_inside(self.rect) 112 | expected = 0 113 | self.assertEqual(actual, expected, 'Expected `get_amount_inside` to return 0.') 114 | 115 | if __name__ == "__main__": 116 | unittest.main() 117 | --------------------------------------------------------------------------------