client.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #!/usr/bin/env python3
  2. import configparser
  3. import tkinter as tk
  4. import tkinter.messagebox
  5. from tkinter.constants import NSEW
  6. import threading
  7. import socket
  8. import selectors
  9. import json
  10. from functools import partial
  11. sel = selectors.DefaultSelector()
  12. class Client(threading.Thread):
  13. def __init__(self, host, port, username, gui):
  14. super().__init__()
  15. self.host = host
  16. self.port = port
  17. self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  18. self.name = username
  19. self.gui = gui
  20. self.start()
  21. def start(self):
  22. self.sock.connect((self.host, self.port))
  23. print('Connected to {}:{}'.format(self.host, self.port))
  24. # Send the username as a welcome message
  25. self.sock.sendall(self.name.encode('utf8'))
  26. super().start()
  27. def close(self):
  28. try:
  29. self.sock.close()
  30. except:
  31. pass
  32. def send(self, message):
  33. self.sock.sendall(message.encode('utf8'))
  34. def vote(self, player):
  35. self.sock.sendall(str(player).encode('utf8'))
  36. def run(self):
  37. try:
  38. while True:
  39. message = self.sock.recv(4096).decode('utf8')
  40. if message:
  41. data = json.loads(message)
  42. if "playerid" in data:
  43. self.gui.player_id = int(data["playerid"])
  44. self.gui.server_data = data
  45. if data["state"] == "vote":
  46. self.gui.messages = []
  47. for key in data["messages"]:
  48. self.gui.messages.append((key, data["messages"][key]))
  49. self.gui.switch_to(data["state"])
  50. else:
  51. self.close()
  52. except:
  53. self.close()
  54. class GUI(tk.Frame):
  55. def __init__(self, master=None):
  56. self.config= configparser.ConfigParser()
  57. self.config.read("client_config.ini", "UTF8")
  58. tk.Frame.__init__(self, master)
  59. self.master.protocol("WM_DELETE_WINDOW", self.quit)
  60. domyslne=self.config["DEFAULT"]
  61. self.geometria_baza=domyslne.get('bazowa_geometria',"1000x800+50+50")
  62. self.master.geometry(self.geometria_baza)
  63. self.master.minsize(1024, 480)
  64. self.add_file_menu()
  65. self.add_help_menu()
  66. self.master.columnconfigure(0, weight=999)
  67. self.master.columnconfigure(1, weight=1)
  68. self.master.rowconfigure(0, weight=1)
  69. self.master.rowconfigure(1, weight=9999)
  70. self.master.rowconfigure(2, weight=1)
  71. self.client = None
  72. self.bg_color = '#36393f'
  73. self.font_color = '#cccccc'
  74. self.server_data = {}
  75. self.frames = {}
  76. self.frames["welcome"] = self.draw_welcome_screen()
  77. self.switch_to("welcome")
  78. self.messages = []
  79. self.player_id = -1
  80. if "username" in domyslne:
  81. self.username_entry.insert(0, domyslne["username"])
  82. if "hostname" in domyslne:
  83. self.address_entry.insert(0, domyslne["hostname"])
  84. else:
  85. self.address_entry.insert(0, "localhost")
  86. self.master.title("AFORYZMY")
  87. def add_file_menu(self):
  88. self.menubar = tk.Menu(self.master)
  89. self.master["menu"] = self.menubar
  90. fileMenu = tk.Menu(self.menubar)
  91. for label, command, shortcut_text, shortcut in (
  92. ("Rozłącz", self.disconnect, None, None),
  93. ("Wyjdź", self.quit, "Ctrl+Q", "<Control-q>")):
  94. if label is None:
  95. fileMenu.add_separator()
  96. else:
  97. fileMenu.add_command(label=label, underline=0,
  98. command=command, accelerator=shortcut_text)
  99. self.master.bind(shortcut, command)
  100. self.menubar.add_cascade(label="Plik", menu=fileMenu, underline=0)
  101. pass
  102. def popup(self, a=""):
  103. window = tk.Toplevel()
  104. window.minsize(240, 80)
  105. window.configure(bg=self.bg_color)
  106. label = tk.Label(window, text="Języki skryptowe 2021", bg=self.bg_color, fg=self.font_color)
  107. label.pack(fill='x', padx=50, pady=5)
  108. button_close = tk.Button(window, text="Zamknij", command=window.destroy, width=6)#, bg=self.bg_color, fg=self.font_color)
  109. button_close.pack()
  110. def add_help_menu(self):
  111. fileMenu = tk.Menu(self.menubar)
  112. fileMenu.add_command(label="O Aforyzmach...", underline=0,
  113. command=self.popup, accelerator="Ctrl+B")
  114. self.master.bind("<Control-b>", self.popup)
  115. self.menubar.add_cascade(label="Help", menu=fileMenu, underline=0)
  116. pass
  117. def close(self):
  118. geometria = self.master.winfo_geometry()
  119. self.config["DEFAULT"]["bazowa_geometria"] = geometria
  120. self.config["DEFAULT"]["username"] = self.username_entry.get()
  121. self.config["DEFAULT"]["hostname"] = self.address_entry.get()
  122. with open("client_config.ini", 'w') as config_file:
  123. self.config.write(config_file)
  124. self.master.destroy()
  125. def disconnect(self, event= None):
  126. if self.client is not None:
  127. self.client.close()
  128. self.client = None
  129. self.switch_to("welcome")
  130. def quit(self, event= None):
  131. reply = True
  132. reply = tkinter.messagebox.askyesno(
  133. "Wyjście",
  134. "Naprawdę wyjść?", master=self.master)
  135. event=event
  136. if reply:
  137. if (self.client is not None):
  138. self.client.close()
  139. self.close()
  140. def connect(self):
  141. if len(self.username_entry.get()) > 0:
  142. self.client = Client(self.address_entry.get(), 7312, self.username_entry.get(), self)
  143. def upload(self):
  144. if len(self.aphorism_entry.get()) > 0:
  145. self.switch_to("wait")
  146. self.client.send(self.aphorism_entry.get())
  147. def vote(self, player):
  148. self.switch_to("wait")
  149. self.client.vote(player)
  150. def switch_to(self, state):
  151. for frame in self.frames:
  152. self.frames[frame].grid_forget()
  153. if state != "welcome":
  154. self.frames[state] = self.draw_screen(state)
  155. self.frames[state].grid(row=1, column=0, columnspan=1, rowspan=1, sticky=NSEW)
  156. def draw_screen(self, type):
  157. if type == "wait":
  158. frame = tk.Frame(self.master, background=self.bg_color)
  159. label = tk.Label(frame, text="Oczekiwanie na innych graczy", pady=100, bg=self.bg_color, fg=self.font_color)
  160. label.pack()
  161. return frame
  162. if type == "vote":
  163. frame = tk.Frame(self.master, background=self.bg_color)
  164. title_label = tk.Label(frame, text="AFORYZMY", bg=self.bg_color, fg=self.font_color, font="Helvetica 22")
  165. title_label.pack()
  166. tk.Label(frame, text="Wybierz najlepszą definicję {}".format(self.server_data["title"].upper()), fg=self.font_color, bg=self.bg_color, font="Helvetica 12", height="2", anchor="n").pack()
  167. for message in self.messages:
  168. player, text = message
  169. if str(player) != str(self.player_id):
  170. tk.Button(frame, text=text, fg=self.font_color, bg=self.bg_color, font="Helvetica 12", width="80", height="3", pady="2", relief="flat", command=partial(self.vote, player)).pack()
  171. return frame
  172. if type == "display":
  173. frame = tk.Frame(self.master, background=self.bg_color)
  174. title_label = tk.Label(frame, text="AFORYZMY", bg=self.bg_color, fg=self.font_color, font="Helvetica 22")
  175. title_label.pack()
  176. tk.Label(frame, text="Wyniki", fg=self.font_color, bg=self.bg_color,
  177. font="Helvetica 12", height="2", anchor="n").pack()
  178. for message in self.messages:
  179. player, text = message
  180. total_score = 0
  181. score = 0
  182. if player in self.server_data["total_scores"]:
  183. total_score = self.server_data["total_scores"][player]
  184. if player in self.server_data["scores"]:
  185. score = self.server_data["scores"][player]
  186. tk.Label(frame, text="{} ({}): {} ({})".format(self.server_data["users"][player], total_score, text, score), fg=self.font_color, bg=self.bg_color, font="Helvetica 12", width="100", anchor="nw",
  187. height="3", pady="2", padx="2").pack(fill="x")
  188. tk.Label(frame, text="Kolejna runda rozpocznie się za chwilę", fg=self.font_color, bg=self.bg_color,
  189. font="Helvetica 12", height="3", anchor="n").pack(side="bottom")
  190. return frame
  191. if type == "game":
  192. frame = tk.Frame(self.master, background=self.bg_color)
  193. title_label = tk.Label(frame, text="AFORYZMY", bg=self.bg_color, fg=self.font_color, font="Helvetica 22")
  194. title_label.pack()
  195. tk.Label(frame, text="Napisz złotą myśl na temat wyrazu {}".format(self.server_data["title"].upper()),
  196. fg=self.font_color, bg=self.bg_color, font="Helvetica 12").pack()
  197. sv = tk.StringVar()
  198. self.aphorism_entry = tk.Entry(frame, width=80, textvariable=sv)
  199. sv.trace_add("write", lambda x, y, z: self.key_fix(sv, 100))
  200. self.aphorism_entry.pack()
  201. send_button = tk.Button(frame, text="Wyślij", command=self.upload)
  202. send_button.pack()
  203. return frame
  204. def draw_welcome_screen(self):
  205. frame = tk.Frame(self.master, background=self.bg_color)
  206. title_label = tk.Label(frame, text="AFORYZMY", bg=self.bg_color, fg=self.font_color, font="Helvetica 22")
  207. title_label.pack()
  208. tk.Label(frame, text="Login", fg=self.font_color, bg=self.bg_color, font="Helvetica 12").pack()
  209. sv = tk.StringVar()
  210. self.username_entry = tk.Entry(frame, textvariable=sv)
  211. sv.trace_add("write", lambda x,y,z: self.key_fix(sv, 20))
  212. self.username_entry.pack()
  213. tk.Label(frame, text="Host", fg=self.font_color, bg=self.bg_color, font="Helvetica 12").pack()
  214. self.address_entry = tk.Entry(frame)
  215. self.address_entry.pack()
  216. title_button = tk.Button(frame, text="Połącz", command=self.connect, anchor="s")
  217. title_button.pack()
  218. return frame
  219. def key_fix(self, sv, limit):
  220. str = sv.get()
  221. list = [
  222. ('ę', 'ê'), ('Ę', 'Ê'),
  223. ('ś', 'œ'), ('Ś', 'Œ'),
  224. ('ć', 'æ'), ('Ć', 'Æ'),
  225. ('ł', '³'), ('Ł', '£'),
  226. ('ń', 'ñ'), ('Ń', 'Ñ'),
  227. ('ą', '¹'), ('Ą', '¥'),
  228. ('ż', '¿'), ('Ż', '¯'),
  229. ('ź', 'Ÿ'), ('', "=")#('Ź', '')
  230. ]
  231. for (pl, k) in list:
  232. str = str.replace(k, pl)
  233. sv.set(str[:limit])
  234. if __name__ == '__main__':
  235. root = tk.Tk()
  236. app = GUI(master=root)
  237. app.mainloop()
  238. pass