game Of Life
This commit is contained in:
152
src/boxes/boxes.go
Normal file
152
src/boxes/boxes.go
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user