mts-mouse/n1.py

274 lines
8.9 KiB
Python
Raw Permalink Normal View History

2024-10-12 20:05:17 +02:00
import requests
import time
class Cell:
def __init__(self, x, y):
self.x = x
self.y = y
self.walls = {'N': None, 'E': None, 'S': None, 'W': None}
self.visited = False
def get_wall_code(self):
up = self.walls['N']
right = self.walls['E']
down = self.walls['S']
left = self.walls['W']
walls = (
1 if up else 0,
1 if right else 0,
1 if down else 0,
1 if left else 0
)
walls_to_code = {
(0, 0, 0, 0): 0,
(0, 0, 0, 1): 1,
(1, 0, 0, 0): 2,
(0, 1, 0, 0): 3,
(0, 0, 1, 0): 4,
(0, 0, 1, 1): 5,
(0, 1, 1, 0): 6,
(1, 1, 0, 0): 7,
(1, 0, 0, 1): 8,
(0, 1, 0, 1): 9,
(1, 0, 1, 0): 10,
(1, 1, 1, 0): 11,
(1, 1, 0, 1): 12,
(1, 0, 1, 1): 13,
(0, 1, 1, 1): 14,
(1, 1, 1, 1): 15
}
return walls_to_code.get(walls, 0)
2024-10-16 09:21:31 +02:00
2024-10-12 20:05:17 +02:00
class Maze:
class ExitDFS(Exception):
pass
def __init__(self):
self.size = 16
self.restart()
def restart(self):
self.grid = [[Cell(x, y) for y in range(self.size)] for x in range(self.size)]
self.start_x = 0
self.start_y = 0
def get_cell(self, x, y):
return self.grid[x][y]
def is_within_bounds(self, x, y):
return 0 <= x < self.size and 0 <= y < self.size
def to_array(self):
maze_array = []
for y in range(self.size - 1, -1, -1):
row = []
for x in range(self.size):
cell = self.get_cell(x, y)
row.append(cell.get_wall_code())
maze_array.append(row)
return maze_array
2024-10-16 09:21:31 +02:00
2024-10-12 20:05:17 +02:00
class Robot:
def __init__(self, token: str, maze: Maze):
self.token = token
self.api_url = 'http://127.0.0.1:8801/api/v1'
self.maze = maze
self.restart()
def restart(self):
self.x = self.maze.start_x
self.y = self.maze.start_y
self.orientation = 'N' # 'N', 'E', 'S', 'W'
self.visited_cells = set()
self.move_count = 0
def get_sensor_data(self):
2024-10-16 09:21:31 +02:00
time.sleep(0.2)
2024-10-12 20:05:17 +02:00
response = requests.get(f'{self.api_url}/robot-cells/sensor-data', params={'token': self.token})
return response.json()
def move_forward(self):
requests.post(f'{self.api_url}/robot-cells/forward', params={'token': self.token})
2024-10-16 09:21:31 +02:00
time.sleep(0.2)
2024-10-12 20:05:17 +02:00
self.update_position('forward')
def turn_left(self):
requests.post(f'{self.api_url}/robot-cells/left', params={'token': self.token})
2024-10-16 09:21:31 +02:00
time.sleep(0.2)
2024-10-12 20:05:17 +02:00
self.update_orientation('left')
def turn_right(self):
requests.post(f'{self.api_url}/robot-cells/right', params={'token': self.token})
2024-10-16 09:21:31 +02:00
time.sleep(0.2)
2024-10-12 20:05:17 +02:00
self.update_orientation('right')
def move_backward(self):
requests.post(f'{self.api_url}/robot-cells/backward', params={'token': self.token})
2024-10-16 09:21:31 +02:00
time.sleep(0.2)
2024-10-12 20:05:17 +02:00
self.update_position('backward')
def update_orientation(self, turn):
directions = ['N', 'E', 'S', 'W']
idx = directions.index(self.orientation)
if turn == 'left':
self.orientation = directions[(idx - 1) % 4]
elif turn == 'right':
self.orientation = directions[(idx + 1) % 4]
def update_position(self, move):
dx, dy = 0, 0
if self.orientation == 'N':
dy = 1 if move == 'forward' else -1
elif self.orientation == 'E':
dx = 1 if move == 'forward' else -1
elif self.orientation == 'S':
dy = -1 if move == 'forward' else 1
elif self.orientation == 'W':
dx = -1 if move == 'forward' else 1
self.x += dx
self.y += dy
self.move_count += 1
def explore(self):
try:
self._dfs(self.x, self.y)
except self.maze.ExitDFS:
pass
def _dfs(self, x, y):
if len(self.visited_cells) == self.maze.size ** 2:
raise self.maze.ExitDFS()
cell = self.maze.get_cell(x, y)
cell.visited = True
self.visited_cells.add((x, y))
sensor_data = self.get_sensor_data()
threshold = 100
walls = {}
walls[self.orientation_to_dir('N')] = sensor_data['front_distance'] < threshold
walls[self.orientation_to_dir('E')] = sensor_data['right_side_distance'] < threshold
walls[self.orientation_to_dir('W')] = sensor_data['left_side_distance'] < threshold
walls[self.orientation_to_dir('S')] = sensor_data['back_distance'] < threshold
cell.walls.update(walls)
for direction in ['N', 'E', 'S', 'W']:
if not cell.walls[direction]:
nx, ny = self.get_next_position(x, y, direction)
if self.maze.is_within_bounds(nx, ny) and (nx, ny) not in self.visited_cells:
self.move_to(direction)
try:
self._dfs(nx, ny)
except self.maze.ExitDFS as e:
raise e
self.move_to(self.opposite_direction(direction)) # Возвращаемся назад
def get_next_position(self, x, y, direction):
dx, dy = 0, 0
if direction == 'N':
dy = 1
elif direction == 'E':
dx = 1
elif direction == 'S':
dy = -1
elif direction == 'W':
dx = -1
return x + dx, y + dy
def move_to(self, direction):
turns = self.calculate_turns(self.orientation, direction)
for turn in turns:
if turn == 'left':
self.turn_left()
elif turn == 'right':
self.turn_right()
self.move_forward()
def calculate_turns(self, current_orientation, target_orientation):
directions = ['N', 'E', 'S', 'W']
idx_current = directions.index(current_orientation)
idx_target = directions.index(target_orientation)
if idx_current == idx_target:
return []
elif (idx_current + 1) % 4 == idx_target:
return ['right']
elif (idx_current - 1) % 4 == idx_target:
return ['left']
else:
return ['left', 'left']
def opposite_direction(self, direction):
opposites = {'N': 'S', 'E': 'W', 'S': 'N', 'W': 'E'}
return opposites[direction]
def orientation_to_dir(self, relative_direction):
directions = ['N', 'E', 'S', 'W']
idx = directions.index(self.orientation)
if relative_direction == 'N':
return directions[idx]
elif relative_direction == 'E':
return directions[(idx + 1) % 4]
elif relative_direction == 'S':
return directions[(idx + 2) % 4]
elif relative_direction == 'W':
return directions[(idx - 1) % 4]
def restart_maze(self):
response = requests.post(f"{self.api_url}/maze/restart", params={'token': self.token})
if response.status_code == 200:
print("Лабиринт перезапущен.")
else:
print(f"Ошибка при перезапуске лабиринта: {response.text}")
def restart(robot: Robot, maze: Maze):
robot.restart()
robot.restart_maze()
maze.restart()
def start_once(robot: Robot, matrix_check: bool=False, score_check: bool=True):
robot.explore()
print_results(robot=robot, matrix_check=matrix_check, score_check=score_check)
restart(robot=robot, maze=robot.maze)
def print_results(robot:Robot, matrix_check: bool=False, score_check: bool=True):
maze_array = robot.maze.to_array()
if matrix_check:
for row in maze_array:
print(row)
response = requests.post(
f'{robot.api_url}/matrix/send',
params={'token': robot.token},
json=maze_array
)
if response.status_code == 200:
response_data = response.json()
score = response_data.get('Score')
if score is not None:
print('Отправка матрицы завершена' + f', Score: {score}' * score_check)
else:
print('Отправка матрицы завершена, но Score отсутствует в ответе:', response_data)
else:
print('Ошибка при отправке матрицы, статус код:', response.status_code)
def main(num_att=1):
token = 'token'
maze = Maze()
robot = Robot(token=token, maze=maze)
times = time.time()
for i in range(num_att):
start_time = time.time()
print(f'Попытка {i + 1}')
2024-10-16 09:21:31 +02:00
start_once(robot=robot, matrix_check=True)
2024-10-12 20:05:17 +02:00
print(f'Время {time.time() - start_time} секунд')
print(f'Общее время {time.time() - times} секунд (лимит - {60 * 15})')
if __name__ == '__main__':
2024-10-16 09:21:31 +02:00
main(num_att=1)