--[[
show_reporter.lua - provide file logging facility to Palette software
Copyright (C) 2008 Horizon Control Inc. -- support@horizoncontrol.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
This file provides logging functionality to the Strand Palette
lighting control software by Horizon Control Inc.
The initial idea came from John Grimshaw of Bytecraft, Australia
With followup work and cleanup by Robert Bell and Alan Martello of
Horizon Control Inc.
---------------------------------------------
Version History
1.00 2008/06/20 Alan Martello
Initial Release
2.00 2008/07/29 Alan Martello, Robert Bell
Added stopwatch and other date-linked html pages
---------------------------------------------
---------------------------------------------
USAGE EXAMPLES
---------------------------------------------
-- this call should not be automated - should only be called when you want to clear the logs
KillIndex()
-- Call this before calling any other logging macros - I put it in Cue 0.5 - House to half - then follow it with StartShow()
StartTodaysLog('Tale of Two Cities')
-- This is called when house goes to half
StartShow()
-- This is a called in when the curtain is raised (must put in text argument)
StartAct('Act 1')
-- call as many of these as you like - only one works in succession to the other
StartScene('blah1')
-- last cue of the scene (might be start of another or you may want to wait for next cue to call StartScene('asdf') again
EndScene()
StartScene('blah2')
EndScene()
EndAct()
StartInterval()
EndInterval()
StartAct('Act 2')
StartScene('blah3')
-- if you want a new scene's start to end the last scene - call with true argument
StartScene('blah4',true)
EndScene()
EndAct()
LogThisCue(true) -- this can be called at any time
EndShow()
----------------------------------------------------------------------------------------------
Section - Logging
----------------------------------------------------------------------------------------------
This section provides logging functionality to the Strand Palette software.
Logged data is written to a file in either html or text format as specified
by the InitializeLogFile call. If writing to html, InitializeLogFile can also
indicate a refresh time in the html for the web page. Logging can optionally
occur to the history as well.
There are only 4 routines in this section for ease of use
InitializeLogFile must be called first to specify the file to log
LogText is called to write text to the log file (optionally with the time)
LogDrawLine is used to draw a line in the log file
LogThisCue is used to log the current cue
Example:
Log data to html file that refreshes every 10 seconds on a laptop
browsing the console.
InitializeLogFile('d:\\web\\index.html', 'Show Description', true, true, 10)
This line opens the default index page on the console and creates a new file
every time. The file is opened for html writing, and will refresh every 10 seconds.
LogText('New Theater Company', nil, nil, 3)
This line logs the text 'New Theater Company' without the time and without writing it to
the history, but does display it as heading level 3 in the html
LogDrawLine()
This line draws a line in the log
LogText('Dress Rehearsal Start', true, true)
This line logs the text 'Dress Rehearsal Start' with the time and logs it to the history
LogThisCue(true, true)
This line logs the current cue with the time and displays it in the history
]]--
--[[
----------------------------------------------------------------------------------------------
Variables used to hold the file name and html/text mode for logging
----------------------------------------------------------------------------------------------
]]--
local LogFileName
local LogHtmlMode
--[[
----------------------------------------------------------------------------------------------
InitializeLogFile
Initializes the log file. Must be called one to create or open the log file.
file_name (required) - string representing the name of the log file
log_description (optional) - string (such as show name) to use to describe the log
create_new_file (optional) - if not nil, creates a new file, otherwise try and
append to an existing file
html_mode (optional) - if not nil, then format the log data as html, otherwise
format the log data as text
html_refresh_seconds (optional) - if not nil and create_new_file is not nil and
html_mode is not nil, the number of seconds to automatically use for
page refresh in the html header
----------------------------------------------------------------------------------------------
]]--
function InitializeLogFile(file_name, log_description, create_new_file, html_mode, html_refresh_seconds)
LogFileName = "" -- clear out the file name in case we have an error
if file_name == nil then
return
end
if log_description == nil or not log_description then
log_description = 'Palette Log in ' .. file_name
end
local f
if html_mode == nil or html_mode == false then
LogHtmlMode = false
else
LogHtmlMode = true
end
-- check if we need to create the new file because we can't open the file
AddHeaders = true
if create_new_file == nil or not create_new_file then
f = io.open(file_name, 'r')
if f == nil then
-- create the file
create_new_file = true
else
-- append to the current file
f:close()
AddHeaders = false
end
end
if create_new_file ~= nil and create_new_file then
-- delete the current file
os.remove(file_name)
f = io.open(file_name, 'w')
if f == nil then
-- error
return
end
-- save the file name for later logging
LogFileName = file_name
if LogHtmlMode and AddHeaders then
f:write('
\n')
if html_refresh_seconds ~= nil and html_refresh_seconds then
f:write('\n')
end
f:write('' .. log_description .. '\n')
f:write('\n')
f:write('' .. log_description .. '
\n')
--f:write('' .. 'Created at ' .. os.date() .. '
\n')
f:write('
\n')
else
f:write(log_description .. '\n')
f:write('Appending from ' .. os.date() .. '\n')
f:write('----------------------------------------------\n');
end
f:close()
else
f = io.open(file_name, 'a')
if f == nil then
-- error
return
end
-- save the file name for later logging
LogFileName = file_name
if LogHtmlMode and AddHeaders then
f:write('
\n')
f:write('' .. log_description .. '
\n')
f:write('' .. 'Log started at ' .. os.date('%x') .. '
\n')
f:write('
\n')
else
--f:write('----------------------------------------------\n');
--f:write(log_description .. '\n')
--f:write('Log continued from ' .. os.date('%x') .. '\n')
--f:write('----------------------------------------------\n');
end
f:close()
end
end
--[[
----------------------------------------------------------------------------------------------
LogText
Logs a line of text with optional time and if html format, optionally
as a heading
log_text (required) - string information to log
log_time (optional) - if not nil, include the time before log_text
log_to_history (optional) - if not nil, log the data to the history as well
heading_level (optional) - if not nil and logging in html_mode, the heading level for the text
----------------------------------------------------------------------------------------------
]]--
function LogText(log_text, log_time, log_to_history, heading_level)
if log_to_history ~= nil and log_to_history then
HC.Status(log_text)
end
-- nothing to log if no log file defined
if LogFileName == nil or LogFileName == "" then
return
end
local f = io.open(LogFileName, 'a')
if f == nil or log_text == nil then
return
end
if LogHtmlMode then
if heading_level ~= nil and heading_level and heading_level >= 1 and heading_level <=6 then
f:write('')
else
f:write('')
end
if log_time ~= nil and log_time then
f:write(os.date('%H:%M:%S') .. ' - ')
end
f:write(log_text)
if heading_level ~= nil and heading_level and heading_level >= 1 and heading_level <=6 then
f:write('
\n')
else
f:write('\n')
end
else
if log_time ~= nil and log_time then
f:write(os.date('%H:%M:%S') .. ' - ')
end
f:write(log_text .. '\n')
end
f:close()
end
--[[
----------------------------------------------------------------------------------------------
LogDrawLine
Draws a line in the log file
log_to_history (optional) - if not nil, log the data to the history as well
----------------------------------------------------------------------------------------------
]]--
function LogDrawLine(log_to_history)
if log_to_history ~= nil and log_to_history then
HC.Status('----------------------------------------------')
end
-- nothing to log if no log file defined
if LogFileName == nil or LogFileName == "" then
return
end
local f = io.open(LogFileName, 'a')
if f == nil then
return
end
if LogHtmlMode then
f:write('
\n')
else
f:write('----------------------------------------------\n');
end
f:close()
end
--[[
----------------------------------------------------------------------------------------------
LogThisCue
Logs the current cue
log_time (optional) - if not nil, include the time before log_text
log_to_history (optional) - if not nil, log the data to the history as well
----------------------------------------------------------------------------------------------
]]--
function LogThisCue(log_time, log_to_history)
local qnum = HC.GetScriptSource('number')
qnum = tonumber(qnum)/1000
local qlabel = HC.GetScriptSource('name')
local log_text = 'Cue ' .. qnum .. ' ' .. qlabel .. ' fired'
LogText(log_text, log_time, log_to_history)
end
--[[
----------------------------------------------------------------------------------------------
display a status in the history indicating this file was loaded
----------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------
End of Section
----------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------
Section - Logging
elapsedtimer.lua - provide an elapsed timer object
----------------------------------------------------------------------------------------------
This section provides an elapsed timer functionality using Object Oriented programming
There are 7 funcitons in the "Object"
new - creates a new timer
ClearTimer - stops and resets the timer
StartTimer - starts the elapsed time accumulation
StopTimer - stops the elapsed time accumuation
RestartTimer - zeros and restarts elapsed time accumulation (calls ClearTimer and StartTimer)
TimeSeconds - returns the current elapsed time in seconds
TimeString - returns the current elapsed time as a string
Example:
[At the start of act 1]
show_timer = ElapsedTimer:new()
show_timer:StartTimer()
act_timer = ElapsedTimer:new()
act_timer:StartTimer()
scene_timer = ElapsedTimer:new()
scene_timer:StartTimer()
[At the end of Scene 1]
HC.Status("Scene 1 Run Time = " .. scene_timer:TimeString())
scene_timer:RestartTimer()
[At the end of Scene 2, also end of Act 1]
HC.Status("Scene 2 Run Time = " .. scene_timer:TimeString())
HC.Status("Act 1 Run Time = " .. act_timer:TimeString())
[At the start of Act2, Scene 1]
act_timer:RestartTimer()
scene_timer:RestartTimer()
[At the end of the Show]
HC.Status("Show Run Time = " .. show_timer:TimeString())
]]--
--
ElapsedTimer = { start = 0, elapsed = 0 }
function ElapsedTimer:new(o)
o = o or {} -- create object if user does not provide one
setmetatable(o, self)
self.__index = self
o:ClearTimer()
return o
end
function ElapsedTimer:ClearTimer()
self.start = 0
self.elapsed = 0
end
function ElapsedTimer:StartTimer()
-- only start the timer if not already running
if self.start == 0 then
self.start = os.time()
end
end
function ElapsedTimer:StopTimer()
self.elapsed = self.elapsed + os.time() - self.start
self.start= 0
return self.elapsed
end
function ElapsedTimer:RestartTimer()
self:ClearTimer()
self:StartTimer()
end
function ElapsedTimer:TimeSeconds()
a = self.elapsed
if self.start > 0 then
a = a + os.time() - self.start
end
return a
end
function ElapsedTimer:TimeString()
a = self:TimeSeconds()
result = ""
if a > 3600 then
-- we have more than an hour worth of secods
result = math.floor(a / 3600)
result = result .. ":"
end
result = result .. os.date("%M:%S", a)
return result
end
--[[
------------------------------------------------------------------
-- end of section
------------------------------------------------------------------
-- Section General
------------------------------------------------------------------
]]--
function KillIndex()
os.remove('d:\\web\\index.html')
end
function StartTodaysLog(logtitle)
-- InitializeLogFile only creates new file if file does not exist
InitializeLogFile('d:\\web\\index.html',logtitle .. ' Stage Management Show Reports', nil, true)
ThisShowFile = os.date('%A_%B_%d_%H_%M') .. '.html'
ThisShowText = os.date('%A %B %d %H:%M')
s = ''..ThisShowText..'
'
LogText(s, nil, nil, 3)
InitializeLogFile('d:\\web\\' .. ThisShowFile,logtitle .. ' - ' .. ThisShowText , nil, true)
LogText('Back to Show Index
')
LogDrawLine()
end
function StartScene(scene_title, endlast)
if endlast == true then
EndScene()
end
ThisScene = scene_title
scene_timer = ElapsedTimer:new()
scene_timer:StartTimer()
LogText(ThisScene .. ' started',true, nil, 3)
end
function EndScene()
LogText(ThisScene .. ' ends. Run-time = ' .. scene_timer:TimeString(),true, nil, 3)
end
function StartAct(act_title)
ThisAct = act_title
act_timer = ElapsedTimer:new()
act_timer:StartTimer()
LogDrawLine()
LogText(ThisAct .. ' started',true, nil, 2)
end
function EndAct()
LogText(ThisAct .. ' ends. Run-time = ' .. act_timer:TimeString(),true, nil, 2)
LogDrawLine()
end
function StartShow()
show_timer = ElapsedTimer:new()
show_timer:StartTimer()
LogText('Show started',true, nil, 1)
end
function EndShow()
LogText('Show ends',true, nil, 1)
LogText('Show run-time = ' .. show_timer:TimeString(),nil,nil,2)
LogText('Excluding an interval of ' .. interval_timer:TimeString(),nil, nil, 2)
end
function StartInterval()
EndScene()
interval_timer = ElapsedTimer:new()
interval_timer:StartTimer()
LogText('Interval started',true, nil, 2)
show_timer:StopTimer()
end
function EndInterval()
LogText('Interval ends. Run-time = ' .. interval_timer:TimeString(),true, nil, 2)
interval_timer:StopTimer()
show_timer:StartTimer()
end
HC.Status('----- ShowReporter loaded')
--[[
------------------------------------------------------------------
-- end of section general
------------------------------------------------------------------
-- end of file
------------------------------------------------------------------
]]--