Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
5.6 kB
5
Indexable
from dataclasses import dataclass


@dataclass
class InfoMessage:
    """Информационное сообщение о тренировке."""

    training_type: str
    duration: float
    distance: float
    speed: float
    calories: float

    def get_message(self) -> str:
        """Возвращает сообщение о тренировке."""

        return (f'Тип тренировки: {self.training_type}; '
                f'Длительность: {self.duration:.3f} ч.; '
                f'Дистанция: {self.distance:.3f} км; '
                f'Ср. скорость: {self.speed:.3f} км/ч; '
                f'Потрачено ккал: {self.calories:.3f}.')


@dataclass()
class Training:
    """Базовый класс тренировки."""

    action: int
    duration: float
    weight: float

    LEN_STEP = 0.65
    M_IN_KM = 1000
    CONVERT_H_TO_MIN = 60

    def get_distance(self) -> float:
        """Получить дистанцию в км."""

        return self.action * self.LEN_STEP / self.M_IN_KM

    def get_mean_speed(self) -> float:
        """Получить среднюю скорость движения."""

        return self.get_distance() / self.duration

    def get_spent_calories(self) -> float:
        """Получить количество затраченных калорий."""

        raise NotImplementedError('Данная функция переопределена'
                                  ' для каждого класса')

    def show_training_info(self) -> InfoMessage:
        """Вернуть информационное сообщение о выполненной тренировке."""

        return InfoMessage(
            training_type=self.__class__.__name__,
            duration=self.duration,
            distance=self.get_distance(),
            speed=self.get_mean_speed(),
            calories=self.get_spent_calories()
        )


@dataclass
class Running(Training):
    """Тренировка: бег."""

    CALORIES_MEAN_SPEED_MULTIPLIER = 18
    CALORIES_MEAN_SPEED_SHIFT = 1.79

    def get_spent_calories(self) -> float:
        """Переопределенная формула потраченных ккал."""

        return (
                self.CALORIES_MEAN_SPEED_MULTIPLIER * self.get_mean_speed()
                + self.CALORIES_MEAN_SPEED_SHIFT
        ) * self.weight / self.M_IN_KM * (
                self.duration * self.CONVERT_H_TO_MIN
        )


@dataclass
class SportsWalking(Training):
    """Тренировка: спортивная ходьба."""

    height: int

    CONVERT_SPEED_IN_H_TO_SEC = 0.278
    CONVERT_HEIGHT = 100
    K1_FOR_COUNTING_CALORIES = 0.035
    K2_FOR_COUNTING_CALORIES = 0.029

    def get_spent_calories(self) -> float:
        """Переопределенная формула потраченных ккал."""

        speed_in_mps = self.get_mean_speed() * self.CONVERT_SPEED_IN_H_TO_SEC
        height_in_m = self.height / self.CONVERT_HEIGHT
        duration_in_min = self.duration * self.CONVERT_H_TO_MIN
        return (
                self.K1_FOR_COUNTING_CALORIES * self.weight
                + (
                        speed_in_mps ** 2 / height_in_m
                ) * self.K2_FOR_COUNTING_CALORIES * self.weight
        ) * duration_in_min


@dataclass
class Swimming(Training):
    """Тренировка: плавание."""

    length_pool: int
    count_pool: int

    LEN_STEP = 1.38
    COEFF_SWM_1 = 1.1
    COEFF_SWM_2 = 2

    def get_mean_speed(self) -> float:
        """Переопределение метода средней скорости для плавания."""

        mean_speed_swimming = (
                self.length_pool * self.count_pool / self.M_IN_KM / self.duration
        )
        return mean_speed_swimming

    def get_spent_calories(self) -> float:
        """Переопределение расчёта израсходованных калорий."""

        total_calories = (
                                 self.get_mean_speed() + self.COEFF_SWM_1
                         ) * self.COEFF_SWM_2 * self.weight * self.duration
        return total_calories


TRAININGS: dict[str: Training] = {
    'SWM': Swimming,
    'RUN': Running,
    'WLK': SportsWalking,
}


def read_package(workout_type: str, data: list) -> Training:
    """Прочитать данные полученные от датчиков."""

    if not isinstance(workout_type, str):
        raise TypeError('Неверный тип данных для workout_type')
    if not isinstance(data, list):
        raise TypeError('Неверный тип данных для data')

    try:
        training_class = TRAININGS[workout_type]
    except KeyError:
        raise ValueError('Фитнес-трекер пока '
                         'не поддерживает данный тип тренировки')

    return training_class(*data)


def main(training: Training) -> None:
    """Главная функция."""

    info = training.show_training_info()
    print(info.get_message())


if __name__ == '__main__':
    packages = [
        ('SWM', [720, 1, 80, 25, 40]),
        ('RUN', [15000, 1, 75]),
        ('WLK', [9000, 1, 75, 180]),
    ]

    for workout_type, data in packages:
        training = read_package(workout_type, data)
        main(training)