Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import pandas as pd | |
| import re | |
| import csv | |
| 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_criteria(criteria_df): | |
| if len(criteria_df) > 1: | |
| sample = criteria_df.sample(n=2) | |
| first_string = sample.iloc[0]["criteria"] | |
| second_string = sample.iloc[1]["criteria"] | |
| return f"Is '{first_string}' more important than '{second_string}'?", first_string, second_string, display_criteria_rankings(criteria_df) | |
| else: | |
| return "Add more criteria to start ranking!", "", "", display_criteria_rankings(criteria_df) | |
| def vote_startup_opponents(opponents_df, criteria_df): | |
| try: | |
| opponents_df = opponents_df[["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]] | |
| except: | |
| opponents_df = pd.DataFrame(columns=["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]) | |
| 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: | |
| 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"] | |
| criteria = criteria_df.sample(n=1)["criteria"].values[0] | |
| return f"Which opponent better represents '{criteria}': '{descriptor} - {opponent}' or '{comparison_opponent['descriptor']} - {comparison_opponent['opponent']}'?", first_string, second_string, criteria, display_rankings(opponents_df, criteria_df) | |
| else: | |
| return "Add some opponents to start voting!", "", "", "", display_rankings(opponents_df, criteria_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, criteria_df): | |
| try: | |
| opponents_df = opponents_df[["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]] | |
| except: | |
| opponents_df = pd.DataFrame(columns=["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]) | |
| if descriptor != "" and opponent != "": | |
| descriptor = clean_string(descriptor) | |
| opponent = clean_string(opponent) | |
| new_opponent = pd.DataFrame({'descriptor': [descriptor], 'opponent': [opponent]}) | |
| for c in criteria_df["criteria"]: | |
| new_opponent[f"{c}_score"] = 1000 | |
| new_opponent["overall_score"] = 1000 | |
| opponents_df = pd.concat([opponents_df, new_opponent], ignore_index=True) | |
| opponents_df.to_csv("opponents_df.csv") | |
| opponents_df = opponents_df[["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]] | |
| return "", "", display_rankings(opponents_df, criteria_df) | |
| def update_ratings_pos(first_string, second_string, criteria, opponents_df, criteria_df): | |
| try: | |
| opponents_df = opponents_df[["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]] | |
| except: | |
| opponents_df = pd.DataFrame(columns=["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]) | |
| if len(opponents_df) == 0: | |
| return "Add some opponents to start voting!", "", "", "", display_rankings(opponents_df, criteria_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] | |
| winner_score, loser_score = update_scores(winner[f"{criteria}_score"].values[0], loser[f"{criteria}_score"].values[0]) | |
| opponents_df.at[winner.index[0], f"{criteria}_score"] = winner_score | |
| opponents_df.at[loser.index[0], f"{criteria}_score"] = loser_score | |
| opponents_df = calculate_overall_scores(opponents_df, criteria_df) | |
| opponents_df.to_csv("opponents_df.csv") | |
| return vote_startup_opponents(opponents_df, criteria_df) | |
| def update_ratings_neg(first_string, second_string, criteria, opponents_df, criteria_df): | |
| try: | |
| opponents_df = opponents_df[["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]] | |
| except: | |
| opponents_df = pd.DataFrame(columns=["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]) | |
| if len(opponents_df) == 0: | |
| return "Add some opponents to start voting!", "", "", "", display_rankings(opponents_df, criteria_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] | |
| winner_score, loser_score = update_scores(winner[f"{criteria}_score"].values[0], loser[f"{criteria}_score"].values[0]) | |
| opponents_df.at[winner.index[0], f"{criteria}_score"] = winner_score | |
| opponents_df.at[loser.index[0], f"{criteria}_score"] = loser_score | |
| opponents_df = calculate_overall_scores(opponents_df, criteria_df) | |
| opponents_df.to_csv("opponents_df.csv") | |
| return vote_startup_opponents(opponents_df, criteria_df) | |
| def display_rankings(opponents_df, criteria_df): | |
| opponents_df = opponents_df.sort_values(by='overall_score', ascending=False) | |
| opponents_df = opponents_df[["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]] | |
| opponents_df.to_csv("opponents_df.csv") | |
| return opponents_df | |
| def export_csv(opponents_df): | |
| save_df = opponents_df | |
| save_df.to_csv("opponents_df.csv") | |
| return "opponents_df.csv" | |
| def import_csv(file, opponents_df, criteria_df): | |
| if file is not None: | |
| new_df = pd.read_csv(file) | |
| try: | |
| opponents_df = opponents_df[["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]] | |
| except: | |
| opponents_df = pd.DataFrame(columns=["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]) | |
| new_df = new_df[["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]] | |
| opponents_df = pd.concat([opponents_df, new_df]) | |
| opponents_df = opponents_df.drop_duplicates(subset=['descriptor', 'opponent']) | |
| return opponents_df | |
| def remove_opponent(descriptor, opponent, opponents_df): | |
| descriptor = clean_string(descriptor) | |
| opponent = clean_string(opponent) | |
| opponents_df = opponents_df[~((opponents_df["descriptor"] == descriptor) & (opponents_df["opponent"] == opponent))] | |
| return opponents_df[["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]] | |
| def reset_rankings(opponents_df, criteria_df): | |
| for c in criteria_df["criteria"]: | |
| opponents_df[f"{c}_score"] = 1000 | |
| opponents_df["overall_score"] = 1000 | |
| opponents_df = opponents_df[["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]] | |
| return display_rankings(opponents_df, criteria_df) | |
| def clear_rankings(opponents_df, criteria_df): | |
| opponents_df = pd.DataFrame(columns=["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]) | |
| return display_rankings(opponents_df, criteria_df) | |
| def add_criteria(criteria, criteria_df): | |
| if criteria != "": | |
| criteria = clean_string(criteria) | |
| new_criteria = pd.DataFrame({'criteria': [criteria], 'score': [1000]}) | |
| criteria_df = pd.concat([criteria_df, new_criteria], ignore_index=True) | |
| criteria_df.to_csv("criteria_df.csv") | |
| criteria_df = criteria_df[["score", "criteria"]] | |
| criteria_df = criteria_df.dropna() | |
| return "", display_criteria_rankings(criteria_df) | |
| def remove_criteria(criteria, criteria_df): | |
| criteria = clean_string(criteria) | |
| criteria_df = criteria_df[criteria_df["criteria"] != criteria] | |
| return display_criteria_rankings(criteria_df) | |
| def update_criteria_ratings_pos(first_string, second_string, criteria_df): | |
| if len(criteria_df) == 0: | |
| return "Add some criteria to start ranking!", "", "", display_criteria_rankings(criteria_df) | |
| if first_string != "": | |
| loser = criteria_df[criteria_df["criteria"] == second_string] | |
| winner = criteria_df[criteria_df["criteria"] == first_string] | |
| winner_score, loser_score = update_scores(winner['score'].values[0], loser['score'].values[0]) | |
| criteria_df.at[winner.index[0], 'score'] = winner_score | |
| criteria_df.at[loser.index[0], 'score'] = loser_score | |
| criteria_df = criteria_df.sort_values(by='score', ascending=False) | |
| criteria_df.to_csv("criteria_df.csv") | |
| return vote_startup_criteria(criteria_df) | |
| def update_criteria_ratings_neg(first_string, second_string, criteria_df): | |
| if len(criteria_df) == 0: | |
| return "Add some criteria to start ranking!", "", "", display_criteria_rankings(criteria_df) | |
| if first_string != "": | |
| loser = criteria_df[criteria_df["criteria"] == first_string] | |
| winner = criteria_df[criteria_df["criteria"] == second_string] | |
| winner_score, loser_score = update_scores(winner['score'].values[0], loser['score'].values[0]) | |
| criteria_df.at[winner.index[0], 'score'] = winner_score | |
| criteria_df.at[loser.index[0], 'score'] = loser_score | |
| criteria_df = criteria_df.sort_values(by='score', ascending=False) | |
| criteria_df.to_csv("criteria_df.csv") | |
| return vote_startup_criteria(criteria_df) | |
| def display_criteria_rankings(criteria_df): | |
| criteria_df = criteria_df.sort_values(by='score', ascending=False) | |
| criteria_df = criteria_df[["score", "criteria"]] | |
| criteria_df.to_csv("criteria_df.csv") | |
| return criteria_df | |
| def calculate_overall_scores(opponents_df, criteria_df): | |
| criteria_scores = criteria_df.set_index("criteria")["score"] | |
| new_scores = [] | |
| for _, row in opponents_df.iterrows(): | |
| overall_score = 0 | |
| total_weight = 0 | |
| for c in criteria_df["criteria"]: | |
| weight = criteria_scores[c] | |
| score = row[f"{c}_score"] | |
| overall_score += weight * score | |
| total_weight += weight | |
| # opponents_df.at[row.name, "overall_score"] = overall_score / total_weight | |
| score = overall_score / total_weight | |
| new_scores.append(score) | |
| opponents_df["overall_score"] = new_scores | |
| return opponents_df | |
| 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 inputs, and then using your | |
| answers to calculate Elo scores for ranking. | |
| """ | |
| ) | |
| with gr.Tab("Criteria Ranking"): | |
| gr.Markdown( | |
| """### Rank Criteria | |
| Add and rank the criteria that will be used to evaluate the opponents. | |
| """ | |
| ) | |
| with gr.Row(): | |
| criteria_input = gr.Textbox(label="Criteria") | |
| add_criteria_button = gr.Button("Add Criteria") | |
| with gr.Row(): | |
| remove_criteria_input = gr.Textbox(label="Criteria") | |
| remove_criteria_button = gr.Button("Remove Criteria") | |
| criteria_df = pd.DataFrame(columns=['score', 'criteria']) | |
| criteria_rankings = gr.DataFrame(value=criteria_df, interactive=False, headers=["Score", "Criteria"]) | |
| with gr.Row(): | |
| criteria_compare_output = gr.Textbox("Add some criteria to start ranking!", label="Comparison", interactive=False) | |
| with gr.Row(): | |
| criteria_yes_button = gr.Button("Yes", variant="secondary") | |
| criteria_no_button = gr.Button("No", variant="primary") | |
| with gr.Row(): | |
| with gr.Column(): | |
| criteria_compare_index_1 = gr.Textbox(label="", interactive=False, visible=False) | |
| with gr.Column(): | |
| criteria_compare_index_2 = gr.Textbox(label="", interactive=False, visible=False) | |
| criteria_new_vote = gr.Button("New Vote") | |
| add_criteria_button.click(add_criteria, inputs=[criteria_input, criteria_rankings], outputs=[criteria_input, criteria_rankings]) | |
| remove_criteria_button.click(remove_criteria, inputs=[remove_criteria_input, criteria_rankings], outputs=criteria_rankings) | |
| criteria_yes_button.click(update_criteria_ratings_pos, inputs=[criteria_compare_index_1, criteria_compare_index_2, criteria_rankings], outputs=[criteria_compare_output, criteria_compare_index_1, criteria_compare_index_2, criteria_rankings]) | |
| criteria_no_button.click(update_criteria_ratings_neg, inputs=[criteria_compare_index_1, criteria_compare_index_2, criteria_rankings], outputs=[criteria_compare_output, criteria_compare_index_1, criteria_compare_index_2, criteria_rankings]) | |
| criteria_new_vote.click(vote_startup_criteria, inputs=[criteria_rankings], outputs=[criteria_compare_output, criteria_compare_index_1, criteria_compare_index_2, criteria_rankings]) | |
| with gr.Tab("Opponent Ranking"): | |
| with gr.Row(): | |
| previews_df = pd.DataFrame(columns=["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]) | |
| 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) | |
| with gr.Row(): | |
| yes_button = gr.Button("1", variant="secondary") | |
| no_button = gr.Button("2", variant="primary") | |
| with gr.Row(): | |
| criteria_output = gr.Textbox(label="Criteria", interactive=False) | |
| 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=["descriptor", "opponent"] + [f"{c}_score" for c in criteria_df["criteria"]] + ["overall_score"]) | |
| rankings = gr.DataFrame(value=opponents_df, interactive=False, headers=["Descriptor", "Opponent"] + [f"{c} Score" for c in criteria_df["criteria"]] + ["Overall Score"]) | |
| gr.Markdown( | |
| """### Add Opponents | |
| """ | |
| ) | |
| with gr.Row(): | |
| descriptor_input = gr.Textbox(label="Descriptor") | |
| opponent_input = gr.Textbox(label="Opponent") | |
| add_button = gr.Button("Add Opponent") | |
| add_button.click(add_and_compare, inputs=[descriptor_input, opponent_input, rankings, criteria_rankings], outputs=[descriptor_input, opponent_input, rankings]) | |
| gr.Markdown( | |
| """### Remove Opponents | |
| """ | |
| ) | |
| with gr.Row(): | |
| remove_descriptor_input = gr.Textbox(label="Descriptor") | |
| 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_button = gr.File(label="Import CSV", file_count="single") | |
| import_button.change(fn=import_csv, inputs=[import_button, rankings, criteria_rankings], outputs=[rankings]) | |
| with gr.Column(): | |
| 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, criteria_rankings], outputs=rankings) | |
| clear_button = gr.Button("Clear Table", variant="primary") | |
| clear_button.click(clear_rankings, inputs=[rankings, criteria_rankings], outputs=rankings) | |
| yes_button.click(update_ratings_pos, inputs=[compare_index_1, compare_index_2, criteria_output, rankings, criteria_rankings], outputs=[compare_output, compare_index_1, compare_index_2, criteria_output, rankings]) | |
| no_button.click(update_ratings_neg, inputs=[compare_index_1, compare_index_2, criteria_output, rankings, criteria_rankings], outputs=[compare_output, compare_index_1, compare_index_2, criteria_output, rankings]) | |
| new_vote.click(vote_startup_opponents, inputs=[rankings, criteria_rankings], outputs=[compare_output, compare_index_1, compare_index_2, criteria_output, rankings]) | |
| app.launch(share=False) |