diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..e97d5fd
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..82fd352
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,154 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "associatedIndex": 4
+}
+
+
+
+
+
+ {
+ "keyToString": {
+ "ModuleVcsDetector.initialDetectionPerformed": "true",
+ "Python.main.executor": "Run",
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
+ "RunOnceActivity.git.unshallow": "true",
+ "RunOnceActivity.typescript.service.memoryLimit.init": "true",
+ "ai.playground.ignore.import.keys.banner.in.settings": "true",
+ "git-widget-placeholder": "main",
+ "ignore.virus.scanning.warn.message": "true",
+ "nodejs_package_manager_path": "npm",
+ "settings.editor.selected.configurable": "configurable.group.editor",
+ "vue.rearranger.settings.migration": "true"
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1775246703281
+
+
+ 1775246703281
+
+
+
+
+
+
+
+
+ 1775249257265
+
+
+
+ 1775249257265
+
+
+
+ 1776443190676
+
+
+
+ 1776443190676
+
+
+
+ 1776443228265
+
+
+
+ 1776443228265
+
+
+
+ 1776443742206
+
+
+
+ 1776443742206
+
+
+
+ 1776443836846
+
+
+
+ 1776443836846
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data/sales.csv b/data/sales.csv
new file mode 100644
index 0000000..4f1a4de
--- /dev/null
+++ b/data/sales.csv
@@ -0,0 +1,20 @@
+Ноутбук,Электроника,1200,5,2024-01-15
+Мышь,Электроника,25,15,2024-01-20
+Клавиатура,Электроника,45,10,2024-02-10
+Кофеварка,Техника,150,3,2024-02-15
+Футболка,Одежда,20,50,2024-02-20
+Джинсы,Одежда,60,20,2024-03-05
+Лампа,Дом,35,12,2024-03-12
+Чайник,Техника,80,8,2024-03-20
+Монитор,Электроника,300,4,2024-04-01
+Носки,Одежда,5,100,2024-04-05
+Рюкзак,Аксессуары,55,15,2024-04-10
+Книга,Хобби,15,30,2024-01-25
+Блокнот,Хобби,8,40,2024-02-01
+Ручка,Хобби,2,200,2024-02-05
+Коврик для йоги,Спорт,25,20,2024-03-15
+Гантели,Спорт,40,10,2024-04-12
+Наушники,Электроника,90,12,2024-04-18
+Сковорода,Дом,45,6,2024-01-30
+Подушка,Дом,25,14,2024-02-28
+Зеркало,Дом,110,2,2024-03-25
diff --git a/data/sales.txt b/data/sales.txt
new file mode 100644
index 0000000..e69de29
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..ec959c9
--- /dev/null
+++ b/main.py
@@ -0,0 +1,117 @@
+import csv
+from collections import defaultdict
+
+
+def load_data(filepath: str) -> list[dict]:
+ records = []
+ with open(filepath, mode='r', encoding='utf-8') as f:
+ reader = csv.reader(f)
+ for row in reader:
+ if not row: continue
+ name, category, price, quantity, date = row
+ records.append({
+ "name": name.strip(),
+ "category": category.strip(),
+ "price": float(price),
+ "quantity": int(quantity),
+ "date": date.strip()
+ })
+ return records
+
+
+def clean_data(records: list[dict]) -> list[dict]:
+ cleaned = []
+ for r in records:
+ if r['price'] >= 0 and r['quantity'] >= 0:
+ r['category'] = r['category'].lower()
+ cleaned.append(r)
+ return cleaned
+
+
+def filter_by_category(records: list[dict], category: str) -> list[dict]:
+ return [r for r in records if r['category'] == category.lower()]
+
+
+def filter_by_price_range(records: list[dict], min_price: float, max_price: float) -> list[dict]:
+ return [r for r in records if min_price <= r['price'] <= max_price]
+
+
+def total_revenue(records: list[dict]) -> float:
+ return sum(r['price'] * r['quantity'] for r in records)
+
+
+def category_revenue(records: list[dict]) -> dict[str, float]:
+ rev_map = defaultdict(float)
+ for r in records:
+ rev_map[r['category']] += r['price'] * r['quantity']
+ return dict(rev_map)
+
+
+def top_n_items(records: list[dict], n: int) -> list[tuple[str, int]]:
+ counts = defaultdict(int)
+ for r in records:
+ counts[r['name']] += r['quantity']
+ sorted_items = sorted(counts.items(), key=lambda x: x[1], reverse=True)
+ return sorted_items[:n]
+
+
+def monthly_sales(records: list[dict]) -> dict[str, float]:
+ monthly_rev = defaultdict(float)
+ for r in records:
+ month = r['date'][:7] # Извлекает YYYY-MM
+ monthly_rev[month] += r['price'] * r['quantity']
+ return dict(sorted(monthly_rev.items()))
+
+
+def best_selling_category(records: list[dict]) -> str:
+ cat_rev = category_revenue(records)
+ if not cat_rev: return ""
+ return max(cat_rev, key=cat_rev.get)
+
+
+def export_summary(records: list[dict], output_path: str) -> None:
+ rev = total_revenue(records)
+ best_cat = best_selling_category(records)
+ top3 = top_n_items(records, 3)
+ monthly = monthly_sales(records)
+
+ with open(output_path, 'w', encoding='utf-8') as f:
+ f.write("СВОДНЫЙ ОТЧЕТ ПО ПРОДАЖАМ\n")
+ f.write("=" * 30 + "\n")
+ f.write(f"Общая выручка: {rev:.2f}\n")
+ f.write(f"Лучшая категория: {best_cat}\n\n")
+ f.write("Топ-3 товара (по количеству):\n")
+ for name, qty in top3:
+ f.write(f"- {name}: {qty} шт.\n")
+ f.write("\nВыручка по месяцам:\n")
+ for month, m_rev in monthly.items():
+ f.write(f"- {month}: {m_rev:.2f}\n")
+
+
+def main():
+ #Пометки для себя любимого
+ #Загрузка
+ data = load_data("data/sales.csv")
+ #Очистка
+ data = clean_data(data)
+ #Фильтрация
+ filtered = filter_by_price_range(data, 10, 500)
+ #Анализ
+ rev = total_revenue(filtered)
+ cat_rev = category_revenue(filtered)
+ best_cat = best_selling_category(filtered)
+ top3 = top_n_items(filtered, 3)
+ monthly = monthly_sales(filtered)
+ #Вывод в консоль
+ print(f"--- Результаты анализа (фильтр: 10-500 руб) ---")
+ print(f"Общая выручка: {rev:.2f}")
+ print(f"Лучшая категория: {best_cat.capitalize()}")
+ print(f"Топ-3 товара: {top3}")
+ print(f"Выручка по месяцам: {monthly}")
+ #Экспорт
+ export_summary(filtered, "report.txt")
+ print(f"\nОтчет успешно сохранен в report.txt")
+
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/report.txt b/report.txt
new file mode 100644
index 0000000..e3a8f60
--- /dev/null
+++ b/report.txt
@@ -0,0 +1,15 @@
+СВОДНЫЙ ОТЧЕТ ПО ПРОДАЖАМ
+==============================
+Общая выручка: 9830.00
+Лучшая категория: электроника
+
+Топ-3 товара (по количеству):
+- Футболка: 50 шт.
+- Книга: 30 шт.
+- Джинсы: 20 шт.
+
+Выручка по месяцам:
+- 2024-01: 1095.00
+- 2024-02: 2250.00
+- 2024-03: 2980.00
+- 2024-04: 3505.00