diff --git a/derby/derby.go b/derby/derby.go
index d144fb3..3c5fdbf 100644
--- a/derby/derby.go
+++ b/derby/derby.go
@@ -43,8 +43,8 @@ const (
// Event represents a race event
type Event struct {
- Type EventType
- Event any // Only populated for EventLaneFinish
+ Type EventType
+ Result *Result // Only populated for EventLaneFinish
}
// DerbyClock represents the connection to the derby clock device
@@ -205,8 +205,8 @@ func (dc *DerbyClock) readLoop() {
if result != nil {
// Send lane finish event
dc.eventChan <- Event{
- Type: EventLaneFinish,
- Event: result,
+ Type: EventLaneFinish,
+ Result: result,
}
}
results = append(results, result)
diff --git a/examples/main.go b/examples/main.go
index 1069e22..7339aa6 100644
--- a/examples/main.go
+++ b/examples/main.go
@@ -162,10 +162,10 @@ func startTerminalInterface(clock *derby.DerbyClock, events <-chan derby.Event,
fmt.Println("\nš Race started!")
case derby.EventLaneFinish:
- result := event.Event.(derby.Result)
+ result := event.Result
fmt.Printf("š Lane %d finished in place %d with time %.4f seconds\n",
result.Lane, result.FinishPlace, result.Time)
- raceResults = append(raceResults, &result)
+ raceResults = append(raceResults, result)
case derby.EventRaceComplete:
fmt.Println("\nš Race complete! Final results:")
diff --git a/models/models.go b/models/models.go
index 8da323c..ecbe318 100644
--- a/models/models.go
+++ b/models/models.go
@@ -87,3 +87,18 @@ type HeatData struct {
Lane3 *LaneData
Lane4 *LaneData
}
+
+// Event types that can be sent on the event channel
+type AdminEventType int
+
+const (
+ EventHeatChanged AdminEventType = iota
+ EventGroupChanged
+ EventHeatRerun
+)
+
+// Event represents a race event
+type AdminEvent struct {
+ Type AdminEventType
+ Event any
+}
diff --git a/web/server.go b/web/server.go
index cde9b1b..f275914 100644
--- a/web/server.go
+++ b/web/server.go
@@ -29,17 +29,19 @@ var content embed.FS
// Server represents the web server for the derby clock
type Server struct {
- router *chi.Mux
- clock *derby.DerbyClock
- events <-chan derby.Event
- clients map[chan string]bool
- clientsMux sync.Mutex
- port int
- server *http.Server
- shutdown chan struct{}
- logger *slog.Logger
- db *db.DB
- adminEvents chan string
+ router *chi.Mux
+ clock *derby.DerbyClock
+ events <-chan derby.Event
+ clients map[chan string]bool
+ clientsMux sync.Mutex
+ adminclients map[chan string]bool
+ adminclientsMux sync.Mutex
+ port int
+ server *http.Server
+ shutdown chan struct{}
+ logger *slog.Logger
+ db *db.DB
+ adminEvents chan string
}
// NewServer creates a new web server
@@ -115,54 +117,49 @@ func (s *Server) routes() {
r.Post("/reset", s.handleReset())
r.Post("/force-end", s.handleForceEnd())
r.Get("/events", s.handleEvents())
+ r.Get("/validate/car-number", s.handleValidateCarNumber())
+ r.Route("/groups", func(r chi.Router) {
+ r.Post("/", s.handleCreateGroup())
+ r.Put("/{id}", s.handleUpdateGroup())
+ r.Delete("/{id}", s.handleDeleteGroup())
+ })
+ r.Route("/racers", func(r chi.Router) {
+ r.Post("/", s.handleCreateRacer())
+ r.Put("/{id}", s.handleUpdateRacer())
+ r.Delete("/{id}", s.handleDeleteRacer())
+ })
+ r.Route("/heats", func(r chi.Router) {
+ r.Post("/generate", s.handleGenerateHeats())
+ })
+ r.Route("/api/race", func(r chi.Router) {
+ r.Get("/current-heat", s.handleCurrentHeat())
+ r.Post("/next-heat", s.handleNextHeat())
+ r.Post("/previous-heat", s.handlePreviousHeat())
+ r.Post("/rerun-heat", s.handleRerunHeat())
+ r.Post("/set-group", s.handleSetRacingGroup())
+ })
+ r.Route("/admin", func(r chi.Router) {
+ r.Get("/events", s.handleAdminEvents())
+ })
})
s.router.Get("/admin", s.handleAdmin())
s.router.Get("/register", s.handleRegister())
s.router.Get("/register/form", s.handleRegisterForm())
- s.router.Route("/api/groups", func(r chi.Router) {
- r.Post("/", s.handleCreateGroup())
- r.Put("/{id}", s.handleUpdateGroup())
- r.Delete("/{id}", s.handleDeleteGroup())
- })
-
- s.router.Route("/api/racers", func(r chi.Router) {
- r.Post("/", s.handleCreateRacer())
- r.Put("/{id}", s.handleUpdateRacer())
- r.Delete("/{id}", s.handleDeleteRacer())
- })
-
// Add heats page route
s.router.Get("/heats", s.handleHeats())
s.router.Get("/heats-content", s.handleHeatsContent())
- // Add heats API routes
- s.router.Route("/api/heats", func(r chi.Router) {
- r.Post("/generate", s.handleGenerateHeats())
- })
-
// Main page
s.router.Get("/", s.handleIndex())
// Add racers list route
s.router.Get("/admin/racers/list", s.handleRacersList())
- // Add validate car number route
- s.router.Get("/api/validate/car-number", s.handleValidateCarNumber())
-
// Add race manager routes
s.router.Get("/race", s.handleRacePublic())
s.router.Get("/race/manage", s.handleRaceManage())
-
- // Add race API routes
- s.router.Route("/api/race", func(r chi.Router) {
- r.Get("/current-heat", s.handleCurrentHeat())
- r.Post("/next-heat", s.handleNextHeat())
- r.Post("/previous-heat", s.handlePreviousHeat())
- r.Post("/rerun-heat", s.handleRerunHeat())
- r.Post("/set-group", s.handleSetRacingGroup())
- })
}
// Start starts the web server
@@ -216,7 +213,7 @@ func (s *Server) forwardEvents() {
return
}
// Process the event and send to clients
- s.broadcastEvent(event)
+ s.broadcastRaceEvent(event)
case <-s.shutdown:
return
}
@@ -224,37 +221,89 @@ func (s *Server) forwardEvents() {
}
// broadcastEvent sends an event to all connected clients
-func (s *Server) broadcastEvent(event derby.Event) {
+func (s *Server) broadcastRaceEvent(event derby.Event) {
+ var heatResult models.HeatResult
switch event.Type {
case derby.EventRaceStart:
s.logger.Info("Broadcasting race start event")
- s.sendEventToAllClients("event: race-status\ndata:
Race Running
")
+ s.sendRaceEventToAllClients("event: race-status\ndata: Race Running
")
+ heatGroup, _ := s.db.GetCurrentRacingGroup()
+ heatResult.GroupID = heatGroup.ID
+ heatResult.HeatNumber, _ = s.db.GetCurrentHeatNumber(heatGroup.ID)
case derby.EventLaneFinish:
s.logger.Info("Broadcasting lane finish event",
- "lane", event.Event.(derby.Result).Lane,
- "time", event.Event.(derby.Result).Time,
- "place", event.Event.(derby.Result).FinishPlace)
+ "lane", event.Result.Lane,
+ "time", event.Result.Time,
+ "place", event.Result.FinishPlace)
+
+ switch event.Result.Lane {
+ case 1:
+ heatResult.Lane1Time = event.Result.Time
+ heatResult.Lane1Position = event.Result.FinishPlace
+ case 2:
+ heatResult.Lane2Time = event.Result.Time
+ heatResult.Lane2Position = event.Result.FinishPlace
+ case 3:
+ heatResult.Lane3Time = event.Result.Time
+ heatResult.Lane3Position = event.Result.FinishPlace
+ case 4:
+ heatResult.Lane4Time = event.Result.Time
+ heatResult.Lane4Position = event.Result.FinishPlace
+ }
+ s.sendRaceEventToAllClients(fmt.Sprintf("event: lane-%d-time\ndata: %.4f", event.Result.Lane, event.Result.Time))
+ s.sendRaceEventToAllClients(fmt.Sprintf("event: lane-%d-position\ndata: %d", event.Result.Lane, event.Result.FinishPlace))
- s.sendEventToAllClients(fmt.Sprintf("event: lane-%d-time\ndata: %.4f", event.Event.(derby.Result).Lane, event.Event.(derby.Result).Time))
- s.sendEventToAllClients(fmt.Sprintf("event: lane-%d-position\ndata: %d", event.Event.(derby.Result).Lane, event.Event.(derby.Result).FinishPlace))
+ case derby.EventRaceComplete:
+ s.logger.Info("Broadcasting race complete event")
+ s.sendRaceEventToAllClients("event: race-status\ndata: Race Complete
")
+ s.db.SaveHeatResult(heatResult)
+ }
+}
- case derby.EventHeatChanged:
+// broadcastEvent sends an event to all connected clients
+func (s *Server) broadcastAdminEvent(event models.AdminEvent) {
+ switch event.Type {
+ case models.EventHeatChanged:
s.logger.Info("Broadcasting heat changed event")
- s.sendEventToAllClients(fmt.Sprintf("event: heat-changed-number\ndata: %d out of %d", event.Event.(models.HeatData).HeatNumber, event.Event.(models.HeatData).TotalHeats))
- s.sendEventToAllClients("event: race-status\ndata: Idle
")
+ if heatData, ok := event.Event.(models.HeatData); ok {
+ component := templates.CurrentHeatDisplay(&heatData)
+ var sb strings.Builder
+ err := component.Render(context.Background(), &sb)
+ if err != nil {
+ s.logger.Error("Failed to render current heat display", "error", err)
+ }
+ s.sendAdminEventToAllClients(fmt.Sprintf("event: current-heat\ndata: %s", sb.String()))
+ nextHeatData, _ := s.db.GetHeatData(heatData.Group.ID, heatData.HeatNumber+1)
+ component = templates.NextHeatDisplay(nextHeatData)
+ var sb2 strings.Builder
+ err = component.Render(context.Background(), &sb2)
+ if err != nil {
+ s.logger.Error("Failed to render next heat display", "error", err)
+ }
+ s.sendAdminEventToAllClients(fmt.Sprintf("event: next-heat\ndata: %s", sb2.String()))
+ s.sendAdminEventToAllClients(fmt.Sprintf("event: heat-number\ndata: Current Heat: %d of %d", heatData.HeatNumber, heatData.TotalHeats))
+ } else {
+ s.logger.Error("Failed to convert event to HeatData")
+ }
- case derby.EventGroupChanged:
- s.logger.Info("Broadcasting group changed event")
- s.sendEventToAllClients("event: group-changed\ndata: Group Changed
")
+ case models.EventGroupChanged:
+ s.logger.Info("Broadcasting group changed event",
+ "group", event.Event)
- case derby.EventRaceComplete:
- s.logger.Info("Broadcasting race complete event")
- s.sendEventToAllClients("event: race-status\ndata: Race Complete
")
+ if heatResults, ok := event.Event.([]models.HeatResult); ok {
+ component := templates.ResultsDisplay(heatResults)
+ var sb strings.Builder
+ err := component.Render(context.Background(), &sb)
+ if err != nil {
+ s.logger.Error("Failed to render current heat results", "error", err)
+ }
+ s.sendAdminEventToAllClients(fmt.Sprintf("event: results\ndata: %s", sb.String()))
+ }
}
}
-func (s *Server) sendEventToAllClients(message string) {
+func (s *Server) sendRaceEventToAllClients(message string) {
if message == "" {
return
}
@@ -274,6 +323,26 @@ func (s *Server) sendEventToAllClients(message string) {
s.clientsMux.Unlock()
}
+func (s *Server) sendAdminEventToAllClients(message string) {
+ if message == "" {
+ return
+ }
+
+ // Send to all clients
+ s.adminclientsMux.Lock()
+ clientCount := len(s.adminclients)
+ sentCount := 0
+ for clientChan := range s.adminclients {
+ clientChan <- message
+ sentCount++
+ }
+ s.logger.Debug("Event broadcast complete",
+ "sentCount", sentCount,
+ "totalClients", clientCount,
+ "message", message)
+ s.adminclientsMux.Unlock()
+}
+
// handleIndex handles the index page
func (s *Server) handleIndex() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -336,9 +405,6 @@ func (s *Server) handleEvents() http.HandlerFunc {
w.Header().Set("Connection", "keep-alive")
w.Header().Set("Access-Control-Allow-Origin", "*")
- // Debug message to confirm connection
- fmt.Fprintf(w, "event: debug\ndata: {\"message\":\"SSE connection established\"}\n\n")
-
// Flush headers to ensure they're sent to the client
if flusher, ok := w.(http.Flusher); ok {
flusher.Flush()
@@ -391,6 +457,67 @@ func (s *Server) handleEvents() http.HandlerFunc {
}
}
+// handleAdminEvents handles SSE events
+func (s *Server) handleAdminEvents() http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ // Set headers for SSE
+ w.Header().Set("Content-Type", "text/event-stream")
+ w.Header().Set("Cache-Control", "no-cache")
+ w.Header().Set("Connection", "keep-alive")
+ w.Header().Set("Access-Control-Allow-Origin", "*")
+
+ // Flush headers to ensure they're sent to the client
+ if flusher, ok := w.(http.Flusher); ok {
+ flusher.Flush()
+ } else {
+ http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
+ return
+ }
+
+ // Create a channel for this client
+ clientChan := make(chan string, 10)
+
+ // Add client to map with mutex protection
+ s.adminclientsMux.Lock()
+ s.adminclients[clientChan] = true
+ clientCount := len(s.adminclients)
+ s.adminclientsMux.Unlock()
+
+ s.logger.Info("New client connected",
+ "clientIP", r.RemoteAddr,
+ "totalClients", clientCount)
+
+ // Remove client when connection is closed
+ defer func() {
+ s.adminclientsMux.Lock()
+ delete(s.adminclients, clientChan)
+ remainingClients := len(s.adminclients)
+ s.adminclientsMux.Unlock()
+ close(clientChan)
+
+ s.logger.Info("Client disconnected",
+ "clientIP", r.RemoteAddr,
+ "remainingClients", remainingClients)
+ }()
+
+ // Keep connection open and send events as they arrive
+ for {
+ select {
+ case msg, ok := <-clientChan:
+ if !ok {
+ return
+ }
+ fmt.Fprintf(w, "%s\n\n", msg)
+ if flusher, ok := w.(http.Flusher); ok {
+ flusher.Flush()
+ }
+ case <-r.Context().Done():
+ return
+ }
+ }
+ }
+}
+
// handleAdmin renders the admin page
func (s *Server) handleAdmin() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -937,29 +1064,6 @@ func (s *Server) handleRacersList() http.HandlerFunc {
}
}
-// handleAdminEvents handles admin events with SSE
-func (s *Server) handleAdminEvents() http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- // Set SSE headers
- w.Header().Set("Content-Type", "text/event-stream")
- w.Header().Set("Cache-Control", "no-cache")
- w.Header().Set("Connection", "keep-alive")
-
- // Send events to client
- for {
- select {
- case event := <-s.adminEvents:
- fmt.Fprintf(w, "data: %s\n\n", event)
- if f, ok := w.(http.Flusher); ok {
- f.Flush()
- }
- case <-r.Context().Done():
- return
- }
- }
- }
-}
-
// handleValidateCarNumber handles the validate car number API endpoint
func (s *Server) handleValidateCarNumber() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -1272,28 +1376,19 @@ func (s *Server) handleNextHeat() http.HandlerFunc {
return
}
- // Reset the clock
- if err := s.clock.Reset(); err != nil {
- s.logger.Error("Failed to reset clock", "error", err)
- }
+ heatData, _ := s.db.GetHeatData(currentGroup.ID, currentHeatNum+1)
// Broadcast event to admin page
- s.broadcastAdminEvent("heat-changed")
+ s.broadcastAdminEvent(models.AdminEvent{
+ Type: models.EventHeatChanged,
+ Event: heatData,
+ })
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
}
}
-// broadcastAdminEvent sends an event to all admin clients
-func (s *Server) broadcastAdminEvent(event string) {
- // Create a simple event message
- eventMsg := fmt.Sprintf(`{"event":"%s"}`, event)
-
- // Send to all admin clients
- s.adminEvents <- eventMsg
-}
-
// handlePreviousHeat goes back to the previous heat
func (s *Server) handlePreviousHeat() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -1326,61 +1421,13 @@ func (s *Server) handlePreviousHeat() http.HandlerFunc {
return
}
- // Reset the clock
- if err := s.clock.Reset(); err != nil {
- s.logger.Error("Failed to reset clock", "error", err)
- }
+ heatData, _ := s.db.GetHeatData(currentGroup.ID, currentHeatNum-1)
// Broadcast event to admin page
- s.broadcastAdminEvent("heat-changed")
-
- w.WriteHeader(http.StatusOK)
- json.NewEncoder(w).Encode(map[string]string{"status": "success"})
- }
-}
-
-// handleSaveHeatResult saves the result of a heat
-func (s *Server) handleSaveHeatResult() http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- // Parse request body
- var request struct {
- GroupID int64 `json:"group_id"`
- HeatNumber int `json:"heat_number"`
- Lane1Time float64 `json:"lane1_time"`
- Lane1Position int `json:"lane1_position"`
- Lane2Time float64 `json:"lane2_time"`
- Lane2Position int `json:"lane2_position"`
- Lane3Time float64 `json:"lane3_time"`
- Lane3Position int `json:"lane3_position"`
- Lane4Time float64 `json:"lane4_time"`
- Lane4Position int `json:"lane4_position"`
- }
-
- if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
- http.Error(w, "Invalid request body", http.StatusBadRequest)
- return
- }
-
- // Create heat result
- result := models.HeatResult{
- GroupID: request.GroupID,
- HeatNumber: request.HeatNumber,
- Lane1Time: request.Lane1Time,
- Lane1Position: request.Lane1Position,
- Lane2Time: request.Lane2Time,
- Lane2Position: request.Lane2Position,
- Lane3Time: request.Lane3Time,
- Lane3Position: request.Lane3Position,
- Lane4Time: request.Lane4Time,
- Lane4Position: request.Lane4Position,
- }
-
- // Save heat result
- if err := s.db.SaveHeatResult(result); err != nil {
- s.logger.Error("Failed to save heat result", "error", err)
- http.Error(w, "Failed to save heat result", http.StatusInternalServerError)
- return
- }
+ s.broadcastAdminEvent(models.AdminEvent{
+ Type: models.EventHeatChanged,
+ Event: heatData,
+ })
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
@@ -1413,13 +1460,13 @@ func (s *Server) handleRerunHeat() http.HandlerFunc {
return
}
- // Reset the clock
- if err := s.clock.Reset(); err != nil {
- s.logger.Error("Failed to reset clock", "error", err)
- }
+ heatData, _ := s.db.GetHeatData(currentGroup.ID, currentHeatNum)
// Broadcast event to admin page
- s.broadcastAdminEvent("heat-rerun")
+ s.broadcastAdminEvent(models.AdminEvent{
+ Type: models.EventHeatChanged,
+ Event: heatData,
+ })
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
@@ -1446,13 +1493,20 @@ func (s *Server) handleSetRacingGroup() http.HandlerFunc {
return
}
- // Reset the clock
- if err := s.clock.Reset(); err != nil {
- s.logger.Error("Failed to reset clock", "error", err)
- }
+ heatData, _ := s.db.GetHeatData(request.GroupID, 1)
// Broadcast event to admin page
- s.broadcastAdminEvent("group-changed")
+ s.broadcastAdminEvent(models.AdminEvent{
+ Type: models.EventHeatChanged,
+ Event: heatData,
+ })
+
+ heatResults, _ := s.db.GetHeatResults(request.GroupID)
+
+ s.broadcastAdminEvent(models.AdminEvent{
+ Type: models.EventGroupChanged,
+ Event: heatResults,
+ })
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
diff --git a/web/templates/race_manage.templ b/web/templates/race_manage.templ
index 0078dbf..05b1674 100644
--- a/web/templates/race_manage.templ
+++ b/web/templates/race_manage.templ
@@ -29,7 +29,7 @@ templ RaceManage(heatData *models.HeatData, nextHeat *models.HeatData, groups []
-
Current Heat: { strconv.Itoa(heatData.HeatNumber) } of { strconv.Itoa(heatData.TotalHeats) }
+
Current Heat: { strconv.Itoa(heatData.HeatNumber) } of { strconv.Itoa(heatData.TotalHeats) }
}
}
+templ ResultsDisplay(results []models.HeatResult) {
+
+
+
+
+
+
+
+ | Heat |
+ Lane 1 |
+ Lane 2 |
+ Lane 3 |
+ Lane 4 |
+
+
+
+ for _, result := range results {
+
+ | { strconv.Itoa(result.HeatNumber) } |
+ { fmt.Sprintf("%.4f", result.Lane1Time) } ({ strconv.Itoa(result.Lane1Position) }) |
+ { fmt.Sprintf("%.4f", result.Lane2Time) } ({ strconv.Itoa(result.Lane2Position) }) |
+ { fmt.Sprintf("%.4f", result.Lane3Time) } ({ strconv.Itoa(result.Lane3Position) }) |
+ { fmt.Sprintf("%.4f", result.Lane4Time) } ({ strconv.Itoa(result.Lane4Position) }) |
+
+ }
+
+
+
+
+
+}
+
// Find the current heat
-templ currentHeatDisplay(heatData *models.HeatData) {
+templ CurrentHeatDisplay(heatData *models.HeatData) {
@@ -189,6 +165,41 @@ templ raceLaneInfo(laneData models.LaneData) {
}
+templ NextHeatDisplay(nextHeat *models.HeatData) {
+ if nextHeat != nil {
+
+
+
+
+
+
+ | Lane |
+ Racer |
+ Car # |
+
+
+
+ if nextHeat.Lane1 != nil {
+ @raceNextHeatRow(*nextHeat.Lane1)
+ }
+ if nextHeat.Lane2 != nil {
+ @raceNextHeatRow(*nextHeat.Lane2)
+ }
+ if nextHeat.Lane3 != nil {
+ @raceNextHeatRow(*nextHeat.Lane3)
+ }
+ if nextHeat.Lane4 != nil {
+ @raceNextHeatRow(*nextHeat.Lane4)
+ }
+
+
+
+
+ }
+}
+
// Helper template for displaying a racer in the next heat
templ nextHeatRacer(laneData models.LaneData) {
diff --git a/web/templates/race_manage_templ.go b/web/templates/race_manage_templ.go
index f1d78ef..5ab7f64 100644
--- a/web/templates/race_manage_templ.go
+++ b/web/templates/race_manage_templ.go
@@ -94,14 +94,14 @@ func RaceManage(heatData *models.HeatData, nextHeat *models.HeatData, groups []m
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "Current Heat: ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
Current Heat: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(heatData.HeatNumber))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 32, Col: 85}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 32, Col: 153}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -114,7 +114,7 @@ func RaceManage(heatData *models.HeatData, nextHeat *models.HeatData, groups []m
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(heatData.TotalHeats))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 32, Col: 126}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 32, Col: 194}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -140,211 +140,31 @@ func RaceManage(heatData *models.HeatData, nextHeat *models.HeatData, groups []m
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, ">Next Heat
Timer Control
0.000
Ready
Gate Status: Unknown
| Heat | Lane 1 | Lane 2 | Lane 3 | Lane 4 |
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, ">Next Heat Timer Control
Ready
Gate Status: Unknown
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- for _, result := range results {
- var templ_7745c5c3_Var7 = []any{"table-primary"}
- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
| ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var9 string
- templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(result.HeatNumber))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 89, Col: 85}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, " | ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var10 string
- templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.4f", result.Lane1Time))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 90, Col: 91}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, " (")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var11 string
- templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(result.Lane1Position))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 90, Col: 131}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, ") | ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var12 string
- templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.4f", result.Lane2Time))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 91, Col: 91}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, " (")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var13 string
- templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(result.Lane2Position))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 91, Col: 131}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, ") | ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var14 string
- templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.4f", result.Lane3Time))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 92, Col: 91}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, " (")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var15 string
- templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(result.Lane3Position))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 92, Col: 131}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, ") | ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var16 string
- templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.4f", result.Lane4Time))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 93, Col: 91}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " (")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var17 string
- templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(result.Lane4Position))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 93, Col: 131}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, ") |
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
+ templ_7745c5c3_Err = ResultsDisplay(results).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = currentHeatDisplay(heatData).Render(ctx, templ_7745c5c3_Buffer)
+ templ_7745c5c3_Err = CurrentHeatDisplay(heatData).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- if nextHeat != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "
| Lane | Racer | Car # |
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if nextHeat.Lane1 != nil {
- templ_7745c5c3_Err = raceNextHeatRow(*nextHeat.Lane1).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- if nextHeat.Lane2 != nil {
- templ_7745c5c3_Err = raceNextHeatRow(*nextHeat.Lane2).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- if nextHeat.Lane3 != nil {
- templ_7745c5c3_Err = raceNextHeatRow(*nextHeat.Lane3).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- if nextHeat.Lane4 != nil {
- templ_7745c5c3_Err = raceNextHeatRow(*nextHeat.Lane4).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
+ templ_7745c5c3_Err = NextHeatDisplay(nextHeat).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -358,8 +178,182 @@ func RaceManage(heatData *models.HeatData, nextHeat *models.HeatData, groups []m
})
}
+func ResultsDisplay(results []models.HeatResult) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var7 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var7 == nil {
+ templ_7745c5c3_Var7 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "| Heat | Lane 1 | Lane 2 | Lane 3 | Lane 4 |
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, result := range results {
+ var templ_7745c5c3_Var8 = []any{"table-primary"}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "| ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var10 string
+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(result.HeatNumber))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 106, Col: 69}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, " | ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var11 string
+ templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.4f", result.Lane1Time))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 107, Col: 75}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, " (")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var12 string
+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(result.Lane1Position))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 107, Col: 115}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, ") | ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var13 string
+ templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.4f", result.Lane2Time))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 108, Col: 75}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " (")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var14 string
+ templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(result.Lane2Position))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 108, Col: 115}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, ") | ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var15 string
+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.4f", result.Lane3Time))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 109, Col: 75}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, " (")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var16 string
+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(result.Lane3Position))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 109, Col: 115}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, ") | ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var17 string
+ templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.4f", result.Lane4Time))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 110, Col: 75}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, " (")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var18 string
+ templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(result.Lane4Position))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 110, Col: 115}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, ") |
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
// Find the current heat
-func currentHeatDisplay(heatData *models.HeatData) templ.Component {
+func CurrentHeatDisplay(heatData *models.HeatData) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@@ -380,20 +374,20 @@ func currentHeatDisplay(heatData *models.HeatData) templ.Component {
templ_7745c5c3_Var19 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -451,72 +445,72 @@ func raceLaneInfo(laneData models.LaneData) templ.Component {
templ_7745c5c3_Var21 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -524,8 +518,7 @@ func raceLaneInfo(laneData models.LaneData) templ.Component {
})
}
-// Helper template for displaying a racer in the next heat
-func nextHeatRacer(laneData models.LaneData) templ.Component {
+func NextHeatDisplay(nextHeat *models.HeatData) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@@ -546,46 +539,119 @@ func nextHeatRacer(laneData models.LaneData) templ.Component {
templ_7745c5c3_Var27 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "
")
+ if nextHeat != nil {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "| Lane | Racer | Car # | ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if nextHeat.Lane1 != nil {
+ templ_7745c5c3_Err = raceNextHeatRow(*nextHeat.Lane1).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ if nextHeat.Lane2 != nil {
+ templ_7745c5c3_Err = raceNextHeatRow(*nextHeat.Lane2).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ if nextHeat.Lane3 != nil {
+ templ_7745c5c3_Err = raceNextHeatRow(*nextHeat.Lane3).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ if nextHeat.Lane4 != nil {
+ templ_7745c5c3_Err = raceNextHeatRow(*nextHeat.Lane4).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ return nil
+ })
+}
+
+// Helper template for displaying a racer in the next heat
+func nextHeatRacer(laneData models.LaneData) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var29 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var29 == nil {
+ templ_7745c5c3_Var29 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, " |
| ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var28 string
- templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(laneData.Lane))
+ var templ_7745c5c3_Var30 string
+ templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(laneData.Lane))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 195, Col: 41}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 206, Col: 41}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, " | ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, " | ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var29 string
- templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(laneData.Name)
+ var templ_7745c5c3_Var31 string
+ templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(laneData.Name)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 196, Col: 27}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 207, Col: 27}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, " | ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, " | ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var30 string
- templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(laneData.CarNum)
+ var templ_7745c5c3_Var32 string
+ templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(laneData.CarNum)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 197, Col: 29}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_manage.templ`, Line: 208, Col: 29}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, " |
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
diff --git a/web/templates/race_public.templ b/web/templates/race_public.templ
index 3922b55..b9da0a8 100644
--- a/web/templates/race_public.templ
+++ b/web/templates/race_public.templ
@@ -107,7 +107,7 @@ templ raceLaneCard(laneData models.LaneData) {
Time
-
+
{ fmt.Sprintf("%.3f", laneData.Time) }
@@ -115,7 +115,7 @@ templ raceLaneCard(laneData models.LaneData) {
Position
-
+
{ strconv.Itoa(laneData.Place) }