from __future__ import annotations import csv from collections import defaultdict from pathlib import Path import matplotlib.pyplot as plt from typing import List, Dict, Any # Карта соответствия заголовков CSV для удобства поддержки _CSV_KEYS = { "STRUCTURE": "Структура", "MODE": "Режим", "OP": "Операция", "MEASURE": "Замер", "TIME": "Время (сек)" } def load_average_results(csv_file: str) -> List[Dict[str, Any]]: """Загружает только строки со средними значениями из CSV.""" with open(csv_file, "r", encoding="utf-8") as fh: return [ { "structure": row[_CSV_KEYS["STRUCTURE"]], "mode": row[_CSV_KEYS["MODE"]], "operation": row[_CSV_KEYS["OP"]], "time": float(row[_CSV_KEYS["TIME"]]) } for row in csv.DictReader(fh) if row[_CSV_KEYS["MEASURE"]] == "среднее" ] def _render_chart(operation: str, data: List[Dict[str, Any]], save_path: Path) -> None: """Вспомогательная функция для отрисовки одного столбчатого графика.""" fig, ax = plt.subplots(figsize=(10, 5)) labels = [f"{rec['structure']}\n{rec['mode']}" for rec in data] values = [rec["time"] for rec in data] ax.bar(labels, values, color="cornflowerblue", edgecolor="navy") ax.set_title(f"{operation.capitalize()} Performance Comparison") ax.set_xlabel("Data Structure & Input Order") ax.set_ylabel("Execution Time (seconds)") ax.tick_params(axis="x", rotation=15) fig.tight_layout() fig.savefig(save_path, dpi=150) plt.close(fig) print(f"Saved chart: {save_path}") def build_graphs(results: List[Dict[str, Any]], output_dir: str = "docs/data") -> None: """Группирует результаты по операциям и сохраняет графики.""" out_path = Path(output_dir) out_path.mkdir(parents=True, exist_ok=True) grouped = defaultdict(list) for record in results: grouped[record["operation"]].append(record) for op_name in ("insert", "find", "delete"): if op_name in grouped: target_file = out_path / f"{op_name}.png" _render_chart(op_name, grouped[op_name], target_file) def main(): avg_data = load_average_results("results.csv") build_graphs(avg_data) if __name__ == "__main__": main()