1 // Copyright (C) 2013, 2015 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
17 using System.Drawing;
\r
19 using System.Windows.Forms;
\r
20 using System.Xml.Serialization;
\r
21 using static System.Math;
\r
23 namespace KancolleSniffer
\r
25 public class QuestStatus
\r
27 public int Id { get; set; }
\r
28 public int Category { get; set; }
\r
29 public string Name { get; set; }
\r
30 public string Detail { get; set; }
\r
31 public int[] Material { get; set; }
\r
32 public int Progress { get; set; }
\r
35 public QuestCount Count { get; set; }
\r
38 public Color Color { get; set; }
\r
40 public string ToToolTip() =>
\r
42 (Material == null || Material.All(x => x == 0)
\r
44 : "\r\n" + string.Join(" ",
\r
45 new[] {"燃", "弾", "鋼", "ボ", "建造", "修復", "開発", "改修"}
\r
46 .Zip(Material, (m, num) => num == 0 ? "" : m + num)
\r
47 .Where(s => !string.IsNullOrEmpty(s))));
\r
50 public enum QuestInterval
\r
59 public class QuestSpec
\r
61 public QuestInterval Interval { get; set; }
\r
62 public int Max { get; set; }
\r
63 public int[] MaxArray { get; set; }
\r
64 public bool AdjustCount { get; set; } = true;
\r
65 public int Shift { get; set; }
\r
66 public int[] Material { get; set; }
\r
69 public class QuestSortie : QuestSpec
\r
71 public string Rank { get; set; }
\r
72 public int[] Maps { get; set; }
\r
73 public int[] ShipTypes { get; set; }
\r
75 public static int CompareRank(string a, string b)
\r
77 const string ranks = "SABCDE";
\r
78 return ranks.IndexOf(a, StringComparison.Ordinal) -
\r
79 ranks.IndexOf(b, StringComparison.Ordinal);
\r
82 public bool Check(string rank, int map, bool boss)
\r
84 return (Rank == null || CompareRank(rank, Rank) <= 0) &&
\r
85 (Maps == null || Maps.Contains(map) && boss);
\r
89 public class QuestEnemyType : QuestSpec
\r
91 public int[] EnemyType { get; set; } = new int[0];
\r
93 public int CountResult(IEnumerable<ShipStatus> enemyResult) =>
\r
94 enemyResult.Count(ship => ship.NowHp == 0 && EnemyType.Contains(ship.Spec.ShipType));
\r
97 public class QuestPractice : QuestSpec
\r
99 public bool Win { get; set; }
\r
100 public bool Check(string rank) => !Win || QuestSortie.CompareRank(rank, "B") <= 0;
\r
103 public class QuestMission : QuestSpec
\r
105 public int[] Ids { get; set; }
\r
106 public bool Check(int id) => Ids == null || Ids.Contains(id);
\r
109 public class QuestDestroyItem : QuestSpec
\r
111 public int[] Items { get; set; }
\r
112 public bool Check(int id) => Items == null || Items.Contains(id);
\r
115 public class QuestPowerup : QuestSpec
\r
119 public class QuestCount
\r
121 public int Id { get; set; }
\r
122 public int Now { get; set; }
\r
123 public int[] NowArray { get; set; }
\r
126 public QuestSpec Spec { get; set; }
\r
128 public bool AdjustCount(int progress)
\r
130 if (!Spec.AdjustCount)
\r
132 if (NowArray != null)
\r
134 if (progress != 100)
\r
136 NowArray = NowArray.Zip(Spec.MaxArray, Max).ToArray();
\r
155 var now = Now + Spec.Shift;
\r
156 var max = Spec.Max + Spec.Shift;
\r
157 var low = (int)Ceiling(max * progress / 100.0);
\r
158 var high = (int)Ceiling(max * next / 100.0);
\r
161 Now = low - Spec.Shift;
\r
166 Now = high - 1 - Spec.Shift;
\r
172 public override string ToString()
\r
174 if (Id == 426 || Id == 854)
\r
175 return $"{NowArray.Count(n => n >= 1)}/{Spec.MaxArray.Length}";
\r
176 return NowArray != null
\r
177 ? string.Join(" ", NowArray.Zip(Spec.MaxArray, (n, m) => $"{n}/{m}"))
\r
178 : $"{Now}/{Spec.Max}";
\r
181 public string ToToolTip()
\r
186 return string.Join(" ",
\r
187 new[] {"警備任務", "対潜警戒任務", "海上護衛任務", "強硬偵察任務"}
\r
188 .Zip(NowArray, (mission, n) => n >= 1 ? mission : "")
\r
189 .Where(s => !string.IsNullOrEmpty(s)));
\r
191 return string.Join(" ",
\r
192 new[] {"対潜警戒任務", "海峡警備行動", "長時間対潜警戒"}.Zip(NowArray, (mission, n) => n >= 1 ? mission + n : "")
\r
193 .Where(s => !string.IsNullOrEmpty(s)));
\r
195 return string.Join(" ",
\r
196 new[] {"2-4", "6-1", "6-3", "6-4"}.Zip(NowArray, (map, n) => n >= 1 ? map : "")
\r
197 .Where(s => !string.IsNullOrEmpty(s)));
\r
202 public bool Cleared => NowArray?.Zip(Spec.MaxArray, (n, m) => n >= m).All(x => x) ?? Now >= Spec.Max;
\r
206 public class QuestCountList
\r
208 private const QuestInterval Daily = QuestInterval.Daily;
\r
209 private const QuestInterval Weekly = QuestInterval.Weekly;
\r
210 private const QuestInterval Monthly = QuestInterval.Monthly;
\r
211 private const QuestInterval Quarterly = QuestInterval.Quarterly;
\r
214 /// このテーブルは七四式電子観測儀を参考に作成した。
\r
215 /// https://github.com/andanteyk/ElectronicObserver/blob/develop/ElectronicObserver/Data/Quest/QuestProgressManager.cs
\r
217 private static readonly Dictionary<int, QuestSpec> QuestSpecs = new Dictionary<int, QuestSpec>
\r
219 {201, new QuestSortie {Interval = Daily, Max = 1, Rank = "B", Material = new[] {0, 0, 1, 0}}}, // 201: 敵艦隊を撃滅せよ!
\r
220 {216, new QuestSortie {Interval = Daily, Max = 1, Rank = "B", Material = new[] {0, 1, 1, 0}}}, // 216: 敵艦隊主力を撃滅せよ!
\r
221 {210, new QuestSortie {Interval = Daily, Max = 10, Material = new[] {0, 0, 1, 0}}}, // 210: 敵艦隊を10回邀撃せよ!
\r
222 {211, new QuestEnemyType {Interval = Daily, Max = 3, EnemyType = new[] {7, 11}, Material = new[] {0, 2, 0, 0}}}, // 211: 敵空母を3隻撃沈せよ!
\r
223 {212, new QuestEnemyType {Interval = Daily, Max = 5, EnemyType = new[] {15}, Material = new[] {0, 0, 2, 0}}}, // 212: 敵輸送船団を叩け!
\r
224 {218, new QuestEnemyType {Interval = Daily, Max = 3, EnemyType = new[] {15}, Material = new[] {0, 1, 1, 0}}}, // 218: 敵補給艦を3隻撃沈せよ!
\r
225 {226, new QuestSortie {Interval = Daily, Max = 5, Rank = "B", Maps = new[] {21, 22, 23, 24, 25}, Material = new[] {1, 1, 0, 0}}}, // 226: 南西諸島海域の制海権を握れ!
\r
226 {230, new QuestEnemyType {Interval = Daily, Max = 6, EnemyType = new[] {13}, Material = new[] {0, 1, 0, 0}}}, // 230: 敵潜水艦を制圧せよ!
\r
228 {213, new QuestEnemyType {Interval = Weekly, Max = 20, EnemyType = new[] {15}, Material = new[] {0, 0, 3, 0}}}, // 213: 海上通商破壊作戦
\r
229 {214, new QuestSpec {Interval = Weekly, MaxArray = new[] {36, 6, 24, 12}, Material = new[] {2, 0, 2, 0}}}, // 214: あ号作戦
\r
230 {220, new QuestEnemyType {Interval = Weekly, Max = 20, EnemyType = new[] {7, 11}, Material = new[] {0, 2, 0, 0}}}, // 220: い号作戦
\r
231 {221, new QuestEnemyType {Interval = Weekly, Max = 50, EnemyType = new[] {15}, Material = new[] {0, 3, 0, 0}}}, // 221: ろ号作戦
\r
232 {228, new QuestEnemyType {Interval = Weekly, Max = 15, EnemyType = new[] {13}, Material = new[] {0, 2, 0, 1}}}, // 228: 海上護衛戦
\r
233 {229, new QuestSortie {Interval = Weekly, Max = 12, Rank = "B", Maps = new[] {41, 42, 43, 44, 45}, Material = new[] {0, 0, 2, 0}}}, // 229: 敵東方艦隊を撃滅せよ!
\r
234 {241, new QuestSortie {Interval = Weekly, Max = 5, Rank = "B", Maps = new[] {33, 34, 35}, Material = new[] {0, 0, 3, 3}}}, // 241: 敵北方艦隊主力を撃滅せよ!
\r
235 {242, new QuestSortie {Interval = Weekly, Max = 1, Rank = "B", Maps = new[] {44}, Material = new[] {0, 1, 1, 0}}}, // 242: 敵東方中枢艦隊を撃破せよ!
\r
236 {243, new QuestSortie {Interval = Weekly, Max = 2, Rank = "S", Maps = new[] {52}, Material = new[] {0, 0, 2, 2}}}, // 243: 南方海域珊瑚諸島沖の制空権を握れ!
\r
237 {256, new QuestSortie {Interval = Monthly, Max = 3, Rank = "S", Maps = new[] {61}, Material = new[] {0, 0, 0, 0}}}, // 256: 「潜水艦隊」出撃せよ!
\r
238 {261, new QuestSortie {Interval = Weekly, Max = 3, Rank = "A", Maps = new[] {15}, Material = new[] {0, 0, 0, 3}}}, // 261: 海上輸送路の安全確保に努めよ!
\r
239 {265, new QuestSortie {Interval = Monthly, Max = 10, Rank = "A", Maps = new[] {15}, Material = new[] {0, 0, 5, 3}}}, // 265: 海上護衛強化月間
\r
241 {822, new QuestSortie {Interval = Quarterly, Max = 2, Rank = "S", Maps = new[] {24}, Material = new[] {0, 0, 0, 5}}}, // 822: 沖ノ島海域迎撃戦
\r
242 {854, new QuestSpec {Interval = Quarterly, MaxArray = new[] {1, 1, 1, 1}, Material = new[] {0, 0, 0, 4}}}, // 854: 戦果拡張任務!「Z作戦」前段作戦
\r
244 {303, new QuestPractice {Interval = Daily, Max = 3, Win = false, Material = new[] {1, 0, 0, 0}}}, // 303: 「演習」で練度向上!
\r
245 {304, new QuestPractice {Interval = Daily, Max = 5, Win = true, Material = new[] {0, 0, 1, 0}}}, // 304: 「演習」で他提督を圧倒せよ!
\r
246 {302, new QuestPractice {Interval = Weekly, Max = 20, Win = true, Material = new[] {0, 0, 2, 1}}}, // 302: 大規模演習
\r
247 {311, new QuestPractice {Interval = Daily, Max = 7, Win = true, Material = new[] {0, 2, 0, 0}}}, // 311: 精鋭艦隊演習
\r
249 {402, new QuestMission {Interval = Daily, Max = 3, Material = new[] {0, 0, 1, 0}}}, // 402: 「遠征」を3回成功させよう!
\r
250 {403, new QuestMission {Interval = Daily, Max = 10, Material = new[] {0, 0, 0, 0}}}, // 403: 「遠征」を10回成功させよう!
\r
251 {404, new QuestMission {Interval = Weekly, Max = 30, Material = new[] {0, 0, 3, 0}}}, // 404: 大規模遠征作戦、発令!
\r
252 {410, new QuestMission {Interval = Weekly, Max = 1, Ids = new[] {37, 38}, Material = new[] {0, 0, 0, 0}}}, // 410: 南方への輸送作戦を成功させよ!
\r
253 {411, new QuestMission {Interval = Weekly, Max = 6, Shift = 1, Ids = new[] {37, 38}, Material = new[] {0, 0, 2, 1}}}, // 411: 南方への鼠輸送を継続実施せよ!
\r
254 {424, new QuestMission {Interval = Monthly, Max = 4, Shift = 1, Ids = new[] {5}, Material = new[] {0, 0, 0, 0}}}, // 424: 輸送船団護衛を強化せよ!
\r
255 {426, new QuestSpec {Interval = Quarterly, MaxArray = new[] {1, 1, 1, 1}, Material = new[] {0, 0, 4, 0}}}, // 426: 海上通商航路の警戒を厳とせよ!
\r
256 {428, new QuestSpec {Interval = Quarterly, MaxArray = new[] {2, 2, 2}, Material = new[] {0, 0, 0, 3}}}, // 428: 近海に侵入する敵潜を制圧せよ!
\r
258 {503, new QuestSpec {Interval = Daily, Max = 5, Material = new[] {0, 2, 0, 0}}}, // 503: 艦隊大整備!
\r
259 {504, new QuestSpec {Interval = Daily, Max = 15, Material = new[] {1, 0, 1, 0}}}, // 504: 艦隊酒保祭り!
\r
261 {605, new QuestSpec {Interval = Daily, Max = 1, Material = new[] {1, 0, 1, 0}}}, // 605: 新装備「開発」指令
\r
262 {606, new QuestSpec {Interval = Daily, Max = 1, Material = new[] {0, 1, 1, 0}}}, // 606: 新造艦「建造」指令
\r
263 {607, new QuestSpec {Interval = Daily, Max = 3, Shift = 1, Material = new[] {0, 0, 2, 0}}}, // 607: 装備「開発」集中強化!
\r
264 {608, new QuestSpec {Interval = Daily, Max = 3, Shift = 1, Material = new[] {1, 0, 2, 0}}}, // 608: 艦娘「建造」艦隊強化!
\r
265 {609, new QuestSpec {Interval = Daily, Max = 2, Material = new[] {0, 1, 0, 0}}}, // 609: 軍縮条約対応!
\r
266 {619, new QuestSpec {Interval = Daily, Max = 1, Material = new[] {0, 0, 0, 1}}}, // 619: 装備の改修強化
\r
268 {613, new QuestSpec {Interval = Weekly, Max = 24, Material = new[] {0, 0, 0, 0}}}, // 613: 資源の再利用
\r
269 {638, new QuestDestroyItem {Interval = Weekly, Max = 6, Items = new[] {21}, Material = new[] {0, 0, 2, 1}}}, // 638: 対空機銃量産
\r
270 {663, new QuestDestroyItem {Interval = Quarterly, Max = 10, Items = new[] {3}, Material = new[] {0, 0, 3, 0}}}, // 663: 新型艤装の継続研究
\r
271 {673, new QuestDestroyItem {Interval = Daily, Max = 4, Items = new[] {1}, Shift = 1, Material = new[] {0, 0, 1, 0}}}, // 673: 装備開発力の整備
\r
272 {674, new QuestDestroyItem {Interval = Daily, Max = 3, Items = new[] {21}, Shift = 2, Material = new[] {0, 1, 1, 0}}}, // 674: 工廠環境の整備
\r
273 {675, new QuestSpec {Interval = Quarterly, MaxArray = new[] {6, 4}, Material = new[] {0, 0, 0, 0}}}, // 675: 運用装備の統合整備
\r
274 {676, new QuestSpec {Interval = Weekly, MaxArray = new[] {3, 3, 1}, Material = new[] {0, 1, 7, 0}}}, // 676: 装備開発力の集中整備
\r
275 {677, new QuestSpec {Interval = Weekly, MaxArray = new[] {4, 2, 3}, Material = new[] {0, 5, 0, 0}}}, // 677: 継戦支援能力の整備
\r
277 {702, new QuestPowerup {Interval = Daily, Max = 2, Material = new[] {0, 1, 0, 0}}}, // 702: 艦の「近代化改修」を実施せよ!
\r
278 {703, new QuestPowerup {Interval = Weekly, Max = 15, Material = new[] {1, 0, 2, 0}}} // 703: 「近代化改修」を進め、戦備を整えよ!
\r
282 private readonly Dictionary<int, QuestCount> _countDict = new Dictionary<int, QuestCount>();
\r
284 public QuestCount GetCount(int id)
\r
286 if (_countDict.TryGetValue(id, out var value))
\r
288 if (QuestSpecs.TryGetValue(id, out var spec))
\r
290 var nowArray = spec.MaxArray?.Select(x => 0).ToArray();
\r
291 return _countDict[id] = new QuestCount
\r
295 NowArray = nowArray,
\r
299 return new QuestCount {Spec = new QuestSpec {Material = new int[0], AdjustCount = false}};
\r
302 public void Remove(int id)
\r
304 _countDict.Remove(id);
\r
307 public void Remove(QuestInterval interval)
\r
310 _countDict.Where(pair => pair.Value.Spec.Interval == interval).Select(pair => pair.Key).ToArray())
\r
312 _countDict.Remove(id);
\r
316 public IEnumerable<QuestCount> CountList
\r
318 get => _countDict.Values.Where(c => c.Now > 0 || (c.NowArray?.Any(n => n > 0) ?? false));
\r
323 foreach (var count in value)
\r
325 count.Spec = QuestSpecs[count.Id];
\r
326 _countDict[count.Id] = count;
\r
332 public class QuestInfo : IHaveState
\r
334 private readonly SortedDictionary<int, QuestStatus> _quests = new SortedDictionary<int, QuestStatus>();
\r
335 private readonly QuestCountList _countList = new QuestCountList();
\r
336 private readonly ItemInfo _itemInfo;
\r
337 private readonly BattleInfo _battleInfo;
\r
338 private readonly Func<DateTime> _nowFunc = () => DateTime.Now;
\r
339 private DateTime _lastReset;
\r
341 private readonly Color[] _color =
\r
343 Color.FromArgb(60, 141, 76), Color.FromArgb(232, 57, 41), Color.FromArgb(136, 204, 120),
\r
344 Color.FromArgb(52, 147, 185), Color.FromArgb(220, 198, 126), Color.FromArgb(168, 111, 76),
\r
345 Color.FromArgb(200, 148, 231), Color.FromArgb(232, 57, 41)
\r
348 public int AcceptMax { get; set; } = 5;
\r
350 public QuestStatus[] Quests => _quests.Values.ToArray();
\r
352 public QuestInfo(ItemInfo itemInfo, BattleInfo battleInfo, Func<DateTime> nowFunc = null)
\r
354 _itemInfo = itemInfo;
\r
355 _battleInfo = battleInfo;
\r
356 if (nowFunc != null)
\r
357 _nowFunc = nowFunc;
\r
360 public void InspectQuestList(dynamic json)
\r
363 if (json.api_list == null)
\r
365 for (var i = 0; i < 2; i++)
\r
367 foreach (var entry in json.api_list)
\r
369 if (entry is double) // -1の場合がある。
\r
372 var id = (int)entry.api_no;
\r
373 var state = (int)entry.api_state;
\r
374 var progress = (int)entry.api_progress_flag;
\r
375 var cat = (int)entry.api_category;
\r
376 var name = (string)entry.api_title;
\r
377 var detail = ((string)entry.api_detail).Replace("<br>", "\r\n");
\r
378 var material = (int[])entry.api_get_material;
\r
394 if (_quests.Remove(id))
\r
401 AddQuest(id, cat, name, detail, material, progress, true);
\r
405 if (_quests.Count <= AcceptMax)
\r
408 * ほかのPCで任務を達成した場合、任務が消えずに受領した任務の数が_questCountを超えることがある。
\r
409 * その場合はいったん任務をクリアして、現在のページの任務だけを登録し直す。
\r
415 private void AddQuest(int id, int category, string name, string detail, int[] material, int progress,
\r
418 var count = _countList.GetCount(id);
\r
421 count.AdjustCount(progress);
\r
424 _quests[id] = new QuestStatus
\r
427 Category = category,
\r
430 Material = material?.Concat(count.Spec.Material).ToArray(),
\r
432 Progress = progress,
\r
433 Color = category <= _color.Length ? _color[category - 1] : Control.DefaultBackColor
\r
437 public void ClearQuests()
\r
442 private void ResetQuests()
\r
444 var now = _nowFunc();
\r
445 var daily = now.Date.AddHours(5);
\r
446 if (!(_lastReset < daily && daily <= now))
\r
448 _quests.Clear(); // 前日に未消化のデイリーを消す。
\r
449 _countList.Remove(QuestInterval.Daily);
\r
450 var weekly = now.Date.AddDays(-((6 + (int)now.DayOfWeek) % 7)).AddHours(5);
\r
451 if (_lastReset < weekly && weekly <= now)
\r
452 _countList.Remove(QuestInterval.Weekly);
\r
453 var monthly = new DateTime(now.Year, now.Month, 1, 5, 0, 0);
\r
454 if (_lastReset < monthly && monthly <= now)
\r
455 _countList.Remove(QuestInterval.Monthly);
\r
456 var season = now.Month / 3;
\r
457 var quarterly = new DateTime(now.Year - (season == 0 ? 1 : 0), (season == 0 ? 12 : season * 3), 1, 5, 0, 0);
\r
458 if (_lastReset < quarterly && quarterly <= now)
\r
459 _countList.Remove(QuestInterval.Quarterly);
\r
464 private bool _boss;
\r
467 public void InspectMapStart(dynamic json)
\r
469 if (_quests.TryGetValue(214, out var ago)) // あ号
\r
470 ago.Count.NowArray[0]++;
\r
471 InspectMapNext(json);
\r
474 public void InspectMapNext(dynamic json)
\r
476 _map = (int)json.api_maparea_id * 10 + (int)json.api_mapinfo_no;
\r
477 _boss = (int)json.api_event_id == 5;
\r
480 public void InspectBattleResult(dynamic json)
\r
482 var rank = json.api_win_rank;
\r
483 foreach (var quest in _quests.Values)
\r
485 var count = quest.Count;
\r
486 switch (count.Spec)
\r
488 case QuestSortie sortie:
\r
489 if (count.Id == 216 && !_boss || sortie.Check(rank, _map, _boss))
\r
490 IncrementCount(count);
\r
492 case QuestEnemyType enemyType:
\r
493 var num = enemyType.CountResult(
\r
494 _battleInfo.Result.Enemy.Main.Concat(_battleInfo.Result.Enemy.Guard));
\r
496 AddCount(count, num);
\r
500 if (_quests.TryGetValue(214, out var ago))
\r
502 var array = ago.Count.NowArray;
\r
506 if (QuestSortie.CompareRank(rank, "B") <= 0)
\r
516 if (_quests.TryGetValue(854, out var opz) && _boss)
\r
518 var array = opz.Count.NowArray;
\r
521 case 24 when QuestSortie.CompareRank(rank, "A") <= 0:
\r
525 case 61 when QuestSortie.CompareRank(rank, "A") <= 0:
\r
529 case 63 when QuestSortie.CompareRank(rank, "A") <= 0:
\r
533 case 64 when QuestSortie.CompareRank(rank, "S") <= 0:
\r
541 public void InspectPracticeResult(dynamic json)
\r
543 foreach (var quest in _quests.Values)
\r
545 var count = quest.Count;
\r
546 if (!(count.Spec is QuestPractice practice))
\r
548 if (practice.Check(json.api_win_rank))
\r
549 IncrementCount(count);
\r
553 private readonly int[] _missionId = new int[ShipInfo.FleetCount];
\r
555 public void InspectDeck(dynamic json)
\r
557 foreach (var entry in json)
\r
558 _missionId[(int)entry.api_id - 1] = (int)entry.api_mission[1];
\r
561 public void InspectMissionResult(string request, dynamic json)
\r
563 var values = HttpUtility.ParseQueryString(request);
\r
564 var deck = int.Parse(values["api_deck_id"]);
\r
565 if ((int)json.api_clear_result == 0)
\r
567 var mid = _missionId[deck - 1];
\r
568 foreach (var quest in _quests.Values)
\r
570 var count = quest.Count;
\r
571 if (!(count.Spec is QuestMission mission))
\r
573 if (mission.Check(mid))
\r
574 IncrementCount(count);
\r
576 if (_quests.TryGetValue(426, out var q426))
\r
578 var count = q426.Count;
\r
582 count.NowArray[0]++;
\r
585 count.NowArray[1]++;
\r
588 count.NowArray[2]++;
\r
591 count.NowArray[3]++;
\r
595 if (_quests.TryGetValue(428, out var q428))
\r
597 var count = q428.Count;
\r
601 count.NowArray[0]++;
\r
604 count.NowArray[1]++;
\r
607 count.NowArray[2]++;
\r
613 private void IncrementCount(QuestCount count)
\r
619 private void AddCount(QuestCount count, int value)
\r
621 count.Now += value;
\r
625 private void IncrementCount(int id)
\r
630 private void AddCount(int id, int value)
\r
632 if (_quests.TryGetValue(id, out var quest))
\r
634 quest.Count.Now += value;
\r
639 public void CountNyukyo() => IncrementCount(503);
\r
641 public void CountCharge() => IncrementCount(504);
\r
643 public void CountCreateItem()
\r
645 IncrementCount(605);
\r
646 IncrementCount(607);
\r
649 public void CountCreateShip()
\r
651 IncrementCount(606);
\r
652 IncrementCount(608);
\r
655 public void InspectDestroyShip(string request)
\r
657 AddCount(609, HttpUtility.ParseQueryString(request)["api_ship_id"].Split(',').Length);
\r
660 public void CountRemodelSlot() => IncrementCount(619);
\r
662 public void InspectDestroyItem(string request, dynamic json)
\r
664 var values = HttpUtility.ParseQueryString(request);
\r
665 var items = values["api_slotitem_ids"].Split(',')
\r
666 .Select(id => _itemInfo.GetStatus(int.Parse(id)).Spec.Type).ToArray();
\r
667 IncrementCount(613); // 613: 資源の再利用
\r
668 foreach (var quest in _quests.Values)
\r
670 var count = quest.Count;
\r
671 if (!(count.Spec is QuestDestroyItem destroy))
\r
673 AddCount(count, items.Count(destroy.Check));
\r
675 if (_quests.TryGetValue(675, out var q675))
\r
677 q675.Count.NowArray[0] += items.Count(id => id == 6);
\r
678 q675.Count.NowArray[1] += items.Count(id => id == 21);
\r
681 if (_quests.TryGetValue(676, out var q676))
\r
683 q676.Count.NowArray[0] += items.Count(id => id == 2);
\r
684 q676.Count.NowArray[1] += items.Count(id => id == 4);
\r
685 q676.Count.NowArray[2] += items.Count(id => id == 30);
\r
688 if (_quests.TryGetValue(677, out var q677))
\r
690 q677.Count.NowArray[0] += items.Count(id => id == 3);
\r
691 q677.Count.NowArray[1] += items.Count(id => id == 10);
\r
692 q677.Count.NowArray[2] += items.Count(id => id == 5);
\r
697 public void InspectPowerup(dynamic json)
\r
699 if ((int)json.api_powerup_flag == 0)
\r
701 foreach (var quest in _quests.Values)
\r
703 var count = quest.Count;
\r
704 if (!(count.Spec is QuestPowerup))
\r
706 IncrementCount(count);
\r
710 public void InspectStop(string request)
\r
712 var values = HttpUtility.ParseQueryString(request);
\r
713 _quests.Remove(int.Parse(values["api_quest_id"]));
\r
717 public void InspectClearItemGet(string request)
\r
719 var values = HttpUtility.ParseQueryString(request);
\r
720 var id = int.Parse(values["api_quest_id"]);
\r
721 _countList.Remove(id);
\r
722 _quests.Remove(id);
\r
726 public bool NeedSave { get; private set; }
\r
728 public void SaveState(Status status)
\r
731 status.QuestLastReset = _lastReset;
\r
732 if (_quests != null)
\r
733 status.QuestList = _quests.Values.ToArray();
\r
734 if (_countList != null)
\r
735 status.QuestCountList = _countList.CountList.ToArray();
\r
738 public void LoadState(Status status)
\r
740 _lastReset = status.QuestLastReset;
\r
741 if (status.QuestCountList != null)
\r
742 _countList.CountList = status.QuestCountList;
\r
743 if (status.QuestList != null)
\r
746 foreach (var q in status.QuestList)
\r
747 AddQuest(q.Id, q.Category, q.Name, q.Detail, q.Material, q.Progress, false);
\r