Thread Tools Display Modes
02-04-22, 07:59 AM   #1
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
Trying to make addon to export WoW Statistics

I currently manually input all my Achievements > Statistics into spreadsheets once every few months and doing it on multiple characters is a massive chore.

I have programming background in vb6, vb.net, java, html, css. I followed the simple starter guides to create an addon and launch a popup window in game.

Then I hit a wall. My gut feeling is WoW has broken, or no API for what I am trying to do. I would love to be proven wrong though!

I launched wow with -console and exported their UI code. I searched through the BlizzardInterfaceCode (specifically the files Blizzard_AchievementUI and Blizzard_APIDocumentation) to no avail.

If you are in game and press Y to bring up Achievements, then click on Statistics at the bottom right, this is the information I would love to export as Comma Seperated Values, or be able to work with the information within the addon to display account wide statistics (aware this would require logging into each alt at least once).

I mainly started this venture as I wanted to consolidate all my battleground and arena statistics to see my win rates per character, my kill death ratio per character & overall. I currently do this by manually inputting every single statistics from the Player vs PLayer section into a spread sheet, which then runs a tonne of formulas and graphs etc to show me that my hunter is 3 kills per death, my dk is 1 kill per death, my warrior is my top flag carrier, etc...

I even tried some getStatistic API stuff within game and noticed this seems to give a STRING value such as false593 with 593 being the value of the specific statistic i found on an api website (but that website is out of date, it still shows the api calls for the things in the Statistics>Character>Combat that got remove a couple patches ago).

Having hit deadends with looking at WoW's code and not finding an addon to do this, as a last resort I figured i'd come ask some experts:

Can this be done? I am willing to put in some work to make the addon but with no working API and no real lua experience im very stuck.
  Reply With Quote
02-04-22, 10:24 AM   #2
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,877
See the GamePedia page on SavedVariables and Saving variables between game sessions

This is the ONLY method/format/place(s) addons can read/write data to the disk. The data is read only once when a character logs in and written only once when the character logs out/reloads.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
02-04-22, 10:49 AM   #3
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
I had a read, that stuff wasn't much help at this point in time - I need to find a way to read that very tidy table of Statistics in the achievement pane.

One thing I just played with was screenshotting a chunk of the Statistics panel in game, then cropped the statistics table into a jpg and saved it. I then went to a website to convert JPG to .xlsx and it correctly translated the picture of the table from in game into a spreadsheet. This doesn't help with an addon, and is still a very manual process and quite time consuming (the conversion is slow).

It baffles me that a program can translate a jpg image of a table into a spreadsheet, but we can't simply export a clean table of data from within the game... :\

My input to website converter:


The result:


Also an example of an addon with data exporting is Reflex - It records all bgs and arenas played.. then lets you export the data as comma seperated values. This has been great for shadowlands season 1 and season 2 for exporting pvp data to spreadsheet to work with... but obviously is limited to the time frame it's been installed, and limited to pvp.

What I want to achieve is far simpler... a dump of the Statistics in the Achievement>Statistics section - pvp at a minimum, but all of it because why not the process will be the same.

Last edited by doublebrutal : 02-04-22 at 10:59 AM. Reason: adding images
  Reply With Quote
02-04-22, 01:48 PM   #4
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,877
Originally Posted by doublebrutal View Post
It baffles me that a program can translate a jpg image of a table into a spreadsheet, but we can't simply export a clean table of data from within the game... :\
Because, complicated

A very basic addon to print the raw stats when you first open the achievement addon

Lua Code:
  1. local f = CreateFrame("Frame")
  2. f:RegisterEvent("ADDON_LOADED")
  3. f:SetScript("OnEvent", function(self, event, ...)
  4.     local addonName = ...
  5.     if addonName == "Blizzard_AchievementUI" then
  6.         self:UnregisterAllEvents()
  7.         local categories = STAT_FUNCTIONS.categoryAccessor()
  8.         for _, cat in ipairs(categories) do
  9.             local catName = GetCategoryInfo(cat)
  10.             local total, completed, incompleted = GetCategoryNumAchievements(cat)
  11.             print(catName, "total", total, "completed", completed, "incompleted", incompleted)
  12.             for i=1, total do
  13.                 local quantity, skip, id = GetStatistic(cat, i)
  14.                 if not skip then
  15.                     print(GetAchievementInfo(cat, i))
  16.                 end
  17.             end
  18.         end
  19.  
  20.     end
  21. end)
you can paste into this website to download as an addon to install.

You can get the information on functions like GetAchievementInfo and more at GamePedia.

Using the information about SavedVariables, you could save then information to disk as a table instead of using print(). From there you can start refining or extending the saved information to achieve the desired result (a result you can read from lua table format to CSV or whatever), but there is no easy "GiveMeWhatIWant" function.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 02-04-22 at 04:17 PM.
  Reply With Quote
02-04-22, 02:52 PM   #5
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,877
I guess the other alternative would be to do a "scroll 'n scrape" of the actual stat rows. The entries in the "value" key will be formatted for display (like icons for gold/silver/copper etc.) so they will need to be broken down for "saving" but something like:

As above, the print() would need to be converted to a Save process.

Lua Code:
  1. SLASH_doublebrutalStats1 = "/dbs"
  2. local achievs = {}
  3. SlashCmdList.doublebrutalStats = function(msg)
  4.     if not AchievementFrame or not AchievementFrameStatsContainer:IsVisible() then
  5.         print("Can't see Achievement Frame!")
  6.         return
  7.     end
  8.     if strupper(msg) == "CLR" then
  9.         wipe(achievs)
  10.         return
  11.     end
  12.     if strupper(msg) == "PRT" then
  13.         for k, v in pairs(achievs) do
  14.             print(k, v.text, v.value)
  15.         end
  16.         return
  17.     end
  18.     local count = 0
  19.     while true do
  20.         count = count + 1
  21.         local button = _G["AchievementFrameStatsContainerButton"..count]
  22.         if not button then break end
  23.         if button.text:GetText() then
  24.             if achievs[button.id] then
  25.                 achievs[button.id].text = button.text:GetText()
  26.                 achievs[button.id].value = button.value:GetText()
  27.             else
  28.                 achievs[button.id] = { text=button.text:GetText(), value=button.value:GetText() }
  29.             end
  30.         end
  31.     end
  32. end

/dbs <scroll> /dbs to scrape the infomration from the list
/dbs prt to print the scraped information
/dbs clr to clear the scraped information
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 02-04-22 at 04:19 PM.
  Reply With Quote
02-04-22, 06:17 PM   #6
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,322
Originally Posted by Fizzlemizz View Post
Originally Posted by doublebrutal View Post
It baffles me that a program can translate a jpg image of a table into a spreadsheet, but we can't simply export a clean table of data from within the game... :\
Because, complicated
It's not that the process itself is complicated, but the reason behind it. Ultimately, Blizzard doesn't want to allow us direct access to the user's filesystem. There are many reasons for this ranging from user security to bot prevention.

Lua itself was designed to be an embedded language, meaning it only has the bare minimum in terms of built-in functions. It's up to the host program to provide the API to expand its functionality. Similarly, the host's developer can decide to remove any of Lua's built-in functions. Many of which can be extremely dangerous on an end user's system if 3rd party scripts (such as addons) are allowed.



As mentioned previously, the only way to save and load data off disk is to use the SavedVar system.

Another method is to show a multi-line EditBox with pre-formatted text the user can copy/paste. Note Ctrl-C/Ctrl-V does work in WoW for this.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 02-04-22 at 06:20 PM.
  Reply With Quote
02-04-22, 08:07 PM   #7
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
Hey guys, thanks for those 2 ideas, going to go test them now!
  Reply With Quote
02-04-22, 08:44 PM   #8
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
So the first code output a messy version of what I am after into the chatbox in game, but is far bigger than i can scroll through in the chatbox to copy/paste. I am currently trying to make it output to savedvariables but not really getting anywhere. When I open my savedvariable for my addon in the WTF folder, it is a single line of code:

EXPORTSTATSDB = nil

An example of the results returned from that code by fizzle is:

7399 Challenge mode dungeons completed 0 false nil nil nil 1 136243 false false nil true

I'm guessing it's hitting one of these nils and just stopping instead of outputting to savedvariables. Would it be easier to have the output come up in a window like /simc or /amr for a simple copy paste export?

I tried using message instead of print but it only outputs the very first value of 7399 in the message window.

Last edited by doublebrutal : 02-04-22 at 09:12 PM.
  Reply With Quote
02-04-22, 08:55 PM   #9
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
I also tried the second suggestion of scraping the statistics panel - this is a tidier output format but unfortunately doesn't behave as expected. I opened the Player vs Player Rated Arenas section. Typed /dbs. Scrolled to bottom of that section. Typed /dbs prt. This output a mash of the arena section and other sections as well into chat. It also is too long for chat box for any kind of copy pasting to be useful.
  Reply With Quote
02-04-22, 09:02 PM   #10
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
Just tried another approach using the addon CopyAnything

This sadly only lets me point at a single cell of a table and copy the text, so one by one, the name of each stat, then the value of each stat, much much worse than even my old way of manual data entry xD
  Reply With Quote
02-04-22, 09:21 PM   #11
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,877
The first one using Saved Variables (assuming EXPORTSTATSDB as the SV declared in the .toc) might look something like (saves the data under each character name/realm sub key) (it's just a crude example so treat accoringly):

You have to open the achievements frame for it to work.

Lua Code:
  1. local f = CreateFrame("Frame")
  2. f:RegisterEvent("ADDON_LOADED")
  3. f:SetScript("OnEvent", function(self, event, ...)
  4.     local addonName = ...
  5.     if addonName == "Blizzard_AchievementUI" then
  6.         self:UnregisterAllEvents()
  7.         EXPORTSTATSDB  = EXPORTSTATSDB or {} -- create SV table iuf required
  8.         local player = UnitName("player") -- create sub-table for current polayer info
  9.         player = player.."-"..GetRealmName()
  10.         EXPORTSTATSDB[player] = EXPORTSTATSDB[player] or {}
  11.         local SVKey = EXPORTSTATSDB[player]
  12.         local categories = STAT_FUNCTIONS.categoryAccessor()
  13.         wipe(SVKey) -- clear the tasble tyo update with latest ionformation
  14.         for catid, cat in ipairs(categories) do
  15.             local catName = GetCategoryInfo(cat)
  16.             local total, completed, incompleted = GetCategoryNumAchievements(cat)
  17.             SVKey[catName] = {} -- create category sub-sub table
  18.             SVKey[catName].total = total
  19.             SVKey[catName].completed =completed
  20.             SVKey[catName].incompleted = incompleted
  21.             SVKey[catName].Stats = {} -- create sub-sub-sub table for category stats
  22.             local Stats = SVKey[catName].Stats
  23.             for i=1, total do
  24.                 local quantity, skip, cid = GetStatistic(cat, i)
  25.                 if not skip then
  26.                     local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe, earnedBy, isStatistic = GetAchievementInfo(cat, i)
  27.                     Stats[id] = {}
  28.                     local Stat = Stats[id]
  29.                     Stat.name = name
  30.                     Stat.points = points
  31.                     Stat.completed = completed
  32.                     Stat.month = month
  33.                     Stat.day = day
  34.                     Stat.year = year
  35.                     Stat.description = description
  36.                     Stat.flags = flags
  37.                     Stat.icon = icon
  38.                     Stat.rewardText = rewardText
  39.                     Stat.isGuild = isGuild
  40.                     Stat.wasEarnedByMe = wasEarnedByMe
  41.                     Stat.earnedBy = earnedBy
  42.                     Stat.quantity = quantity
  43.                     Stat.isStatistic = isStatistic
  44.                     local numCriteria = GetAchievementNumCriteria(id)
  45.                     if numCriteria > 0 then
  46.                         Stat.criteria = {}
  47.                         Stat.numCriteria = numCriteria
  48.                         for c = 1, numCriteria do
  49.                             local criteriaString, criteriaType, completed, quantityNumber, reqQuantity, charName, flags, assetID, quantity = GetAchievementCriteriaInfo(id, c)
  50.                             tinsert(Stat.criteria, {
  51.                                 criteriaString=criteriaString,
  52.                                 criteriaType=criteriaType,
  53.                                 completed=completed,
  54.                                 quantityNumber=quantityNumber,
  55.                                 reqQuantity=reqQuantity,
  56.                                 charName=charName,
  57.                                 flags=flags,
  58.                                 assetID=assetID,
  59.                                 quantity=quantity,
  60.                             })
  61.                         end
  62.                     end
  63.                 end
  64.             end
  65.         end
  66.     end
  67. end)
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 02-05-22 at 09:40 AM.
  Reply With Quote
02-04-22, 09:55 PM   #12
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
OK that SavedVariables output is a thing of beauty I can definitely work with this!!! Thank you so much for the help!!!

UPDATE: Never mind, I think I will just have to data entry, even this beautifully formatted SavedVariables file didn't save a single value for any of the statistics ):

Example output:

[14785] = {
["rewardText"] = "",
["wasEarnedByMe"] = false,
["isGuild"] = false,
["flags"] = 1,
["description"] = "",
["name"] = "Total deaths in PvP arenas",
["completed"] = false,
["points"] = 0,
["icon"] = 136243,
["isStatistic"] = true,

It only gives the true or false of the statistic - a problem i encountered a few weeks ago when i first tried making scripts/macros using getStatistic()

Last edited by doublebrutal : 02-04-22 at 10:13 PM.
  Reply With Quote
02-04-22, 10:08 PM   #13
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,877
Don't be too quick with the thanks, it's by no means complete as each stat can have different value sets and this doesn't get those .

The information should be buried somwehere in the Achivement UI code.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
02-04-22, 10:22 PM   #14
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
https://www.wowhead.com/forums/topic...s-macro-248202

I found this resource just now which is much closer to what I am trying to do

UPDATE: Using this method, I created my own list of PvP achievement IDs, which 'printed' to chat log at 12.29pm.. which i thought would be saved in ElvUI chatlog at 12.29pm.. nope, it only saved player chat stuff and the achi stuff was skipped ):

Last edited by doublebrutal : 02-04-22 at 10:35 PM. Reason: update
  Reply With Quote
02-04-22, 10:25 PM   #15
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
Originally Posted by Fizzlemizz View Post
Don't be too quick with the thanks, it's by no means complete as each stat can have different value sets and this doesn't get those .

The information should be buried somwehere in the Achivement UI code.
Yeah it looked so clean at first but as soon as i went to use it I realised it didn't catch a single value of any statistic ):

With all the crazy websites like DataForAzeroth i thought BLizzard's API was gonna be way better than this, was not expecting the statistics panel to not have API calls.
  Reply With Quote
02-05-22, 09:47 AM   #16
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,877
Originally Posted by doublebrutal View Post
i thought BLizzard's API was gonna be way better than this...
Define better.

Updated the previous code to add some numbers. I suggest you run it, /reload and check it against what you see in the in-game stats. for that character.
Probably better to delete the SavedVariables files(s) before starting the game so you only have one characters worth of information.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 02-05-22 at 10:50 AM.
  Reply With Quote
02-05-22, 11:36 AM   #17
elcius
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Sep 2011
Posts: 75
I think this is something you should be doing with the web api instead of in-game
https://develop.battle.net/documenta...t/profile-apis
  Reply With Quote
02-06-22, 03:57 AM   #18
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
Things like Duels won and Duels lost are correct, along with Total deaths from players. Gonna spend some time now figuring out what all the incorrect value have in common.
  Reply With Quote
02-06-22, 04:05 AM   #19
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
Oooh never mind I see it's somehow combining oddly seperated data to one correct value:

[105] = {
["rewardText"] = "",
["numCriteria"] = 2,
["criteria"] = {
{
["criteriaString"] = "Warsong Gulch Victories",
["charName"] = "Doubleßrutal",
["quantityNumber"] = 186,
["completed"] = true,
["quantity"] = "186",
["reqQuantity"] = 1,
["assetID"] = 489,
["criteriaType"] = 1,
["flags"] = 0,
}, -- [1]
{
["criteriaString"] = "Warsong Gulch Victories",
["charName"] = "Doubleßrutal",
["quantityNumber"] = 41,
["completed"] = true,
["quantity"] = "41",
["reqQuantity"] = 1,
["assetID"] = 2106,
["criteriaType"] = 1,
["flags"] = 0,
}, -- [2]
},
["wasEarnedByMe"] = false,
["isGuild"] = false,
["description"] = "Warsong Gulch victories",
["flags"] = 1,
["quantity"] = "227",
["name"] = "Warsong Gulch victories",
["completed"] = false,
["points"] = 0,
["icon"] = 136243,
["isStatistic"] = true,

Now I am reading it properly it seems like you have done it!

The 227 is correct, and the same pattern of output actually worked for Warsong Gulch battles too!

Good job on getting through Blizzard's Spaghetti code on this one!

Last edited by doublebrutal : 02-06-22 at 04:09 AM.
  Reply With Quote
02-07-22, 02:28 AM   #20
doublebrutal
A Deviate Faerie Dragon
Join Date: Feb 2022
Posts: 12
So to follow up on one thing that works for now, I dumped all my toons into the SavedVariables file. I then copied it's entirety to Excel. I then made 2 copies of a table of PvP statistics, with a column for each character.

In one copy of this table, I linked each stat to it's value in the raw paste data (this way I could easily select the correct value of the 3 in situations like warsong gulch above. The other copy of the same table simply linked to this table (=SHEET3!B3245) for example.

This way I have a permanent list of all the stats in raw format which for example:

Code:
                Char name                  Char name                      etc...
Arenas played   ["quantity"] = "8582",     ["quantity"] = "1328",
I then wrote a VBScript to remove non numeric characters and put it on a button on the copied sheet.

When I paste the data in sheet 3, sheet 2 pulls the values I want for each character accurately, then sheet 1 is literally just linked to sheet 2 cells so it updates identically. Then on sheet 1 I push the button, and it cleans the whole sheet up to show:

Code:
                   Char name            Char name          etc...
Arenas played      8582                 1328
Now this will work for me personally for the time being but it is far from future proof.

In patch 9.2 when new arenas are added, the links between sheet 2 and the raw data will no longer be accurate, as there will be more lines of code and it will all go out of whack until I manually rejoin the data, but this shouldn't happen super often so I think I can live with it.

I spent some time thinking how to turn the savedvariable data into usable info for an addon but since things like Warsong gulch has 3 values called "[quantity=""] trying to search the strings and pick the max of the 3 seemed like a nightmare.

Thanks again for the help at least now for personal use I can spend the next 2 weeks in excel nerding out over 17 years of WoW PvP data
  Reply With Quote

WoWInterface » AddOns, Compilations, Macros » AddOn Search/Requests » Trying to make addon to export WoW Statistics

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off