Spaces:
Sleeping
Sleeping
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(songs_df): | |
try: | |
songs_df = songs_df[["elo_score", "artist", "song_title"]] | |
except: | |
songs_df = pd.DataFrame(columns=['elo_score', 'artist', 'song_title']) | |
if len(songs_df)>0: | |
if len(songs_df>10): | |
slice_size = 4 | |
slice = int(len(songs_df)/slice_size) | |
sample = songs_df[slice:(slice_size-1)*slice].sample(frac=1).iloc[0] | |
song_title, artist = sample["song_title"], sample["artist"] | |
else: | |
sample = songs_df.sample(frac=1).iloc[0] | |
song_title, artist = sample["song_title"], sample["artist"] | |
if len(songs_df) > 1: | |
# Randomly select a song to compare with | |
sample = songs_df.sample(frac=1) | |
comparison_song = sample.iloc[0] | |
if comparison_song['song_title'] == song_title and comparison_song['artist'] == artist: | |
comparison_song = sample.iloc[1] | |
first_df = songs_df[songs_df["song_title"]==song_title][songs_df["artist"]==artist] | |
first_string = first_df["song_title"].tolist()[0]+" - "+first_df["artist"].tolist()[0] | |
second_df = comparison_song | |
second_string = second_df["song_title"]+" - "+second_df["artist"] | |
return f"Do you like '{artist} - {song_title}' better than '{comparison_song['artist']} - {comparison_song['song_title']}'?", first_string, second_string, display_rankings(songs_df) | |
else: | |
return "Add some songs to start voting!", "", "", display_rankings(songs_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(artist, song_title, songs_df): | |
try: | |
songs_df = songs_df[["elo_score", "artist", "song_title"]] | |
except: | |
songs_df = pd.DataFrame(columns=['elo_score', 'artist', 'song_title']) | |
if artist != "" and song_title != "": | |
artist = clean_string(artist) | |
song_title = clean_string(song_title) | |
new_song = pd.DataFrame({'artist': [artist], 'song_title': [song_title], 'elo_score': [1000]}) | |
songs_df = pd.concat([songs_df, new_song], ignore_index=True) | |
songs_df.to_csv("songs_df.csv") | |
songs_df = songs_df[["elo_score", "artist", "song_title"]] | |
return "", "", display_rankings(songs_df) | |
# Function to update Elo ratings based on user's choice | |
def update_ratings_pos(first_string, second_string, songs_df): | |
try: | |
songs_df = songs_df[["elo_score", "artist", "song_title"]] | |
except: | |
songs_df = pd.DataFrame(columns=['elo_score', 'artist', 'song_title']) | |
if len(songs_df)==0: | |
return "Add some songs to start voting!", "", "", display_rankings(songs_df) | |
if first_string != "": | |
songs_df["combined"] = songs_df["song_title"] + " - " + songs_df["artist"] | |
loser = songs_df[songs_df["combined"] == second_string] | |
winner = songs_df[songs_df["combined"] == first_string] | |
# Update Elo scores | |
winner_score, loser_score = update_scores(winner['elo_score'].values[0], loser['elo_score'].values[0]) | |
songs_df.at[winner.index[0], 'elo_score'] = winner_score | |
songs_df.at[loser.index[0], 'elo_score'] = loser_score | |
songs_df = songs_df.sort_values(by='elo_score', ascending=False) | |
songs_df.to_csv("songs_df.csv") | |
if len(songs_df>10): | |
slice_size = 4 | |
slice = int(len(songs_df)/slice_size) | |
sample = songs_df[slice:(slice_size-1)*slice].sample(frac=1).iloc[0] | |
song_title, artist = sample["song_title"], sample["artist"] | |
else: | |
sample = songs_df.sample(frac=1).iloc[0] | |
song_title, artist = sample["song_title"], sample["artist"] | |
if len(songs_df) > 1: | |
# Randomly select a song to compare with | |
sample = songs_df.sample(frac=1) | |
comparison_song = sample.iloc[0] | |
if comparison_song['song_title'] == song_title and comparison_song['artist'] == artist: | |
comparison_song = sample.iloc[1] | |
first_df = songs_df[songs_df["song_title"]==song_title][songs_df["artist"]==artist] | |
first_string = first_df["song_title"].tolist()[0]+" - "+first_df["artist"].tolist()[0] | |
second_df = comparison_song | |
second_string = second_df["song_title"]+" - "+second_df["artist"] | |
return f"Do you like '{artist} - {song_title}' better than '{comparison_song['artist']} - {comparison_song['song_title']}'?", first_string, second_string, display_rankings(songs_df) | |
else: | |
return "Add some songs to start voting!", "", "", display_rankings(songs_df) | |
# Function to update Elo ratings based on user's choice | |
def update_ratings_neg(first_string, second_string, songs_df): | |
try: | |
songs_df = songs_df[["elo_score", "artist", "song_title"]] | |
except: | |
songs_df = pd.DataFrame(columns=['elo_score', 'artist', 'song_title']) | |
if len(songs_df)==0: | |
return "Add some songs to start voting!", "", "", display_rankings(songs_df) | |
if first_string != "": | |
songs_df["combined"] = songs_df["song_title"] + " - " + songs_df["artist"] | |
loser = songs_df[songs_df["combined"] == first_string] | |
winner = songs_df[songs_df["combined"] == second_string] | |
# Update Elo scores | |
winner_score, loser_score = update_scores(winner['elo_score'].values[0], loser['elo_score'].values[0]) | |
songs_df.at[winner.index[0], 'elo_score'] = winner_score | |
songs_df.at[loser.index[0], 'elo_score'] = loser_score | |
songs_df = songs_df.sort_values(by='elo_score', ascending=False) | |
songs_df.to_csv("songs_df.csv") | |
if len(songs_df>10): | |
slice_size = 4 | |
slice = int(len(songs_df)/slice_size) | |
sample = songs_df[slice:(slice_size-1)*slice].sample(frac=1).iloc[0] | |
song_title, artist = sample["song_title"], sample["artist"] | |
else: | |
sample = songs_df.sample(frac=1).iloc[0] | |
song_title, artist = sample["song_title"], sample["artist"] | |
if len(songs_df) > 1: | |
# Randomly select a song to compare with | |
sample = songs_df.sample(frac=1) | |
comparison_song = sample.iloc[0] | |
if comparison_song['song_title'] == song_title and comparison_song['artist'] == artist: | |
comparison_song = sample.iloc[1] | |
first_df = songs_df[songs_df["song_title"]==song_title][songs_df["artist"]==artist] | |
first_string = first_df["song_title"].tolist()[0]+" - "+first_df["artist"].tolist()[0] | |
second_df = comparison_song | |
second_string = second_df["song_title"]+" - "+second_df["artist"] | |
return f"Do you like '{artist} - {song_title}' better than '{comparison_song['artist']} - {comparison_song['song_title']}'?", first_string, second_string, display_rankings(songs_df) | |
else: | |
return "Add some songs to start voting!", "", "", display_rankings(songs_df) | |
def display_rankings(songs_df=pd.DataFrame(columns=['elo_score', 'artist', 'song_title'])): | |
songs_df = songs_df.sort_values(by='elo_score', ascending=False) | |
songs_df = songs_df[["elo_score", "artist", "song_title"]] | |
songs_df.to_csv("songs_df.csv") | |
return songs_df | |
def export_csv(songs_df): | |
# Function to export DataFrame to CSV | |
save_df = songs_df | |
save_df.to_csv("songs_df.csv") | |
return "songs_df.csv" | |
def import_csv(file, songs_df): | |
if file is not None: | |
#file_content = file.decode('utf-8') | |
new_df = pd.read_csv(file) | |
try: | |
songs_df = songs_df[["elo_score", "artist", "song_title"]] | |
except: | |
songs_df = pd.DataFrame(columns=['elo_score', 'artist', 'song_title']) | |
new_df = new_df[["elo_score", "artist", "song_title"]] | |
songs_df = pd.concat([songs_df,new_df]) | |
songs_df = songs_df.drop_duplicates(subset=['artist', 'song_title']) | |
return songs_df | |
# Function to remove a song | |
def remove_song(artist, song_title, songs_df): | |
# Find and remove the song from the DataFrame | |
artist = clean_string(artist) | |
song_title = clean_string(song_title) | |
songs_df = songs_df[~((songs_df["artist"] == artist) & (songs_df["song_title"] == song_title))] | |
return songs_df[["elo_score", "artist", "song_title"]] | |
def reset_rankings(songs_df): | |
songs_df["elo_score"] = [1000]*len(songs_df) | |
songs_df = songs_df[["elo_score", "artist", "song_title"]] | |
return display_rankings(songs_df) | |
def clear_rankings(songs_df): | |
songs_df = pd.DataFrame(columns=['elo_score', 'artist', 'song_title']) | |
return display_rankings(songs_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', 'artist', 'song_title']) | |
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 | |
""" | |
) | |
songs_df = pd.DataFrame(columns=['elo_score', 'artist', 'song_title']) | |
rankings = gr.DataFrame(value=songs_df, interactive=False, headers=["Score","Artist", "Song"]) | |
with gr.Row(): | |
artist_input = gr.Textbox(label="Artist") | |
song_title_input = gr.Textbox(label="Song Title") | |
add_button = gr.Button("Add Song") | |
add_button.click(add_and_compare, inputs=[artist_input, song_title_input, rankings], outputs=[artist_input, song_title_input, rankings]) | |
gr.Markdown( | |
"""### Remove Songs | |
""" | |
) | |
with gr.Row(): | |
remove_artist_input = gr.Textbox(label="Artist") | |
remove_song_title_input = gr.Textbox(label="Song Title") | |
remove_button = gr.Button("Remove Song") | |
remove_button.click(remove_song, inputs=[remove_artist_input, remove_song_title_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=[artist_input, song_title_input, rankings], outputs=[artist_input, song_title_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) |