Skip to content

Instantly share code, notes, and snippets.

@mafshin
Created December 24, 2023 20:25
Show Gist options
  • Save mafshin/d24c0cd11b9562644f427a9c4979c9be to your computer and use it in GitHub Desktop.
Save mafshin/d24c0cd11b9562644f427a9c4979c9be to your computer and use it in GitHub Desktop.
Draw Solution of Problem 40 with NiceGUI
from enum import Enum
from nicegui import ui
Direction = Enum('Direction', ['Up', 'Down', 'Right', 'Left'])
def build_svg(grid_size, cell_size) -> str:
width = cell_size * grid_size + 1
height = cell_size * grid_size + 1
solution_path = 'D D D D L L L L L U U U U U U L U R R R R R R R R R'
robot_x = 7
robot_y = 4
path = draw_path(robot_x, robot_y, solution_path, grid_size, cell_size, 'orange')
gate = draw_path(10, 5, 'U U U', grid_size, cell_size, 'blue')
ball_x = get_x_position(2, grid_size, cell_size)
ball_y = get_y_position(1, grid_size, cell_size)
ball = f'<circle cx="{ball_x}" cy="{ball_y}" r="10" fill="red" />'
robot_pos_x = get_x_position(robot_x, grid_size, cell_size)
robot_pos_y = get_y_position(robot_y, grid_size, cell_size)
robot = f'<circle cx="{robot_pos_x}" cy="{robot_pos_y}" r="20" fill="green" />'
return f'''
<svg id='patternId' width='{width}' height='{height}' xmlns='http://www.w3.org/2000/svg'>
<defs><pattern id='a' patternUnits='userSpaceOnUse' width='{cell_size}' height='{cell_size}' patternTransform='rotate(0)'>
<rect x='0' y='0' width='100%' height='100%' fill='hsla(0,0%,100%,1)'/>
<path d='M 0,0 V {cell_size} Z M 0,0 H {cell_size} Z' stroke-width='1' stroke='hsla(133, 35%, 32%, 1)' fill='none'/>
</pattern></defs>
<rect width='100%' height='100%' fill='url(#a)'/>
{path}
{gate}
{ball}
{robot}
</svg>
'''
def get_x_position(pos, grid_size, cell_size):
return pos * cell_size
def get_y_position(pos, grid_size, cell_size):
return (grid_size - pos) * cell_size
def draw_path(x, y, path, grid_size, cell_size, color):
directions = path.split(' ')
lines = []
next_x = x
next_y = y
for dir in directions:
direction: Direction = get_direction(dir)
lines.append(generate_line(next_x, next_y, direction, 1, grid_size, cell_size, color))
next_x, next_y = calculate_next_position(next_x, next_y, direction)
return str.join(" ", lines)
def calculate_next_position(x, y, direction: Direction):
match direction:
case Direction.Down:
return (x, y - 1)
case Direction.Up:
return (x, y + 1)
case Direction.Left:
return (x - 1, y)
case Direction.Right:
return (x + 1, y)
def get_direction(dir):
match dir:
case 'D':
return Direction.Down
case 'U':
return Direction.Up
case 'L':
return Direction.Left
case 'R':
return Direction.Right
def generate_line(x, y, direction: Direction, length, grid_size, cell_size, color):
target_x = x
target_y = (grid_size) - y
match direction:
case Direction.Down:
target_y = target_y + length # SVG grid is top to bottom
case Direction.Up:
target_y = target_y - length # SVG grid is top to bottom
case Direction.Right:
target_x = target_x + length
case Direction.Left:
target_x = target_x - length
scaled_x = x * cell_size
scaled_y = ((grid_size) - y) * cell_size
scaled_target_x = target_x * cell_size
scaled_target_y = target_y * cell_size
return f'''
<path d='M {scaled_x} {scaled_y} L {scaled_target_x} {scaled_target_y}' stroke-width='3' stroke='{color}'/>
'''
grid_size = 10
cell_size = 50
body = ui.html().classes('self-center')
html_content = build_svg(grid_size, cell_size)
body.set_content(html_content)
ui.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment