NOTE: Unfortunately, the widget below will not function on a static HTML page. If you are viewing this in GitHub or nbviewer, the only way to interact with it is to have Jupyter installed on your computer, download the file containing this notebook, and view it through Jupyter on your own computer.
A regularized logistic regression supplies a rating for each item as it tries to predict which items lead to a win. Using this information, we suggest useful alternatives to the most popular items used.
Try pairing up a guardian and a hunter in ranked, or compare recommendations between enemies in duel vs ranked mode.
Just remember, item use *correlating* with a win does not necessarily mean that the item helped *cause* the win!
In [1]:
import pandas as pd
from IPython.display import display, HTML, clear_output
from seaborn import light_palette
from ipywidgets import interact
import ipywidgets as widgets
import numpy as np
import os.path
def centered(html_string):
return(HTML('<center>{}</center>'.format(html_string)))
def color_it(s, color = "#bbdcdc"):
return('background-color: {}'.format(color))
def color_negative_red(val):
if isinstance(val, float):
color = '#d25349' if val < 0 else 'black'
else: color= 'black'
return('color: {}'.format(color))
def highlight_popular(val, popular_items):
if val not in popular_items:
weight = 'bold'
else: weight = 'normal'
return('font-weight: {}'.format(weight))
def itemstyle(df, pop_items, relic=False):
cm = light_palette("#7cbbbb", as_cmap=True)
output = df.style.background_gradient(cmap=cm)\
.applymap(highlight_popular, popular_items=pop_items)\
.applymap(color_negative_red)\
.format({'-Rating-': "{:.2f}",'Rating': "{:.2f}",'-Win Rate-': '{:.1%}', 'Win Rate': '{:.1%}'})
if relic == False:
output.format({'Rating/Cost': "{:.2f}",'Win Rate/Cost': '{:.3}'})
else:
output.format({"Paired": "{:.1%}",'-Paired-': '{:.1%}'})
return(centered(output.render()))
def recommendationstyle(df, pop_items):
cm = light_palette("#7cbbbb", as_cmap=True)
output = df.style.background_gradient(cmap=cm).applymap(color_negative_red)\
.applymap(highlight_popular, popular_items=pop_items)\
.format({'Win Rate': '{:.1%}', 'Win Rate/Cost': '{:.3}'})
return(centered(output.render()))
In [2]:
gods_lookup = pd.DataFrame.from_csv("SMITE_data/SMITE_Gods_All_Lookup.csv", index_col="Name")
god_names = list(gods_lookup.index)
def self_align(s):
""" Allows for text input to update dropdown widget"""
if self_text.value.title() in god_names:
self.value = self_text.value.title()
self_text = widgets.Text(placeholder="Enter a god and hit 'Enter'")
self = widgets.Dropdown(options=god_names, value='Agni', button_style='success')
self_text.on_submit(self_align)
def partner_align(s):
""" Allows for text input to update dropdown widget"""
if partner_text.value.title() in god_names:
partner.value = partner_text.value.title()
partner_text = widgets.Text(placeholder="Enter a god and hit 'Enter'")
partner = widgets.Dropdown(options=god_names, value='Agni', button_style='info')
partner_text.on_submit(partner_align)
godcardsHTML='<img src={} style="float:left; border-radius: 40px; border: 8px solid green;" width="380px" height="512px"/>'\
'<img src={} style="float:right; border-radius: 40px; border: 8px solid {};" width="380px" height="512px"/>'
def update(button):
""" pulls SmiteRecommender dfs based on widget input, and returns styled pandas dfs of results
needs SMITE_recommendations folder in the same directory to work.
"""
clear_output()
if toggle_gamemode.value == "casual":
print("No data for casual mode. Please try a different mode")
return
selfcard = gods_lookup.loc[self.value, "godCard_URL"]
partnercard = gods_lookup.loc[partner.value, "godCard_URL"]
partnercolor = "green" if toggle_friend.value == True else "darkred"
godcards.value = godcardsHTML.format(selfcard, partnercard, partnercolor)
god_id = gods_lookup.loc[self.value, "id"]
partner_id = gods_lookup.loc[partner.value, "id"]
friend = "_friend/" if toggle_friend.value == True else "_foe/"
path = "SMITE_recommendations/" + toggle_gamemode.value + friend
try:
fullpath = path + "{}-{}_info.txt".format(god_id, partner_id)
if os.path.getsize(fullpath) == 0:
print("Empty file found. Please try a different pairing.")
return
with open(fullpath, "rb") as f:
info_table = f.read().decode("utf-8")
print(info_table)
except OSError:
print("Pairing not allowed, or less than 100 matches.")
try:
recommendation = pd.DataFrame.from_csv(path + "{}-{}_recommendation.csv".format(god_id, partner_id), parse_dates=False).fillna(0)
recommendation.index.name = ''
recommendation.columns = ["Recommendation", "Win Rate", "Win Rate/Cost"]
items = pd.DataFrame.from_csv(path + "{}-{}_items.csv".format(god_id, partner_id), index_col= None, parse_dates=False).fillna(0)
items.columns = ["Most Popular", "-Rating-", "-Win Rate-", "Most Recommended", "Rating", "Win Rate", "Cost Adjusted", "Rating/Cost", "Win Rate/Cost"]
relics = pd.DataFrame.from_csv(path + "{}-{}_relics.csv".format(god_id, partner_id), index_col= None, parse_dates=False).fillna(0)
relics.columns = ["Most Popular", "-Rating-", "-Win Rate-", "-Paired-", "Most Recommended", "Rating", "Win Rate", "Paired"]
relics.loc[1,"-Paired-"]=relics.loc[0,"-Paired-"]
relics.loc[1,"Paired"]=relics.loc[0,"Paired"]
pop_items = list(items["Most Popular"].values) + list(relics["Most Popular"].values)
display(recommendationstyle(recommendation, pop_items))
display(itemstyle(items, pop_items))
display(itemstyle(relics, pop_items, relic=True))
except OSError:
print("Unable to get recommendation. Please try a different pairing.")
In [3]:
toggle_friend = widgets.ToggleButtons(options={'Friend': True, 'Foe': False},margin = '10px')
toggle_gamemode = widgets.ToggleButtons(options={'Ranked' : "ranked", 'Casual' : "casual", 'Joust' : "joust", "Duel": "duel"}, margin = '10px')
button = widgets.Button(description='Get Recommendation', button_style='warning', pack= 'center', margin= '0 243px 30px 243px')
center = widgets.Layout(align_self="center",justify_content= 'center', width= "50%")
firstrow = widgets.HBox(children=[toggle_friend, toggle_gamemode], layout=center)
secondrow = widgets.HBox(children=[self, self_text], layout=center)
thirdrow = widgets.HBox(children=[partner, partner_text], layout=center)
button = widgets.Button(description='Get Recommendation', button_style='warning',layout=center)
godcards = widgets.HTML(value=None)
In [4]:
button.on_click(update)
recommender_widget = widgets.VBox(children=[firstrow, secondrow, thirdrow, button], layout=widgets.Layout(margin = "25px"))
display(recommender_widget)
display(godcards)
In [5]:
# found from a stackoverflow answer: http://tinyurl.com/zwl2wtl
HTML('''<script>
code_show=true;
function code_toggle() {
if (code_show){
$('div.input').hide();
} else {
$('div.input').show();
}
code_show = !code_show
}
$( document ).ready(code_toggle);
</script>
<center><form action="javascript:code_toggle()"><input type="submit" value="View/Hide code cells."></form><center>''')
Out[5]:
Recommendations are made by replacing the two popular items with the worst rating with the best two new items from the cost adjusted rating. This is an imperfect approach, but does a decent job most of the time.
Note that item use correlating with a win/loss does not necessarily mean that the item helped cause the win/loss, and that these recommendations are based only off of end game data.
Win-more items have a high rating and win rate, because having them is a good predictor that you won the game. However, being ahead is probably what causes you to buy expensive items; buying expensive items is not in and of itself going to cause you to win (quite the opposite).
Starter items are meant to be replaced by more powerful items later in the game. Having a starter item at the end of the game is a good predictor that you lost (meaning it has a negative rating). It likely didn't cause the loss, it's simply a good indicator that you were behind in gold and experience relative to your opponents.
As a final example, a relic like Sanctuary or Purification can have a negative rating but high popularity. This could be because getting the relic is necessary in certain matchups (like against hard CC), but you are still likely to lose. In this case, getting the relic correlates with the specific pairing, and the specific pairing correlates with a poor win rate, so the relic correlates with, but is not responsible for, a poor win rate.