mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Ops
This commit is contained in:
parent
adc89feda9
commit
ed47b4b3db
@ -26,8 +26,6 @@
|
|||||||
-- @module Core.Base
|
-- @module Core.Base
|
||||||
-- @image Core_Base.JPG
|
-- @image Core_Base.JPG
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local _TraceOnOff = true
|
local _TraceOnOff = true
|
||||||
local _TraceLevel = 1
|
local _TraceLevel = 1
|
||||||
local _TraceAll = false
|
local _TraceAll = false
|
||||||
|
|||||||
@ -71,7 +71,7 @@
|
|||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
-- ### Contributions:
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@ -81,6 +81,12 @@
|
|||||||
do -- FSM
|
do -- FSM
|
||||||
|
|
||||||
--- @type FSM
|
--- @type FSM
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field Core.Scheduler#SCHEDULER CallScheduler Call scheduler.
|
||||||
|
-- @field #table options Options.
|
||||||
|
-- @field #table subs Subs.
|
||||||
|
-- @field #table Scores Scores.
|
||||||
|
-- @field #string current Current state name.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
@ -369,8 +375,7 @@ do -- FSM
|
|||||||
self._EventSchedules = {}
|
self._EventSchedules = {}
|
||||||
|
|
||||||
self.CallScheduler = SCHEDULER:New( self )
|
self.CallScheduler = SCHEDULER:New( self )
|
||||||
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -379,7 +384,6 @@ do -- FSM
|
|||||||
-- @param #FSM self
|
-- @param #FSM self
|
||||||
-- @param #string State A string defining the start state.
|
-- @param #string State A string defining the start state.
|
||||||
function FSM:SetStartState( State )
|
function FSM:SetStartState( State )
|
||||||
|
|
||||||
self._StartState = State
|
self._StartState = State
|
||||||
self.current = State
|
self.current = State
|
||||||
end
|
end
|
||||||
@ -389,7 +393,6 @@ do -- FSM
|
|||||||
-- @param #FSM self
|
-- @param #FSM self
|
||||||
-- @return #string A string containing the start state.
|
-- @return #string A string containing the start state.
|
||||||
function FSM:GetStartState()
|
function FSM:GetStartState()
|
||||||
|
|
||||||
return self._StartState or {}
|
return self._StartState or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -406,6 +409,7 @@ do -- FSM
|
|||||||
Transition.Event = Event
|
Transition.Event = Event
|
||||||
Transition.To = To
|
Transition.To = To
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
self:T2( Transition )
|
self:T2( Transition )
|
||||||
|
|
||||||
self._Transitions[Transition] = Transition
|
self._Transitions[Transition] = Transition
|
||||||
@ -414,9 +418,9 @@ do -- FSM
|
|||||||
|
|
||||||
|
|
||||||
--- Returns a table of the transition rules defined within the FSM.
|
--- Returns a table of the transition rules defined within the FSM.
|
||||||
-- @return #table
|
-- @param #FSM self
|
||||||
function FSM:GetTransitions()
|
-- @return #table Transitions.
|
||||||
|
function FSM:GetTransitions()
|
||||||
return self._Transitions or {}
|
return self._Transitions or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -448,7 +452,8 @@ do -- FSM
|
|||||||
|
|
||||||
|
|
||||||
--- Returns a table of the SubFSM rules defined within the FSM.
|
--- Returns a table of the SubFSM rules defined within the FSM.
|
||||||
-- @return #table
|
-- @param #FSM self
|
||||||
|
-- @return #table Sub processes.
|
||||||
function FSM:GetProcesses()
|
function FSM:GetProcesses()
|
||||||
|
|
||||||
self:F( { Processes = self._Processes } )
|
self:F( { Processes = self._Processes } )
|
||||||
@ -480,15 +485,17 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Adds an End state.
|
--- Adds an End state.
|
||||||
function FSM:AddEndState( State )
|
-- @param #FSM self
|
||||||
|
-- @param #string State The FSM state.
|
||||||
|
function FSM:AddEndState( State )
|
||||||
self._EndStates[State] = State
|
self._EndStates[State] = State
|
||||||
self.endstates[State] = State
|
self.endstates[State] = State
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the End states.
|
--- Returns the End states.
|
||||||
function FSM:GetEndStates()
|
-- @param #FSM self
|
||||||
|
-- @return #table End states.
|
||||||
|
function FSM:GetEndStates()
|
||||||
return self._EndStates or {}
|
return self._EndStates or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -532,18 +539,22 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a table with the scores defined.
|
--- Returns a table with the scores defined.
|
||||||
function FSM:GetScores()
|
-- @param #FSM self
|
||||||
|
-- @param #table Scores.
|
||||||
|
function FSM:GetScores()
|
||||||
return self._Scores or {}
|
return self._Scores or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a table with the Subs defined.
|
--- Returns a table with the Subs defined.
|
||||||
function FSM:GetSubs()
|
-- @param #FSM self
|
||||||
|
-- @return #table Sub processes.
|
||||||
|
function FSM:GetSubs()
|
||||||
return self.options.subs
|
return self.options.subs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Load call backs.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #table CallBackTable Table of call backs.
|
||||||
function FSM:LoadCallBacks( CallBackTable )
|
function FSM:LoadCallBacks( CallBackTable )
|
||||||
|
|
||||||
for name, callback in pairs( CallBackTable or {} ) do
|
for name, callback in pairs( CallBackTable or {} ) do
|
||||||
@ -551,21 +562,34 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Event map.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #table Events Events.
|
||||||
|
-- @param #table EventStructure Event structure.
|
||||||
function FSM:_eventmap( Events, EventStructure )
|
function FSM:_eventmap( Events, EventStructure )
|
||||||
|
|
||||||
local Event = EventStructure.Event
|
local Event = EventStructure.Event
|
||||||
local __Event = "__" .. EventStructure.Event
|
local __Event = "__" .. EventStructure.Event
|
||||||
|
|
||||||
self[Event] = self[Event] or self:_create_transition(Event)
|
self[Event] = self[Event] or self:_create_transition(Event)
|
||||||
self[__Event] = self[__Event] or self:_delayed_transition(Event)
|
self[__Event] = self[__Event] or self:_delayed_transition(Event)
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
self:T2( "Added methods: " .. Event .. ", " .. __Event )
|
self:T2( "Added methods: " .. Event .. ", " .. __Event )
|
||||||
|
|
||||||
Events[Event] = self.Events[Event] or { map = {} }
|
Events[Event] = self.Events[Event] or { map = {} }
|
||||||
self:_add_to_map( Events[Event].map, EventStructure )
|
self:_add_to_map( Events[Event].map, EventStructure )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Sub maps.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #table subs Subs.
|
||||||
|
-- @param #table sub Sub.
|
||||||
|
-- @param #string name Name.
|
||||||
function FSM:_submap( subs, sub, name )
|
function FSM:_submap( subs, sub, name )
|
||||||
--self:F( { sub = sub, name = name } )
|
|
||||||
subs[sub.From] = subs[sub.From] or {}
|
subs[sub.From] = subs[sub.From] or {}
|
||||||
subs[sub.From][sub.Event] = subs[sub.From][sub.Event] or {}
|
subs[sub.From][sub.Event] = subs[sub.From][sub.Event] or {}
|
||||||
|
|
||||||
@ -578,22 +602,23 @@ do -- FSM
|
|||||||
subs[sub.From][sub.Event][sub].ReturnEvents = sub.ReturnEvents or {} -- these events need to be given to find the correct continue event ... if none given, the processing will stop.
|
subs[sub.From][sub.Event][sub].ReturnEvents = sub.ReturnEvents or {} -- these events need to be given to find the correct continue event ... if none given, the processing will stop.
|
||||||
subs[sub.From][sub.Event][sub].name = name
|
subs[sub.From][sub.Event][sub].name = name
|
||||||
subs[sub.From][sub.Event][sub].fsmparent = self
|
subs[sub.From][sub.Event][sub].fsmparent = self
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Call handler.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string step Step "onafter", "onbefore", "onenter", "onleave".
|
||||||
|
-- @param #string trigger Trigger.
|
||||||
|
-- @param #table params Parameters.
|
||||||
|
-- @param #string EventName Event name.
|
||||||
|
-- @return Value.
|
||||||
function FSM:_call_handler( step, trigger, params, EventName )
|
function FSM:_call_handler( step, trigger, params, EventName )
|
||||||
|
--env.info(string.format("FF T=%.3f _call_handler step=%s, trigger=%s, event=%s", timer.getTime(), step, trigger, EventName))
|
||||||
|
|
||||||
local handler = step .. trigger
|
local handler = step .. trigger
|
||||||
local ErrorHandler = function( errmsg )
|
|
||||||
|
|
||||||
env.info( "Error in SCHEDULER function:" .. errmsg )
|
|
||||||
if BASE.Debug ~= nil then
|
|
||||||
env.info( BASE.Debug.traceback() )
|
|
||||||
end
|
|
||||||
|
|
||||||
return errmsg
|
|
||||||
end
|
|
||||||
if self[handler] then
|
if self[handler] then
|
||||||
|
|
||||||
if step == "onafter" or step == "OnAfter" then
|
if step == "onafter" or step == "OnAfter" then
|
||||||
self:T( ":::>" .. step .. params[2] .. " : " .. params[1] .. " >> " .. params[2] .. ">" .. step .. params[2] .. "()" .. " >> " .. params[3] )
|
self:T( ":::>" .. step .. params[2] .. " : " .. params[1] .. " >> " .. params[2] .. ">" .. step .. params[2] .. "()" .. " >> " .. params[3] )
|
||||||
elseif step == "onbefore" or step == "OnBefore" then
|
elseif step == "onbefore" or step == "OnBefore" then
|
||||||
@ -604,14 +629,31 @@ do -- FSM
|
|||||||
self:T( ":::>" .. step .. params[1] .. " : " .. params[1] .. ">" .. step .. params[1] .. "()" .. " >> " .. params[2] .. " >> " .. params[3] )
|
self:T( ":::>" .. step .. params[1] .. " : " .. params[1] .. ">" .. step .. params[1] .. "()" .. " >> " .. params[2] .. " >> " .. params[3] )
|
||||||
else
|
else
|
||||||
self:T( ":::>" .. step .. " : " .. params[1] .. " >> " .. params[2] .. " >> " .. params[3] )
|
self:T( ":::>" .. step .. " : " .. params[1] .. " >> " .. params[2] .. " >> " .. params[3] )
|
||||||
end
|
end
|
||||||
|
|
||||||
self._EventSchedules[EventName] = nil
|
self._EventSchedules[EventName] = nil
|
||||||
|
|
||||||
|
-- Error handler.
|
||||||
|
local ErrorHandler = function( errmsg )
|
||||||
|
env.info( "Error in SCHEDULER function:" .. errmsg )
|
||||||
|
if BASE.Debug ~= nil then
|
||||||
|
env.info( BASE.Debug.traceback() )
|
||||||
|
end
|
||||||
|
return errmsg
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Protected call.
|
||||||
local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler )
|
local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler )
|
||||||
|
|
||||||
return Value
|
return Value
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #FSM self
|
--- Handler.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string EventName Event name.
|
||||||
|
-- @param ... Arguments.
|
||||||
function FSM._handler( self, EventName, ... )
|
function FSM._handler( self, EventName, ... )
|
||||||
|
|
||||||
local Can, To = self:can( EventName )
|
local Can, To = self:can( EventName )
|
||||||
@ -621,7 +663,11 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
|
|
||||||
if Can then
|
if Can then
|
||||||
|
|
||||||
|
-- From state.
|
||||||
local From = self.current
|
local From = self.current
|
||||||
|
|
||||||
|
-- Parameters.
|
||||||
local Params = { From, EventName, To, ... }
|
local Params = { From, EventName, To, ... }
|
||||||
|
|
||||||
|
|
||||||
@ -632,8 +678,8 @@ do -- FSM
|
|||||||
self["onafter".. EventName] or
|
self["onafter".. EventName] or
|
||||||
self["OnAfter".. EventName] or
|
self["OnAfter".. EventName] or
|
||||||
self["onenter".. To] or
|
self["onenter".. To] or
|
||||||
self["OnEnter".. To]
|
self["OnEnter".. To] then
|
||||||
then
|
|
||||||
if self:_call_handler( "onbefore", EventName, Params, EventName ) == false then
|
if self:_call_handler( "onbefore", EventName, Params, EventName ) == false then
|
||||||
self:T( "*** FSM *** Cancel" .. " *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** onbefore" .. EventName )
|
self:T( "*** FSM *** Cancel" .. " *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** onbefore" .. EventName )
|
||||||
return false
|
return false
|
||||||
@ -653,8 +699,11 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
local ClassName = self:GetClassName()
|
local ClassName = self:GetClassName()
|
||||||
|
|
||||||
if ClassName == "FSM" then
|
if ClassName == "FSM" then
|
||||||
self:T( "*** FSM *** Transit *** " .. self.current .. " --> " .. EventName .. " --> " .. To )
|
self:T( "*** FSM *** Transit *** " .. self.current .. " --> " .. EventName .. " --> " .. To )
|
||||||
end
|
end
|
||||||
@ -672,84 +721,125 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- New current state.
|
||||||
self.current = To
|
self.current = To
|
||||||
|
|
||||||
local execute = true
|
local execute = true
|
||||||
|
|
||||||
local subtable = self:_gosub( From, EventName )
|
local subtable = self:_gosub( From, EventName )
|
||||||
|
|
||||||
for _, sub in pairs( subtable ) do
|
for _, sub in pairs( subtable ) do
|
||||||
|
|
||||||
--if sub.nextevent then
|
--if sub.nextevent then
|
||||||
-- self:F2( "nextevent = " .. sub.nextevent )
|
-- self:F2( "nextevent = " .. sub.nextevent )
|
||||||
-- self[sub.nextevent]( self )
|
-- self[sub.nextevent]( self )
|
||||||
--end
|
--end
|
||||||
|
|
||||||
self:T( "*** FSM *** Sub *** " .. sub.StartEvent )
|
self:T( "*** FSM *** Sub *** " .. sub.StartEvent )
|
||||||
|
|
||||||
sub.fsm.fsmparent = self
|
sub.fsm.fsmparent = self
|
||||||
sub.fsm.ReturnEvents = sub.ReturnEvents
|
sub.fsm.ReturnEvents = sub.ReturnEvents
|
||||||
sub.fsm[sub.StartEvent]( sub.fsm )
|
sub.fsm[sub.StartEvent]( sub.fsm )
|
||||||
|
|
||||||
execute = false
|
execute = false
|
||||||
end
|
end
|
||||||
|
|
||||||
local fsmparent, Event = self:_isendstate( To )
|
local fsmparent, Event = self:_isendstate( To )
|
||||||
|
|
||||||
if fsmparent and Event then
|
if fsmparent and Event then
|
||||||
|
|
||||||
self:T( "*** FSM *** End *** " .. Event )
|
self:T( "*** FSM *** End *** " .. Event )
|
||||||
|
|
||||||
self:_call_handler("onenter", To, Params, EventName )
|
self:_call_handler("onenter", To, Params, EventName )
|
||||||
self:_call_handler("OnEnter", To, Params, EventName )
|
self:_call_handler("OnEnter", To, Params, EventName )
|
||||||
self:_call_handler("onafter", EventName, Params, EventName )
|
self:_call_handler("onafter", EventName, Params, EventName )
|
||||||
self:_call_handler("OnAfter", EventName, Params, EventName )
|
self:_call_handler("OnAfter", EventName, Params, EventName )
|
||||||
self:_call_handler("onstate", "change", Params, EventName )
|
self:_call_handler("onstate", "change", Params, EventName )
|
||||||
|
|
||||||
fsmparent[Event]( fsmparent )
|
fsmparent[Event]( fsmparent )
|
||||||
|
|
||||||
execute = false
|
execute = false
|
||||||
end
|
end
|
||||||
|
|
||||||
if execute then
|
if execute then
|
||||||
self:_call_handler("onafter", EventName, Params, EventName )
|
|
||||||
self:_call_handler("OnAfter", EventName, Params, EventName )
|
|
||||||
|
|
||||||
-- only execute the call if the From state is not equal to the To state! Otherwise this function should never execute!
|
self:_call_handler("onafter", EventName, Params, EventName )
|
||||||
--if from ~= to then
|
self:_call_handler("OnAfter", EventName, Params, EventName )
|
||||||
self:_call_handler("onenter", To, Params, EventName )
|
|
||||||
self:_call_handler("OnEnter", To, Params, EventName )
|
self:_call_handler("onenter", To, Params, EventName )
|
||||||
--end
|
self:_call_handler("OnEnter", To, Params, EventName )
|
||||||
|
|
||||||
self:_call_handler("onstate", "change", Params, EventName )
|
self:_call_handler("onstate", "change", Params, EventName )
|
||||||
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:T( "*** FSM *** NO Transition *** " .. self.current .. " --> " .. EventName .. " --> ? " )
|
self:I( "*** FSM *** NO Transition *** " .. self.current .. " --> " .. EventName .. " --> ? " )
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Delayed transition.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string EventName Event name.
|
||||||
|
-- @return #function Function.
|
||||||
function FSM:_delayed_transition( EventName )
|
function FSM:_delayed_transition( EventName )
|
||||||
|
|
||||||
return function( self, DelaySeconds, ... )
|
return function( self, DelaySeconds, ... )
|
||||||
|
|
||||||
|
-- Debug.
|
||||||
self:T2( "Delayed Event: " .. EventName )
|
self:T2( "Delayed Event: " .. EventName )
|
||||||
|
|
||||||
local CallID = 0
|
local CallID = 0
|
||||||
if DelaySeconds ~= nil then
|
if DelaySeconds ~= nil then
|
||||||
|
|
||||||
if DelaySeconds < 0 then -- Only call the event ONCE!
|
if DelaySeconds < 0 then -- Only call the event ONCE!
|
||||||
|
|
||||||
DelaySeconds = math.abs( DelaySeconds )
|
DelaySeconds = math.abs( DelaySeconds )
|
||||||
if not self._EventSchedules[EventName] then
|
|
||||||
|
if not self._EventSchedules[EventName] then
|
||||||
|
|
||||||
|
-- Call _handler.
|
||||||
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
|
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
|
||||||
|
|
||||||
|
-- Set call ID.
|
||||||
self._EventSchedules[EventName] = CallID
|
self._EventSchedules[EventName] = CallID
|
||||||
|
|
||||||
|
-- Debug output.
|
||||||
self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID)))
|
self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID)))
|
||||||
else
|
else
|
||||||
self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec CANCELLED as we already have such an event in the queue.", EventName, DelaySeconds))
|
self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec CANCELLED as we already have such an event in the queue.", EventName, DelaySeconds))
|
||||||
-- reschedule
|
-- reschedule
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|
||||||
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
|
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
|
||||||
|
|
||||||
self:T2(string.format("Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID)))
|
self:T2(string.format("Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID)))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
error( "FSM: An asynchronous event trigger requires a DelaySeconds parameter!!! This can be positive or negative! Sorry, but will not process this." )
|
error( "FSM: An asynchronous event trigger requires a DelaySeconds parameter!!! This can be positive or negative! Sorry, but will not process this." )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Debug.
|
||||||
self:T2( { CallID = CallID } )
|
self:T2( { CallID = CallID } )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Create transition.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string EventName Event name.
|
||||||
|
-- @return #function Function.
|
||||||
function FSM:_create_transition( EventName )
|
function FSM:_create_transition( EventName )
|
||||||
return function( self, ... ) return self._handler( self, EventName , ... ) end
|
return function( self, ... ) return self._handler( self, EventName , ... ) end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Go sub.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string ParentFrom Parent from state.
|
||||||
|
-- @param #string ParentEvent Parent event name.
|
||||||
|
-- @return #table Subs.
|
||||||
function FSM:_gosub( ParentFrom, ParentEvent )
|
function FSM:_gosub( ParentFrom, ParentEvent )
|
||||||
local fsmtable = {}
|
local fsmtable = {}
|
||||||
if self.subs[ParentFrom] and self.subs[ParentFrom][ParentEvent] then
|
if self.subs[ParentFrom] and self.subs[ParentFrom][ParentEvent] then
|
||||||
@ -759,9 +849,15 @@ do -- FSM
|
|||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Is end state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string Current Current state name.
|
||||||
|
-- @return #table FSM parent.
|
||||||
|
-- @return #string Event name.
|
||||||
function FSM:_isendstate( Current )
|
function FSM:_isendstate( Current )
|
||||||
local FSMParent = self.fsmparent
|
local FSMParent = self.fsmparent
|
||||||
|
|
||||||
if FSMParent and self.endstates[Current] then
|
if FSMParent and self.endstates[Current] then
|
||||||
--self:T( { state = Current, endstates = self.endstates, endstate = self.endstates[Current] } )
|
--self:T( { state = Current, endstates = self.endstates, endstate = self.endstates[Current] } )
|
||||||
FSMParent.current = Current
|
FSMParent.current = Current
|
||||||
@ -778,9 +874,14 @@ do -- FSM
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Add to map.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #table Map Map.
|
||||||
|
-- @param #table Event Event table.
|
||||||
function FSM:_add_to_map( Map, Event )
|
function FSM:_add_to_map( Map, Event )
|
||||||
self:F3( { Map, Event } )
|
self:F3( { Map, Event } )
|
||||||
|
|
||||||
if type(Event.From) == 'string' then
|
if type(Event.From) == 'string' then
|
||||||
Map[Event.From] = Event.To
|
Map[Event.From] = Event.To
|
||||||
else
|
else
|
||||||
@ -788,33 +889,59 @@ do -- FSM
|
|||||||
Map[From] = Event.To
|
Map[From] = Event.To
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T3( { Map, Event } )
|
self:T3( { Map, Event } )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get current state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @return #string Current FSM state.
|
||||||
function FSM:GetState()
|
function FSM:GetState()
|
||||||
return self.current
|
return self.current
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get current state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @return #string Current FSM state.
|
||||||
function FSM:GetCurrentState()
|
function FSM:GetCurrentState()
|
||||||
return self.current
|
return self.current
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if FSM is in state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string State State name.
|
||||||
|
-- @param #boolean If true, FSM is in this state.
|
||||||
function FSM:Is( State )
|
function FSM:Is( State )
|
||||||
return self.current == State
|
return self.current == State
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if FSM is in state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string State State name.
|
||||||
|
-- @param #boolean If true, FSM is in this state.
|
||||||
function FSM:is(state)
|
function FSM:is(state)
|
||||||
return self.current == state
|
return self.current == state
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if can do an event.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string e Event name.
|
||||||
|
-- @return #boolean If true, FSM can do the event.
|
||||||
|
-- @return #string To state.
|
||||||
function FSM:can(e)
|
function FSM:can(e)
|
||||||
local Event = self.Events[e]
|
local Event = self.Events[e]
|
||||||
|
|
||||||
self:F3( { self.current, Event } )
|
self:F3( { self.current, Event } )
|
||||||
|
|
||||||
local To = Event and Event.map[self.current] or Event.map['*']
|
local To = Event and Event.map[self.current] or Event.map['*']
|
||||||
|
|
||||||
return To ~= nil, To
|
return To ~= nil, To
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if cannot do an event.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string e Event name.
|
||||||
|
-- @return #boolean If true, FSM cannot do the event.
|
||||||
function FSM:cannot(e)
|
function FSM:cannot(e)
|
||||||
return not self:can(e)
|
return not self:can(e)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1988,6 +1988,7 @@ function AIRWING:CountAssetsOnMission(MissionTypes, Squadron)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
env.info(string.format("FF N=%d Np=%d, Nq=%d", Np+Nq, Np, Nq))
|
||||||
return Np+Nq, Np, Nq
|
return Np+Nq, Np, Nq
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -486,6 +486,7 @@ function AUFTRAG:New(Type)
|
|||||||
self.engageAsGroup=true
|
self.engageAsGroup=true
|
||||||
self.missionRepeated=0
|
self.missionRepeated=0
|
||||||
self.missionRepeatMax=0
|
self.missionRepeatMax=0
|
||||||
|
self.NrepeatSuccess=0
|
||||||
self.nassets=1
|
self.nassets=1
|
||||||
self.dTevaluate=0
|
self.dTevaluate=0
|
||||||
self.Ncasualties=0
|
self.Ncasualties=0
|
||||||
@ -982,6 +983,10 @@ function AUFTRAG:NewBOMBRUNWAY(Airdrome, Altitude)
|
|||||||
if type(Airdrome)=="string" then
|
if type(Airdrome)=="string" then
|
||||||
Airdrome=AIRBASE:FindByName(Airdrome)
|
Airdrome=AIRBASE:FindByName(Airdrome)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Airdrome:IsInstanceOf("AIRBASE") then
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
local mission=AUFTRAG:New(AUFTRAG.Type.BOMBRUNWAY)
|
local mission=AUFTRAG:New(AUFTRAG.Type.BOMBRUNWAY)
|
||||||
|
|
||||||
@ -995,7 +1000,7 @@ function AUFTRAG:NewBOMBRUNWAY(Airdrome, Altitude)
|
|||||||
-- Mission options:
|
-- Mission options:
|
||||||
mission.missionTask=ENUMS.MissionTask.RUNWAYATTACK
|
mission.missionTask=ENUMS.MissionTask.RUNWAYATTACK
|
||||||
mission.missionAltitude=mission.engageAltitude*0.8
|
mission.missionAltitude=mission.engageAltitude*0.8
|
||||||
mission.missionFraction=0.2
|
mission.missionFraction=0.75
|
||||||
mission.optionROE=ENUMS.ROE.OpenFire
|
mission.optionROE=ENUMS.ROE.OpenFire
|
||||||
mission.optionROT=ENUMS.ROT.PassiveDefense
|
mission.optionROT=ENUMS.ROT.PassiveDefense
|
||||||
|
|
||||||
@ -3052,7 +3057,7 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
|
|||||||
-- BOMBRUNWAY Mission --
|
-- BOMBRUNWAY Mission --
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
local DCStask=CONTROLLABLE.TaskBombingRunway(nil, self.engageTarget.Target, self.engageWeaponType, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAsGroup)
|
local DCStask=CONTROLLABLE.TaskBombingRunway(nil, self.engageTarget:GetObject(), self.engageWeaponType, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAsGroup)
|
||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
@ -3092,7 +3097,7 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
|
|||||||
-- ESCORT Mission --
|
-- ESCORT Mission --
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
local DCStask=CONTROLLABLE.TaskEscort(nil, self.engageTarget.Target, self.escortVec3, LastWaypointIndex, self.engageMaxDistance, self.engageTargetTypes)
|
local DCStask=CONTROLLABLE.TaskEscort(nil, self.engageTarget:GetObject(), self.escortVec3, LastWaypointIndex, self.engageMaxDistance, self.engageTargetTypes)
|
||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
@ -3102,7 +3107,7 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
|
|||||||
-- FAC Mission --
|
-- FAC Mission --
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
local DCStask=CONTROLLABLE.TaskFAC_AttackGroup(nil, self.engageTarget.Target, self.engageWeaponType, self.facDesignation, self.facDatalink, self.facFreq, self.facModu, CallsignName, CallsignNumber)
|
local DCStask=CONTROLLABLE.TaskFAC_AttackGroup(nil, self.engageTarget:GetObject(), self.engageWeaponType, self.facDesignation, self.facDatalink, self.facFreq, self.facModu, CallsignName, CallsignNumber)
|
||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
|
|||||||
@ -416,6 +416,9 @@ function NAVYGROUP:onafterStatus(From, Event, To)
|
|||||||
local pos=self:GetCoordinate()
|
local pos=self:GetCoordinate()
|
||||||
local speed=self.group:GetVelocityKNOTS()
|
local speed=self.group:GetVelocityKNOTS()
|
||||||
|
|
||||||
|
-- Update last known position, orientation, velocity.
|
||||||
|
self:_UpdatePosition()
|
||||||
|
|
||||||
-- Check if group started or stopped turning.
|
-- Check if group started or stopped turning.
|
||||||
self:_CheckTurning()
|
self:_CheckTurning()
|
||||||
|
|
||||||
@ -440,9 +443,6 @@ function NAVYGROUP:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check water is ahead.
|
|
||||||
--collision=self:_CheckCollisionCoord(pos:Translate(freepath+100, hdg))
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check into wind queue.
|
-- Check into wind queue.
|
||||||
@ -1348,10 +1348,10 @@ function NAVYGROUP:_CheckTurning()
|
|||||||
if unit and unit:IsAlive() then
|
if unit and unit:IsAlive() then
|
||||||
|
|
||||||
-- Current orientation of carrier.
|
-- Current orientation of carrier.
|
||||||
local vNew=unit:GetOrientationX()
|
local vNew=self.orientX --unit:GetOrientationX()
|
||||||
|
|
||||||
-- Last orientation from 30 seconds ago.
|
-- Last orientation from 30 seconds ago.
|
||||||
local vLast=self.Corientlast or vNew
|
local vLast=self.orientXLast --self.Corientlast or vNew
|
||||||
|
|
||||||
-- We only need the X-Z plane.
|
-- We only need the X-Z plane.
|
||||||
vNew.y=0 ; vLast.y=0
|
vNew.y=0 ; vLast.y=0
|
||||||
@ -1360,7 +1360,7 @@ function NAVYGROUP:_CheckTurning()
|
|||||||
local deltaLast=math.deg(math.acos(UTILS.VecDot(vNew,vLast)/UTILS.VecNorm(vNew)/UTILS.VecNorm(vLast)))
|
local deltaLast=math.deg(math.acos(UTILS.VecDot(vNew,vLast)/UTILS.VecNorm(vNew)/UTILS.VecNorm(vLast)))
|
||||||
|
|
||||||
-- Last orientation becomes new orientation
|
-- Last orientation becomes new orientation
|
||||||
self.Corientlast=vNew
|
--self.Corientlast=vNew
|
||||||
|
|
||||||
-- Carrier is turning when its heading changed by at least two degrees since last check.
|
-- Carrier is turning when its heading changed by at least two degrees since last check.
|
||||||
local turning=math.abs(deltaLast)>=2
|
local turning=math.abs(deltaLast)>=2
|
||||||
|
|||||||
@ -2386,7 +2386,7 @@ function OPSGROUP:onafterCheckZone(From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsStopped() then
|
if not self:IsStopped() then
|
||||||
self:__CheckZone(-1)
|
self:__CheckZone(-10)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2443,7 +2443,6 @@ function OPSGROUP:_CheckInZones()
|
|||||||
self:EnterZone(enterzone)
|
self:EnterZone(enterzone)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -3494,6 +3493,30 @@ end
|
|||||||
-- Element and Group Status Functions
|
-- Element and Group Status Functions
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Check if all elements of the group have the same status (or are dead).
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param #string unitname Name of unit.
|
||||||
|
function OPSGROUP:_UpdatePosition()
|
||||||
|
|
||||||
|
if self:IsAlive() then
|
||||||
|
|
||||||
|
self.positionLast=self.position or self:GetCoordinate()
|
||||||
|
self.headingLast=self.heading or self:GetHeading()
|
||||||
|
self.orientXLast=self.orientX or self.group:GetUnit(1):GetOrientationX()
|
||||||
|
self.velocityLast=self.velocity or self.group:GetVelocityMPS()
|
||||||
|
|
||||||
|
self.position=self:GetCoordinate()
|
||||||
|
self.heading=self:GetHeading()
|
||||||
|
self.orientX=self.group:GetUnit(1):GetOrientationX()
|
||||||
|
self.velocity=self.group:GetVelocityMPS()
|
||||||
|
|
||||||
|
self.dTpositionUpdate=self.TpositionUpdate and self.TpositionUpdate-timer.getAbsTime() or 0
|
||||||
|
self.TpositionUpdate=timer.getAbsTime()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if all elements of the group have the same status (or are dead).
|
--- Check if all elements of the group have the same status (or are dead).
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param #string unitname Name of unit.
|
-- @param #string unitname Name of unit.
|
||||||
|
|||||||
@ -574,8 +574,11 @@ function SQUADRON:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
local NassetsTot=#self.assets
|
local NassetsTot=#self.assets
|
||||||
local NassetsInS=self:CountAssetsInStock()
|
local NassetsInS=self:CountAssetsInStock()
|
||||||
local NassetsQP, NassetsP, NassetsQ=self.airwing and self.airwing:CountAssetsOnMission(nil, self) or 0,0,0
|
local NassetsQP=0 ; local NassetsP=0 ; local NassetsQ=0
|
||||||
|
if self.airwing then
|
||||||
|
NassetsQP, NassetsP, NassetsQ=self.airwing:CountAssetsOnMission(nil, self)
|
||||||
|
end
|
||||||
|
|
||||||
-- Short info.
|
-- Short info.
|
||||||
local text=string.format("%s [Type=%s, Callsign=%s, Modex=%d, Skill=%s]: Assets Total=%d, InStock=%d, OnMission=%d [P=%d, Q=%d]",
|
local text=string.format("%s [Type=%s, Callsign=%s, Modex=%d, Skill=%s]: Assets Total=%d, InStock=%d, OnMission=%d [P=%d, Q=%d]",
|
||||||
fsmstate, self.aircrafttype, callsign, modex, skill, NassetsTot, NassetsInS, NassetsQP, NassetsP, NassetsQ)
|
fsmstate, self.aircrafttype, callsign, modex, skill, NassetsTot, NassetsInS, NassetsQP, NassetsP, NassetsQ)
|
||||||
@ -613,6 +616,8 @@ function SQUADRON:_CheckAssetStatus()
|
|||||||
if mission then
|
if mission then
|
||||||
local distance=asset.flightgroup and UTILS.MetersToNM(mission:GetTargetDistance(asset.flightgroup.group:GetCoordinate())) or 0
|
local distance=asset.flightgroup and UTILS.MetersToNM(mission:GetTargetDistance(asset.flightgroup.group:GetCoordinate())) or 0
|
||||||
text=text..string.format(" Mission %s - %s: Status=%s, Dist=%.1f NM", mission.name, mission.type, mission.status, distance)
|
text=text..string.format(" Mission %s - %s: Status=%s, Dist=%.1f NM", mission.name, mission.type, mission.status, distance)
|
||||||
|
else
|
||||||
|
text=text.."Mission None"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Flight status.
|
-- Flight status.
|
||||||
|
|||||||
@ -74,16 +74,22 @@ PROFILER = {
|
|||||||
fTimeTotal = {},
|
fTimeTotal = {},
|
||||||
eventHandler = {},
|
eventHandler = {},
|
||||||
startTime = nil,
|
startTime = nil,
|
||||||
endTime = nil,
|
|
||||||
runTime = nil,
|
runTime = nil,
|
||||||
sortBy = 1,
|
|
||||||
logUnknown = false,
|
logUnknown = false,
|
||||||
lowCpsThres = 5,
|
lowCpsThres = 5,
|
||||||
|
fileName = "",
|
||||||
}
|
}
|
||||||
|
|
||||||
PROFILER.sortBy=1 -- Sort reports by 0=Count, 1=Total time by function
|
--- Waypoint data.
|
||||||
PROFILER.logUnknown=true -- Log unknown functions
|
-- @type PROFILER.Data
|
||||||
PROFILER.lowCpsThres=1 -- Skip results with less than X calls per second
|
-- @field #string func The function name.
|
||||||
|
-- @field #string src The source file.
|
||||||
|
-- @field #number line The line number
|
||||||
|
-- @field #number count Number of function calls.
|
||||||
|
-- @field #number tm Total time in seconds.
|
||||||
|
|
||||||
|
PROFILER.logUnknown=false -- Log unknown functions
|
||||||
|
PROFILER.lowCpsThres=5 -- Skip results with less than X calls per second
|
||||||
PROFILER.fileName="_LuaProfiler.txt"
|
PROFILER.fileName="_LuaProfiler.txt"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -99,9 +105,8 @@ function PROFILER.Start(Delay, Duration)
|
|||||||
BASE:ScheduleOnce(Delay, PROFILER.Start, 0, Duration)
|
BASE:ScheduleOnce(Delay, PROFILER.Start, 0, Duration)
|
||||||
else
|
else
|
||||||
|
|
||||||
PROFILER.startTime=timer.getTime()
|
PROFILER.TstartGame=timer.getTime()
|
||||||
PROFILER.endTime=0
|
PROFILER.TstartOS=os.clock()
|
||||||
PROFILER.runTime=0
|
|
||||||
|
|
||||||
-- Add event handler.
|
-- Add event handler.
|
||||||
world.addEventHandler(PROFILER.eventHandler)
|
world.addEventHandler(PROFILER.eventHandler)
|
||||||
@ -142,11 +147,10 @@ function PROFILER.Stop(Delay)
|
|||||||
-- Remove hook.
|
-- Remove hook.
|
||||||
debug.sethook()
|
debug.sethook()
|
||||||
|
|
||||||
-- Set end time.
|
|
||||||
PROFILER.endTime=timer.getTime()
|
|
||||||
|
|
||||||
-- Run time.
|
-- Run time.
|
||||||
PROFILER.runTime=PROFILER.endTime-PROFILER.startTime
|
PROFILER.runTimeGame=timer.getTime()-PROFILER.TstartGame
|
||||||
|
PROFILER.runTimeOS=os.clock()-PROFILER.TstartOS
|
||||||
|
|
||||||
-- Show info.
|
-- Show info.
|
||||||
PROFILER.showInfo()
|
PROFILER.showInfo()
|
||||||
@ -208,13 +212,19 @@ end
|
|||||||
|
|
||||||
--- Get data.
|
--- Get data.
|
||||||
-- @param #function func Function.
|
-- @param #function func Function.
|
||||||
-- @param #boolean detailed Not used.
|
-- @return #string Function name.
|
||||||
function PROFILER.getData(func, detailed)
|
-- @return #string Source file name.
|
||||||
|
-- @return #string Line number.
|
||||||
|
-- @return #number Function time in seconds.
|
||||||
|
function PROFILER.getData(func)
|
||||||
|
|
||||||
local n=PROFILER.dInfo[func]
|
local n=PROFILER.dInfo[func]
|
||||||
|
|
||||||
if n.what=="C" then
|
if n.what=="C" then
|
||||||
return n.name, "", "", PROFILER.fTimeTotal[func]
|
return n.name, "?", "?", PROFILER.fTimeTotal[func]
|
||||||
end
|
end
|
||||||
return n.name, n.short_src, n.linedefined, PROFILER.fTimeTotal[func]
|
|
||||||
|
return n.name, n.short_src, n.linedefined, PROFILER.fTimeTotal[func]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Write text to log file.
|
--- Write text to log file.
|
||||||
@ -225,24 +235,27 @@ function PROFILER._flog(f, txt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Show table.
|
--- Show table.
|
||||||
-- @param #table t Data table.
|
-- @param #table data Data table.
|
||||||
-- @param #function f The file.
|
-- @param #function f The file.
|
||||||
-- @param #boolean detailed Show detailed info.
|
-- @param #boolean detailed Show detailed info.
|
||||||
function PROFILER.showTable(t, f, detailed)
|
function PROFILER.showTable(data, f, detailed)
|
||||||
for i=1, #t do
|
|
||||||
|
-- Loop over data.
|
||||||
|
for i=1, #data do
|
||||||
|
local t=data[i] --#PROFILER.Data
|
||||||
|
|
||||||
local cps=t[i].count/PROFILER.runTime
|
-- Calls per second.
|
||||||
|
local cps=t.count/PROFILER.runTimeGame
|
||||||
|
|
||||||
if (cps>=PROFILER.lowCpsThres) then
|
if (cps>=PROFILER.lowCpsThres) then
|
||||||
|
|
||||||
if (detailed==false) then
|
-- Output
|
||||||
PROFILER._flog(f,"- Function: "..t[i].func..": "..tostring(t[i].count).." ("..string.format("%.01f",cps).."/sec) Time: "..string.format("%g",t[i].tm).." seconds")
|
local text=string.format("%20s: %8d calls %8.1f/sec - Time %8.3f sec (%.3f %%) %s line %s", t.func, t.count, cps, t.tm, t.tm/PROFILER.runTimeGame*100, tostring(t.src), tostring(t.line))
|
||||||
else
|
PROFILER._flog(f, text)
|
||||||
PROFILER._flog(f,"- Function: "..t[i].func..": "..tostring(t[i].count).." ("..string.format("%.01f",cps).."/sec) "..tostring(t[i].src)..":"..tostring(t[i].line).." Time: "..string.format("%g",t[i].tm).." seconds")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Write info to output file.
|
--- Write info to output file.
|
||||||
@ -250,15 +263,15 @@ function PROFILER.showInfo()
|
|||||||
|
|
||||||
-- Output file.
|
-- Output file.
|
||||||
local file=lfs.writedir()..[[Logs\]]..PROFILER.fileName
|
local file=lfs.writedir()..[[Logs\]]..PROFILER.fileName
|
||||||
local f=io.open(file, 'w')
|
local f=io.open(file, 'w')
|
||||||
|
|
||||||
BASE:I(string.format("### Profiler: Writing result to file %s", file))
|
|
||||||
|
|
||||||
-- Gather data.
|
-- Gather data.
|
||||||
|
local Ttot=0
|
||||||
|
local Calls=0
|
||||||
local t={}
|
local t={}
|
||||||
for func, count in pairs(PROFILER.Counters) do
|
for func, count in pairs(PROFILER.Counters) do
|
||||||
|
|
||||||
local s,src,line,tm=PROFILER.getData(func, false)
|
local s,src,line,tm=PROFILER.getData(func)
|
||||||
|
|
||||||
if PROFILER.logUnknown==true then
|
if PROFILER.logUnknown==true then
|
||||||
if s==nil then s="<Unknown>" end
|
if s==nil then s="<Unknown>" end
|
||||||
@ -272,39 +285,65 @@ function PROFILER.showInfo()
|
|||||||
count=count,
|
count=count,
|
||||||
tm=tm,
|
tm=tm,
|
||||||
}
|
}
|
||||||
|
Ttot=Ttot+tm
|
||||||
|
Calls=Calls+count
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Sort result.
|
env.info("**************************************************************************************************")
|
||||||
if PROFILER.sortBy==0 then
|
env.info(string.format("Profiler"))
|
||||||
table.sort(t, function(a,b) return a.count>b.count end )
|
env.info(string.format("--------"))
|
||||||
end
|
env.info(string.format("* Runtime Game : %s = %d sec", UTILS.SecondsToClock(PROFILER.runTimeGame, true), PROFILER.runTimeGame))
|
||||||
if (PROFILER.sortBy==1) then
|
env.info(string.format("* Runtime Real : %s = %d sec", UTILS.SecondsToClock(PROFILER.runTimeOS, true), PROFILER.runTimeOS))
|
||||||
table.sort(t, function(a,b) return a.tm>b.tm end )
|
env.info(string.format("* Function time : %s = %.1f sec (%.1f percent of runtime game)", UTILS.SecondsToClock(Ttot, true), Ttot, Ttot/PROFILER.runTimeGame*100))
|
||||||
end
|
env.info(string.format("* Total functions : %d", #t))
|
||||||
|
env.info(string.format("* Total func calls : %d", Calls))
|
||||||
|
env.info(string.format("* Writing to file : \"%s\"", file))
|
||||||
|
env.info("**************************************************************************************************")
|
||||||
|
|
||||||
|
-- Sort by total time.
|
||||||
|
table.sort(t, function(a,b) return a.tm>b.tm end)
|
||||||
|
|
||||||
-- Write data.
|
-- Write data.
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog(f,"")
|
||||||
PROFILER._flog(f,"#### #### #### #### #### ##### #### #### #### #### ####")
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
PROFILER._flog(f,"#### #### #### ---- Profiler Report ---- #### #### ####")
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
PROFILER._flog(f,"#### Profiler Runtime: "..string.format("%.01f",PROFILER.runTime/60).." minutes")
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
PROFILER._flog(f,"#### #### #### #### #### ##### #### #### #### #### ####")
|
PROFILER._flog(f,"")
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog(f,"-------------------------")
|
||||||
PROFILER.showTable(t, f, false)
|
PROFILER._flog(f,"---- Profiler Report ----")
|
||||||
|
PROFILER._flog(f,"-------------------------")
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER._flog(f,string.format("* Runtime Game : %s = %.1f sec", UTILS.SecondsToClock(PROFILER.runTimeGame, true), PROFILER.runTimeGame))
|
||||||
|
PROFILER._flog(f,string.format("* Runtime Real : %s = %.1f sec", UTILS.SecondsToClock(PROFILER.runTimeOS, true), PROFILER.runTimeOS).." (can vary significantly compared to the game time)")
|
||||||
|
PROFILER._flog(f,string.format("* Function time : %s = %.1f sec (%.1f %% of runtime game)", UTILS.SecondsToClock(Ttot, true), Ttot, Ttot/PROFILER.runTimeGame*100))
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER._flog(f,string.format("* Total functions = %d", #t))
|
||||||
|
PROFILER._flog(f,string.format("* Total func calls = %d", Calls))
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER.showTable(t, f, true)
|
||||||
|
|
||||||
|
-- Sort by number of calls.
|
||||||
|
table.sort(t, function(a,b) return a.count>b.count end)
|
||||||
|
|
||||||
-- Detailed data.
|
-- Detailed data.
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog(f,"")
|
||||||
PROFILER._flog(f,"#### #### #### #### #### #### #### #### #### #### #### #### ####")
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
PROFILER._flog(f,"#### #### #### ---- Profiler Detailed Report ---- #### #### ####")
|
PROFILER._flog(f,"")
|
||||||
PROFILER._flog(f,"#### #### #### #### #### #### #### #### #### #### #### #### ####")
|
PROFILER._flog(f,"------------------------------")
|
||||||
|
PROFILER._flog(f,"---- Data Sorted by Calls ----")
|
||||||
|
PROFILER._flog(f,"------------------------------")
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog(f,"")
|
||||||
PROFILER.showTable(t, f, true)
|
PROFILER.showTable(t, f, true)
|
||||||
|
|
||||||
-- Closing.
|
-- Closing.
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog(f,"")
|
||||||
PROFILER._flog(f,"#### #### #### #### #### #### #### #### #### #### #### #### ####")
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
-- Close file.
|
-- Close file.
|
||||||
f:close()
|
f:close()
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user