testdoor.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "log"
  6. "os"
  7. "red-green/door"
  8. "runtime/debug"
  9. "runtime/pprof"
  10. "time"
  11. // "net/http"
  12. // _ "net/http/pprof"
  13. )
  14. const ENABLE_PROFILER bool = false
  15. // "runtime/pprof"
  16. // Max X value we can use before hitting MemStats panel.
  17. var MaxX int = 0
  18. func press_keys(d *door.Door) {
  19. d.WriteA(door.Reset, door.CRNL, "Press some keys... <ENTER> to exit.")
  20. var r rune
  21. var ex door.Extended
  22. var err error
  23. for (r != 0x0d) && (err == nil) {
  24. r, ex, err = d.WaitKey(door.Inactivity)
  25. if ex == door.MOUSE {
  26. m, ok := d.GetMouse()
  27. if ok {
  28. // var m door.MouseInfo = door.Mouse
  29. d.WriteA(fmt.Sprintf("M %d (%d,%d) ", m.Button, m.X, m.Y))
  30. }
  31. } else {
  32. if ex == door.NOP {
  33. d.WriteA(fmt.Sprintf("%d (%x) ", r, r))
  34. } else {
  35. d.WriteA(fmt.Sprintf("<%s> ", ex.String()))
  36. }
  37. }
  38. }
  39. d.WriteA(door.Reset, door.CRNL)
  40. }
  41. func press_key_or_mouse(d *door.Door) error {
  42. var err error
  43. var ex door.Extended
  44. for {
  45. _, ex, err = d.WaitKey(door.Inactivity)
  46. if err != nil {
  47. return err
  48. }
  49. if ex == door.MOUSE {
  50. m, ok := d.GetMouse()
  51. if ok {
  52. if m.Button == 1 {
  53. break
  54. }
  55. }
  56. } else {
  57. break
  58. }
  59. }
  60. return nil
  61. }
  62. func press_a_key(d *door.Door) error {
  63. var err error
  64. // var ex door.Extended
  65. d.WriteA(door.Reset, door.CRNL, "Press a key, or LEFT mouse click to continue...")
  66. /*
  67. for {
  68. _, ex, err = d.WaitKey(door.Inactivity)
  69. if ex == door.MOUSE {
  70. m, ok := d.GetMouse()
  71. if ok {
  72. if m.Button == 1 {
  73. break
  74. }
  75. }
  76. } else {
  77. break
  78. }
  79. }
  80. */
  81. err = press_key_or_mouse(d)
  82. d.WriteA(door.CRNL)
  83. return err
  84. }
  85. func main() {
  86. var message string
  87. if ENABLE_PROFILER {
  88. fp1, err1 := os.Create("cpu.pro")
  89. if err1 != nil {
  90. log.Fatal(err1)
  91. }
  92. pprof.StartCPUProfile(fp1)
  93. defer pprof.StopCPUProfile()
  94. defer func() {
  95. fp2, err2 := os.Create("memory.pro")
  96. if err2 != nil {
  97. log.Fatal(err2)
  98. }
  99. pprof.WriteHeapProfile(fp2)
  100. }()
  101. }
  102. /*
  103. go func() {
  104. http.ListenAndServe(":6060", nil)
  105. }()
  106. */
  107. var d door.Door = door.Door{}
  108. d.Init("testdoor")
  109. defer func() {
  110. if err := recover(); err != nil {
  111. // This displays stack trace stderr
  112. debug.PrintStack()
  113. fmt.Println("ERROR:", err)
  114. log.Println("FAILURE:", err)
  115. // Display error to user
  116. d.WriteA(fmt.Sprintf(door.Reset+door.CRNL+"Exception: %v"+door.CRNL, err))
  117. }
  118. }()
  119. defer d.Close()
  120. // Updaters work best when the screen doesn't scroll, so start
  121. // us off at the very top.
  122. d.WriteA(door.Clrscr)
  123. // Start spinrite effects
  124. var ticker *time.Ticker = time.NewTicker(time.Millisecond * time.Duration(100)) // 100
  125. var spin door.SpinRiteMsg = door.SpinRiteMsgInit(15, 5,
  126. door.ColorText("RED ON GREEN"),
  127. []string{"RED", "GREEN", "SOFTWARE"})
  128. /*
  129. var spin2 door.SpinRite = door.SpinRiteInit(13, 5,
  130. door.ColorText("BRI CYA ON BLUE"))
  131. */
  132. // Add in the GoRoutine Status panel
  133. MaxX = door.Width - 20
  134. var goPanel door.Panel = door.Panel{X: door.Width - 19,
  135. Y: 3,
  136. Width: 16,
  137. Style: door.DOUBLE,
  138. Title: "] GoRuntime [",
  139. BorderColor: door.ColorText("BOLD YELL"),
  140. }
  141. const DisplayGoRoutines bool = true
  142. if DisplayGoRoutines {
  143. goLineUpdater := func(u *bytes.Buffer) {
  144. u.Reset()
  145. u.Write(GoRoutinesStatus())
  146. // log.Println(status)
  147. }
  148. var goLine *door.Line = &door.Line{
  149. Text: &bytes.Buffer{},
  150. UpdateF: goLineUpdater,
  151. Width: goPanel.Width,
  152. DefaultColor: door.ColorText("CYAN"),
  153. }
  154. // goLine.Update() // Force Update
  155. goPanel.Lines = append(goPanel.Lines, goLine)
  156. }
  157. // Display Legend on GoRuntime panel
  158. const DisplayGoRoutineLegend bool = false
  159. // Display Memory
  160. const DisplayMemory bool = true
  161. var MemoryStats map[string]*bytes.Buffer = make(map[string]*bytes.Buffer)
  162. if DisplayGoRoutineLegend {
  163. // Line for legend.
  164. goPanel.Lines = append(goPanel.Lines, &door.Line{Width: goPanel.Width})
  165. }
  166. if DisplayMemory {
  167. memColor := door.ColorText("BRI BLUE")
  168. memoryUpdater := func(u *bytes.Buffer) {
  169. if u == nil {
  170. u = &bytes.Buffer{}
  171. }
  172. u.Reset()
  173. Memory(&MemoryStats)
  174. fmt.Fprintf(u, "%-8s%8s", "Sys", MemoryStats["Sys"].Bytes())
  175. }
  176. // memoryUpdater(&bytes.Buffer{})
  177. goPanel.Lines = append(goPanel.Lines, &door.Line{UpdateF: memoryUpdater,
  178. Width: goPanel.Width,
  179. DefaultColor: memColor})
  180. heapUpdater := func(u *bytes.Buffer) {
  181. if u == nil {
  182. u = &bytes.Buffer{}
  183. }
  184. u.Reset()
  185. fmt.Fprintf(u, "%-8s%8s", "HeapSys", MemoryStats["Heap"].Bytes())
  186. }
  187. goPanel.Lines = append(goPanel.Lines, &door.Line{UpdateF: heapUpdater,
  188. Width: goPanel.Width,
  189. DefaultColor: memColor})
  190. stackUpdater := func(u *bytes.Buffer) {
  191. u.Reset()
  192. fmt.Fprintf(u, "%-8s%8s", "StackSys", MemoryStats["StackSys"].Bytes())
  193. }
  194. goPanel.Lines = append(goPanel.Lines, &door.Line{UpdateF: stackUpdater,
  195. Width: goPanel.Width,
  196. DefaultColor: memColor})
  197. gcUpdater := func(u *bytes.Buffer) {
  198. u.Reset()
  199. fmt.Fprintf(u, "%-8s%8s", "NumGC", MemoryStats["NumGC"].Bytes())
  200. }
  201. goPanel.Lines = append(goPanel.Lines, &door.Line{UpdateF: gcUpdater,
  202. Width: goPanel.Width,
  203. DefaultColor: memColor})
  204. }
  205. var lIndex int = 0
  206. var legendCount int = 0
  207. const legendUpdate = 20
  208. go func() {
  209. defer func() {
  210. r := recover()
  211. if r != nil {
  212. log.Printf("** FAIL: %s, %#v\n", r, r)
  213. }
  214. }()
  215. // var output string
  216. var legend []string = []string{
  217. "R=run r=Runnable",
  218. "S=Select s=Syscall",
  219. "Chan <read >write",
  220. "Z=Sleep P=Preempt",
  221. "I=Idle D=Dead",
  222. "W=Wait C=Copystk",
  223. }
  224. if DisplayGoRoutineLegend {
  225. goPanel.Lines[1].Text = bytes.NewBuffer([]byte(legend[0]))
  226. }
  227. for range ticker.C {
  228. // output = door.SavePos + door.Goto(door.Width-16, 1) + spin.Output() +
  229. // door.Goto(door.Width-15, 3) + spin2.Output() + door.RestorePos
  230. if DisplayGoRoutineLegend {
  231. legendCount++
  232. if legendCount >= legendUpdate {
  233. legendCount = 0
  234. lIndex++
  235. if lIndex == len(legend) {
  236. lIndex = 0
  237. }
  238. goPanel.Lines[1].Text = bytes.NewBuffer([]byte(legend[lIndex]))
  239. }
  240. }
  241. if goPanel.X == 0 {
  242. goPanel.X = door.Width - 40
  243. }
  244. goPanel.Update()
  245. //output = door.Goto(door.Width-16, 1) + spin.Output() + goPanel.Output()
  246. /*
  247. +
  248. door.Goto(door.Width-15, 3) + spin2.Output()
  249. */
  250. if !d.Disconnect() {
  251. // d.Update(output)
  252. d.WriteA(door.SavePos, door.Goto(door.Width-16, 1), spin.Output(), goPanel.Output(), door.RestorePos)
  253. } else {
  254. log.Println("Ticker.Stop: Disconnected!")
  255. ticker.Stop()
  256. return
  257. }
  258. }
  259. log.Println("range Ticker.C stopped.")
  260. }()
  261. var wopr door.WOPR
  262. wopr.Init(d.StartTime, d.TimeOut, []byte{})
  263. wopr.ElapsedPanel.X = door.Width - 19
  264. wopr.ElapsedPanel.Y = door.Height - 15
  265. wopr.RemainingPanel.X = door.Width - 19
  266. wopr.RemainingPanel.Y = door.Height - 8
  267. wopr.Animate(&d)
  268. // bold := door.Color(1, 37, 40)
  269. var bolder = door.ColorText("BOLD YEL ON BLUE")
  270. d.WriteA("Welcome to ", bolder, "go door go TestDoor.", door.Reset, door.CRNL, "...", door.CRNL)
  271. d.EnableMouse(door.Normal)
  272. press_a_key(&d)
  273. d.WriteA(door.CRNL)
  274. var b []string
  275. if door.CP437 {
  276. b = door.AlertBox("Alert: go \xfb is in use!", 1)
  277. } else {
  278. b = door.AlertBox("Alert: go \u221a is in use!", 1)
  279. }
  280. warningColor := door.ColorText("BRI WHI ON GREEN")
  281. for _, line := range b {
  282. // Prevent color bleeding.
  283. d.WriteA(warningColor, line, door.Reset, door.CRNL)
  284. }
  285. d.WriteA(door.Reset, door.CRNL)
  286. var left time.Duration = d.TimeLeft()
  287. message = fmt.Sprintf("You have %0.2f minutes / %0.2f seconds remaining..."+door.CRNL, left.Minutes(), left.Seconds())
  288. d.WriteA(message)
  289. press_a_key(&d)
  290. var mainmenu door.Menu = MainMenu()
  291. var choice int
  292. for choice >= 0 {
  293. d.WriteA(door.Clrscr, door.HideCursor)
  294. choice = mainmenu.Choose(&d)
  295. d.WriteA(door.ShowCursor)
  296. if choice < 0 {
  297. break
  298. }
  299. option := mainmenu.GetOption(choice)
  300. wopr.Stop()
  301. // Clear WOPR panels.
  302. d.WriteA(door.Reset, wopr.Clear())
  303. r, b := mainmenu.Panel.RightBottomPos()
  304. d.WriteA(door.Goto(r, b))
  305. // fmt.Printf("Choice: %d, Option: %c\n", choice, option)
  306. switch option {
  307. case 'A':
  308. display_ansi(&d)
  309. press_a_key(&d)
  310. case 'D':
  311. display_information(&d)
  312. press_a_key(&d)
  313. case 'F':
  314. font_demo(&d)
  315. press_a_key(&d)
  316. case 'I':
  317. d.WriteA(door.Reset, door.CRNL, door.CRNL)
  318. input_demo(&d)
  319. press_a_key(&d)
  320. case 'M':
  321. // Why is this so far down on the screen? (Scrolls)
  322. d.WriteA(door.Reset, door.CRNL, "TO DO: Provide menu of options to select from...", door.CRNL)
  323. press_a_key(&d)
  324. case 'P':
  325. progress_bars(&d)
  326. press_a_key(&d)
  327. case 'S':
  328. panel_demo(&d)
  329. press_a_key(&d)
  330. case 'T':
  331. about_test_door(&d)
  332. press_a_key(&d)
  333. case 'W':
  334. width_demo(&d)
  335. case 'Q':
  336. // This is also far down on the screen ...
  337. choice = -1
  338. case 'C': // Disabled
  339. var a, z int
  340. z = 0
  341. a = 10 / z
  342. z = a
  343. _ = a
  344. _ = z
  345. }
  346. wopr.Animate(&d)
  347. }
  348. // d.Write("\x1b[?1000l") // disable mouse
  349. // d.Write("\x1b[?1002l")
  350. d.DisableMouse()
  351. d.WriteA(door.Reset, door.CRNL)
  352. if d.Config.BBSID != "" {
  353. message = fmt.Sprintf("Returning to the %s BBS..."+door.CRNL, d.Config.BBSID)
  354. } else {
  355. message = "Returning to the BBS..." + door.CRNL
  356. }
  357. d.WriteA(message)
  358. d.WaitKey(time.Second)
  359. left = d.TimeLeft()
  360. ticker.Stop()
  361. message = fmt.Sprintf("You had %0.2f minutes remaining!"+door.CRNL, left.Minutes())
  362. d.WriteA(message)
  363. left = d.TimeUsed()
  364. d.WriteA(fmt.Sprintf("You used %0.2f seconds / %0.2f minutes."+door.CRNL, left.Seconds(), left.Minutes()))
  365. fmt.Println("Ending testdoor.go")
  366. }