<reponame>nethy/profile-generator
from __future__ import annotations

import math
from collections.abc import Iterator

from .precision import DECIMALS, equals


class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

    def distance(self, other: Point) -> float:
        diff_x = self.x - other.x
        diff_y = self.y - other.y
        return math.sqrt(math.pow(diff_x, 2) + math.pow(diff_y, 2))

    @property
    def gradient(self) -> float:
        return self.y / self.x if not math.isclose(self.x, 0) else math.inf

    def __repr__(self) -> str:
        return f"Point(x={self.x:.{DECIMALS}f}, y={self.y:.{DECIMALS}f})"

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Point):
            return NotImplemented

        return equals(self.x, other.x) and equals(self.y, other.y)

    def __ne__(self, other: object) -> bool:
        if not isinstance(other, Point):
            return NotImplemented

        return not self.__eq__(other)

    def __lt__(self, other: object) -> bool:
        if not isinstance(other, Point):
            return NotImplemented

        return self.x < other.x or (math.isclose(self.x, other.x) and self.y < other.y)

    def __add__(self, operand: Point) -> Point:
        return Point(self.x + operand.x, self.y + operand.y)

    __radd__ = __add__

    __iadd__ = __add__

    def __mul__(self, operand: float) -> Point:
        return Point(self.x * operand, self.y * operand)

    __rmul__ = __mul__

    def __truediv__(self, other: float) -> Point:
        return Point(self.x / other, self.y / other)

    def __hash__(self) -> int:
        return hash((self.x, self.y))

    def __iter__(self) -> Iterator[float]:
        yield self.x
        yield self.y

from __future__ import annotations

import math
from collections.abc import Iterator

from .precision import DECIMALS, equals


class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

    def distance(self, other: Point) -> float:
        diff_x = self.x - other.x
        diff_y = self.y - other.y
        return math.sqrt(math.pow(diff_x, 2) + math.pow(diff_y, 2))

    @property
    def gradient(self) -> float:
        return self.y / self.x if not math.isclose(self.x, 0) else math.inf

    def __repr__(self) -> str:
        return f"Point(x={self.x:.{DECIMALS}f}, y={self.y:.{DECIMALS}f})"

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Point):
            return NotImplemented

        return equals(self.x, other.x) and equals(self.y, other.y)

    def __ne__(self, other: object) -> bool:
        if not isinstance(other, Point):
            return NotImplemented

        return not self.__eq__(other)

    def __lt__(self, other: object) -> bool:
        if not isinstance(other, Point):
            return NotImplemented

        return self.x < other.x or (math.isclose(self.x, other.x) and self.y < other.y)

    def __add__(self, operand: Point) -> Point:
        return Point(self.x + operand.x, self.y + operand.y)

    __radd__ = __add__

    __iadd__ = __add__

    def __mul__(self, operand: float) -> Point:
        return Point(self.x * operand, self.y * operand)

    __rmul__ = __mul__

    def __truediv__(self, other: float) -> Point:
        return Point(self.x / other, self.y / other)

    def __hash__(self) -> int:
        return hash((self.x, self.y))

    def __iter__(self) -> Iterator[float]:
        yield self.x
        yield self.y