Created
June 2, 2011 05:44
-
-
Save chron/1003992 to your computer and use it in GitHub Desktop.
WoW Armory average ilvl and boss kill comparison
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# compare-kills-new-armory.rb | |
# Paul Prestidge | |
# 2011-05-20 | |
# | |
require 'fileutils' | |
module Armory | |
class ArmoryCacher | |
CACHE_DIR = 'na' | |
class << self | |
attr_accessor :path | |
end | |
def initialize fn, url | |
location = File.join(CACHE_DIR, self.class.path) | |
FileUtils.mkdir_p(location) | |
fn = File.join(location, "/#{fn}.html") | |
@armorydata = if File.exist?(fn) | |
File.read(fn) | |
else | |
x = %x(curl --silent http://us.battle.net/#{url}) | |
File.open(fn, 'w') { |f| f.puts x } | |
x | |
end | |
end | |
def self.set_path p | |
self.path = p | |
end | |
end | |
class Character < ArmoryCacher | |
set_path 'character' | |
def initialize character_name, realm | |
@name, @realm = character_name, realm | |
super "#{realm.downcase}-#{character_name.downcase}", "wow/en/character/#{realm}/#{character_name}/advanced" | |
@armorydata.gsub!(/bwl: \{.+?\},/m,'') # HACK: remove bwd because nef is in two places | |
end | |
def name | |
@armorydata.scan(/<title>(.+?) @/).first.first | |
end | |
def boss_kills | |
@armorydata.scan(/name: "([^"]+)"(?:, nKills: (-?\d+))?(?:, nHeroicKills: (-?\d+))?/).map do |b,k,hk| | |
[b, k.to_i, hk.to_i] | |
end | |
end | |
def items include_vanity = false | |
@armorydata.scan(/\/wow\/en\/item\/(\d+)" class="item"/).uniq.map { |n| Item.new(n.first) }.select { |i| include_vanity || !i.vanity? } | |
end | |
def achievements category | |
CharacterAchievements.new(@name, @realm, category) | |
end | |
def <=> o | |
self.name <=> o.name | |
end | |
end | |
class CharacterAchievements < ArmoryCacher | |
set_path 'character' | |
CATEGORIES = { | |
:dungeon_and_raid => '168' | |
} | |
def initialize character_name, realm, category | |
cat = CATEGORIES[category] | |
raise 'Unknown category' unless cat | |
super "#{realm.downcase}-#{character_name.downcase}-ach-#{cat.tr(':','c')}", "/wow/en/character/#{realm}/#{character_name}/achievement/#{cat}" | |
end | |
def gotcr | |
data = @armorydata[/Glory of the Cataclysm Raider(.+)<\/div>/m, 1].scan(/<li class="(.+?)">.+?<\/span>(.+?)<\/a>/m).map do |a,b| | |
[b.strip.gsub(/'/, "'"), !!(a =~ /unlocked/)] | |
end | |
Hash[*data.flatten] | |
#data.map { |a,b| a } | |
end | |
end | |
class Item < ArmoryCacher | |
set_path 'item' | |
attr_reader :itemid | |
def initialize id | |
@itemid = id | |
super "item-#{id}", "wow/en/item/#{id}/tooltip" | |
end | |
def vanity? | |
@armorydata =~ /Shirt|Tabard/ # hmm | |
end | |
def shirt? | |
@armorydata =~ /\bShirt\b/ | |
end | |
def tabard? | |
@armorydata =~ /\bTabard\b/ | |
end | |
def set_item? | |
@armorydata =~ /\(\d+\) Set:/ | |
end | |
def name | |
(@armorydata[/<h3 class="color-q\d+">(.+?)<\/h3>/, 1] || '?').gsub(/'/, "'") | |
end | |
def ilvl | |
@armorydata[/Item Level (\d+)/, 1].to_i | |
end | |
def icon | |
@armorydata[/background-image: url\("([^"]+)"/, 1] | |
end | |
end | |
def self.report_gear_quality characters | |
r = characters.map do |c| | |
inv = c.items | |
#puts c.name; c.items.each { |i| puts ' -> %40s %6i %3i' % [i.name, i.itemid, i.ilvl] } | |
ntier, htier = [359, 372].map { |v| inv.select { |i| i.ilvl == v && i.set_item? }.size } | |
avgilvl = inv.inject(0.0) { |s,i| s + i.ilvl } / inv.size | |
[c.name, c.items.inject(Hash.new(0)) { |h,i| h[i.ilvl] += 1; h }, avgilvl, ntier, htier] | |
end | |
categories = r.map { |v| v[1].keys }.flatten.uniq.sort | |
puts ('%14s' + (' %3i' * categories.size) + ' avg set') % ['', *categories] | |
r.sort_by { |cn,h,avgilvl,nt,ht| [-avgilvl, cn] }.each do |cn,h,*r| | |
hp = categories.map { |cat| h[cat] || 0 } + r | |
puts ('%14s' + (' %3i' * categories.size) + ' %3.2f %1i/%1i') % [cn, *hp] | |
end | |
end | |
def self.report_boss_kills characters, heroic_only = false | |
puts (' '*15) + BOSSES.map { |n| s = n[0,3]; ABBREVS[s] || s }.join(' ') | |
characters.map do |c| | |
bk = BOSSES.map { |b| bn,k,hk = c.boss_kills.assoc(b); heroic_only ? [hk,0].max : [hk,0].max+[k,0].max } | |
[bk.inject{|a,b|a+b}, ('%14s' + (' %3i' * BOSSES.size)) % [c.name, *bk]] | |
end.sort_by { |sum,line| -sum }.each do |sum,line| | |
puts "#{line} => #{sum}" | |
end | |
end | |
def self.report_glory_progress characters, include_totals = false | |
template = '%14s' + (' %5s' * GLORY.size) + (include_totals ? ' %5s' : '') | |
puts template % ['', GLORY.map { |achi,abbrev| abbrev }, (include_totals ? 'total' : nil)].compact.flatten | |
ca = characters.sort.map { |c| [c, c.achievements(:dungeon_and_raid).gotcr] } | |
ca.each do |c,a| | |
puts template % [c.name, GLORY.map { |achi,abbrev| a[achi] ? 'X' : '-' }, (include_totals ? a.select{|k,v| v}.size : nil)].flatten | |
end | |
if include_totals | |
totals = GLORY.map { |achi,abbrev| ca.inject(0) { |i,j| i + (j.last[achi] ? 1 : 0) }} | |
puts template % ['Total', totals, totals.inject { |s,c| s + c }].flatten | |
end | |
# GLORY.each { |achi,abbr| puts '%10s => %s' % [abbr, achi] } | |
end | |
BOSSES = %w( | |
Argaloth | |
Magmaw Toxitron Maloriak Atramedes Chimaeron Nefarian | |
Halfus\ Wyrmbreaker Valiona Elementium\ Monstrosity Cho\\'gall Sinestra | |
Conclave\ of\ Wind Al\\'Akir | |
) | |
ABBREVS = { 'Tox' => 'OmC', 'Val' => 'V&T', 'Ele' => 'AsC', 'Al\\' => 'A\'A' } | |
GLORY = [ | |
['Heroic: Magmaw', 'h-mag'], | |
['Heroic: Omnotron Defense System', 'h-omn'], | |
['Heroic: Maloriak', 'h-mal'], | |
['Heroic: Atramedes', 'h-atr'], | |
['Heroic: Chimaeron', 'h-chi'], | |
['Heroic: Nefarian', 'h-nef'], | |
['Heroic: Halfus Wyrmbreaker', 'h-hal'], | |
['Heroic: Valiona and Theralion', 'h-v&t'], | |
['Heroic: Ascendant Council', 'h-asc'], | |
['Heroic: Cho\'gall', 'h-cho'], | |
['Heroic: Conclave of Wind', 'h-con'], | |
['Heroic: Al\'Akir', 'h-a\'a'], | |
['Parasite Evening', 'para'], | |
['Achieve-a-tron', 'achi'], | |
['Silence is Golden', 'silen'], | |
['Full of Sound and Fury', 'fos&f'], | |
['Aberrant Behavior', 'aberr'], | |
['Keeping it in the Family', 'kiitf'], | |
['The Only Escape', 'escap'], | |
['Double Dragon', 'dd'], | |
['Elementary', 'elem'], | |
['The Abyss Will Gaze Back Into You', 'abyss'], | |
['Stay Chill', 'chill'], | |
['Four Play', 'four'] | |
] | |
end | |
if $0 == __FILE__ | |
characters = %w(freshest rockmellon azuba zuzum soul slyran shebull leafi sovereigna talvirr wendy snokey).map { |c| Armory::Character.new(c, 'Saurfang') } | |
#Armory.report_boss_kills(characters, true) | |
#Armory.report_gear_quality(characters) | |
#Armory.report_glory_progress(characters, true) | |
#characters.sort.each do |c| | |
# inv = c.items(true) | |
# shirt, tabard = inv.find { |i| i.shirt? }, inv.find { |i| i.tabard? } | |
# puts '%14s %30s %30s' % [c.name, shirt ? shirt.name : '', tabard ? tabard.name : ''] | |
#end | |
File.open('iconfreq.txt', 'w') do |f| | |
characters.each do |c| | |
c.items.each do |item| | |
url = item.icon | |
fn = url[/\w+.\w+$/] | |
fp = File.join('na', 'icons', fn) | |
f.puts fn | |
%x(curl --silent -o #{fp} #{url}) unless File.exist?(fp) | |
end | |
end | |
end | |
require 'RMagick' | |
s = 56 | |
icons = File.readlines('iconfreq.txt').map { |l| File.join('na', 'icons', l.chomp) } #Dir['icons/*.jpg'] | |
w = h = nil | |
puts ' => %i icons' % icons.size | |
Math.sqrt(icons.size).ceil.downto(1) do |i| | |
if (icons.size/i.to_f) % 1 == 0 | |
w, h = icons.size/i, i | |
break; | |
end | |
end | |
i = Magick::Image.new(s * w, s * h) { | |
self.background_color = 'black' | |
} | |
icons.sort_by { rand }.each_with_index do |icon,idx| | |
image = Magick::Image.read(icon).first | |
i.composite!(image, idx%w * s, idx/w * s, Magick::CopyCompositeOp) | |
end | |
i.write('icons.jpeg') | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment