diff --git a/db/db.go b/db/db.go index defd07a..cf4aea2 100644 --- a/db/db.go +++ b/db/db.go @@ -441,3 +441,115 @@ func (db *DB) DeleteHeatResult(groupID int64, heatNum int) error { groupID, heatNum) return err } + +func (db *DB) GetHeatData(groupID int64, heatNum int) (*models.HeatData, error) { + heatData := &models.HeatData{} + lane1 := int64(0) + lane2 := int64(0) + lane3 := int64(0) + lane4 := int64(0) + + err := db.QueryRow(` + SELECT + group_id, heat_number, + g.name as group_name, + (SELECT COUNT(*) FROM heats WHERE group_id = ?) as total_heats, + h.lane1_id, h.lane2_id, h.lane3_id, h.lane4_id + FROM heats h + JOIN groups g ON g.id = h.group_id + WHERE h.group_id = ? AND h.heat_num = ?`, + groupID, groupID, heatNum).Scan( + &heatData.Group.ID, &heatData.HeatNumber, + &heatData.Group.Name, &heatData.TotalHeats, + &lane1, &lane2, &lane3, &lane4) + + if err != nil { + return nil, fmt.Errorf("error getting heat data: %v", err) + } + + // Get racer data for each lane + if lane1 != 0 { + lane1Data, err := db.getLaneData(1, lane1, heatNum, groupID) + if err != nil { + return nil, err + } + heatData.Lane1 = lane1Data + } + + if lane2 != 0 { + lane2Data, err := db.getLaneData(2, lane2, heatNum, groupID) + if err != nil { + return nil, err + } + heatData.Lane2 = lane2Data + } + + if lane3 != 0 { + lane3Data, err := db.getLaneData(3, lane3, heatNum, groupID) + if err != nil { + return nil, err + } + heatData.Lane3 = lane3Data + } + + if lane4 != 0 { + lane4Data, err := db.getLaneData(4, lane4, heatNum, groupID) + if err != nil { + return nil, err + } + heatData.Lane4 = lane4Data + } + + return heatData, nil +} + +// getLaneData gets the racer data for a specific lane +func (db *DB) getLaneData(lane int, racerID int64, heatNum int, groupID int64) (*models.LaneData, error) { + // Get racer data + var racer models.Racer + err := db.QueryRow(` + SELECT id, first_name, last_name, car_number, car_weight, group_id + FROM racers + WHERE id = ?`, racerID).Scan( + &racer.ID, &racer.FirstName, &racer.LastName, &racer.CarNumber, &racer.CarWeight, &racer.GroupID) + + if err != nil { + if err == sql.ErrNoRows { + return nil, ErrNotFound + } + return nil, err + } + + // Create lane data with racer info + laneData := &models.LaneData{ + Lane: lane, + RacerID: racerID, + Name: racer.FirstName + " " + racer.LastName, + CarNum: racer.CarNumber, + CarWeight: racer.CarWeight, + Time: 0, + Place: 0, + } + + heatResult, err := db.GetHeatResult(groupID, heatNum) + if err != nil { + return laneData, nil + } + + switch lane { + case 1: + laneData.Time = heatResult.Lane1Time + laneData.Place = heatResult.Lane1Position + case 2: + laneData.Time = heatResult.Lane2Time + laneData.Place = heatResult.Lane2Position + case 3: + laneData.Time = heatResult.Lane3Time + laneData.Place = heatResult.Lane3Position + case 4: + laneData.Time = heatResult.Lane4Time + laneData.Place = heatResult.Lane4Position + } + + return laneData, nil +} diff --git a/derby/derby.go b/derby/derby.go index 80318f6..d144fb3 100644 --- a/derby/derby.go +++ b/derby/derby.go @@ -36,12 +36,15 @@ const ( EventRaceStart EventType = iota EventLaneFinish EventRaceComplete + EventHeatChanged + EventGroupChanged + EventHeatRerun ) // Event represents a race event type Event struct { - Type EventType - Result *Result // Only populated for EventLaneFinish + Type EventType + Event any // Only populated for EventLaneFinish } // DerbyClock represents the connection to the derby clock device @@ -202,8 +205,8 @@ func (dc *DerbyClock) readLoop() { if result != nil { // Send lane finish event dc.eventChan <- Event{ - Type: EventLaneFinish, - Result: result, + Type: EventLaneFinish, + Event: result, } } results = append(results, result) diff --git a/examples/main.go b/examples/main.go index 7339aa6..1069e22 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.Result + result := event.Event.(derby.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 c003c65..8da323c 100644 --- a/models/models.go +++ b/models/models.go @@ -67,3 +67,23 @@ type HeatResult struct { Lane4Time float64 `json:"lane4_time"` Lane4Position int `json:"lane4_position"` } + +type LaneData struct { + Lane int + RacerID int64 + Name string + CarNum string + CarWeight float64 + Time float64 + Place int +} + +type HeatData struct { + Group Group + HeatNumber int + TotalHeats int + Lane1 *LaneData + Lane2 *LaneData + Lane3 *LaneData + Lane4 *LaneData +} diff --git a/web/server.go b/web/server.go index ad2aa9d..a6c8584 100644 --- a/web/server.go +++ b/web/server.go @@ -148,9 +148,6 @@ func (s *Server) routes() { // Add racers list route s.router.Get("/admin/racers/list", s.handleRacersList()) - // Add admin events route - s.router.Get("/api/admin-events", s.handleAdminEvents()) - // Add validate car number route s.router.Get("/api/validate/car-number", s.handleValidateCarNumber()) @@ -163,7 +160,6 @@ func (s *Server) routes() { r.Get("/current-heat", s.handleCurrentHeat()) r.Post("/next-heat", s.handleNextHeat()) r.Post("/previous-heat", s.handlePreviousHeat()) - r.Post("/save-result", s.handleSaveHeatResult()) r.Post("/rerun-heat", s.handleRerunHeat()) r.Post("/set-group", s.handleSetRacingGroup()) }) @@ -229,49 +225,36 @@ func (s *Server) forwardEvents() { // broadcastEvent sends an event to all connected clients func (s *Server) broadcastEvent(event derby.Event) { - var message string - switch event.Type { case derby.EventRaceStart: s.logger.Info("Broadcasting race start event") - statusMsg := struct { - Status string `json:"status"` - }{ - Status: "running", - } - statusJSON, _ := json.Marshal(statusMsg) - message = fmt.Sprintf("event: status\ndata: %s", statusJSON) + s.sendEventToAllClients("event: race-status\ndata:
Race Running
") case derby.EventLaneFinish: s.logger.Info("Broadcasting lane finish event", - "lane", event.Result.Lane, - "time", event.Result.Time, - "place", event.Result.FinishPlace) - - // Create a message for lane finish - laneData := struct { - Lane int `json:"lane"` - Time float64 `json:"time"` - Place int `json:"place"` - }{ - Lane: event.Result.Lane, - Time: event.Result.Time, - Place: event.Result.FinishPlace, - } - laneJSON, _ := json.Marshal(laneData) - message = fmt.Sprintf("event: lane-finish\ndata: %s", laneJSON) + "lane", event.Event.(derby.Result).Lane, + "time", event.Event.(derby.Result).Time, + "place", event.Event.(derby.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.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
") + + case derby.EventGroupChanged: + s.logger.Info("Broadcasting group changed event") + s.sendEventToAllClients("event: group-changed\ndata:
Group Changed
") case derby.EventRaceComplete: s.logger.Info("Broadcasting race complete event") - statusMsg := struct { - Status string `json:"status"` - }{ - Status: "finished", - } - statusJSON, _ := json.Marshal(statusMsg) - message = fmt.Sprintf("event: status\ndata: %s", statusJSON) + s.sendEventToAllClients("event: race-status\ndata:
Race Complete
") } +} +func (s *Server) sendEventToAllClients(message string) { if message == "" { return } @@ -281,17 +264,13 @@ func (s *Server) broadcastEvent(event derby.Event) { clientCount := len(s.clients) sentCount := 0 for clientChan := range s.clients { - select { - case clientChan <- message: - sentCount++ - default: - s.logger.Warn("Client channel is full, event not sent") - } + clientChan <- message + sentCount++ } - s.logger.Info("Event broadcast complete", + s.logger.Debug("Event broadcast complete", "sentCount", sentCount, "totalClients", clientCount, - "eventType", event.Type) + "message", message) s.clientsMux.Unlock() } @@ -1026,31 +1005,21 @@ func (s *Server) handleRacePublic() http.HandlerFunc { } // Get heats for the group - heats, err := s.db.GetHeats(currentGroup.ID) + heatData, err := s.db.GetHeatData(currentGroup.ID, currentHeatNum) if err != nil { s.logger.Error("Failed to get heats", "error", err) http.Error(w, "Failed to get heats", http.StatusInternalServerError) return } - // Get racers for the group - racers, err := s.db.GetRacersByGroup(currentGroup.ID) - if err != nil { - s.logger.Error("Failed to get racers", "error", err) - http.Error(w, "Failed to get racers", http.StatusInternalServerError) - return - } + // Get next heat data + nextHeatData, _ := s.db.GetHeatData(currentGroup.ID, currentHeatNum+1) - // Get heat results - results, err := s.db.GetHeatResults(currentGroup.ID) - if err != nil { - s.logger.Error("Failed to get heat results", "error", err) - http.Error(w, "Failed to get heat results", http.StatusInternalServerError) - return - } + // Get on-deck heat data + onDeckHeatData, _ := s.db.GetHeatData(currentGroup.ID, currentHeatNum+2) // Render template - component := templates.RacePublic(currentGroup, heats, racers, currentHeatNum, results) + component := templates.RacePublic(heatData, nextHeatData, onDeckHeatData) if err := component.Render(r.Context(), w); err != nil { s.logger.Error("Failed to render race public template", "error", err) http.Error(w, "Failed to render page", http.StatusInternalServerError) diff --git a/web/static/js/sse.min.js b/web/static/js/sse.min.js new file mode 100644 index 0000000..2ba734c --- /dev/null +++ b/web/static/js/sse.min.js @@ -0,0 +1 @@ +(function(){var g;htmx.defineExtension("sse",{init:function(e){g=e;if(htmx.createEventSource==undefined){htmx.createEventSource=t}},getSelectors:function(){return["[sse-connect]","[data-sse-connect]","[sse-swap]","[data-sse-swap]"]},onEvent:function(e,t){var r=t.target||t.detail.elt;switch(e){case"htmx:beforeCleanupElement":var n=g.getInternalData(r);var s=n.sseEventSource;if(s){g.triggerEvent(r,"htmx:sseClose",{source:s,type:"nodeReplaced"});n.sseEventSource.close()}return;case"htmx:afterProcessNode":i(r)}}});function t(e){return new EventSource(e,{withCredentials:true})}function a(n){if(g.getAttributeValue(n,"sse-swap")){var s=g.getClosestMatch(n,v);if(s==null){return null}var e=g.getInternalData(s);var a=e.sseEventSource;var t=g.getAttributeValue(n,"sse-swap");var r=t.split(",");for(var i=0;i0){const t=r.querySelectorAll("[sse-swap], [data-sse-swap], [hx-trigger], [data-hx-trigger]");for(let e=0;e
-

{ currentGroup.Name } - Heat { strconv.Itoa(currentHeatNum) } of { strconv.Itoa(len(heats)) }

+

{ heatData.Group.Name } - Heat { strconv.Itoa(heatData.HeatNumber) } of { strconv.Itoa(heatData.TotalHeats) }

@@ -26,7 +26,7 @@ templ RacePublic(currentGroup models.Group, heats []models.Heat, racers []models
- @raceCurrentHeatLanes(heats, racers, currentHeatNum, results) + @raceCurrentHeatLanes(heatData)
@@ -43,8 +43,8 @@ templ RacePublic(currentGroup models.Group, heats []models.Heat, racers []models

Next Heat

- if currentHeatNum < len(heats) { - @raceNextHeatPreview(heats, racers, currentHeatNum+1) + if nextHeat != nil { + @raceNextHeatPreview(nextHeat) } else {
No more heats in this group
} @@ -57,8 +57,8 @@ templ RacePublic(currentGroup models.Group, heats []models.Heat, racers []models

Upcoming Heat

- if currentHeatNum+1 < len(heats) { - @raceNextHeatPreview(heats, racers, currentHeatNum+2) + if onDeckHeat != nil { + @raceNextHeatPreview(onDeckHeat) } else {
No more heats in this group
} @@ -67,214 +67,56 @@ templ RacePublic(currentGroup models.Group, heats []models.Heat, racers []models
- - } } // Helper template for displaying current heat lanes -templ raceCurrentHeatLanes(heats []models.Heat, racers []models.Racer, currentHeatNum int, results []models.HeatResult) { - {{ - // Find current heat - var currentHeat models.Heat - for _, heat := range heats { - if heat.HeatNum == currentHeatNum { - currentHeat = heat - break - } - } - - // Find heat result if available - var currentResult *models.HeatResult - for _, result := range results { - if result.HeatNumber == currentHeatNum { - currentResult = &result - break - } - } - }} +templ raceCurrentHeatLanes(heatData *models.HeatData) {
- if currentHeat.Lane1ID != nil { - @raceLaneCard(1, *currentHeat.Lane1ID, racers, currentResult) + if heatData.Lane1 != nil { + @raceLaneCard(*heatData.Lane1) } - if currentHeat.Lane2ID != nil { - @raceLaneCard(2, *currentHeat.Lane2ID, racers, currentResult) + if heatData.Lane2 != nil { + @raceLaneCard(*heatData.Lane2) } - if currentHeat.Lane3ID != nil { - @raceLaneCard(3, *currentHeat.Lane3ID, racers, currentResult) + if heatData.Lane3 != nil { + @raceLaneCard(*heatData.Lane3) } - if currentHeat.Lane4ID != nil { - @raceLaneCard(4, *currentHeat.Lane4ID, racers, currentResult) + if heatData.Lane4 != nil { + @raceLaneCard(*heatData.Lane4) }
} // Helper template for displaying a lane card -templ raceLaneCard(lane int, racerID int64, racers []models.Racer, result *models.HeatResult) { - {{ - // Find racer - var racer models.Racer - for _, r := range racers { - if r.ID == racerID { - racer = r - break - } - } - - // Get time and position from result if available - var time float64 - var position int - var hasResult bool - - if result != nil { - hasResult = true - switch lane { - case 1: - time = result.Lane1Time - position = result.Lane1Position - case 2: - time = result.Lane2Time - position = result.Lane2Position - case 3: - time = result.Lane3Time - position = result.Lane3Position - case 4: - time = result.Lane4Time - position = result.Lane4Position - } - } - }} - +templ raceLaneCard(laneData models.LaneData) {
-
+
-

Lane { strconv.Itoa(lane) }

+

Lane { strconv.Itoa(laneData.Lane) }

-
{ racer.FirstName } { racer.LastName }
+
{ laneData.Name }

- Car #: { racer.CarNumber }
- Weight: { fmt.Sprintf("%.1f oz", racer.CarWeight) } + Car #: { laneData.CarNum }
+ Weight: { fmt.Sprintf("%.1f oz", laneData.CarWeight) }

Time
-
- if hasResult { - { fmt.Sprintf("%.3f", time) } - } else { - --.- - } +
+ { fmt.Sprintf("%.3f", laneData.Time) }
Position
-
- if hasResult { - { strconv.Itoa(position) } - } else { - - - } +
+ { strconv.Itoa(laneData.Place) }
@@ -286,19 +128,8 @@ templ raceLaneCard(lane int, racerID int64, racers []models.Racer, result *model } // Helper template for displaying next heat preview -templ raceNextHeatPreview(heats []models.Heat, racers []models.Racer, heatNum int) { - {{ - // Find the heat - var nextHeat models.Heat - for _, heat := range heats { - if heat.HeatNum == heatNum { - nextHeat = heat - break - } - } - }} - -

Heat { strconv.Itoa(heatNum) }

+templ raceNextHeatPreview(heatData *models.HeatData) { +

Heat { strconv.Itoa(heatData.HeatNumber) }

@@ -309,17 +140,17 @@ templ raceNextHeatPreview(heats []models.Heat, racers []models.Racer, heatNum in - if nextHeat.Lane1ID != nil { - @raceNextHeatRow(1, *nextHeat.Lane1ID, racers) + if heatData.Lane1 != nil { + @raceNextHeatRow(*heatData.Lane1) } - if nextHeat.Lane2ID != nil { - @raceNextHeatRow(2, *nextHeat.Lane2ID, racers) + if heatData.Lane2 != nil { + @raceNextHeatRow(*heatData.Lane2) } - if nextHeat.Lane3ID != nil { - @raceNextHeatRow(3, *nextHeat.Lane3ID, racers) + if heatData.Lane3 != nil { + @raceNextHeatRow(*heatData.Lane3) } - if nextHeat.Lane4ID != nil { - @raceNextHeatRow(4, *nextHeat.Lane4ID, racers) + if heatData.Lane4 != nil { + @raceNextHeatRow(*heatData.Lane4) }
@@ -327,21 +158,10 @@ templ raceNextHeatPreview(heats []models.Heat, racers []models.Racer, heatNum in } // Helper template for displaying a row in the next heat preview -templ raceNextHeatRow(lane int, racerID int64, racers []models.Racer) { - {{ - // Find racer - var racer models.Racer - for _, r := range racers { - if r.ID == racerID { - racer = r - break - } - } - }} - +templ raceNextHeatRow(laneData models.LaneData) { - { strconv.Itoa(lane) } - { racer.FirstName } { racer.LastName } - { racer.CarNumber } + { strconv.Itoa(laneData.Lane) } + { laneData.Name } + { laneData.CarNum } } \ No newline at end of file diff --git a/web/templates/race_public_templ.go b/web/templates/race_public_templ.go index d2117e3..72d7c40 100644 --- a/web/templates/race_public_templ.go +++ b/web/templates/race_public_templ.go @@ -15,7 +15,7 @@ import ( ) // RacePublic renders the public race view -func RacePublic(currentGroup models.Group, heats []models.Heat, racers []models.Racer, currentHeatNum int, results []models.HeatResult) templ.Component { +func RacePublic(heatData *models.HeatData, nextHeat *models.HeatData, onDeckHeat *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 { @@ -53,9 +53,9 @@ func RacePublic(currentGroup models.Group, heats []models.Heat, racers []models. return templ_7745c5c3_Err } var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(currentGroup.Name) + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(heatData.Group.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 17, Col: 76} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 17, Col: 78} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -66,9 +66,9 @@ func RacePublic(currentGroup models.Group, heats []models.Heat, racers []models. return templ_7745c5c3_Err } var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(currentHeatNum)) + templ_7745c5c3_Var4, 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_public.templ`, Line: 17, Col: 116} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 17, Col: 123} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { @@ -79,9 +79,9 @@ func RacePublic(currentGroup models.Group, heats []models.Heat, racers []models. return templ_7745c5c3_Err } var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(len(heats))) + templ_7745c5c3_Var5, 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_public.templ`, Line: 17, Col: 148} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 17, Col: 164} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { @@ -91,7 +91,7 @@ func RacePublic(currentGroup models.Group, heats []models.Heat, racers []models. if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = raceCurrentHeatLanes(heats, racers, currentHeatNum, results).Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = raceCurrentHeatLanes(heatData).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -99,8 +99,8 @@ func RacePublic(currentGroup models.Group, heats []models.Heat, racers []models. if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if currentHeatNum < len(heats) { - templ_7745c5c3_Err = raceNextHeatPreview(heats, racers, currentHeatNum+1).Render(ctx, templ_7745c5c3_Buffer) + if nextHeat != nil { + templ_7745c5c3_Err = raceNextHeatPreview(nextHeat).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -114,8 +114,8 @@ func RacePublic(currentGroup models.Group, heats []models.Heat, racers []models. if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if currentHeatNum+1 < len(heats) { - templ_7745c5c3_Err = raceNextHeatPreview(heats, racers, currentHeatNum+2).Render(ctx, templ_7745c5c3_Buffer) + if onDeckHeat != nil { + templ_7745c5c3_Err = raceNextHeatPreview(onDeckHeat).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -125,13 +125,13 @@ func RacePublic(currentGroup models.Group, heats []models.Heat, racers []models. return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) - templ_7745c5c3_Err = LayoutPublic("Race - "+currentGroup.Name).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = LayoutPublic("Race - "+heatData.Group.Name).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -140,7 +140,7 @@ func RacePublic(currentGroup models.Group, heats []models.Heat, racers []models. } // Helper template for displaying current heat lanes -func raceCurrentHeatLanes(heats []models.Heat, racers []models.Racer, currentHeatNum int, results []models.HeatResult) templ.Component { +func raceCurrentHeatLanes(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 { @@ -161,48 +161,30 @@ func raceCurrentHeatLanes(heats []models.Heat, racers []models.Racer, currentHea templ_7745c5c3_Var6 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - - // Find current heat - var currentHeat models.Heat - for _, heat := range heats { - if heat.HeatNum == currentHeatNum { - currentHeat = heat - break - } - } - - // Find heat result if available - var currentResult *models.HeatResult - for _, result := range results { - if result.HeatNumber == currentHeatNum { - currentResult = &result - break - } - } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if currentHeat.Lane1ID != nil { - templ_7745c5c3_Err = raceLaneCard(1, *currentHeat.Lane1ID, racers, currentResult).Render(ctx, templ_7745c5c3_Buffer) + if heatData.Lane1 != nil { + templ_7745c5c3_Err = raceLaneCard(*heatData.Lane1).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - if currentHeat.Lane2ID != nil { - templ_7745c5c3_Err = raceLaneCard(2, *currentHeat.Lane2ID, racers, currentResult).Render(ctx, templ_7745c5c3_Buffer) + if heatData.Lane2 != nil { + templ_7745c5c3_Err = raceLaneCard(*heatData.Lane2).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - if currentHeat.Lane3ID != nil { - templ_7745c5c3_Err = raceLaneCard(3, *currentHeat.Lane3ID, racers, currentResult).Render(ctx, templ_7745c5c3_Buffer) + if heatData.Lane3 != nil { + templ_7745c5c3_Err = raceLaneCard(*heatData.Lane3).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - if currentHeat.Lane4ID != nil { - templ_7745c5c3_Err = raceLaneCard(4, *currentHeat.Lane4ID, racers, currentResult).Render(ctx, templ_7745c5c3_Buffer) + if heatData.Lane4 != nil { + templ_7745c5c3_Err = raceLaneCard(*heatData.Lane4).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -216,7 +198,7 @@ func raceCurrentHeatLanes(heats []models.Heat, racers []models.Racer, currentHea } // Helper template for displaying a lane card -func raceLaneCard(lane int, racerID int64, racers []models.Racer, result *models.HeatResult) templ.Component { +func raceLaneCard(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 { @@ -237,46 +219,14 @@ func raceLaneCard(lane int, racerID int64, racers []models.Racer, result *models templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - - // Find racer - var racer models.Racer - for _, r := range racers { - if r.ID == racerID { - racer = r - break - } - } - - // Get time and position from result if available - var time float64 - var position int - var hasResult bool - - if result != nil { - hasResult = true - switch lane { - case 1: - time = result.Lane1Time - position = result.Lane1Position - case 2: - time = result.Lane2Time - position = result.Lane2Position - case 3: - time = result.Lane3Time - position = result.Lane3Position - case 4: - time = result.Lane4Time - position = result.Lane4Position - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "

Lane ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "

Lane ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(lane)) + templ_7745c5c3_Var8, 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_public.templ`, Line: 247, Col: 58} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 97, Col: 67} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { @@ -287,120 +237,67 @@ func raceLaneCard(lane int, racerID int64, racers []models.Racer, result *models return templ_7745c5c3_Err } var templ_7745c5c3_Var9 string - templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(racer.FirstName) + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(laneData.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 250, Col: 56} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 100, Col: 54} } _, 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, 14, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "

Car #: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var10 string - templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(racer.LastName) + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(laneData.CarNum) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 250, Col: 75} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 102, Col: 61} } _, 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, 15, "

Car #: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
Weight: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var11 string - templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(racer.CarNumber) + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f oz", laneData.CarWeight)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 252, Col: 61} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 103, Col: 89} } _, 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, 16, "
Weight: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "

Time
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var12 string - templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f oz", racer.CarWeight)) + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.3f", laneData.Time)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 253, Col: 86} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 111, Col: 72} } _, 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, 17, "

Time
Position
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var13 string - templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("lane-%d-time", lane)) + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(laneData.Place)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 260, Col: 75} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 119, Col: 66} } _, 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, 18, "\" class=\"display-6\">") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if hasResult { - var templ_7745c5c3_Var14 string - templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.3f", time)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 262, Col: 67} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "--.-") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "
Position
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if hasResult { - var templ_7745c5c3_Var16 string - templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(position)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 274, Col: 64} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "-") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -409,7 +306,7 @@ func raceLaneCard(lane int, racerID int64, racers []models.Racer, result *models } // Helper template for displaying next heat preview -func raceNextHeatPreview(heats []models.Heat, racers []models.Racer, heatNum int) templ.Component { +func raceNextHeatPreview(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 { @@ -425,62 +322,53 @@ func raceNextHeatPreview(heats []models.Heat, racers []models.Racer, heatNum int }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var17 := templ.GetChildren(ctx) - if templ_7745c5c3_Var17 == nil { - templ_7745c5c3_Var17 = templ.NopComponent + templ_7745c5c3_Var14 := templ.GetChildren(ctx) + if templ_7745c5c3_Var14 == nil { + templ_7745c5c3_Var14 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - - // Find the heat - var nextHeat models.Heat - for _, heat := range heats { - if heat.HeatNum == heatNum { - nextHeat = heat - break - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "

Heat ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "

Heat ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var18 string - templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(heatNum)) + var templ_7745c5c3_Var15 string + templ_7745c5c3_Var15, 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_public.templ`, Line: 301, Col: 49} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 132, Col: 61} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) + _, 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, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "
LaneRacerCar #
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if nextHeat.Lane1ID != nil { - templ_7745c5c3_Err = raceNextHeatRow(1, *nextHeat.Lane1ID, racers).Render(ctx, templ_7745c5c3_Buffer) + if heatData.Lane1 != nil { + templ_7745c5c3_Err = raceNextHeatRow(*heatData.Lane1).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - if nextHeat.Lane2ID != nil { - templ_7745c5c3_Err = raceNextHeatRow(2, *nextHeat.Lane2ID, racers).Render(ctx, templ_7745c5c3_Buffer) + if heatData.Lane2 != nil { + templ_7745c5c3_Err = raceNextHeatRow(*heatData.Lane2).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - if nextHeat.Lane3ID != nil { - templ_7745c5c3_Err = raceNextHeatRow(3, *nextHeat.Lane3ID, racers).Render(ctx, templ_7745c5c3_Buffer) + if heatData.Lane3 != nil { + templ_7745c5c3_Err = raceNextHeatRow(*heatData.Lane3).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - if nextHeat.Lane4ID != nil { - templ_7745c5c3_Err = raceNextHeatRow(4, *nextHeat.Lane4ID, racers).Render(ctx, templ_7745c5c3_Buffer) + if heatData.Lane4 != nil { + templ_7745c5c3_Err = raceNextHeatRow(*heatData.Lane4).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "
LaneRacerCar #
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -489,7 +377,7 @@ func raceNextHeatPreview(heats []models.Heat, racers []models.Racer, heatNum int } // Helper template for displaying a row in the next heat preview -func raceNextHeatRow(lane int, racerID int64, racers []models.Racer) templ.Component { +func raceNextHeatRow(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 { @@ -505,73 +393,51 @@ func raceNextHeatRow(lane int, racerID int64, racers []models.Racer) templ.Compo }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var19 := templ.GetChildren(ctx) - if templ_7745c5c3_Var19 == nil { - templ_7745c5c3_Var19 = templ.NopComponent + templ_7745c5c3_Var16 := templ.GetChildren(ctx) + if templ_7745c5c3_Var16 == nil { + templ_7745c5c3_Var16 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - - // Find racer - var racer models.Racer - for _, r := range racers { - if r.ID == racerID { - racer = r - break - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var20 string - templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(lane)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 343, Col: 32} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var21 string - templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(racer.FirstName) + var templ_7745c5c3_Var17 string + templ_7745c5c3_Var17, 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_public.templ`, Line: 344, Col: 29} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 163, Col: 41} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) + _, 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, 29, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var22 string - templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(racer.LastName) + var templ_7745c5c3_Var18 string + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(laneData.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 344, Col: 48} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 164, Col: 27} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) + _, 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, 30, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var23 string - templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(racer.CarNumber) + var templ_7745c5c3_Var19 string + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(laneData.CarNum) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 345, Col: 29} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates/race_public.templ`, Line: 165, Col: 29} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err }