class UrwidVisualisation(threading.Thread): """ main visualisation class which runs in its own thread and and is based on the python package urwid """ def __init__(self, game): """ UrwidVisualisation constructor with all initial parametrisation """ threading.Thread.__init__(self) self.game = game self.newGame = None self.gameChanged = False self.statisticBeastName = None self.psychedelicMode = False self.flash = False self.logEntrys = 0 self.running = False self.beastAnalytics = self.game.beastAnalytics #adding a specific handler to the logger so all modules can log to urwid self.handler = UrwidLoggingHandler(self) self.handler.setLevel(logging.INFO) logging.getLogger('beast-arena-logging').addHandler(self.handler) self.palette = [ ('body', '', '', '', '#8f0', '#000'), ('header', '', '', '', '#f00', '#000'), ('frameHeader', '', '', '', '#000', '#f00'), ('textContent', '', '', '', '#8f0', '#000'), ('innerBorder', '', '', '', '', 'g31'), ('outerBorder', '', '', '', '#0d0', '#8f0'), ('innerBg', '', '', '', '#8f0', '#000'), ] self.rainbow_table = ['#00f', '#06f', '#08f', '#0af', '#0df', '#0ff', '#0fd', '#0fa', '#0f8', \ '#0f6', '#0f0', '#6d0', '#8d0', '#ad0', '#dd0', '#fd0', '#fa0', '#f80', \ '#f60', '#f00', '#f06', '#f08', '#f0a', '#f0d', '#f0f', '#d0f', '#a0f', '#80f', '#60f'] self.palette = self.palette blank = urwid.Divider() #frame header box creation self.frameHeader = urwid.AttrMap(urwid.Text('Welcome to beast-arena - type the name of a beast to view its statistics!', 'center'), 'frameHeader') #headline box creation self.headline = urwid.Padding(urwid.BigText("beast-arena\n", urwid.font.HalfBlock7x7Font(),), 'center', width='clip') self.headline = self.getOutlinedObject(self.headline, 'innerBorder', 'header', 2) #worldmap box creation self.worldString = 'loading...' self.worldText = urwid.Text(self.worldString, 'center') self.world = urwid.AttrMap(self.worldText, 'innerBg') #ranking creation self.rankingText = urwid.Text("Ranking:") self.rankingBorder = self.getOutlinedObject(self.rankingText, 'innerBorder', 'textContent', 2) #statistic box generation self.statisticText = urwid.Text("Type valid beast name for individual analytics!") self.statisticBorder = self.getOutlinedObject(self.statisticText, 'innerBorder', 'textContent', 2) #logging box creation self.loggingTextBuffer = '' self.loggingText = urwid.Text(self.loggingTextBuffer, 'left') self.loggingList = urwid.ListBox([self.loggingText]) self.logging = urwid.Pile([ blank, urwid.AttrMap(blank, 'frameHeader'), urwid.AttrMap(urwid.Padding(urwid.Text("Logging:"), left=2), 'textContent'), urwid.Padding(urwid.BoxAdapter(self.loggingList, 10), left=2, right=2) ]) # self.logging = self.getOutlinedObject(self.logging, 'innerBorder', 'textContent') #main area creation self.mainArea = urwid.AttrMap(urwid.Columns([ ('fixed', 40, self.statisticBorder), self.world, ('fixed', 40, self.rankingBorder) ]), 'innerBg') self.listContent = [ blank, self.headline, blank, self.mainArea, urwid.AttrMap(blank, 'innerBg'), self.logging, # urwid.AttrMap(blank,'outerBorder') ] self.content = urwid.Pile(self.listContent) self.fill = urwid.Filler(self.content, 'middle') self.map = urwid.AttrMap(self.fill, 'body') frame = urwid.Frame(self.map, header=self.frameHeader) def inputHandler(key): """ handles all user input """ if str(key) is not "up" and str(key) is not "down": if str(key) is " ": if not self.psychedelicMode: self.psychedelicMode = True return elif not self.flash and self.psychedelicMode: self.flash = True return else: self.psychedelicMode = False self.flash = False return if self.beastAnalytics.analyticBeastMap.has_key(str(key)): self.statisticBeastName = str(key) else: self.statisticBeastName = None self.statisticText.set_text("invalid beastname! choose valid beast") if str(key) == "esc": raise KeyboardInterrupt self.loop = urwid.MainLoop(frame, self.palette, unhandled_input=inputHandler) self.loop.screen.set_terminal_properties(colors=256) #psychedelic variables self.flashSwitchState = False self.colorOffset = 0 def getOffsetColor (self, offset): """ for internal use only (psychedelic mode) """ tmp = self.colorOffset + offset while tmp > len(self.rainbow_table) - 1: tmp -= len(self.rainbow_table) return self.rainbow_table[tmp] def getOutlinedObject(self, obj, borderStyle, innerStyle, padding): """ used to generate specific borders around given urwid objects """ return urwid.Pile([urwid.AttrMap(urwid.Divider(), borderStyle), urwid.AttrWrap(urwid.Padding(urwid.AttrWrap(urwid.AttrMap(urwid.Padding(obj, \ left=padding, right=padding), innerStyle), innerStyle), left=padding, right=padding), borderStyle), urwid.AttrMap(urwid.Divider(), borderStyle) ]) def updateWorld(self): """ updates the world. is to be called exclusively from "run" """ self.worldString = '\n' for j in range(self.game.worldMap.height): for i in range(self.game.worldMap.height): self.worldString += self.game.worldMap.world[j, i] + ' ' self.worldString += '\n' self.worldText.set_text(self.worldString) def changeGame(self, game): """ signals run() to react to changed game to visualize """ self.newGame = game self.gameChanged = True self.log('game changed') def run(self): """ main urwid loop to update content of all boxes gets called by gui.start() in Game """ time.sleep(0.1) self.running=True while self.running: if self.gameChanged: #reset variables. used to switch game: self.game = self.newGame self.newGame = None self.gameChanged = False self.statisticBeastName = None self.logEntrys = 0 self.loggingTextBuffer = '' self.beastAnalytics = self.game.beastAnalytics if not self.game.gameStarted: self.log("Waiting for Game to start...") while not self.game.gameStarted and self.running: if self.gameChanged: break time.sleep(0.05) while self.game.gameStarted and not self.gameChanged and self.running: self.updateWorld() self.rankingText.set_text(self.game.getRankingList()) if self.statisticBeastName is not None: self.statisticText.set_text('\n' + self.beastAnalytics.getStatistic(self.statisticBeastName) + '\n') else: self.statisticText.set_text('\ntype valid beast name to view analytics!\n') self.loggingText.set_text(self.loggingTextBuffer) # psychocolorswitch if self.psychedelicMode and self.running: if self.flash: if self.flashSwitchState: self.loop.screen.register_palette([ ('body', '', '', '', '#fff', '#fff'), ('header', '', '', '', '#fff', '#fff'), ('frameHeader', '', '', '', '#fff', '#fff'), ('textContent', '', '', '', '#fff', '#fff'), ('innerBorder', '', '', '', '', '#fff'), ('outerBorder', '', '', '', '', '#fff'), ('innerBg', '', '', '', '#fff', '#fff'), ] ) self.flashSwitchState = not(self.flashSwitchState) self.loop.draw_screen() time.sleep(0.05) self.loop.screen.register_palette([ ('body', '', '', '', self.getOffsetColor(6), self.getOffsetColor(0)), ('header', '', '', '', self.getOffsetColor(12), self.getOffsetColor(18)), ('frameHeader', '', '', '', self.getOffsetColor(28), self.getOffsetColor(5)), ('textContent', '', '', '', self.getOffsetColor(20), self.getOffsetColor(15)), ('innerBorder', '', '', '', '', self.getOffsetColor(20)), ('outerBorder', '', '', '', '', self.getOffsetColor(10)), ('innerBg', '', '', '', self.getOffsetColor(9), self.getOffsetColor(25)), ] ) if (self.colorOffset + 1) > len(self.rainbow_table): self.colorOffset = 0 else: self.colorOffset += 1 if not self.psychedelicMode and self.running: self.loop.screen.register_palette(self.palette) if self.running: self.loop.draw_screen() time.sleep(0.1) def runLoop(self): """ main urwid loop (does not check updated content! only redraws screen on keystrokes or via manually called drawscreen() ) """ self.loop.run() def log(self, string): """ method for logging module to print to urwid TUI console """ self.logEntrys += 1 self.loggingTextBuffer = string + "\n" + self.loggingTextBuffer def stop(self): """ stops urwid-thread run() by setting running flag stops game-thread """ # self.log.warning('urwidVisualisatoin: Stop() called ') self.running = False
def __init__(self, game): """ UrwidVisualisation constructor with all initial parametrisation """ threading.Thread.__init__(self) self.game = game self.newGame = None self.gameChanged = False self.statisticBeastName = None self.psychedelicMode = False self.flash = False self.logEntrys = 0 self.running = False self.beastAnalytics = self.game.beastAnalytics #adding a specific handler to the logger so all modules can log to urwid self.handler = UrwidLoggingHandler(self) self.handler.setLevel(logging.INFO) logging.getLogger('beast-arena-logging').addHandler(self.handler) self.palette = [ ('body', '', '', '', '#8f0', '#000'), ('header', '', '', '', '#f00', '#000'), ('frameHeader', '', '', '', '#000', '#f00'), ('textContent', '', '', '', '#8f0', '#000'), ('innerBorder', '', '', '', '', 'g31'), ('outerBorder', '', '', '', '#0d0', '#8f0'), ('innerBg', '', '', '', '#8f0', '#000'), ] self.rainbow_table = ['#00f', '#06f', '#08f', '#0af', '#0df', '#0ff', '#0fd', '#0fa', '#0f8', \ '#0f6', '#0f0', '#6d0', '#8d0', '#ad0', '#dd0', '#fd0', '#fa0', '#f80', \ '#f60', '#f00', '#f06', '#f08', '#f0a', '#f0d', '#f0f', '#d0f', '#a0f', '#80f', '#60f'] self.palette = self.palette blank = urwid.Divider() #frame header box creation self.frameHeader = urwid.AttrMap(urwid.Text('Welcome to beast-arena - type the name of a beast to view its statistics!', 'center'), 'frameHeader') #headline box creation self.headline = urwid.Padding(urwid.BigText("beast-arena\n", urwid.font.HalfBlock7x7Font(),), 'center', width='clip') self.headline = self.getOutlinedObject(self.headline, 'innerBorder', 'header', 2) #worldmap box creation self.worldString = 'loading...' self.worldText = urwid.Text(self.worldString, 'center') self.world = urwid.AttrMap(self.worldText, 'innerBg') #ranking creation self.rankingText = urwid.Text("Ranking:") self.rankingBorder = self.getOutlinedObject(self.rankingText, 'innerBorder', 'textContent', 2) #statistic box generation self.statisticText = urwid.Text("Type valid beast name for individual analytics!") self.statisticBorder = self.getOutlinedObject(self.statisticText, 'innerBorder', 'textContent', 2) #logging box creation self.loggingTextBuffer = '' self.loggingText = urwid.Text(self.loggingTextBuffer, 'left') self.loggingList = urwid.ListBox([self.loggingText]) self.logging = urwid.Pile([ blank, urwid.AttrMap(blank, 'frameHeader'), urwid.AttrMap(urwid.Padding(urwid.Text("Logging:"), left=2), 'textContent'), urwid.Padding(urwid.BoxAdapter(self.loggingList, 10), left=2, right=2) ]) # self.logging = self.getOutlinedObject(self.logging, 'innerBorder', 'textContent') #main area creation self.mainArea = urwid.AttrMap(urwid.Columns([ ('fixed', 40, self.statisticBorder), self.world, ('fixed', 40, self.rankingBorder) ]), 'innerBg') self.listContent = [ blank, self.headline, blank, self.mainArea, urwid.AttrMap(blank, 'innerBg'), self.logging, # urwid.AttrMap(blank,'outerBorder') ] self.content = urwid.Pile(self.listContent) self.fill = urwid.Filler(self.content, 'middle') self.map = urwid.AttrMap(self.fill, 'body') frame = urwid.Frame(self.map, header=self.frameHeader) def inputHandler(key): """ handles all user input """ if str(key) is not "up" and str(key) is not "down": if str(key) is " ": if not self.psychedelicMode: self.psychedelicMode = True return elif not self.flash and self.psychedelicMode: self.flash = True return else: self.psychedelicMode = False self.flash = False return if self.beastAnalytics.analyticBeastMap.has_key(str(key)): self.statisticBeastName = str(key) else: self.statisticBeastName = None self.statisticText.set_text("invalid beastname! choose valid beast") if str(key) == "esc": raise KeyboardInterrupt self.loop = urwid.MainLoop(frame, self.palette, unhandled_input=inputHandler) self.loop.screen.set_terminal_properties(colors=256) #psychedelic variables self.flashSwitchState = False self.colorOffset = 0