Skip to content

Instantly share code, notes, and snippets.

@pioz
Last active January 11, 2022 17:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pioz/479f6be0a53900f554b8d6a15828e040 to your computer and use it in GitHub Desktop.
Save pioz/479f6be0a53900f554b8d6a15828e040 to your computer and use it in GitHub Desktop.
Grab some pvp stats in World of Warcraft
require 'net/http'
require 'json'
require 'tty-progressbar'
SPECID_MAP = {
250 => 'Death Knight Blood',
251 => 'Death Knight Frost',
252 => 'Death Knight Unholy',
577 => 'Demon Hunter Havoc',
581 => 'Demon Hunter Vengeance',
102 => 'Druid Balance',
103 => 'Druid Feral Combat',
104 => 'Druid Guardian',
105 => 'Druid Restoration',
253 => 'Hunter Beast Mastery',
254 => 'Hunter Marksmanship',
255 => 'Hunter Survival',
62 => 'Mage Arcane',
63 => 'Mage Fire',
64 => 'Mage Frost',
268 => 'Monk Brewmaster',
269 => 'Monk Windwalker',
270 => 'Monk Mistweaver',
65 => 'Paladin Holy',
66 => 'Paladin Protection',
70 => 'Paladin Retribution',
256 => 'Priest Discipline',
257 => 'Priest Holy',
258 => 'Priest Shadow',
259 => 'Rogue Assassination',
260 => 'Rogue Outlaw',
261 => 'Rogue Subtlety',
262 => 'Shaman Elemental',
263 => 'Shaman Enhancement',
264 => 'Shaman Restoration',
265 => 'Warlock Affliction',
266 => 'Warlock Demonology',
267 => 'Warlock Destruction',
71 => 'Warrior Arms',
72 => 'Warrior Fury',
73 => 'Warrior Protection'
}
APIKEY = 'YOURAPIKEY'
%w(2v2 3v3).each do |bracket|
api_endpoint = "https://eu.api.battle.net/wow/leaderboard/#{bracket}?locale=en_GB&apikey=#{APIKEY}"
result = Net::HTTP.get(URI.parse(api_endpoint))
leaderboard = JSON.parse(result)
counters = {}
leaderboard['rows'].each do |row|
counters[row['specId']] = (counters[row['specId']] || 0) + 1
end
counters.delete(0)
counters = counters.sort{|x, y| y[1] <=> x[1]}
max = counters.map(&:last).max
sum = counters.map(&:last).sum
padding = SPECID_MAP.values.map(&:size).max
puts "Stats #{bracket} updated at #{Time.now.strftime('%d/%m/%Y')} for the first #{sum} best EU players\n"
counters.each do |data|
bar = TTY::ProgressBar.new("#{SPECID_MAP[data[0]].ljust(padding)} [:bar] #{(data[1]*100.0/sum).round(2)}% - :current", total: max, width: 70 - padding)
bar.current = data[1]
bar.start
bar.stop
end
end
Stats 2v2 updated at 08/09/2017 for the first 4966 best EU players
Priest Discipline [================================================] 12.36% - 614
Shaman Restoration [=========================================== ] 10.99% - 546
Druid Restoration [================================== ] 8.88% - 441
Druid Feral Combat [================================== ] 8.8% - 437
Demon Hunter Havoc [========================= ] 6.44% - 320
Warrior Arms [====================== ] 5.76% - 286
Paladin Holy [====================== ] 5.6% - 278
Rogue Subtlety [==================== ] 5.07% - 252
Death Knight Frost [=================== ] 4.87% - 242
Paladin Retribution [================ ] 4.05% - 201
Priest Shadow [============= ] 3.34% - 166
Death Knight Unholy [============= ] 3.28% - 163
Monk Windwalker [=========== ] 2.8% - 139
Monk Mistweaver [========= ] 2.44% - 121
Shaman Elemental [========= ] 2.19% - 109
Druid Balance [======= ] 1.81% - 90
Rogue Assassination [====== ] 1.61% - 80
Shaman Enhancement [====== ] 1.55% - 77
Priest Holy [==== ] 1.13% - 56
Warlock Affliction [==== ] 0.99% - 49
Mage Frost [==== ] 0.95% - 47
Hunter Survival [=== ] 0.77% - 38
Hunter Marksmanship [=== ] 0.68% - 34
Warlock Destruction [== ] 0.42% - 21
Paladin Protection [== ] 0.42% - 21
Warlock Demonology [= ] 0.36% - 18
Druid Guardian [= ] 0.36% - 18
Mage Arcane [= ] 0.34% - 17
Death Knight Blood [= ] 0.32% - 16
Warrior Fury [= ] 0.32% - 16
Mage Fire [= ] 0.26% - 13
Hunter Beast Mastery [= ] 0.22% - 11
Demon Hunter Vengeance [= ] 0.18% - 9
Warrior Protection [= ] 0.16% - 8
Monk Brewmaster [= ] 0.16% - 8
Rogue Outlaw [ ] 0.08% - 4
Stats 3v3 updated at 08/09/2017 for the first 4958 best EU players
Shaman Restoration [================================================] 10.49% - 520
Warrior Arms [================================== ] 7.32% - 363
Priest Discipline [=============================== ] 6.88% - 341
Druid Feral Combat [=============================== ] 6.76% - 335
Paladin Holy [============================= ] 6.23% - 309
Priest Shadow [============================ ] 6.17% - 306
Demon Hunter Havoc [========================= ] 5.49% - 272
Druid Restoration [======================= ] 5.02% - 249
Death Knight Frost [===================== ] 4.68% - 232
Rogue Subtlety [=================== ] 4.24% - 210
Paladin Retribution [=================== ] 4.07% - 202
Mage Frost [=============== ] 3.33% - 165
Shaman Elemental [============== ] 3.07% - 152
Warlock Affliction [============= ] 2.86% - 142
Hunter Marksmanship [============= ] 2.84% - 141
Warlock Destruction [============= ] 2.84% - 141
Druid Balance [============= ] 2.84% - 141
Death Knight Unholy [============ ] 2.56% - 127
Monk Windwalker [============ ] 2.56% - 127
Monk Mistweaver [========= ] 1.9% - 94
Shaman Enhancement [======== ] 1.73% - 86
Mage Arcane [===== ] 1.13% - 56
Warlock Demonology [=== ] 0.73% - 36
Priest Holy [=== ] 0.67% - 33
Hunter Survival [=== ] 0.61% - 30
Mage Fire [== ] 0.54% - 27
Rogue Assassination [== ] 0.5% - 25
Warrior Fury [== ] 0.44% - 22
Druid Guardian [= ] 0.26% - 13
Death Knight Blood [= ] 0.26% - 13
Hunter Beast Mastery [= ] 0.24% - 12
Paladin Protection [= ] 0.2% - 10
Demon Hunter Vengeance [= ] 0.18% - 9
Monk Brewmaster [= ] 0.16% - 8
Warrior Protection [ ] 0.1% - 5
Rogue Outlaw [ ] 0.08% - 4
require 'nokogiri'
require 'open-uri'
require 'gruff'
# Extend Pie chart class to set custom labels
class LabeledPie < Gruff::Pie
def data(name, data_points = [], options = {})
super(name, data_points, options[:color])
@data.each { |data_array| data_array << options[:label] }
end
private
def slice_class
CustomLabeledSlice
end
class CustomLabeledSlice < ::Gruff::Pie::PieSlice
def label
data_array[3] || super
end
end
end
# URL where we grab the data
url = 'https://worldofwarcraft.com/en-gb/game/pvp/leaderboards'
# Wow Class colors
COLORS = {
'mage' => '#68ccef',
'monk' => '#00ffba',
'priest' => '#ffffff',
'warlock' => '#9382c9',
'deathknight' => '#c41e3b',
'paladin' => '#f48cba',
'warrior' => '#c69b6d',
'rogue' => '#fff468',
'shaman' => '#2359ff',
'druid' => '#ff7c0a',
'demonhunter' => '#a330c9',
'hunter' => '#aad372'
}
%w(2v2 3v3).each do |arena|
# Plus 1 the counter when we found the wow class in the leaderboard
counters = {
'mage' => 0,
'monk' => 0,
'priest' => 0,
'warlock' => 0,
'deathknight' => 0,
'paladin' => 0,
'warrior' => 0,
'rogue' => 0,
'shaman' => 0,
'druid' => 0,
'demonhunter' => 0,
'hunter' => 0
}
tot = 0
# Parse the 10 pages of the leaderboard
10.times do |i|
doc = Nokogiri::HTML(open("#{url}/#{arena}?page=#{i+1}"))
doc.search('a.Character').each do |row|
regexp = counters.keys.reduce(){|x,y| "#{x}|#{y}"}
klass = row[:class].downcase[/#{regexp}/]
if klass
counters[klass] += 1
tot += 1
end
end
end
# Sort counters
counters = counters.sort{|x, y| y[1] <=> x[1]}
# Generate pie graph
g = LabeledPie.new
g.title = "Stats #{arena} updated at #{Time.now.strftime('%d/%m/%Y')} for\nthe first #{tot} best EU players"
g.legend_font_size = 14
g.marker_font_size = 12
g.colors = []
counters.each { |klass, counter| g.colors << COLORS[klass] }
counters.each do |klass, counter|
g.data(klass.capitalize, counter, label: "#{klass.capitalize}: #{(counter*100.0/tot).round}% (#{counter})")
end
g.write("stats_#{arena}.png")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment