package app import ( "sync" ) const ( ChunkSize = 16 ) // Point represents the request body for setting cell position type Point struct { X, Y int } // Area represents the visible area for SSE updates type Area struct { X, Y, Width, Height int } // Contains checks if a point is within the SSE area func (a Area) Contains(x int, y int) bool { return x >= a.X && x <= a.X+a.Width && y >= a.Y && y <= a.Y+a.Height } // SpatialHashMap implements spatial hashing for efficient point storage and retrieval type SpatialHashMap struct { mu sync.RWMutex db *SQLiteEngine } // NewSpatialHashMap creates a new spatial hash map func NewSpatialHashMap(dbPath string) (*SpatialHashMap, error) { db, err := CreateSQLite(dbPath) if err != nil { return nil, err } return &SpatialHashMap{ db: db, }, nil } func (s *SpatialHashMap) InitSchema() error { err := s.db.Execute( `CREATE TABLE IF NOT EXISTS spatial_hashmap ( cluster_x INTEGER NOT NULL, cluster_y INTEGER NOT NULL, x INTEGER NOT NULL, y INTEGER NOT NULL, PRIMARY KEY (cluster_x, cluster_y, x, y)) WITHOUT ROWID`) if err != nil { return err } return nil } // getHash calculates the hash coordinates for a given point func (s *SpatialHashMap) getHash(x, y int) Point { return Point{X: x / ChunkSize, Y: y / ChunkSize} } // Insert adds a point to the spatial hash map func (s *SpatialHashMap) Insert(x, y int) error { s.mu.Lock() defer s.mu.Unlock() key := s.getHash(x, y) err := s.db.Execute( "INSERT INTO spatial_hashmap (cluster_x, cluster_y, x, y) VALUES (?, ?, ?, ?)", key.X, key.Y, x, y) if err != nil { return err } return nil } // Remove removes a point from the spatial hash map func (s *SpatialHashMap) Remove(x, y int) error { s.mu.Lock() defer s.mu.Unlock() key := s.getHash(x, y) err := s.db.Execute( "DELETE FROM spatial_hashmap WHERE cluster_x = ? AND cluster_y = ? AND x = ? AND y = ?", key.X, key.Y, x, y) if err != nil { return err } return nil } // GetLocalPoints returns all points within the given bounding box func (s *SpatialHashMap) GetLocalPoints(area Area) []Point { hashStart, hashEnd := s.getHash(area.X, area.Y), s.getHash(area.X+area.Width, area.Y+area.Height) rows, err := s.db.Query( "SELECT x, y FROM spatial_hashmap WHERE cluster_x BETWEEN ? AND ? AND cluster_y BETWEEN ? AND ?", hashStart.X, hashEnd.X, hashStart.Y, hashEnd.Y) if err != nil { return nil } defer rows.Close() localPoints := make([]Point, 0) for rows.Next() { var x, y int if err := rows.Scan(&x, &y); err != nil { continue } localPoints = append(localPoints, Point{X: x, Y: y}) } return localPoints } func (s *SpatialHashMap) Close() error { if s.db != nil { return s.db.Close() } return nil }