--[[ 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 ------------------------------------------------------------------ ]]--