//
// MaaWpfGui - A part of the MaaCoreArknights project
// Copyright (C) 2021 MistEO and Contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License v3.0 only as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
//
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using MaaWpfGui.Constants;
using MaaWpfGui.Helper;
using MaaWpfGui.Utilities.ValueType;
namespace MaaWpfGui.ViewModels.UserControl.TaskQueue;
///
/// 刷理智
///
public class FightSettingsUserControlModel : TaskViewModel
{
static FightSettingsUserControlModel()
{
Instance = new();
}
public static FightSettingsUserControlModel Instance { get; }
private ObservableCollection _stageList = [];
///
/// Gets or private sets the list of stages.
///
public ObservableCollection StageList
{
get => _stageList;
private set => SetAndNotify(ref _stageList, value);
}
private ObservableCollection _remainingSanityStageList = [];
public ObservableCollection RemainingSanityStageList
{
get => _remainingSanityStageList;
private set => SetAndNotify(ref _remainingSanityStageList, value);
}
///
/// Gets the stage.
///
public string Stage
{
get
{
Stage1 ??= _stage1Fallback;
if (!UseAlternateStage)
{
return Stage1;
}
if (Instances.TaskQueueViewModel.IsStageOpen(Stage1))
{
return Stage1;
}
if (Instances.TaskQueueViewModel.IsStageOpen(Stage2))
{
return Stage2;
}
return Instances.TaskQueueViewModel.IsStageOpen(Stage3) ? Stage3 : Stage1;
}
}
private readonly Dictionary _stageDictionary = new()
{
{ "AN", "Annihilation" },
{ "剿灭", "Annihilation" },
{ "CE", "CE-6" },
{ "龙门币", "CE-6" },
{ "LS", "LS-6" },
{ "经验", "LS-6" },
{ "狗粮", "LS-6" },
{ "CA", "CA-5" },
{ "技能", "CA-5" },
{ "AP", "AP-5" },
{ "红票", "AP-5" },
{ "SK", "SK-5" },
{ "碳", "SK-5" },
{ "炭", "SK-5" },
};
///
/// Gets or private sets the list of series.
///
public List SeriesList { get; private set; } = ["1", "2", "3", "4", "5", "6"];
public string?[] Stages => [Stage1, Stage2, Stage3];
/// Try to fix: issues#5742. 关卡选择为 null 时的一个补丁,可能是 StageList 改变后,wpf binding 延迟更新的问题。
public string _stage1Fallback = ConfigurationHelper.GetValue(ConfigurationKeys.Stage1, string.Empty) ?? string.Empty;
private string? _stage1 = ConfigurationHelper.GetValue(ConfigurationKeys.Stage1, string.Empty) ?? string.Empty;
///
/// Gets or sets the stage1.
///
public string? Stage1
{
get => _stage1;
set
{
if (_stage1 == value)
{
SetAndNotify(ref _stage1, value);
return;
}
if (CustomStageCode)
{
// 从后往前删
if (_stage1?.Length != 3 && value != null)
{
value = ToUpperAndCheckStage(value);
}
}
SetAndNotify(ref _stage1, value);
Instances.TaskQueueViewModel.SetFightParams();
ConfigurationHelper.SetValue(ConfigurationKeys.Stage1, value);
Instances.TaskQueueViewModel.UpdateDatePrompt();
}
}
private string _stage2 = ConfigurationHelper.GetValue(ConfigurationKeys.Stage2, string.Empty) ?? string.Empty;
///
/// Gets or sets the stage2.
///
public string Stage2
{
get => _stage2;
set
{
if (_stage2 == value)
{
SetAndNotify(ref _stage2, value);
return;
}
if (CustomStageCode)
{
if (_stage2?.Length != 3 && value != null)
{
value = ToUpperAndCheckStage(value);
}
}
SetAndNotify(ref _stage2, value);
Instances.TaskQueueViewModel.SetFightParams();
ConfigurationHelper.SetValue(ConfigurationKeys.Stage2, value);
Instances.TaskQueueViewModel.UpdateDatePrompt();
}
}
private string _stage3 = ConfigurationHelper.GetValue(ConfigurationKeys.Stage3, string.Empty) ?? string.Empty;
///
/// Gets or sets the stage2.
///
public string Stage3
{
get => _stage3;
set
{
if (_stage3 == value)
{
SetAndNotify(ref _stage3, value);
return;
}
if (CustomStageCode)
{
if (_stage3?.Length != 3 && value != null)
{
value = ToUpperAndCheckStage(value);
}
}
SetAndNotify(ref _stage3, value);
Instances.TaskQueueViewModel.SetFightParams();
ConfigurationHelper.SetValue(ConfigurationKeys.Stage3, value);
Instances.TaskQueueViewModel.UpdateDatePrompt();
}
}
private bool _useRemainingSanityStage = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.UseRemainingSanityStage, bool.TrueString));
public bool UseRemainingSanityStage
{
get => _useRemainingSanityStage;
set
{
SetAndNotify(ref _useRemainingSanityStage, value);
ConfigurationHelper.SetValue(ConfigurationKeys.UseRemainingSanityStage, value.ToString());
}
}
private bool _customStageCode = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.CustomStageCode, bool.FalseString));
///
/// Gets or sets a value indicating whether to use custom stage code.
///
public bool CustomStageCode
{
get => _customStageCode;
set
{
SetAndNotify(ref _customStageCode, value);
ConfigurationHelper.SetValue(ConfigurationKeys.CustomStageCode, value.ToString());
}
}
private string _remainingSanityStage = ConfigurationHelper.GetValue(ConfigurationKeys.RemainingSanityStage, string.Empty) ?? string.Empty;
public string RemainingSanityStage
{
get => _remainingSanityStage;
set
{
if (_remainingSanityStage == value)
{
SetAndNotify(ref _remainingSanityStage, value);
return;
}
if (CustomStageCode)
{
if (_remainingSanityStage?.Length != 3 && value != null)
{
value = ToUpperAndCheckStage(value);
}
}
SetAndNotify(ref _remainingSanityStage, value);
Instances.TaskQueueViewModel.SetFightRemainingSanityParams();
ConfigurationHelper.SetValue(ConfigurationKeys.RemainingSanityStage, value);
}
}
///
/// Reset unsaved battle parameters.
///
public void ResetFightVariables()
{
if (UseStoneWithNull == null)
{
UseStone = false;
}
if (UseMedicineWithNull == null)
{
UseMedicine = false;
}
if (HasTimesLimitedWithNull == null)
{
HasTimesLimited = false;
}
if (IsSpecifiedDropsWithNull == null)
{
IsSpecifiedDrops = false;
}
}
private bool? _useMedicineWithNull = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.UseMedicine, bool.FalseString));
///
/// Gets or sets a value indicating whether to use medicine with null.
///
public bool? UseMedicineWithNull
{
get => _useMedicineWithNull;
set
{
SetAndNotify(ref _useMedicineWithNull, value);
if (value == false)
{
UseStone = false;
}
Instances.TaskQueueViewModel.SetFightParams();
value ??= false;
ConfigurationHelper.SetValue(ConfigurationKeys.UseMedicine, value.ToString());
}
}
///
/// Gets or sets a value indicating whether to use medicine.
///
public bool UseMedicine
{
get => UseMedicineWithNull != false;
set => UseMedicineWithNull = value;
}
private string _medicineNumber = ConfigurationHelper.GetValue(ConfigurationKeys.UseMedicineQuantity, "999");
///
/// Gets or sets the amount of medicine used.
///
public string MedicineNumber
{
get => _medicineNumber;
set
{
if (_medicineNumber == value)
{
return;
}
SetAndNotify(ref _medicineNumber, value);
Instances.TaskQueueViewModel.SetFightParams();
ConfigurationHelper.SetValue(ConfigurationKeys.UseMedicineQuantity, MedicineNumber);
}
}
public static string UseStoneString => LocalizationHelper.GetString("UseOriginitePrime");
private bool? _useStoneWithNull = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.UseMedicine, bool.FalseString)) &&
Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.UseStone, bool.FalseString));
///
/// Gets or sets a value indicating whether to use originiums with null.
///
public bool? UseStoneWithNull
{
get => _useStoneWithNull;
set
{
if (!AllowUseStoneSave && value == true)
{
value = null;
}
SetAndNotify(ref _useStoneWithNull, value);
if (value != false)
{
MedicineNumber = "999";
if (!UseMedicine)
{
UseMedicineWithNull = value;
}
}
// IsEnabled="{c:Binding UseStone}"
NotifyOfPropertyChange(nameof(UseStone));
Instances.TaskQueueViewModel.SetFightParams();
if (AllowUseStoneSave)
{
ConfigurationHelper.SetValue(ConfigurationKeys.UseStone, (value ?? false).ToString());
}
}
}
///
/// Gets or sets a value indicating whether to use originiums.
///
// ReSharper disable once MemberCanBePrivate.Global
public bool UseStone
{
get => UseStoneWithNull != false;
set => UseStoneWithNull = value;
}
private string _stoneNumber = ConfigurationHelper.GetValue(ConfigurationKeys.UseStoneQuantity, "0");
///
/// Gets or sets the amount of originiums used.
///
public string StoneNumber
{
get => _stoneNumber;
set
{
if (_stoneNumber == value)
{
return;
}
SetAndNotify(ref _stoneNumber, value);
Instances.TaskQueueViewModel.SetFightParams();
ConfigurationHelper.SetValue(ConfigurationKeys.UseStoneQuantity, StoneNumber);
}
}
private bool? _hasTimesLimitedWithNull = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.TimesLimited, bool.FalseString));
///
/// Gets or sets a value indicating whether the number of times is limited with null.
///
public bool? HasTimesLimitedWithNull
{
get => _hasTimesLimitedWithNull;
set
{
SetAndNotify(ref _hasTimesLimitedWithNull, value);
Instances.TaskQueueViewModel.SetFightParams();
value ??= false;
ConfigurationHelper.SetValue(ConfigurationKeys.TimesLimited, value.ToString());
}
}
///
/// Gets or sets a value indicating whether the number of times is limited.
///
public bool HasTimesLimited
{
get => HasTimesLimitedWithNull != false;
set => HasTimesLimitedWithNull = value;
}
private string _maxTimes = ConfigurationHelper.GetValue(ConfigurationKeys.TimesLimitedQuantity, "5");
///
/// Gets or sets the max number of times.
///
public string MaxTimes
{
get => _maxTimes;
set
{
if (MaxTimes == value)
{
return;
}
SetAndNotify(ref _maxTimes, value);
Instances.TaskQueueViewModel.SetFightParams();
ConfigurationHelper.SetValue(ConfigurationKeys.TimesLimitedQuantity, MaxTimes);
}
}
private string _series = ConfigurationHelper.GetValue(ConfigurationKeys.SeriesQuantity, "1");
///
/// Gets or sets the max number of times.
///
// 所以为啥这玩意是 string 呢?改配置的时候把上面那些也都改成 int 吧
public string Series
{
get => _series;
set
{
if (_series == value)
{
return;
}
SetAndNotify(ref _series, value);
Instances.TaskQueueViewModel.SetFightParams();
ConfigurationHelper.SetValue(ConfigurationKeys.SeriesQuantity, value);
}
}
#region Drops
private bool? _isSpecifiedDropsWithNull = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.DropsEnable, bool.FalseString));
///
/// Gets or sets a value indicating whether the drops are specified.
///
public bool? IsSpecifiedDropsWithNull
{
get => _isSpecifiedDropsWithNull;
set
{
SetAndNotify(ref _isSpecifiedDropsWithNull, value);
Instances.TaskQueueViewModel.SetFightParams();
value ??= false;
ConfigurationHelper.SetValue(ConfigurationKeys.DropsEnable, value.ToString());
}
}
///
/// Gets or sets a value indicating whether the drops are specified.
///
public bool IsSpecifiedDrops
{
get => IsSpecifiedDropsWithNull != false;
set => IsSpecifiedDropsWithNull = value;
}
///
/// Gets the list of all drops.
///
private List AllDrops { get; } = new();
///
/// 关卡不可掉落的材料
///
private static readonly HashSet _excludedValues =
[
"3213", "3223", "3233", "3243", // 双芯片
"3253", "3263", "3273", "3283", // 双芯片
"7001", "7002", "7003", "7004", // 许可
"4004", "4005", // 凭证
"3105", "3131", "3132", "3233", // 龙骨/加固建材
"6001", // 演习券
"3141", "4002", // 源石
"32001", // 芯片助剂
"30115", // 聚合剂
"30125", // 双极纳米片
"30135", // D32钢
"30145", // 晶体电子单元
"30155", // 烧结核凝晶
];
public void InitDrops()
{
foreach (var (val, value) in ItemListHelper.ArkItems)
{
// 不是数字的东西都是正常关卡不会掉的(大概吧)
if (!int.TryParse(val, out _))
{
continue;
}
var dis = value.Name;
if (_excludedValues.Contains(val))
{
continue;
}
AllDrops.Add(new CombinedData { Display = dis, Value = val });
}
AllDrops.Sort((a, b) => string.Compare(a.Value, b.Value, StringComparison.Ordinal));
DropsList = new ObservableCollection(AllDrops);
}
///
/// Gets or private sets the list of drops.
///
public ObservableCollection DropsList { get; private set; } = [];
private string _dropsItemId = ConfigurationHelper.GetValue(ConfigurationKeys.DropsItemId, string.Empty);
///
/// Gets or sets the item ID of drops.
///
public string DropsItemId
{
get => _dropsItemId;
set
{
SetAndNotify(ref _dropsItemId, value);
Instances.TaskQueueViewModel.SetFightParams();
ConfigurationHelper.SetValue(ConfigurationKeys.DropsItemId, DropsItemId);
}
}
private string _dropsItemName = ConfigurationHelper.GetValue(ConfigurationKeys.DropsItemName, LocalizationHelper.GetString("NotSelected"));
///
/// Gets or sets the item Name of drops.
///
public string DropsItemName
{
get => _dropsItemName;
set
{
SetAndNotify(ref _dropsItemName, value);
Instances.TaskQueueViewModel.SetFightParams();
ConfigurationHelper.SetValue(ConfigurationKeys.DropsItemName, DropsItemName);
}
}
// UI 绑定的方法
// ReSharper disable once UnusedMember.Global
public void DropsListDropDownClosed()
{
foreach (var item in DropsList)
{
if (DropsItemName != item.Display)
{
continue;
}
DropsItemId = item.Value;
if (DropsItemName != item.Display || DropsItemId != item.Value)
{
DropsItemName = LocalizationHelper.GetString("NotSelected");
}
return;
}
DropsItemName = LocalizationHelper.GetString("NotSelected");
}
private string _dropsQuantity = ConfigurationHelper.GetValue(ConfigurationKeys.DropsQuantity, "5");
///
/// Gets or sets the quantity of drops.
///
public string DropsQuantity
{
get => _dropsQuantity;
set
{
SetAndNotify(ref _dropsQuantity, value);
Instances.TaskQueueViewModel.SetFightParams();
ConfigurationHelper.SetValue(ConfigurationKeys.DropsQuantity, DropsQuantity);
}
}
#endregion Drops
private bool _isDrGrandet = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.IsDrGrandet, bool.FalseString));
///
/// Gets or sets a value indicating whether to use DrGrandet mode.
///
public bool IsDrGrandet
{
get => _isDrGrandet;
set
{
SetAndNotify(ref _isDrGrandet, value);
ConfigurationHelper.SetValue(ConfigurationKeys.IsDrGrandet, value.ToString());
}
}
private bool _useAlternateStage = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.UseAlternateStage, bool.FalseString));
///
/// Gets or sets a value indicating whether to use alternate stage.
///
public bool UseAlternateStage
{
get => _useAlternateStage;
set
{
SetAndNotify(ref _useAlternateStage, value);
ConfigurationHelper.SetValue(ConfigurationKeys.UseAlternateStage, value.ToString());
if (value)
{
HideUnavailableStage = false;
}
}
}
private bool _allowUseStoneSave = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.AllowUseStoneSave, bool.FalseString));
public bool AllowUseStoneSave
{
get => _allowUseStoneSave;
set
{
if (value)
{
var result = MessageBoxHelper.Show(
LocalizationHelper.GetString("AllowUseStoneSaveWarning"),
LocalizationHelper.GetString("Warning"),
MessageBoxButton.YesNo,
MessageBoxImage.Warning,
no: LocalizationHelper.GetString("Confirm"),
yes: LocalizationHelper.GetString("Cancel"),
iconBrushKey: "DangerBrush");
if (result != MessageBoxResult.No)
{
return;
}
}
SetAndNotify(ref _allowUseStoneSave, value);
ConfigurationHelper.SetValue(ConfigurationKeys.AllowUseStoneSave, value.ToString());
}
}
private bool _useExpiringMedicine = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.UseExpiringMedicine, bool.FalseString));
public bool UseExpiringMedicine
{
get => _useExpiringMedicine;
set
{
SetAndNotify(ref _useExpiringMedicine, value);
ConfigurationHelper.SetValue(ConfigurationKeys.UseExpiringMedicine, value.ToString());
Instances.TaskQueueViewModel.SetFightParams();
}
}
private bool _hideUnavailableStage = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.HideUnavailableStage, bool.TrueString));
///
/// Gets or sets a value indicating whether to hide unavailable stages.
///
public bool HideUnavailableStage
{
get => _hideUnavailableStage;
set
{
SetAndNotify(ref _hideUnavailableStage, value);
ConfigurationHelper.SetValue(ConfigurationKeys.HideUnavailableStage, value.ToString());
if (value)
{
UseAlternateStage = false;
}
Instances.TaskQueueViewModel.UpdateStageList();
}
}
private bool _hideSeries = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.HideSeries, bool.FalseString));
///
/// Gets or sets a value indicating whether to hide series.
///
public bool HideSeries
{
get => _hideSeries;
set
{
SetAndNotify(ref _hideSeries, value);
ConfigurationHelper.SetValue(ConfigurationKeys.HideSeries, value.ToString());
}
}
private string ToUpperAndCheckStage(string value)
{
if (string.IsNullOrEmpty(value))
{
return value;
}
string upperValue = value.ToUpper();
if (_stageDictionary.TryGetValue(upperValue, out var stage))
{
return stage;
}
if (StageList == null)
{
return value;
}
foreach (var item in StageList)
{
if (upperValue == item.Value.ToUpper() || upperValue == item.Display.ToUpper())
{
return item.Value;
}
}
return value;
}
#region 双入口设置可见性
private bool _customInfrastPlanShowInFightSettings = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.CustomInfrastPlanShowInFightSettings, bool.FalseString));
public bool CustomInfrastPlanShowInFightSettings
{
get => _customInfrastPlanShowInFightSettings;
set
{
SetAndNotify(ref _customInfrastPlanShowInFightSettings, value);
ConfigurationHelper.SetValue(ConfigurationKeys.CustomInfrastPlanShowInFightSettings, value.ToString());
}
}
#endregion
}