package main import ( "encoding/json" "log" "net/http" "time" "github.com/gorilla/websocket" ) const ( workDuration = 15 * 60 shortBreakDuration = 5 * 60 longBreakDuration = 10 * 60 sessions = 4 ) type BroadcastMessage struct { Mode string `json:"mode"` Session int `json:"session"` MaxSession int `json:"max_session"` TimeLeft int `json:"time_left"` } var clients = make(map[*websocket.Conn]bool) // broadcastMessage sends the remaining time to all connected clients. func broadcastMessage(message BroadcastMessage) { jsonMessage, _ := json.Marshal(message) for client := range clients { err := client.WriteMessage(websocket.TextMessage, jsonMessage) if err != nil { log.Printf("Error broadcasting to client: %v", err) client.Close() delete(clients, client) } } } // start a countdown and broadcast ever second func startTimer(remaining_seconds int, mode string, session int) { for remaining_seconds > 0 { broadcastMessage(BroadcastMessage{ Mode: mode, Session: session, MaxSession: sessions, TimeLeft: remaining_seconds, }) time.Sleep(time.Second) remaining_seconds-- } // send final 0 timer broadcastMessage(BroadcastMessage{ Mode: mode, Session: 1, MaxSession: 4, TimeLeft: 0, }) } // iterate the Pomodoro work/break sessions func runPomodoroTimer() { for session := 1; session <= sessions; session++ { startTimer(workDuration, "Work", session) if session == sessions { startTimer(longBreakDuration, "LongBreak", session) } else { startTimer(shortBreakDuration, "ShortBreak", session) } } } // upgrade HTTP requests to WebSocket connections. var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } func handleConnections(w http.ResponseWriter, r *http.Request) { // Upgrade initial GET request to a WebSocket ws, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Printf("WebSocket upgrade error: %v", err) return } defer ws.Close() // Register the new client clients[ws] = true // Clean up when the client disconnects for { _, _, err := ws.ReadMessage() if err != nil { log.Printf("Client disconnected: %v", err) delete(clients, ws) break } } } func main() { http.HandleFunc("/ws", handleConnections) // Start a goroutine that runs the Pomodoro timer and broadcasts updates. go runPomodoroTimer() log.Println("Pomodoro WebSocket server started on :8080") err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatalf("Error starting server: %v", err) } }