Created
December 24, 2023 20:25
-
-
Save mafshin/d24c0cd11b9562644f427a9c4979c9be to your computer and use it in GitHub Desktop.
Draw Solution of Problem 40 with NiceGUI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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