github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2012/chat/markov/chat.go (about) 1 // +build OMIT 2 3 package main 4 5 import ( 6 "fmt" 7 "io" 8 "log" 9 "net/http" 10 "time" 11 12 "golang.org/x/net/websocket" 13 ) 14 15 const listenAddr = "localhost:4000" 16 17 func main() { 18 http.HandleFunc("/", rootHandler) 19 http.Handle("/socket", websocket.Handler(socketHandler)) 20 err := http.ListenAndServe(listenAddr, nil) 21 if err != nil { 22 log.Fatal(err) 23 } 24 } 25 26 type socket struct { 27 io.Reader 28 io.Writer 29 done chan bool 30 } 31 32 func (s socket) Close() error { 33 s.done <- true 34 return nil 35 } 36 37 var chain = NewChain(2) // 2-word prefixes 38 39 func socketHandler(ws *websocket.Conn) { 40 r, w := io.Pipe() // HL 41 go func() { // HL 42 _, err := io.Copy(io.MultiWriter(w, chain), ws) // HL 43 w.CloseWithError(err) // HL 44 }() // HL 45 s := socket{r, ws, make(chan bool)} 46 go match(s) 47 <-s.done 48 } 49 50 var partner = make(chan io.ReadWriteCloser) 51 52 func match(c io.ReadWriteCloser) { 53 fmt.Fprint(c, "Waiting for a partner...") 54 select { 55 case partner <- c: 56 // now handled by the other goroutine 57 case p := <-partner: 58 chat(p, c) 59 case <-time.After(5 * time.Second): // HL 60 chat(Bot(), c) // HL 61 } 62 } 63 64 func chat(a, b io.ReadWriteCloser) { 65 fmt.Fprintln(a, "Found one! Say hi.") 66 fmt.Fprintln(b, "Found one! Say hi.") 67 errc := make(chan error, 1) 68 go cp(a, b, errc) 69 go cp(b, a, errc) 70 if err := <-errc; err != nil { 71 log.Println(err) 72 } 73 a.Close() 74 b.Close() 75 } 76 77 func cp(w io.Writer, r io.Reader, errc chan<- error) { 78 _, err := io.Copy(w, r) 79 errc <- err 80 } 81 82 // Bot returns an io.ReadWriteCloser that responds to 83 // each incoming write with a generated sentence. 84 func Bot() io.ReadWriteCloser { 85 r, out := io.Pipe() // for outgoing data 86 return bot{r, out} 87 } 88 89 type bot struct { 90 io.ReadCloser 91 out io.Writer 92 } 93 94 func (b bot) Write(buf []byte) (int, error) { 95 go b.speak() 96 return len(buf), nil 97 } 98 99 func (b bot) speak() { 100 time.Sleep(time.Second) 101 msg := chain.Generate(10) // at most 10 words 102 b.out.Write([]byte(msg)) 103 }