private readonly Config _config = new Config();\r
private readonly ConfigDialog _configDialog;\r
private readonly ProxyManager _proxyManager;\r
+ private readonly ToolTip _toolTip = new ToolTip {ShowAlways = true};\r
private int _currentFleet;\r
private bool _combinedFleet;\r
private readonly Label[] _labelCheckFleets;\r
private readonly ListForm _listForm;\r
private readonly NotificationManager _notificationManager;\r
private bool _started;\r
+ private bool _timerEnabled;\r
private string _debugLogFile;\r
private IEnumerator<string> _playLog;\r
+ private DateTime _prev, _now;\r
\r
private readonly ErrorDialog _errorDialog = new ErrorDialog();\r
- private bool _missionFinishTimeMode;\r
- private bool _ndockFinishTimeMode;\r
- private readonly KancolleDb _kancolleDb = new KancolleDb();\r
private readonly ErrorLog _errorLog;\r
\r
public MainForm()\r
panelRepairList.CreateLabels(panelRepairList_Click);\r
labelPresetAkashiTimer.BackColor = ShipLabels.ColumnColors[1];\r
_listForm = new ListForm(_sniffer, _config) {Owner = this};\r
- _notificationManager = new NotificationManager(Ring);\r
+ _notificationManager = new NotificationManager(Alarm);\r
try\r
{\r
_config.Load();\r
WriteDebugLog(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
ProcessRequestMain(url, request, response);\r
if (_errorDialog.ShowDialog(this,\r
"艦これに仕様変更があったか、受信内容が壊れています。",\r
_errorLog.GenerateErrorLog(url, request, response, e.ToString())) == DialogResult.Abort)\r
- Application.Exit();\r
+ Exit();\r
}\r
catch (LogIOException e)\r
{\r
// ReSharper disable once PossibleNullReferenceException\r
if (_errorDialog.ShowDialog(this, e.Message, e.InnerException.ToString()) == DialogResult.Abort)\r
- Application.Exit();\r
+ Exit();\r
}\r
catch (BattleResultError)\r
{\r
if (_errorDialog.ShowDialog(this, "戦闘結果の計算に誤りがあります。",\r
_errorLog.GenerateBattleErrorLog()) == DialogResult.Abort)\r
- Application.Exit();\r
+ Exit();\r
}\r
catch (Exception e)\r
{\r
if (_errorDialog.ShowDialog(this, "エラーが発生しました。",\r
_errorLog.GenerateErrorLog(url, request, response, e.ToString())) == DialogResult.Abort)\r
- Application.Exit();\r
+ Exit();\r
}\r
}\r
\r
+ private void Exit()\r
+ {\r
+ _proxyManager.Shutdown();\r
+ Environment.Exit(1);\r
+ }\r
+\r
private void WriteDebugLog(string url, string request, string response)\r
{\r
if (_debugLogFile != null)\r
}\r
if (!_started)\r
return;\r
+ if (_now == DateTime.MinValue)\r
+ _now = DateTime.Now;\r
if ((update & Sniffer.Update.Item) != 0)\r
UpdateItemInfo();\r
if ((update & Sniffer.Update.Timer) != 0)\r
ApplyDebugLogSetting();\r
ApplyLogSetting();\r
ApplyProxySetting();\r
- if (_config.KancolleDb.On)\r
- _kancolleDb.Start(_config.KancolleDb.Token);\r
CheckVersionUp((current, latest) =>\r
{\r
if (double.Parse(latest) <= double.Parse(current))\r
_config.ShipList.Visible = _listForm.Visible && _listForm.WindowState == FormWindowState.Normal;\r
_config.Save();\r
_proxyManager.Shutdown();\r
- _kancolleDb.Stop();\r
}\r
\r
private void MainForm_Resize(object sender, EventArgs e)\r
foreach (var control in new Control[]\r
{\r
this, _listForm, labelLogin, linkLabelGuide,\r
- _configDialog, contextMenuStripMain, _errorDialog\r
+ _configDialog, _configDialog.NotificationConfigDialog,\r
+ contextMenuStripMain, _errorDialog\r
})\r
{\r
control.Font = new Font(control.Font.FontFamily, control.Font.Size * _config.Zoom / 100);\r
_sniffer.Achievement.ResetHours = _config.ResetHours;\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
\r
private void timerMain_Tick(object sender, EventArgs e)\r
{\r
- if (_started)\r
+ if (_timerEnabled)\r
{\r
try\r
{\r
+ _now = DateTime.Now;\r
UpdateTimers();\r
+ NotifyTimers();\r
+ _prev = _now;\r
}\r
catch (Exception ex)\r
{\r
{\r
UpdateNumOfShips();\r
UpdateNumOfEquips();\r
+ _notificationManager.Flash();\r
labelNumOfBuckets.Text = _sniffer.Material.MaterialHistory[(int)Material.Bucket].Now.ToString("D");\r
UpdateBucketHistory();\r
var ac = _sniffer.Achievement.Value;\r
var item = _sniffer.Item;\r
labelNumOfShips.Text = $"{item.NowShips:D}/{item.MaxShips:D}";\r
labelNumOfShips.ForeColor = item.TooManyShips ? CUDColor.Red : Color.Black;\r
- if (item.RingShips)\r
+ if (item.AlarmShips)\r
{\r
var message = $"残り{_sniffer.Item.MaxShips - _sniffer.Item.NowShips:D}隻";\r
_notificationManager.Enqueue("艦娘数超過", message);\r
- item.RingShips = false;\r
+ item.AlarmShips = false;\r
}\r
}\r
\r
var item = _sniffer.Item;\r
labelNumOfEquips.Text = $"{item.NowEquips:D}/{item.MaxEquips:D}";\r
labelNumOfEquips.ForeColor = item.TooManyEquips ? CUDColor.Red : Color.Black;\r
- if (item.RingEquips)\r
+ if (item.AlarmEquips)\r
{\r
var message = $"残り{_sniffer.Item.MaxEquips - _sniffer.Item.NowEquips:D}個";\r
_notificationManager.Enqueue("装備数超過", message);\r
- item.RingEquips = false;\r
+ item.AlarmEquips = false;\r
}\r
}\r
\r
\r
private void NotifyDamagedShip()\r
{\r
- if (_sniffer.BadlyDamagedShips.Any())\r
- _notificationManager.Enqueue("大破警告", string.Join(" ", _sniffer.BadlyDamagedShips));\r
- }\r
-\r
- private void NotifyAkashiTimer()\r
- {\r
- var akashi = _sniffer.AkashiTimer;\r
- var msgs = akashi.GetNotice();\r
- if (msgs.Length == 0)\r
- {\r
- _notificationManager.StopRepeat("泊地修理");\r
- return;\r
- }\r
- if (!akashi.CheckReparing() && !(akashi.CheckPresetReparing() && _config.UsePresetAkashi))\r
- {\r
- _notificationManager.StopRepeat("泊地修理");\r
+ if (!_sniffer.BadlyDamagedShips.Any())\r
return;\r
- }\r
- if (msgs[0].Proceeded == "20分経過しました。")\r
- {\r
- SetNotification("泊地修理20分経過", msgs[0].Proceeded);\r
- msgs[0].Proceeded = "";\r
- // 修理完了がいるかもしれないので続ける\r
- }\r
- for (var i = 0; i < ShipInfo.FleetCount; i++)\r
- {\r
- if (msgs[i].Proceeded != "")\r
- SetNotification("泊地修理進行", i, msgs[i].Proceeded);\r
- if (msgs[i].Completed != "")\r
- SetNotification("泊地修理完了", i, msgs[i].Completed);\r
- }\r
+ _notificationManager.Enqueue("大破警告", string.Join(" ", _sniffer.BadlyDamagedShips));\r
+ _notificationManager.Flash();\r
}\r
\r
public void UpdateFighterPower(bool combined)\r
private void UpdateBattleInfo()\r
{\r
ResetBattleInfo();\r
+ _listForm.UpdateBattleResult();\r
if (_sniffer.Battle.BattleState == BattleState.None)\r
return;\r
panelBattleInfo.BringToFront();\r
var battle = _sniffer.Battle;\r
- labelFormation.Text = battle.Formation;\r
+ labelFormation.Text = new[] {"同航戦", "反航戦", "T字有利", "T字不利"}[battle.Formation[2] - 1];\r
UpdateBattleFighterPower();\r
- if (_config.AlwaysShowResultRank)\r
+ if ((_config.Spoilers & Spoiler.ResultRank) != 0)\r
ShowResultRank();\r
if (_sniffer.Battle.BattleState == BattleState.Day)\r
_listForm.UpdateAirBattleResult();\r
\r
private void labelNDock_Click(object sender, EventArgs e)\r
{\r
- _ndockFinishTimeMode = !_ndockFinishTimeMode;\r
+ _config.ShowEndTime ^= TimerKind.NDock;\r
UpdateTimers();\r
}\r
\r
\r
private void labelMission_Click(object sender, EventArgs e)\r
{\r
- _missionFinishTimeMode = !_missionFinishTimeMode;\r
+ _config.ShowEndTime ^= TimerKind.Mission;\r
UpdateTimers();\r
}\r
\r
for (var i = 0; i < mission.Length; i++)\r
{\r
var entry = _sniffer.Missions[i];\r
- entry.Timer.Update();\r
- SetTimerColor(mission[i], entry.Timer);\r
- mission[i].Text = entry.Timer.ToString(_missionFinishTimeMode);\r
- if (!entry.Timer.NeedRing)\r
- continue;\r
- SetNotification("遠征終了", i + 1, entry.Name);\r
- entry.Timer.NeedRing = false;\r
+ SetTimerColor(mission[i], entry.Timer, _now);\r
+ mission[i].Text = entry.Timer.ToString(_now, (_config.ShowEndTime & TimerKind.Mission) != 0);\r
}\r
for (var i = 0; i < _sniffer.NDock.Length; i++)\r
{\r
var entry = _sniffer.NDock[i];\r
- entry.Timer.Update();\r
- _shipLabels.SetNDockTimer(i, entry.Timer, _ndockFinishTimeMode);\r
- if (!entry.Timer.NeedRing)\r
- continue;\r
- SetNotification("入渠終了", i, entry.Name);\r
- entry.Timer.NeedRing = false;\r
+ _shipLabels.SetNDockTimer(i, entry.Timer, _now, (_config.ShowEndTime & TimerKind.NDock) != 0);\r
}\r
var kdock = new[] {labelConstruct1, labelConstruct2, labelConstruct3, labelConstruct4};\r
for (var i = 0; i < kdock.Length; i++)\r
{\r
var timer = _sniffer.KDock[i];\r
- timer.Update();\r
- SetTimerColor(kdock[i], timer);\r
-\r
- kdock[i].Text = timer.ToString();\r
- if (!timer.NeedRing)\r
- continue;\r
- SetNotification("建造完了", $"第{i + 1:D}ドック");\r
- timer.NeedRing = false;\r
+ SetTimerColor(kdock[i], timer, _now);\r
+ kdock[i].Text = timer.ToString(_now);\r
}\r
UpdateCondTimers();\r
UpdateAkashiTimer();\r
+ _timerEnabled = true;\r
}\r
\r
- private void SetTimerColor(Label label, RingTimer timer)\r
+ private void NotifyTimers()\r
{\r
- label.ForeColor = timer.IsFinished ? CUDColor.Red : Color.Black;\r
+ for (var i = 0; i < _sniffer.Missions.Length; i++)\r
+ {\r
+ var entry = _sniffer.Missions[i];\r
+ CheckAlarm("遠征終了", entry.Timer, i + 1, entry.Name);\r
+ }\r
+ for (var i = 0; i < _sniffer.NDock.Length; i++)\r
+ {\r
+ var entry = _sniffer.NDock[i];\r
+ CheckAlarm("入渠終了", entry.Timer, i, entry.Name);\r
+ }\r
+ for (var i = 0; i < _sniffer.KDock.Length; i++)\r
+ {\r
+ var timer = _sniffer.KDock[i];\r
+ CheckAlarm("建造完了", timer, 0, $"第{i + 1:D}ドック");\r
+ }\r
+ NotifyCondTimers();\r
+ NotifyAkashiTimer();\r
+ _notificationManager.Flash();\r
+ }\r
+\r
+ private void CheckAlarm(string key, AlarmTimer timer, int fleet, string subject)\r
+ {\r
+ if (timer.CheckAlarm(_prev, _now))\r
+ {\r
+ SetNotification(key, fleet, subject);\r
+ return;\r
+ }\r
+ var pre = TimeSpan.FromSeconds(_config.Notifications[key].PreliminaryPeriod);\r
+ if (pre == TimeSpan.Zero)\r
+ return;\r
+ if (timer.CheckAlarm(_prev + pre, _now + pre))\r
+ SetPreNotification(key, fleet, subject);\r
+ }\r
+\r
+ private void SetTimerColor(Label label, AlarmTimer timer, DateTime now)\r
+ {\r
+ label.ForeColor = timer.IsFinished(now) ? CUDColor.Red : Color.Black;\r
}\r
\r
private void UpdateCondTimers()\r
{\r
timer = _sniffer.GetConditionTimer(_currentFleet);\r
}\r
- var now = DateTime.Now;\r
if (timer == DateTime.MinValue)\r
{\r
labelCondTimerTitle.Text = "";\r
labelCondTimer.Text = "";\r
return;\r
}\r
- var span = TimeSpan.FromSeconds(Ceiling((timer - now).TotalSeconds));\r
+ var span = TimeSpan.FromSeconds(Ceiling((timer - _now).TotalSeconds));\r
if (span >= TimeSpan.FromMinutes(9))\r
{\r
labelCondTimerTitle.Text = "cond40まで";\r
labelCondTimer.Text = (span >= TimeSpan.Zero ? span : TimeSpan.Zero).ToString(@"mm\:ss");\r
labelCondTimer.ForeColor = span <= TimeSpan.Zero ? CUDColor.Red : DefaultForeColor;\r
}\r
- var notice = _sniffer.GetConditionNotice();\r
- if (notice == null)\r
- return;\r
- for (var i = 0; i < ShipInfo.FleetCount; i++)\r
- {\r
- if (!_config.NotifyConditions.Contains(notice[i]))\r
- return;\r
- SetNotification("疲労回復" + notice[i], i, "cond" + notice[i]);\r
- }\r
- }\r
-\r
- private void SetNotification(string key, string subject)\r
- {\r
- SetNotification(key, 0, subject);\r
}\r
\r
- private void SetNotification(string key, int fleet, string subject)\r
+ private void NotifyCondTimers()\r
{\r
- var spec = _config.Notifications[_notificationManager.KeyToName(key)];\r
- _notificationManager.Enqueue(key, fleet, subject,\r
- (spec.Flags & _config.NotificationFlags & NotificationType.Repeat) == 0 ? 0 : spec.RepeatInterval);\r
+ var notice = _sniffer.GetConditionNotice(_prev, _now);\r
+ var pre = TimeSpan.FromSeconds(_config.Notifications["疲労回復"].PreliminaryPeriod);\r
+ var preNotice = pre == TimeSpan.Zero\r
+ ? new int[ShipInfo.FleetCount]\r
+ : _sniffer.GetConditionNotice(_prev + pre, _now + pre);\r
+ for (var i = 0; i < ShipInfo.FleetCount; i++)\r
+ {\r
+ if (_config.NotifyConditions.Contains(notice[i]))\r
+ {\r
+ SetNotification("疲労回復" + notice[i], i, "cond" + notice[i]);\r
+ }\r
+ else if (_config.NotifyConditions.Contains(preNotice[i]))\r
+ {\r
+ SetPreNotification("疲労回復" + preNotice[i], i, "cond" + notice[i]);\r
+ }\r
+ }\r
}\r
\r
private void UpdateAkashiTimer()\r
var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
_shipLabels.SetAkashiTimer(statuses,\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
- var color = span == TimeSpan.Zero && akashi.CheckPresetReparing() ? CUDColor.Red : DefaultForeColor;\r
+ var color = span == TimeSpan.Zero && akashi.CheckPresetRepairing() ? CUDColor.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
+ if (akashi.CheckPresetRepairing() && !akashi.CheckRepairing(_currentFleet))\r
{\r
labelPresetAkashiTimer.ForeColor = color;\r
labelPresetAkashiTimer.Text = text;\r
}\r
}\r
\r
+ private void NotifyAkashiTimer()\r
+ {\r
+ var akashi = _sniffer.AkashiTimer;\r
+ var msgs = akashi.GetNotice(_prev, _now);\r
+ if (msgs.Length == 0)\r
+ {\r
+ _notificationManager.StopRepeat("泊地修理");\r
+ return;\r
+ }\r
+ if (!akashi.CheckRepairing() && !(akashi.CheckPresetRepairing() && _config.UsePresetAkashi))\r
+ {\r
+ _notificationManager.StopRepeat("泊地修理");\r
+ return;\r
+ }\r
+ var skipPreliminary = false;\r
+ if (msgs[0].Proceeded == "20分経過しました。")\r
+ {\r
+ SetNotification("泊地修理20分経過", msgs[0].Proceeded);\r
+ msgs[0].Proceeded = "";\r
+ skipPreliminary = true;\r
+ // 修理完了がいるかもしれないので続ける\r
+ }\r
+ for (var i = 0; i < ShipInfo.FleetCount; i++)\r
+ {\r
+ if (msgs[i].Proceeded != "")\r
+ SetNotification("泊地修理進行", i, msgs[i].Proceeded);\r
+ if (msgs[i].Completed != "")\r
+ SetNotification("泊地修理完了", i, msgs[i].Completed);\r
+ }\r
+ var pre = TimeSpan.FromSeconds(_config.Notifications["泊地修理20分経過"].PreliminaryPeriod);\r
+ if (skipPreliminary || pre == TimeSpan.Zero)\r
+ return;\r
+ if ((msgs = akashi.GetNotice(_prev + pre, _now + pre))[0].Proceeded == "20分経過しました。")\r
+ SetPreNotification("泊地修理20分経過", 0, msgs[0].Proceeded);\r
+ }\r
+\r
+ private void SetNotification(string key, string subject)\r
+ {\r
+ SetNotification(key, 0, subject);\r
+ }\r
+\r
+ private void SetNotification(string key, int fleet, string subject)\r
+ {\r
+ var spec = _config.Notifications[_notificationManager.KeyToName(key)];\r
+ _notificationManager.Enqueue(key, fleet, subject,\r
+ (spec.Flags & _config.NotificationFlags & NotificationType.Repeat) == 0 ? 0 : spec.RepeatInterval);\r
+ }\r
+\r
+ private void SetPreNotification(string key, int fleet, string subject)\r
+ {\r
+ var spec = _config.Notifications[_notificationManager.KeyToName(key)];\r
+ if ((spec.Flags & NotificationType.Preliminary) != 0)\r
+ _notificationManager.Enqueue(key, fleet, subject, 0, true);\r
+ }\r
+\r
private void UpdateRepairList()\r
{\r
panelRepairList.SetRepairList(_sniffer.RepairList);\r
labelQuestColor6\r
};\r
var name = new[] {labelQuest1, labelQuest2, labelQuest3, labelQuest4, labelQuest5, labelQuest6};\r
+ var count = new[]\r
+ {\r
+ labelQuestCount1, labelQuestCount2, labelQuestCount3, labelQuestCount4, labelQuestCount5,\r
+ labelQuestCount6\r
+ };\r
var progress = new[]\r
{labelProgress1, labelProgress2, labelProgress3, labelProgress4, labelProgress5, labelProgress6};\r
var quests = _sniffer.Quests;\r
category[i].BackColor = quests[i].Color;\r
name[i].Text = quests[i].Name;\r
progress[i].Text = $"{quests[i].Progress:D}%";\r
+ var c = quests[i].Count;\r
+ if (c.Id == 0)\r
+ {\r
+ count[i].Text = "";\r
+ count[i].ForeColor = Color.Black;\r
+ _toolTip.SetToolTip(count[i], "");\r
+ continue;\r
+ }\r
+ count[i].Text = " " + c;\r
+ count[i].ForeColor = c.Cleared ? CUDColor.Green : Color.Black;\r
+ _toolTip.SetToolTip(count[i], c.ToToolTip());\r
}\r
else\r
{\r
category[i].BackColor = DefaultBackColor;\r
- name[i].Text = progress[i].Text = "";\r
+ name[i].Text = count[i].Text = progress[i].Text = "";\r
+ _toolTip.SetToolTip(count[i], "");\r
}\r
}\r
}\r
\r
- private void Ring(string balloonTitle, string balloonMessage, string name)\r
+ private void Alarm(string balloonTitle, string balloonMessage, string name)\r
{\r
var flags = _config.Notifications[name].Flags;\r
var effective = _config.NotificationFlags & _config.Notifications[name].Flags;\r
Process.Start("http://localhost:" + _config.Proxy.Listen + "/");\r
}\r
\r
+ private void labelClearQuest_Click(object sender, EventArgs e)\r
+ {\r
+ _sniffer.ClearQuests();\r
+ UpdateQuestList();\r
+ }\r
+\r
+ private void labelClearQuest_MouseDown(object sender, MouseEventArgs e)\r
+ {\r
+ labelClearQuest.BackColor = _activeButtonColor;\r
+ }\r
+\r
+ private void labelClearQuest_MouseUp(object sender, MouseEventArgs e)\r
+ {\r
+ labelClearQuest.BackColor = DefaultBackColor;\r
+ }\r
+\r
private void CaptureToolStripMenuItem_Click(object sender, EventArgs e)\r
{\r
try\r