Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions projects/002-polygon-area-calculator/main.py

This file was deleted.

5 changes: 5 additions & 0 deletions projects/002-polygon-area-calculator/python/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from poligon_calculator.controller import Controller

if __name__ == "__main__":
controller = Controller()
controller.start()
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
from poligon_calculator.input import Input
from poligon_calculator.output import Output
from poligon_calculator.shape_calculator import ShapeCalculator


class Controller:
"""Main controller class responsible for managing user interactions
and delegating shape-related operations to the ShapeCalculator.
"""

def __init__(self):
"""Initialize the Controller instance and create a ShapeCalculator object."""
self.shape_calculator = ShapeCalculator()

def start(self) -> None:
"""Start the program by displaying the intro menu and handling user choices."""
Output.welcome()
choice = Input.get_intro_menu_selection()

match choice:
case 1:
self.handle_rect()
case 2:
self.handle_square()
case 3:
self.handle_square_and_rect()
case _:
print("You didn't enter a valid choice")
return
self.second_menu()

def handle_rect(self) -> None:
"""Handle the creation of a rectangle by collecting user input and storing it."""

width, height = Input.create_rectangle()
self.shape_calculator.create_rectangle(width, height)
print("Rectangle create successfully")

def handle_square(self) -> None:
"""Handle the creation of a square by collecting user input and storing it."""

side = Input.create_square()
self.shape_calculator.create_square(side)
print("Square create successfully")

def handle_square_and_rect(self) -> None:
"""Handle the creation of both a rectangle and a square."""

self.handle_rect()
self.handle_square()

def second_menu(self) -> None:
"""Display the secondary menu and handle subsequent user interactions."""

while True:
choice = Input.menu_after_shape()

match choice:
case 1:
self.show_specs()
case 2:
self.calculate_square_in_rect()

case 3:
self.modify_shapes()
case 4:
print("Thank you for using this program")
break
case _:
print("You didn't enter a valid choice")

def show_specs(self) -> None:
"""Display the specifications (area, perimeter, etc.) of the chosen shape."""

shape_choice = Input.get_shape()

if shape_choice == 1:
if self.shape_calculator.rectangle:
Output.print_shape_specs(self.shape_calculator.rectangle)
else:
print("You didn't enter a valid shape")
elif shape_choice == 2:
if self.shape_calculator.square:
Output.print_shape_specs(self.shape_calculator.square)
else:
print("You didn't enter a valid shape")

def calculate_square_in_rect(self) -> None:
"""Calculate how many squares fit inside the rectangle.

This method ensures that both shapes exist. If not, it prompts
the user to create them first. It then calls the calculator
to determine how many squares can fit within the rectangle.
"""
try:
if not self.shape_calculator.rectangle:
choice = Input.if_not_rectangle()
if choice == "y":
self.handle_rect()
else:
return

if not self.shape_calculator.square:
choice = Input.if_not_square()
if choice == "y":
self.handle_square()
else:
return

amount = self.shape_calculator.square_in_rectangle()
if amount is not None:
Output.print_how_square_in_rect(amount)
except Exception as e:
print(f"Error calculating square in rectangle: {e}")

def modify_shapes(self) -> None:
"""Allow the user to modify the measures of existing shapes.

Raises:
Exception: If an unexpected error occurs during modification.
"""
try:
if not self.shape_calculator.rectangle and not self.shape_calculator.square:
print("No shape has been created.")
return

result = Input.modify_measures()

if result is None:
return

if result[0] == "rectangle":
if self.shape_calculator.rectangle:
_, width, height = result
self.shape_calculator.set_width(width)
self.shape_calculator.set_height(height)
print("Rectangle modify successfully")
else:
print("You didn't enter a valid shape")

elif result[0] == "square":
if self.shape_calculator.square:
_, side = result
self.shape_calculator.set_side(side)
print("Square modify successfully")
else:
print("You didn't enter a valid shape")
except Exception as e:
print(f"Error modifying shape: {e}")
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
class Input:
"""Class responsible for handling all user input operations."""

def create_rectangle() -> tuple[int, int]:
"""Prompt the user to input the dimensions of a rectangle.

Returns:
tuple[int, int]: A tuple containing the width and height of the rectangle.
"""
while True:
width: int = Input.validate_positive_number("Insert width: ")
height: int = Input.validate_positive_number("Insert height: ")
if width != height:
return width, height
else:
print("Width and height must be greater than or equal to two.")

def create_square() -> int:
"""Prompt the user to input the side length of a square.

Returns:
int: The side length of the square.
"""
width: int = Input.validate_positive_number("Insert side length: ")
return width

def get_intro_menu_selection() -> int | None:
"""Display the main menu and get the user's choice of shape.

Returns:
int | None: The user's menu selection (1, 2, or 3), or None if invalid input is entered.
"""
print("What shape do you want to work on?")
print("1. Rectangle")
print("2. Square")
print("3. Rectangle / Square\n")
try:
while (choice := (int(input("Enter your choice: ")))) not in (1, 2, 3):
print("Invalid input. Try again.")
return choice
except ValueError:
print("Please enter a number.")

def validate_positive_number(prompt: str) -> int:
"""Validate that the user input is a positive integer.

Args:
prompt (str): The text prompt displayed to the user.

Returns:
int: A positive integer input by the user.
"""
while True:
try:
number = int(input(prompt))
if number > 0:
return number

print("Please enter a positive number")
except ValueError:
print("Please enter a positive number")

def if_not_square() -> str:
"""Ask the user if they want to create a square when one does not exist.

Returns:
str: 'y' if the user wants to create a square, 'n' otherwise.
"""

print("For use this function, you must create a square shape.")
while (choose := (input("Do you want create it?(y/n) "))) not in ("y", "n"):
print("Please enter y or n")
return choose

def if_not_rectangle() -> str:
"""Ask the user if they want to create a rectangle when one does not exist.

Returns:
str: 'y' if the user wants to create a rectangle, 'n' otherwise.
"""
print("For use this function, you must create a rectangle shape.")
while (choose := (input("Do you want create it?(y/n) "))) not in ("y", "n"):
print("Please enter y or n")
return choose

def get_shape() -> int:
"""Ask the user which shape they want to view.

Returns:
int | None: 1 for rectangle, 2 for square, or None if invalid input is entered.
"""
print("Which shape do you want to view?")
print("1. Rectangle")
print("2. Square")
try:
while (choice := (int(input("Choose shape: ")))) not in (1, 2):
print("Invalid input. Try again.")
return choice
except ValueError:
print("Please enter a number.")

def menu_after_shape() -> int:
"""Display the post-creation menu and get the user's choice.

Returns:
int | None: The user's menu selection (1–4), or None if invalid input is entered.
"""
print("1. Calculate shape specs (Area, Perimeter, Diagonal)")
print("2. Calculate amount square inside rectangle")
print("3. Modify measures")
print("4. Exit")
try:
while (choice := (int(input("Enter your choice: ")))) not in (1, 2, 3, 4):
print("Invalid input. Try again.")
return choice
except ValueError:
print("Please enter a number.")

def modify_measures() -> tuple[str, int, int] | tuple[str, int] | None:
"""Allow the user to modify the dimensions of a shape.

Returns:
tuple[str, int, int] | tuple[str, int] | None:
A tuple containing the shape type and its new dimensions,
or None if invalid input is entered.
- ("rectangle", width, height)
- ("square", side)
"""
print("\nWhich shape do you want to modify?")
print("1. Rectangle")
print("2. Square")

try:
while (choice := int(input("Choose shape: "))) not in (1, 2):
print("Please enter 1 or 2")
if choice == 1:
width = Input.validate_positive_number("Enter new width: ")
height = Input.validate_positive_number("Enter new height: ")
return "rectangle", width, height
elif choice == 2:
side = Input.validate_positive_number("Enter new side: ")
return "square", side
except ValueError:
print("Please enter a valid number")
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class Output:
"""Class responsible for displaying information to the user."""

def welcome() -> None:
"""Display a welcome message at the start of the program."""
print("WELCOME TO THE SHAPE CALCULATOR\n")

def print_shape_specs(shape) -> None:
"""Print the specifications of a given shape, including dimensions,
area, perimeter, diagonal, and a visual representation.

Args:
shape: The shape object containing geometric data.
"""
specs = f"{shape}:\n"
specs += f"Width: {shape.width} Height: {shape.height}\n"
specs += f"Area: {shape.get_area()}\n"
specs += f"Perimeter: {shape.get_perimeter()}\n"
specs += f"Diagonal: {shape.get_diagonal():.2f}\n"
specs += f"Pic:\n{shape.get_picture()}"
print(specs)

def print_how_square_in_rect(amount: int) -> None:
"""Print the number of squares that can fit inside a rectangle.

Args:
amount (int): The number of squares that fit within the rectangle.
"""
print(f"In rectangle area can stay {amount} square units")
Loading