Скачиваний:
0
Добавлен:
28.09.2026
Размер:
9 Кб
Скачать
☆
# Импорт библиотеки
import random

# --- Базовый класс Sensor ---
class Sensor:
    def __init__(self, id, calibration_factor, unit):
        """
        Инициализирует базовый датчик.
        :param id: Уникальный идентификатор датчика
        :param calibration_factor: Фактор калибровки (инкапсулирован)
        :param unit: Единица измерения
        """
        self._id = id
        # Используем сеттер для проверки и установки фактора калибровки
        self.calibration_factor = calibration_factor
        self._unit = unit

    @property
    def id(self):
        """Свойство для доступа к идентификатору датчика."""
        return self._id

    @property
    def calibration_factor(self):
        """Свойство для доступа к фактору калибровки."""
        return self._calibration_factor

    @calibration_factor.setter
    def calibration_factor(self, value):
        """
        Сеттер для фактора калибровки.
        Проверяет, что значение — число.
        """
        if not isinstance(value, (int, float)):
            raise ValueError("Коэффициент калибровки должен быть числом!")
        self._calibration_factor = value

    @property
    def unit(self):
        """Свойство для доступа к единице измерения."""
        return self._unit

    def read_data(self):
        """
        Симуляция чтения данных с датчика.
        Возвращает случайное значение, умноженное на фактор калибровки.
        """
        raw_value = random.uniform(0, 100)
        calibrated_value = raw_value * self.calibration_factor
        return calibrated_value

    def __str__(self):
        """Строковое представление датчика для пользователя."""
        return f"Sensor(id={self.id}, unit={self.unit})"

    def __repr__(self):
        """Строковое представление датчика для разработчика."""
        return f"Sensor(id={self.id!r}, calibration_factor={self.calibration_factor!r}, unit={self.unit!r})"

# --- Класс AdvancedSensor, наследующий от Sensor ---
class AdvancedSensor(Sensor):
    def __init__(self, id, calibration_factor, unit, precision, last_calibration_date):
        """
        Инициализирует продвинутый датчик.
        :param precision: Точность датчика (влияет на шум)
        :param last_calibration_date: Дата последней калибровки
        """
        # Вызов конструктора родительского класса
        super().__init__(id, calibration_factor, unit)
        self._precision = precision
        self._last_calibration_date = last_calibration_date

    @property
    def precision(self):
        """Свойство для доступа к точности датчика."""
        return self._precision

    @precision.setter
    def precision(self, value):
        """
        Сеттер для точности датчика.
        Проверяет, что значение — положительное число.
        """
        if not isinstance(value, (int, float)) or value <= 0:
            raise ValueError("Точность должна быть положительным числом!")
        self._precision = value

    @property
    def last_calibration_date(self):
        """Свойство для доступа к дате последней калибровки."""
        return self._last_calibration_date

    def read_data(self):
        """
        Переопределение метода read_data.
        Добавляет шум, зависящий от точности.
        """
        raw_value = super().read_data()  # Получаем откалиброванное значение из родителя
        # Генерируем шум, обратно пропорциональный точности (чем выше точность, тем меньше шум)
        noise = random.uniform(-1, 1) / self.precision
        noisy_value = raw_value + noise
        return noisy_value

    def __str__(self):
        """Строковое представление продвинутого датчика."""
        return f"AdvancedSensor(id={self.id}, unit={self.unit}, precision={self.precision})"

    def __repr__(self):
        """Строковое представление продвинутого датчика для разработчика."""
        return f"AdvancedSensor(id={self.id!r}, calibration_factor={self.calibration_factor!r}, unit={self.unit!r}, precision={self.precision!r}, last_calibration_date={self.last_calibration_date!r})"

# --- Класс Experiment ---
class Experiment:
    def __init__(self, name, start_date):
        """
        Инициализирует эксперимент.
        :param name: Название эксперимента
        :param start_date: Дата начала эксперимента
        """
        self._name = name
        self._start_date = start_date
        # Композиция: эксперимент содержит список датчиков
        self._sensor_list = []

    @property
    def name(self):
        """Свойство для доступа к названию эксперимента."""
        return self._name

    @property
    def sensor_list(self):
        """Свойство для доступа к списку датчиков."""
        return self._sensor_list

    def add_sensor(self, sensor):
        """
        Добавляет датчик в эксперимент.
        :param sensor: Объект Sensor или его наследника
        """
        if not isinstance(sensor, Sensor):
            raise TypeError("Можно калибровать только объекты типа Sensor или его подклассы!")
        self._sensor_list.append(sensor)

    def run(self, iterations=5):
        """
        Запускает эксперимент: собирает данные со всех датчиков.
        :param iterations: Количество итераций сбора данных
        :return: Список словарей с результатами
        """
        results = []
        for i in range(iterations):
            iteration_data = {"iteration": i + 1}
            for sensor in self._sensor_list:
                # Используем полиморфизм: вызываем read_data, который может быть переопределён
                value = sensor.read_data()
                iteration_data[f"sensor_{sensor.id}"] = value
            results.append(iteration_data)
        return results

    def get_average_readings(self):
        """
        Вычисляет среднее значение для каждого датчика за всё время эксперимента.
        :return: Словарь {sensor_id: average_value}
        """
        if not self._sensor_list:
            return {}

        averages = {}
        # Запускаем эксперимент, чтобы получить данные
        data = self.run(iterations=10)  # Собираем 10 итераций для усреднения

        for sensor in self._sensor_list:
            key = f"sensor_{sensor.id}"
            values = [d[key] for d in data]
            avg = sum(values) / len(values)
            averages[sensor.id] = avg

        return averages

    def __str__(self):
        """Строковое представление эксперимента."""
        return f"Experiment(name={self.name}, sensors={len(self._sensor_list)})"

    def __repr__(self):
        """Строковое представление эксперимента для разработчика."""
        return f"Experiment(name={self.name!r}, start_date={self._start_date!r}, sensor_list={self._sensor_list!r})"

# --- Класс Calibrator (доп. задание) ---
class Calibrator:
    """
    Класс для калибровки датчиков.
    """
    @staticmethod
    def calibrate(sensor, new_factor):
        """
        Изменяет фактор калибровки датчика.
        :param sensor: Объект Sensor или его наследника
        :param new_factor: Новый фактор калибровки
        """
        if not isinstance(sensor, Sensor):
            raise TypeError("Можно калибровать только объекты типа Sensor или его подклассы!")
        sensor.calibration_factor = new_factor
        print(f"Датчик {sensor.id} откалиброван с фактором {new_factor}.")
Соседние файлы в папке Лабораторная работа №5