Adafruit_Learning_System_Gu.../PyPortal_Calculator/calculator.py
2022-02-23 14:10:24 -05:00

140 lines
4.8 KiB
Python
Executable file

# SPDX-FileCopyrightText: 2019 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
CircuitPython library to handle the input and calculations
* Author(s): Melissa LeBlanc-Williams
"""
# pylint: disable=eval-used
def calculate(number_one, operator, number_two):
result = eval(number_one + operator + number_two)
if int(result) == result:
result = int(result)
return str(result)
class Calculator:
def __init__(self, calc_display, clear_button, label_offset):
self._error = False
self._calc_display = calc_display
self._clear_button = clear_button
self._label_offset = label_offset
self._accumulator = "0"
self._operator = None
self._equal_pressed = False
self._operand = None
self._all_clear()
def get_current_operator(self):
operator = self._operator
if operator == "*":
operator = "x"
return operator
def _all_clear(self):
self._accumulator = "0"
self._operator = None
self._equal_pressed = False
self._clear_entry()
def _clear_entry(self):
self._operand = None
self._error = False
self._set_button_ce(False)
self._set_text("0")
def _set_button_ce(self, entry_only):
self._clear_button.selected = False
if entry_only:
self._clear_button.label = "CE"
else:
self._clear_button.label = "AC"
def _set_text(self, text):
self._calc_display.text = text
_, _, screen_w, _ = self._calc_display.bounding_box
self._calc_display.x = self._label_offset - screen_w
def _get_text(self):
return self._calc_display.text
def _handle_number(self, input_key):
display_text = self._get_text()
if self._operand is None and self._operator is not None:
display_text = ""
elif self._operand is not None and self._operator is not None and self._equal_pressed:
self._accumulator = self._operand
self._operator = None
self._operand = None
display_text = ""
elif display_text == "0":
display_text = ""
display_text += input_key
self._set_text(display_text)
if self._operator is not None:
self._operand = display_text
self._set_button_ce(True)
self._equal_pressed = False
def _handle_operator(self, input_key):
if input_key == "x":
input_key = "*"
if self._equal_pressed:
self._operand = None
if self._operator is None:
self._operator = input_key
else:
# Perform current calculation before changing input_keys
if self._operand is not None:
self._accumulator = calculate(self._accumulator, self._operator, self._operand)
self._set_text(self._accumulator)
self._operand = None
self._operator = input_key
self._accumulator = self._get_text()
self._equal_pressed = False
def _handle_equal(self):
if self._operator is not None:
if self._operand is None:
self._operand = self._get_text()
self._accumulator = calculate(self._accumulator, self._operator, self._operand)
self._set_text(self._accumulator)
self._equal_pressed = True
def _update_operand(self):
if self._operand is not None:
self._operand = self._get_text()
def add_input(self, input_key):
try:
if self._error:
self._clear_entry()
elif input_key == "AC":
self._all_clear()
elif input_key == "CE":
self._clear_entry()
elif self._operator is None and input_key == "0":
pass
elif len(input_key) == 1 and 48 <= ord(input_key) <= 57:
self._handle_number(input_key)
elif input_key in ('+', '-', '/', 'x'):
self._handle_operator(input_key)
elif input_key == ".":
if not input_key in self._get_text():
self._set_text(self._get_text() + input_key)
self._set_button_ce(True)
self._equal_pressed = False
elif input_key == "+/-":
self._set_text(calculate(self._get_text(), "*", "-1"))
self._update_operand()
elif input_key == "%":
self._set_text(calculate(self._get_text(), "/", "100"))
self._update_operand()
elif input_key == "=":
self._handle_equal()
except (ZeroDivisionError, RuntimeError):
self._all_clear()
self._error = True
self._set_text("Error")