using Microsoft.CSharp.RuntimeBinder;\r
using Microsoft.Win32;\r
using static System.Math;\r
-using Timer = System.Windows.Forms.Timer;\r
\r
namespace KancolleSniffer\r
{\r
private readonly Label[] _labelCheckFleets;\r
private readonly ShipLabels _shipLabels;\r
private readonly ListForm _listForm;\r
- private readonly NoticeQueue _noticeQueue;\r
+ private readonly NotificationManager _notificationManager;\r
private bool _started;\r
private string _debugLogFile;\r
private IEnumerator<string> _playLog;\r
panelRepairList.CreateLabels(panelRepairList_Click);\r
labelPresetAkashiTimer.BackColor = ShipLabels.ColumnColors[1];\r
_listForm = new ListForm(_sniffer, _config) {Owner = this};\r
- _noticeQueue = new NoticeQueue(Ring);\r
+ _notificationManager = new NotificationManager(Ring);\r
_config.Load();\r
PerformZoom();\r
_shipLabels.AdjustAkashiTimers();\r
if (item.RingShips)\r
{\r
var message = $"残り{_sniffer.Item.MaxShips - _sniffer.Item.NowShips:D}隻";\r
- _noticeQueue.Enqueue("艦娘が多すぎます", message, "艦娘数超過");\r
+ _notificationManager.Enqueue("艦娘数超過", message);\r
item.RingShips = false;\r
}\r
}\r
if (item.RingEquips)\r
{\r
var message = $"残り{_sniffer.Item.MaxEquips - _sniffer.Item.NowEquips:D}個";\r
- _noticeQueue.Enqueue("装備が多すぎます", message, "装備数超過");\r
+ _notificationManager.Enqueue("装備数超過", message);\r
item.RingEquips = false;\r
}\r
}\r
private void NotifyDamagedShip()\r
{\r
if (_sniffer.BadlyDamagedShips.Any())\r
- _noticeQueue.Enqueue("大破した艦娘がいます", string.Join(" ", _sniffer.BadlyDamagedShips), "大破警告");\r
+ _notificationManager.Enqueue("大破警告", string.Join(" ", _sniffer.BadlyDamagedShips));\r
}\r
\r
private void NotifyAkashiTimer()\r
return;\r
if (msgs[0].Proceeded == "20分経過しました。")\r
{\r
- _noticeQueue.Enqueue("泊地修理", msgs[0].Proceeded, "泊地修理20分経過");\r
+ _notificationManager.Enqueue("泊地修理20分経過", msgs[0].Proceeded);\r
msgs[0].Proceeded = "";\r
// 修理完了がいるかもしれないので続ける\r
}\r
- var fn = new[] {"第一艦隊", "第二艦隊", "第三艦隊", "第四艦隊"};\r
- for (var i = 0; i < fn.Length; i++)\r
+ for (var i = 0; i < ShipInfo.FleetCount; i++)\r
{\r
if (msgs[i].Proceeded != "")\r
- _noticeQueue.Enqueue("泊地修理 " + fn[i], "修理進行:" + msgs[i].Proceeded, "泊地修理進行");\r
+ _notificationManager.Enqueue("泊地修理進行", i, msgs[i].Proceeded);\r
if (msgs[i].Completed != "")\r
- _noticeQueue.Enqueue("泊地修理 " + fn[i], "修理完了:" + msgs[i].Completed, "泊地修理完了");\r
+ _notificationManager.Enqueue("泊地修理完了", i, msgs[i].Completed);\r
}\r
}\r
\r
entry.label.Text = entry.Timer.ToString(_missionFinishTimeMode);\r
if (!entry.Timer.NeedRing)\r
continue;\r
- _noticeQueue.Enqueue("遠征が終わりました", entry.Name, "遠征終了");\r
+ _notificationManager.Enqueue("遠征終了", entry.Name);\r
entry.Timer.NeedRing = false;\r
}\r
for (var i = 0; i < _sniffer.NDock.Length; i++)\r
_shipLabels.SetNDockTimer(i, entry.Timer, _ndockFinishTimeMode);\r
if (!entry.Timer.NeedRing)\r
continue;\r
- _noticeQueue.Enqueue("入渠が終わりました", entry.Name, "入渠終了");\r
+ _notificationManager.Enqueue("入渠終了", entry.Name);\r
entry.Timer.NeedRing = false;\r
}\r
var kdock = new[] {labelConstruct1, labelConstruct2, labelConstruct3, labelConstruct4};\r
kdock[i].Text = timer.EndTime == DateTime.MinValue ? "" : timer.Rest.ToString(@"hh\:mm\:ss");\r
if (!timer.NeedRing)\r
continue;\r
- _noticeQueue.Enqueue("建造が終わりました", $"第{i + 1:D}ドック", "建造完了");\r
+ _notificationManager.Enqueue("建造完了", $"第{i + 1:D}ドック");\r
timer.NeedRing = false;\r
}\r
UpdateCondTimers();\r
var notice = _sniffer.GetConditionNotice();\r
if (notice == null)\r
return;\r
- var fn = new[] {"第一艦隊", "第二艦隊", "第三艦隊", "第四艦隊"};\r
- for (var i = 0; i < fn.Length; i++)\r
+ for (var i = 0; i < ShipInfo.FleetCount; i++)\r
{\r
if (!_config.NotifyConditions.Contains(notice[i]))\r
return;\r
- _noticeQueue.Enqueue("疲労が回復しました", fn[i] + " cond" + notice[i].ToString("D"), "疲労回復");\r
+ _notificationManager.Enqueue("疲労回復" + notice[i], i, "cond" + notice[i]);\r
}\r
}\r
\r
}\r
}\r
\r
- private class NoticeQueue\r
- {\r
- private readonly Action<string, string, string> _ring;\r
- private readonly Queue<Tuple<string, string, string>> _queue = new Queue<Tuple<string, string, string>>();\r
- private readonly Timer _timer = new Timer {Interval = 2000};\r
-\r
- public NoticeQueue(Action<string, string, string> ring)\r
- {\r
- _ring = ring;\r
- _timer.Tick += TimerOnTick;\r
- }\r
-\r
- private void TimerOnTick(object obj, EventArgs e)\r
- {\r
- if (_queue.Count == 0)\r
- {\r
- _timer.Stop();\r
- return;\r
- }\r
- var notice = _queue.Dequeue();\r
- _ring(notice.Item1, notice.Item2, notice.Item3);\r
- }\r
-\r
- public void Enqueue(string title, string message, string name)\r
- {\r
- if (_timer.Enabled)\r
- {\r
- _queue.Enqueue(new Tuple<string, string, string>(title, message, name));\r
- }\r
- else\r
- {\r
- _ring(title, message, name);\r
- _timer.Start();\r
- }\r
- }\r
- }\r
-\r
private void Ring(string balloonTitle, string balloonMessage, string name)\r
{\r
if (_config.FlashWindow && (_config.Notifications[name] & NotificationType.FlashWindow) != 0)\r
--- /dev/null
+// Copyright (C) 2017 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
+//\r
+// Licensed under the Apache License, Version 2.0 (the "License");\r
+// you may not use this file except in compliance with the License.\r
+// You may obtain a copy of the License at\r
+//\r
+// http://www.apache.org/licenses/LICENSE-2.0\r
+//\r
+// Unless required by applicable law or agreed to in writing, software\r
+// distributed under the License is distributed on an "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+// See the License for the specific language governing permissions and\r
+// limitations under the License.\r
+\r
+using System;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Windows.Forms;\r
+\r
+namespace KancolleSniffer\r
+{\r
+ public class NotificationManager\r
+ {\r
+ private readonly NotificationQueue _notificationQueue;\r
+ private readonly NotificationConfig _notificationConfig = new NotificationConfig();\r
+\r
+ public class Notification\r
+ {\r
+ public string Title;\r
+ public string Body;\r
+ public string Name;\r
+ }\r
+\r
+ public NotificationManager(Action<string, string, string> ring)\r
+ {\r
+ _notificationQueue = new NotificationQueue(ring);\r
+ }\r
+\r
+ public void Enqueue(string key, int fleet, string subject)\r
+ {\r
+ _notificationConfig.LoadConfig();\r
+ var notification = _notificationConfig[key];\r
+ _notificationQueue.Enqueue(new Notification\r
+ {\r
+ Title = ProcessFormatString(notification.Title, fleet, subject),\r
+ Body = ProcessFormatString(notification.Body, fleet, subject),\r
+ Name = notification.Name\r
+ });\r
+ }\r
+\r
+ public void Enqueue(string key, string subject)\r
+ {\r
+ Enqueue(key, 0, subject);\r
+ }\r
+\r
+ private string ProcessFormatString(string format, int fleet, string subject)\r
+ {\r
+ var fn = new[] {"第一艦隊", "第二艦隊", "第三艦隊", "第四艦隊"};\r
+ var result = "";\r
+ var percent = false;\r
+ foreach (var ch in format)\r
+ {\r
+ if (ch == '%')\r
+ {\r
+ if (percent)\r
+ {\r
+ percent = false;\r
+ result += '%';\r
+ }\r
+ else\r
+ {\r
+ percent = true;\r
+ }\r
+ }\r
+ else if (percent)\r
+ {\r
+ percent = false;\r
+ switch (ch)\r
+ {\r
+ case 'f':\r
+ result += fn[fleet];\r
+ break;\r
+ case 's':\r
+ result += subject;\r
+ break;\r
+ default:\r
+ result += '%'.ToString() + ch;\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ result += ch;\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+ private class NotificationConfig\r
+ {\r
+ private readonly Dictionary<string, Notification> _config = new Dictionary<string, Notification>();\r
+\r
+ private readonly Dictionary<string, Notification> _default = new Dictionary<string, Notification>\r
+ {\r
+ {\r
+ "遠征終了", new Notification\r
+ {\r
+ Title = "遠征が終わりました",\r
+ Body = "%s",\r
+ Name = "遠征終了"\r
+ }\r
+ },\r
+ {\r
+ "入渠終了", new Notification\r
+ {\r
+ Title = "入渠が終わりました",\r
+ Body = "%s",\r
+ Name = "入渠終了"\r
+ }\r
+ },\r
+ {\r
+ "建造完了", new Notification\r
+ {\r
+ Title = "建造が終わりました",\r
+ Body = "%s",\r
+ Name = "建造完了"\r
+ }\r
+ },\r
+ {\r
+ "艦娘数超過", new Notification\r
+ {\r
+ Title = "艦娘が多すぎます",\r
+ Body = "%s",\r
+ Name = "艦娘数超過"\r
+ }\r
+ },\r
+ {\r
+ "装備数超過", new Notification\r
+ {\r
+ Title = "装備が多すぎます",\r
+ Body = "%s",\r
+ Name = "装備数超過"\r
+ }\r
+ },\r
+ {\r
+ "大破警告", new Notification\r
+ {\r
+ Title = "大破した艦娘がいます",\r
+ Body = "%s",\r
+ Name = "大破警告"\r
+ }\r
+ },\r
+ {\r
+ "泊地修理20分経過", new Notification\r
+ {\r
+ Title = "泊地修理 %f",\r
+ Body = "20分経過しました。",\r
+ Name = "泊地修理20分経過"\r
+ }\r
+ },\r
+ {\r
+ "泊地修理進行", new Notification\r
+ {\r
+ Title = "泊地修理 %f",\r
+ Body = "修理進行:%s",\r
+ Name = "泊地修理進行"\r
+ }\r
+ },\r
+ {\r
+ "泊地修理完了", new Notification\r
+ {\r
+ Title = "泊地修理 %f",\r
+ Body = "修理完了:%s",\r
+ Name = "泊地修理完了"\r
+ }\r
+ },\r
+ {\r
+ "疲労回復40", new Notification\r
+ {\r
+ Title = "疲労が回復しました",\r
+ Body = "%f 残り9分",\r
+ Name = "疲労回復"\r
+ }\r
+ },\r
+ {\r
+ "疲労回復49", new Notification\r
+ {\r
+ Title = "疲労が回復しました",\r
+ Body = "%f",\r
+ Name = "疲労回復"\r
+ }\r
+ }\r
+ };\r
+\r
+ public Notification this[string key] => _config.TryGetValue(key, out Notification value) ? value : _default[key];\r
+\r
+ public void LoadConfig()\r
+ {\r
+ const string fileName = "notification.json";\r
+ _config.Clear();\r
+ try\r
+ {\r
+ dynamic config = JsonParser.Parse(File.ReadAllText(fileName));\r
+ foreach (var entry in config)\r
+ {\r
+ if (!_default.ContainsKey(entry.key))\r
+ continue;\r
+ _config[entry.key] = new Notification\r
+ {\r
+ Title = entry.title,\r
+ Body = entry.body,\r
+ Name = _default[entry.key].Name\r
+ };\r
+ }\r
+ }\r
+ catch (FileNotFoundException)\r
+ {\r
+ }\r
+ catch (Exception ex)\r
+ {\r
+ throw new Exception($"{fileName}に誤りがあります。: ${ex.Message}", ex);\r
+ }\r
+ }\r
+ }\r
+\r
+ private class NotificationQueue\r
+ {\r
+ private readonly Action<string, string, string> _ring;\r
+ private readonly Queue<Notification> _queue = new Queue<Notification>();\r
+ private readonly Timer _timer = new Timer {Interval = 2000};\r
+\r
+ public NotificationQueue(Action<string, string, string> ring)\r
+ {\r
+ _ring = ring;\r
+ _timer.Tick += TimerOnTick;\r
+ }\r
+\r
+ private void TimerOnTick(object obj, EventArgs e)\r
+ {\r
+ if (_queue.Count == 0)\r
+ {\r
+ _timer.Stop();\r
+ return;\r
+ }\r
+ var notification = _queue.Dequeue();\r
+ _ring(notification.Title, notification.Body, notification.Name);\r
+ }\r
+\r
+ public void Enqueue(Notification notification)\r
+ {\r
+ if (_timer.Enabled)\r
+ {\r
+ _queue.Enqueue(notification);\r
+ }\r
+ else\r
+ {\r
+ _ring(notification.Title, notification.Body, notification.Name);\r
+ _timer.Start();\r
+ }\r
+ }\r
+ }\r
+ }\r
+}
\ No newline at end of file