Skip to content

Instantly share code, notes, and snippets.

@Specnr
Last active October 14, 2023 22:03
Show Gist options
  • Select an option

  • Save Specnr/cef8e4e9aa475629f0c88961e453f017 to your computer and use it in GitHub Desktop.

Select an option

Save Specnr/cef8e4e9aa475629f0c88961e453f017 to your computer and use it in GitHub Desktop.
A Tkinter GUI which writes commands for the tourney controller to read
import tkinter as tk
from tkinter import ttk
import os
import time
import scripts.PlayerFetcher as pf
class Player:
def __init__(self, twitch_username, display_name):
self.twitch_username = twitch_username
self.display_name = display_name
path = os.path.dirname(os.path.realpath(__file__))
obstxtPath = os.path.abspath(os.path.realpath(
os.path.join(path, 'data', 'obs.txt')))
defaultPlayerPath = os.path.abspath(os.path.realpath(
os.path.join(path, 'data', 'default_players.txt')))
def write_to_file(cmd):
with open(obstxtPath, 'w') as f:
f.write(cmd)
def swap_players(idx1, idx2):
write_to_file(f"sw{idx1}{idx2}")
def set_player(idx, player):
write_to_file(f"s{idx}{player}")
def focus_player(idx):
write_to_file(f"f{idx}")
def get_defaults():
names = []
with open(defaultPlayerPath, "r") as f:
for line in f:
names.append(line.strip())
return names
class Rectangle:
def __init__(self, master, grid, row, col, idx, val):
self.master = master
self.grid = grid
self.row = row
self.col = col
self.idx = idx
if val:
self.value = tk.StringVar(value=val)
set_player(self.idx + 1, val)
elif self.idx < len(self.grid.players):
self.value = tk.StringVar(value=self.grid.players[self.idx].twitch_username)
else:
self.value = tk.StringVar(value="NULL")
self.isSelected = tk.BooleanVar(value=False)
self.rectangle_frame = tk.Frame(
self.master, bg="white", borderwidth=2, relief="groove", width=100, height=100)
self.rectangle_frame.grid(
row=self.row, column=self.col, padx=20, pady=20)
self.checkbox = tk.Checkbutton(
self.rectangle_frame, variable=self.isSelected, command=self.on_checkbox_click)
self.checkbox.pack(side="left", padx=(10, 0), pady=10)
# Add a label next to the checkbox
self.label = tk.Label(self.rectangle_frame, textvariable=self.value)
self.label.pack(side="left", padx=(0, 10), pady=10)
def on_checkbox_click(self):
if self.isSelected.get():
self.grid.on_rectangle_select(self)
else:
self.grid.on_rectangle_deselect(self)
def swap_with(self, other):
temp_value = self.value.get()
self.value.set(other.value.get())
other.value.set(temp_value)
temp_is_selected = self.isSelected.get()
self.isSelected.set(other.isSelected.get())
other.isSelected.set(temp_is_selected)
class RectangleGrid:
def __init__(self, master):
self.master = master
self.master.resizable(False, False)
self.rectangles = []
self.players = pf.get_players_directly()
self.filtered_players = []
defaults = get_defaults()
for i in range(2):
for j in range(3):
self.rectangles.append(
Rectangle(self.master, self, i, j, len(self.rectangles), defaults[i * 3 + j]))
time.sleep(0.5)
self.selected_rectangles = []
self.entry = ttk.Entry(self.master)
self.entry.grid(row=0, column=3, padx=(10))
self.entry.bind("<KeyRelease>", self.update_players)
self.listbox = tk.Listbox(self.master)
self.listbox.grid(row=1, column=3, rowspan=2, padx=(10))
self.listbox.bind("<<ListboxSelect>>", self.on_listbox_select)
self.button_frame = tk.Frame(self.master)
self.button_frame.grid(row=4, column=0, columnspan=2, pady=10)
self.focus_button = tk.Button(
self.button_frame, text="Focus", command=self.on_focus, state="disabled", width=10, pady=5)
self.focus_button.pack(side="left", padx=(0, 5))
self.update_players(None)
def get_current_names(self):
return [rect.value.get().lower() for rect in self.rectangles]
def update_players(self, _):
self.players = pf.get_players_directly()
self.filtered_players = [p for p in self.players if self.entry.get().lower() in p.twitch_username.lower() and not p.twitch_username.lower() in self.get_current_names()]
self.filtered_players.sort(key=lambda x: x.twitch_username)
self.listbox.delete(0, tk.END)
for s in self.filtered_players:
self.listbox.insert(tk.END, s.twitch_username)
def swap_logic(self):
if len(self.selected_rectangles) == 2:
self.selected_rectangles[0].swap_with(self.selected_rectangles[1])
for rect in self.selected_rectangles:
rect.isSelected.set(False)
self.selected_rectangles = []
def on_focus(self):
if len(self.selected_rectangles) == 1:
focus_player(
self.selected_rectangles[0].idx + 1)
if self.selected_rectangles[0].idx > 0:
self.selected_rectangles.append(self.rectangles[0])
self.swap_logic()
self.focus_button.config(state="disabled")
def on_swap(self):
if len(self.selected_rectangles) == 2:
swap_players(
self.selected_rectangles[0].idx + 1, self.selected_rectangles[1].idx + 1)
self.swap_logic()
self.focus_button.config(state="disabled")
def on_rectangle_select(self, rectangle):
self.selected_rectangles.append(rectangle)
if len(self.selected_rectangles) == 1:
self.focus_button.config(state="normal")
self.on_swap()
def on_rectangle_deselect(self, rectangle):
self.selected_rectangles.remove(rectangle)
self.focus_button.config(state="disabled")
def on_listbox_select(self, event):
selected_index = self.listbox.curselection()
if selected_index and len(self.selected_rectangles) > 0:
index = int(selected_index[0])
selected_player = self.filtered_players[index]
set_player(self.selected_rectangles[0].idx + 1, selected_player.twitch_username)
self.selected_rectangles[0].value.set(selected_player.twitch_username)
self.selected_rectangles[0].isSelected.set(False)
self.selected_rectangles[0].on_checkbox_click()
self.update_players(None)
self.entry.delete(0, tk.END)
print("BOOTING...")
root = tk.Tk()
root.title("Tournament Controller v3")
grid = RectangleGrid(root)
def update_players():
global grid
grid.players = pf.get_players_directly()
print("Updated players")
root.after(10000, update_players)
update_players()
print("READY!")
root.mainloop()
@Specnr
Copy link
Author

Specnr commented Oct 14, 2023

Removed dropdowns as they made it less intuitive

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment