OSDN Git Service

ShipListForm→ListFormなどの名前の変更を行う
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / MainForm.cs
index 23f9646..214d64e 100644 (file)
@@ -1,19 +1,16 @@
 // Copyright (C) 2013, 2014, 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
 // \r
-// This program is part of KancolleSniffer.\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
-// KancolleSniffer is free software: you can redistribute it and/or modify\r
-// it under the terms of the GNU General Public License as published by\r
-// the Free Software Foundation, either version 3 of the License, or\r
-// (at your option) any later version.\r
+//    http://www.apache.org/licenses/LICENSE-2.0\r
 //\r
-// This program is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-// GNU General Public License for more details.\r
-//\r
-// You should have received a copy of the GNU General Public License\r
-// along with this program; if not, see <http://www.gnu.org/licenses/>.\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
@@ -22,7 +19,6 @@ using System.Drawing;
 using System.Globalization;\r
 using System.IO;\r
 using System.Linq;\r
-using System.Net;\r
 using System.Net.Sockets;\r
 using System.Runtime.InteropServices;\r
 using System.Text;\r
@@ -30,11 +26,8 @@ using System.Text.RegularExpressions;
 using System.Threading;\r
 using System.Threading.Tasks;\r
 using System.Windows.Forms;\r
-using System.Xml;\r
-using Codeplex.Data;\r
 using Microsoft.CSharp.RuntimeBinder;\r
 using Microsoft.Win32;\r
-using Nekoxy;\r
 using static System.Math;\r
 using Timer = System.Windows.Forms.Timer;\r
 \r
@@ -49,7 +42,7 @@ namespace KancolleSniffer
         private bool _combinedFleet;\r
         private readonly Label[] _labelCheckFleets;\r
         private readonly ShipLabels _shipLabels;\r
-        private readonly ShipListForm _shipListForm;\r
+        private readonly ListForm _listForm;\r
         private readonly NoticeQueue _noticeQueue;\r
         private bool _started;\r
         private string _debugLogFile;\r
@@ -60,6 +53,7 @@ namespace KancolleSniffer
         private readonly ErrorDialog _errorDialog = new ErrorDialog();\r
         private bool _missionFinishTimeMode;\r
         private bool _ndockFinishTimeMode;\r
+        private readonly KancolleDb _kancolleDb = new KancolleDb();\r
 \r
         public MainForm()\r
         {\r
@@ -76,51 +70,42 @@ namespace KancolleSniffer
             SetupFleetClick();\r
             _shipLabels = new ShipLabels();\r
             _shipLabels.CreateAkashiTimers(panelShipInfo);\r
-            _shipLabels.CreateLabels(panelShipInfo, ShowShipOnShipList);\r
+            _shipLabels.CreateShipLabels(panelShipInfo, ShowShipOnShipList);\r
             _shipLabels.CreateCombinedShipLabels(panelCombinedFleet, ShowShipOnShipList);\r
-            _shipLabels.CreateDamagedShipList(panelDamagedShipList, panelDamagedShipList_Click);\r
-            _shipLabels.CreateNDockLabels(panelDock, (obj, args) =>\r
-            {\r
-                _ndockFinishTimeMode = !_ndockFinishTimeMode;\r
-                UpdateTimers();\r
-            });\r
-            _shipListForm = new ShipListForm(_sniffer, _config) {Owner = this};\r
+            _shipLabels.CreateRepairList(panelRepairList, panelRepairList_Click);\r
+            _shipLabels.CreateNDockLabels(panelDock, labelNDock_Click);\r
+            labelPresetAkashiTimer.BackColor = ShipLabels.ColumnColors[1];\r
+            _listForm = new ListForm(_sniffer, _config) {Owner = this};\r
             _noticeQueue = new NoticeQueue(Ring);\r
+            _config.Load();\r
+            PerformZoom();\r
+            _sniffer.LoadState();\r
         }\r
 \r
-        private void HttpProxy_AfterSessionComplete(Session session)\r
+        private void HttpProxy_AfterSessionComplete(HttpProxy.Session session)\r
         {\r
-            Invoke(new Action<Session>(ProcessRequest), session);\r
+            Invoke(new Action<HttpProxy.Session>(ProcessRequest), session);\r
         }\r
 \r
-        private void ProcessRequest(Session session)\r
+        private void ProcessRequest(HttpProxy.Session session)\r
         {\r
             var url = session.Request.PathAndQuery;\r
-            var request = session.Request.BodyAsString;\r
-            var response = session.Response.BodyAsString;\r
             if (!url.Contains("kcsapi/"))\r
                 return;\r
+            var request = session.Request.BodyAsString;\r
+            var response = session.Response.BodyAsString;\r
             if (response == null || !response.StartsWith("svdata="))\r
             {\r
                 WriteDebugLog(url, request, response);\r
-                ShowServerError(url, request, response);\r
                 return;\r
             }\r
+            if (_config.KancolleDb.On)\r
+                _kancolleDb.Send(url, request, response);\r
             response = UnescapeString(response.Remove(0, "svdata=".Length));\r
             WriteDebugLog(url, request, response);\r
             try\r
             {\r
-                var update = _sniffer.Sniff(url, request, DynamicJson.Parse(response));\r
-                if (update == Sniffer.Update.Error)\r
-                {\r
-                    ShowServerError(url, request, response);\r
-                    return;\r
-                }\r
-                UpdateInfo(update);\r
-            }\r
-            catch (XmlException e)\r
-            {\r
-                ShowServerError(url, request, response, e);\r
+                UpdateInfo(_sniffer.Sniff(url, request, JsonParser.Parse(response)));\r
             }\r
             catch (RuntimeBinderException e)\r
             {\r
@@ -133,6 +118,11 @@ namespace KancolleSniffer
                 if (_errorDialog.ShowDialog(this, e.Message, e.InnerException.ToString()) == DialogResult.Abort)\r
                     Application.Exit();\r
             }\r
+            catch (Exception e)\r
+            {\r
+                if (_errorDialog.ShowDialog(this, "エラーが発生しました。", e.ToString()) == DialogResult.Abort)\r
+                    Application.Exit();\r
+            }\r
         }\r
 \r
         private void WriteDebugLog(string url, string request, string response)\r
@@ -144,16 +134,6 @@ namespace KancolleSniffer
             }\r
         }\r
 \r
-        private void ShowServerError(string url, string request, string response, Exception e = null)\r
-        {\r
-            if (_errorDialog.Visible)\r
-                return;\r
-            if (_errorDialog.ShowDialog(this, "サーバーからの応答が異常です。",\r
-                $"{(e == null ? "" : e.Message + "\r\n")}url: {url}\r\nrequest: {request}\r\nresponse: {response ?? "(null)"}\r\n") ==\r
-                DialogResult.Abort)\r
-                Application.Exit();\r
-        }\r
-\r
         private string UnescapeString(string s)\r
         {\r
             try\r
@@ -197,16 +177,16 @@ namespace KancolleSniffer
 \r
         private void MainForm_Load(object sender, EventArgs e)\r
         {\r
-            _config.Load();\r
             RestoreLocation();\r
             if (_config.HideOnMinimized && WindowState == FormWindowState.Minimized)\r
                 ShowInTaskbar = false;\r
             ApplyConfig();\r
             ApplyDebugLogSetting();\r
             ApplyLogSetting();\r
-            _sniffer.LoadState();\r
             ApplyProxySetting();\r
             SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;\r
+            if (_config.KancolleDb.On)\r
+                _kancolleDb.Start(_config.KancolleDb.Token);\r
         }\r
 \r
         private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)\r
@@ -216,32 +196,7 @@ namespace KancolleSniffer
             Task.Run(() =>\r
             {\r
                 for (var i = 0; i < 5; Thread.Sleep(10000), i++)\r
-                {\r
-                    WebResponse res = null;\r
                     SystemProxy.Refresh();\r
-                    var system = WebRequest.GetSystemWebProxy();\r
-                    if (!system.GetProxy(new Uri("http://125.6.184.16/")).IsLoopback)\r
-                    {\r
-                        File.AppendAllText("wakeup.log",\r
-                            $"[{DateTime.Now.ToString("g")}] proxy settings doesn't work.\r\n");\r
-                        continue;\r
-                    }\r
-                    try\r
-                    {\r
-                        var req = WebRequest.Create("http://kancollesniffer.osdn.jp/version");\r
-                        res = req.GetResponse();\r
-                        break;\r
-                    }\r
-                    catch\r
-                    {\r
-                        File.AppendAllText("wakeup.log",\r
-                            $"[{DateTime.Now.ToString("g")}] failed to connect internet.\r\n");\r
-                    }\r
-                    finally\r
-                    {\r
-                        res?.Close();\r
-                    }\r
-                }\r
             });\r
         }\r
 \r
@@ -255,6 +210,7 @@ namespace KancolleSniffer
             if (_config.Proxy.Auto)\r
                 _systemProxy.RestoreSettings();\r
             SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;\r
+            _kancolleDb.Stop();\r
         }\r
 \r
         private void ShutdownProxy()\r
@@ -291,6 +247,19 @@ namespace KancolleSniffer
                 ApplyConfig();\r
         }\r
 \r
+        private void PerformZoom()\r
+        {\r
+            if (_config.Zoom == 100)\r
+                return;\r
+            var prev = CurrentAutoScaleDimensions;\r
+            foreach (var control in new Control[] {this, _listForm, labelLogin, labelGuide})\r
+                control.Font = new Font(control.Font.FontFamily, control.Font.Size * _config.Zoom / 100);\r
+            ShipLabel.LatinFont = new Font("Tahoma", 8f * _config.Zoom / 100);\r
+            var cur = CurrentAutoScaleDimensions;\r
+            ShipLabel.ScaleFactor = new SizeF(ShipLabel.ScaleFactor.Width * cur.Width / prev.Width,\r
+                ShipLabel.ScaleFactor.Height * cur.Height / prev.Height);\r
+        }\r
+\r
         private void RestoreLocation()\r
         {\r
             if (_config.Location.X == int.MinValue)\r
@@ -303,11 +272,14 @@ namespace KancolleSniffer
 \r
         private void ApplyConfig()\r
         {\r
-            _shipListForm.TopMost = TopMost = _config.TopMost;\r
+            _listForm.TopMost = TopMost = _config.TopMost;\r
             _sniffer.Item.MarginShips = _config.MarginShips;\r
             _sniffer.Item.MarginEquips = _config.MarginEquips;\r
             _sniffer.Achievement.ResetHours = _config.ResetHours;\r
-            labelAkashiRepair.Visible = labelAkashiRepairTimer.Visible = _config.UsePresetAkashi;\r
+            labelAkashiRepair.Visible = labelAkashiRepairTimer.Visible =\r
+                labelPresetAkashiTimer.Visible = _config.UsePresetAkashi;\r
+            if (_config.KancolleDb.On)\r
+                _kancolleDb.Start(_config.KancolleDb.Token);\r
         }\r
 \r
         public void ApplyDebugLogSetting()\r
@@ -424,7 +396,17 @@ namespace KancolleSniffer
         private void timerMain_Tick(object sender, EventArgs e)\r
         {\r
             if (_started)\r
-                UpdateTimers();\r
+            {\r
+                try\r
+                {\r
+                    UpdateTimers();\r
+                }\r
+                catch (Exception ex)\r
+                {\r
+                    if (_errorDialog.ShowDialog(this, "エラーが発生しました。", ex.ToString()) == DialogResult.Abort)\r
+                        Application.Exit();\r
+                }\r
+            }\r
             if (_playLog == null || _configDialog.Visible)\r
             {\r
                 labelPlayLog.Visible = false;\r
@@ -451,19 +433,19 @@ namespace KancolleSniffer
                 lines.Add(_playLog.Current.Substring(s.Length));\r
             }\r
             labelPlayLog.Visible = !labelPlayLog.Visible;\r
-            var json = DynamicJson.Parse(lines[2]);\r
+            var json = JsonParser.Parse(lines[2]);\r
             UpdateInfo(_sniffer.Sniff(lines[0], lines[1], json));\r
         }\r
 \r
         private void ShowShipOnShipList(object sender, EventArgs ev)\r
         {\r
-            if (!_shipListForm.Visible)\r
+            if (!_listForm.Visible)\r
                 return;\r
             var idx = (int)((Control)sender).Tag;\r
             var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
             if (statuses.Length <= idx)\r
                 return;\r
-            _shipListForm.ShowShip(statuses[idx].Id);\r
+            _listForm.ShowShip(statuses[idx].Id);\r
         }\r
 \r
         private void UpdateItemInfo()\r
@@ -480,8 +462,8 @@ namespace KancolleSniffer
                 "今月 " + _sniffer.Achievement.ValueOfMonth.ToString("F1") + "\n" +\r
                 "EO " + _sniffer.ExMap.Achievement);\r
             UpdateMaterialHistry();\r
-            if (_shipListForm.Visible)\r
-                _shipListForm.UpdateList();\r
+            if (_listForm.Visible)\r
+                _listForm.UpdateList();\r
         }\r
 \r
         private void UpdateNumOfShips()\r
@@ -492,7 +474,7 @@ namespace KancolleSniffer
             if (item.RingShips)\r
             {\r
                 var message = $"残り{_sniffer.Item.MaxShips - _sniffer.Item.NowShips:D}隻";\r
-                _noticeQueue.Enqueue("艦娘が多すぎます", message, _config.MaxShipsSoundFile);\r
+                _noticeQueue.Enqueue("艦娘が多すぎます", message, _config.Sounds["艦娘数超過"]);\r
                 item.RingShips = false;\r
             }\r
         }\r
@@ -505,7 +487,7 @@ namespace KancolleSniffer
             if (item.RingEquips)\r
             {\r
                 var message = $"残り{_sniffer.Item.MaxEquips - _sniffer.Item.NowEquips:D}個";\r
-                _noticeQueue.Enqueue("装備が多すぎます", message, _config.MaxEquipsSoundFile);\r
+                _noticeQueue.Enqueue("装備が多すぎます", message, _config.Sounds["装備数超過"]);\r
                 item.RingEquips = false;\r
             }\r
         }\r
@@ -547,21 +529,21 @@ namespace KancolleSniffer
             UpdatePanelShipInfo();\r
             NotifyDamagedShip();\r
             UpdateChargeInfo();\r
-            UpdateDamagedShipList();\r
-            if (_shipListForm.Visible)\r
-                _shipListForm.UpdateList();\r
+            UpdateRepairList();\r
+            if (_listForm.Visible)\r
+                _listForm.UpdateList();\r
         }\r
 \r
         private void UpdatePanelShipInfo()\r
         {\r
             var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
-            _shipLabels.SetShipInfo(statuses);\r
+            _shipLabels.SetShipLabels(statuses);\r
             if (_sniffer.CombinedFleetType == 0)\r
                 _combinedFleet = false;\r
             labelFleet1.Text = _combinedFleet ? "連合" : "第一";\r
             panelCombinedFleet.Visible = _combinedFleet;\r
             if (_combinedFleet)\r
-                _shipLabels.SetCombinedShipInfo(_sniffer.GetShipStatuses(0), _sniffer.GetShipStatuses(1));\r
+                _shipLabels.SetCombinedShipLabels(_sniffer.GetShipStatuses(0), _sniffer.GetShipStatuses(1));\r
             UpdateAkashiTimer();\r
             UpdateFighterPower();\r
             UpdateLoS();\r
@@ -570,21 +552,22 @@ namespace KancolleSniffer
 \r
         private void NotifyDamagedShip()\r
         {\r
-            if (_sniffer.Battle.HasDamagedShip)\r
-                _noticeQueue.Enqueue("大破した艦娘がいます", string.Join(" ", _sniffer.Battle.DamagedShipNames),\r
-                    _config.DamagedShipSoundFile);\r
+            if (_sniffer.BadlyDamagedShips.Any())\r
+                _noticeQueue.Enqueue("大破した艦娘がいます", string.Join(" ", _sniffer.BadlyDamagedShips),\r
+                    _config.Sounds["大破警告"]);\r
         }\r
 \r
         private void NotifyAkashiTimer()\r
         {\r
             var akashi = _sniffer.AkashiTimer;\r
             var msgs = akashi.GetNotice();\r
-            if (msgs.All(msg => msg.Completed != "" || msg.Proceeded != "") ||\r
-                !(akashi.CheckReparing() || akashi.CheckPresetReparing()))\r
+            if (msgs.Length == 0)\r
+                return;\r
+            if (!akashi.CheckReparing() && !(akashi.CheckPresetReparing() && _config.UsePresetAkashi))\r
                 return;\r
             if (msgs[0].Proceeded == "20分経過しました。")\r
             {\r
-                _noticeQueue.Enqueue("泊地修理", msgs[0].Proceeded, _config.Akashi20MinSoundFile);\r
+                _noticeQueue.Enqueue("泊地修理", msgs[0].Proceeded, _config.Sounds["泊地修理20分経過"]);\r
                 msgs[0].Proceeded = "";\r
                 // 修理完了がいるかもしれないので続ける\r
             }\r
@@ -592,21 +575,26 @@ namespace KancolleSniffer
             for (var i = 0; i < fn.Length; i++)\r
             {\r
                 if (msgs[i].Proceeded != "")\r
-                    _noticeQueue.Enqueue("泊地修理 " + fn[i], "修理進行:" + msgs[i].Proceeded, _config.AkashiProgressSoundFile);\r
+                    _noticeQueue.Enqueue("泊地修理 " + fn[i], "修理進行:" + msgs[i].Proceeded, _config.Sounds["泊地修理進行"]);\r
                 if (msgs[i].Completed != "")\r
-                    _noticeQueue.Enqueue("泊地修理 " + fn[i], "修理完了:" + msgs[i].Completed, _config.AkashiCompleteSoundFile);\r
+                    _noticeQueue.Enqueue("泊地修理 " + fn[i], "修理完了:" + msgs[i].Completed, _config.Sounds["泊地修理完了"]);\r
             }\r
         }\r
 \r
         public void UpdateFighterPower()\r
         {\r
-            labelFighterPower.Text = _sniffer.GetFighterPower(_currentFleet, true).ToString("D");\r
-            toolTipFigherPower.SetToolTip(labelFighterPower, "熟練度抜き " + _sniffer.GetFighterPower(_currentFleet, false));\r
+            var fp = _sniffer.GetFighterPower(_currentFleet);\r
+            labelFighterPower.Text = fp[0].ToString("D");\r
+            var cr = _sniffer.GetContactTriggerRate(_currentFleet) * 100;\r
+            var text = "制空: " + (fp[0] == fp[1] ? $"{fp[0]}" : $"{fp[0]}~{fp[1]}") +\r
+                       $" 触接: {cr:f1}";\r
+            toolTipFighterPower.SetToolTip(labelFighterPower, text);\r
+            toolTipFighterPower.SetToolTip(labelFighterPowerCaption, text);\r
         }\r
 \r
         private void UpdateLoS()\r
         {\r
-            labelLoS.Text = _sniffer.GetFleetLineOfSights(_currentFleet).ToString("F1");\r
+            labelLoS.Text = (Floor(_sniffer.GetFleetLineOfSights(_currentFleet) * 10) / 10.0).ToString("F1");\r
         }\r
 \r
         private void UpdateBattleInfo()\r
@@ -622,10 +610,7 @@ namespace KancolleSniffer
             var battle = _sniffer.Battle;\r
             var color = new[] {DefaultForeColor, DefaultForeColor, Color.Blue, Color.Green, Color.Orange, Color.Red};\r
             labelFormation.Text = battle.Formation;\r
-            var enemyFp = battle.EnemyFighterPower;\r
-            labelEnemyFighterPower.Text = (enemyFp & BattleInfo.IncollectFighterPowerFlag) == 0\r
-                ? enemyFp.ToString()\r
-                : (enemyFp & ~BattleInfo.IncollectFighterPowerFlag) + "+";\r
+            labelEnemyFighterPower.Text = battle.EnemyFighterPower;\r
             labelFighterPower.ForeColor = color[battle.AirControlLevel + 1];\r
             if (_config.AlwaysShowResultRank)\r
                 ShowResultRank();\r
@@ -660,6 +645,13 @@ namespace KancolleSniffer
             _shipLabels.SetNDockLabels(_sniffer.NDock);\r
         }\r
 \r
+\r
+        private void labelNDock_Click(object sender, EventArgs e)\r
+        {\r
+            _ndockFinishTimeMode = !_ndockFinishTimeMode;\r
+            UpdateTimers();\r
+        }\r
+\r
         private void UpdateMissionLabels()\r
         {\r
             foreach (var entry in\r
@@ -682,16 +674,10 @@ namespace KancolleSniffer
             {\r
                 entry.Timer.Update();\r
                 SetTimerColor(entry.label, entry.Timer);\r
-                var rest = entry.Timer.Rest;\r
-                entry.label.Text =\r
-                    entry.Timer.EndTime == DateTime.MinValue\r
-                        ? ""\r
-                        : _missionFinishTimeMode\r
-                            ? entry.Timer.EndTime.ToString(@"dd\ HH\:mm")\r
-                            : rest.ToString(@"hh\:mm\:ss");\r
+                entry.label.Text = entry.Timer.ToString(_missionFinishTimeMode);\r
                 if (!entry.Timer.NeedRing)\r
                     continue;\r
-                _noticeQueue.Enqueue("遠征が終わりました", entry.Name, _config.MissionSoundFile);\r
+                _noticeQueue.Enqueue("遠征が終わりました", entry.Name, _config.Sounds["遠征終了"]);\r
                 entry.Timer.NeedRing = false;\r
             }\r
             for (var i = 0; i < _sniffer.NDock.Length; i++)\r
@@ -701,7 +687,7 @@ namespace KancolleSniffer
                 _shipLabels.SetNDockTimer(i, entry.Timer, _ndockFinishTimeMode);\r
                 if (!entry.Timer.NeedRing)\r
                     continue;\r
-                _noticeQueue.Enqueue("入渠が終わりました", entry.Name, _config.NDockSoundFile);\r
+                _noticeQueue.Enqueue("入渠が終わりました", entry.Name, _config.Sounds["入渠終了"]);\r
                 entry.Timer.NeedRing = false;\r
             }\r
             var kdock = new[] {labelConstruct1, labelConstruct2, labelConstruct3, labelConstruct4};\r
@@ -714,7 +700,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}ドック", _config.KDockSoundFile);\r
+                _noticeQueue.Enqueue("建造が終わりました", $"第{i + 1:D}ドック", _config.Sounds["建造完了"]);\r
                 timer.NeedRing = false;\r
             }\r
             UpdateCondTimers();\r
@@ -728,7 +714,17 @@ namespace KancolleSniffer
 \r
         private void UpdateCondTimers()\r
         {\r
-            var timer = _sniffer.GetConditionTimer(_currentFleet);\r
+            DateTime timer;\r
+            if (_combinedFleet)\r
+            {\r
+                var timer1 = _sniffer.GetConditionTimer(0);\r
+                var timer2 = _sniffer.GetConditionTimer(1);\r
+                timer = timer2 > timer1 ? timer2 : timer1;\r
+            }\r
+            else\r
+            {\r
+                timer = _sniffer.GetConditionTimer(_currentFleet);\r
+            }\r
             var now = DateTime.Now;\r
             if (timer == DateTime.MinValue)\r
             {\r
@@ -755,27 +751,42 @@ namespace KancolleSniffer
             {\r
                 if (!_config.NotifyConditions.Contains(notice[i]))\r
                     return;\r
-                _noticeQueue.Enqueue("疲労が回復しました", fn[i] + " cond" + notice[i].ToString("D"), _config.ConditionSoundFile);\r
+                _noticeQueue.Enqueue("疲労が回復しました", fn[i] + " cond" + notice[i].ToString("D"), _config.Sounds["疲労回復"]);\r
             }\r
         }\r
 \r
         private void UpdateAkashiTimer()\r
         {\r
+            if (_config.UsePresetAkashi)\r
+                UpdatePresetAkashiTimer();\r
+            _shipLabels.SetAkashiTimer(_sniffer.GetShipStatuses(_currentFleet),\r
+                _sniffer.AkashiTimer.GetTimers(_currentFleet));\r
+            NotifyAkashiTimer();\r
+        }\r
+\r
+        private void UpdatePresetAkashiTimer()\r
+        {\r
             var akashi = _sniffer.AkashiTimer;\r
             var span = akashi.PresetDeckTimer;\r
-            if (_config.UsePresetAkashi)\r
+            var color = span == TimeSpan.Zero && akashi.CheckPresetReparing() ? Color.Red : DefaultForeColor;\r
+            var text = span == TimeSpan.MinValue ? "" : span.ToString(@"mm\:ss");\r
+            labelAkashiRepairTimer.ForeColor = color;\r
+            labelAkashiRepairTimer.Text = text;\r
+            if (akashi.CheckPresetReparing() && !akashi.CheckReparing(_currentFleet))\r
             {\r
-                labelAkashiRepairTimer.ForeColor =\r
-                    span == TimeSpan.Zero && akashi.CheckPresetReparing() ? Color.Red : DefaultForeColor;\r
-                labelAkashiRepairTimer.Text = span == TimeSpan.MinValue ? "" : span.ToString(@"mm\:ss");\r
+                labelPresetAkashiTimer.ForeColor = color;\r
+                labelPresetAkashiTimer.Text = text;\r
+            }\r
+            else\r
+            {\r
+                labelPresetAkashiTimer.ForeColor = DefaultForeColor;\r
+                labelPresetAkashiTimer.Text = "";\r
             }\r
-            _shipLabels.SetAkashiTimer(_sniffer.GetShipStatuses(_currentFleet), akashi.GetTimers(_currentFleet));\r
-            NotifyAkashiTimer();\r
         }\r
 \r
-        private void UpdateDamagedShipList()\r
+        private void UpdateRepairList()\r
         {\r
-            _shipLabels.SetDamagedShipList(_sniffer.DamagedShipList);\r
+            _shipLabels.SetRepairList(_sniffer.RepairList);\r
         }\r
 \r
         private void UpdateQuestList()\r
@@ -788,19 +799,12 @@ namespace KancolleSniffer
             var name = new[] {labelQuest1, labelQuest2, labelQuest3, labelQuest4, labelQuest5, labelQuest6};\r
             var progress = new[]\r
             {labelProgress1, labelProgress2, labelProgress3, labelProgress4, labelProgress5, labelProgress6};\r
-            var color = new[]\r
-            {\r
-                Color.FromArgb(60, 141, 76), Color.FromArgb(232, 57, 41), Color.FromArgb(136, 204, 120),\r
-                Color.FromArgb(52, 147, 185), Color.FromArgb(220, 198, 126), Color.FromArgb(168, 111, 76),\r
-                Color.FromArgb(200, 148, 231)\r
-            };\r
-\r
             var quests = _sniffer.Quests;\r
             for (var i = 0; i < name.Length; i++)\r
             {\r
                 if (i < quests.Length)\r
                 {\r
-                    category[i].BackColor = color[quests[i].Category - 1];\r
+                    category[i].BackColor = quests[i].Color;\r
                     name[i].Text = quests[i].Name;\r
                     progress[i].Text = $"{quests[i].Progress:D}%";\r
                 }\r
@@ -856,7 +860,7 @@ namespace KancolleSniffer
             if (_config.ShowBaloonTip)\r
                 notifyIconMain.ShowBalloonTip(20000, baloonTitle, baloonMessage, ToolTipIcon.Info);\r
             if (_config.PlaySound)\r
-                PlaySound(soundFile, _config.SoundVolume);\r
+                PlaySound(soundFile, _config.Sounds.Volume);\r
         }\r
 \r
         [DllImport("winmm.dll")]\r
@@ -983,34 +987,34 @@ namespace KancolleSniffer
             UpdateItemInfo();\r
         }\r
 \r
-        private void labelDamgedShipListButton_Click(object sender, EventArgs e)\r
+        private void labelRepairListButton_Click(object sender, EventArgs e)\r
         {\r
-            if (panelDamagedShipList.Visible)\r
+            if (panelRepairList.Visible)\r
             {\r
-                panelDamagedShipList.Visible = false;\r
-                labelDamgedShipListButton.BackColor = DefaultBackColor;\r
+                panelRepairList.Visible = false;\r
+                labelRepairListButton.BackColor = DefaultBackColor;\r
             }\r
             else\r
             {\r
-                panelDamagedShipList.Visible = true;\r
-                panelDamagedShipList.BringToFront();\r
-                labelDamgedShipListButton.BackColor = SystemColors.ActiveCaption;\r
+                panelRepairList.Visible = true;\r
+                panelRepairList.BringToFront();\r
+                labelRepairListButton.BackColor = SystemColors.ActiveCaption;\r
             }\r
         }\r
 \r
-        private void panelDamagedShipList_Click(object sender, EventArgs e)\r
+        private void panelRepairList_Click(object sender, EventArgs e)\r
         {\r
-            panelDamagedShipList.Visible = false;\r
-            labelDamgedShipListButton.BackColor = DefaultBackColor;\r
+            panelRepairList.Visible = false;\r
+            labelRepairListButton.BackColor = DefaultBackColor;\r
         }\r
 \r
         private void ShipListToolStripMenuItem_Click(object sender, EventArgs e)\r
         {\r
-            _shipListForm.UpdateList();\r
-            _shipListForm.Show();\r
-            if (_shipListForm.WindowState == FormWindowState.Minimized)\r
-                _shipListForm.WindowState = FormWindowState.Normal;\r
-            _shipListForm.Activate();\r
+            _listForm.UpdateList();\r
+            _listForm.Show();\r
+            if (_listForm.WindowState == FormWindowState.Minimized)\r
+                _listForm.WindowState = FormWindowState.Normal;\r
+            _listForm.Activate();\r
         }\r
 \r
         private void LogToolStripMenuItem_Click(object sender, EventArgs e)\r