import csv
import statistics
import matplotlib.pyplot as plt
import numpy as np


rows = []
with open("results.csv", encoding="utf-8") as f:
    for r in csv.DictReader(f):
        rows.append(r)

MAZES    = ["small_10x10", "medium_50x50", "large_100x100",
            "empty_30x30", "no_exit_20x20", "weighted_40x40"]
STRATS   = ["BFS", "DFS", "A*", "Dijkstra"]
MAZE_RU  = {
    "small_10x10":   "10×10",
    "medium_50x50":  "50×50",
    "large_100x100": "100×100",
    "empty_30x30":   "30×30 пустой",
    "no_exit_20x20": "20×20 без выхода",
    "weighted_40x40":"40×40 взвешенный",
}

def avg(maze, strat, metric):
    vals = [float(r[metric]) for r in rows
            if r["maze"] == maze and r["strategy"] == strat]
    return statistics.mean(vals) if vals else 0.0

def std(maze, strat, metric):
    vals = [float(r[metric]) for r in rows
            if r["maze"] == maze and r["strategy"] == strat]
    return statistics.stdev(vals) if len(vals) > 1 else 0.0


fig, axes = plt.subplots(1, 3, figsize=(16, 5))
fig.suptitle("Сравнение алгоритмов (среднее, 7 запусков)")

x = np.arange(len(MAZES))
W = 0.18
offsets = np.linspace(-(len(STRATS)-1)/2, (len(STRATS)-1)/2, len(STRATS)) * W

for ax, (metric, ylabel, title) in zip(axes, [
    ("time_ms",       "Время (мс)",      "Время выполнения"),
    ("visited_cells", "Посещено клеток", "Посещённые клетки"),
    ("path_length",   "Длина пути",      "Длина найденного пути"),
]):
    for i, strat in enumerate(STRATS):
        vals = [avg(m, strat, metric) for m in MAZES]
        errs = [std(m, strat, metric) for m in MAZES]
        ax.bar(x + offsets[i], vals, W * 0.95, label=strat, yerr=errs, capsize=3)
    ax.set_title(title)
    ax.set_xticks(x)
    ax.set_xticklabels([MAZE_RU[m] for m in MAZES], fontsize=7, rotation=15)
    ax.set_ylabel(ylabel)
    ax.legend(fontsize=8)
    ax.yaxis.grid(True, linestyle="--", alpha=0.5)
    ax.set_axisbelow(True)
    if metric == "time_ms":
        ax.set_yscale("log")

plt.tight_layout()
plt.savefig("../../performance_plot.png", dpi=150)
plt.close()