init
This commit is contained in:
143
src/tft_crunch.cr
Normal file
143
src/tft_crunch.cr
Normal file
@ -0,0 +1,143 @@
|
||||
require "json"
|
||||
require "math"
|
||||
|
||||
class Champion
|
||||
include JSON::Serializable
|
||||
|
||||
property cost : Int32
|
||||
property name : String
|
||||
property traits : Array(String)
|
||||
end
|
||||
|
||||
class Trait
|
||||
include JSON::Serializable
|
||||
|
||||
class Effect
|
||||
include JSON::Serializable
|
||||
|
||||
@[JSON::Field(key: "minUnits")]
|
||||
property min_units : Int32
|
||||
|
||||
@[JSON::Field(key: "maxUnits")]
|
||||
property max_units : Int32
|
||||
|
||||
property style : Int32
|
||||
end
|
||||
|
||||
property effects : Array(Effect)
|
||||
property name : String
|
||||
|
||||
def active_at?(unit_count)
|
||||
return effects.any? do |effect|
|
||||
effect.max_units >= unit_count && effect.min_units <= unit_count
|
||||
end
|
||||
end
|
||||
|
||||
def tier_at(unit_count)
|
||||
return effects.index do |effect|
|
||||
effect.max_units >= unit_count && effect.min_units <= unit_count
|
||||
end
|
||||
end
|
||||
|
||||
def unique?
|
||||
return effects.any? do |effect|
|
||||
effect.style == 4
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def comb(n, r)
|
||||
return ((n-r+1)..n).product // (1..r).product
|
||||
end
|
||||
|
||||
def check_active(champions, trait_data, emblems = [] of String, uniques = false)
|
||||
active = [] of Tuple(Trait, Int32, Int32)
|
||||
count = {} of String => Int32
|
||||
|
||||
champions.each do |champion|
|
||||
champion.traits.tally(count)
|
||||
end
|
||||
count.each do |trait_name, count|
|
||||
trait = trait_data[trait_name]
|
||||
if trait.active_at?(count) && (uniques || !trait.unique?)
|
||||
active << {trait, count, trait.tier_at(count).not_nil!}
|
||||
end
|
||||
end
|
||||
|
||||
return active
|
||||
end
|
||||
|
||||
def score_comp(champions, trait_data)
|
||||
traits = check_active(champions, trait_data)
|
||||
score = 0
|
||||
if champions.any?{|e| e.name == "Vander"}
|
||||
score += 100
|
||||
end
|
||||
if traits.any?{|e| e[0].name == "Family"}
|
||||
score += 100
|
||||
end
|
||||
traits.each do |trait, count, tier|
|
||||
score += 2**tier
|
||||
end
|
||||
return score
|
||||
end
|
||||
|
||||
RES_FILE = "res/en_us.json"
|
||||
|
||||
file = File.open(RES_FILE)
|
||||
data = JSON.parse(file)
|
||||
trait_data = data["sets"]["13"]["traits"].as_a.to_json
|
||||
champion_data = data["sets"]["13"]["champions"].as_a.to_json
|
||||
|
||||
traits = Array(Trait).from_json(trait_data).index_by(&.name)
|
||||
champions = Array(Champion).from_json(champion_data)
|
||||
champions.reject!{ |champ| champ.traits.empty? }
|
||||
cbn = champions.index_by(&.name)
|
||||
|
||||
unit_count = ARGV[0]?.try(&.to_i) || 7
|
||||
super_count = ARGV[1]?.try(&.to_i) || 4
|
||||
other_count = unit_count - super_count
|
||||
cost_limit = ARGV[2]?.try(&.to_i) || 10
|
||||
min_score = ARGV[3]?.try(&.to_i) || unit_count
|
||||
|
||||
champions.select!{ |champ| champ.cost <= cost_limit }
|
||||
champions.sort_by!{ |champ| champ.name }
|
||||
super_units = champions.select{ |champ| champ.traits.size == 3 }
|
||||
other_units = champions.select{ |champ| champ.traits.size == 2 }
|
||||
puts "#{super_count.to_s.rjust(2)}x #{super_units.size.to_s.rjust(2)} 3-trait champions"
|
||||
puts "#{other_count.to_s.rjust(2)}x #{other_units.size.to_s.rjust(2)} 2-trait champions"
|
||||
|
||||
results = [] of Tuple(Array(Champion), Int32)
|
||||
|
||||
counter : UInt64 = 0
|
||||
total = comb(super_units.size, super_count)
|
||||
total *= comb(other_units.size, other_count)
|
||||
|
||||
test_array1 = [] of Champion
|
||||
test_array2 = [] of Champion
|
||||
super_units.each_combination(super_count, reuse: test_array1) do |units|
|
||||
other_units.each_combination(other_count, reuse: test_array2) do |others|
|
||||
others.concat(units)
|
||||
score = score_comp(others, traits)
|
||||
if score >= min_score
|
||||
results << {others.dup, score}
|
||||
end
|
||||
if counter % 100000 == 0
|
||||
percent = (counter / total * 100).format(decimal_places: 2).rjust(6) + "%"
|
||||
puts "#{percent} | #{counter.to_s.rjust(10)} | #{score.to_s.rjust(3)} | #{others.map(&.name).join(", ")}"
|
||||
end
|
||||
counter += 1
|
||||
others.clear
|
||||
end
|
||||
units.clear
|
||||
end
|
||||
|
||||
output = results.sort_by{|e| e[1]}.reverse.first(50).map do |list, count|
|
||||
"#{list.map(&.name).join(", ").ljust(30)} - #{count} score"
|
||||
end
|
||||
|
||||
File.write("output.txt", output.join("\n"))
|
||||
|
||||
puts "\nTop Ten:"
|
||||
puts "-" * 80
|
||||
puts output.first(10).reverse.join("\n")
|
Reference in New Issue
Block a user