+draws
=setup: add heats =priority: load heats
This commit is contained in:
parent
50a1d74e65
commit
c6f4800273
16 changed files with 436 additions and 146 deletions
|
@ -8,14 +8,15 @@ func (w *Webapp) initApi() {
|
|||
|
||||
http_api := w.Engine.Group("/api")
|
||||
http_api.GET("/priority", w.GetPriority)
|
||||
http_api.GET("/load", w.LoadHeats)
|
||||
http_api.POST("/priority", w.SetPriority)
|
||||
http_api.POST("/start", w.StartTimer)
|
||||
|
||||
// SSE
|
||||
http_api.GET("/sse", HeadersMiddleware(), stream.serveHTTP(), stream.retvalSSE())
|
||||
|
||||
http_api.POST("/setup", w.SetupHeat)
|
||||
http_api.POST("/startheat", w.StartHeat)
|
||||
http_api.POST("/saveheat", w.SaveHeat)
|
||||
http_api.POST("/deleteheat", w.DeleteHeat)
|
||||
http_api.GET("/loadheats", w.LoadHeats)
|
||||
|
||||
// // Surfers
|
||||
// http_api.GET("/surfers", w.GetSurfers)
|
||||
|
|
BIN
backend/backend
BIN
backend/backend
Binary file not shown.
179
backend/heats.go
Normal file
179
backend/heats.go
Normal file
|
@ -0,0 +1,179 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
scribble "github.com/nanobox-io/golang-scribble"
|
||||
)
|
||||
|
||||
type Surfer struct {
|
||||
Name string `json:"name"`
|
||||
Color string `json:"color"`
|
||||
Priority string `json:"priority"`
|
||||
Score string `json:"score"`
|
||||
}
|
||||
|
||||
type Heat struct {
|
||||
Name string `json:"name"`
|
||||
Category string `json:"category"`
|
||||
Number int `json:"number"`
|
||||
Timer int `json:"timer"`
|
||||
Status string `json:"status"`
|
||||
Surfers []Surfer `json:"surfers"`
|
||||
}
|
||||
|
||||
func heatName(heat Heat) string {
|
||||
return fmt.Sprintf("%s.%d.%s", heat.Name, heat.Number, heat.Category)
|
||||
}
|
||||
|
||||
func (w *Webapp) SaveHeat(c *gin.Context) {
|
||||
var heat Heat
|
||||
|
||||
err := c.ShouldBind(&heat)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("req error: %+v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("heat: %+v", heat)
|
||||
|
||||
heat.Status = "idle"
|
||||
|
||||
err = w.DB.Write("Heat", heatName(heat), heat)
|
||||
if err != nil {
|
||||
log.Printf("set error: %+v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"status": fmt.Sprintf("Error: %+v", err)})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"status": "saved"})
|
||||
}
|
||||
|
||||
func (w *Webapp) DeleteHeat(c *gin.Context) {
|
||||
var heat Heat
|
||||
|
||||
err := c.ShouldBind(&heat)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("req error: %+v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("heat: %+v", heat)
|
||||
|
||||
err = w.DB.Delete("Heat", heatName(heat))
|
||||
if err != nil {
|
||||
log.Printf("set error: %+v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"status": fmt.Sprintf("Error: %+v", err)})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"status": "deleted"})
|
||||
}
|
||||
|
||||
func (w *Webapp) LoadRunning(c *gin.Context) {
|
||||
heats := loadHeats(w.DB)
|
||||
|
||||
for _, heat := range heats {
|
||||
if heat.Status == "running" {
|
||||
c.JSON(http.StatusOK, heat)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Webapp) LoadHeats(c *gin.Context) {
|
||||
heats := loadHeats(w.DB)
|
||||
|
||||
c.JSON(http.StatusOK, heats)
|
||||
|
||||
log.Printf("heats: %+v", heats)
|
||||
}
|
||||
|
||||
func (w *Webapp) StartHeatTimer(c *gin.Context) {
|
||||
var msg Message
|
||||
var err error
|
||||
var timer time.Duration
|
||||
|
||||
if w.Stream.Start {
|
||||
c.JSON(http.StatusOK, w.Stream.Duration)
|
||||
return
|
||||
}
|
||||
|
||||
err = c.ShouldBind(&msg)
|
||||
if err != nil {
|
||||
log.Printf("req error: %+v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
timer, err = time.ParseDuration(msg.Duration)
|
||||
if err != nil {
|
||||
log.Printf("req error: %+v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
w.Stream.Duration = timer
|
||||
w.Stream.Start = true
|
||||
|
||||
startHeat(w.DB, *w.Stream.Heat)
|
||||
|
||||
log.Printf("start timer %s - received %s", w.Stream.Duration, msg.Duration)
|
||||
c.JSON(http.StatusOK, w.Stream.Duration)
|
||||
}
|
||||
|
||||
func loadHeats(db *scribble.Driver) []Heat {
|
||||
records, err := db.ReadAll("Heat")
|
||||
if err != nil {
|
||||
fmt.Printf("read error: %+v", err)
|
||||
}
|
||||
|
||||
heats := make([]Heat, 0)
|
||||
for _, record := range records {
|
||||
var heat Heat
|
||||
err = json.Unmarshal([]byte(record), &heat)
|
||||
if err != nil {
|
||||
fmt.Printf("decode error: %+v", err)
|
||||
}
|
||||
heats = append(heats, heat)
|
||||
}
|
||||
|
||||
return heats
|
||||
}
|
||||
|
||||
func startHeat(db *scribble.Driver, heat Heat) error {
|
||||
log.Printf("heat: %+v", heat)
|
||||
|
||||
heat.Status = "running"
|
||||
|
||||
err := db.Write("Heat", heatName(heat), heat)
|
||||
if err != nil {
|
||||
log.Printf("set error: %+v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func stopHeat(db *scribble.Driver, heat Heat) error {
|
||||
|
||||
log.Printf("heat: %+v", heat)
|
||||
|
||||
heat.Status = "ended"
|
||||
|
||||
err := db.Write("Heat", heatName(heat), heat)
|
||||
if err != nil {
|
||||
log.Printf("set error: %+v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
@ -37,27 +35,6 @@ func (w *Webapp) StartTimer(c *gin.Context) {
|
|||
c.JSON(http.StatusOK, w.Stream.Duration)
|
||||
}
|
||||
|
||||
func (w *Webapp) LoadHeats(c *gin.Context) {
|
||||
records, err := w.DB.ReadAll("Heat")
|
||||
if err != nil {
|
||||
fmt.Printf("read error: %+v", err)
|
||||
}
|
||||
|
||||
heats := make([]Heat, 0)
|
||||
for _, record := range records {
|
||||
var heat Heat
|
||||
err = json.Unmarshal([]byte(record), &heat)
|
||||
if err != nil {
|
||||
fmt.Printf("decode error: %+v", err)
|
||||
}
|
||||
heats = append(heats, heat)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, heats)
|
||||
|
||||
log.Printf("heats: %+v", heats)
|
||||
}
|
||||
|
||||
func (w *Webapp) GetPriority(c *gin.Context) {
|
||||
log.Printf("send priority %s", w.Stream.StatusPriority)
|
||||
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Surfer struct {
|
||||
Name string `json:"name"`
|
||||
Color string `json:"color"`
|
||||
Priority string `json:"priority"`
|
||||
Score string `json:"score"`
|
||||
}
|
||||
|
||||
type Heat struct {
|
||||
Name string `json:"name"`
|
||||
Category string `json:"category"`
|
||||
Number int `json:"number"`
|
||||
Timer int `json:"timer"`
|
||||
Surfers []Surfer `json:"surfers"`
|
||||
}
|
||||
|
||||
func (w *Webapp) SetupHeat(c *gin.Context) {
|
||||
var heat Heat
|
||||
|
||||
err := c.ShouldBind(&heat)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("req error: %+v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("heat: %+v", heat)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"status": "added"})
|
||||
|
||||
err = w.DB.Write("Heat", fmt.Sprintf("%s.%s.%d", heat.Name, heat.Category, heat.Number), heat)
|
||||
if err != nil {
|
||||
log.Printf("set error: %+v", err)
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ type SurferLive struct {
|
|||
type Message struct {
|
||||
Surfers []SurferLive `json:"surfers"`
|
||||
Priority []string `json:"priority"`
|
||||
Heat Heat `json:"heat"`
|
||||
Duration string `json:"duration"`
|
||||
Source string `json:"source"`
|
||||
Msg string `json:"msg"`
|
||||
|
@ -36,7 +37,7 @@ type ClientChan chan Message
|
|||
|
||||
type IPAddress string
|
||||
|
||||
type PriorityStream struct {
|
||||
type SseStream struct {
|
||||
// Events are pushed to this channel by the main events-gathering routine
|
||||
Message chan Message
|
||||
|
||||
|
@ -52,16 +53,18 @@ type PriorityStream struct {
|
|||
StatusPriority []string
|
||||
Duration time.Duration
|
||||
Start bool
|
||||
Heat *Heat
|
||||
}
|
||||
|
||||
// Initialize event and Start procnteessing requests
|
||||
func NewServer() (sse *PriorityStream) {
|
||||
sse = &PriorityStream{
|
||||
func NewServer() (sse *SseStream) {
|
||||
sse = &SseStream{
|
||||
Message: make(chan Message),
|
||||
NewClients: make(chan Client),
|
||||
ClosedClients: make(chan ClientChan),
|
||||
TotalClients: make(map[ClientChan]IPAddress),
|
||||
Start: false,
|
||||
Heat: &Heat{},
|
||||
}
|
||||
|
||||
go sse.listen()
|
||||
|
@ -73,7 +76,7 @@ func NewServer() (sse *PriorityStream) {
|
|||
|
||||
// It Listens all incoming requests from clients.
|
||||
// Handles addition and removal of clients and broadcast messages to clients.
|
||||
func (stream *PriorityStream) listen() {
|
||||
func (stream *SseStream) listen() {
|
||||
for {
|
||||
select {
|
||||
// Add new available client
|
||||
|
@ -108,7 +111,7 @@ func HeadersMiddleware() gin.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func (stream *PriorityStream) serveHTTP() gin.HandlerFunc {
|
||||
func (stream *SseStream) serveHTTP() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// Initialize client channel
|
||||
clientChan := make(ClientChan)
|
||||
|
@ -132,7 +135,7 @@ func (stream *PriorityStream) serveHTTP() gin.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func (stream *PriorityStream) retvalSSE() gin.HandlerFunc {
|
||||
func (stream *SseStream) retvalSSE() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
if len(stream.StatusPriority) > 0 {
|
||||
|
@ -159,14 +162,14 @@ func (stream *PriorityStream) retvalSSE() gin.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func (stream *PriorityStream) SendPriority(pri []string) {
|
||||
func (stream *SseStream) SendPriority(pri []string) {
|
||||
stream.Message <- Message{
|
||||
Priority: pri,
|
||||
Mode: Priority.String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (stream *PriorityStream) timer() {
|
||||
func (stream *SseStream) timer() {
|
||||
for {
|
||||
if stream.Start {
|
||||
timer := time.NewTimer(stream.Duration)
|
||||
|
@ -180,6 +183,7 @@ func (stream *PriorityStream) timer() {
|
|||
}
|
||||
stream.Message <- msg
|
||||
log.Printf("stop timer %+v", stream.Duration)
|
||||
stream.Heat.Status = "ended"
|
||||
continue
|
||||
default:
|
||||
if len(stream.TotalClients) > 0 {
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":"1702477632110"}
|
||||
{"version":"1702551352225"}
|
Binary file not shown.
Binary file not shown.
|
@ -5,17 +5,17 @@
|
|||
<link rel="icon" href="/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link rel="modulepreload" href="/_app/immutable/entry/start.f2f23bb5.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/entry/start.99d6dd70.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/chunks/scheduler.d1a939e8.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/chunks/singletons.f3cb4e26.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/entry/app.c3a1467b.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/chunks/singletons.2b3a0a27.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/entry/app.3faab5fc.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/chunks/index.994dd985.js">
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">
|
||||
<script>
|
||||
{
|
||||
__sveltekit_1cx8eia = {
|
||||
__sveltekit_1lbm7l = {
|
||||
base: "",
|
||||
env: {}
|
||||
};
|
||||
|
@ -23,8 +23,8 @@
|
|||
const element = document.currentScript.parentElement;
|
||||
|
||||
Promise.all([
|
||||
import("/_app/immutable/entry/start.f2f23bb5.js"),
|
||||
import("/_app/immutable/entry/app.c3a1467b.js")
|
||||
import("/_app/immutable/entry/start.99d6dd70.js"),
|
||||
import("/_app/immutable/entry/app.3faab5fc.js")
|
||||
]).then(([kit, app]) => {
|
||||
kit.start(app, element);
|
||||
});
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
type Webapp struct {
|
||||
Engine *gin.Engine
|
||||
Stream *PriorityStream
|
||||
Stream *SseStream
|
||||
DB *scribble.Driver
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,9 @@ func InitHttp(d *scribble.Driver) *Webapp {
|
|||
setup := router.Group("/setup")
|
||||
setup.Static("/", "./static/setup")
|
||||
|
||||
draws := router.Group("/draws")
|
||||
draws.Static("/", "./static/draws")
|
||||
|
||||
sapp := router.Group("/_app")
|
||||
sapp.Static("/", "./static/_app")
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue