flow-free / app.py
darwinharianto's picture
added japanese
912a5ea
import streamlit as st
from streamlit_drawable_canvas import st_canvas
from PIL import Image, ImageDraw
import matplotlib.colors
import pandas as pd
import numpy as np
from flow_game_solver import (
validate_board_and_count_colors,
initiate_model_with_param,
solve_model,
)
from enum import Enum
class Language(Enum):
English = 1
Japanese = 2
if 'language' not in st.session_state:
st.session_state['language'] = Language.English
_, col2 = st.columns([5,1])
with col2:
language = st.selectbox("Language" if st.session_state['language'] == Language.English else "言語", ("English", "日本語"))
st.session_state['language'] = Language.English if language == "English" else Language.Japanese
# use canvas for user input, read the input, and connect those dots!!
def position_to_index(x, y, width, height, rows, columns):
return int(x / (width / columns)), int(y / (height / rows))
def convert_json_to_board(
data: pd.DataFrame, width: int, height: int, rows: int, columns: int
):
board = np.zeros((columns, rows))
circleIdList = {}
for _, row in data.iterrows():
x, y = row["left"] + row["radius"], row["top"]
idx, idy = position_to_index(int(x), int(y), width, height, rows, columns)
circleId = row["stroke"]
if circleId == "#ffffff":
circleIdList[row["stroke"]] = -1
elif circleId not in circleIdList.keys():
circleIdList[row["stroke"]] = len(circleIdList) + 1
board[idx, idy] = circleIdList[row["stroke"]]
return board.T.astype(int).tolist()
def draw_grid(img: Image, columns: int, rows: int):
width = img.width
height = img.height
draw = ImageDraw.Draw(img)
for col in range(columns):
x = (width / columns) * (col + 1)
draw.line((x, 0, x, height), fill=128)
for row in range(rows):
y = (width / rows) * (row + 1)
draw.line((0, y, width, y), fill=128)
return img
st.title("Connect the dots" if st.session_state['language'] == Language.English else "ドットを繋ごう")
WIDTH = 300
HEIGHT = 300
col1, col2, col3 = st.columns(3)
with col1:
COLUMNS = st.number_input("Columns" if st.session_state['language'] == Language.English else "列数", min_value=1, max_value=100, value=3)
with col2:
ROWS = st.number_input("Rows" if st.session_state['language'] == Language.English else "行数", min_value=1, max_value=100, value=3)
with col3:
fill = st.slider("Minimum Fill" if st.session_state['language'] == Language.English else "最低埋める率", min_value=0.0, max_value=1.0, value=1.0)
waitLimit = st.number_input(
"Max wait time in seconds" if st.session_state['language'] == Language.English else "最大待つ秒数", value=1, min_value=1, max_value=100
)
bg_image = Image.fromarray((np.ones((HEIGHT, WIDTH, 3)) * 0).astype(np.uint8))
# draw = ImageDraw.Draw(bg_image)
# draw grid
bg_image = draw_grid(bg_image, COLUMNS, ROWS)
# draw.line((0, 0, 100, 100), fill=128)
stroke_color = st.color_picker("Point Color: " if st.session_state['language'] == Language.English else "色", "#eab")
# Create a canvas component
col1, col2 = st.columns(2)
with col1:
canvas_result = st_canvas(
# fill_color="rgba(255, 165, 0, 0.3)", # Fixed fill color with some opacity
fill_color=stroke_color, # Fixed fill color with some opacity
stroke_width=5,
stroke_color=stroke_color,
background_color="#fff",
background_image=bg_image,
update_streamlit=True,
height=HEIGHT,
width=WIDTH,
drawing_mode="point",
point_display_radius=min(WIDTH / COLUMNS, HEIGHT / ROWS) / 3,
key="canvas",
)
with col2:
st.info("""
Click on the board to add pair of color source(s).
Change color for different source(s).
Use White color for unpassable path.
Results is shown below.
"""
if st.session_state['language'] == Language.English else
"""
ボードをクリックして、カラー ソースのペアを追加します。
ソースごとに色を変更して、
通行できないパスには白色を使用してお願いします。
結果は下にあります。
""")
clicked = st.button("Show result" if st.session_state['language'] == Language.English else "結果表示")
if clicked:
boardData = pd.json_normalize(canvas_result.json_data["objects"])
colors = [
matplotlib.colors.to_rgb(row["stroke"]) for _, row in boardData.iterrows()
]
colors = list(set(colors))
colors.insert(0, matplotlib.colors.to_rgb("#222"))
board = convert_json_to_board(
boardData,
WIDTH,
HEIGHT,
ROWS,
COLUMNS,
)
min_length = 0
max_length = 1000
num_colors, num_wall = validate_board_and_count_colors(board)
# initiate model
model, solution, edge = initiate_model_with_param(
board,
num_colors,
num_wall,
fill=fill,
area_matrix=None,
min_length=min_length,
max_length=max_length,
)
# solve
ax = solve_model(model, board, solution, edge, waitLimit, None, colors=colors)
if ax is not None:
st.pyplot(ax.get_figure())
else:
st.error("Solution does not exist" if st.session_state['language'] == Language.English else "解が見つからない")
# connect dots using or tools