/// <summary> /// Saves information about the trigger call in the history database /// </summary> /// <param name="call">Trigger call information</param> /// <param name="dbContext">Database context</param> private async Task TriggerHistoryEntryAsync(TriggerCall call, ITriggerHistoryManager triggerHistoryManager) { _logger.LogInformation("Plastic called trigger: {trigger}", call.Type); // Save trigger call await triggerHistoryManager.StoreTriggerCallAsync(call); }
private MethodInfo FindMethod(TriggerCall call) { var argType = typeof(Object); if (!string.IsNullOrEmpty(call.Arguments.unityObjectArgumentAssemblyTypeName)) { argType = Type.GetType(call.Arguments.unityObjectArgumentAssemblyTypeName, false) ?? typeof(Object); } return(FindMethod(call.MethodName, call.Target, call.Mode, argType)); }
/// <summary> /// Prepare the actual text message /// </summary> /// <param name="rule">Notification rule configuration data</param> /// <param name="call">Trigger call information</param> private Message PrepareMessage(NotificationRule rule, TriggerCall call) => new Message(rule.NotificationBodyType) { // Replace PLASTIC-placeholers in all fields of the message Title = TextHelper.ReplaceVars(rule.NotificationTitle ?? string.Empty, call.EnvironmentVars), Body = TextHelper.ReplaceVars(rule.NotificationBody ?? string.Empty, call.EnvironmentVars), Tags = TextHelper.ReplaceVars(rule.NotificationTags ?? string.Empty, call.EnvironmentVars) .Split(',') .Select(tag => tag.Trim()) .ToArray() };
/// <summary> /// Queues a trigger call /// </summary> /// <param name="call">Trigger call information</param> public void QueueTriggerCall(TriggerCall call) { if (call == null) { throw new ArgumentNullException(nameof(call)); } // Enqueue _calls.Enqueue(call); // Send signal to waiting dequeue _signal.Release(); }
/// <summary> /// Finds all notification rules for a trigger call and sends the notifications /// </summary> /// <param name="call">Trigger call</param> /// <returns></returns> private async Task EvaluateNotificationRulesAsync(TriggerCall call, INotificationRulesManager notificationRulesManager) { // Get all rules for the rigger var triggerRules = await notificationRulesManager.GetRulesOwnedTiggerType(call.Type).ToListAsync(); // Apply filters var filteredRules = _conditionEval.EvalFilterAsync(triggerRules, call.EnvironmentVars, call.Input); // Send them notifications for each rule await foreach (var rule in filteredRules) { // Send notifications in parallel await RunRuleAsync(rule, call); } }
public async Task <IActionResult> FireAsync([FromRoute] string type) { // Check parameter if (string.IsNullOrWhiteSpace(type)) { return(BadRequest()); } // Read POST body to TriggerCall object TriggerCall call = null; using (var reader = new StreamReader(Request.Body)) { string body = await reader.ReadToEndAsync(); if (string.IsNullOrWhiteSpace(body)) { return(BadRequest()); } try { // Parse post body call = TriggerCall.ParseJson(body, type); } catch (JsonException jsonEx) { _logger.LogError(jsonEx, "Error while parsing trigger call"); return(BadRequest()); } catch (InvalidOperationException ex) { _logger.LogError(ex, "Error while parsing trigger call"); return(BadRequest()); } } // Handle the rest in the background _notificationQueue.QueueTriggerCall(call); // Return Success message to Plastic SCM return(Ok("Trigger ok")); }
/// <summary> /// Saves a new trigger invocation to the history /// </summary> /// <param name="call">Trigger call information</param> public async Task StoreTriggerCallAsync(TriggerCall call) { // remove old values _dbContext.TriggerVariables.RemoveRange(_dbContext.TriggerVariables.Where(v => v.Trigger == call.Type)); // prepare new values List <TriggerVariable> variables = new List <TriggerVariable>( call.EnvironmentVars.Select(var => new TriggerVariable(call.Type, var.Key, var.Value)) ); // add new values await _dbContext.TriggerHistory.AddAsync(TriggerHistory.From(call)); await _dbContext.TriggerVariables.AddRangeAsync(variables); // save await _dbContext.SaveChangesAsync(); }
/// <summary> /// Send the notifications for a rule /// </summary>z /// <param name="rule">Notification rule</param> /// <param name="call">Trigger call information</param> private async Task RunRuleAsync(NotificationRule rule, TriggerCall call) { // Validate notifiers prerequisite if (!rule.Notifiers.Any()) { _logger.LogError("This rule has no notifiers: {ruleName}", rule.DisplayName); return; } // Log rule using var _ = _logger.BeginScope("Sending notifications for rule: {ruleName}", rule.DisplayName); // Prepare the message texts var message = await Task.Run(() => PrepareMessage(rule, call)); if (string.IsNullOrWhiteSpace(message.Body)) { _logger.LogError("The message body is empty for rule: {ruleName}", rule.DisplayName); return; } _logger.LogDebug("The message is: {message}", message.ToString()); // Apply global template if (rule.UseGlobalMessageTemplate) { using var scope = _serviceProvider.CreateScope(); IAppSettingsManager appSettingsManager = scope.ServiceProvider.GetRequiredService <IAppSettingsManager>(); AppSettings appSettings = appSettingsManager.AppSettings; message.ApplyTemplate(appSettings.HtmlMessageTemplate, $"{appSettings.BaseUrl}/Rules"); } // Resolv groups and get all recipient users var recipients = await Task.Run(() => GetRecipientUsers(rule)); _logger.LogDebug("Recipients are: {recipients}", string.Join(", ", recipients.Select(u => u.UserName))); // send message through each notifier rule.Notifiers .Select(notifier => notifier.Notifier) .AsParallel().ForAll(async notifier => await SendMessageAsync(notifier, message, recipients)); }
public CallBinding(TriggerCall call, Action onUnbind, Action onRebind = null) { _onUnbind = onUnbind; _onRebind = onRebind; View = call._view; }
/// <summary> /// Checks if a TriggerCall for a given Theme has already been stored in the map for this tick, and updates the map accordingly. /// </summary> /// <param name="triggerCall"></param> private void ProcessTriggerCall(TriggerCall triggerCall) { bool storeNewTriggerCall = false; if (mapThemeIdsToTriggerCalls.ContainsKey(triggerCall.themeId)) { TriggerCall storedTriggerCall = mapThemeIdsToTriggerCalls[triggerCall.themeId]; if (triggerCall.senderBehaviour.addUpIntensities) { triggerCall.intensity += storedTriggerCall.intensity; if (triggerCall.intensity > triggerCall.senderBehaviour.limitIntensitySum) { triggerCall.intensity = triggerCall.senderBehaviour.limitIntensitySum; } storeNewTriggerCall = true; } else { if (storedTriggerCall.intensity < triggerCall.intensity) { storeNewTriggerCall = true; } } } else { storeNewTriggerCall = true; } if (storeNewTriggerCall) { mapThemeIdsToTriggerCalls[triggerCall.themeId] = triggerCall; } }
void ProcessAllIncomingTriggerCallsForThisTick() { mapThemeIdsToTriggerCalls.Clear(); foreach (PsaiSynchronizedTrigger triggerBehaviour in continuousTriggersInScene) { if (triggerBehaviour.EvaluateAllTriggerConditions() == true) { float calculatedIntensity = triggerBehaviour.CalculateTriggerIntensity(); TriggerCall triggerCall = new TriggerCall(triggerBehaviour, triggerBehaviour.themeId, calculatedIntensity, triggerBehaviour.musicDurationInSeconds); ProcessTriggerCall(triggerCall); } } // Now we check for synchronized One-Shot Triggers foreach (TriggerCall triggerCall in _synchronizedOneShotTriggerCallsForNextTick) { if (triggerCall.intensity > 0) { ProcessTriggerCall(triggerCall); } } _synchronizedOneShotTriggerCallsForNextTick.Clear(); // Execute explicit calls to GoToRest, StopMusic,... if (playbackControlCallFiringInThisTick.controlType != PlaybackControlType.None) { bool executeControlCall = true; if (mapThemeIdsToTriggerCalls.Keys.Count > 0 && playbackControlCallFiringInThisTick.dontExecuteIfOtherTriggersAreFiring == true) { foreach(int themeId in mapThemeIdsToTriggerCalls.Keys) { ThemeInfo themeInfo = PsaiCore.Instance.GetThemeInfo(themeId); if (themeInfo.type == playbackControlCallFiringInThisTick.restrictBlockToThisThemeType) { #if !(PSAI_NOLOG) if (this.logTriggerScripts) { Debug.LogWarning("skipping " + playbackControlCallFiringInThisTick.controlType + " as there are other Triggers firing:" + themeInfo.type); } #endif executeControlCall = false; break; } } } if (executeControlCall) { switch (playbackControlCallFiringInThisTick.controlType) { case PlaybackControlType.StopMusic: { PsaiCore.Instance.StopMusic(playbackControlCallFiringInThisTick.immediately); } break; case PlaybackControlType.GoToRest: { PsaiCore.Instance.GoToRest(playbackControlCallFiringInThisTick.immediately, playbackControlCallFiringInThisTick.fadeOutSeconds, playbackControlCallFiringInThisTick.overrideRestSecondsMin * 1000, playbackControlCallFiringInThisTick.overrideRestSecondsMax * 1000); } break; case PlaybackControlType.ReturnToLastBasicMood: { PsaiCore.Instance.ReturnToLastBasicMood(playbackControlCallFiringInThisTick.immediately); } break; } } playbackControlCallFiringInThisTick.Init(); } foreach (TriggerCall triggerCall in mapThemeIdsToTriggerCalls.Values) { // adding up triggers may exceed the limit float triggerIntensity = Mathf.Min(1.0f, triggerCall.intensity); if (logTriggerScripts) { Debug.Log("[" + Time.timeSinceLevelLoad + " ]PsaiCoreManager executing TriggerCall " + triggerCall.ToString()); } if (triggerCall.forceImmediateStopBeforeTriggering) { PsaiCore.Instance.StopMusic(true); } if (triggerCall.senderBehaviour.overrideMusicDurationInSeconds && triggerCall.musicDurationInSeconds > 0) { PsaiCore.Instance.TriggerMusicTheme(triggerCall.themeId, triggerIntensity, triggerCall.musicDurationInSeconds); } else { PsaiCore.Instance.TriggerMusicTheme(triggerCall.themeId, triggerIntensity); } } }
public void RegisterOneShotTriggerCall(TriggerCall triggerCall) { _synchronizedOneShotTriggerCallsForNextTick.Add(triggerCall); }
/// <summary> /// Creates a new instance of TriggerHistory for a TriggerCall /// </summary> /// <param name="call">The call to a trigger that should be preserved in history</param> /// <returns>A new TriggerHistory instance</returns> public static TriggerHistory From(TriggerCall call) => new TriggerHistory(call.Type, string.Join(Environment.NewLine, call.Input));
protected virtual void Start() { bodyTriggerRef = bodyRef.GetComponent <TriggerCall>(); turretTriggerRef = turretRef.GetComponent <TriggerCall>(); backWardsSpeed = movementSpeed / 2; }