package clock import ( "context" "encoding/json" "time" ) // StartTicker runs the clock ticker for the given engine. // It ticks every 100ms and broadcasts clock snapshots: // - 1/sec during normal play // - 10/sec (every 100ms) during the final 10 seconds // // The ticker stops when the context is cancelled. func StartTicker(ctx context.Context, engine *ClockEngine) { ticker := time.NewTicker(100 * time.Millisecond) defer ticker.Stop() var lastBroadcastSecond int64 = -1 for { select { case <-ctx.Done(): return case <-ticker.C: shouldBroadcast, snapshot := engine.Tick() if !shouldBroadcast { continue } // Determine broadcast rate: // - Final 10 seconds: broadcast every tick (10/sec) // - Normal: broadcast once per second (1/sec) currentSecond := snapshot.RemainingMs / 1000 isFinalSeconds := snapshot.RemainingMs <= 10000 if isFinalSeconds { // Broadcast every 100ms tick in final 10 seconds broadcastSnapshot(engine, snapshot) lastBroadcastSecond = currentSecond } else if currentSecond != lastBroadcastSecond { // Broadcast once per second change broadcastSnapshot(engine, snapshot) lastBroadcastSecond = currentSecond } } } } // broadcastSnapshot sends a clock snapshot to all WebSocket clients. func broadcastSnapshot(engine *ClockEngine, snapshot ClockSnapshot) { engine.mu.RLock() hub := engine.hub tournamentID := engine.tournamentID engine.mu.RUnlock() if hub == nil { return } data, err := json.Marshal(snapshot) if err != nil { return } hub.Broadcast(tournamentID, "clock.tick", data) }