# Экспериментальное сравнение алгоритмов поиска пути
# Запуск: python3 experiment.py

import csv
import time
from maze_core import TextFileMazeBuilder
from pathfinding import BFSStrategy, DFSStrategy, AStarStrategy


class MazeSolverExperiment:
    
    def __init__(self, maze):
        self._maze = maze
        self._strategy = None
    
    def set_strategy(self, strategy):
        self._strategy = strategy
    
    def solve(self):
        if self._strategy is None:
            return None
        
        start_time = time.perf_counter()
        path = self._strategy.find_path(self._maze, self._maze.start, self._maze.exit)
        end_time = time.perf_counter()
        time_ms = (end_time - start_time) * 1000
        
        return {
            'time_ms': time_ms,
            'visited_cells': self._strategy.get_visited_count(),
            'path_length': len(path)
        }


def run_experiment(maze_file, strategy, runs=5):
    builder = TextFileMazeBuilder()
    maze = builder.build_from_file(maze_file)
    
    total_time = 0
    total_visited = 0
    total_length = 0
    
    for _ in range(runs):
        solver = MazeSolverExperiment(maze)
        solver.set_strategy(strategy)
        stats = solver.solve()
        if stats:
            total_time += stats['time_ms']
            total_visited += stats['visited_cells']
            total_length += stats['path_length']
    
    return {
        'time_ms': total_time / runs,
        'visited_cells': total_visited / runs,
        'path_length': total_length / runs
    }


def main():
    
    # Список лабиринтов для тестирования
    mazes = [
        ("maze1.txt", "Small (10x6)"),
        ("maze10x10.txt", "Medium (10x10)"),
        ("maze20x20.txt", "Large (20x20)"),
        ("maze_empty.txt", "Empty (15x15)"),
        ("maze_no_exit.txt", "No exit (10x10)")
    ]
    
    strategies = [
        ("BFS", BFSStrategy()),
        ("DFS", DFSStrategy()),
        ("AStar", AStarStrategy())
    ]
    
    results = []
    
    print("=" * 60)
    print("ЭКСПЕРИМЕНТАЛЬНОЕ СРАВНЕНИЕ АЛГОРИТМОВ ПОИСКА ПУТИ")
    print("=" * 60)
    
    for maze_file, maze_name in mazes:
        print(f"\nТестирование: {maze_name} ({maze_file})")
        print("-" * 40)
        
        for strat_name, strat in strategies:
            try:
                stats = run_experiment(maze_file, strat, runs=5)
                results.append({
                    'maze': maze_name,
                    'strategy': strat_name,
                    'time_ms': stats['time_ms'],
                    'visited_cells': stats['visited_cells'],
                    'path_length': stats['path_length']
                })
                print(f"  {strat_name}: время={stats['time_ms']:.3f}мс, "
                      f"посещено={stats['visited_cells']:.0f}, "
                      f"длина пути={stats['path_length']:.0f}")
            except Exception as e:
                print(f"  {strat_name}: ОШИБКА - {e}")
                results.append({
                    'maze': maze_name,
                    'strategy': strat_name,
                    'time_ms': -1,
                    'visited_cells': -1,
                    'path_length': -1
                })
    
    valid_results = [r for r in results if r['time_ms'] >= 0]
    
    with open('experiment_results_2.csv', 'w', newline='', encoding='utf-8') as f:
        writer = csv.DictWriter(f, fieldnames=['maze', 'strategy', 'time_ms', 'visited_cells', 'path_length'])
        writer.writeheader()
        writer.writerows(valid_results)
    
    print("\n" + "=" * 60)
    print(f"Результаты сохранены в experiment_results_2.csv")
    print(f"Всего успешных экспериментов: {len(valid_results)}")
    print("=" * 60)


if __name__ == "__main__":
    main()