235 lines
4.7 KiB
Plaintext
Executable File
235 lines
4.7 KiB
Plaintext
Executable File
/*
|
|
Utility for logging user statistics and events to a database.
|
|
|
|
Author: Jason Hayes (jason.hayes@rockstarsandiego.com)
|
|
|
|
Example:
|
|
|
|
-- Timing example.
|
|
|
|
exportUsage = RsUsage()
|
|
exportUsage.start "Map Export" "Export textures"
|
|
|
|
-- Export textures process
|
|
|
|
exportUsage.start "Map Export" "Syncing textures"
|
|
|
|
-- Syncing textures process
|
|
|
|
exportUsage.stop() -- Stop syncing textures timer.
|
|
|
|
exportUsage.stop() -- Stop export textures timer.
|
|
|
|
-- After export is finished.
|
|
if exportUsage.anyStillRunning() then (
|
|
exportUsage.stopAll()
|
|
)
|
|
|
|
|
|
-- Event example.
|
|
|
|
on button clicked do (
|
|
RsLogEvent "The Tool Name" "The button was clicked."
|
|
)
|
|
|
|
*/
|
|
|
|
struct RsUsageTimer (
|
|
/*
|
|
Wrapper for working with a RSG.MaxUtils.UserStatisticsTimer object.
|
|
*/
|
|
|
|
private
|
|
|
|
usageTimer = undefined,
|
|
|
|
|
|
public
|
|
|
|
enabled = true,
|
|
id = undefined,
|
|
guid = undefined,
|
|
filename = undefined,
|
|
|
|
|
|
-- Methods
|
|
|
|
fn start scope = (
|
|
/*
|
|
Start the timer, using the supplied scope.
|
|
*/
|
|
local result = false
|
|
|
|
if usageTimer == undefined then (
|
|
if id == undefined or filename == undefined then (
|
|
RsAssert ( id != undefined or filename != undefined )
|
|
|
|
) else (
|
|
usageTimer = dotNetObject "RSG.MaxUtils.UserStatisticsTimer" id filename
|
|
)
|
|
)
|
|
|
|
if usageTimer != undefined then (
|
|
if enabled do (
|
|
usageTimer.Start scope
|
|
|
|
result = true
|
|
)
|
|
) else (
|
|
RsAssert ( usageTimer != undefined ) message:"Cannot start usage timer because the dotNet object has not been created!"
|
|
)
|
|
|
|
result
|
|
),
|
|
|
|
fn stop = (
|
|
/*
|
|
Stop the timer.
|
|
*/
|
|
local result = false
|
|
|
|
if usageTimer != undefined then (
|
|
if enabled do (
|
|
usageTimer.Stop()
|
|
|
|
result = true
|
|
)
|
|
) else (
|
|
RsAssert ( usageTimer != undefined ) message:"Cannot stop usage timer because the dotNet object has not been created!"
|
|
)
|
|
|
|
result
|
|
)
|
|
)
|
|
|
|
|
|
struct RsUsage
|
|
(
|
|
/*
|
|
Manager class for dealing with usage statistics. This class employs a push/pop method, where each time .start
|
|
is called, a new RsUsageTimer is placed on the stack. Every time .stop is called, the last RsUsageTimer on the
|
|
stack will be stopped and popped off the stack.
|
|
*/
|
|
|
|
private
|
|
|
|
-- Stack of usage timers.
|
|
usageTimerStack = #(),
|
|
|
|
-- Current position on the stack.
|
|
currentStackPos = 0,
|
|
|
|
-- Link timers via a GUID.
|
|
guid = undefined,
|
|
|
|
|
|
public
|
|
|
|
enabled = true,
|
|
|
|
|
|
-- Methods
|
|
|
|
fn start id scope filename:"" = (
|
|
/*
|
|
Creates a new RsUsageTimer, places it on the stack and starts the timer.
|
|
*/
|
|
|
|
if enabled then (
|
|
|
|
-- If no timers have been started, then generate a new GUID.
|
|
if usageTimerStack.count == 0 then (
|
|
local dotNetGuid = dotNetClass "System.Guid"
|
|
newGuid = dotNetGuid.NewGuid()
|
|
|
|
guid = newGuid.ToString()
|
|
)
|
|
|
|
local newTimer = RsUsageTimer()
|
|
newTimer.id = id
|
|
newTimer.guid = guid
|
|
newTimer.filename = filename
|
|
|
|
append usageTimerStack newTimer
|
|
|
|
newTimer.start scope
|
|
|
|
currentStackPos += 1
|
|
)
|
|
|
|
-- Return stack position in case it's useful.
|
|
currentStackPos
|
|
),
|
|
|
|
fn stop = (
|
|
/*
|
|
Stops and removes the last timer placed on the stack.
|
|
*/
|
|
local result = false
|
|
|
|
if enabled then (
|
|
|
|
-- Still have usage timers on the stack.
|
|
if usageTimerStack.count > 0 and currentStackPos <= usageTimerStack.count then (
|
|
local existingTimer = usageTimerStack[ currentStackPos ]
|
|
|
|
if existingTimer != undefined then (
|
|
existingTimer.stop()
|
|
|
|
deleteItem usageTimerStack currentStackPos
|
|
|
|
currentStackPos -= 1
|
|
|
|
if currentStackPos == 0 then (
|
|
guid = undefined
|
|
)
|
|
|
|
result = true
|
|
)
|
|
|
|
-- No usage timers left.
|
|
) else if usageTimerStack.count == 0 and currentStackPos == 0 then (
|
|
format "No usage timers to stop!\n"
|
|
|
|
-- Something bad happened to the stack.
|
|
) else (
|
|
format "Cannot stop usage timer. Internal usage timer stack is wrong, or the stack position index (%) is incorrect.\n" currentStackPos
|
|
)
|
|
)
|
|
|
|
result
|
|
),
|
|
|
|
fn stopAll = (
|
|
/*
|
|
Stops all timers and cleans up the stack.
|
|
*/
|
|
local numTimersInStack = usageTimerStack.count
|
|
|
|
for stackIdx = 1 to numTimersInStack do (
|
|
stop()
|
|
)
|
|
),
|
|
|
|
fn anyStillRunning = (
|
|
/*
|
|
Returns whether any timers are still running.
|
|
*/
|
|
local result = false
|
|
|
|
if usageTimerStack.count > 0 then (
|
|
result = true
|
|
)
|
|
|
|
result
|
|
)
|
|
)
|
|
|
|
|
|
fn RsLogEvent identifier message = (
|
|
/*
|
|
Logs a single event to the Usage Statistics database.
|
|
*/
|
|
( dotNetObject "RSG.MaxUtils.UserStatistics" ).RegisterUsage identifier message
|
|
)
|