enum ECLSForcedState { DEFAULT = 0, ForcedON = 1, ForcedOFF = 2, } struct ForcedStateData { persistent var state : ECLSForcedState; persistent var sourceName : CName; persistent var priority : EPriority; persistent var savable : Bool; default savable = true; } struct RecipientData { persistent var fuseID : Int32; persistent var entryID : Int32; } struct FuseData { persistent var psOwnerData : PSOwnerData; persistent var timeTable : array< SDeviceTimetableEntry >; persistent var lights : Int32; } class TimetableCallbackData extends IScriptable { private persistent var m_time : SSimpleGameTime; private persistent var m_recipients : array< RecipientData >; private persistent var m_callbackID : Uint32; public function Initialize( timetableEntry : SSimpleGameTime, recipient : RecipientData ) { m_time = timetableEntry; AddRecipient( recipient ); } public const function GetTime() : SSimpleGameTime { return m_time; } public const function GetGameTime() : GameTime { return GameTime.MakeGameTime( 0, m_time.hours, m_time.minutes, m_time.seconds ); } public const function GetRecipients() : array< RecipientData > { return m_recipients; } public const function GetCallbackID() : Uint32 { return m_callbackID; } public function AddRecipient( recipient : RecipientData ) { if( !( HasReciepient( recipient ) ) ) { m_recipients.PushBack( recipient ); } } public function SetCallbackID( id : Uint32 ) { m_callbackID = id; } private function HasReciepient( recipient : RecipientData ) : Bool { var i : Int32; for( i = 0; i < m_recipients.Size(); i += 1 ) { if( recipient.fuseID == m_recipients[ i ].fuseID ) { return true; } } return false; } } class CityLightSystemUpdateEvent extends Event { } class NotifyRecipientsRequest extends ScriptableSystemRequest { var recipients : array< RecipientData >; var time : GameTime; } class ForceCLSStateRequest extends ScriptableSystemRequest { editable var state : ECLSForcedState; editable var sourceName : CName; editable var priority : EPriority; default priority = EPriority.Medium; editable var removePreviousRequests : Bool; default removePreviousRequests = true; var savable : Bool; default savable = true; public constexpr function GetFriendlyDescription() : String { return "Force CLS State"; } } class TimeTableCallbackRequest extends ScriptableSystemRequest { var m_callBackID : Uint32; } class RegisterTimetableRequest extends ScriptableSystemRequest { var requesterData : PSOwnerData; var timeTable : array< SDeviceTimetableEntry >; var lights : Int32; } class UnregisterTimetableRequest extends ScriptableSystemRequest { var requesterData : PSOwnerData; } class CLSWeatherListener extends WeatherScriptListener { private var m_owner : weak< CityLightSystem >; public function Initialize( owner : CityLightSystem ) { m_owner = owner; } public export override function OnRainIntensityChanged( rainIntensity : Float ) {} public export override function OnRainIntensityTypeChanged( rainIntensityType : worldRainIntensity ) { if( rainIntensityType == worldRainIntensity.HeavyRain ) { TurnOnLights( 'RAIN' ); } else if( rainIntensityType == worldRainIntensity.NoRain ) { TurnOffLights( 'RAIN' ); } } private function TurnOnLights( reason : CName ) { var request : ForceCLSStateRequest; if( m_owner ) { request = new ForceCLSStateRequest; request.state = ECLSForcedState.ForcedON; request.sourceName = reason; request.priority = EPriority.VeryLow; request.removePreviousRequests = true; request.savable = false; m_owner.QueueRequest( request ); } } private function TurnOffLights( reason : CName ) { var request : ForceCLSStateRequest; if( m_owner ) { request = new ForceCLSStateRequest; request.state = ECLSForcedState.DEFAULT; request.sourceName = reason; request.priority = EPriority.VeryLow; request.removePreviousRequests = true; request.savable = false; m_owner.QueueRequest( request ); } } } class CityLightSystem extends ScriptableSystem { private persistent var m_timeSystemCallbacks : array< TimetableCallbackData >; private persistent var m_fuses : array< FuseData >; private persistent var m_state : ECLSForcedState; default m_state = ECLSForcedState.DEFAULT; private persistent var m_forcedStateSource : CName; private persistent var m_forcedStatesStack : array< ForcedStateData >; private var m_weatherListener : CLSWeatherListener; private var m_turnOffLisenerID : CName; private var m_turnOnLisenerID : CName; private var m_resetLisenerID : CName; private var m_weatherCallbackId : Uint32; private export override function OnAttach() { if( !( IsFinal() ) ) { InitializeDebugButtons(); ShowDebug_state(); } m_weatherListener = new CLSWeatherListener; m_weatherListener.Initialize( this ); m_weatherCallbackId = GameInstance.GetWeatherSystem( GetGameInstance() ).RegisterWeatherListener( m_weatherListener ); } private export override function OnDetach() { GameInstance.GetWeatherSystem( GetGameInstance() ).UnregisterWeatherListener( m_weatherCallbackId ); m_weatherListener = NULL; if( !( IsFinal() ) ) { UninitializeDebugButtons(); } } private export override function OnRestored( saveVersion : Int32, gameVersion : Int32 ) { var i : Int32; ResolveForcedStatesStackOnLoad(); for( i = 0; i < m_timeSystemCallbacks.Size(); i += 1 ) { RegisterTimetableCallback( m_timeSystemCallbacks[ i ] ); } if( !( IsFinal() ) ) { ShowDebug_fuses( m_fuses ); } } private export function OnTimeTableCallbackRequest( request : TimeTableCallbackRequest ) { var i : Int32; for( i = 0; i < m_timeSystemCallbacks.Size(); i += 1 ) { if( request.m_callBackID == m_timeSystemCallbacks[ i ].GetCallbackID() ) { NotifyRecipients( m_timeSystemCallbacks[ i ] ); if( !( IsFinal() ) ) { ShowDebug_fuses( m_fuses ); } } } } private export function OnRegisterTimetableRequest( request : RegisterTimetableRequest ) { AddTimeTableCallbacks( request.requesterData, request.timeTable, request.lights ); } private export function OnForceCLSStateRequest( request : ForceCLSStateRequest ) { var shoulEvaluate : Bool; if( request.state == ECLSForcedState.DEFAULT ) { shoulEvaluate = RemoveForcedStateRequestForSource( request.sourceName ); } else { if( request.removePreviousRequests ) { RemoveForcedStateRequestForSource( request.sourceName ); } shoulEvaluate = AddForcedStateRequest( request.state, request.sourceName, request.priority, request.savable ); } if( shoulEvaluate ) { EvaluateForcedStatesStack(); } } private function UpdateCLSForcedState() { var i : Int32; for( i = 0; i < m_fuses.Size(); i += 1 ) { SendForceStateDeviceTimetableEvent( m_fuses[ i ], m_state ); } } private function AddForcedStateRequest( state : ECLSForcedState, sourceName : CName, priority : EPriority, savable : Bool ) : Bool { var i : Int32; var data : ForcedStateData; if( state == ECLSForcedState.DEFAULT || !( IsNameValid( sourceName ) ) ) { return false; } for( i = 0; i < m_forcedStatesStack.Size(); i += 1 ) { if( ( m_forcedStatesStack[ i ].state == state && m_forcedStatesStack[ i ].sourceName == sourceName ) && m_forcedStatesStack[ i ].priority == priority ) { return false; } } data.state = state; data.sourceName = sourceName; data.priority = priority; data.savable = savable; m_forcedStatesStack.PushBack( data ); return true; } private function RemoveForcedStateRequestForSource( sourceName : CName ) : Bool { var i : Int32; var wasRemoved : Bool; if( !( IsNameValid( sourceName ) ) ) { return false; } for( i = m_forcedStatesStack.Size() - 1; i >= 0; i -= 1 ) { if( m_forcedStatesStack[ i ].sourceName == sourceName ) { m_forcedStatesStack.Erase( i ); wasRemoved = true; } } return wasRemoved; } private function ResolveForcedStatesStackOnLoad() { var wasRemoved : Bool; var i : Int32; for( i = m_forcedStatesStack.Size() - 1; i >= 0; i -= 1 ) { if( !( IsNameValid( m_forcedStatesStack[ i ].sourceName ) ) || !( IsForcedRequestSavable( m_forcedStatesStack[ i ] ) ) ) { m_forcedStatesStack.Erase( i ); wasRemoved = true; } } if( wasRemoved ) { EvaluateForcedStatesStack(); } } private function EvaluateForcedStatesStack() { var i : Int32; var newPriority : EPriority; var newState : ECLSForcedState; var newSource : CName; var shouldUpdate : Bool; shouldUpdate = false; newPriority = EPriority.VeryLow; newState = ECLSForcedState.DEFAULT; for( i = 0; i < m_forcedStatesStack.Size(); i += 1 ) { if( !( IsNameValid( m_forcedStatesStack[ i ].sourceName ) ) ) { continue; } if( ( ( Int32 )( m_forcedStatesStack[ i ].priority ) ) >= ( ( Int32 )( newPriority ) ) ) { newPriority = m_forcedStatesStack[ i ].priority; newState = m_forcedStatesStack[ i ].state; newSource = m_forcedStatesStack[ i ].sourceName; } } if( m_state != newState ) { shouldUpdate = true; } m_state = newState; m_forcedStateSource = newSource; if( shouldUpdate ) { UpdateCLSForcedState(); if( !( IsFinal() ) ) { ShowDebug_state(); } } } private function IsForcedRequestSavable( data : ForcedStateData ) : Bool { if( data.sourceName == 'RAIN' ) { return false; } else { return data.savable; } } private function RegisterTimetableCallback( callbackData : TimetableCallbackData ) { var request : TimeTableCallbackRequest; var timeout : GameTime; var entryTime : GameTime; var timeSystem : TimeSystem; timeSystem = GameInstance.GetTimeSystem( GetGameInstance() ); timeout = GameTime.MakeGameTime( 0, 24, 0, 0 ); request = new TimeTableCallbackRequest; entryTime = callbackData.GetGameTime(); timeout += entryTime; request.m_callBackID = timeSystem.RegisterScriptableSystemIntervalListener( 'CityLightSystem', request, entryTime, timeout, -1 ); callbackData.SetCallbackID( request.m_callBackID ); NotifyRecipientsOnRegistration( callbackData ); } private function NotifyRecipientsOnRegistration( callbackData : TimetableCallbackData ) { var recipients : array< RecipientData >; var i : Int32; recipients = callbackData.GetRecipients(); for( i = 0; i < recipients.Size(); i += 1 ) { if( ShouldNotifyRecipient( recipients[ i ], callbackData.GetGameTime() ) ) { SendDeviceTimetableEvent( recipients[ i ] ); } } } private function NotifyRecipients( callbackData : TimetableCallbackData ) { var recipients : array< RecipientData >; recipients = callbackData.GetRecipients(); SendNotificationToRecipients( recipients, callbackData.GetGameTime() ); } private function SendNotificationToRecipients( const recipients : ref< array< RecipientData > >, time : GameTime ) { var i : Int32; var totalNotifications : Int32; var excessRecipients : array< RecipientData >; for( i = 0; i < recipients.Size(); i += 1 ) { if( totalNotifications >= GetMaxNotificationsPerFrame() ) { excessRecipients.PushBack( recipients[ i ] ); } else if( ShouldNotifyRecipient( recipients[ i ], time ) ) { SendDeviceTimetableEvent( recipients[ i ] ); totalNotifications += 1; } } if( excessRecipients.Size() > 0 ) { SendNotificationByRequest( excessRecipients, time ); } } private function SendNotificationByRequest( const recipients : ref< array< RecipientData > >, time : GameTime ) { var request : NotifyRecipientsRequest; request = new NotifyRecipientsRequest; request.recipients = recipients; request.time = time; GameInstance.GetDelaySystem( GetGameInstance() ).DelayScriptableSystemRequestNextFrame( GetClassName(), request ); } private function OnNotifyRecipientsrequest( request : NotifyRecipientsRequest ) { SendNotificationToRecipients( request.recipients, request.time ); } private constexpr static function GetMaxNotificationsPerFrame() : Int32 { return 50; } private function SendDeviceTimetableEvent( data : RecipientData ) { var evt : DeviceTimetableEvent; var fuse : FuseData; evt = new DeviceTimetableEvent; if( GetFuse( data.fuseID, fuse ) ) { if( m_state == ECLSForcedState.DEFAULT ) { evt.state = fuse.timeTable[ data.entryID ].state; } else if( m_state == ECLSForcedState.ForcedON ) { evt.state = EDeviceStatus.ON; } else if( m_state == ECLSForcedState.ForcedOFF ) { evt.state = EDeviceStatus.OFF; } evt.requesterID = PersistentID.ExtractEntityID( fuse.psOwnerData.id ); if( EntityID.IsDefined( evt.requesterID ) ) { GameInstance.GetPersistencySystem( GetGameInstance() ).QueuePSEvent( fuse.psOwnerData.id, fuse.psOwnerData.className, evt ); } } } private function SendForceStateDeviceTimetableEvent( const fuse : ref< FuseData >, state : ECLSForcedState ) { var evt : DeviceTimetableEvent; var entry : SDeviceTimetableEntry; evt = new DeviceTimetableEvent; if( m_state == ECLSForcedState.DEFAULT ) { GetActiveTimeTableEntry( fuse, entry ); evt.state = entry.state; } else if( m_state == ECLSForcedState.ForcedON ) { evt.state = EDeviceStatus.ON; } else if( m_state == ECLSForcedState.ForcedOFF ) { evt.state = EDeviceStatus.OFF; } evt.requesterID = PersistentID.ExtractEntityID( fuse.psOwnerData.id ); if( EntityID.IsDefined( evt.requesterID ) ) { GameInstance.GetPersistencySystem( GetGameInstance() ).QueuePSEvent( fuse.psOwnerData.id, fuse.psOwnerData.className, evt ); } } private function AddTimeTableCallbacks( requesterData : PSOwnerData, const timeTable : ref< array< SDeviceTimetableEntry > >, optional lights : Int32 ) { var i : Int32; var callbackData : TimetableCallbackData; var recipientData : RecipientData; var fuseID : Int32; fuseID = AddFuse( requesterData, timeTable, lights ); for( i = 0; i < timeTable.Size(); i += 1 ) { callbackData = GetTimeTableCallback( timeTable[ i ].time ); recipientData.fuseID = fuseID; recipientData.entryID = i; if( callbackData == NULL ) { callbackData = new TimetableCallbackData; callbackData.Initialize( timeTable[ i ].time, recipientData ); m_timeSystemCallbacks.PushBack( callbackData ); RegisterTimetableCallback( callbackData ); } else { callbackData.AddRecipient( recipientData ); } } } private function GetTimeTableCallback( time : SSimpleGameTime ) : TimetableCallbackData { var i : Int32; for( i = 0; i < m_timeSystemCallbacks.Size(); i += 1 ) { if( IsTimeTheSame( m_timeSystemCallbacks[ i ].GetTime(), time ) ) { return m_timeSystemCallbacks[ i ]; } } return NULL; } private function AddFuse( requesterData : PSOwnerData, const timeTable : ref< array< SDeviceTimetableEntry > >, optional lights : Int32 ) : Int32 { var fuse : FuseData; var id : Int32; if( !( HasFuse( requesterData, id ) ) ) { fuse.psOwnerData = requesterData; fuse.timeTable = timeTable; fuse.lights = lights; m_fuses.PushBack( fuse ); if( !( IsFinal() ) ) { ShowDebug_fuses( m_fuses ); } id = m_fuses.Size() - 1; return id; } return id; } private const function HasFuse( requesterData : PSOwnerData, out id : Int32 ) : Bool { var i : Int32; for( i = 0; i < m_fuses.Size(); i += 1 ) { if( m_fuses[ i ].psOwnerData.id == requesterData.id ) { id = i; return true; } } id = -1; return false; } private const function GetFuseID( requesterData : PSOwnerData ) : Int32 { var i : Int32; for( i = 0; i < m_fuses.Size(); i += 1 ) { if( m_fuses[ i ].psOwnerData.id == requesterData.id ) { return i; } } return -1; } private const function GetFuseID( id : PersistentID ) : Int32 { var i : Int32; for( i = 0; i < m_fuses.Size(); i += 1 ) { if( m_fuses[ i ].psOwnerData.id == id ) { return i; } } return -1; } private const function GetFuse( fuseID : Int32, fuseData : ref< FuseData > ) : Bool { if( ( fuseID >= 0 ) && ( fuseID < m_fuses.Size() ) ) { fuseData = m_fuses[ fuseID ]; return true; } return false; } private function IsTimeTheSame( time1 : SSimpleGameTime, time2 : SSimpleGameTime ) : Bool { return ( ( time1.hours == time2.hours ) && ( time1.minutes == time2.minutes ) ) && ( time1.seconds == time2.seconds ); } private const function GetCurrentTime() : GameTime { var currentTime : GameTime; var time : GameTime; currentTime = GameInstance.GetTimeSystem( GetGameInstance() ).GetGameTime(); time = GameTime.MakeGameTime( 0, GameTime.Hours( currentTime ), GameTime.Minutes( currentTime ), GameTime.Seconds( currentTime ) ); return time; } private const function ShouldNotifyRecipient( recipient : RecipientData, callbackTime : GameTime ) : Bool { var entryTime : GameTime; var entry : SDeviceTimetableEntry; var fuse : FuseData; if( !( GetFuse( recipient.fuseID, fuse ) ) ) { return false; } if( GetActiveTimeTableEntry( fuse, entry ) ) { entryTime = GameTime.MakeGameTime( 0, entry.time.hours, entry.time.minutes, entry.time.seconds ); return entryTime == callbackTime; } else { return false; } } private const function GetActiveTimeTableEntry( const fuse : ref< FuseData >, out entry : SDeviceTimetableEntry ) : Bool { var currentTime : GameTime; var entryTime : GameTime; var time : GameTime; var storedtime : GameTime; var i : Int32; var id : Int32; var wasTimeStored : Bool; currentTime = GetCurrentTime(); id = -1; for( i = 0; i < fuse.timeTable.Size(); i += 1 ) { entryTime = GameTime.MakeGameTime( 0, fuse.timeTable[ i ].time.hours, fuse.timeTable[ i ].time.minutes, fuse.timeTable[ i ].time.seconds ); if( currentTime < entryTime ) { time = ( GameTime.MakeGameTime( 0, 24, 0, 0 ) - entryTime ) + currentTime; } else { time = currentTime - entryTime; } if( ( time < storedtime ) || !( wasTimeStored ) ) { wasTimeStored = true; storedtime = time; id = i; entry = fuse.timeTable[ i ]; } } return id >= 0; } private const function GetActiveTimeTableEntryID( const fuse : ref< FuseData > ) : Int32 { var currentTime : GameTime; var entryTime : GameTime; var time : GameTime; var storedtime : GameTime; var i : Int32; var id : Int32; var wasTimeStored : Bool; currentTime = GetCurrentTime(); id = -1; for( i = 0; i < fuse.timeTable.Size(); i += 1 ) { entryTime = GameTime.MakeGameTime( 0, fuse.timeTable[ i ].time.hours, fuse.timeTable[ i ].time.minutes, fuse.timeTable[ i ].time.seconds ); if( currentTime < entryTime ) { time = ( GameTime.MakeGameTime( 0, 24, 0, 0 ) - entryTime ) + currentTime; } else { time = currentTime - entryTime; } if( ( time < storedtime ) || !( wasTimeStored ) ) { wasTimeStored = true; storedtime = time; id = i; } } return id; } public const function GetFuseStateByID( id : PersistentID ) : EDeviceStatus { var fuse : FuseData; var returnValue : EDeviceStatus; var entry : SDeviceTimetableEntry; returnValue = EDeviceStatus.DISABLED; if( m_state == ECLSForcedState.DEFAULT ) { if( GetFuse( GetFuseID( id ), fuse ) ) { if( GetActiveTimeTableEntry( fuse, entry ) ) { returnValue = entry.state; } } } else { if( m_state == ECLSForcedState.ForcedON ) { returnValue = EDeviceStatus.ON; } else if( m_state == ECLSForcedState.ForcedOFF ) { returnValue = EDeviceStatus.OFF; } } return returnValue; } public const function GetState() : ECLSForcedState { return m_state; } public const function GetFusesCount() : Int32 { return m_fuses.Size(); } public const function GetLightsCount() : Int32 { var i : Int32; var counter : Int32; for( i = 0; i < m_fuses.Size(); i += 1 ) { counter += m_fuses[ i ].lights; } return counter; } public const function GetCallbacks() : array< TimetableCallbackData > { return m_timeSystemCallbacks; } private function OnDebugButtonClicked( request : SDOClickedRequest ) { var stateRequest : ForceCLSStateRequest; stateRequest = new ForceCLSStateRequest; if( request.key == 'Turn On' ) { stateRequest.state = ECLSForcedState.ForcedON; stateRequest.sourceName = 'DEBUG'; stateRequest.priority = EPriority.Absolute; stateRequest.removePreviousRequests = true; QueueRequest( stateRequest ); } else if( request.key == 'Turn Off' ) { stateRequest.state = ECLSForcedState.ForcedOFF; stateRequest.sourceName = 'DEBUG'; stateRequest.priority = EPriority.Absolute; stateRequest.removePreviousRequests = true; QueueRequest( stateRequest ); } else if( request.key == 'Reset' ) { stateRequest.state = ECLSForcedState.DEFAULT; stateRequest.sourceName = 'DEBUG'; stateRequest.priority = EPriority.Absolute; stateRequest.removePreviousRequests = true; QueueRequest( stateRequest ); } } private function UninitializeDebugButtons() { var sink : SDOSink; sink = GameInstance.GetScriptsDebugOverlaySystem( GetGameInstance() ).CreateSink(); SDOSink.SetRoot( sink, "CLS" ); SDOSink.UnregisterListener_OnClicked( sink, this, m_turnOffLisenerID ); SDOSink.UnregisterListener_OnClicked( sink, this, m_turnOnLisenerID ); SDOSink.UnregisterListener_OnClicked( sink, this, m_resetLisenerID ); } private function InitializeDebugButtons() { var sink : SDOSink; sink = GameInstance.GetScriptsDebugOverlaySystem( GetGameInstance() ).CreateSink(); SDOSink.SetRoot( sink, "CLS" ); SDOSink.PushString( sink, "Turn On", "EXECUTE" ); SDOSink.PushString( sink, "Turn Off", "EXECUTE" ); SDOSink.PushString( sink, "Reset", "EXECUTE" ); m_turnOnLisenerID = SDOSink.RegisterListener_OnClicked( sink, this, "Turn On" ); m_turnOffLisenerID = SDOSink.RegisterListener_OnClicked( sink, this, "Turn Off" ); m_resetLisenerID = SDOSink.RegisterListener_OnClicked( sink, this, "Reset" ); } private function ShowDebug_state() { var sink : SDOSink; sink = GameInstance.GetScriptsDebugOverlaySystem( GetGameInstance() ).CreateSink(); SDOSink.SetRoot( sink, "CLS" ); SDOSink.PushString( sink, "STATE", ( ( String )( GetState() ) ) ); SDOSink.SetRoot( sink, "CLS/STATE" ); SDOSink.PushName( sink, "SOURCE", m_forcedStateSource ); } private function ShowDebug_fuses( const fuses : ref< array< FuseData > > ) { var sink : SDOSink; var entryString : String; var stateString : String; var globalIDString : String; var activeEntry : SDeviceTimetableEntry; var i : Int32; var k : Int32; sink = GameInstance.GetScriptsDebugOverlaySystem( GetGameInstance() ).CreateSink(); SDOSink.SetRoot( sink, "CLS" ); SDOSink.PushString( sink, "FUSES", ( ( String )( GetFusesCount() ) ) ); SDOSink.PushString( sink, "LIGHTS", ( ( String )( GetLightsCount() ) ) ); for( i = 0; i < fuses.Size(); i += 1 ) { globalIDString = PersistentID.ToDebugString( fuses[ i ].psOwnerData.id ); if( !( PersistentID.IsDefined( fuses[ i ].psOwnerData.id ) ) ) { globalIDString += " [WARNING: INVALID GLOBAL ID!]"; } SDOSink.SetRoot( sink, "CLS/FUSES/fuse" + ( ( String )( i ) ) ); SDOSink.PushString( sink, "", globalIDString ); SDOSink.PushString( sink, "globalID", globalIDString ); SDOSink.PushString( sink, "connectedLights", ( ( String )( fuses[ i ].lights ) ) ); for( k = 0; k < fuses[ i ].timeTable.Size(); k += 1 ) { activeEntry = fuses[ i ].timeTable[ k ]; entryString = ( ( ( ( ( String )( activeEntry.time.hours ) ) + " : " ) + ( ( String )( activeEntry.time.minutes ) ) ) + " : " ) + ( ( String )( activeEntry.time.seconds ) ); stateString = ( " [" + ( ( String )( activeEntry.state ) ) ) + "]"; entryString += stateString; if( GetActiveTimeTableEntryID( fuses[ i ] ) == k ) { entryString += " [ACTIVE]"; } SDOSink.PushString( sink, "entry" + ( ( String )( k ) ), entryString ); } } } }