ScheduledEvent.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. using Comal.Classes;
  2. using InABox.Core;
  3. using InABox.Database;
  4. using InABox.Scripting;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Runtime.Serialization;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. namespace PRS.Shared.Events;
  12. public class ScheduledEventDayOfWeek : BaseObject
  13. {
  14. [EditorSequence(1)]
  15. [Editable(Editable.Disabled)]
  16. public DayOfWeek DayOfWeek { get; set; }
  17. [EditorSequence(2)]
  18. [TimeOfDayEditor]
  19. public TimeSpan StartTime { get; set; } = TimeSpan.Zero;
  20. [EditorSequence(3)]
  21. [TimeOfDayEditor]
  22. public TimeSpan EndTime { get; set; } = new TimeSpan(23, 59, 59);
  23. [EditorSequence(4)]
  24. public bool Enabled { get; set; } = true;
  25. public ScheduledEventDayOfWeek()
  26. {
  27. }
  28. public ScheduledEventDayOfWeek(DayOfWeek dayOfWeek)
  29. {
  30. DayOfWeek = dayOfWeek;
  31. }
  32. static ScheduledEventDayOfWeek()
  33. {
  34. DefaultColumns.Add<ScheduledEventDayOfWeek>(x => x.DayOfWeek);
  35. DefaultColumns.Add<ScheduledEventDayOfWeek>(x => x.StartTime);
  36. DefaultColumns.Add<ScheduledEventDayOfWeek>(x => x.EndTime);
  37. }
  38. }
  39. /// <summary>
  40. /// Properties class to manage the timing of a scheduled event.
  41. /// </summary>
  42. /// <remarks>
  43. /// <para>
  44. /// This is fairly complex. First, we have the <see cref="Frequency"/> and <see cref="Period"/> properties. These function as expected.
  45. /// If <see cref="Frequency"/> is 3, and <see cref="Period"/> is <see cref="SchedulePeriod.Hour"/>, the event happens every three hours. Similarly,
  46. /// if <see cref="Frequency"/> is 4, and <see cref="Period"/> is <see cref="SchedulePeriod.Month"/>, the event happens every four months.
  47. /// </para>
  48. /// <para>
  49. /// However, the other properties are dependent on <see cref="Period"/>. If <see cref="Period"/> is <see cref="SchedulePeriod.Minute"/>,
  50. /// <see cref="SchedulePeriod.Hour"/> or <see cref="SchedulePeriod.Day"/> (that is, anything a day or smaller), the <see cref="DayOfWeekSettings"/>
  51. /// is used, which says which days of the week the schedule should occur, and at what time on those days.
  52. /// If the period is <see cref="SchedulePeriod.Day"/>, then only the <see cref="ScheduledEventDayOfWeek.StartTime"/> is used, and the event occurs
  53. /// at that time. Otherwise, the event occurs at regular intervals according to the frequency and period, beginning at
  54. /// <see cref="ScheduledEventDayOfWeek.StartTime"/> and running until <see cref="ScheduledEventDayOfWeek.EndTime"/>.
  55. /// </para>
  56. /// <para>
  57. /// Alternatively, if the period is greater than a day, <see cref="NextSchedule"/> is used, and whenever the schedule executes, it is updated by the
  58. /// frequency and period <i>from the due date</i>, and not from when the schedule actually occurred.
  59. /// </para>
  60. /// </remarks>
  61. public class ScheduledEventProperties : BaseObject
  62. {
  63. [EditorSequence(1)]
  64. public int Frequency { get; set; } = 1;
  65. [EditorSequence(2)]
  66. public SchedulePeriod Period { get; set; } = SchedulePeriod.Hour;
  67. [EditorSequence(3)]
  68. public DateTime NextSchedule { get; set; }
  69. [EditorSequence(4)]
  70. [Editable(Editable.Disabled)]
  71. [TimestampEditor]
  72. public DateTime LastExecution { get; set; }
  73. [EmbeddedListEditor(typeof(ScheduledEventDayOfWeek), AddRows = false)]
  74. public List<ScheduledEventDayOfWeek> DayOfWeekSettings { get; set; } = new()
  75. {
  76. new(DayOfWeek.Monday),
  77. new(DayOfWeek.Tuesday),
  78. new(DayOfWeek.Wednesday),
  79. new(DayOfWeek.Thursday),
  80. new(DayOfWeek.Friday),
  81. new(DayOfWeek.Saturday),
  82. new(DayOfWeek.Sunday),
  83. };
  84. [OnDeserializing]
  85. private void OnDeserialisingMethod(StreamingContext context)
  86. {
  87. DayOfWeekSettings.Clear();
  88. }
  89. }
  90. public class ScheduledEvent : IEvent<ScheduledEventDataModel>, IPropertiesEvent<ScheduledEventProperties>
  91. {
  92. public ScheduledEventProperties Properties { get; set; } = new();
  93. public IEventDataModelDefinition DataModelDefinition()
  94. {
  95. return new ScheduledEventDataModelDefinition();
  96. }
  97. public Notification GenerateNotification(ScheduledEventDataModel model)
  98. {
  99. var notification = new Notification();
  100. notification.Title = $"Schedule has run.";
  101. notification.Description = $"Schedule has run.";
  102. return notification;
  103. }
  104. public void Init(IStore store, IEventData data, ScheduledEventDataModel model)
  105. {
  106. }
  107. public ScheduledEventProperties GetProperties()
  108. {
  109. return Properties;
  110. }
  111. public void SetProperties(ScheduledEventProperties properties)
  112. {
  113. Properties = properties;
  114. }
  115. }
  116. public class ScheduledEventDataModelDefinition : IEventDataModelDefinition
  117. {
  118. public IEventVariable? GetVariable(string name)
  119. {
  120. return null;
  121. }
  122. public IEnumerable<IEventVariable> GetVariables()
  123. {
  124. return [];
  125. }
  126. }
  127. public class ScheduledEventDataModel : IEventDataModel
  128. {
  129. public bool TryGetVariable(string name, out object? value)
  130. {
  131. value = null;
  132. return false;
  133. }
  134. }
  135. #region Triggers
  136. [Caption("Custom Script")]
  137. public class ScriptScheduledEventTrigger : IEventTrigger<ScheduledEvent, ScheduledEventDataModel>
  138. {
  139. public string Description => "Custom Script";
  140. private ScriptDocument? _scriptDocument;
  141. private ScriptDocument? ScriptDocument
  142. {
  143. get
  144. {
  145. if(_scriptDocument is null && Script is not null)
  146. {
  147. _scriptDocument = new(Script);
  148. _scriptDocument.Compile();
  149. }
  150. return _scriptDocument;
  151. }
  152. }
  153. private string? _script;
  154. public string? Script
  155. {
  156. get => _script;
  157. set
  158. {
  159. if(_script != value)
  160. {
  161. _script = value;
  162. _scriptDocument = null;
  163. }
  164. }
  165. }
  166. public IEnumerable<string> ReferencedVariables => [];
  167. public string DefaultScript()
  168. {
  169. return @"using PRS.Shared.Events;
  170. public class Module
  171. {
  172. public bool Check(ScheduledEventDataModel model)
  173. {
  174. // Return true if the requirements are met for this event trigger.
  175. return true;
  176. }
  177. }";
  178. }
  179. public bool Check(ScheduledEventDataModel dataModel)
  180. {
  181. if (ScriptDocument is null) return false;
  182. return ScriptDocument.Execute(methodname: "Check", parameters: [dataModel]);
  183. }
  184. }
  185. #endregion
  186. #region Actions
  187. [Caption("Custom Script")]
  188. public class ScriptScheduledEventAction : IEventAction<ScheduledEvent>
  189. {
  190. private ScriptDocument? _scriptDocument;
  191. private ScriptDocument? ScriptDocument
  192. {
  193. get
  194. {
  195. if(_scriptDocument is null && Script is not null)
  196. {
  197. _scriptDocument = new(Script);
  198. _scriptDocument.SetValue("Result", null);
  199. _scriptDocument.Compile();
  200. }
  201. return _scriptDocument;
  202. }
  203. }
  204. private string? _script;
  205. public string? Script
  206. {
  207. get => _script;
  208. set
  209. {
  210. if(_script != value)
  211. {
  212. _script = value;
  213. _scriptDocument = null;
  214. }
  215. }
  216. }
  217. public IEnumerable<string> ReferencedVariables => [];
  218. public string Description => "Custom Script";
  219. public string DefaultScript()
  220. {
  221. return @"using PRS.Shared.Events;
  222. public class Module
  223. {
  224. public object? Result { get; set; }
  225. public bool Execute(ScheduledEventDataModel model)
  226. {
  227. // Do anything you want, and then save return-value to 'Result', or leave it as 'null' if no return value is needed.
  228. return true;
  229. }
  230. }";
  231. }
  232. public object? Execute(IEventDataModel dataModel)
  233. {
  234. if (ScriptDocument is null) return null;
  235. var model = dataModel.RootModel<ScheduledEventDataModel>();
  236. if(ScriptDocument.Execute(methodname: "Execute", parameters: [model]))
  237. {
  238. return ScriptDocument.GetValue("Result");
  239. }
  240. else
  241. {
  242. return null;
  243. }
  244. }
  245. }
  246. #endregion