diff --git a/lesson-8/helper.py b/lesson-8/helper.py new file mode 100644 index 0000000..5e5442e --- /dev/null +++ b/lesson-8/helper.py @@ -0,0 +1,22 @@ +def int_input(prompt): + return typed_input(prompt, int) + + +def str_input(prompt): + return typed_input(prompt, str) + + +def float_input(prompt): + return typed_input(prompt, float) + + +def typed_input(prompt, input_type): + value = None + while True: + try: + value = input_type(input(prompt)) + except ValueError: + print('Input error') + continue + break + return value diff --git a/lesson-8/task-1.py b/lesson-8/task-1.py new file mode 100644 index 0000000..02ccc5d --- /dev/null +++ b/lesson-8/task-1.py @@ -0,0 +1,42 @@ +import re + + +def get_max_month_days(month): + if month == 2: + return 28 + elif month in [4, 6, 9, 11]: + return 30 + return 31 + + +class Date: + def __init__(self, date_str): + if self.validate(date_str): + self.date = date_str + else: + raise ValueError + + def __str__(self): + return self.date + + @classmethod + def parse(cls, date_str): + # return map(int, date_str.split('-')) + date_split = date_str.split('-') + return int(date_split[0]), int(date_split[1]), int(date_split[2]) + + @staticmethod + def validate(date_str): + if not re.match(r'\d{1,2}-\d{1,2}-\d{4}', date_str): + return False + day, month, year = Date.parse(date_str) + has_errors = month not in range(1, 12) + has_errors |= day not in range(1, get_max_month_days(month)) + return not has_errors + + +try: + print(Date.parse('46-4-2341')) + print(Date.validate('46-4-2341')) +except ValueError: + print('Date error') diff --git a/lesson-8/task-2.py b/lesson-8/task-2.py new file mode 100644 index 0000000..bf2b788 --- /dev/null +++ b/lesson-8/task-2.py @@ -0,0 +1,24 @@ +from helper import int_input + + +class MyZeroDivisionExtension(Exception): + pass + + +class Number: + def __init__(self, num: int): + self.num = num + + def __truediv__(self, other): + if other.num == 0: + raise MyZeroDivisionExtension('Division by zero') + return self.num/other.num + + +number1 = Number(int_input('Enter number 1: ')) +number2 = Number(int_input('Enter number 2: ')) + +try: + print('Div: ', number1 / number2) +except MyZeroDivisionExtension as e: + print(e.__class__.__name__, ':', e) diff --git a/lesson-8/task-3.py b/lesson-8/task-3.py new file mode 100644 index 0000000..f43921c --- /dev/null +++ b/lesson-8/task-3.py @@ -0,0 +1,37 @@ +import re + + +class InvalidListValueException(Exception): + pass + + +class IntList: + def __init__(self): + self._elements = [] + + @staticmethod + def validate(value): + return re.match(r'\d+', value) + + def append(self, value): + if not self.validate(value): + raise InvalidListValueException('Input value must be number') + self._elements.append(int(value)) + + def __str__(self): + return ' '.join(map(str, self._elements)) + + +int_list = IntList() +while True: + input_string = input('Enter number or stop: ') + if input_string.lower() == 'stop': + break + + try: + int_list.append(input_string) + except InvalidListValueException as e: + print(e.__class__.__name__, ':', e) + +print('Result:') +print(int_list) diff --git a/lesson-8/task-4_6.py b/lesson-8/task-4_6.py new file mode 100644 index 0000000..a1a8944 --- /dev/null +++ b/lesson-8/task-4_6.py @@ -0,0 +1,54 @@ +import datetime +import random +import string + +from warehouse import models + +BRANDS_LIST = ['Canon', 'LG', 'Philips', 'Xiaomi'] + + +def generate_model_name(): + return '%s (%s)' % ( + random.choice(BRANDS_LIST), + random.choices(string.ascii_uppercase + string.digits, k=8) + ) + + +def generate_equip(): + cls = random.choice(models.Equipment.__subclasses__()) + return cls( + model=generate_model_name(), + year=random.randint(2000, datetime.date.today().year), + is_new=random.choice([True, False, True]) + ) + + +equipments = [generate_equip() for i in range(10)] + +eq_1 = equipments[0] +eq_2 = equipments[1] + +deparment_1 = models.Department('Department 1') +deparment_2 = models.Department('Department 2') +warehouse = models.Warehouse('Main') + +warehouse.append_list(equipments) +print('==== WAREHOUSE BALANCE ====') +warehouse.balance() +print('==================') +warehouse.append(eq_1) + +warehouse.move_equipment(eq_1, deparment_1) +warehouse.move_equipment(eq_2, deparment_1) +warehouse.move_equipment(eq_1, deparment_2) +print('========= DEPARTMENT 1 BALANCE =========') +deparment_1.balance() +print('==================') + +try: + warehouse.move_equipments(models.Printer.__name__, deparment_2, 2) +except AssertionError as e: + print('На складе нет столько техники') +print('========= DEPARTMENT 2 BALANCE =========') +deparment_2.balance() +print('==================') diff --git a/lesson-8/task-7.py b/lesson-8/task-7.py new file mode 100644 index 0000000..283dc33 --- /dev/null +++ b/lesson-8/task-7.py @@ -0,0 +1,56 @@ +import unittest + + +class Complex: + def __init__(self, real, imagine): + assert isinstance(real, int) + assert isinstance(imagine, int) + self.real = real + self.imagine = imagine + + def __add__(self, other): + return Complex(self.real + other.real, self.imagine + other.imagine) + + def __mul__(self, other): + return Complex( + real=(self.real * other.real - self.imagine * other.imagine), + imagine=(self.real * other.imagine + self.imagine * other.real) + ) + + def __str__(self): + if self.imagine == 0: + return str(self.real) + + return '(%s%s%sj)' % ( + self.real, + '+' if self.imagine > 0 else '-', + abs(self.imagine) if self.imagine != 1 else '' + ) + + +class ComplexTest(unittest.TestCase): + def test_str(self): + complex_1 = Complex(1, 2) + complex_2 = complex(1, 2) + self.assertEqual(str(complex_1), str(complex_2)) + + def test_add(self): + c_1_1 = Complex(1, 2) + c_1_2 = Complex(2, 1) + + c_2_1 = complex(1, 2) + c_2_2 = complex(2, 1) + + self.assertEqual(str(c_1_1 + c_1_2), str(c_2_1 + c_2_2)) + + def test_mul(self): + c_1_1 = Complex(3, 1) + c_1_2 = Complex(8, 4) + + c_2_1 = complex(3, 1) + c_2_2 = complex(8, 4) + + self.assertEqual(str(c_1_1 * c_1_2), str(c_2_1 * c_2_2)) + + +unittest.main() diff --git a/lesson-8/warehouse/__init__.py b/lesson-8/warehouse/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lesson-8/warehouse/models.py b/lesson-8/warehouse/models.py new file mode 100644 index 0000000..89f624b --- /dev/null +++ b/lesson-8/warehouse/models.py @@ -0,0 +1,143 @@ +import random + + +class Department: + def __init__(self, name: str): + assert len(name) > 0 + self.name = name + self._storage = [] + self._counts = {cls.__name__: 0 for cls in Equipment.__subclasses__()} + + def append(self, equipment): + assert issubclass(equipment.__class__, Equipment) + if not self.find_in_storage(equipment): + self._storage.append(equipment) + self._counts[equipment.__class__.__name__] += 1 + else: + print('Техника уже на складе') + + def append_list(self, equipments): + for equipment in equipments: + self.append(equipment) + + def remove(self, equipment): + assert issubclass(equipment.__class__, Equipment) + if self.find_in_storage(equipment): + self._storage.remove(equipment) + self._counts[equipment.__class__.__name__] -= 1 + return True + return False + + def find_in_storage(self, equipment): + assert issubclass(equipment.__class__, Equipment) + return next((x for x in self._storage if x == equipment), None) + + def get_all(self, equipment_type): + # return [x for x in self._storage if x.__class__ == equipment_type] + for x in self._storage: + if x.__class__.__name__ == equipment_type: + yield x + + def balance(self): + for cls, cnt in self._counts.items(): + print(f'{cls}: {cnt}') + + +class Warehouse(Department): + + def move_equipment(self, equipment, department): + if self.remove(equipment): + department.append(equipment) + else: + print('На складе нет необходимой техники') + + def back_equipment(self, equipment, department): + if department.remove(equipment): + self.append(equipment) + else: + print('В отделении нет необходимой техники') + + def move_equipments(self, equipment_type, deparmet, count): + assert self._counts[equipment_type] >= count + for equipment in self.get_all(equipment_type): + self.move_equipment(equipment, deparmet) + + +class Equipment: + def __init__(self, model: str, year: int, is_new: bool): + self.serial = random.randint(10000, 999999) # серийный номер + self.model = model # модель + self.year = year # год выпуска + self.is_new = is_new # новый/бу + self.is_broken = False + + def __str__(self): + return f'{self.serial} {self.model} {self.year}' + + def broke(self): + print('Упс! Устройство сломалось') + self.is_broken = True + + def repair(self): + self.is_broken = False + self.is_new = False + + def action(self): # действие устройства + if random.randint(0, 100) < 10: + self.broke() + return True + + def __eq__(self, other): + return isinstance(other, self.__class__) and other.serial == self.serial + + +class Printer(Equipment): + def __init__(self, model, year, is_new): + super().__init__(model, year, is_new) + self._ink = {'r': 0, 'g': 0, 'b': 0} # черлила + + def refuel(self): + self._ink = {'r': 100, 'g': 100, 'b': 100} + + def action(self): + if not self.can_print(): + self._empty_ink_signal() + return False + # при печати принтер тратит бумагу + for k, ink in self._ink.items(): + self._ink[k] = random.randint(0, ink - 10) if ink - 10 > 0 else 0 + return super().action() + + def can_print(self): + ret = True + for ink in self._ink: + ret &= ink > 0 + return ret + + def _empty_ink_signal(self): + print('Кончились чернила, необходимо замена') + + +class Fax(Equipment): + def __init__(self, model, year, is_new): + super().__init__(model, year, is_new) + self._papers = 100 + + def action(self): + if self._papers == 0: + print('Закончилась бумага') + return False + self._papers -= random.randint(1, self._papers) + return super().action() + + +class Scaner(Equipment): + def action(self): + print('Сканирование...') + return super().action() + + +class Xerox(Equipment): + def action(self): + print('Ксерокопирование...') + return super().action()