package door import ( "bytes" "fmt" "strings" "time" ) /* WOPR [ GAME ] [ TIME ELAPSED ] [ XX HRS ] [ XX MIN XX SEC ] [■ ] -> [ GAME ] [ TIME REMAINING ] [ XX HRS ] [ XX MIN XX SEC ] [ ■] <- Border SINGLE Ok, Width = 16 1000 / 16 = 62.5 ms = 62500 us Width 16 (at pos 1, update time/sec increment) Black on Cyan */ type WOPR struct { ElapsedPanel Panel Elapsed time.Duration RemainingPanel Panel Remaining time.Duration Color string Index int Ticker *time.Ticker } // Initialize, Set X, Y on Panels, Animate() // Initialize, and create panels func (w *WOPR) Init(elapsed time.Duration, remaining time.Duration, color string) { if color == "" { color = ColorText("BLACK ON CYAN") } w.Elapsed = elapsed w.Remaining = remaining w.Index = 0 w.ElapsedPanel = Panel{Width: 16, BorderColor: color, Style: SINGLE} w.ElapsedPanel.Lines = append(w.ElapsedPanel.Lines, Line{Text: " GAME "}) w.ElapsedPanel.Lines = append(w.ElapsedPanel.Lines, Line{Text: " TIME ELAPSED "}) var ehour Line = Line{} ehour.UpdateF = func() string { var hours int = int(w.Elapsed.Hours()) return fmt.Sprintf(" %02d HRS ", hours%100) } ehour.Text = ehour.UpdateF() w.ElapsedPanel.Lines = append(w.ElapsedPanel.Lines, ehour) var eminsec Line = Line{} eminsec.UpdateF = func() string { var mins int = int(w.Elapsed.Minutes()) % 60 var secs int = int(w.Elapsed.Seconds()) % 60 return fmt.Sprintf(" %02d MIN %02d SEC ", mins, secs) } eminsec.Text = eminsec.UpdateF() w.ElapsedPanel.Lines = append(w.ElapsedPanel.Lines, eminsec) var eanimate Line = Line{} eanimate.UpdateF = func() string { // Left to Right if Unicode { var buffer []rune = []rune(strings.Repeat(" ", 16)) buffer[w.Index] = '\u25a0' return string(buffer) } else { var buffer []byte = bytes.Repeat([]byte(" "), 16) buffer[w.Index] = '\xfe' return string(buffer) } } eanimate.Text = eanimate.UpdateF() w.ElapsedPanel.Lines = append(w.ElapsedPanel.Lines, eanimate) w.RemainingPanel = Panel{Width: 16, BorderColor: color, Style: SINGLE} w.RemainingPanel.Lines = append(w.RemainingPanel.Lines, Line{Text: " GAME "}) w.RemainingPanel.Lines = append(w.RemainingPanel.Lines, Line{Text: " TIME REMAINING "}) var rhour Line = Line{} rhour.UpdateF = func() string { var hours int = int(w.Remaining.Hours()) return fmt.Sprintf(" %02d HRS ", hours%100) } rhour.Text = rhour.UpdateF() w.RemainingPanel.Lines = append(w.RemainingPanel.Lines, rhour) var rminsec Line = Line{} rminsec.UpdateF = func() string { var mins int = int(w.Remaining.Minutes()) % 60 var secs int = int(w.Remaining.Seconds()) % 60 return fmt.Sprintf(" %02d MIN %02d SEC ", mins, secs) } rminsec.Text = rminsec.UpdateF() w.RemainingPanel.Lines = append(w.RemainingPanel.Lines, rminsec) var ranimate Line = Line{} ranimate.UpdateF = func() string { // Left to Right if Unicode { var buffer []rune = []rune(strings.Repeat(" ", 16)) buffer[15-w.Index] = '\u25a0' return string(buffer) } else { var buffer []byte = bytes.Repeat([]byte(" "), 16) buffer[15-w.Index] = '\xfe' return string(buffer) } } ranimate.Text = ranimate.UpdateF() w.RemainingPanel.Lines = append(w.RemainingPanel.Lines, ranimate) } func (w *WOPR) Inc() { w.Index++ if w.Index == 16 { w.Remaining = time.Duration(w.Remaining.Seconds()-1) * time.Second w.Elapsed = time.Duration(w.Elapsed.Seconds()+1) * time.Second w.Index = 0 } } func (w *WOPR) Animate(d *Door) { w.Ticker = time.NewTicker(time.Microsecond * time.Duration(62500)) go func(d *Door) { var output string for range w.Ticker.C { w.ElapsedPanel.Update() w.RemainingPanel.Update() output = SavePos + w.ElapsedPanel.Output() + w.RemainingPanel.Output() + RestorePos if !d.Disconnect() { d.Write(output) } else { w.Ticker.Stop() return } w.Inc() } }(d) } func (w *WOPR) Stop() { w.Ticker.Stop() }