client.py 11 KB

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