Skip to content

Commit

Permalink
add champion model
Browse files Browse the repository at this point in the history
  • Loading branch information
danReynolds committed Jan 16, 2017
1 parent 4752e76 commit 44deb86
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 215 deletions.
115 changes: 46 additions & 69 deletions app/controllers/champions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ def ranking
end

def stats
stats = @champion[:stats]
name = @champion.name
stats = @champion.stats
stat = champion_params[:stat]
level = champion_params[:level].to_i
stat_value = stats[stat]
Expand All @@ -58,19 +59,19 @@ def stats

render json: {
speech: (
"#{@name} has #{stat_value.round} #{stat_name}#{level_message}."
"#{name} has #{stat_value.round} #{stat_name}#{level_message}."
)
}
end

def description
play_style = @champion[:tags].en.conjunction
roles = @champion[:champion_gg].map { |variant| variant[:role] }
play_style = @champion.tags.en.conjunction
roles = @champion.roles.map { |variant| variant[:role] }
.en.conjunction(article: false)

render json: {
speech: (
"#{@name}, the #{@champion[:title]}, is #{play_style} and " \
"#{@champion.name}, the #{@champion.title}, is #{play_style} and " \
"is played as #{roles}."
)
}
Expand All @@ -80,7 +81,7 @@ def ability_order
order = parse_ability_order(@role_data[:skills][:highestWinPercent][:order])
render json: {
speech: (
"The highest win rate on #{@name} #{@role} has you start " \
"The highest win rate on #{@champion.name} #{@role} has you start " \
"#{order[:firstOrder].join(', ')} and then max " \
"#{order[:maxOrder].join(', ')}."
)
Expand All @@ -93,29 +94,33 @@ def build
end.en.conjunction(article: false)

render json: {
speech: "The highest win rate build for #{@name} #{@role} is #{build}."
speech: (
"The highest win rate build for #{@champion.name} #{@role} is #{build}."
)
}
end

def matchup
role = champion_params[:lane]
champion_query = champion_params[:champion1].strip
unless other_champion = RiotApi.get_champion(champion_query)
render json: champion_not_found_response(champion_query)
other_champion = Champion.new(name: champion_query)

unless other_champion.valid?
render json: { speech: other_champion.error_message }
return false
end

shared_roles = @champion[:champion_gg].map do |role_data|
shared_roles = @champion.roles.map do |role_data|
role_data[:role]
end & other_champion[:champion_gg].map do |role_data|
end & other_champion.roles.map do |role_data|
role_data[:role]
end

if shared_roles.length.zero? || !role.blank? && !shared_roles.include?(role)
return render json: {
speech: (
"#{@name} and #{other_champion[:name]} do not typically play " \
"against eachother in #{role.blank? ? 'any role' : role}."
"#{@champion.name} and #{other_champion.name} do not typically " \
"play against eachother in #{role.blank? ? 'any role' : role}."
)
}
end
Expand All @@ -128,19 +133,19 @@ def matchup
end
end

champion_role = find_by_role(@champion, role)
other_champion_role = find_by_role(other_champion, role)
champion_role = @champion.find_by_role(role)
other_champion_role = other_champion.find_by_role(role)

matchup = champion_role[:matchups].detect do |matchup|
matchup[:key] == other_champion[:key]
matchup[:key] == other_champion.key
end
change = matchup[:winRateChange] > 0 ? 'better' : 'worse'

return render json: {
speech: (
"#{@name} got #{change} against #{other_champion[:name]} in the " \
"latest patch and has a win rate of #{matchup[:winRate]}% against " \
"#{other_champion[:title]} in #{role}."
"#{@champion.name} got #{change} against #{other_champion.name} in " \
"the latest patch and has a win rate of #{matchup[:winRate]}% " \
"against #{other_champion.title} in #{role}."
)
}
end
Expand All @@ -159,19 +164,22 @@ def counters
"#{counter_name} at a #{(100 - counter[:winRate]).round(2)}% win rate"
end.en.conjunction(article: false)
render json: {
speech: "The best #{list_message}counters for #{@name} #{@role} are " \
"#{counters}."
speech: (
"The best #{list_message}counters for #{@champion.name} " \
"#{@role} are #{counters}."
)
}
end

def lane
overall = @role_data[:overallPosition]
role_size = Rails.cache.read(rankings: @role).length.en.numwords
change = overall[:change] > 0 ? 'better' : 'worse'

render json: {
speech: (
"#{@name} got #{change} in the last patch and is currently ranked " \
"#{overall[:position].en.ordinate} with a " \
"#{@champion.name} got #{change} in the last patch and is currently " \
"ranked #{overall[:position].en.ordinate} out of #{role_size} with a " \
"#{@role_data[:patchWin].last}% win rate and a " \
"#{@role_data[:patchPlay].last}% play rate as #{@role}."
)
Expand All @@ -181,70 +189,54 @@ def lane
def ability
ability = champion_params[:ability].to_sym
if ability == :passive
spell = @champion[:passive]
spell = @champion.passive
else
spell = @champion[:spells][RiotApi::ABILITIES[ability]]
spell = @champion.spells[RiotApi::ABILITIES[ability]]
end

render json: {
speech: (
"#{@name}'s #{ability} ability is called " \
"#{@champion.name}'s #{ability} ability is called " \
"#{spell[:name]}. #{spell[:sanitizedDescription]}"
)
}
end

def cooldown
ability = champion_params[:ability].to_sym
spell = @champion[:spells][RiotApi::ABILITIES[ability]]
spell = @champion.spells[RiotApi::ABILITIES[ability]]
rank = champion_params[:rank].split(' ').last.to_i

render json: {
speech: (
"#{@name}'s #{ability} ability, #{spell[:name]}, has a cooldown of " \
"#{spell[:cooldown][rank - 1].to_i} seconds at rank #{rank}."
"#{@champion.name}'s #{ability} ability, #{spell[:name]}, has a " \
"cooldown of #{spell[:cooldown][rank - 1].to_i} seconds at rank #{rank}."
)
}
end

def title
render json: {
speech: "#{@name}'s title is #{@champion[:title]}."
speech: "#{@champion.name}'s title is #{@champion.title}."
}
end

def ally_tips
tip = remove_html_tags(@champion[:allytips].sample.to_s)
tip = remove_html_tags(@champion.allytips.sample.to_s)
render json: {
speech: "Here's a tip for playing as #{@name}: #{tip}"
speech: "Here's a tip for playing as #{@champion.name}: #{tip}"
}
end

def enemy_tips
tip = remove_html_tags(@champion[:enemytips].sample.to_s)
tip = remove_html_tags(@champion.enemytips.sample.to_s)
render json: {
speech: "Here's a tip for playing against #{@name}: #{tip}"
speech: "Here's a tip for playing against #{@champion.name}: #{tip}"
}
end

private

def find_by_role(champion, role)
champion_gg = champion[:champion_gg]
if role.blank?
if champion_gg.length == 1
champion_role = champion_gg.first
return champion_role
else
return nil
end
end

champion_gg.detect do |champion_data|
champion_data[:role] == role
end
end

def parse_ability_order(abilities)
first_abilities = abilities.first(3)

Expand All @@ -267,18 +259,11 @@ def remove_html_tags(speech)
end

def load_champion
champion_query = champion_params[:champion].strip
if champion_query.blank?
render json: no_champion_specified_response
return false
end

unless @champion = RiotApi.get_champion(champion_query)
render json: champion_not_found_response(champion_query)
@champion = Champion.new(name: champion_params[:champion])
unless @champion.valid?
render json: { speech: @champion.error_message }
return false
end

@name = @champion[:name]
end

def do_not_play_response(name, role)
Expand All @@ -292,14 +277,6 @@ def do_not_play_response(name, role)
}
end

def no_champion_specified_response
{ speech: 'What champion are you looking for?' }
end

def champion_not_found_response(name)
{ speech: "I could not find a champion called '#{name}'." }
end

def ask_for_role_response
{ speech: 'What role are they in?' }
end
Expand All @@ -310,7 +287,7 @@ def ask_for_level_response

def verify_role
@role = champion_params[:lane]
unless @role_data = find_by_role(@champion, @role)
unless @role_data = @champion.find_by_role(@role)
if @role.blank?
render json: ask_for_role_response
else
Expand Down
31 changes: 25 additions & 6 deletions app/controllers/summoners_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class SummonersController < ApplicationController
include RiotApi
before_action :load_summoner
before_action :load_champion, only: :champion

BEST_CHAMPION_SIZE = 3

Expand All @@ -22,6 +23,14 @@ def show
}
end

def champion
name = @summoner.name
id = @summoner.id
region = @region.region

summoner_champions = RiotApi.get_summoner_champions(id: id, region: region)
end

private

def no_games_response
Expand All @@ -43,19 +52,29 @@ def summoner_stats_message(summoner_stats)

def summoner_champions_message(summoner_champions)
champions = Rails.cache.read(:champions)
summoner_champions.first(BEST_CHAMPION_SIZE).each do |champion|
details = champions.detect { |_, data| data[:id] == champion[:id] }
champion[:name] = details.last[:name]
end.map do |champion|

summoner_champions.sort do |champ1, champ2|
champ2[:stats][:totalSessionsPlayed] <=> champ1[:stats][:totalSessionsPlayed]
end.first(BEST_CHAMPION_SIZE).map do |champion|
name = champions.values.detect do |data|
data[:id] == champion[:id]
end[:name]

stats = champion[:stats]
winrate = stats[:totalSessionsWon] / stats[:totalSessionsPlayed].to_f * 100
"#{winrate.round(2)}% win rate on #{champion[:name]} in " \
"#{winrate.round(2)}% win rate on #{name} in " \
"#{stats[:totalSessionsPlayed]} games"
end.en.conjunction
end

def summoner_params
params.require(:result).require(:parameters).permit(:summoner, :region)
params.require(:result).require(:parameters).permit(
:summoner, :region, :champion
)
end

def load_champion
@champion = Champion.new(summoner_params[:champion])
end

def load_summoner
Expand Down
39 changes: 39 additions & 0 deletions app/models/champion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
class Champion < Collection
include ActiveModel::Validations
CHAMPION_NAMES = Rails.cache.read(:champions).values.map { |data| data[:name] }
ACCESSORS = [
:name, :roles, :stats, :tags, :title, :passive, :spells, :allytips,
:enemytips, :key
].freeze
ACCESSORS.each do |accessor|
attr_accessor accessor
end

validates :name, presence: true
validates :name, inclusion: { in: CHAMPION_NAMES }

def initialize(attributes = {})
@name = attributes[:name].strip
if data = Rails.cache.read(name: @name) || match_collection(@name, CHAMPION_NAMES)
ACCESSORS.each do |key|
instance_variable_set("@#{key}", data[key])
end
end
end

def find_by_role(role)
if role.blank?
return @roles.length == 1 ? @roles.first : nil
end

@roles.detect do |role_data|
role_data[:role] == role
end
end

def error_message
errors.messages.map do |key, value|
"#{key} #{value.first}"
end.en.conjunction(article: false)
end
end
14 changes: 14 additions & 0 deletions app/models/collection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Collection
SIMILARITY_THRESHOLD = 0.7

def match_collection(name, collection)
collection_key = self.class.to_s.downcase.pluralize.to_sym
matcher = Matcher::Matcher.new(name)

search_key = Hash.new
if match = matcher.find_match(collection, SIMILARITY_THRESHOLD)
search_key[collection_key] = match.result
Rails.cache.read(search_key)
end
end
end
2 changes: 1 addition & 1 deletion champions.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'net/http'
require 'json'
require 'pry'
binding.pry

champions = JSON.parse(File.read('champions.txt'))[:data]
f = File.new('champions-output.txt', 'w+')
f.write(
Expand Down
7 changes: 6 additions & 1 deletion config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,9 @@ en:
summoner:
attributes:
id:
not_a_number: "could not be found for the given summoner name."
not_a_number: 'could not be found for the given summoner name.'
champion:
attributes:
name:
blank: 'of champion was not provided.'
inclusion: 'provided is not a valid champion name, to the best of my knowledge.'
Loading

0 comments on commit 44deb86

Please sign in to comment.