import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from tkinter import font
import os
import random
import re

# Initialize the main application window
root = tk.Tk()

# Define window dimensions
window_width = 1600
window_height = 900

# Set the window title
root.title('FFA Tournament')

# Set the window size
root.geometry(f'{window_width}x{window_height}')

# Disable resizing of the window
root.resizable(False, False)

# Center the window on the screen
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x_coordinate = int((screen_width/2) - (window_width/2))
y_coordinate = int((screen_height/2) - (window_height/2))

# Set the window position to the center of the screen
root.geometry(f"+{x_coordinate}+{y_coordinate}")

# Create the main container frame
main_container = tk.Frame(root)
main_container.pack(fill='both', expand=True)

# Configure the grid layout for the main container frame
for column in range(4):
    main_container.columnconfigure(column, weight=1)
main_container.rowconfigure(0, weight=9)  # 90% of the vertical space for the story containers
main_container.rowconfigure(1, weight=1)  # 10% of the vertical space for the submit button

# List to keep track of the textboxes
textboxes = []

# Function to swap the contents of two textboxes and update the contestants list
def swap_stories(textbox1, textbox2):
    # Determine if we are in the finals round
    in_finals = current_group_index == len(contestant_groups) + 1

    # Get the stories from each textbox
    story1 = textbox1.get('1.0', tk.END)
    story2 = textbox2.get('1.0', tk.END)

    # Swap the stories in the textboxes
    textbox1.delete('1.0', tk.END)
    textbox1.insert('1.0', story2)
    textbox2.delete('1.0', tk.END)
    textbox2.insert('1.0', story1)

    # Swap the corresponding data in the contestant groups or finalists
    if not in_finals:
        group = contestant_groups[current_group_index - 1]  # Get the current group
        index1 = textboxes.index(textbox1)
        index2 = textboxes.index(textbox2)
        group[index1], group[index2] = group[index2], group[index1]
        # Print statements to verify correct pairing
        print(f'Swapped {group[index1]["name"]} with {group[index2]["name"]}')
        print_contestants_group(group)
    else:
        index1 = textboxes.index(textbox1)
        index2 = textboxes.index(textbox2)
        finalists[index1], finalists[index2] = finalists[index2], finalists[index1]
        # Print statements to verify correct pairing in finals
        print(f'Swapped {finalists[index1]["name"]} with {finalists[index2]["name"]}')
        print_contestants_group(finalists)

# Function to print the current group's contestants and their stories
def print_contestants_group(group):
    for contestant in group:
        print(f'Contestant: {contestant["name"]} - Story: {contestant["story"][:30]}...')

# Function to create a story container frame with a specific textbox background color
def create_story_container(parent, column, bg_color, story_text=''):
    # Create the story frame within the parent frame
    story_frame = tk.Frame(parent)
    story_frame.grid(row=0, column=column, sticky='nsew', padx=5, pady=5)

    # Configure the grid layout inside the story frame
    story_frame.rowconfigure(0, weight=9)  # 90% of the vertical space for the textbox
    story_frame.rowconfigure(1, weight=1)  # 10% of the vertical space for the arrow buttons
    story_frame.columnconfigure(0, weight=1)

    # Create the custom font
    custom_font = font.Font(family="Helvetica", size=16)

    # Create the textbox inside the story frame with the specified background color
    textbox = tk.Text(story_frame, wrap='word', bg=bg_color, font=custom_font, padx=10, pady=10)
    textbox.grid(row=0, column=0, sticky='nsew', padx=10, pady=10)
    textbox.insert('1.0', story_text)

    # Create a scrollbar and attach it to the textbox
    scrollbar = ttk.Scrollbar(story_frame, orient='vertical', command=textbox.yview)
    scrollbar.grid(row=0, column=1, sticky='ns')  # Place it to the right of the textbox
    textbox['yscrollcommand'] = scrollbar.set

    # Create a frame for the arrow buttons inside the story frame
    arrows_frame = tk.Frame(story_frame, bg='gray')
    arrows_frame.grid(row=1, column=0, sticky='ew')

    # Create a grid configuration for the arrows frame with equal weight columns
    arrows_frame.columnconfigure(0, weight=1)
    arrows_frame.columnconfigure(1, weight=1)

    # Create the left arrow button
    left_arrow_button = ttk.Button(arrows_frame, text='<-- Left', command=lambda: swap_stories(textboxes[column-1], textbox) if column > 0 else None)
    left_arrow_button.grid(row=0, column=0, sticky='ew', padx=10, pady=10)

    # Create the right arrow button
    right_arrow_button = ttk.Button(arrows_frame, text='Right -->', command=lambda: swap_stories(textbox, textboxes[column+1]) if column < 3 else None)
    right_arrow_button.grid(row=0, column=1, sticky='ew', padx=10, pady=10)

    return textbox

# Define the hex background colors for the textboxes - gold, silver, bronze, white
textbox_colors = [
    '#F3E0FF',  # Light Purple
    '#FFECB3',  # Gold
    '#C0C0C0',  # Silver
    '#D2B48C',  # Bronze
]

# Create 4 story containers in the main container with the specified background colors
for i in range(4):
    textbox = create_story_container(main_container, i, textbox_colors[i])
    textboxes.append(textbox)

# Global variable to keep track of the current group index
current_group_index = 0

# Function to update the textboxes with the next group's stories
def update_stories(group_index):
    global current_group_index
    if group_index < len(contestant_groups):
        for i in range(len(contestant_groups[group_index])):
            textbox = textboxes[i]
            textbox.delete('1.0', tk.END)  # Clear the current text
            textbox.insert('1.0', contestant_groups[group_index][i]['story'])  # Insert new text
        current_group_index += 1
    else:
        messagebox.showinfo("End of Tournament", "All groups have been displayed.")

# Function to convert text to a list of chunks of numbers and non-numbers
def natural_keys(text):
    return [int(c) if c.isdigit() else c.lower() for c in re.split('(\d+)', text)]

# Function to output the sorted results to a text file
def output_results_to_file(contestants_list):
    # Sort the contestants using natural sorting
    sorted_contestants = sorted(contestants_list, key=lambda c: natural_keys(c['name']))

    # Open the file for writing
    with open('tournament_results.txt', 'w', encoding='utf-8') as file:
        # Write each contestant's name and points to the file
        for contestant in sorted_contestants:
            file.write(f"{contestant['points']} - {contestant['name']}\n")

# Global list to keep track of the finalists
finalists = []

# Function to handle the submit action
def submit_action():
    global current_group_index
    global finalists

    # Check if we're still in the initial group phase
    if current_group_index <= len(contestant_groups):
        current_group = contestant_groups[current_group_index - 1]
        # Award points and determine the winner of the current group
        group_winner = None
        max_points = -1
        for i, contestant in enumerate(current_group):
            points_to_add = 0
            if i == 0:  # Gold
                points_to_add = 3
            elif i == 1:  # Silver
                points_to_add = 2
            elif i == 2:  # Bronze
                points_to_add = 1

            # Update points for the contestant in the original list
            contestant['points'] += points_to_add
            # Check for the winner
            if contestant['points'] > max_points:
                max_points = contestant['points']
                group_winner = contestant

        # Add the winner to the finalists list
        finalists.append(group_winner)
        # Move on to the next group if there are more groups left
        if current_group_index < len(contestant_groups):
            update_stories(current_group_index)
        else:
            # If we're done with the initial groups, set up the finalists' group
            update_stories_with_finalists()

    # If we're in the finalists' phase
    elif current_group_index == len(contestant_groups) + 1:
        # Award points for the finalists based on their ranking
        for i, finalist in enumerate(finalists):
            points_to_add = 0
            if i == 0:  # Gold
                points_to_add = 3
            elif i == 1:  # Silver
                points_to_add = 2
            elif i == 2:  # Bronze
                points_to_add = 1

            # Update points for the finalist
            finalist['points'] += points_to_add

        # Determine the overall winner
        overall_winner = max(finalists, key=lambda f: f['points'])
        # Display the winner in a pop-up
        messagebox.showinfo("Winner", f"Winner: {overall_winner['name']}")

        # Output the sorted results to a text file
        output_results_to_file(contestants)

        # End the program
        root.destroy()

    # If we're in the finalists' phase
    elif current_group_index == len(contestant_groups) + 1:
        # Determine the overall winner
        overall_winner = None
        max_points = -1
        for finalist in finalists:
            if finalist['points'] > max_points:
                max_points = finalist['points']
                overall_winner = finalist
        # Display the winner in a pop-up
        # Output the sorted results to a text file
        output_results_to_file(contestants)
        messagebox.showinfo("Winner", f"Winner: {overall_winner['name']}")
        root.destroy()  # End the program

# Function to load the finalists' stories into the textboxes
def update_stories_with_finalists():
    global current_group_index
    # Clear all textboxes
    for textbox in textboxes:
        textbox.delete('1.0', tk.END)
    # Load the finalists' stories
    for i, finalist in enumerate(finalists):
        textboxes[i].insert('1.0', finalist['story'])
    # Increment the index to indicate we're now in the finalists' phase
    current_group_index += 1

# Create a frame for the submit button at the bottom
submit_button_frame = tk.Frame(main_container)
submit_button_frame.grid(row=1, column=0, columnspan=4, sticky='ew', padx=5, pady=5)
submit_button_frame.columnconfigure(0, weight=1)  # Configure the frame to expand the button to the full width

# Create the Submit button and place it into the submit_button_frame
submit_button = ttk.Button(submit_button_frame, text='Submit', command=submit_action)
submit_button.grid(row=0, column=0, sticky='ew', padx=10, pady=10)

# Function to read the contestant files and return a list of contestants
def load_contestants(directory):
    contestants = []
    try:
        for filename in os.listdir(directory):
            if filename.endswith('.txt'):
                with open(os.path.join(directory, filename), 'r', encoding='utf-8') as file:
                    story = file.read()
                    contestants.append({'name': filename[:-4], 'story': story, 'points': 0})
    except FileNotFoundError:
        messagebox.showerror("Error", "The contestants directory was not found.")
        root.destroy()
    return contestants

# Function to shuffle and group contestants into groups of 4
def group_contestants(contestants_list):
    random.shuffle(contestants_list)  # Randomly shuffle the list of contestants
    groups = [contestants_list[i:i + 4] for i in range(0, len(contestants_list), 4)]  # Slice the list into groups of 4
    return groups

# Load contestants and check for the correct number
contestants = load_contestants('contestants')
if len(contestants) != 16:
    messagebox.showerror("Error", "There must be 16 contestants to proceed.")
    root.destroy()
else:
    contestant_groups = group_contestants(contestants)  # Group the contestants
    # Load the first group's stories into the textboxes
    update_stories(current_group_index)

# Start the main application loop
root.mainloop()
Edit Report
Pub: 29 Jan 2024 23:30 UTC
Views: 210