game Of Life

This commit is contained in:
JurajKubrican
2025-03-04 16:31:19 +01:00
parent 7ed413648c
commit 00c209032f
16 changed files with 540 additions and 346 deletions

152
src/boxes/boxes.go Normal file
View File

@@ -0,0 +1,152 @@
package boxes
import (
"fmt"
"math/rand"
"strconv"
"strings"
"sync"
"time"
"github.com/labstack/echo/v4"
"github.com/labstack/gommon/log"
"golang.org/x/net/websocket"
)
var (
wsConnections = make(map[*websocket.Conn]bool)
wsMutex sync.Mutex
db = initDb()
random = rand.New(rand.NewSource(time.Now().UnixNano()))
)
type Box struct {
Id int
Value bool
}
func deserializeBox(msg string) (Box, error) {
parts := strings.Split(msg, ":")
index, err := strconv.Atoi(parts[1])
if err != nil {
return Box{}, err
}
checked := parts[2] == "+"
return Box{index, checked}, nil
}
func (box Box) serialize() string {
message := "b:" + strconv.Itoa(box.Id)
if box.Value {
message += ":+"
} else {
message += ":-"
}
return message + "\n"
}
func handleWsError(err error, conn *websocket.Conn) {
if err != nil {
log.Errorf("Failed to handle websocket: %v", err)
conn.Close()
wsMutex.Lock()
defer wsMutex.Unlock()
delete(wsConnections, conn)
}
}
func broadcastMessage(message string) {
wsMutex.Lock()
defer wsMutex.Unlock()
for conn := range wsConnections {
err := websocket.Message.Send(conn, message)
handleWsError(err, conn)
}
}
func handleMessage(msg string, ws *websocket.Conn) error {
if msg == "gol" {
matrix := make(map[string]Box)
boxes := GetBoxes()
index := 0
for i := 0; i < 32; i++ {
for j := 0; j < 32; j++ {
matrix[fmt.Sprintf("%d-%d", i, j)] = boxes[index]
index++
}
}
log.Error(matrix)
nextGen := make([]Box, 0)
for id, item := range matrix {
nextItem := shouldBeAlive(matrix, id)
if nextItem.Value != item.Value {
nextGen = append(nextGen, shouldBeAlive(matrix, id))
}
}
nextMessage := ""
for _, item := range nextGen {
item.persist()
nextMessage += item.serialize()
}
broadcastMessage(nextMessage)
} else if msg == "random" {
index := random.Int() % 1000
box, err := getBox(index)
if err != nil {
log.Fatal(err)
}
box.Value = !box.Value
box.persist()
message := box.serialize()
broadcastMessage(message)
} else if strings.Contains(msg, "b:") {
box, err := deserializeBox(msg)
if err != nil {
return err
}
broadcastMessage(msg)
box.persist()
} else if strings.Contains(msg, "ping") {
len := len(wsConnections)
websocket.Message.Send(ws, "pong-"+strconv.Itoa(len))
}
return nil
}
func InitWs(c echo.Context) error {
websocket.Handler(func(ws *websocket.Conn) {
wsMutex.Lock()
wsConnections[ws] = true
wsMutex.Unlock()
boxes := GetBoxes()
msg := ""
for _, box := range boxes {
msg += box.serialize()
}
err := websocket.Message.Send(ws, msg)
handleWsError(err, ws)
for {
var msg string
err := websocket.Message.Receive(ws, &msg)
handleWsError(err, ws)
if err != nil {
break
}
handleMessage(msg, ws)
log.Infof("Received message: %s", msg)
}
}).ServeHTTP(c.Response(), c.Request())
return nil
}