| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -5,7 +5,6 @@ import (
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						"fmt" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						"io" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						"io/ioutil" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						"net/http" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						"os" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						"os/exec" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						"strconv" | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -21,13 +20,12 @@ import (
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					type Config struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						NethackLauncher struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							Loglevel        string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							ServerDisplay   string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							NethackVersion  string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							HackDir         string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							NhdatLocation   string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							ReclistLocation string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							BootstrapDelay  time.Duration | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							Loglevel       string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							ServerDisplay  string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							NethackVersion string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							HackDir        string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							NhdatLocation  string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							BootstrapDelay time.Duration | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						Redis struct { | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -111,13 +109,6 @@ func checkFiles() {
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							fmt.Printf("%s\n", err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							os.Exit(1) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// make sure reclist bin exists
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if _, err := os.Stat(config.NethackLauncher.ReclistLocation); os.IsNotExist(err) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							glogger.Info.Printf("reclist binary not found in %s\n", config.NethackLauncher.ReclistLocation) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							fmt.Printf("%s\n", err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							os.Exit(1) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// TODO check other needed files
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					func clearScreen() { | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -135,6 +126,7 @@ func printWelcomeScreen(redisClient *redis.Client) string {
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" l) Login") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" r) Register new user") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" w) Watch games in progress") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" h) View highscores") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" q) Quit") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println("") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						fmt.Printf(">> ") | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -161,6 +153,9 @@ func printWelcomeScreen(redisClient *redis.Client) string {
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							case "w": | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								clearScreen() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								printProgressScreen(redisClient, "") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							case "h": | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								clearScreen() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								printHighScores(redisClient, "") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							case "q": | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								clearScreen() | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -178,6 +173,7 @@ func printUserScreen(redisClient *redis.Client, username string) string {
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println("") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" l) Logout") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" w) Watch games in progress") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" h) View highscores") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" e) Edit config") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						fmt.Printf(" p) Play NetHack %s\n", config.NethackLauncher.NethackVersion) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" q) Quit") | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -212,6 +208,9 @@ func printUserScreen(redisClient *redis.Client, username string) string {
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							case "w": | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								clearScreen() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								printProgressScreen(redisClient, username) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							case "h": | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								clearScreen() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								printHighScores(redisClient, username) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							case "p": | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								wg.Add(1) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								currentTime := time.Now().UTC() | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -481,7 +480,6 @@ func startWatcher(username, timestamp string, redisClient *redis.Client) chan st
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								case <-ch: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									return | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								default: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									// SADD
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									redisClient.Expire(fmt.Sprintf("inprogress:%s", username), 10*time.Second) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									time.Sleep(8 * time.Second) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -536,16 +534,42 @@ func janitor(redisClient *redis.Client) {
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					func gethighscore(w http.ResponseWriter, r *http.Request) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// run script
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						output, err := exec.Command(config.NethackLauncher.ReclistLocation, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							"-f", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							fmt.Sprintf("%s/record", config.NethackLauncher.HackDir)).CombinedOutput() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							fmt.Printf("%s\n", err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					func printHighScores(redisClient *redis.Client, username string) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						clearScreen() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						fmt.Fprintf(w, "%s\n", output) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						nh := exec.Command("nethack", "-d", config.NethackLauncher.HackDir, "-s") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						nh.Stdout = os.Stdout | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						nh.Stdin = os.Stdin | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						nh.Stderr = os.Stderr | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						nh.Run() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println("") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println(" Press enter to return to menu") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						println("") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						fmt.Printf(">> ") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// allow user back to home screen
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// disable input buffering
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// do not display entered characters on the screen
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						exec.Command("stty", "-F", "/dev/tty", "-echo").Run() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						var b []byte = make([]byte, 1) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						for { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							os.Stdin.Read(b) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							// check if user is trying to navigate
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if string(b) == "\n" { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								clearScreen() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if username == "" { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									printWelcomeScreen(redisClient) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									printUserScreen(redisClient, username) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					func checkDir(dirName string) (bool, error) { | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				 | 
				
					
 
					 |