package main import ( "bufio" "fmt" "os" "os/signal" "strings" "syscall" "time" "track-gopher/derby" ) func main() { // Replace with your actual serial port portName := "/dev/ttyACM0" if len(os.Args) > 1 { portName = os.Args[1] } // Create a new derby clock connection clock, err := derby.NewDerbyClock(portName, 19200) if err != nil { fmt.Printf("Error opening derby clock: %v\n", err) os.Exit(1) } defer clock.Close() // Set up signal handling for clean shutdown sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) // Reset the clock to start fresh if err := clock.Reset(); err != nil { fmt.Printf("Error resetting clock: %v\n", err) os.Exit(1) } fmt.Println("Clock reset. Ready to start race.") // Print instructions fmt.Println("\nCommands:") fmt.Println(" r - Reset the clock") fmt.Println(" f - Force end the race") fmt.Println(" q - Quit the program") fmt.Println(" ? - Show this help message") // Process events from the clock go func() { raceResults := make([]*derby.Result, 0) for event := range clock.Events() { switch event.Type { case derby.EventRaceStart: fmt.Println("\nšŸ Race started!") case derby.EventLaneFinish: 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) case derby.EventRaceComplete: fmt.Println("\nšŸ† Race complete! Final results:") for _, result := range raceResults { fmt.Printf("Place %d: Lane %d - %.4f seconds\n", result.FinishPlace, result.Lane, result.Time) } fmt.Println("\nEnter command (r/f/q/?):") raceResults = nil } } }() // Handle keyboard input go func() { reader := bufio.NewReader(os.Stdin) for { fmt.Print("Enter command (r/f/q/?): ") input, err := reader.ReadString('\n') if err != nil { fmt.Printf("Error reading input: %v\n", err) continue } // Trim whitespace and convert to lowercase command := strings.TrimSpace(strings.ToLower(input)) switch command { case "r": fmt.Println("Resetting clock...") if err := clock.Reset(); err != nil { fmt.Printf("Error resetting clock: %v\n", err) } else { fmt.Println("Clock reset. Ready to start race.") } case "f": fmt.Println("Forcing race to end...") if err := clock.ForceEnd(); err != nil { fmt.Printf("Error forcing race end: %v\n", err) } case "q": fmt.Println("Quitting...") sigChan <- syscall.SIGTERM return case "?": fmt.Println("\nCommands:") fmt.Println(" r - Reset the clock") fmt.Println(" f - Force end the race") fmt.Println(" q - Quit the program") fmt.Println(" ? - Show this help message") default: if command != "" { fmt.Println("Unknown command. Type ? for help.") } } } }() // Wait for signal to exit <-sigChan fmt.Println("Shutting down...") time.Sleep(500 * time.Millisecond) // Give a moment for any pending operations to complete }