From c54467d929480d58b042ea0ded26e01c84321125 Mon Sep 17 00:00:00 2001 From: GiuliaGGG <144107205+GiuliaGGG@users.noreply.github.com> Date: Wed, 13 Mar 2024 18:53:36 +0100 Subject: [PATCH] Excercise 1 Calculate area and perimeter of a circle from the radius --- .../__pycache__/circle.cpython-311.pyc | Bin 0 -> 1406 bytes .../__pycache__/circle.cpython-312.pyc | Bin 0 -> 160 bytes .../__pycache__/flask_app.cpython-311.pyc | Bin 0 -> 3549 bytes .../__pycache__/helper.cpython-311.pyc | Bin 0 -> 1475 bytes .../__pycache__/helper.cpython-312.pyc | Bin 0 -> 1435 bytes .../__pycache__/test_circle.cpython-311.pyc | Bin 0 -> 1331 bytes calculator_app/circle.py | 51 +++++++++ calculator_app/flask_app.py | 70 +++++++++++++ calculator_app/helper.py | 47 +++++++++ calculator_app/static/main.css | 99 ++++++++++++++++++ calculator_app/templates/calculator.html | 23 ++++ calculator_app/templates/home.html | 5 + calculator_app/templates/layout.html | 25 +++++ calculator_app/templates/perimeter.html | 21 ++++ calculator_app/test_circle.py | 16 +++ 15 files changed, 357 insertions(+) create mode 100644 calculator_app/__pycache__/circle.cpython-311.pyc create mode 100644 calculator_app/__pycache__/circle.cpython-312.pyc create mode 100644 calculator_app/__pycache__/flask_app.cpython-311.pyc create mode 100644 calculator_app/__pycache__/helper.cpython-311.pyc create mode 100644 calculator_app/__pycache__/helper.cpython-312.pyc create mode 100644 calculator_app/__pycache__/test_circle.cpython-311.pyc create mode 100644 calculator_app/circle.py create mode 100644 calculator_app/flask_app.py create mode 100644 calculator_app/helper.py create mode 100644 calculator_app/static/main.css create mode 100644 calculator_app/templates/calculator.html create mode 100644 calculator_app/templates/home.html create mode 100644 calculator_app/templates/layout.html create mode 100644 calculator_app/templates/perimeter.html create mode 100644 calculator_app/test_circle.py diff --git a/calculator_app/__pycache__/circle.cpython-311.pyc b/calculator_app/__pycache__/circle.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d37fc2843fbce5ea638e51174980c1a0d5a15edd GIT binary patch literal 1406 zcmah|&1(}u6rbIEH2tzoYg?%zgQ#tw1U%S76h+$lfmF0sg%SwUor&GL*$K0=k%km< z@X(`$O5?33MZ9?Q&uBf#f>7|(lY!!;7kx9kNkj2tmYw(Bytlvi=Dpv(@9*zHu<+F% zY&DM1cV)CzGExq6pll#U0^4u@fc-N z2MXvxkgO2LXIFx5US@(wo4Y|$FzE}|GNV*V#G>~w56U*G8Ps^8{bE=uf3#MOmR3X5 ztfmmECJPO!T`A@+mM=Nh zSMahu;YUP}5|d1LIc+PT@Q!%0=x`!4IV=dZeGj+&ZRHqx(vt!r7gtzEKFKk3N!66a zGsMNq3{Mcj$ix($0EeyfUI^=0&`stz-P?1`EXYSjUG;Oz>H| zVtX*0IU%^n;d@0)q-3SCwB6?z%A(+>3@@+YDnw`Xg@X7ksO>geW7F8{=X=H>6$zGD+SPlQeKv)uAa%$4d`-u0LBFbB(bh~%O` z%H_Oe3(H~I@>(zys)ben)GYb|yc=F`8n!xWo=2(l>)T(t#&^5MzokdE#v0Q*kKSI} zOJCkdZY1~9LvI$ho^76ORQA%B!0t`g=MUja6eRQ@tv1QvtWC^|U~D7V;j5u{V0~<# ztQ$4Oe53kHw`YdC6(%HxK}Sv06H2 z2%h2##-dL-1|yJy fu*uC&Da}c>D`Ewj#|Xs5AjU^#Mn=XWW*`dybwVgT literal 0 HcmV?d00001 diff --git a/calculator_app/__pycache__/flask_app.cpython-311.pyc b/calculator_app/__pycache__/flask_app.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c95cadc8ca78b5773fa8febba93971bd38e7f6f GIT binary patch literal 3549 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 E-www>VE_OC literal 0 HcmV?d00001 diff --git a/calculator_app/circle.py b/calculator_app/circle.py new file mode 100644 index 0000000..1919608 --- /dev/null +++ b/calculator_app/circle.py @@ -0,0 +1,51 @@ +# create function to calculate the perimeter of a circle by inputting the radius +import math +import unittest + + +# create helper functions for calculations + + +def circle_calculation(value1: float, operation: str) -> float: + """ + Perform a mathematical operation on two values. + + Parameters: + value1 (float): radius + + operation (str): The operation to perform. Can be 'area', 'perimeter" + + Returns: + float: The result of the operation. + + Raises: + ZeroDivisionError: If attempting to divide by zero. + """ + if operation == 'Area': + result = math.pi * value1 ** 2 # πr^2 + else: + result = 2 * math.pi * value1 # 2πr + + return result + + +def convert_to_float(value: str) -> float: + """ + Convert string to floating point number. + + Parameters: + value (str): The value to convert. + + Returns: + float: The converted float value of input value. + + Raises: + ValueError: If value cannot be converted to a float. + """ + + float_value = float(value) + + return float_value + + + diff --git a/calculator_app/flask_app.py b/calculator_app/flask_app.py new file mode 100644 index 0000000..0a7c546 --- /dev/null +++ b/calculator_app/flask_app.py @@ -0,0 +1,70 @@ +from flask import Flask, render_template, request + +from helper import perform_calculation, convert_to_float +from circle import circle_calculation, convert_to_float + + +app = Flask(__name__) # create the instance of the flask class + + +@app.route('/') +@app.route('/home') +def home(): + return render_template('home.html') + + +@app.route('/calculate', methods=['GET', 'POST']) # associating the GET and POST method with this route +def calculate(): + if request.method == 'POST': + # using the request method from flask to request the values that were sent to the server through the POST method + value1 = request.form['value1'] + value2 = request.form['value2'] + operation = str(request.form['operation']) + + # make sure the input is one of the allowed inputs (not absolutely necessary in the drop-down case) + if operation not in ['add', 'subtract', 'divide', 'multiply']: + return render_template('calculator.html', + printed_result='Operation must be one of "add", "subtract", "divide", or "multiply".') + + try: + value1 = convert_to_float(value=value1) + value2 = convert_to_float(value=value2) + except ValueError: + return render_template('calculator.html', printed_result="Cannot perform operation with this input") + + try: + result = perform_calculation(value1=value1, value2=value2, operation=operation) + #result = perform_calculation(value1=value1, operation=operation) + return render_template('calculator.html', printed_result=str(result)) + + except ZeroDivisionError: + return render_template('calculator.html', printed_result="You cannot divide by zero") + + return render_template('calculator.html') + + +@app.route('/perimeter', methods=['GET', 'POST']) # associating the GET and POST method with this route +def perimeter(): + if request.method == 'POST': + # using the request method from flask to request the values that were sent to the server through the POST method + value1 = request.form['value1'] + operation = str(request.form['operation']) + + # make sure the input is one of the allowed inputs (not absolutely necessary in the drop-down case) + if operation not in ['Area', 'Perimeter']: + return render_template('perimeter.html', + printed_result='Operation must be one of "Area", "Perimeter".') + + try: + value1 = convert_to_float(value=value1) + except ValueError: + return render_template('perimeter.html', printed_result="Cannot perform operation with this input") + + try: + result = circle_calculation(value1=value1, operation=operation) + return render_template('perimeter.html', printed_result=str(result)) + + except ZeroDivisionError: + return render_template('perimeter.html', printed_result="You cannot divide by zero") + + return render_template('perimeter.html') diff --git a/calculator_app/helper.py b/calculator_app/helper.py new file mode 100644 index 0000000..5f21aed --- /dev/null +++ b/calculator_app/helper.py @@ -0,0 +1,47 @@ +# create helper functions for calculations + + +def perform_calculation(value1: float, value2: float, operation: str) -> float: + """ + Perform a mathematical operation on two values. + + Parameters: + value1 (float): The first value. + value2 (float): The second value. + operation (str): The operation to perform. Can be 'add', 'subtract', 'divide', or 'multiply'. + + Returns: + float: The result of the operation. + + Raises: + ZeroDivisionError: If attempting to divide by zero. + """ + if operation == 'add': + result = value1 + value2 + elif operation == 'subtract': + result = value1 - value2 + elif operation == 'divide': + result = value1 / value2 + else: + result = value1 * value2 + + return result + + +def convert_to_float(value: str) -> float: + """ + Convert string to floating point number. + + Parameters: + value (str): The value to convert. + + Returns: + float: The converted float value of input value. + + Raises: + ValueError: If value cannot be converted to a float. + """ + + float_value = float(value) + + return float_value diff --git a/calculator_app/static/main.css b/calculator_app/static/main.css new file mode 100644 index 0000000..776cbb4 --- /dev/null +++ b/calculator_app/static/main.css @@ -0,0 +1,99 @@ +/* Global Styles */ +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background-color: #f8f9fa; + color: #333; + margin: 0; + padding: 0; +} + +.container { + max-width: 800px; + margin: 0 auto; + padding: 20px; +} + +/* Header Styles */ +header { + background-color: #343a40; /* Dark neutral color for header */ + color: #fff; /* Light text color for header */ + padding: 10px 0; +} + +#navbar { + display: flex; + justify-content: space-between; + align-items: center; + padding-left: 20px; + padding-right: 20px; +} + +.logo { + margin: 0; + font-size: 24px; +} + +.menu { + list-style-type: none; + padding: 0; +} + +.menu li { + display: inline-block; + margin-right: 20px; +} + +.menu li a { + color: #fff; + text-decoration: none; + font-weight: bold; + font-size: 18px; +} + +h1 a { + color: #ffc8dd; +} + +h1 a:hover { + color: #ffafcc; +} + +.menu li a:hover { + color: #bde0fe; /* Light pastel color on hover */ +} + +/* Calculator Styles */ +h1 { + text-align: center; + margin-top: 0; + font-size: 36px; + color: #343a40; /* Dark neutral color for heading */ +} + +form { + max-width: 400px; + margin: 0 auto; +} + +input[type="text"], +select, +button { + margin: 10px 0; + padding: 10px; + width: 100%; + box-sizing: border-box; + font-size: 16px; +} + +button { + background-color: #343a40; /* Dark neutral color for button */ + color: #fff; + border: none; + cursor: pointer; + font-size: 16px; + transition: background-color 0.3s ease; /* Smooth transition for background color change */ +} + +button:hover { + background-color: #23272b; /* Slightly darker color on hover */ +} diff --git a/calculator_app/templates/calculator.html b/calculator_app/templates/calculator.html new file mode 100644 index 0000000..998ccdf --- /dev/null +++ b/calculator_app/templates/calculator.html @@ -0,0 +1,23 @@ +{% extends 'layout.html' %} +{% block content %} +

Calculator

+
+ + + + + + + +
+ +
+ + {{ printed_result }} + +{% endblock %} \ No newline at end of file diff --git a/calculator_app/templates/home.html b/calculator_app/templates/home.html new file mode 100644 index 0000000..8a634f3 --- /dev/null +++ b/calculator_app/templates/home.html @@ -0,0 +1,5 @@ +{% extends 'layout.html' %} +{% block content %} +

Welcome!

+

Use the navigation bar, to find the calculator you need.

+{% endblock %} \ No newline at end of file diff --git a/calculator_app/templates/layout.html b/calculator_app/templates/layout.html new file mode 100644 index 0000000..3e5b534 --- /dev/null +++ b/calculator_app/templates/layout.html @@ -0,0 +1,25 @@ + + + + + + + + +
+ +
+
+ {% block content %} + {% endblock %} +
+ + \ No newline at end of file diff --git a/calculator_app/templates/perimeter.html b/calculator_app/templates/perimeter.html new file mode 100644 index 0000000..d4785f6 --- /dev/null +++ b/calculator_app/templates/perimeter.html @@ -0,0 +1,21 @@ +{% extends 'layout.html' %} +{% block content %} +

Calculator

+
+ + + + + + +
+ +
+ + {{ printed_result }} + +{% endblock %} + diff --git a/calculator_app/test_circle.py b/calculator_app/test_circle.py new file mode 100644 index 0000000..7e038bd --- /dev/null +++ b/calculator_app/test_circle.py @@ -0,0 +1,16 @@ +import unittest +from circle import circle_calculation + +class TestCircleCalculations(unittest.TestCase): + def test_area(self): + # Testing area calculation + result = circle_calculation(value1=5, operation='Area') + self.assertAlmostEqual(result, 78.53981633974483, places=5) + + def test_perimeter(self): + # Testing perimeter calculation + result = circle_calculation(value1=5, operation='Perimeter') + self.assertAlmostEqual(result, 31.41592653589793, places=5) + +if __name__ == '_main_': + unittest.main()