def run(self, *args, **kwargs): """ The main process for this level Please overwrite the following methods and not this one: * prepareGame and * finishGame besides * GameQueue.run as these 3 provide the necessary game-functionalities and not this "run" method """ logger.debug('level started') status = models.getCleanGameState(self.user_id) status.msg = (_("Level is running")) status.level_progress = 0 models.setGameState(self.user_id, status) if not userOk(self.user_id): status.msg = _("You have to login in order to play this level...") models.setGameState(self.user_id, status) return queue = self.GameQueue() stop_event = Event() hardware = self.prepareGame(status, queue) language = translation.get_language() #print(str(language)) qThread = startThread( queue.run, args=( stop_event, self, hardware, language, ), name="queue_for_level") #needed to loop through the messages stop_event.wait( ) #wait until queues stops processing or level gets terminated stop_event.clear() status = getGameState(self.user_id) self.finishGame(status, hardware) status = getGameState(self.user_id) logger.info('Level State= ' + str(status)) logger.debug('Level ended') queue.close() abortThread(qThread, 1, "aborting message-Queue") glob = tlu_globals.globMgr.tlu_glob() glob.startClock() #restart clock in case it had been stopped return
def msg(self, gameProcess, msg, progress, key=-1, error=False): status = models.getGameState(gameProcess.user_id) status.msg = msg if key > -1: status.msg += str(key) if error: status.result = Level.DIDNOTFINISH status.level_progress = progress models.setGameState(gameProcess.user_id, status)
def set_abortmsg(self, user_id): """ Internal service function :param user_id: The user in question """ status = models.getGameState(user_id) status.msg = _("Game aborted :(") status.result = Level.ABORT status.level_progress = 100 models.setGameState(user_id, status)
def run(self, stop_event, gameProcess, hardware, language): # @UnusedVariable """ Main loop for Level2 Main :param stop_event: event coming from main-loop, once set, level will terminate :param gameProcess: the main process running the level. Needed to check for termination requests and the user_id :param hardware: list of started threads """ translation.activate(language) self.clearQueue() #cleanup before we start keymatrix = {} thread = threading.currentThread() while True: if len(keymatrix) == 4: stop_event.set() break (queueobject, breakIndicator) = self.getQueueObject(stop_event, gameProcess, thread) if breakIndicator: break if queueobject == None: continue self.queue.task_done() #release object from queue if self.checkAbort(stop_event, gameProcess, thread, queueobject): break elif queueobject.msg_num == self.MSG_KEYPRESSED: glob = tlu_globals.globMgr.tlu_glob() glob.lcdMessagebyline( _("Level: ") + "02", str(_("Cursor=")) + tlu_cursor.cursorname(None, queueobject.msg_info)) keymatrix[queueobject.msg_info] = 1 symbolname = 'space' if queueobject.msg_info == 100: symbolname = 'arrow_up' elif queueobject.msg_info == 200: symbolname = 'arrow_right' elif queueobject.msg_info == 300: symbolname = 'arrow_down' elif queueobject.msg_info == 400: symbolname = 'arrow_left' glob.matrixShow_symbol(symbolname) status = models.getGameState(gameProcess.user_id) status.msg = str(_("You have just pressed cursor - ") ) + tlu_cursor.cursorname( None, queueobject.msg_info) status.level_progress = int(len(keymatrix) / 4 * 100) models.setGameState(gameProcess.user_id, status) time.sleep(0.5) #wait for messages to settle elif queueobject.msg_num == self.MSG_KEYRELEASED: pass
def checkLevel(request, level_id): """ Check that the provided level is within the allowed range. If not raises an OutOfRangeError :param request: HTTP-request :param level_id: level-number (picked from url) """ if level_id == 1: #startup level is ever ok return user = request.user try: tlu_globals.init() tlu_hardware_global.init() game = user.game except: return if game.current_level == None: if (level_id > 1): status = getGameState(user.id) status.msg = _( "You just started from the beginning, so level has to be one, please restart the game!" ) setGameState(user.id, status) raise OutOfRangeError else: return if (level_id > game.current_level.levelnum + 1) or ( level_id < game.current_level.levelnum) or game.completed(level_id): status = getGameState(user.id) status.msg = _( "The requested level is not in line with our expectations, please restart the game!" ) setGameState(user.id, status) raise OutOfRangeError
def test_status(self): """ Test the status object """ logging.debug('Test test_status started') game = self.getGame('test_status') gamestate = getCleanGameState(game.user.id) self.assertEqual(gamestate.level_progress, 0, "The initial Progress has to be 0") gamestate.msg = "HALLO" gamestate.level_progress = 55 setGameState(game.user.id, gamestate) gamestate = getGameState(game.user.id) self.assertEqual(gamestate.msg, "HALLO", "The messages differ :(") self.assertEqual(gamestate.level_progress, 55, "The Progress has to be 55") logging.debug('Test status ended')
def checkAbort(self, thread, user_id, msg): """ Check if a thread should be aborted. Each thread has now added an attribute "is_aborted", if set the thread should terminate itself :param thread: The thread in question :param user_id: user that is currently active, needed for the gamestated :param msg: Message that will be shown on the web once the task has been aborted """ if getattr(thread, "is_aborted", False): status = models.getGameState(user_id) status.msg = msg status.level_progress = 100 status.result = Level.ABORT models.setGameState(user_id, status) return True return False
def run(self, stop_event, gameProcess, hardware, language): # @UnusedVariable """ Queue loop for level 1 Main :param stop_event: event coming from main-loop, once set, level will terminate :param gameProcess: the main process running the level. Needed to check for termination requests and the user_id :param hardware: list of started threads """ translation.activate(language) self.clearQueue() #cleanup before we start keymatrix = {} thread = threading.currentThread() glob = tlu_globals.globMgr.tlu_glob() while True: if len(keymatrix) == 16: stop_event.set() break (queueobject, breakIndicator) = self.getQueueObject(stop_event, gameProcess, thread) if breakIndicator: break if queueobject == None: continue self.queue.task_done() #release object from queue if self.checkAbort(stop_event, gameProcess, thread, queueobject): break elif queueobject.msg_num == self.MSG_KEYPRESSED: glob.lcdMessagebyline( _("Level: ") + "01", str(_("Key = ")) + str(queueobject.msg_info)) keymatrix[queueobject.msg_info] = 1 status = models.getGameState(gameProcess.user_id) status.msg = str(_("You have just pressed Key #")) + str( queueobject.msg_info) status.level_progress = int(len(keymatrix) / 16 * 100) models.setGameState(gameProcess.user_id, status) elif queueobject.msg_num == self.MSG_KEYRELEASED: pass
def checkAbort(self, stop_event, gameProcess, thread, queueobject): """ Checks the current thread, queue and message object for an indication that we shall abort. Returns True in case we have to abort :param stop_event: the event from the main-level that would be "set" here in case the level ended or terminated :param gameProcess: the main process running the level. Needed to check for termination requests and the user_id :param thread: The thread where the queue is looping in :param queueobject: the message-object that we should check here """ if stop_event.is_set(): logger.debug('Gamequeue aborted') self.set_abortmsg(gameProcess.user_id) return True elif getattr(thread, 'is_aborted', False): logger.debug('Queue-Thread shall be aborted/stopped') self.set_abortmsg(gameProcess.user_id) stop_event.set() return True elif gameProcess.exit.is_set(): logger.debug('Game-Process shall be terminated') self.set_abortmsg(gameProcess.user_id) stop_event.set() return True elif queueobject.msg_num == self.MSG_STOP: logger.debug('Gamequeue stopped via msg') self.set_abortmsg(gameProcess.user_id) stop_event.set() return True elif queueobject.msg_num == self.MSG_TIMEOUT: logger.debug('Timeout raised in queue') status = models.getGameState(gameProcess.user_id) status.msg = _("Timeout reached :(") status.result = Level.TIMEOUT status.level_progress = 100 models.setGameState(gameProcess.user_id, status) stop_event.set() return True return False
def run(self, stop_event, gameProcess, hardware, language): """ Queue loop for level 3 Main :param stop_event: event coming from main-loop, once set, level will terminate :param gameProcess: the main process running the level. Needed to check for termination requests and the user_id :param hardware: list of started threads """ translation.activate(language) self.clearQueue() #cleanup before we start key=-1 numkeys=0 secondstiltimeout=4 thread=threading.currentThread() (timer, kbd,) = hardware # @UnusedVariable glob=tlu_globals.globMgr.tlu_glob() while True: if emulatekey and (numkeys>8): stop_event.set() break elif numkeys >= 20: stop_event.set() break if key == -1: key=randint(1,16) status=models.getGameState(gameProcess.user_id) m=str(_("You have to press Key #")) status.msg=str(numkeys)+": "+m+str(key) status.level_progress=int(numkeys/20*100) models.setGameState(gameProcess.user_id, status) timer.changeSecondsAndRestart(secondstiltimeout) (queueobject,breakIndicator)=self.getQueueObject(stop_event, gameProcess, thread) if breakIndicator: break if queueobject == None: continue self.queue.task_done() #release object from queue if self.checkAbort(stop_event,gameProcess,thread,queueobject): if queueobject.msg_num==tlu_queue.MSG_TIMEOUT: glob.lcdMessagebyline(_("Level: ")+"03", str(_("Timeout"))+" :(") break if queueobject.msg_num == self.MSG_KEYPRESSED: glob.lcdMessagebyline(_("Level: ")+"03", "#"+str(numkeys+1)+": "+str(_("Key="))+str(queueobject.msg_info)+"/"+str(key)) if key != queueobject.msg_info: status=models.getGameState(gameProcess.user_id) status.level_progress=0 status.result=Level.DIDNOTFINISH status.msg="#"+str(queueobject.msg_info)+str(_(" was the wrong key, level terminates!")) models.setGameState(gameProcess.user_id, status) logging.info("Wrong Key:"+str(key)+" instead of:"+str(queueobject.msg_info)) stop_event.set() break else: timer.pause() numkeys += 1 glob.matrixShow_symbol('root') key=-1 #generate next key status=models.getGameState(gameProcess.user_id) status.level_progress=int(numkeys/20*100) models.setGameState(gameProcess.user_id, status) logging.info("Correct key pressed :)") secondstiltimeout=4 if numkeys > 5: secondstiltimeout = 3 if numkeys > 10: secondstiltimeout = 2.5 if numkeys > 15: secondstiltimeout = 2 elif queueobject.msg_num == self.MSG_KEYRELEASED: glob.matrixShow_symbol('space')
def level_update(request): """ Ajax call (via js-component) to retrieve the current status of the level in order to update the frontend returns json formatted data :param request: HTTP-request """ if request.method == 'GET': pagelevel = request.GET['level'] user = request.user try: game = user.game except: data = { 'info': _("The user seems to be unknown, please log in and restart"), 'current_progress': 0, 'overall_progress': 0, 'poll': 0, 'delay_ms': 1000, 'button_text': _("log in"), 'button_url': "/accounts/login/" } return JsonResponse(data) logging.debug("Game update requested: " + str(game)) status = getGameState(user.id) overall_progress = game.getOverallProgress() level = game.current_level current_level_num = 0 if level != None: current_level_num = level.levelnum logger.info("Updating level " + pagelevel + " Game=" + str(game)) button_text = _("Start Level") + " " + str(current_level_num) button_url = '/tlu_joyit_game/start/' + str(current_level_num) info = status.msg if (info == None): info = _("No info available...") running = 0 if game.is_running(): running = 1 button_text = _("Abort Level?") button_url = '/tlu_joyit_game/abort/' + str(current_level_num) else: res = game.result(0.5) logging.debug("Game returned with result " + str(res) + " Game=" + str(game)) if res == Level.PASSED: #finished with success button_text = _("Next Level") button_url = '/tlu_joyit_game/level/' + str(current_level_num + 1) if game.endReached(): button_text = _("Restart?") button_url = '/tlu_joyit_game/restart' elif (res == Level.TIMEOUT) or (res == Level.DIDNOTFINISH): #timeout reached or level ende by an gamer error button_text = _("Retry") button_url = '/tlu_joyit_game/retry/' + str(current_level_num) else: #failure somehow info = str( _("Level failed somehow, please try again, result=")) info += Level.strFromResult(Level(), res) button_text = _("Retry Level?") button_url = '/tlu_joyit_game/retry/' + str(current_level_num) data = { 'info': info, 'current_progress': status.level_progress, 'overall_progress': overall_progress, 'poll': running, 'delay_ms': game.getFrequentUpdatesMs(current_level_num), 'button_text': button_text, 'button_url': button_url } return JsonResponse(data) return HttpResponseNotAllowed(['POST'])