Quantcast

Added highscore database.

Peter Eliasson [01-11-15 - 19:23]
Added highscore database.
Filename
GuildSkadaHighScore.toc
highscore.lua
inspect.lua
lib/lib.xml
main.lua
main.xml
diff --git a/GuildSkadaHighScore.toc b/GuildSkadaHighScore.toc
index b826101..cd633f0 100644
--- a/GuildSkadaHighScore.toc
+++ b/GuildSkadaHighScore.toc
@@ -3,6 +3,7 @@
 ## Version: 0.01
 ## Title: Guild Skada High Score
 ## Notes: Ranking for dps/hps for raid bosses in a guild.
+## SavedVariables: GuildSkadaHighScoreDB
 ## Dependencies: Skada

 lib/lib.xml
diff --git a/highscore.lua b/highscore.lua
new file mode 100644
index 0000000..3aee5bc
--- /dev/null
+++ b/highscore.lua
@@ -0,0 +1,113 @@
+local addonName, addonTable = ...
+
+-- Global functions for faster access
+local tinsert = tinsert;
+local tContains = tContains;
+
+-- Set up module
+local addon = addonTable[1];
+local highscore = addon:NewModule("highscore", "AceEvent-3.0", "AceTimer-3.0")
+addon.highscore = highscore;
+
+-- db defaults
+addon.dbDefaults.realm.modules["highscore"] = {
+	["zones"] = {
+	--[[
+		["*"] = { -- zoneId
+			zoneName = "Unknown",
+			encounters = {
+				["*"] = { -- encounterId
+					encounterName = "Unknown",
+					difficulties = {
+						["**"] = {
+							playerParses = {} -- List of objects "{playerInfo, role, dps, hps}"
+						},
+						["Normal"] = {},
+						["Heroic"] = {},
+						["Mythic"] = {}
+					}
+				}
+			}
+		}
+	--]]
+	}
+}
+
+
+local trackedZoneIds = {994}
+
+function highscore:GetOrCreateEncounterTable(zoneId, zoneName, encounterId, encounterName, difficultyName)
+	if not self.db.zones[zoneId] then
+		self.db.zones[zoneId] = {zoneName = zoneName, encounters = {}}
+	end
+
+	local zone = self.db.zones[zoneId]
+	if not zone.encounters[encounterId] then
+		zone.encounters[encounterId] = {
+			encounterName = encounterName,
+			difficulties = {
+				Normal = {playerParses = {}},
+				Heroic = {playerParses = {}},
+				Mythic = {playerParses = {}}
+		}};
+	end
+
+	local encounter = zone.encounters[encounterId]
+	if not encounter.difficulties[difficultyName] then
+		return nil
+	else
+		return encounter.difficulties[difficultyName]
+	end
+end
+
+function highscore:AddEncounterParseForPlayer(zoneId, zoneName, encounterId, encounterName, difficultyName, player)
+	local encounterTable = self:GetOrCreateEncounterTable(zoneId,
+		zoneName, encounterId, encounterName, difficultyName);
+
+	if encounterTable then
+		local parse = {
+			playerId = player.id,
+			playerName = player.name,
+			role = player.role,
+			specName = player.specName,
+			itemLevel = player.itemLevel,
+			damage = player.damage,
+			healing = player.healing,
+			duration = encounter.duration
+		}
+		tinsert(encounterTable.playerParses, parse);
+	end
+end
+
+function highscore:AddEncounterParsesForPlayers(encounter, players)
+	local zoneId = encounter.zoneId;
+	local zoneName = encounter.zoneName;
+	local encounterId = encounter.id;
+	local encounterName = encounter.name;
+	local difficultyName = encounter.difficultyName;
+
+	assert(zoneId and zoneId > 1)
+	assert(zoneName)
+	assert(encounterId)
+	assert(encounterName)
+	assert(difficultyName)
+	assert(players)
+
+	if not tContains(trackedZoneIds, zoneId) then
+		self:Debug("Current zone not not in tracked zones");
+		return
+	end
+
+	for _, player in ipairs(players) do
+		self:AddEncounterParseForPlayer(zoneId, zoneName,
+			encounterId, encounterName, difficultyName, player)
+	end
+end
+
+function highscore:OnEnable()
+	self.db = addon.db.realm.modules["highscore"];
+end
+
+function highscore:OnDisable()
+	self.db = nil;
+end
diff --git a/inspect.lua b/inspect.lua
index 2130e4e..dabe888 100644
--- a/inspect.lua
+++ b/inspect.lua
@@ -1,7 +1,14 @@
 local addonName, addonTable = ...

+-- Global functions for faster access
+local tinsert = tinsert;
+local floor = floor;
+local wipe = wipe;
+
+-- Set up module
 local addon = addonTable[1];
-local inspect = addon.inspect;
+local inspect = addon:NewModule("inspect", "AceEvent-3.0", "AceTimer-3.0")
+addon.inspect = inspect;

 -- Constants
 local INSPECT_CACHE_TIMEOUT = 900;
@@ -10,10 +17,7 @@ local INVENTORY_SLOT_NAMES = {
 	"HandsSlot","WaistSlot","LegsSlot","FeetSlot","Finger0Slot","Finger1Slot",
 	"Trinket0Slot","Trinket1Slot","MainHandSlot","SecondaryHandSlot"
 }
-
-inspect.inspectQueue = {};
-inspect.notifyInspectTimer = nil;
-inspect.currentInspectPlayerId = nil;
+local NOOP = function() end

 local playerGUID = UnitGUID("player");
 local inspectCache = {};
@@ -65,12 +69,15 @@ local function getItemLevel(unitName)
 end

 local function hasPlayerInspectCache(playerId, ignoreExpired)
-	if not inspectCache[playerId] then
-		return false; -- No entry for player id
-	elseif not ignoreExpired and ((GetTime() - inspectCache[playerId].time) > INSPECT_CACHE_TIMEOUT) then
-		return false; -- Cache entry is too old
+	if inspectCache[playerId] and ignoreExpired then
+		return true -- We have a cache, might be expired
+	elseif inspectCache[playerId] and inspectCache[playerId].time then
+		local isExpired = (GetTime() - inspectCache[playerId].time) > INSPECT_CACHE_TIMEOUT
+		local hasAllAttributes = inspectCache[playerId].specName and inspectCache[playerId].itemLevel;
+
+		return (not isExpired and hasAllAttributes)
 	else
-		return true;
+		return false; -- No entry for player id
 	end
 end

@@ -83,15 +90,15 @@ end

 function inspect:StartNotifyInspectTimer()
 	if not self.notifyInspectTimer then
-		self.notifyInspectTimer = addon:ScheduleRepeatingTimer(function()
-			self:NOTIFY_INSPECT_TIMER_DONE();
-		end, 1)
+		self.notifyInspectTimer = self:ScheduleRepeatingTimer(function()
+			self:NOTIFY_INSPECT_TIMER_DONE()
+		end, 1);
 	end
 end

 function inspect:StopNotifyInspectTimer()
 	if self.notifyInspectTimer then
-		addon:CancelTimer(self.notifyInspectTimer);
+		self:CancelTimer(self.notifyInspectTimer);
 		self.notifyInspectTimer = nil;
 	end
 end
@@ -108,7 +115,7 @@ function inspect:IsPlayerInInspectQueue(player)
 end

 function inspect:QueueInspect(player, callback)
-	addon:Debug("QueueNotifyInspect " .. player.name)
+	self:Debug("QueueNotifyInspect " .. player.name)

 	if not self.inspectQueue[player.id] then
 		self.inspectQueue[player.id] = {player = player, callbacks = {}};
@@ -138,6 +145,9 @@ function inspect:SetCachedInspectDataForPlayer(player)
 end

 function inspect:GetInspectDataForPlayer(player, callback)
+	-- Make sure we always have a callback
+	callback = callback and callback or NOOP;
+
 	if self:SetCachedInspectDataForPlayer(player) then
 		return callback()
 	elseif not CanInspect(player.name, false) then
@@ -162,8 +172,6 @@ function inspect:GetInspectDataForPlayers(players, callback)
 end

 function inspect:ResolveInspect(playerId, success)
-	addon:Debug("ResolveInspect " .. playerId .. " " .. (success and "success" or "fail"))
-
 	if not self.inspectQueue[playerId] then
 		return
 	end
@@ -172,6 +180,8 @@ function inspect:ResolveInspect(playerId, success)
 	local callbacks = self.inspectQueue[playerId].callbacks;
 	self.inspectQueue[playerId] = nil;

+	self:Debug("ResolveInspect " .. player.name .. " " .. (success and "success" or "fail"))
+
 	if success then
 		if not hasPlayerInspectCache(player.id) then
 			local specName = getTalentSpec(player.name);
@@ -188,9 +198,20 @@ function inspect:ResolveInspect(playerId, success)
 	end
 end

-function inspect:NOTIFY_INSPECT_TIMER_DONE()
-	addon:Debug("NOTIFY_INSPECT_TIMER_DONE");
+function inspect:PreInspectGroup()
+	for i=1, GetNumGroupMembers() do
+		local playerName = GetRaidRosterInfo(i);
+		if playerName then
+			local playerId = UnitGUID(playerName)
+			if playerId and not hasPlayerInspectCache(playerId) and CanInspect(playerName) then
+				local player = {name=playerName, id = playerId}
+				self:QueueInspect(player, NOOP);
+			end
+		end
+	end
+end

+function inspect:NOTIFY_INSPECT_TIMER_DONE()
 	-- Timeout any current inspection
 	if self.currentInspectPlayerId then
 		self:ResolveInspect(self.currentInspectPlayerId, false);
@@ -211,4 +232,42 @@ function inspect:INSPECT_READY(evt, GUID)
 		self:ResolveInspect(self.currentInspectPlayerId, true)
 		self.currentInspectPlayerId = nil;
 	end
+end
+
+function inspect:GROUP_ROSTER_UPDATE(evt)
+	if not IsInGroup() then
+		self:Debug("Left group, wiping inspect cache");
+		wipe(inspectCache);
+		wipe(inspect.inspectQueue);
+		inspect.currentInspectPlayerId = nil;
+	end
+end
+
+function inspect:ZONE_CHANGED_NEW_AREA(evt)
+	if IsInInstance() and IsInRaid() then
+		-- We just zoned into an instance, try pre-inspecting the group
+		self:PreInspectGroup();
+	end
+end
+
+function inspect:OnEnable()
+	inspect.inspectQueue = {};
+	inspect.notifyInspectTimer = nil;
+	inspect.currentInspectPlayerId = nil;
+
+	self:RegisterEvent("INSPECT_READY");
+	self:RegisterEvent("GROUP_ROSTER_UPDATE");
+	self:RegisterEvent("ZONE_CHANGED_NEW_AREA");
+end
+
+function inspect:OnDisable()
+	self:UnregisterEvent("INSPECT_READY");
+	self:UnregisterEvent("GROUP_ROSTER_UPDATE");
+	self:UnregisterEvent("ZONE_CHANGED_NEW_AREA");
+
+	self:StopNotifyInspectTimer();
+
+	wipe(inspectCache);
+	wipe(inspect.inspectQueue);
+	inspect.currentInspectPlayerId = nil;
 end
\ No newline at end of file
diff --git a/lib/lib.xml b/lib/lib.xml
index 579e7fe..a47ad4c 100644
--- a/lib/lib.xml
+++ b/lib/lib.xml
@@ -6,4 +6,5 @@
     <Include file="Ace3\AceGUI-3.0\AceGUI-3.0.xml"/>
     <Include file="Ace3\AceHook-3.0\AceHook-3.0.xml"/>
     <Include file="Ace3\AceTimer-3.0\AceTimer-3.0.xml"/>
+    <Include file="Ace3\AceDB-3.0\AceDB-3.0.xml"/>
 </Ui>
\ No newline at end of file
diff --git a/main.lua b/main.lua
index 3606815..de34b7a 100644
--- a/main.lua
+++ b/main.lua
@@ -1,21 +1,25 @@
 local addonName, addonTable = ...

 local tinsert = tinsert;
-local tremove = tremove;
-local tContains = tContains;
-local floor = floor;

 -- Create ACE3 addon
-local addon = LibStub("AceAddon-3.0"):NewAddon(addonName,
-	"AceConsole-3.0", "AceEvent-3.0", "AceHook-3.0", "AceTimer-3.0")
+local addon = LibStub("AceAddon-3.0"):NewAddon(addonName, "AceConsole-3.0", "AceEvent-3.0", "AceHook-3.0")
+
+-- Set up a default prototype for all modules
+local modPrototype = { Debug = function(self, ...) addon:Debug(...) end }
+addon:SetDefaultModulePrototype(modPrototype)
+
+
+-- Db default settings
+addon.dbDefaults = {
+	realm = {
+		modules = {}
+	}
+}

 tinsert(addonTable, addon);
 _G[addonName] = addon

-addon.currentEncounter = nil;
-addon.currentZoneId = nil;
-addon.guildName = nil;
-addon.inspect = {};

 local function getDifficultyNameById(difficultyId)
 	if difficultyId == 7 or difficultyId == 17 then
@@ -46,14 +50,30 @@ function addon:UpdateMyGuildName()
 	end
 end

+function addon:UpdateCurrentZone()
+	local zoneId, _ = GetCurrentMapAreaID()
+	local zoneName = GetRealZoneText();
+	self.currentZone = {id = zoneId, name = zoneName};
+
+	if not IsInInstance() then
+		self:UnsetCurrentEncounter();
+	end
+end
+
 function addon:SetCurrentEncounter(encounterId, encounterName, difficultyId, raidSize)
-	self.currentEncounter = {
-		id = encounterId,
-		name = encounterName,
-		difficultyId = difficultyId,
-		difficultyName = getDifficultyNameById(difficultyId),
-		raidSize = raidSize
-	}
+
+	local difficultyName = getDifficultyNameById(difficultyId);
+	if difficultyName then
+		self.currentEncounter = {
+			zoneId = self.currentZone.id,
+			zoneName = self.currentZone.name,
+			id = encounterId,
+			name = encounterName,
+			difficultyId = difficultyId,
+			difficultyName = difficultyName,
+			raidSize = raidSize
+		}
+	end
 end

 function addon:UnsetCurrentEncounter()
@@ -61,7 +81,6 @@ function addon:UnsetCurrentEncounter()
 end

 function addon:IsInMyGuild(playerName)
-	if 1 then return true end
 	if self.guildName then
 		local guildName, _, _ = GetGuildInfo(playerName)
 		return guildName == self.guildName
@@ -102,7 +121,7 @@ function addon:PLAYER_GUILD_UPDATE(evt, unitId)
 end

 function addon:ENCOUNTER_START(evt, encounterId, encounterName, difficultyId, raidSize)
-	self:Debug("ENCOUNTER_START")
+	self:Debug("ENCOUNTER_START " .. encounterId)
 	self:SetCurrentEncounter(encounterId, encounterName, difficultyId, raidSize)
 end

@@ -115,6 +134,11 @@ function addon:ENCOUNTER_END(evt, encounterId, encounterName, difficultyId, raid
 	end
 end

+function addon:ZONE_CHANGED_NEW_AREA(evt)
+	self:Debug("ZONE_CHANGED_NEW_AREA");
+	self:UpdateCurrentZone();
+end
+
 function addon:EndSegment()
 	self:Debug("EndSegment")

@@ -123,53 +147,47 @@ function addon:EndSegment()
 		return
 	end

-	local encounter = self.currentEncounter
+	local encounter = self.currentEncounter;
+	encounter.duration = Skada.last.time;
+
 	local players = self:GetGuildPlayersFromSet(Skada.last);
 	self:SetRoleForPlayers(players);
 	self.inspect:GetInspectDataForPlayers(players, function()
-		for i, player in ipairs(players) do
-			local name = player.name;
-			local damage = Skada:FormatNumber(player.damage);
-			local role = player.role;
-			local itemLevel = player.itemLevel and player.itemLevel or "N/A"
-			local specName = player.specName and player.specName or "N/A"
-			-- "(DAMAGE) Saniera - 20.1k (560 Shadow)"
-			self:Debug(format("(%s) %s - %s (%d %s)", role, name, damage, itemLevel, specName));
-		end
+		self.highscore:AddEncounterParsesForPlayers(encounter, players);
 	end)

-	--[[
-	self:Printf("%s (%s - %d) %dm",
-		encounter.name,
-		encounter.difficultyName and encounter.difficultyName or "Unknown",
-		encounter.difficultyId,
-		encounter.raidSize);
-	]]--
 	self:UnsetCurrentEncounter();
 end

-
 function addon:OnInitialize()
+	self.db = LibStub("AceDB-3.0"):New("GuildSkadaHighScoreDB", addon.dbDefaults)
 end

 function addon:OnEnable()
+	self.currentEncounter = nil;
+	self.currentZone = {};
+	self.guildName = nil;
+
 	self:RegisterEvent("ENCOUNTER_START")
 	self:RegisterEvent("ENCOUNTER_END")
 	self:RegisterEvent("PLAYER_GUILD_UPDATE")
-	self:RegisterEvent("INSPECT_READY")
+	self:RegisterEvent("ZONE_CHANGED_NEW_AREA")

 	self:SecureHook(Skada, "EndSegment")

 	self:UpdateMyGuildName()
+	self:UpdateCurrentZone();
 end

 function addon:OnDisable()
-	self:UnRegisterEvent("ENCOUNTER_START")
-	self:UnRegisterEvent("ENCOUNTER_END")
-	self:UnRegisterEvent("PLAYER_GUILD_UPDATE")
-	self:UnRegisterEvent("INSPECT_READY")
-
-	self:StopNotifyInspectTimer();
+	self.currentEncounter = nil;
+	self.currentZone = {};
+	self.guildName = nil;
+
+	self:UnregisterEvent("ENCOUNTER_START")
+	self:UnregisterEvent("ENCOUNTER_END")
+	self:UnregisterEvent("PLAYER_GUILD_UPDATE")
+	self:UnregisterEvent("ZONE_CHANGED_NEW_AREA")

     self:UnHook(Skada, "EndSegment")
 end
diff --git a/main.xml b/main.xml
index 2af183a..82c4b1f 100644
--- a/main.xml
+++ b/main.xml
@@ -1,4 +1,5 @@
 <Ui xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\..\FrameXML\UI.xsd">
     <Script file="main.lua"/>
     <Script file="inspect.lua"/>
+    <Script file="highscore.lua"/>
 </Ui>
\ No newline at end of file