forked from hkociemba/RubiksCube-TwophaseSolver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
client_gui.py
189 lines (160 loc) · 7.69 KB
/
client_gui.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# ################ A simple graphical interface which communicates with the server #####################################
from tkinter import *
import socket
import face
import cubie
# ################################## Some global variables and constants ###############################################
DEFAULT_HOST = 'localhost'
DEFAULT_PORT = '8080'
width = 60 # width of a facelet in pixels
facelet_id = [[[0 for col in range(3)] for row in range(3)] for face in range(6)]
colorpick_id = [0 for i in range(6)]
curcol = None
t = ("U", "R", "F", "D", "L", "B")
cols = ("yellow", "green", "red", "white", "blue", "orange")
########################################################################################################################
# ################################################ Diverse functions ###################################################
def show_text(txt):
"""Display messages."""
print(txt)
display.insert(INSERT, txt)
root.update_idletasks()
def create_facelet_rects(a):
"""Initialize the facelet grid on the canvas."""
offset = ((1, 0), (2, 1), (1, 1), (1, 2), (0, 1), (3, 1))
for f in range(6):
for row in range(3):
y = 10 + offset[f][1] * 3 * a + row * a
for col in range(3):
x = 10 + offset[f][0] * 3 * a + col * a
facelet_id[f][row][col] = canvas.create_rectangle(x, y, x + a, y + a, fill="grey")
if row == 1 and col == 1:
canvas.create_text(x + width // 2, y + width // 2, font=("", 14), text=t[f], state=DISABLED)
for f in range(6):
canvas.itemconfig(facelet_id[f][1][1], fill=cols[f])
def create_colorpick_rects(a):
"""Initialize the "paintbox" on the canvas."""
global curcol
global cols
for i in range(6):
x = (i % 3)*(a+5) + 7*a
y = (i // 3)*(a+5) + 7*a
colorpick_id[i] = canvas.create_rectangle(x, y, x + a, y + a, fill=cols[i])
canvas.itemconfig(colorpick_id[0], width=4)
curcol = cols[0]
def get_definition_string():
"""Generate the cube definition string from the facelet colors."""
color_to_facelet = {}
for i in range(6):
color_to_facelet.update({canvas.itemcget(facelet_id[i][1][1], "fill"): t[i]})
s = ''
for f in range(6):
for row in range(3):
for col in range(3):
s += color_to_facelet[canvas.itemcget(facelet_id[f][row][col], "fill")]
return s
########################################################################################################################
# ############################### Solve the displayed cube with a local or remote server ###############################
def solve():
"""Connect to the server and return the solving maneuver."""
display.delete(1.0, END) # clear output window
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
show_text('Failed to create socket')
return
# host = 'f9f0b2jt6zmzyo6b.myfritz.net' # my RaspberryPi, if online
host = txt_host.get(1.0, END).rstrip() # default is localhost
port = int(txt_port.get(1.0, END)) # default is port 8080
try:
remote_ip = socket.gethostbyname(host)
except socket.gaierror:
show_text('Hostname could not be resolved.')
return
try:
s.connect((remote_ip, port))
except:
show_text('Cannot connect to server!')
return
show_text('Connected with ' + remote_ip + '\n')
try:
defstr = get_definition_string()+'\n'
except:
show_text('Invalid facelet configuration.\nWrong or missing colors.')
return
show_text(defstr)
try:
s.sendall((defstr+'\n').encode())
except:
show_text('Cannot send cube configuration to server.')
return
show_text(s.recv(2048).decode())
########################################################################################################################
# ################################# Functions to change the facelet colors #############################################
def clean():
"""Restore the cube to a clean cube."""
for f in range(6):
for row in range(3):
for col in range(3):
canvas.itemconfig(facelet_id[f][row][col], fill=canvas.itemcget(facelet_id[f][1][1], "fill"))
def empty():
"""Remove the facelet colors except the center facelets colors."""
for f in range(6):
for row in range(3):
for col in range(3):
if row != 1 or col != 1:
canvas.itemconfig(facelet_id[f][row][col], fill="grey")
def random():
"""Generate a random cube and set the corresponding facelet colors."""
cc = cubie.CubieCube()
cc.randomize()
fc = cc.to_facelet_cube()
idx = 0
for f in range(6):
for row in range(3):
for col in range(3):
canvas.itemconfig(facelet_id[f][row][col], fill=cols[fc.f[idx]] )
idx += 1
########################################################################################################################
# ################################### Edit the facelet colors ##########################################################
def click(event):
"""Define how to react on left mouse clicks."""
global curcol
idlist = canvas.find_withtag("current")
if len(idlist) > 0:
if idlist[0] in colorpick_id:
curcol = canvas.itemcget("current", "fill")
for i in range(6):
canvas.itemconfig(colorpick_id[i], width=1)
canvas.itemconfig("current", width=5)
else:
canvas.itemconfig("current", fill=curcol)
########################################################################################################################
# ###################################### Generate and display the TK_widgets ##########################################
root = Tk()
root.wm_title("Solver Client")
canvas = Canvas(root, width=12 * width + 20, height=9 * width + 20)
canvas.pack()
bsolve = Button(text="Solve", height=2, width=10, relief=RAISED, command=solve)
bsolve_window = canvas.create_window(10 + 10.5 * width, 10 + 6.5 * width, anchor=NW, window=bsolve)
bclean = Button(text="Clean", height=1, width=10, relief=RAISED, command=clean)
bclean_window = canvas.create_window(10 + 10.5 * width, 10 + 7.5 * width, anchor=NW, window=bclean)
bempty = Button(text="Empty", height=1, width=10, relief=RAISED, command=empty)
bempty_window = canvas.create_window(10 + 10.5 * width, 10 + 8 * width, anchor=NW, window=bempty)
brandom = Button(text="Random", height=1, width=10, relief=RAISED, command=random)
brandom_window = canvas.create_window(10 + 10.5 * width, 10 + 8.5 * width, anchor=NW, window=brandom)
display = Text(height=7, width=39)
text_window = canvas.create_window(10 + 6.5 * width, 10 + .5 * width, anchor=NW, window=display)
hp = Label(text=' Hostname and Port')
hp_window = canvas.create_window(10 + 0 * width, 10 + 0.6 * width, anchor=NW, window=hp)
txt_host = Text(height=1, width=20)
txt_host_window = canvas.create_window(10 + 0 * width, 10 + 1 * width, anchor=NW, window=txt_host)
txt_host.insert(INSERT, DEFAULT_HOST)
txt_port = Text(height=1, width=20)
txt_port_window = canvas.create_window(10 + 0 * width, 10 + 1.5 * width, anchor=NW, window=txt_port)
txt_port.insert(INSERT, DEFAULT_PORT)
canvas.bind("<Button-1>", click)
create_facelet_rects(width)
create_colorpick_rects(width)
root.mainloop()
########################################################################################################################