import csv
import matplotlib.pyplot as plt
import numpy as np
from collections import defaultdict
import os

report_file = open("analys_report.txt", "w", encoding="utf-8")
data = defaultdict(lambda: defaultdict(dict))

with open("C:/Users/Honor/Documents/dep2k/lab_inf_1/data/results.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)
    header = next(reader)
    print(f"{header}")
    report_file.write(f"{header}\n")

    for row in reader:
        if len(row) >= 4:
            struct = row[0]      # LinkedList, HashTable, Bst
            mode = row[1]         # shuffled или sorted
            op = row[2]           # insert, find, delete
            time_val = float(row[3])

            data[struct][mode][op] = time_val
            print(f"{struct} | {mode} | {op} | {time_val:.6f}")
            report_file.write(f"{struct} | {mode} | {op} | {time_val:.6f}\n")

op_names = {
    'insert': 'вставка',
    'find': 'поиск',
    'delete': 'удаление'
}

structures = ["LinkedList", "HashTable", "Bst"]
modes = ["shuffled", "sorted"]
operations = ["insert", "find", "delete"]

print("Результаты:")
report_file.write("\nРезультаты:\n")
print(f"{'Структура':<15} {'Режим':<10} {'вставка':<15} {'поиск':<15} {'удаление':<15}")
report_file.write(f"{'Структура':<15} {'Режим':<10} {'вставка':<15} {'поиск':<15} {'удаление':<15}\n")

for struct in structures:
    for mode in modes:
        insert_time = data[struct][mode]['insert']
        find_time = data[struct][mode]['find']
        delete_time = data[struct][mode]['delete']
        print(f"{struct:<15} {mode:<10} {insert_time:<15.6f} {find_time:<15.6f} {delete_time:<15.6f}")
        report_file.write(f"{struct:<15} {mode:<10} {insert_time:<15.6f} {find_time:<15.6f} {delete_time:<15.6f}\n")

#графики
fig, axes = plt.subplots(1, 3, figsize=(15, 5))

for idx, op in enumerate(operations):
    ax = axes[idx]

    x = np.arange(len(structures))
    width = 0.35

    shuffled_vals = [data[s]["shuffled"][op] for s in structures]
    sorted_vals = [data[s]["sorted"][op] for s in structures]

    bars1 = ax.bar(x - width/2, shuffled_vals, width, label='shuffled', color='orange', alpha=0.8)
    bars2 = ax.bar(x + width/2, sorted_vals, width, label='sorted', color='cyan', alpha=0.8)

    ax.set_xlabel('Структура')
    ax.set_ylabel('Время (сек)')
    ax.set_title(f'{op_names[op]}')
    ax.set_xticks(x)
    ax.set_xticklabels(structures, rotation=45)
    ax.legend()
    ax.set_yscale('log')

    for bar in bars1:
        height = bar.get_height()
        ax.text(bar.get_x() + bar.get_width()/2, height,
               f'{height:.3f}', ha='center', va='bottom', fontsize=8)
    for bar in bars2:
        height = bar.get_height()
        ax.text(bar.get_x() + bar.get_width()/2, height,
               f'{height:.3f}', ha='center', va='bottom', fontsize=8)

plt.tight_layout()
plot_filename = "results_plot.png"
plt.savefig('results_plot.png', dpi=150)
plt.show()

report_file.write("График\n")
report_file.write(f"График сохранён в файл: {plot_filename}\n")

print("Анализ:")
report_file.write("\nАнализ:\n")

for op in operations:
    print(f"\n{op_names[op].upper()}:")
    report_file.write(f"\n{op_names[op].upper()}:\n")

    # Среднее по двум режимам
    avg_times = []
    for s in structures:
        avg = (data[s]["shuffled"][op] + data[s]["sorted"][op]) / 2
        avg_times.append((s, avg))

    avg_times.sort(key=lambda x: x[1])
    print(f"  Лучшая: {avg_times[0][0]} ({avg_times[0][1]:.6f} сек)")
    print(f"  Худшая: {avg_times[-1][0]} ({avg_times[-1][1]:.6f} сек)")
    report_file.write(f"  Лучшая: {avg_times[0][0]} ({avg_times[0][1]:.6f} сек)\n")
    report_file.write(f"  Худшая: {avg_times[-1][0]} ({avg_times[-1][1]:.6f} сек)\n")


print("Вывод:")
report_file.write("\nВывод:\n")
print("Для вставок, поиска и удаления лучше всего использовать HashTable как для отсортированных, так и для неотсортированных данных")
print("BST неплох для отсортированных данных, но всё равно хуже HashTable")
print("LinkedList показал худшие результаты")
print("HashTable - оптимальный выбор для телефонного справочника")

report_file.write("Для вставок, поиска и удаления лучше всего использовать HashTable как для отсортированных, так и для неотсортированных данных\n")
report_file.write("BST неплох для отсортированных данных, но всё равно хуже HashTable\n")
report_file.write("LinkedList показал худшие результаты\n")
report_file.write("HashTable - оптимальный выбор для телефонного справочника\n")
report_file.close()