'''
Операции сравнения и hash - функция

__eq__ - == (противоположный __ne__)
__ne__ - != (противоположный __eq__)
__lt__ - <  (противоположный __gt__)
__le__ - <= (противоположный __ge__)
__gt__ - >  (противоположный __lt__)
__ge__ - >= (противоположный __le__)

Для сокращения кода можно спользовать @total_ordering



hash() - можно взять только от неизменяемых объектов
Хешируемые объекты могут быть ключами в словарях и элементов множества.

'''

from functools import total_ordering


class OldRectangle:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    @property
    def area(self):
        return self.a * self.b

    '''self - левая сторона, other - правая сторона'''
    ''' Если делать проверку на !=, то питон вызовет противоположный метод'''
    def __eq__(self, other):
        print('__eq__ call')
        if isinstance(other, OldRectangle):
            return self.a == other.b and self.b == other.b
        
    '''метод меньше'''
    def __lt__(self, other):
        print('__lt__ call')
        if isinstance(other, OldRectangle):
            return self.area < other.area
        if isinstance(other, (int, float)):
            return self.area < other
        
    '''Вызовет методы __eq__ и __lt__'''
    def __le__(self, other):
        return self==other or self<other
    

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class ChessPlayer:
    def __init__(self, name, surname, rating):
        self.name = name
        self.surname = surname
        self.rating = rating

    def __eq__(self, other):
        if isinstance(other, ChessPlayer):
            return self.rating == other.rating
        elif isinstance(other, int):
            return self.rating == other
        else:
            return 'Невозможно выполнить сравнение'
        
    def __gt__(self, other):
        if isinstance(other, ChessPlayer):
            return self.rating > other.rating
        elif isinstance(other, int):
            return self.rating > other
        else:
            return 'Невозможно выполнить сравнение'
        
    def __lt__(self, other):
        if isinstance(other, ChessPlayer):
            return self.rating < other.rating
        elif isinstance(other, int):
            return self.rating < other
        else:
            return 'Невозможно выполнить сравнение'
        
def test_1():
    magnus = ChessPlayer('Carlsen', 'Magnus', 2847)
    assert magnus.name == 'Carlsen'
    assert magnus.surname == 'Magnus'
    assert magnus.rating == 2847
    ian = ChessPlayer('Ian', 'Nepomniachtchi', 2789)
    assert not magnus == 4000
    assert ian == 2789
    assert not magnus == ian
    assert magnus > ian
    assert not magnus < ian
    assert (magnus < [1, 2]) == 'Невозможно выполнить сравнение'

    v1 = ChessPlayer('Гарри ', 'Каспаров', 10)
    v2 = ChessPlayer('Бобби', 'Фишер', 20)
    v3 = ChessPlayer('Bot', 'Bot', 20)

    assert isinstance(v1, ChessPlayer)
    assert isinstance(v2, ChessPlayer)
    assert v2.__dict__ == {'name': 'Бобби', 'surname': 'Фишер', 'rating': 20}
    assert v1.__dict__ == {'name': 'Гарри ', 'surname': 'Каспаров', 'rating': 10}
    assert v1 > 5
    assert not v1 > 10
    assert not v1 > 11
    assert not v1 < 5
    assert not v1 < 10
    assert v1 < 11
    assert not v1 == 5
    assert v1 == 10
    assert not v1 == 11
    assert not v1 > v2
    assert not v1 == v2
    assert v3 == v2
    assert not v3 != v2
    assert v1 < v2
    assert (v1 > 'fdsfd') == 'Невозможно выполнить сравнение'
    assert (v1 < 'fdsfd') == 'Невозможно выполнить сравнение'
    assert (v1 == 'fdsfd') == 'Невозможно выполнить сравнение'
    assert (v1 == [1, 2]) == 'Невозможно выполнить сравнение'
    assert (v1 < [1, 2]) == 'Невозможно выполнить сравнение'        
    print('Good')


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@total_ordering
class Account:
    def __init__(self, balance):
        self.balance = balance

    def __eq__(self, other):
        return self.balance == other.balance
    
    def __lt__(self, other):
        return self.balance < other.balance
    

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@total_ordering
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height
    
    def __eq__(self, other):
        if isinstance(other, Rectangle):
            return self.area == other.area
        if isinstance(other, (int, float)):
            return self.area == other
        
    def __lt__(self, other):
        if isinstance(other, Rectangle):
            return self.area < other.area
        if isinstance(other, (int, float)):
            return self.area < other


def main():
    test_1()


if __name__ == '__main__':
    main()