diff --git a/paperio/local_runner/clients.py b/paperio/local_runner/clients.py index 27e6622..34a6026 100644 --- a/paperio/local_runner/clients.py +++ b/paperio/local_runner/clients.py @@ -147,13 +147,41 @@ def send_message(self, t, d): pass -class TcpClient(Client): - EXECUTION_LIMIT = datetime.timedelta(seconds=MAX_EXECUTION_TIME) +class BasicProxyClient(Client): + REQUEST_LIMIT = datetime.timedelta(seconds=REQUEST_MAX_TIME) + TOTAL_LIMIT = datetime.timedelta(seconds=MAX_EXECUTION_TIME) + + def __init__(self): + self.execution_time = datetime.timedelta() + self.started_measure_time = None + + def prepare_message_bytes(self, t, d): + msg = { + 'type': t, + 'params': d, + 'time_left': round((self.TOTAL_LIMIT - self.execution_time).total_seconds() * 1000) + } + return '{}\n'.format(json.dumps(msg)).encode() + + def begin_measure_time(self): + self.started_measure_time = datetime.datetime.now() + + def end_measure_time(self): + request_time = (datetime.datetime.now() - self.started_measure_time) + if request_time > self.REQUEST_LIMIT: + raise Exception('request timeout error') + + self.execution_time += request_time + if self.execution_time > self.TOTAL_LIMIT: + raise Exception('sum timeout error') + + +class TcpClient(BasicProxyClient): def __init__(self, reader, writer): + super(TcpClient, self).__init__() self.reader = reader self.writer = writer - self.execution_time = datetime.timedelta() self.solution_id = None def save_log_to_disk(self, log, path): @@ -178,31 +206,25 @@ async def set_solution_id(self): return bool(self.solution_id) def send_message(self, t, d): - msg = { - 'type': t, - 'params': d, - 'time_left': round((self.EXECUTION_LIMIT-self.execution_time).total_seconds()*1000) - } - msg_bytes = '{}\n'.format(json.dumps(msg)).encode() + msg_bytes = self.prepare_message_bytes(t, d) self.writer.write(msg_bytes) async def get_command(self): try: - before = datetime.datetime.now() + self.begin_measure_time() + # z = await asyncio.wait_for(self.reader.readline(), timeout=REQUEST_MAX_TIME) if not z: raise ConnectionError('Connection closed') - self.execution_time += (datetime.datetime.now() - before) - if self.execution_time > self.EXECUTION_LIMIT: - raise Exception('sum timeout error') + # + self.end_measure_time() except asyncio.TimeoutError: raise asyncio.TimeoutError('read timeout error') + try: - z = json.loads(z.decode()) + return json.loads(z.decode()) except ValueError: - z = {'debug': 'cant pars json'} - - return z + return {'debug': 'cant pars json'} def close(self): self.writer.close() @@ -211,10 +233,13 @@ def get_solution_id(self): return self.solution_id -class FileClient(Client): - def __init__(self, path_to_script, path_to_log=None): +class FileClient(BasicProxyClient): + + def __init__(self, path_to_script, path_to_log=None, check_ai_timeout=False): + super(FileClient, self).__init__() self.process = Popen(path_to_script, stdout=PIPE, stdin=PIPE) self.last_message = None + self.check_ai_timeout = check_ai_timeout if path_to_log is None: base_dir = os.getcwd() now = datetime.datetime.now().strftime('%Y_%m_%d-%H-%M-%S.log.gz') @@ -223,20 +248,21 @@ def __init__(self, path_to_script, path_to_log=None): self.path_to_log = path_to_log def send_message(self, t, d): - msg = { - 'type': t, - 'params': d - } - msg_bytes = '{}\n'.format(json.dumps(msg)).encode() - + msg_bytes = self.prepare_message_bytes(t, d) self.process.stdin.write(msg_bytes) self.process.stdin.flush() async def get_command(self): try: - line = self.process.stdout.readline().decode('utf-8') - state = json.loads(line) - return state + if self.check_ai_timeout: + self.begin_measure_time() + # + z = self.process.stdout.readline().decode('utf-8') + # + if self.check_ai_timeout: + self.end_measure_time() + + return json.loads(z) except Exception as e: return {'debug': str(e)} diff --git a/paperio/local_runner/game_objects/scene.py b/paperio/local_runner/game_objects/scene.py index a5a1c7a..d527a87 100644 --- a/paperio/local_runner/game_objects/scene.py +++ b/paperio/local_runner/game_objects/scene.py @@ -79,7 +79,7 @@ def reset_leaderboard(self): self.leaderboard_rows_count = 0 def show_game_over(self, timeout=False): - self.game_over_label.text = 'TIMEOUT' if timeout else 'GAME OVER' + self.game_over_label.text = 'END TICK' if timeout else 'GAME OVER' self.game_over_label.draw() def draw_grid(self): diff --git a/paperio/local_runner/localrunner.py b/paperio/local_runner/localrunner.py index 49ab49c..f2a16cc 100755 --- a/paperio/local_runner/localrunner.py +++ b/paperio/local_runner/localrunner.py @@ -25,7 +25,8 @@ help='Path to executable with strategy for player {}'.format(i)) parser.add_argument('--p{}l'.format(i), type=str, nargs='?', help='Path to log for player {}'.format(i)) -parser.add_argument('-t', '--timeout', type=str, nargs='?', help='off/on timeout', default='on') +parser.add_argument('-t', '--timeout', type=str, nargs='?', help='off/on tick limit per game', default='on') +parser.add_argument('--ai-timeout', type=str, nargs='?', help='off/on AI execution time limit', default='off') parser.add_argument('-s', '--scale', type=int, nargs='?', help='window scale (%%)', default=100) parser.add_argument('--replay', help='Replay visio.gz') parser.add_argument('--no-gui', help='Disable default gui', action='store_true') @@ -149,7 +150,7 @@ def get_solution_id(self): elif arg == 'simple_bot': client = SimplePythonClient() else: - client = FileClient(arg.split(), getattr(args, 'p{}l'.format(i))) + client = FileClient(arg.split(), getattr(args, 'p{}l'.format(i)), args.ai_timeout == 'on') clients.append(client)