Thread Tools Display Modes
06-15-20, 10:20 AM   #1
Adapt
A Murloc Raider
Join Date: Jun 2020
Posts: 6
Post Logging all XP gains

Hi all,
I am making a small addon for Classic that logs all XP gains to a SavedVariables file that I can then parse later for analysis. I am struggling a bit with the SavedVariables piece. Hoping someone can help.

XPlogger.toc
Lua Code:
  1. ## Interface: 11303
  2. ## Title: XPLogger
  3. ## Author: eightfive labs
  4. ## Notes: Logs all XP gains to a file for analysis later
  5. ## Version: 0.0.1
  6. ## SavedVariablesPerCharacter: XPLogger
  7.  
  8. main.lua

main.lua
Lua Code:
  1. local Congrats_EventFrame = CreateFrame("Frame")
  2. local defaults = {
  3.     TotalXP = 0
  4. }
  5.  
  6. XPLogger = XPLogger or defaults
  7. Congrats_EventFrame:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN")
  8. Congrats_EventFrame:SetScript("OnEvent",
  9.     function(self, event, ...)
  10.         local arg1 = ...
  11.         local xpgained = string.match(string.match(arg1, "%d+ experience"), "%d+")
  12.        
  13.         print('--xp gained--')
  14.         print(UnitLevel("player"), xpgained, date("%d/%m/%y %H:%M:%S"))
  15.         print('---')
  16.         XPLogger.TotalXP = XPLogger.TotalXP + tonumber(xpgained)
  17.         print('Total XP' .. XPLogger.TotalXP)
  18.     end)

However, I am not seeing the SavedVariables file being written and the XPLogger.TotalXP is reset on /reload.

Any help would be appreciated.
  Reply With Quote
06-15-20, 10:52 AM   #2
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
You need to wait until ADDON_LOADED until your savedvariables are available
https://wow.gamepedia.com/Saving_var..._game_sessions

Something like this
Lua Code:
  1. local Congrats_EventFrame = CreateFrame("Frame")
  2. local defaults = {
  3.     TotalXP = 0
  4. }
  5.  
  6. Congrats_EventFrame:RegisterEvent("ADDON_LOADED")
  7. Congrats_EventFrame:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN")
  8. Congrats_EventFrame:SetScript("OnEvent",
  9.     function(self, event, ...)
  10.         if event == "CHAT_MSG_COMBAT_XP_GAIN" then
  11.             -- do stuff
  12.         elseif event == "ADDON_LOADED" then
  13.             local addon = ...
  14.             if addon == "XPlogger" then
  15.                 XPLogger = XPLogger or defaults
  16.                 self:UnregisterEvent(event)
  17.             end
  18.         end
  19.     end)
  Reply With Quote
06-15-20, 12:57 PM   #3
Adapt
A Murloc Raider
Join Date: Jun 2020
Posts: 6
Originally Posted by Ketho View Post
You need to wait until ADDON_LOADED until your savedvariables are available
https://wow.gamepedia.com/Saving_var..._game_sessions

...
Thanks for your kind help and quick response. Does this mean that any logic in relation to interacting with that variable needed to come after that event has fired?

i.e.

Lua Code:
  1. local Congrats_EventFrame = CreateFrame("Frame")
  2. local defaults = {
  3.     TotalXP = 0
  4. }
  5.  
  6. Congrats_EventFrame:RegisterEvent("ADDON_LOADED")
  7. Congrats_EventFrame:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN")
  8. Congrats_EventFrame:SetScript("OnEvent",
  9.     function(self, event, ...)
  10.         if event == "CHAT_MSG_COMBAT_XP_GAIN" then
  11.             local arg1 = ...
  12.             local xpgained = string.match(string.match(arg1, "%d+ experience"), "%d+")
  13.        
  14.             print('--xp gained--')
  15.             print(UnitLevel("player"), xpgained, date("%d/%m/%y %H:%M:%S"))
  16.             print('---')
  17.  
  18.             -- this doesn't seem to get saved or displayed?
  19.             XPLogger.TotalXP = XPLogger.TotalXP + tonumber(xpgained)
  20.             print('Total XP' .. XPLogger.TotalXP)
  21.         elseif event == "ADDON_LOADED" then
  22.             local addon = ...
  23.             if addon == "XPlogger" then
  24.                 print('XPLogger loaded')
  25.                 XPLogger = XPLogger or defaults
  26.                 self:UnregisterEvent(event)
  27.             end
  28.         end
  29.     end)
  Reply With Quote
06-15-20, 01:25 PM   #4
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Yes. It is generally preferred that you know what your saved variables are before you try to use them.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
06-15-20, 01:44 PM   #5
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
Originally Posted by Adapt View Post
Lua Code:
  1. -- this doesn't seem to get saved or displayed?
  2. XPLogger.TotalXP = XPLogger.TotalXP + tonumber(xpgained)
  3. print('Total XP' .. XPLogger.TotalXP)

Your last script works fine for me. Check if you have any errors by getting BugSack
  Reply With Quote
06-15-20, 02:12 PM   #6
Adapt
A Murloc Raider
Join Date: Jun 2020
Posts: 6
Originally Posted by Seerah View Post
Yes. It is generally preferred that you know what your saved variables are before you try to use them.
Ha! Yes, I more meant if all logic needed to be inside the ADDON_LOADED event.
  Reply With Quote
06-15-20, 02:33 PM   #7
Adapt
A Murloc Raider
Join Date: Jun 2020
Posts: 6
Originally Posted by Ketho View Post
Your last script works fine for me. Check if you have any errors by getting BugSack
Thanks. Seems for some reason I needed to restart client, not just /reload.

The last piece I think is now logging each XP gain in a table.

Edit: All sorted. Sharing below for those interested.

Lua Code:
  1. local EventFrame = CreateFrame("Frame")
  2. local defaults = {
  3.     TotalXP = 0,
  4.     TotalXPEvents = 0,
  5.     IndividualGains = {},
  6. }
  7.  
  8. EventFrame:RegisterEvent("ADDON_LOADED")
  9. EventFrame:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN")
  10. EventFrame:SetScript("OnEvent",
  11.     function(self, event, ...)
  12.         if event == "CHAT_MSG_COMBAT_XP_GAIN" then
  13.             local arg1 = ...
  14.  
  15.             local DateTime = date("%d/%m/%y %H:%M:%S")
  16.             local XPGained = string.match(string.match(arg1, "%d+ experience"), "%d+")
  17.             local Creature = string.match(arg1, "(%a+) dies")
  18.             local QuestOrCreature = "Creature"
  19.             if Creature == nil then
  20.                 QuestOrCreature = "Quest"
  21.             end
  22.            
  23.             -- Increment number of XP events
  24.             CharacterDB.TotalXPEvents = CharacterDB.TotalXPEvents + 1
  25.             print('Total XP events ' .. CharacterDB.TotalXPEvents)
  26.        
  27.             -- Add to total XP gained
  28.             CharacterDB.TotalXP = CharacterDB.TotalXP + tonumber(XPGained)
  29.             print('Total XP ' .. CharacterDB.TotalXP)
  30.  
  31.             -- Setup table for new individual XP gain
  32.             local NewGain = {}
  33.             NewGain["Timestamp"] = DateTime
  34.             NewGain["XP Gained"] = XPGained
  35.             NewGain["Zone"] = GetZoneText()
  36.             NewGain["Minimap Zone"] = GetMinimapZoneText()
  37.             NewGain["Level"] = UnitLevel("player")
  38.             NewGain["Total XP"] = CharacterDB.TotalXP
  39.             NewGain["Quest or Creature"] = QuestOrCreature
  40.             NewGain["Creature"] = Creature
  41.  
  42.             -- Log individual XP gain statistics
  43.             table.insert(CharacterDB.IndividualGains, NewGain)
  44.  
  45.         elseif event == "ADDON_LOADED" then
  46.             local addon = ...
  47.             if addon == "XPLogger" then
  48.                 CharacterDB = CharacterDB or defaults
  49.                 print('----------------')
  50.                 print('XPLogger loaded')
  51.                 print('Total XP ' .. CharacterDB.TotalXP)
  52.                 print('Total XP events ' .. CharacterDB.TotalXPEvents)
  53.                 print('----------------')
  54.  
  55.                 self:UnregisterEvent(event)
  56.             end
  57.         end
  58.     end)

Will now write a parser.

Last edited by Adapt : 06-15-20 at 03:39 PM.
  Reply With Quote
06-16-20, 12:23 AM   #8
JDoubleU00
A Firelord
 
JDoubleU00's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 463
Originally Posted by Adapt View Post
Thanks. Seems for some reason I needed to restart client, not just /reload.

The last piece I think is now logging each XP gain in a table.

Edit: All sorted. Sharing below for those interested.

Lua Code:
  1. local EventFrame = CreateFrame("Frame")
  2. local defaults = {
  3.     TotalXP = 0,
  4.     TotalXPEvents = 0,
  5.     IndividualGains = {},
  6. }
  7.  
  8. EventFrame:RegisterEvent("ADDON_LOADED")
  9. EventFrame:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN")
  10. EventFrame:SetScript("OnEvent",
  11.     function(self, event, ...)
  12.         if event == "CHAT_MSG_COMBAT_XP_GAIN" then
  13.             local arg1 = ...
  14.  
  15.             local DateTime = date("%d/%m/%y %H:%M:%S")
  16.             local XPGained = string.match(string.match(arg1, "%d+ experience"), "%d+")
  17.             local Creature = string.match(arg1, "(%a+) dies")
  18.             local QuestOrCreature = "Creature"
  19.             if Creature == nil then
  20.                 QuestOrCreature = "Quest"
  21.             end
  22.            
  23.             -- Increment number of XP events
  24.             CharacterDB.TotalXPEvents = CharacterDB.TotalXPEvents + 1
  25.             print('Total XP events ' .. CharacterDB.TotalXPEvents)
  26.        
  27.             -- Add to total XP gained
  28.             CharacterDB.TotalXP = CharacterDB.TotalXP + tonumber(XPGained)
  29.             print('Total XP ' .. CharacterDB.TotalXP)
  30.  
  31.             -- Setup table for new individual XP gain
  32.             local NewGain = {}
  33.             NewGain["Timestamp"] = DateTime
  34.             NewGain["XP Gained"] = XPGained
  35.             NewGain["Zone"] = GetZoneText()
  36.             NewGain["Minimap Zone"] = GetMinimapZoneText()
  37.             NewGain["Level"] = UnitLevel("player")
  38.             NewGain["Total XP"] = CharacterDB.TotalXP
  39.             NewGain["Quest or Creature"] = QuestOrCreature
  40.             NewGain["Creature"] = Creature
  41.  
  42.             -- Log individual XP gain statistics
  43.             table.insert(CharacterDB.IndividualGains, NewGain)
  44.  
  45.         elseif event == "ADDON_LOADED" then
  46.             local addon = ...
  47.             if addon == "XPLogger" then
  48.                 CharacterDB = CharacterDB or defaults
  49.                 print('----------------')
  50.                 print('XPLogger loaded')
  51.                 print('Total XP ' .. CharacterDB.TotalXP)
  52.                 print('Total XP events ' .. CharacterDB.TotalXPEvents)
  53.                 print('----------------')
  54.  
  55.                 self:UnregisterEvent(event)
  56.             end
  57.         end
  58.     end)

Will now write a parser.
I'd be interested in see your parser. I've been curious about parsing saved variables for a while.
__________________
Author of JWExpBar and JWRepBar.
  Reply With Quote
06-16-20, 08:49 AM   #9
Adapt
A Murloc Raider
Join Date: Jun 2020
Posts: 6
Originally Posted by JDoubleU00 View Post
I'd be interested in see your parser. I've been curious about parsing saved variables for a while.
I wrote a small .net application to do it. Here is the meat of the code - not elegant, and specific to the addon I made, but does the job.

Use at your own risk, I take no responsibility.

Code:
private void Button_ParseFile(object sender, RoutedEventArgs e)
        {
            string fileToParse = SelectFile("Select file to parse", "lua", "lua files(*.lua) | *.lua");
            if (fileToParse == null) return;

            string[] lines = File.ReadAllLines(fileToParse);

            // Regexes
            Regex TotalXPRegex = new Regex(@"(\d+)");
            Regex CreatureRegex = new Regex(@".* = ""(.+)""");
            Regex MinimapZoneRegex = new Regex(@".* = ""(.+)""");
            Regex ZoneRegex = new Regex(@".* = ""(.+)""");
            Regex LevelRegex = new Regex(@"(\d+)");
            Regex TimeStampRegex = new Regex(@".* = ""(.+)""");
            Regex QuestOrCreature = new Regex(@".* = ""(.+)""");
            Regex XPGainedRegex = new Regex(@"(\d+)");
            Regex EndOfIndividualGainRegex = new Regex(@"-- \[\d+\]");

            var records = new List<XPLogger> { };
            var record = new XPLogger();

            foreach (string line in lines)
            {
                if (line.Contains("[\"Total XP\"]"))
                {
                    Match match = TotalXPRegex.Match(line);
                    record.TotalXP = Int16.Parse(match.Groups[1].Value);
                    continue;
                }

                if (line.Contains("[\"Creature\"]"))
                {
                    Match match = CreatureRegex.Match(line);
                    record.Creature = match.Groups[1].Value;
                    continue;
                }

                if (line.Contains("[\"Minimap Zone\"]"))
                {
                    Match match = MinimapZoneRegex.Match(line);
                    record.MinimapZone = match.Groups[1].Value;
                    continue;
                }

                if (line.Contains("[\"Zone\"]"))
                {
                    Match match = ZoneRegex.Match(line);
                    record.Zone = match.Groups[1].Value;
                    continue;
                }

                if (line.Contains("[\"Level\"]"))
                {
                    Match match = LevelRegex.Match(line);
                    record.Level = Int16.Parse(match.Groups[1].Value);
                    continue;
                }

                if (line.Contains("[\"Timestamp\"]"))
                {
                    Match match = TimeStampRegex.Match(line);
                    record.TimeStamp = match.Groups[1].Value;
                    continue;
                }

                if (line.Contains("[\"Quest or Creature\"]"))
                {
                    Match match = QuestOrCreature.Match(line);
                    record.QuestOrCreature = match.Groups[1].Value;
                    continue;
                }

                if (line.Contains("[\"XP Gained\"]"))
                {
                    Match match = XPGainedRegex.Match(line);
                    record.XPGained = Int16.Parse(match.Groups[1].Value);
                    continue;
                }

                if (EndOfIndividualGainRegex.IsMatch(line))
                {
                    records.Add(record);
                    record = new XPLogger();
                }

            }

            string newFile = SaveFile("Select file to output", "csv", "csv files(*.csv) | *.csv");

            if (newFile == null) return;

            using (var writer = new StreamWriter(newFile))
            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                csv.WriteRecords(records);
            }


        }
  Reply With Quote
06-16-20, 11:07 PM   #10
JDoubleU00
A Firelord
 
JDoubleU00's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 463
Originally Posted by Adapt View Post
I wrote a small .net application to do it. Here is the meat of the code - not elegant, and specific to the addon I made, but does the job.

Use at your own risk, I take no responsibility.

Code:
private void Button_ParseFile(object sender, RoutedEventArgs e)
        {
            string fileToParse = SelectFile("Select file to parse", "lua", "lua files(*.lua) | *.lua");
            if (fileToParse == null) return;

            string[] lines = File.ReadAllLines(fileToParse);

            // Regexes
            Regex TotalXPRegex = new Regex(@"(\d+)");
            Regex CreatureRegex = new Regex(@".* = ""(.+)""");
            Regex MinimapZoneRegex = new Regex(@".* = ""(.+)""");
            Regex ZoneRegex = new Regex(@".* = ""(.+)""");
            Regex LevelRegex = new Regex(@"(\d+)");
            Regex TimeStampRegex = new Regex(@".* = ""(.+)""");
            Regex QuestOrCreature = new Regex(@".* = ""(.+)""");
            Regex XPGainedRegex = new Regex(@"(\d+)");
            Regex EndOfIndividualGainRegex = new Regex(@"-- \[\d+\]");

            var records = new List<XPLogger> { };
            var record = new XPLogger();

            foreach (string line in lines)
            {
                if (line.Contains("[\"Total XP\"]"))
                {
                    Match match = TotalXPRegex.Match(line);
                    record.TotalXP = Int16.Parse(match.Groups[1].Value);
                    continue;
                }

                if (line.Contains("[\"Creature\"]"))
                {
                    Match match = CreatureRegex.Match(line);
                    record.Creature = match.Groups[1].Value;
                    continue;
                }

                if (line.Contains("[\"Minimap Zone\"]"))
                {
                    Match match = MinimapZoneRegex.Match(line);
                    record.MinimapZone = match.Groups[1].Value;
                    continue;
                }

                if (line.Contains("[\"Zone\"]"))
                {
                    Match match = ZoneRegex.Match(line);
                    record.Zone = match.Groups[1].Value;
                    continue;
                }

                if (line.Contains("[\"Level\"]"))
                {
                    Match match = LevelRegex.Match(line);
                    record.Level = Int16.Parse(match.Groups[1].Value);
                    continue;
                }

                if (line.Contains("[\"Timestamp\"]"))
                {
                    Match match = TimeStampRegex.Match(line);
                    record.TimeStamp = match.Groups[1].Value;
                    continue;
                }

                if (line.Contains("[\"Quest or Creature\"]"))
                {
                    Match match = QuestOrCreature.Match(line);
                    record.QuestOrCreature = match.Groups[1].Value;
                    continue;
                }

                if (line.Contains("[\"XP Gained\"]"))
                {
                    Match match = XPGainedRegex.Match(line);
                    record.XPGained = Int16.Parse(match.Groups[1].Value);
                    continue;
                }

                if (EndOfIndividualGainRegex.IsMatch(line))
                {
                    records.Add(record);
                    record = new XPLogger();
                }

            }

            string newFile = SaveFile("Select file to output", "csv", "csv files(*.csv) | *.csv");

            if (newFile == null) return;

            using (var writer = new StreamWriter(newFile))
            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                csv.WriteRecords(records);
            }


        }
Thanks!!!!
__________________
Author of JWExpBar and JWRepBar.
  Reply With Quote
06-20-20, 11:27 PM   #11
Adapt
A Murloc Raider
Join Date: Jun 2020
Posts: 6
To continue with this thread, is there a way to catch XP awarded through exploring a new zone? Those don't seem to get captured by CHAT_MSG_COMBAT_XP_GAIN.

Thanks
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Logging all XP gains

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