OSDN Git Service

通知メッセージをカスタマイズできるようにする
authorKazuhiro Fujieda <fujieda@users.osdn.me>
Sun, 28 May 2017 19:01:36 +0000 (04:01 +0900)
committerKazuhiro Fujieda <fujieda@users.osdn.me>
Fri, 2 Jun 2017 12:02:16 +0000 (21:02 +0900)
KancolleSniffer/KancolleSniffer.csproj
KancolleSniffer/MainForm.cs
KancolleSniffer/NotificationManager.cs [new file with mode: 0644]

index 00247f4..ee6c1dd 100644 (file)
@@ -97,6 +97,7 @@
     <Compile Include="NotificationConfigDialog.Designer.cs">\r
       <DependentUpon>NotificationConfigDialog.cs</DependentUpon>\r
     </Compile>\r
+    <Compile Include="NotificationManager.cs" />\r
     <Compile Include="PresetDeck.cs" />\r
     <Compile Include="PushBullet.cs" />\r
     <Compile Include="RepairListForMain.cs">\r
index 043ffaf..ae4e3ca 100644 (file)
@@ -28,7 +28,6 @@ using System.Windows.Forms;
 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
@@ -42,7 +41,7 @@ namespace KancolleSniffer
         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
@@ -74,7 +73,7 @@ namespace KancolleSniffer
             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
@@ -434,7 +433,7 @@ namespace KancolleSniffer
             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
@@ -447,7 +446,7 @@ namespace KancolleSniffer
             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
@@ -512,7 +511,7 @@ namespace KancolleSniffer
         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
@@ -525,17 +524,16 @@ namespace KancolleSniffer
                 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
@@ -670,7 +668,7 @@ namespace KancolleSniffer
                 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
@@ -680,7 +678,7 @@ namespace KancolleSniffer
                 _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
@@ -693,7 +691,7 @@ namespace KancolleSniffer
                 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
@@ -739,12 +737,11 @@ namespace KancolleSniffer
             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
@@ -809,43 +806,6 @@ namespace KancolleSniffer
             }\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
diff --git a/KancolleSniffer/NotificationManager.cs b/KancolleSniffer/NotificationManager.cs
new file mode 100644 (file)
index 0000000..ddbcb85
--- /dev/null
@@ -0,0 +1,263 @@
+// 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