/
Demek
/
DSam621
Обзор
Документация
Войти
/
Demek
/
DSam621
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
Python/hw8.py
203 строки
8 KB
d_e_m_e_k
добавил сохранение расчетов в файл
21 июн 2026, 17:13
21 июн 2026, 17:13
40bc5f0
Код
Авторство
О чём код?
# === Импорты и константы === import datetime from pathlib import Path # === Функция для безопасного ввода положительного числа === def get_valid_number(prompt: str, allow_zero: bool = False) -> float: """Получает валидное положительное число от пользователя""" while True: try: value = float(input(prompt).strip()) if value < 0 or (value == 0 and not allow_zero): print("❌ Значение должно быть положительным числом. Попробуйте снова.") continue return value except ValueError: print("❌ Неверный формат. Введите число (например, 12.5).") # === Универсальная функция для ввода пары чисел с валидацией === def get_two_numbers_with_validation( prompt1: str, prompt2: str, validation_func=None, error_msg: str = "Ошибка ввода! Попробуйте снова." ) -> tuple[float, float]: """ Вводит два числа с валидацией и повтором при ошибке. """ while True: try: num1 = float(input(prompt1).strip()) num2 = float(input(prompt2).strip()) if validation_func and not validation_func(num1, num2): print(error_msg) continue return num1, num2 except ValueError: print("❌ Неверный формат числа. Попробуйте снова.") # === Валидаторы для показаний счётчика === def validate_readings(current: float, prev: float) -> bool: """Проверка показаний: неотрицательные и current >= prev""" if current < 0 or prev < 0: print("❌ Показания не могут быть отрицательными.") return False if current < prev: print("❌ Текущее показание не может быть меньше предыдущего!") return False return True def validate_comparison(current: float, prev: float) -> bool: """Для сравнения: текущий и предыдущий должны быть положительными""" if current <= 0 or prev <= 0: print("❌ Оба значения должны быть положительными (нельзя сравнивать с нулём).") return False return True # === Функция для выбора операции === def get_operation() -> str: """Запрашивает операцию с проверкой""" print("\n" + "=" * 45) print("📚 Доступные операции:") print("1. Расчёт по тарифу (месяц)") print("2. Расчёт по счётчику (разница показаний)") print("3. Сравнение с предыдущим периодом") print("4. Выход") print("=" * 45) while True: op = input("\nВыберите операцию (1-4): ").strip() if op in ['1', '2', '3', '4']: return op print("❌ Введите число от 1 до 4.") # === Функция для расчёта по фиксированному тарифу === def calculate_tariff_based(): """Расчёт по фиксированному тарифу""" print("\n" + "-" * 25) print("💰 Расчёт по фиксированному тарифу") print("-" * 25) consumption = get_valid_number("Введите расход газа (м³): ") tariff = get_valid_number("Введите тариф (руб/м³): ") cost = consumption * tariff result = f"Расход: {consumption:.2f} м³, Тариф: {tariff:.2f} руб/м³" print(f"\n📊 {result}") print(f"💰 Сумма к оплате: {cost:.2f} руб.") save_result_to_file("Расчёт по тарифу", result, f"{cost:.2f} руб.") # === Функция для расчёта по разнице показаний счётчика === def calculate_meter_based(): """Расчёт по разнице показаний счётчика""" print("\n" + "-" * 25) print("📊 Расчёт по показаниям счётчика") print("-" * 25) current, prev = get_two_numbers_with_validation( "Текущее показание (м³): ", "Предыдущее показание (м³): ", validation_func=validate_readings ) tariff = get_valid_number("Тариф (руб/м³): ") consumption = current - prev cost = consumption * tariff result = f"Показания: {prev:.2f} → {current:.2f} м³, Расход: {consumption:.2f} м³" print(f"\n📊 {result}") print(f"💰 Сумма к оплате: {cost:.2f} руб.") save_result_to_file("Расчёт по счётчику", result, f"{cost:.2f} руб.") # === Функция для сравнения с предыдущим периодом === def compare_with_previous(): """Сравнение с предыдущим периодом""" print("\n" + "-" * 25) print("📈 Сравнение с предыдущим периодом") print("-" * 25) current, prev = get_two_numbers_with_validation( "Текущий расход (м³): ", "Прошлый расход (м³): ", validation_func=validate_comparison, error_msg="❌ Оба значения должны быть больше 0. Попробуйте снова." ) diff = current - prev percent = (diff / prev) * 100 if prev > 0 else 0 result = f"Расход: {prev:.2f} → {current:.2f} м³ ({percent:+.1f}%)" print(f"\n📊 Изменение: {diff:.2f} м³ ({percent:+.1f}%)") if diff > 0: print("⚠️ Потребление выросло!") elif diff < 0: print("✅ Потребление сократилось!") else: print("→ Потребление не изменилось.") save_result_to_file("Сравнение периодов", result, f"Изменение: {diff:+.2f} м³ ({percent:+.1f}%)") # === Функция сохранения в файл === def save_result_to_file(title: str, details: str, cost: str): """Сохраняет результаты расчёта в текстовый файл рядом с исполняемым файлом""" timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") report = f"[{timestamp}] {title}\n{details}\n{cost}\n{'-' * 30}\n" # 🎯 Получаем путь к директории, где лежит скрипт (hw8.py) script_dir = Path(__file__).resolve().parent reports_dir = script_dir / "gas_reports" # Создаём папку, если её нет reports_dir.mkdir(exist_ok=True) # Формируем путь к файлу отчёта file_path = reports_dir / "calc_history.txt" # Сохраняем with open(file_path, "a", encoding="utf-8") as f: f.write(report) # === Основная функция === def main(): """Основная функция""" print("\n🧮 Расчёт потребления газа (финальная версия)") print("=" * 45) print("💡 Результаты сохраняются в папке 'gas_reports'") while True: op = get_operation() match op: case '1': calculate_tariff_based() case '2': calculate_meter_based() case '3': compare_with_previous() case '4': print("\n👋 Спасибо за использование! До свидания.") print(f"📝 История сохранена в: gas_reports/calc_history.txt") break case _: print("❌ Непредвиденная ошибка. Попробуйте снова.") if __name__ == "__main__": main()