mod.go
1 package interface 2 3 import ( 4 "errors" 5 "fmt" 6 "sync" 7 "time" 8 9 "github.com/gdamore/tcell/v2" 10 "github.com/google/uuid" 11 ) 12 13 // NEON_CYAN represents the neon cyan color. 14 var NEON_CYAN = tcell.NewRGBColor(0, 255, 255) 15 16 // DARK_CYAN represents the dark cyan color. 17 var DARK_CYAN = tcell.NewRGBColor(0, 128, 128) 18 19 // SYSTEM_BLUE represents the system blue color. 20 var SYSTEM_BLUE = tcell.NewRGBColor(41, 171, 226) 21 22 // NEON_YELLOW represents the neon yellow color. 23 var NEON_YELLOW = tcell.NewRGBColor(255, 255, 0) 24 25 // STARK_BLUE represents the stark blue color. 26 var STARK_BLUE = tcell.NewRGBColor(0, 255, 255) 27 28 // STARK_ACCENT represents the stark accent color. 29 var STARK_ACCENT = tcell.NewRGBColor(0, 200, 255) 30 31 // STARK_HIGHLIGHT represents the stark highlight color. 32 var STARK_HIGHLIGHT = tcell.NewRGBColor(255, 200, 0) 33 34 // ENERGY_COLOR represents the energy color. 35 var ENERGY_COLOR = tcell.NewRGBColor(0, 255, 200) 36 37 // WARNING_COLOR represents the warning color. 38 var WARNING_COLOR = tcell.NewRGBColor(255, 100, 0) 39 40 // SUCCESS_COLOR represents the success color. 41 var SUCCESS_COLOR = tcell.NewRGBColor(0, 255, 150) 42 43 // SimulationStats holds statistics about the simulation. 44 type SimulationStats struct { 45 ActiveCells int 46 Clusters int 47 Generation uint64 48 GridDepth int 49 EnergyLevel float64 50 ThoughtCount int 51 PlanCount int 52 MutationRate float64 53 BandwidthUsage float64 54 UpdatesPerSecond float64 55 TotalAPICalls int 56 RuntimeSeconds float64 57 CurrentBatch int 58 TotalBatches int 59 ProcessingPhase ProcessingPhase 60 LatestThoughts []string 61 PerformanceMetrics map[string]float64 62 StartTime time.Time 63 LastUpdate time.Time 64 } 65 66 // ProcessingPhase represents the current phase of the simulation. 67 type ProcessingPhase int 68 69 const ( 70 ProcessingPhaseThoughtGeneration ProcessingPhase = iota 71 ProcessingPhasePlanCreation 72 ProcessingPhaseEvolution 73 ProcessingPhaseMemoryCompression 74 ProcessingPhaseActive 75 ) 76 77 // CellGrid represents a grid of cells. 78 type CellGrid struct { 79 Cells [][]bool 80 EnergyLevels [][]float64 81 GridID uuid.UUID 82 } 83 84 // Interface represents the terminal interface for the simulation. 85 type Interface struct { 86 screen tcell.Screen 87 stats SimulationStats 88 cellGrids []CellGrid 89 quitChan chan struct{} 90 statsMutex sync.Mutex 91 gridsMutex sync.Mutex 92 } 93 94 // NewInterface creates a new Interface. 95 func NewInterface() (*Interface, error) { 96 screen, err := tcell.NewScreen() 97 if err != nil { 98 return nil, fmt.Errorf("failed to create screen: %v", err) 99 } 100 101 if err := screen.Init(); err != nil { 102 return nil, fmt.Errorf("failed to initialize screen: %v", err) 103 } 104 105 return &Interface{ 106 screen: screen, 107 stats: SimulationStats{}, 108 cellGrids: make([]CellGrid, 0), 109 quitChan: make(chan struct{}), 110 statsMutex: sync.Mutex{}, 111 gridsMutex: sync.Mutex{}, 112 }, nil 113 } 114 115 // ShouldQuit checks if the user has requested to quit. 116 func (i *Interface) ShouldQuit() (bool, error) { 117 select { 118 case <-i.quitChan: 119 return true, nil 120 default: 121 ev := i.screen.PollEvent() 122 switch ev := ev.(type) { 123 case *tcell.EventKey: 124 if ev.Key() == tcell.KeyCtrlC || ev.Rune() == 'q' { 125 return true, nil 126 } 127 } 128 } 129 return false, nil 130 } 131 132 // UpdateStats updates the simulation statistics. 133 func (i *Interface) UpdateStats(stats SimulationStats) { 134 i.statsMutex.Lock() 135 defer i.statsMutex.Unlock() 136 i.stats = stats 137 } 138 139 // UpdateGrids updates the cell grids. 140 func (i *Interface) UpdateGrids(grids []CellGrid) { 141 i.gridsMutex.Lock() 142 defer i.gridsMutex.Unlock() 143 i.cellGrids = grids 144 } 145 146 // Draw renders the interface. 147 func (i *Interface) Draw() error { 148 i.screen.Clear() 149 150 // Draw the main layout 151 width, height := i.screen.Size() 152 mainLayout := []struct { 153 x, y, w, h int 154 }{ 155 {1, 1, width / 4, height - 2}, 156 {width / 4, 1, width / 4, height - 2}, 157 {width / 2, 1, width / 4, height - 2}, 158 {3 * width / 4, 1, width / 4, height - 2}, 159 } 160 161 // Draw view panels 162 i.drawViewPanel("◢ TOP VIEW ◣", i.cellGrids[0], mainLayout[0]) 163 i.drawViewPanel("◢ FRONT VIEW ◣", i.cellGrids[1], mainLayout[1]) 164 i.drawViewPanel("◢ SIDE VIEW ◣", i.cellGrids[2], mainLayout[2]) 165 166 // Draw system logs 167 i.drawSystemLogs(i.stats.LatestThoughts, mainLayout[3]) 168 169 // Draw status bar 170 i.drawStatusBar() 171 172 i.screen.Show() 173 return nil 174 } 175 176 // drawViewPanel draws a view panel. 177 func (i *Interface) drawViewPanel(title string, grid CellGrid, area struct{ x, y, w, h int }) { 178 style := tcell.StyleDefault.Foreground(NEON_CYAN).Bold(true) 179 i.screen.SetContent(area.x, area.y, '◢', nil, style) 180 i.screen.SetContent(area.x+1, area.y, ' ', nil, style) 181 i.screen.SetContent(area.x+2, area.y, 'T', nil, style) 182 i.screen.SetContent(area.x+3, area.y, 'O', nil, style) 183 i.screen.SetContent(area.x+4, area.y, 'P', nil, style) 184 i.screen.SetContent(area.x+5, area.y, ' ', nil, style) 185 i.screen.SetContent(area.x+6, area.y, 'V', nil, style) 186 i.screen.SetContent(area.x+7, area.y, 'I', nil, style) 187 i.screen.SetContent(area.x+8, area.y, 'E', nil, style) 188 i.screen.SetContent(area.x+9, area.y, 'W', nil, style) 189 i.screen.SetContent(area.x+10, area.y, ' ', nil, style) 190 i.screen.SetContent(area.x+11, area.y, '◣', nil, style) 191 192 // Draw the grid 193 for y := 0; y < len(grid.Cells); y++ { 194 for x := 0; x < len(grid.Cells[y]); x++ { 195 if grid.Cells[y][x] { 196 i.screen.SetContent(area.x+x, area.y+y+1, '■', nil, tcell.StyleDefault.Foreground(ENERGY_COLOR)) 197 } 198 } 199 } 200 } 201 202 // drawSystemLogs draws the system logs. 203 func (i *Interface) drawSystemLogs(thoughts []string, area struct{ x, y, w, h int }) { 204 style := tcell.StyleDefault.Foreground(NEON_CYAN).Bold(true) 205 i.screen.SetContent(area.x, area.y, '◢', nil, style) 206 i.screen.SetContent(area.x+1, area.y, ' ', nil, style) 207 i.screen.SetContent(area.x+2, area.y, 'S', nil, style) 208 i.screen.SetContent(area.x+3, area.y, 'Y', nil, style) 209 i.screen.SetContent(area.x+4, area.y, 'S', nil, style) 210 i.screen.SetContent(area.x+5, area.y, 'T', nil, style) 211 i.screen.SetContent(area.x+6, area.y, 'E', nil, style) 212 i.screen.SetContent(area.x+7, area.y, 'M', nil, style) 213 i.screen.SetContent(area.x+8, area.y, ' ', nil, style) 214 i.screen.SetContent(area.x+9, area.y, 'L', nil, style) 215 i.screen.SetContent(area.x+10, area.y, 'O', nil, style) 216 i.screen.SetContent(area.x+11, area.y, 'G', nil, style) 217 i.screen.SetContent(area.x+12, area.y, 'S', nil, style) 218 i.screen.SetContent(area.x+13, area.y, ' ', nil, style) 219 i.screen.SetContent(area.x+14, area.y, '◣', nil, style) 220 221 for idx, thought := range thoughts { 222 if idx >= area.h-1 { 223 break 224 } 225 i.screen.SetContent(area.x, area.y+idx+1, '►', nil, tcell.StyleDefault.Foreground(NEON_YELLOW)) 226 i.screen.SetContent(area.x+1, area.y+idx+1, ' ', nil, style) 227 for i, ch := range thought { 228 if i >= area.w-2 { 229 break 230 } 231 i.screen.SetContent(area.x+2+i, area.y+idx+1, ch, nil, tcell.StyleDefault.Foreground(SYSTEM_BLUE)) 232 } 233 } 234 } 235 236 // drawStatusBar draws the status bar. 237 func (i *Interface) drawStatusBar() { 238 width, height := i.screen.Size() 239 style := tcell.StyleDefault.Foreground(NEON_CYAN).Bold(true) 240 241 statusText := fmt.Sprintf( 242 "CELLS: %d | GEN: %d | UPS: %.1f | %s", 243 i.stats.ActiveCells, 244 i.stats.Generation, 245 i.stats.UpdatesPerSecond, 246 i.getProcessingPhaseText(), 247 ) 248 249 for x, ch := range statusText { 250 i.screen.SetContent(x, height-1, ch, nil, style) 251 } 252 } 253 254 // getProcessingPhaseText returns the text representation of the current processing phase. 255 func (i *Interface) getProcessingPhaseText() string { 256 switch i.stats.ProcessingPhase { 257 case ProcessingPhaseThoughtGeneration: 258 return "◢ THINKING ◣" 259 case ProcessingPhasePlanCreation: 260 return "◢ PLANNING ◣" 261 case ProcessingPhaseEvolution: 262 return "◢ EVOLVING ◣" 263 case ProcessingPhaseMemoryCompression: 264 return "◢ COMPRESSING ◣" 265 case ProcessingPhaseActive: 266 return "◢ ACTIVE ◣" 267 default: 268 return "◢ UNKNOWN ◣" 269 } 270 } 271 272 // Cleanup cleans up the terminal interface. 273 func (i *Interface) Cleanup() error { 274 i.screen.Fini() 275 return nil 276 }