1 // Copyright (C) 2017 Kazuhiro Fujieda <fujieda@users.osdn.me>
\r
3 // Licensed under the Apache License, Version 2.0 (the "License");
\r
4 // you may not use this file except in compliance with the License.
\r
5 // You may obtain a copy of the License at
\r
7 // http://www.apache.org/licenses/LICENSE-2.0
\r
9 // Unless required by applicable law or agreed to in writing, software
\r
10 // distributed under the License is distributed on an "AS IS" BASIS,
\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
12 // See the License for the specific language governing permissions and
\r
13 // limitations under the License.
\r
16 using System.Collections.Generic;
\r
19 using System.Windows.Forms;
\r
21 namespace KancolleSniffer
\r
23 public class NotificationManager
\r
25 private readonly NotificationQueue _notificationQueue;
\r
27 private class Notification
\r
29 public string Key { get; set; }
\r
30 public int Fleet { get; set; }
\r
31 public string Subject { get; set; }
\r
32 public int Repeat { get; set; }
\r
33 public DateTime Schedule { get; set; }
\r
36 public NotificationManager(Action<string, string, string> ring, ITimer timer = null)
\r
38 _notificationQueue = new NotificationQueue(ring, timer);
\r
41 public void Enqueue(string key, int fleet, string subject, int repeat = 0)
\r
43 _notificationQueue.Enqueue(new Notification
\r
52 public void Enqueue(string key, string subject, int repeat = 0)
\r
54 Enqueue(key, 0, subject, repeat);
\r
57 public void StopRepeat(string key)
\r
59 _notificationQueue.StopRepeat(key);
\r
62 private class NotificationConfig
\r
64 public class Message
\r
66 public string Title { get; set; }
\r
67 public string Body { get; set; }
\r
68 public string Name { get; set; }
\r
71 private readonly Dictionary<string, Message> _config = new Dictionary<string, Message>();
\r
73 private readonly Dictionary<string, Message> _default = new Dictionary<string, Message>
\r
78 Title = "遠征が終わりました",
\r
85 Title = "入渠が終わりました",
\r
92 Title = "建造が終わりました",
\r
97 "艦娘数超過", new Message
\r
104 "装備数超過", new Message
\r
106 Title = "装備が多すぎます",
\r
111 "大破警告", new Message
\r
113 Title = "大破した艦娘がいます",
\r
118 "泊地修理20分経過", new Message
\r
121 Body = "20分経過しました。"
\r
125 "泊地修理進行", new Message
\r
132 "泊地修理完了", new Message
\r
139 "疲労回復40", new Message
\r
141 Title = "疲労が回復しました",
\r
146 "疲労回復49", new Message
\r
148 Title = "疲労が回復しました",
\r
154 public static string KeyToName(string key) => key.StartsWith("疲労回復") ? key.Substring(0, 4) : key;
\r
156 private void LoadConfig()
\r
158 const string fileName = "notification.json";
\r
162 dynamic config = JsonParser.Parse(File.ReadAllText(fileName));
\r
163 foreach (var entry in config)
\r
165 if (!_default.ContainsKey(entry.key))
\r
167 _config[entry.key] = new Message
\r
169 Title = entry.title,
\r
174 catch (FileNotFoundException)
\r
177 catch (Exception ex)
\r
179 throw new Exception($"{fileName}に誤りがあります。: ${ex.Message}", ex);
\r
183 public Message GenerateMessage(Notification notification)
\r
186 var format = _config.TryGetValue(notification.Key, out Message value) ? value : _default[notification.Key];
\r
189 Title = ProcessFormatString(format.Title, notification.Fleet, notification.Subject),
\r
190 Body = ProcessFormatString(format.Body, notification.Fleet, notification.Subject),
\r
191 Name = KeyToName(notification.Key)
\r
195 private string ProcessFormatString(string format, int fleet, string subject)
\r
197 var fn = new[] {"第一艦隊", "第二艦隊", "第三艦隊", "第四艦隊"};
\r
199 var percent = false;
\r
200 foreach (var ch in format)
\r
220 result += fn[fleet];
\r
226 result += '%'.ToString() + ch;
\r
239 public interface ITimer
\r
241 int Interval { get; set; }
\r
242 bool Enabled { get; set; }
\r
243 event EventHandler Tick;
\r
246 DateTime Now { get; }
\r
249 public class TimerWrapper : ITimer
\r
251 private readonly Timer _timer = new Timer();
\r
253 public int Interval
\r
255 get => _timer.Interval;
\r
256 set => _timer.Interval = value;
\r
259 public bool Enabled
\r
261 get => _timer.Enabled;
\r
262 set => _timer.Enabled = value;
\r
265 public event EventHandler Tick
\r
267 add => _timer.Tick += value;
\r
268 remove => _timer.Tick -= value;
\r
271 public void Start() => _timer.Start();
\r
273 public void Stop() => _timer.Stop();
\r
275 public DateTime Now => DateTime.Now;
\r
278 private class NotificationQueue
\r
280 private readonly Action<string, string, string> _ring;
\r
281 private readonly List<Notification> _queue = new List<Notification>();
\r
282 private readonly ITimer _timer;
\r
283 private readonly NotificationConfig _notificationConfig = new NotificationConfig();
\r
284 private DateTime _lastRing;
\r
286 public NotificationQueue(Action<string, string, string> ring, ITimer timer = null)
\r
289 _timer = timer ?? new TimerWrapper();
\r
290 _timer.Interval = 1000;
\r
291 _timer.Tick += TimerOnTick;
\r
294 private void TimerOnTick(object obj, EventArgs e)
\r
296 if (_queue.Count == 0)
\r
304 public void Enqueue(Notification notification)
\r
306 _queue.Add(notification);
\r
308 if (_queue.Count > 0)
\r
312 public void StopRepeat(string key)
\r
314 _queue.RemoveAll(n => n.Key.Substring(0, 4) == key.Substring(0, 4) && n.Schedule != default);
\r
317 private void Ring()
\r
319 var now = _timer.Now;
\r
320 if (now - _lastRing < TimeSpan.FromSeconds(2))
\r
322 var notification = _queue.FirstOrDefault(n => n.Schedule.CompareTo(now) <= 0);
\r
323 if (notification == null)
\r
325 if (notification.Repeat == 0)
\r
327 _queue.Remove(notification);
\r
331 notification.Schedule = _timer.Now + TimeSpan.FromSeconds(notification.Repeat);
\r
334 _notificationConfig.GenerateMessage(notification);
\r
335 _ring(message.Title, message.Body, message.Name);
\r