Skip to content

Commit

Permalink
Merge faa686a into 3920704
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensayshi committed Jun 25, 2019
2 parents 3920704 + faa686a commit 19df49c
Show file tree
Hide file tree
Showing 15 changed files with 404 additions and 55 deletions.
2 changes: 2 additions & 0 deletions TheClassicRace.toc
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ src\core\core.lua
src\core\tracker.lua
src\core\updater.lua
src\core\scan.lua
src\core\chat-notifier.lua
src\gui\status-frame.lua
7 changes: 4 additions & 3 deletions src/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ local TheClassicRaceConfig = {
Id = 1, -- will be set at runtime to channel ID when joined
},
Events = {
Ding = "TCRACE_DING",
RequestUpdate = "TCRACE_REQUEST_UPDATE",
PlayerInfo = "TCRACE_NET_PLAYER_INFO",
RequestUpdate = "TCRACE_NET_REQUEST_UPDATE",
},
},
Events = {
PlayerInfo = "TCRACE_PLAYER_INFO",
SlashWhoResult = "TCRACE_WHO_RESULT",
Ding = "TCRACE_DING",
},
}
TheClassicRace.Config = TheClassicRaceConfig
49 changes: 49 additions & 0 deletions src/core/chat-notifier.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
-- Addon global
local TheClassicRace = _G.TheClassicRace

--[[
ChatNotifier is responsible for notifying the user about events through the chat window
based on events from the EventBus
]]--
---@class TheClassicRaceChatNotifier
---@field Core TheClassicRaceCore
---@field EventBus TheClassicRaceEventBus
local TheClassicRaceChatNotifier = {}
TheClassicRaceChatNotifier.__index = TheClassicRaceChatNotifier
TheClassicRace.ChatNotifier = TheClassicRaceChatNotifier
setmetatable(TheClassicRaceChatNotifier, {
__call = function(cls, ...)
return cls.new(...)
end,
})

function TheClassicRaceChatNotifier.new(Config, Core, EventBus)
local self = setmetatable({}, TheClassicRaceChatNotifier)

self.Config = Config
self.Core = Core
self.EventBus = EventBus

-- subscribe to local events
EventBus:RegisterCallback(self.Config.Events.Ding, self, self.OnDing)

return self
end

function TheClassicRaceChatNotifier:OnDing(playerInfo, rank)
if rank == 1 then
if playerInfo.level == self.Config.MaxLevel then
TheClassicRace:PPrint("The race is over! Gratz to " .. playerInfo.name .. ", first to reach max level!!")
else
TheClassicRace:PPrint("Gratz to " .. TheClassicRace:PlayerChatLink(playerInfo.name) .. ", " ..
"first to reach level " .. playerInfo.level .. "!")
end
else
if playerInfo.level == self.Config.MaxLevel then
TheClassicRace:PPrint("Gratz to " .. playerInfo.name .. ", reached max level as #" .. rank .. "!")
else
TheClassicRace:PPrint("Gratz to " .. playerInfo.name .. ", reached level " .. playerInfo.level .. "! " ..
"Currently rank #" .. rank .. " in the race!")
end
end
end
42 changes: 37 additions & 5 deletions src/core/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,36 @@ setmetatable(TheClassicRaceCore, {
function TheClassicRaceCore.new(player, realm)
local self = setmetatable({}, TheClassicRaceCore)

self.realm = realm
self.realme = self:PlayerFull(player, realm)
self.me = self.realme
self.InitMe(self, player, realm)

return self
end

function TheClassicRaceCore:PlayerFull(name, realm)
function TheClassicRaceCore:InitMe(player, realm)
TheClassicRace:DebugPrint("InitMe: " .. tostring(player) .. ", " .. tostring(realm))
if realm == nil then
realm = "NaN"
end

self.realm = realm
self.realme = player
self.me = self.realme
end

function TheClassicRaceCore:PlayerFull(player, realm)
if realm == nil then
realm = self.realm
end

return name .. "-" .. realm
return player .. "-" .. realm
end

function TheClassicRaceCore:IsMyRealm(realm)
return realm == nil or realm == self.realm
end

function TheClassicRaceCore:MyRealm()
return self.realm
end

function TheClassicRaceCore:Me()
Expand All @@ -41,6 +58,21 @@ function TheClassicRaceCore:RealMe()
return self.realme
end

function TheClassicRaceCore:FullMe()
return self:PlayerFull(self.me)
end

function TheClassicRaceCore:FullRealMe()
return self:PlayerFull(self.realme)
end

function TheClassicRaceCore:SplitFullPlayer(fullPlayer)
local splt = TheClassicRace.SplitString(fullPlayer, "-")

return splt[1], splt[2]
end


function TheClassicRaceCore:Now()
return GetServerTime()
end
14 changes: 14 additions & 0 deletions src/core/scan.lua
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,23 @@ end

function TheClassicRaceScan:Shortcut()
local function cb(query, result, complete)
-- filter out nils, seems to be a possibility ...
-- filter out other servers ...
result = TheClassicRace.list.filter(result, function (player)
if player ~= nil and player.Name ~= nil and player.Level ~= nil then
local _, realm = self.Core:SplitFullPlayer(player.Name)

return realm == nil or self.Core:IsMyRealm(realm)
else
return false
end
end)

TheClassicRace:DebugPrint("who '" .. query .. "' result: " .. #result .. ", complete: " .. tostring(complete))

if complete and #result > 0 then
self.done = true

for _, player in ipairs(result) do
TheClassicRace:DebugPrint(" - " .. player.Name .. " lvl" .. player.Level)
end
Expand Down
42 changes: 20 additions & 22 deletions src/core/tracker.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
-- Addon global
local TheClassicRace = _G.TheClassicRace

--[[
Tracker is responsible for maintaining our leaderboard data based on data provided by other parts of the system
to us through the EventBus.
]]--
---@class TheClassicRaceTracker
---@field DB table<string, table>
---@field Core TheClassicRaceCore
Expand All @@ -27,10 +31,10 @@ function TheClassicRaceTracker.new(Config, Core, DB, EventBus, Network)
self.throttles = {}

-- subscribe to network events
EventBus:RegisterCallback(self.Config.Network.Events.Ding, self, self.OnDing)
EventBus:RegisterCallback(self.Config.Network.Events.PlayerInfo, self, self.OnPlayerInfo)
EventBus:RegisterCallback(self.Config.Network.Events.RequestUpdate, self, self.OnRequestUpdate)
-- subscribe to local events
EventBus:RegisterCallback(self.Config.Events.PlayerInfo, self, self.OnPlayerInfo)
EventBus:RegisterCallback(self.Config.Events.SlashWhoResult, self, self.OnSlashWhoResult)

return self
end
Expand Down Expand Up @@ -72,22 +76,22 @@ function TheClassicRaceTracker:OnRequestUpdate(_, sender)
table.insert(self.throttles, {sender = sender, time = now})

-- respond with leader
self.Network:SendObject(self.Config.Network.Events.Ding, {
self.Network:SendObject(self.Config.Network.Events.PlayerInfo, {
self.DB.realm.leaderboard[1].name,
self.DB.realm.leaderboard[1].level,
self.DB.realm.leaderboard[1].dingedAt
}, "WHISPER", sender)
end

function TheClassicRaceTracker:OnDing(playerInfo)
function TheClassicRaceTracker:OnPlayerInfo(playerInfo)
self:HandlePlayerInfo({
name = playerInfo[1],
level = playerInfo[2],
dingedAt = playerInfo[3],
}, false)
end

function TheClassicRaceTracker:OnPlayerInfo(playerInfo)
function TheClassicRaceTracker:OnSlashWhoResult(playerInfo)
self:HandlePlayerInfo(playerInfo, true)
end

Expand Down Expand Up @@ -161,28 +165,22 @@ function TheClassicRaceTracker:HandlePlayerInfo(playerInfo, shouldBroadcast)

-- broadcast
if shouldBroadcast then
self.Network:SendObject(self.Config.Network.Events.Ding,
self.Network:SendObject(self.Config.Network.Events.PlayerInfo,
{ playerInfo.name, playerInfo.level, dingedAt }, "CHANNEL")
self.Network:SendObject(self.Config.Network.Events.Ding,
self.Network:SendObject(self.Config.Network.Events.PlayerInfo,
{ playerInfo.name, playerInfo.level, dingedAt }, "GUILD")
end

-- new highest level! implies ding
if playerInfo.level > self.DB.realm.highestLevel then
self.DB.realm.highestLevel = playerInfo.level

-- @TODO: move out of tracker
if playerInfo.level == self.Config.MaxLevel then
TheClassicRace:PPrint("The race is over! Gratz to " .. playerInfo.name .. ", first to reach max level!!")
else
TheClassicRace:PPrint("Gratz to " .. TheClassicRace:PlayerChatLink(playerInfo.name) .. ", " ..
"first to reach level " .. playerInfo.level .. "!")
end
elseif isDing then
TheClassicRace:PPrint("Gratz to " .. playerInfo.name .. ", reached level " .. playerInfo.level .. "! " ..
"Currently rank #" .. insertAtRank .. "in the race!")
-- publish internal event
if isNew or isDing then
self.EventBus:PublishEvent(self.Config.Events.Ding, playerInfo, insertAtRank)
end

-- update highest level
self.DB.realm.highestLevel = math.max(self.DB.realm.highestLevel, playerInfo.level)

-- we only care about levels >= our bottom ranked on the leaderboard
self.DB.realm.levelThreshold = self.DB.realm.leaderboard[#self.DB.realm.leaderboard].level
if #self.DB.realm.leaderboard >= self.Config.LeaderboardSize then
self.DB.realm.levelThreshold = self.DB.realm.leaderboard[#self.DB.realm.leaderboard].level
end
end
30 changes: 24 additions & 6 deletions src/core/updater.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ local LibWho = LibStub("LibWho-2.0")
-- WoW API
local C_Timer = _G.C_Timer

--[[
Updater is responsible for periodically doing a Scan to get updated results
and relaying that back to the rest of the system through the EventBus
This is also the place where we have the LibWho specific code, so it's not being unittested atm ...
so it would be good if we can keep it small
]]--
---@class TheClassicRaceUpdater
---@field DB table<string, table>
---@field Core TheClassicRaceCore
Expand All @@ -30,7 +37,7 @@ function TheClassicRaceUpdater.new(Core, DB, EventBus)
self.Ticker = nil
self.Scan = nil

if TheClassicRace.Config.Debug then
if TheClassicRace.Config.Trace then
LibWho:SetWhoLibDebug(true)
end

Expand All @@ -45,16 +52,25 @@ function TheClassicRaceUpdater.new(Core, DB, EventBus)
end

function TheClassicRaceUpdater:ProcessWhoResult(result)
-- sort table descending on their level
table.sort(result, function(a, b)
return a.Level > b.Level
-- filter out nils, seems to be a possibility ...
result = TheClassicRace.list.filter(result, function (player)
return player ~= nil and player.Name ~= nil and player.Level ~= nil
end)

-- sort table descending on their level to make sure we don't announce multiple leaders from 1 result
-- @TODO: need to write test for this
if #result > 1 then
table.sort(result, function(a, b)
return a.Level > b.Level
end)
end

for _, player in ipairs(result) do
-- Name, Online, Guild, Class, Race, Level, Zone
local name = self.Core:SplitFullPlayer(player.Name)

self.EventBus:PublishEvent(TheClassicRace.Config.Events.PlayerInfo, {
name = player.Name,
self.EventBus:PublishEvent(TheClassicRace.Config.Events.SlashWhoResult, {
name = name,
level = player.Level,
})
end
Expand All @@ -73,11 +89,13 @@ end
function TheClassicRaceUpdater:StartScan()
-- we don't start another scan when the queue isn't empty yet
if not LibWho:AllQueuesEmpty() then
TheClassicRace:DebugPrint("StartScan but LibWho not ready")
return
end

-- don't start a scan if previous is still busy
if self.Scan ~= nil and not self.Scan:IsDone() then
TheClassicRace:DebugPrint("StartScan but scan still in progress")
return
end

Expand Down
18 changes: 13 additions & 5 deletions src/dev.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ function TheClassicRace:tcr(input)
elseif action == "reset" then
self.DB:ResetDB()

--[[SHOW FRAME]]--
elseif action == "show" then
self.StatusFrame:Show()

--[[UPDATE FRAME]]--
elseif action == "render" then
self.StatusFrame:Render()

--[[REQUEST UPDATE]]--
elseif action == "update" then
self.Tracker:RequestUpdate()
Expand All @@ -29,16 +37,16 @@ function TheClassicRace:tcr(input)
TheClassicRace:PPrint("highest level: " .. self.DB.realm.highestLevel)
TheClassicRace:PPrint("lower bound threshold: " .. self.DB.realm.levelThreshold)

for playerName, playerInfo in pairs(self.DB.realm.leaderboard) do
print(" - " .. playerName .. " lvl" .. playerInfo.level)
for rank, playerInfo in ipairs(self.DB.realm.leaderboard) do
print(" - #" .. rank .. " " .. playerInfo.name .. " lvl" .. playerInfo.level)
end

--[[DING name level]]--
elseif action == "ding" then
TheClassicRace:DebugPrint("Forced Ding [" .. arg1 .. "] lvl" .. arg2 .. ".")
self.EventBus:PublishEvent(self.Config.Events.PlayerInfo, {
Name = arg1,
Level = tonumber(arg2),
self.EventBus:PublishEvent(self.Config.Events.SlashWhoResult, {
name = arg1,
level = tonumber(arg2),
})
else
self:PPrint("Unknown action: " .. tostring(action))
Expand Down
Loading

0 comments on commit 19df49c

Please sign in to comment.