2020using System . IO ;
2121using System . Linq ;
2222using System . Net ;
23+ using System . Security . Policy ;
2324using System . Text ;
2425using Newtonsoft . Json ;
2526using ORTS . Common ;
2627using ORTS . Settings ;
2728using ORTS . Updater ;
2829using SharpDX ;
30+ using static System . Windows . Forms . VisualStyles . VisualStyleElement ;
2931using static ORTS . Common . SystemInfo ;
3032using static ORTS . NotificationPage ;
3133
34+ //TODO Add caching of criteria
35+ //TODO Add "includeIf" for individual notifications
36+
3237namespace ORTS
3338{
3439 class NotificationManager
@@ -46,9 +51,9 @@ class NotificationManager
4651 private Exception Error ;
4752 private Dictionary < string , string > ParameterDictionary ;
4853
49- private MainForm MainForm ; // Needed so we can add controls to the NotificationPage
50- private UpdateManager UpdateManager ;
51- private UserSettings Settings ;
54+ private readonly MainForm MainForm ; // Needed so we can add controls to the NotificationPage
55+ private readonly UpdateManager UpdateManager ;
56+ private readonly UserSettings Settings ;
5257
5358 public NotificationManager ( MainForm mainForm , UpdateManager updateManager , UserSettings settings )
5459 {
@@ -64,7 +69,6 @@ public void CheckNotifications()
6469 {
6570 Error = null ;
6671 Notifications = GetNotifications ( ) ;
67- DropUnusedUpdateNotifications ( ) ;
6872 ParameterDictionary = new Dictionary < string , string > ( StringComparer . OrdinalIgnoreCase ) ;
6973
7074 // To support testing, add any overriding values to the ValueDictionary
@@ -84,7 +88,7 @@ public void CheckNotifications()
8488 }
8589
8690 static bool Log = false ;
87- static string LogFile = "notifications_trial_log.txt" ;
91+ const string LogFile = "notifications_trial_log.txt" ;
8892
8993 public Notifications GetNotifications ( )
9094 {
@@ -128,7 +132,7 @@ private string GetRemoteJson()
128132 // Helpful to supply server with data for its log file.
129133 client . Headers [ HttpRequestHeader . UserAgent ] = $ "{ System . Windows . Forms . Application . ProductName } /{ VersionInfo . VersionOrBuild } ";
130134
131- return client . DownloadString ( new Uri ( "https://wepp.co.uk/openrails/notifications /menu.json" ) ) ;
135+ return client . DownloadString ( new Uri ( "https://wepp.co.uk/openrails/notifications2 /menu.json" ) ) ;
132136 }
133137
134138 public void PopulatePageList ( )
@@ -144,7 +148,7 @@ public void PopulatePageList()
144148 /// Ultimately there will be a list of notifications downloaded from https://static.openrails.org/api/notifications/menu.json .
145149 /// Until then, there is a single notification announcing either that a new update is available or the installation is up to date.
146150 /// </summary>
147- void SetUpdateNotificationPage ( )
151+ private void SetUpdateNotificationPage ( )
148152 {
149153 MainForm . UpdateNotificationPageAlert ( ) ;
150154 PageList . Clear ( ) ;
@@ -181,93 +185,60 @@ void SetUpdateNotificationPage()
181185 var skipPage = false ;
182186 new NTitleControl ( page , Index + 1 , list . Count , n . Date , n . Title ) . Add ( ) ;
183187
184- // Check constraints for the MetList.
185- var failingCheck = ( n . Met . ItemList ? . Count > 0 && n . Met . CheckIdList ? . Count > 0 )
186- ? CheckConstraints ( n )
187- : null ;
188+ // Check constraints for each item
189+ foreach ( var item in n . ItemList )
190+ {
191+ if ( AreChecksMet ( item ) ) AddItemToPage ( page , item ) ;
192+ }
193+ if ( skipPage == false ) PageList . Add ( page ) ;
194+ }
188195
189- // If any check fails then its UnmetList is added to the page, otherwise the MetList is added.
190- n . PrefixItemList ? . ForEach ( item => AddItemToPage ( page , item ) ) ;
191- if ( failingCheck == null )
196+ #region Process Criteria
197+ private bool AreChecksMet ( Item item )
198+ {
199+ if ( item . IncludeIf != null || item . IncludeIfNot != null )
192200 {
193- n . Met . ItemList ? . ForEach ( item => AddItemToPage ( page , item ) ) ;
201+ AppendToLog ( $ "Label: { item . Label } " ) ;
194202 }
195- else
203+ if ( item . IncludeIf != null )
196204 {
197- if ( failingCheck . UnmetItemList == null ) // Omit this section to skip the notification entirely.
205+ foreach ( var checkName in item . IncludeIf )
198206 {
199- // Don't skip if there is only one notification .
200- if ( list . Count > 1 ) skipPage = true ;
207+ // Include if A=true AND B=true AND .. .
208+ if ( IsCheckMet ( checkName ) == false ) return false ;
201209 }
202- else
210+ }
211+ if ( item . IncludeIfNot != null )
212+ {
213+ foreach ( var checkName in item . IncludeIfNot )
203214 {
204- failingCheck . UnmetItemList ? . ForEach ( item => AddItemToPage ( page , item ) ) ;
215+ // Include if C=false AND D=false AND ...
216+ if ( IsCheckMet ( checkName ) == true ) return false ;
205217 }
206218 }
207- n . SuffixItemList ? . ForEach ( item => AddItemToPage ( page , item ) ) ;
208- if ( skipPage == false ) PageList . Add ( page ) ;
219+
220+ return true ;
209221 }
210222
211- /// <summary>
212- /// CheckConstraints() checks the constraints in sequence, but all parts are optional.
213- /// If all the constraints in any Includes are met, then the whole check is met.
214- /// If all the constraints in any Excludes are met, then the whole check is not met.
215- /// Returns null if the whole check is met else returns the check that failed.
216- /// </summary>
217- /// <param name="n"></param>
218- private Check CheckConstraints ( Notification n )
223+ private bool IsCheckMet ( string checkname )
219224 {
220- Check failingCheck = null ;
221- foreach ( var nc in n . Met . CheckIdList ) // CheckIdList is optional
225+ foreach ( var check in Notifications . CheckList )
222226 {
223- LogChecks ( nc ) ;
224-
225- // Find the matching check
226- var check = Notifications . CheckList . Where ( c => c . Id == nc . Id ) . FirstOrDefault ( ) ;
227- if ( check != null && check . AnyOfList . Count ( ) > 0 )
227+ if ( check . Id == checkname )
228228 {
229- foreach ( var anyOf in check . AnyOfList )
230- {
231- if ( anyOf is Excludes )
232- {
233- if ( CheckAllMatch ( anyOf . AllOfList ) == true ) return check ; // immediate fail so quit
234- }
235- if ( anyOf is Includes )
236- {
237- if ( CheckAllMatch ( anyOf . AllOfList ) == false ) failingCheck = check ; // fail but continue testing other Includes
238- }
239- }
229+ if ( CheckAnyMatch ( check . AnyOfList ) ) return true ;
240230 }
241231 }
242- return failingCheck ;
232+ return false ;
243233 }
244234
245- private void AddItemToPage ( NotificationPage page , Item item )
235+ private bool CheckAnyMatch ( List < AnyOf > anyOfList )
246236 {
247- if ( item is Record record )
248- {
249- new NRecordControl ( page , item . Label , item . Indent , record . Value ) . Add ( ) ;
250- }
251- else if ( item is Link link )
252- {
253- new NLinkControl ( page , item . Label , item . Indent , link . Value , MainForm , link . Url ) . Add ( ) ;
254- }
255- else if ( item is Update update )
256- {
257- new NUpdateControl ( page , item . Label , item . Indent , update . Value , MainForm ) . Add ( ) ;
258- }
259- else if ( item is Heading heading )
260- {
261- new NHeadingControl ( page , item . Label , heading . Color ) . Add ( ) ;
262- }
263- else if ( item is Text text )
237+ foreach ( var anyOf in anyOfList )
264238 {
265- new NTextControl ( page , item . Label , text . Color ) . Add ( ) ;
266- }
267- else if ( item is Item item2 )
268- {
269- new NTextControl ( page , item . Label ) . Add ( ) ;
239+ if ( CheckAllMatch ( anyOf . AllOfList ) ) return true ;
270240 }
241+ return false ;
271242 }
272243
273244 private bool CheckAllMatch ( List < Criteria > criteriaList )
@@ -303,29 +274,61 @@ private bool CheckContains(Criteria criteria, bool sense)
303274 LogCheckContains ( criteria . Value , sense , content , result ) ;
304275 return result ;
305276 }
277+ #endregion
306278
307- /// <summary>
308- /// Drop any notifications for the channel not selected
309- /// </summary>
310- /// <param name="updateManager"></param>
311- public void DropUnusedUpdateNotifications ( )
279+ private void AddItemToPage ( NotificationPage page , Item item )
312280 {
313- var updateModeSetting = UpdateManager . ChannelName . ToLower ( ) ;
314- foreach ( var n in Notifications . NotificationList )
281+ if ( item is Record record )
315282 {
316- if ( n . UpdateMode == null ) // Skip notifications which are not updates
317- continue ;
318-
319- var lowerUpdateMode = n . UpdateMode . ToLower ( ) ;
320-
321- // If setting == "none", then keep just one update notification, e.g. the stable one
322- if ( updateModeSetting == "" && lowerUpdateMode == "stable" )
323- continue ;
283+ new NRecordControl ( page , item . Label , item . Indent , record . Value ) . Add ( ) ;
284+ }
285+ else if ( item is Link link )
286+ {
287+ var url = GetUrl ( link ) ;
288+ if ( string . IsNullOrEmpty ( url ) == false )
289+ {
290+ new NLinkControl ( page , item . Label , item . Indent , link . Value , MainForm , url ) . Add ( ) ;
291+ }
292+ }
293+ else if ( item is Update update )
294+ {
295+ new NUpdateControl ( page , item . Label , item . Indent , update . Value , MainForm ) . Add ( ) ;
296+ }
297+ else if ( item is Heading heading )
298+ {
299+ new NHeadingControl ( page , item . Label , heading . Color ) . Add ( ) ;
300+ }
301+ else if ( item is Text text )
302+ {
303+ new NTextControl ( page , item . Label , text . Color ) . Add ( ) ;
304+ }
305+ else
306+ {
307+ new NTextControl ( page , item . Label ) . Add ( ) ;
308+ }
309+ }
324310
325- // Mark unused updates for deletion outside loop
326- n . ToDelete = lowerUpdateMode != updateModeSetting ;
311+ private string GetUrl ( Link link )
312+ {
313+ var url = link . Url ;
314+ if ( string . IsNullOrEmpty ( url ) )
315+ {
316+ switch ( UpdateManager . ChannelName . ToLower ( ) )
317+ {
318+ case "stable" :
319+ case "" : // Channel None
320+ url = link . StableUrl ;
321+ break ;
322+ case "testing" :
323+ url = link . TestingUrl ;
324+ break ;
325+ case "unstable" :
326+ url = link . UnstableUrl ;
327+ break ;
328+ }
327329 }
328- Notifications . NotificationList . RemoveAll ( n => n . ToDelete ) ;
330+
331+ return url ;
329332 }
330333
331334 public void ReplaceParameters ( )
@@ -334,9 +337,10 @@ public void ReplaceParameters()
334337 {
335338 n . Title = ReplaceParameter ( n . Title ) ;
336339 n . Date = ReplaceParameter ( n . Date ) ;
337- n . PrefixItemList ? . ForEach ( item => ReplaceItemParameter ( item ) ) ;
338- n . Met . ItemList ? . ForEach ( item => ReplaceItemParameter ( item ) ) ;
339- n . SuffixItemList ? . ForEach ( item => ReplaceItemParameter ( item ) ) ;
340+ //n.PrefixItemList?.ForEach(item => ReplaceItemParameter(item));
341+ //n.Met.ItemList?.ForEach(item => ReplaceItemParameter(item));
342+ //n.SuffixItemList?.ForEach(item => ReplaceItemParameter(item));
343+ n . ItemList ? . ForEach ( item => ReplaceItemParameter ( item ) ) ;
340344 }
341345 foreach ( var list in Notifications . CheckList )
342346 {
@@ -382,7 +386,7 @@ private string ReplaceParameter(string field)
382386 var parameterArray = field . Split ( '{' , '}' ) ; // 5 elements: prefix, "", target, "", suffix
383387 var target = parameterArray [ 2 ] ;
384388 var lowerCaseTarget = parameterArray [ 2 ] . ToLower ( ) ;
385- var replacement = parameterArray [ 2 ] ; // Default is original text
389+ string replacement ;
386390
387391 // If found in dictionary, then use that else extract it from program
388392 if ( ParameterDictionary . ContainsKey ( lowerCaseTarget ) )
@@ -521,6 +525,7 @@ public OverrideParameterList GetOverrideParameters()
521525 return null ;
522526 }
523527
528+ #region Logging
524529 public void LogOverrideParameters ( )
525530 {
526531 if ( Log == false ) return ;
@@ -557,14 +562,14 @@ public void LogNotification(Notification n)
557562 {
558563 AppendToLog ( $ "Notification: { n . Title } ") ;
559564 }
560- public void LogChecks ( CheckId ci )
565+ public void LogChecks ( string checkName )
561566 {
562- AppendToLog ( $ "CheckId: { ci . Id } ") ;
567+ AppendToLog ( $ "CheckId: { checkName } ") ;
563568 }
564569 public void LogCheckContains ( string value , bool sense , string content , bool result )
565570 {
566571 var negation = sense ? "" : "NOT " ;
567- AppendToLog ( $ "Check: '{ value } ' { negation } contained in '{ content } ' = { result } ") ;
572+ AppendToLog ( $ "Check: { result } = '{ value } ' { negation } contained in '{ content } '") ;
568573 }
569574
570575 public void AppendToLog ( string record )
@@ -576,5 +581,6 @@ public void AppendToLog(string record)
576581 sw . WriteLine ( record ) ;
577582 }
578583 }
584+ #endregion
579585 }
580586}
0 commit comments