Quantcast

Cleanup of database structure.

Peter Eliasson [01-15-15 - 00:29]
Cleanup of database structure.

* Tried to remove all redundant data (zone name for a zone id was repeated for each zone, same for encounter name and player name).
* Some general cleanup of the code, broken into smaller functions.
Filename
highscore.lua
diff --git a/highscore.lua b/highscore.lua
index 417aeb3..e2399a0 100644
--- a/highscore.lua
+++ b/highscore.lua
@@ -4,6 +4,8 @@ local addonName, addonTable = ...
 local tinsert = tinsert;
 local tContains = tContains;
 local sort = sort;
+local random = random;
+local format = format;

 -- Set up module
 local addon = addonTable[1];
@@ -16,23 +18,19 @@ addon.dbDefaults.realm.modules["highscore"] = {
 		["*"] = { -- Guild Name
 			["zones"] = {
 				["*"] = { -- zoneId
-					zoneName = nil, -- Note: Must be set.
 					encounters = {
 						["*"] = { -- encounterId
-							encounterName = nil, -- Note: Must be set.
 							difficulties = {
 								-- playerParses is a list of objects:
 								--[[
 									{
-										playerId 	= "",
-										playerName 	= "",
-										role 		= "",
-										specName 	= "",
-										itemLevel 	= 0,
-										damage 		= 0,
-										healing 	= 0,
-										duration 	= 0,
-										startTime 	= 0
+										playerId 	 = "",
+										role 		 = "",
+										specName 	 = "",
+										itemLevel 	 = 0,
+										damage 		 = 0,
+										healing 	 = 0,
+										groupParseId = ""
 									}
 								--]]
 								["LFR"] 	= {playerParses = {}},
@@ -45,10 +43,34 @@ addon.dbDefaults.realm.modules["highscore"] = {
 				}
 			}
 		}
+	},
+	["zones"] = {
+		["*"] = { -- zoneId
+			zoneName = nil
+		}
+	},
+	["encounters"] = {
+		["*"] = { -- encounterId
+			encounterName = nil
+		}
+	},
+	["players"] = {
+		["*"] = { -- playerId
+			name 	= nil,
+			class 	= nil
+		}
+	},
+	["groupParses"] = {
+		--[[
+		["*"] = { -- groupParseId
+			startTime 	= 0,
+			duration 	= 0,
+		}
+		--]]
 	}
 }

-addon.dbVersion = addon.dbVersion + 2
+addon.dbVersion = addon.dbVersion + 3

 -- Constants
 local TRACKED_ZONE_IDS = {
@@ -56,62 +78,95 @@ local TRACKED_ZONE_IDS = {
 }


-local function getOrCreateEncounterTable(db, guildName, zoneId, zoneName, encounterId, encounterName, difficultyName)
-	local guildTable = db.guilds[guildName];
-	local zoneTable = guildTable.zones[zoneId];
-	local encounterTable = zoneTable.encounters[encounterId];
+local function generateRandomKey()
+	local r1 = random(0, 1000);
+	local r2 = random(0, 1000);
+	local r3 = random(0, 1000);
+	-- 1000^3 = 1´000´000´000, should be enough for now...
+	return format("%x-%x-%x", r1, r2, r3);
+end

-	if not zoneTable.zoneName then
-		zoneTable.zoneName = zoneName;
+local function addGroupParse(db, startTime, duration)
+	-- Find a new unique key for the raid parse
+	local key = generateRandomKey();
+	while db.groupParses[key] do
+		key = generateRandomKey();
 	end

-	if not encounterTable.encounterName then
-		encounterTable.encounterName = encounterName;
-	end
+	db.groupParses[key] = {
+		startTime 	= startTime,
+		duration 	= duration
+	};
+
+	return key
+end
+
+local function addZone(db, zoneId, zoneName)
+	db.zones[zoneId].zoneName = zoneName;
+end
+
+local function addEncounter(db, encounterId, encounterName)
+	db.encounters[encounterId].encounterName = encounterName;
+end
+
+local function addPlayer(db, playerId, playerName, playerClass)
+	db.players[playerId].name = playerName;
+	db.players[playerId].class = playerClass;
+end
+
+local function getParsesTable(db, guildName, zoneId, encounterId, difficultyName)
+	local encounterTable = db.guilds[guildName].zones[zoneId].encounters[encounterId];

 	if not encounterTable.difficulties[difficultyName] then
 		return nil
 	else
-		return encounterTable.difficulties[difficultyName]
+		return encounterTable.difficulties[difficultyName].playerParses
 	end
 end

-local function addEncounterParseForPlayer(encounterTable, startTime, duration, player)
+local function addEncounterParseForPlayer(parsesTable, player, groupParseId)
 	local parse = {
-		playerId 	= player.id,
-		playerName 	= player.name,
-		role 		= player.role,
-		specName 	= player.specName,
-		itemLevel 	= player.itemLevel,
-		damage 		= player.damage,
-		healing 	= player.healing,
-		duration 	= duration,
-		startTime 	= startTime
+		playerId 	 = player.id,
+		role 		 = player.role,
+		specName 	 = player.specName,
+		itemLevel 	 = player.itemLevel,
+		damage 		 = player.damage,
+		healing 	 = player.healing,
+		groupParseId = groupParseId
 	}
-	tinsert(encounterTable.playerParses, parse);
+	tinsert(parsesTable, parse);
 end

 -- Function for convering a database representation of
 -- a parse to a parse that can be returned to users.
 -- Copies all values and adds calculated once (like dps)
-local function getReturnableParse(parse)
+local function getReturnableParse(db, parse)
 	local parseCopy = {};
 	for key, val in pairs(parse) do
 		parseCopy[key] = val;
 	end

-	-- Calculate values
+	-- Get duration, statTime from the group parse
+	local groupParse = db.groupParses[parse["groupParseId"]]
+	parseCopy["duration"] = groupParse.duration;
+	parseCopy["startTime"] = groupParse.startTime;
+	parseCopy["groupParseId"] = nil
+
+	-- Get player name and class
+	parseCopy["name"] = db.players[parse["playerId"]].name;
+	parseCopy["class"] = db.players[parse["playerId"]].class;
+
+	-- Calculate dps/hps
 	parseCopy["dps"] = 0;
 	parseCopy["hps"] = 0;
-	if parse.duration > 0 then
-		parseCopy["dps"] = parse.damage / parse.duration;
-		parseCopy["hps"] = parse.healing / parse.duration;
+	if parseCopy["duration"] > 0 then
+		parseCopy["dps"] = parseCopy["damage"] / parseCopy["duration"];
+		parseCopy["hps"] = parseCopy["healing"] / parseCopy["duration"];
 	end

 	return parseCopy;
 end

-
 function highscore:AddEncounterParsesForPlayers(guildName, encounter, players)
 	local zoneId = encounter.zoneId;
 	local zoneName = encounter.zoneName;
@@ -136,17 +191,26 @@ function highscore:AddEncounterParsesForPlayers(guildName, encounter, players)
 		return
 	end

-	local encounterTable = getOrCreateEncounterTable(self.db, guildName, zoneId, zoneName, encounterId, encounterName, difficultyName);
+	-- Add zone and encounter info
+	addZone(self.db, zoneId, zoneName);
+	addEncounter(self.db, encounterId, encounterName);
+
+	-- Add a group parse entry, holding data shared between all players
+	local groupParseId = addGroupParse(self.db, startTime, duration);

-	if not encounterTable then
-		self:Debug("AddEncounterParsesForPlayers: Could not get encounterTable")
+	local parsesTable = getParsesTable(self.db, guildName, zoneId, encounterId, difficultyName);
+	if not parsesTable then
+		self:Debug("AddEncounterParsesForPlayers: Could not get parsesTable")
 		return
 	end

 	for _, player in ipairs(players) do
 		self:Debug(format("addEncounterParseForPlayer: %s", player.name));
-		addEncounterParseForPlayer(encounterTable, startTime, duration, player)
+
+		addPlayer(self.db, player.id, player.name, player.class);
+		addEncounterParseForPlayer(parsesTable, player, groupParseId)
 	end
+
 end

 function highscore:GetParses(guildName, zoneId, encounterId, difficultyName, role, sortBy)
@@ -162,19 +226,18 @@ function highscore:GetParses(guildName, zoneId, encounterId, difficultyName, rol
 		end
 	end

-	local encountersTable = self.db.guilds[guildName].zones[zoneId].encounters;
-	local parsesTable = encountersTable[encounterId].difficulties[difficultyName];
+	local parsesTable = getParsesTable(self.db, guildName, zoneId, encounterId, difficultyName);
+	parsesTable = parsesTable or {};

-	-- Get a copy of all parses for the specified role
+	-- Get a *copy* of all parses for the specified role
 	local parses = {};
-	for _, parse in ipairs(parsesTable.playerParses) do
+	for _, parse in ipairs(parsesTable) do
 		if parse.role == role then
-			local parseCopy = getReturnableParse(parse);
+			local parseCopy = getReturnableParse(self.db, parse);
 			tinsert(parses, parseCopy);
 		end
 	end

-	-- Sort these parses by the sortBy field
 	sort(parses, function(a, b)
 		return a[sortBy] > b[sortBy];
 	end)
@@ -187,8 +250,9 @@ end
 function highscore:GetEncounters(guildName, zoneId)
 	local encounters = {};
 	local encountersTable = self.db.guilds[guildName].zones[zoneId].encounters;
-	for encounterId, encounter in pairs(encountersTable) do
-		tinsert(encounters, {encounterId, encounter.encounterName});
+	for encounterId, _ in pairs(encountersTable) do
+		local encounterName = self.db.encounters[encounterId].encounterName;
+		tinsert(encounters, {encounterId, encounterName});
 	end
 	return encounters;
 end
@@ -197,8 +261,9 @@ end
 -- The returned value is a list of {zoneId, zoneName}.
 function highscore:GetZones(guildName)
 	local zones = {};
-	for zoneId, zone in pairs(self.db.guilds[guildName].zones) do
-		tinsert(zones, {zoneId, zone.zoneName});
+	for zoneId, _ in pairs(self.db.guilds[guildName].zones) do
+		local zoneName = self.db.zones[zoneId].zoneName;
+		tinsert(zones, {zoneId, zoneName});
 	end
 	return zones;
 end