import gradio as gr import pandas as pd import re import csv import pandas as pd def update_scores(winner, loser, k_factor=100): score_difference = int(k_factor/(winner/loser)) winner += score_difference loser -= score_difference return winner, loser def vote_startup(opponents_df): try: opponents_df = opponents_df[["elo_score", "descriptor", "opponent"]] except: opponents_df = pd.DataFrame(columns=['elo_score', 'descriptor', 'opponent']) if len(opponents_df)>0: if len(opponents_df)>10: slice_size = 4 slice = int(len(opponents_df)/slice_size) sample = opponents_df[slice:(slice_size-1)*slice].sample(frac=1).iloc[0] opponent, descriptor = sample["opponent"], sample["descriptor"] else: sample = opponents_df.sample(frac=1).iloc[0] opponent, descriptor = sample["opponent"], sample["descriptor"] if len(opponents_df) > 1: # Randomly select a opponent to compare with sample = opponents_df.sample(frac=1) comparison_opponent = sample.iloc[0] if comparison_opponent['opponent'] == opponent and comparison_opponent['descriptor'] == descriptor: comparison_opponent = sample.iloc[1] first_df = opponents_df[opponents_df["opponent"]==opponent][opponents_df["descriptor"]==descriptor] first_string = first_df["opponent"].tolist()[0]+" - "+first_df["descriptor"].tolist()[0] second_df = comparison_opponent second_string = second_df["opponent"]+" - "+second_df["descriptor"] return f"Do you like '{descriptor} - {opponent}' better than '{comparison_opponent['descriptor']} - {comparison_opponent['opponent']}'?", first_string, second_string, display_rankings(opponents_df) else: return "Add some opponents to start voting!", "", "", display_rankings(opponents_df) def clean_string(string): string = string.strip().replace(" "," ").lower() string = " ".join([x[0].upper()+x[1:] for x in string.split()]) return string def add_and_compare(descriptor, opponent, opponents_df): try: opponents_df = opponents_df[["elo_score", "descriptor", "opponent"]] except: opponents_df = pd.DataFrame(columns=['elo_score', 'descriptor', 'opponent']) if descriptor != "" and opponent != "": descriptor = clean_string(descriptor) opponent = clean_string(opponent) new_opponent = pd.DataFrame({'descriptor': [descriptor], 'opponent': [opponent], 'elo_score': [1000]}) opponents_df = pd.concat([opponents_df, new_opponent], ignore_index=True) opponents_df.to_csv("opponents_df.csv") opponents_df = opponents_df[["elo_score", "descriptor", "opponent"]] return "", "", display_rankings(opponents_df) # Function to update Elo ratings based on user's choice def update_ratings_pos(first_string, second_string, opponents_df): try: opponents_df = opponents_df[["elo_score", "descriptor", "opponent"]] except: opponents_df = pd.DataFrame(columns=['elo_score', 'descriptor', 'opponent']) if len(opponents_df)==0: return "Add some opponents to start voting!", "", "", display_rankings(opponents_df) if first_string != "": opponents_df["combined"] = opponents_df["opponent"] + " - " + opponents_df["descriptor"] loser = opponents_df[opponents_df["combined"] == second_string] winner = opponents_df[opponents_df["combined"] == first_string] # Update Elo scores winner_score, loser_score = update_scores(winner['elo_score'].values[0], loser['elo_score'].values[0]) opponents_df.at[winner.index[0], 'elo_score'] = winner_score opponents_df.at[loser.index[0], 'elo_score'] = loser_score opponents_df = opponents_df.sort_values(by='elo_score', ascending=False) opponents_df.to_csv("opponents_df.csv") if len(opponents_df)>10: slice_size = 4 slice = int(len(opponents_df)/slice_size) sample = opponents_df[slice:(slice_size-1)*slice].sample(frac=1).iloc[0] opponent, descriptor = sample["opponent"], sample["descriptor"] else: sample = opponents_df.sample(frac=1).iloc[0] opponent, descriptor = sample["opponent"], sample["descriptor"] if len(opponents_df) > 1: # Randomly select a opponent to compare with sample = opponents_df.sample(frac=1) comparison_opponent = sample.iloc[0] if comparison_opponent['opponent'] == opponent and comparison_opponent['descriptor'] == descriptor: comparison_opponent = sample.iloc[1] first_df = opponents_df[opponents_df["opponent"]==opponent][opponents_df["descriptor"]==descriptor] first_string = first_df["opponent"].tolist()[0]+" - "+first_df["descriptor"].tolist()[0] second_df = comparison_opponent second_string = second_df["opponent"]+" - "+second_df["descriptor"] return f"Do you like '{descriptor} - {opponent}' better than '{comparison_opponent['descriptor']} - {comparison_opponent['opponent']}'?", first_string, second_string, display_rankings(opponents_df) else: return "Add some opponents to start voting!", "", "", display_rankings(opponents_df) # Function to update Elo ratings based on user's choice def update_ratings_neg(first_string, second_string, opponents_df): try: opponents_df = opponents_df[["elo_score", "descriptor", "opponent"]] except: opponents_df = pd.DataFrame(columns=['elo_score', 'descriptor', 'opponent']) if len(opponents_df)==0: return "Add some opponents to start voting!", "", "", display_rankings(opponents_df) if first_string != "": opponents_df["combined"] = opponents_df["opponent"] + " - " + opponents_df["descriptor"] loser = opponents_df[opponents_df["combined"] == first_string] winner = opponents_df[opponents_df["combined"] == second_string] # Update Elo scores winner_score, loser_score = update_scores(winner['elo_score'].values[0], loser['elo_score'].values[0]) opponents_df.at[winner.index[0], 'elo_score'] = winner_score opponents_df.at[loser.index[0], 'elo_score'] = loser_score opponents_df = opponents_df.sort_values(by='elo_score', ascending=False) opponents_df.to_csv("opponents_df.csv") if len(opponents_df)>10: slice_size = 4 slice = int(len(opponents_df)/slice_size) sample = opponents_df[slice:(slice_size-1)*slice].sample(frac=1).iloc[0] opponent, descriptor = sample["opponent"], sample["descriptor"] else: sample = opponents_df.sample(frac=1).iloc[0] opponent, descriptor = sample["opponent"], sample["descriptor"] if len(opponents_df) > 1: # Randomly select a opponent to compare with sample = opponents_df.sample(frac=1) comparison_opponent = sample.iloc[0] if comparison_opponent['opponent'] == opponent and comparison_opponent['descriptor'] == descriptor: comparison_opponent = sample.iloc[1] first_df = opponents_df[opponents_df["opponent"]==opponent][opponents_df["descriptor"]==descriptor] first_string = first_df["opponent"].tolist()[0]+" - "+first_df["descriptor"].tolist()[0] second_df = comparison_opponent second_string = second_df["opponent"]+" - "+second_df["descriptor"] return f"Do you like '{descriptor} - {opponent}' better than '{comparison_opponent['descriptor']} - {comparison_opponent['opponent']}'?", first_string, second_string, display_rankings(opponents_df) else: return "Add some opponents to start voting!", "", "", display_rankings(opponents_df) def display_rankings(opponents_df=pd.DataFrame(columns=['elo_score', 'descriptor', 'opponent'])): opponents_df = opponents_df.sort_values(by='elo_score', ascending=False) opponents_df = opponents_df[["elo_score", "descriptor", "opponent"]] opponents_df.to_csv("opponents_df.csv") return opponents_df def export_csv(opponents_df): # Function to export DataFrame to CSV save_df = opponents_df save_df.to_csv("opponents_df.csv") return "opponents_df.csv" def import_csv(file, opponents_df): if file is not None: #file_content = file.decode('utf-8') new_df = pd.read_csv(file) try: opponents_df = opponents_df[["elo_score", "descriptor", "opponent"]] except: opponents_df = pd.DataFrame(columns=['elo_score', 'descriptor', 'opponent']) new_df = new_df[["elo_score", "descriptor", "opponent"]] opponents_df = pd.concat([opponents_df,new_df]) opponents_df = opponents_df.drop_duplicates(subset=['descriptor', 'opponent']) return opponents_df # Function to remove a opponent def remove_opponent(descriptor, opponent, opponents_df): # Find and remove the opponent from the DataFrame descriptor = clean_string(descriptor) opponent = clean_string(opponent) opponents_df = opponents_df[~((opponents_df["descriptor"] == descriptor) & (opponents_df["opponent"] == opponent))] return opponents_df[["elo_score", "descriptor", "opponent"]] def reset_rankings(opponents_df): opponents_df["elo_score"] = [1000]*len(opponents_df) opponents_df = opponents_df[["elo_score", "descriptor", "opponent"]] return display_rankings(opponents_df) def clear_rankings(opponents_df): opponents_df = pd.DataFrame(columns=['elo_score', 'descriptor', 'opponent']) return display_rankings(opponents_df) # theme='Taithrah/Minimal' # Gradio interface theme = gr.themes.Soft(primary_hue="red", secondary_hue="blue") with gr.Blocks(theme=theme) as app: gr.Markdown( """## Preference-based Elo Ranker This tool helps you create **accurate rankings** of things based on your personal preferences. It does this by asking you questions comparing a random pair of your inpys, and then using your answers to calculate Elo scores for ranking. """ ) with gr.Row(): previews_df = pd.DataFrame(columns=['elo_score', 'descriptor', 'opponent']) previews = gr.DataFrame(value=previews_df, interactive=False, visible=False) with gr.Column(): gr.Markdown( """### Vote to Rank """ ) with gr.Row(): compare_output = gr.Textbox("Add some options to start voting!", label="Comparison", interactive=False, scale=3) with gr.Row(): yes_button = gr.Button("Yes", variant="secondary") no_button = gr.Button("No", variant="primary") new_vote = gr.Button("New Vote") with gr.Row(): with gr.Column(): compare_index_1 = gr.Textbox(label="",interactive=False, visible=False) with gr.Column(): compare_index_2 = gr.Textbox(label="",interactive=False, visible=False) with gr.Column(): gr.Markdown( """### Rankings """ ) opponents_df = pd.DataFrame(columns=['elo_score', 'descriptor', 'opponent']) rankings = gr.DataFrame(value=opponents_df, interactive=False, headers=["Score","descriptor", "opponent"]) gr.Markdown( """### Add Opponents """ ) with gr.Row(): descriptor_input = gr.Textbox(label="Type") opponent_input = gr.Textbox(label="Opponent") add_button = gr.Button("Add Opponent") add_button.click(add_and_compare, inputs=[descriptor_input, opponent_input, rankings], outputs=[descriptor_input, opponent_input, rankings]) gr.Markdown( """### Remove Opponents """ ) with gr.Row(): remove_descriptor_input = gr.Textbox(label="Type") remove_opponent_input = gr.Textbox(label="Opponent") remove_button = gr.Button("Remove opponent") remove_button.click(remove_opponent, inputs=[remove_descriptor_input, remove_opponent_input, rankings], outputs=rankings) gr.Markdown( """### Import and Export Rankings """ ) with gr.Row(): # Import CSV file to replace the existing DataFrame import_button = gr.File(label="Import CSV", file_count="single") import_button.change(fn=import_csv, inputs=[import_button, rankings], outputs=[rankings]) with gr.Column(): # Export button to download the DataFrame as CSV export_link = gr.File(label="Download CSV", file_count="single") export_button = gr.Button("Export as CSV") export_button.click(fn=export_csv, inputs=[rankings], outputs=export_link) gr.Markdown("### Reset Data") with gr.Row(): reset_button = gr.Button("Reset Scores") reset_button.click(reset_rankings, inputs=[rankings], outputs=rankings) clear_button = gr.Button("Clear Table", variant="primary") clear_button.click(clear_rankings, inputs=[rankings], outputs=rankings) # add_button.click(add_and_compare, inputs=[descriptor_input, opponent_input, rankings], outputs=[descriptor_input, opponent_input, rankings]) yes_button.click(update_ratings_pos, inputs=[compare_index_1, compare_index_2, rankings], outputs=[compare_output, compare_index_1, compare_index_2, rankings]) no_button.click(update_ratings_neg, inputs=[compare_index_1, compare_index_2, rankings], outputs=[compare_output, compare_index_1, compare_index_2, rankings]) new_vote.click(vote_startup, inputs=[rankings],outputs=[compare_output, compare_index_1, compare_index_2, rankings]) app.launch(share=False)