practica_olynin/Практика.py

169 lines
5.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
from __future__ import annotations
from collections import defaultdict
from pathlib import Path
Order = dict[str, str | int | float]
def load_orders(filepath: str) -> list[Order]:
orders: list[Order] = []
with open(filepath, "r", encoding="utf-8") as file:
for line_number, raw_line in enumerate(file, start=1):
line = raw_line.strip()
if not line:
continue
parts = [part.strip() for part in line.split(",")]
if len(parts) != 4:
raise ValueError(
f"Некорректный формат строки {line_number}: ожидалось 4 поля."
)
customer, drink, quantity_text, price_text = parts
try:
quantity = int(quantity_text)
price = float(price_text)
except ValueError as error:
raise ValueError(
f"Ошибка в числовых данных строки {line_number}: {line}"
) from error
orders.append(
{
"customer": customer,
"drink": drink.title(),
"quantity": quantity,
"price": price,
}
)
return orders
def normalize_names(orders: list[Order]) -> list[Order]:
normalized_orders: list[Order] = []
for order in orders:
normalized_order = order.copy()
customer = str(normalized_order["customer"]).strip()
normalized_order["customer"] = customer.capitalize()
normalized_orders.append(normalized_order)
return normalized_orders
def filter_by_drink(orders: list[Order], drink: str) -> list[Order]:
target = drink.strip().lower()
return [
order
for order in orders
if str(order["drink"]).strip().lower() == target
]
def calculate_total(orders: list[Order]) -> float:
return sum(float(order["quantity"]) * float(order["price"]) for order in orders)
def top_clients(orders: list[Order], n: int) -> list[str]:
spent_by_client: defaultdict[str, float] = defaultdict(float)
for order in orders:
customer = str(order["customer"])
spent_by_client[customer] += float(order["quantity"]) * float(order["price"])
sorted_clients = sorted(
spent_by_client.items(),
key=lambda item: (-item[1], item[0]),
)
return [client for client, _ in sorted_clients[:n]]
def drinks_summary(orders: list[Order]) -> dict[str, int]:
summary: defaultdict[str, int] = defaultdict(int)
for order in orders:
drink = str(order["drink"]).strip().title()
summary[drink] += int(order["quantity"])
return dict(summary)
def most_popular_drink(summary: dict[str, int]) -> str:
if not summary:
return ""
return max(summary, key=summary.get)
def average_order_value(orders: list[Order]) -> float:
if not orders:
return 0.0
return round(calculate_total(orders) / len(orders), 2)
def format_report(
summary: dict[str, int], top: list[str], popular: str, total: float
) -> str:
drinks_lines = "\n".join(
f"- {drink}: {quantity}" for drink, quantity in sorted(summary.items())
)
top_clients_line = ", ".join(top) if top else "Нет данных"
return (
"===== Отчет по кофейне =====\n"
"Сводка по напиткам:\n"
f"{drinks_lines}\n"
f"Самый популярный напиток: {popular}\n"
f"Топ клиентов: {top_clients_line}\n"
f"Общая выручка: {total:.2f} руб.\n"
"============================"
)
def save_report(report: str, filepath: str) -> None:
path = Path(filepath)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(report, encoding="utf-8-sig")
def main() -> None:
base_dir = Path(__file__).resolve().parent
data_path = base_dir / "data" / "data.txt"
report_path = base_dir / "data" / "report.txt"
orders = load_orders(str(data_path))
orders = normalize_names(orders)
summary = drinks_summary(orders)
popular_drink = most_popular_drink(summary)
popular_orders = filter_by_drink(orders, popular_drink)
print(f"Заказы по напитку '{popular_drink}':")
for order in popular_orders:
print(
f"{order['customer']} - {order['drink']} - "
f"{order['quantity']} шт. по {order['price']:.2f} руб."
)
total = calculate_total(orders)
top = top_clients(orders, 3)
average = average_order_value(orders)
print(f"\nСредняя стоимость заказа: {average:.2f} руб.")
report = format_report(summary, top, popular_drink, total)
save_report(report, str(report_path))
print("\nОтчет сформирован:")
print(report)
print(f"\nОтчет сохранен в файл: {report_path}")
if __name__ == "__main__":
main()