import { create } from 'zustand'; import type { GridState, SearchResult, PlanResult, ComparisonResult, Algorithm, SearchStep, GridConfig, } from '../types'; import { generateGrid, createPlan, compareAlgorithms, findPath } from '../api/client'; interface GridStore { // Grid state grid: GridState | null; initialState: string; traffic: string; // Search state searchResult: SearchResult | null; planResult: PlanResult | null; comparisonResults: ComparisonResult[] | null; // Visualization state currentStep: number; steps: SearchStep[]; isPlaying: boolean; playbackSpeed: number; // ms per step // UI state selectedAlgorithm: Algorithm; isLoading: boolean; error: string | null; // Actions setGrid: (grid: GridState, initialState: string, traffic: string) => void; generateNewGrid: (config?: GridConfig) => Promise; runSearch: (start: { x: number; y: number }, goal: { x: number; y: number }) => Promise; runPlan: (visualize?: boolean) => Promise; runComparison: () => Promise; setAlgorithm: (algorithm: Algorithm) => void; setCurrentStep: (step: number) => void; play: () => void; pause: () => void; setSpeed: (speed: number) => void; reset: () => void; nextStep: () => void; prevStep: () => void; } export const useGridStore = create((set, get) => ({ // Initial state grid: null, initialState: '', traffic: '', searchResult: null, planResult: null, comparisonResults: null, currentStep: 0, steps: [], isPlaying: false, playbackSpeed: 100, selectedAlgorithm: 'BF', isLoading: false, error: null, // Actions setGrid: (grid, initialState, traffic) => { set({ grid, initialState, traffic, searchResult: null, planResult: null, comparisonResults: null, currentStep: 0, steps: [], isPlaying: false, error: null, }); }, generateNewGrid: async (config = {}) => { set({ isLoading: true, error: null }); try { const result = await generateGrid(config); set({ grid: result.parsed, initialState: result.initialState, traffic: result.traffic, searchResult: null, planResult: null, comparisonResults: null, currentStep: 0, steps: [], isPlaying: false, isLoading: false, }); } catch (error) { set({ error: error instanceof Error ? error.message : 'Failed to generate grid', isLoading: false, }); } }, runSearch: async (start, goal) => { const { grid, selectedAlgorithm } = get(); if (!grid) return; set({ isLoading: true, error: null }); try { const result = await findPath( grid.width, grid.height, start, goal, grid.segments, grid.tunnels, selectedAlgorithm ); set({ searchResult: result, steps: result.steps || [], currentStep: 0, isPlaying: false, isLoading: false, }); } catch (error) { set({ error: error instanceof Error ? error.message : 'Search failed', isLoading: false, }); } }, runPlan: async (visualize = false) => { const { initialState, traffic, selectedAlgorithm } = get(); if (!initialState) return; set({ isLoading: true, error: null }); try { const result = await createPlan(initialState, traffic, selectedAlgorithm, visualize); set({ planResult: result, isLoading: false, }); } catch (error) { set({ error: error instanceof Error ? error.message : 'Planning failed', isLoading: false, }); } }, runComparison: async () => { const { initialState, traffic } = get(); if (!initialState) return; set({ isLoading: true, error: null }); try { const result = await compareAlgorithms(initialState, traffic); set({ comparisonResults: result.comparisons, isLoading: false, }); } catch (error) { set({ error: error instanceof Error ? error.message : 'Comparison failed', isLoading: false, }); } }, setAlgorithm: (algorithm) => { set({ selectedAlgorithm: algorithm }); }, setCurrentStep: (step) => { const { steps } = get(); set({ currentStep: Math.max(0, Math.min(step, steps.length - 1)) }); }, play: () => { set({ isPlaying: true }); }, pause: () => { set({ isPlaying: false }); }, setSpeed: (speed) => { set({ playbackSpeed: speed }); }, reset: () => { set({ currentStep: 0, isPlaying: false, }); }, nextStep: () => { const { currentStep, steps } = get(); if (currentStep < steps.length - 1) { set({ currentStep: currentStep + 1 }); } else { set({ isPlaying: false }); } }, prevStep: () => { const { currentStep } = get(); if (currentStep > 0) { set({ currentStep: currentStep - 1 }); } }, }));