using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Newtonsoft.Json.Linq;
namespace XFEWarframe.Desktop.Editing;
public partial class RivenStatRow : ObservableObject
{
private readonly Action<RivenStatRow> remove;
public RivenStatRow(IReadOnlyList<RivenStatOption> tags, Action<RivenStatRow> remove)
{
this.remove = remove;
Tags = tags.Select(x => new RivenStatOption(x.Key, x.Label, x.ColorKey)).ToArray();
SelectedTag = Tags.FirstOrDefault();
}
public IReadOnlyList<RivenStatOption> Tags { get; }
public IReadOnlyList<string> Modes { get; } = ["品质(9000–11000)", "实际数值"];
[ObservableProperty, NotifyPropertyChangedFor(nameof(Tone))] public partial RivenStatOption? SelectedTag { get; set; }
[ObservableProperty, NotifyPropertyChangedFor(nameof(Tone))] public partial bool Negative { get; set; }
[ObservableProperty] public partial int ModeIndex { get; set; }
[ObservableProperty] public partial double Value { get; set; } = 10000;
[ObservableProperty] public partial string Result { get; set; } = "";
[ObservableProperty] public partial string Quality { get; set; } = "";
public string Tone => Negative ? "negative" : SelectedTag?.ColorKey ?? "";
private double? displayedValue, rollValue;
partial void OnModeIndexChanged(int value)
{
if ((value == 1 ? displayedValue : rollValue) is double converted) Value = converted;
}
partial void OnSelectedTagChanged(RivenStatOption? value)
{
if (ModeIndex == 1 && value?.DisplayValue is double converted) Value = converted;
}
public void ResetResult()
{
Result = Quality = "";
// Keep the last calculated numeric choices while the user types a new selection.
foreach (var option in Tags) { option.DisplayText = option.Label; option.Tone = Negative ? "negative" : option.ColorKey; }
}
public void ApplyResult(JToken result)
{
Result = result.Value<string>("text") ?? $"{result.Value<double>("displayValue"):+0.##;-0.##;0} {SelectedTag?.Label}";
displayedValue = result.Value<double>("displayValue"); rollValue = result.Value<double>("roll");
Quality = $"{result.Value<string>("grade")} · {UiText.Translate("品质")} {result.Value<double>("roll"):0.##}";
foreach (var data in result["options"] ?? new JArray())
if (Tags.FirstOrDefault(x => x.Key == data.Value<string>("key")) is { } option)
{ option.DisplayText = data.Value<string>("text") ?? option.Label; option.DisplayValue = data.Value<double?>("displayValue"); option.Tone = Negative ? "negative" : option.ColorKey; }
}
private JObject? original;
private double originalValue;
public void Retain(JObject row) { original = (JObject)row.DeepClone(); originalValue = Value; }
public object Request() => new { tag = SelectedTag?.Key ?? "", negative = Negative, mode = ModeIndex == 1 ? "stat" : "roll", value = Value,
originalRow = original, encodedValue = ModeIndex == 0 && Value == originalValue && SelectedTag?.Key == original?.Value<string>("Tag") ? original?.Value<long?>("Value") : null };
[RelayCommand] private void Remove() => remove(this);
}
public partial class RivenStatOption(string key, string label, string colorKey) : ObservableObject
{
public string Key { get; } = key;
public string Label { get; } = label;
public string ColorKey { get; } = colorKey;
public override string ToString() => Label;
public double? DisplayValue { get; set; }
[ObservableProperty] public partial string DisplayText { get; set; } = label;
[ObservableProperty] public partial string Tone { get; set; } = colorKey;
public static RivenStatOption FromJson(JToken value) => new(value.Value<string>("key")!, value.Value<string>("label")!, value.Value<string>("color") ?? "");
}
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Newtonsoft.Json.Linq;
namespace XFEWarframe.Desktop.Editing;
public partial class RivenStatRow : ObservableObject
{
private readonly Action<RivenStatRow> remove;
public RivenStatRow(IReadOnlyList<RivenStatOption> tags, Action<RivenStatRow> remove)
{
this.remove = remove;
Tags = tags.Select(x => new RivenStatOption(x.Key, x.Label, x.ColorKey)).ToArray();
SelectedTag = Tags.FirstOrDefault();
}
public IReadOnlyList<RivenStatOption> Tags { get; }
public IReadOnlyList<string> Modes { get; } = ["品质(9000–11000)", "实际数值"];
[ObservableProperty, NotifyPropertyChangedFor(nameof(Tone))] public partial RivenStatOption? SelectedTag { get; set; }
[ObservableProperty, NotifyPropertyChangedFor(nameof(Tone))] public partial bool Negative { get; set; }
[ObservableProperty] public partial int ModeIndex { get; set; }
[ObservableProperty] public partial double Value { get; set; } = 10000;
[ObservableProperty] public partial string Result { get; set; } = "";
[ObservableProperty] public partial string Quality { get; set; } = "";
public string Tone => Negative ? "negative" : SelectedTag?.ColorKey ?? "";
private double? displayedValue, rollValue;
partial void OnModeIndexChanged(int value)
{
if ((value == 1 ? displayedValue : rollValue) is double converted) Value = converted;
}
partial void OnSelectedTagChanged(RivenStatOption? value)
{
if (ModeIndex == 1 && value?.DisplayValue is double converted) Value = converted;
}
public void ResetResult()
{
Result = Quality = "";
// Keep the last calculated numeric choices while the user types a new selection.
foreach (var option in Tags) { option.DisplayText = option.Label; option.Tone = Negative ? "negative" : option.ColorKey; }
}
public void ApplyResult(JToken result)
{
Result = result.Value<string>("text") ?? $"{result.Value<double>("displayValue"):+0.##;-0.##;0} {SelectedTag?.Label}";
displayedValue = result.Value<double>("displayValue"); rollValue = result.Value<double>("roll");
Quality = $"{result.Value<string>("grade")} · {UiText.Translate("品质")} {result.Value<double>("roll"):0.##}";
foreach (var data in result["options"] ?? new JArray())
if (Tags.FirstOrDefault(x => x.Key == data.Value<string>("key")) is { } option)
{ option.DisplayText = data.Value<string>("text") ?? option.Label; option.DisplayValue = data.Value<double?>("displayValue"); option.Tone = Negative ? "negative" : option.ColorKey; }
}
private JObject? original;
private double originalValue;
public void Retain(JObject row) { original = (JObject)row.DeepClone(); originalValue = Value; }
public object Request() => new { tag = SelectedTag?.Key ?? "", negative = Negative, mode = ModeIndex == 1 ? "stat" : "roll", value = Value,
originalRow = original, encodedValue = ModeIndex == 0 && Value == originalValue && SelectedTag?.Key == original?.Value<string>("Tag") ? original?.Value<long?>("Value") : null };
[RelayCommand] private void Remove() => remove(this);
}
public partial class RivenStatOption(string key, string label, string colorKey) : ObservableObject
{
public string Key { get; } = key;
public string Label { get; } = label;
public string ColorKey { get; } = colorKey;
public override string ToString() => Label;
public double? DisplayValue { get; set; }
[ObservableProperty] public partial string DisplayText { get; set; } = label;
[ObservableProperty] public partial string Tone { get; set; } = colorKey;
public static RivenStatOption FromJson(JToken value) => new(value.Value<string>("key")!, value.Value<string>("label")!, value.Value<string>("color") ?? "");
}