OSDN Git Service

ヘッダのCondとExpのマウスカーソルを変える
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / AkashiTimer.cs
index a36dcf4..584fce1 100644 (file)
@@ -1,19 +1,16 @@
 // Copyright (C) 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
@@ -25,6 +22,7 @@ namespace KancolleSniffer
     {\r
         private readonly ShipInfo _shipInfo;\r
         private readonly DockInfo _dockInfo;\r
+        private readonly PresetDeck _presetDeck;\r
         private readonly RepairStatus[] _repairStatuses = new RepairStatus[ShipInfo.FleetCount];\r
         private DateTime _start;\r
         private DateTime _prev;\r
@@ -45,18 +43,23 @@ namespace KancolleSniffer
         {\r
             private ShipStatus[] _target = new ShipStatus[0];\r
             private int[] _deck = new int[0];\r
+            private TimeSpan FirstRepairTime => TimeSpan.FromMinutes(20);\r
+\r
+            private bool PassedFirstRepairTime(DateTime start, DateTime prev, DateTime now) =>\r
+                prev - start < FirstRepairTime && now - start >= FirstRepairTime;\r
+\r
+            private TimeSpan RepairTime(ShipStatus ship, int damage) =>\r
+                TimeSpan.FromMinutes(Math.Ceiling(ship.RepairTime.TotalMinutes / (ship.MaxHp - ship.NowHp) * damage));\r
+\r
 \r
             public int[] Deck\r
             {\r
-                set { _deck = value; }\r
+                set => _deck = value;\r
             }\r
 \r
             public State State { get; set; }\r
 \r
-            public void Invalidate()\r
-            {\r
-                _target = new ShipStatus[0];\r
-            }\r
+            public bool IsRepaired(ShipStatus[] target) => _target.Zip(target, (a, b) => a.NowHp < b.NowHp).Any(x => x);\r
 \r
             public bool DeckChanged(IEnumerable<int> deck) => !_deck.SequenceEqual(deck);\r
 \r
@@ -73,17 +76,17 @@ namespace KancolleSniffer
                     var damage = s.MaxHp - s.NowHp;\r
                     if (damage == 0)\r
                         return new RepairSpan(0, TimeSpan.MinValue);\r
-                    if (spent < TimeSpan.FromMinutes(20))\r
-                        return new RepairSpan(0, TimeSpan.FromMinutes(20) - spent);\r
+                    if (spent < FirstRepairTime)\r
+                        return new RepairSpan(0, FirstRepairTime - spent);\r
                     if (damage == 1)\r
                         return new RepairSpan(1, TimeSpan.Zero);\r
                     for (var d = 2; d <= damage; d++)\r
                     {\r
-                        var sec = s.CalcRepairSec(d) + 60;\r
-                        if (sec <= 20 * 60)\r
+                        var span = RepairTime(s, d);\r
+                        if (span <= FirstRepairTime)\r
                             continue;\r
-                        if (TimeSpan.FromSeconds(sec) > spent)\r
-                            return new RepairSpan(d - 1, TimeSpan.FromSeconds(sec) - spent);\r
+                        if (span > spent)\r
+                            return new RepairSpan(d - 1, span - spent);\r
                     }\r
                     return new RepairSpan(damage, TimeSpan.Zero);\r
                 }).ToArray();\r
@@ -91,7 +94,6 @@ namespace KancolleSniffer
 \r
             public Notice GetNotice(DateTime start, DateTime prev, DateTime now)\r
             {\r
-                var m20 = TimeSpan.FromMinutes(20);\r
                 var proc = new List<string>();\r
                 var comp = new List<string>();\r
                 foreach (var s in _target)\r
@@ -101,7 +103,7 @@ namespace KancolleSniffer
                         continue;\r
                     if (damage == 1)\r
                     {\r
-                        if (prev - start < m20 && now - start >= m20)\r
+                        if (PassedFirstRepairTime(start, prev, now))\r
                             comp.Add(s.Name);\r
                         continue;\r
                     }\r
@@ -109,14 +111,13 @@ namespace KancolleSniffer
                     // 完全回復から減らしながら所要時間と経過時間と比較する。\r
                     for (var d = damage; d >= 2; d--)\r
                     {\r
-                        var sec = s.CalcRepairSec(d) + 60;\r
-                        if (sec <= 20 * 60)\r
+                        var span = RepairTime(s, d);\r
+                        if (span <= FirstRepairTime)\r
                         {\r
-                            if (d == damage && (prev - start < m20 && now - start >= m20))\r
+                            if (d == damage && PassedFirstRepairTime(start, prev, now))\r
                                 comp.Add(s.Name);\r
                             continue;\r
                         }\r
-                        var span = TimeSpan.FromSeconds(sec);\r
                         if (span <= prev - start || now - start < span)\r
                             continue;\r
                         if (d == damage)\r
@@ -140,46 +141,37 @@ namespace KancolleSniffer
             public string Completed { get; set; }\r
         }\r
 \r
-        public AkashiTimer(ShipInfo ship, DockInfo dock)\r
+        public AkashiTimer(ShipInfo ship, DockInfo dock, PresetDeck preset)\r
         {\r
             _shipInfo = ship;\r
             _dockInfo = dock;\r
+            _presetDeck = preset;\r
             for (var i = 0; i < _repairStatuses.Length; i++)\r
                 _repairStatuses[i] = new RepairStatus();\r
         }\r
 \r
-        [Flags]\r
         private enum State\r
         {\r
-            Stop = 0,\r
-            Continue = 1,\r
-            Reset = 2,\r
-            Reparing = 4\r
+            Continue = 0,\r
+            Reset = 1,\r
         }\r
 \r
         public void Port()\r
         {\r
             CheckFleet();\r
             var now = DateTime.Now;\r
-            var reparing = _repairStatuses.Any(r => (r.State & State.Reparing) != 0);\r
-            var stop = _repairStatuses.All(r => (r.State & State.Continue) == 0);\r
-            if (now - _start > TimeSpan.FromMinutes(20))\r
-            {\r
-                if (reparing)\r
-                    _start = now;\r
-                else if (stop)\r
-                    _start = DateTime.MinValue;\r
-            }\r
-            else if (!stop && _start == DateTime.MinValue)\r
-            {\r
+            var reset = _repairStatuses.Any(r => r.State == State.Reset);\r
+            if (_start == DateTime.MinValue || now - _start > TimeSpan.FromMinutes(20) || reset)\r
                 _start = now;\r
-            }\r
         }\r
 \r
-        public void DeckChanged()\r
+        public void InspectChange(string request)\r
         {\r
             CheckFleet();\r
-            if (_repairStatuses.Any(r => (r.State & State.Reset) != 0))\r
+            var values = HttpUtility.ParseQueryString(request);\r
+            if (int.Parse(values["api_ship_idx"]) == -1)\r
+                return;\r
+            if (_repairStatuses.Any(r => r.State == State.Reset))\r
                 _start = DateTime.Now;\r
         }\r
 \r
@@ -194,35 +186,40 @@ namespace KancolleSniffer
             var deck = _shipInfo.GetDeck(fleet).ToArray();\r
             var repair = _repairStatuses[fleet];\r
             var fs = _shipInfo.GetStatus(deck[0]);\r
-            /*\r
-             * 旗艦が明石でないか明石がドックに入っている場合は泊地修理を止める。\r
-            */\r
-            if (!fs.Name.StartsWith("明石") || _shipInfo.InMission(fleet))\r
+            repair.State = State.Continue;\r
+            if (!fs.Spec.IsRepairShip)\r
             {\r
-                repair.Invalidate();\r
-                repair.State = State.Stop;\r
+                repair.UpdateTarget(new ShipStatus[0]);\r
                 repair.Deck = deck;\r
                 return;\r
             }\r
-            var cap = fs.Slot.Count(item => item.Spec.Name == "艦艇修理施設") + 2;\r
+            if (repair.DeckChanged(deck))\r
+            {\r
+                repair.State = State.Reset;\r
+                repair.Deck = deck;\r
+            }\r
+            var target = RepairTarget(deck);\r
+            if (repair.IsRepaired(target))\r
+                repair.State = State.Reset;\r
+            repair.UpdateTarget(target);\r
+        }\r
+\r
+        private ShipStatus[] RepairTarget(int[] deck)\r
+        {\r
+            var fs = _shipInfo.GetStatus(deck[0]);\r
+            if (!fs.Spec.IsRepairShip || _dockInfo.InNDock(fs.Id) || fs.DamageLevel >= ShipStatus.Damage.Half)\r
+                return new ShipStatus[0];\r
+            var cap = fs.Slot.Count(item => item.Spec.IsRepairFacility) + 2;\r
             /*\r
              * 泊地修理の条件を満たさない艦はMaxHp==NowHpのダミーを設定する。\r
-             * 入渠中の艦娘は終わったときに回復扱いされないようNowHp=MaxHpにする。\r
-             * 中破以上でNowHp=MaxHpにすると回復扱いされるのでNowHp=MaxHp=0にする。\r
+             * - 入渠中の艦娘は終わったときに回復扱いされないようNowHp=MaxHpに\r
+             * - 中破以上でNowHp=MaxHpにすると回復扱いされるのでNowHp=MaxHp=0に\r
             */\r
-            var target = (from id in deck.Take(cap)\r
-                let s = _shipInfo.GetStatus(id)\r
+            return (from id in deck.Take(cap)\r
+                let s = (ShipStatus)_shipInfo.GetStatus(id).Clone()\r
                 let full = new ShipStatus {NowHp = s.MaxHp, MaxHp = s.MaxHp}\r
                 let zero = new ShipStatus()\r
                 select _dockInfo.InNDock(id) ? full : s.DamageLevel >= ShipStatus.Damage.Half ? zero : s).ToArray();\r
-            repair.State = State.Continue;\r
-            if (repair.DeckChanged(deck))\r
-                repair.State |= State.Reset;\r
-            if (target[0].DamageLevel < ShipStatus.Damage.Half &&\r
-                target.Any(s => s.NowHp < s.MaxHp))\r
-                repair.State |= State.Reparing;\r
-            repair.UpdateTarget(target);\r
-            repair.Deck = deck;\r
         }\r
 \r
         public RepairSpan[] GetTimers(int fleet)\r
@@ -232,13 +229,21 @@ namespace KancolleSniffer
         {\r
             get\r
             {\r
-                if (_start == DateTime.MinValue || _repairStatuses.Any(rs => rs.State != State.Stop))\r
+                if (_start == DateTime.MinValue)\r
                     return TimeSpan.MinValue;\r
-                var r = _start + TimeSpan.FromMinutes(20) - DateTime.Now;\r
+                var r = TimeSpan.FromMinutes(20) - TimeSpan.FromSeconds((int)(DateTime.Now - _start).TotalSeconds);\r
                 return r >= TimeSpan.Zero ? r : TimeSpan.Zero;\r
             }\r
         }\r
 \r
+        public bool CheckReparing(int fleet) => GetTimers(fleet).Any(r => r.Span != TimeSpan.MinValue);\r
+\r
+        public bool CheckReparing() => Enumerable.Range(0, ShipInfo.FleetCount).Any(CheckReparing);\r
+\r
+        public bool CheckPresetReparing()\r
+            => _presetDeck.Decks.Where(deck => deck != null)\r
+                .Any(deck => RepairTarget(deck).Any(s => s.NowHp < s.MaxHp));\r
+\r
         public Notice[] GetNotice()\r
         {\r
             var now = DateTime.Now;\r