Add violin plots for reliability

And move custom imraii stuff to imraii2
This commit is contained in:
Asriel Camora
2023-11-13 02:35:26 -08:00
parent f63483c9bd
commit bdce750238
10 changed files with 248 additions and 99 deletions
+1
View File
@@ -39,6 +39,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DalamudPackager" Version="2.1.12" /> <PackageReference Include="DalamudPackager" Version="2.1.12" />
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
<PackageReference Include="Meziantou.Analyzer" Version="2.0.106"> <PackageReference Include="Meziantou.Analyzer" Version="2.0.106">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+1 -1
View File
@@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
namespace Craftimizer; namespace Craftimizer.Plugin;
internal static unsafe class ImGuiExtras internal static unsafe class ImGuiExtras
{ {
+71 -31
View File
@@ -2,12 +2,16 @@ using Craftimizer.Utils;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using ImGuiNET; using ImGuiNET;
using ImPlotNET;
using MathNet.Numerics.Statistics;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -130,37 +134,6 @@ internal static class ImGuiUtils
ImGui.PopID(); ImGui.PopID();
} }
private struct EndUnconditionally : ImRaii.IEndObject, IDisposable
{
private Action EndAction { get; }
public bool Success { get; }
public bool Disposed { get; private set; }
public EndUnconditionally(Action endAction, bool success)
{
EndAction = endAction;
Success = success;
Disposed = false;
}
public void Dispose()
{
if (!Disposed)
{
EndAction();
Disposed = true;
}
}
}
public static ImRaii.IEndObject GroupPanel(string name, float width, out float internalWidth)
{
internalWidth = BeginGroupPanel(name, width);
return new EndUnconditionally(EndGroupPanel, true);
}
private static Vector2 UnitCircle(float theta) private static Vector2 UnitCircle(float theta)
{ {
var (s, c) = MathF.SinCos(theta); var (s, c) = MathF.SinCos(theta);
@@ -168,6 +141,7 @@ internal static class ImGuiUtils
return new Vector2(c, -s); return new Vector2(c, -s);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float Lerp(float a, float b, float t) => private static float Lerp(float a, float b, float t) =>
MathF.FusedMultiplyAdd(b - a, t, a); MathF.FusedMultiplyAdd(b - a, t, a);
@@ -251,6 +225,72 @@ internal static class ImGuiUtils
Arc(MathF.PI / 2, MathF.PI / 2 - MathF.Tau * Math.Clamp(value, 0, 1), radiusInner, radiusOuter, backgroundColor, filledColor); Arc(MathF.PI / 2, MathF.PI / 2 - MathF.Tau * Math.Clamp(value, 0, 1), radiusInner, radiusOuter, backgroundColor, filledColor);
} }
public sealed class ViolinData
{
[StructLayout(LayoutKind.Sequential)]
public struct Point
{
public float X, Y, Y2;
public Point(float x, float y, float y2)
{
X = x;
Y = y;
Y2 = y2;
}
}
public ReadOnlySpan<Point> Data => (DataArray ?? Array.Empty<Point>()).AsSpan();
private Point[]? DataArray { get; set; }
public readonly float Min;
public readonly float Max;
public ViolinData(IEnumerable<int> samples, float min, float max, int resolution, double bandwidth)
{
Min = min;
Max = max;
bandwidth *= Max - Min;
var samplesList = samples.AsParallel().Select(s => (double)s).ToArray();
_ = Task.Run(() => {
var s = Stopwatch.StartNew();
var data = ParallelEnumerable.Range(0, resolution)
.Select(n => Lerp(min, max, n / (float)resolution))
.Select(n => (n, (float)KernelDensity.EstimateGaussian(n, bandwidth, samplesList)))
.Select(n => new Point(n.n, n.Item2, -n.Item2));
DataArray = data.ToArray();
s.Stop();
Log.Debug($"Violin plot processing took {s.Elapsed.TotalMilliseconds:0.00}ms");
});
}
}
public static void ViolinPlot(in ViolinData data, Vector2 size)
{
using var padding = ImRaii2.PushStyle(ImPlotStyleVar.PlotPadding, Vector2.Zero);
using var plotBg = ImRaii2.PushColor(ImPlotCol.PlotBg, Vector4.Zero);
using var frameBg = ImRaii2.PushColor(ImPlotCol.FrameBg, Vector4.Zero);
using var fill = ImRaii2.PushColor(ImPlotCol.Fill, Vector4.One.WithAlpha(.5f));
using var plot = ImRaii2.Plot("##violin", size, ImPlotFlags.CanvasOnly);
if (plot)
{
ImPlot.SetupAxes(null, null, ImPlotAxisFlags.NoDecorations, ImPlotAxisFlags.NoDecorations | ImPlotAxisFlags.AutoFit);
ImPlot.SetupAxisLimits(ImAxis.X1, data.Min, data.Max, ImPlotCond.Always);
ImPlot.SetupFinish();
if (data.Data is { } points && !points.IsEmpty)
{
unsafe {
var label_id = stackalloc byte[] { (byte)'\0' };
fixed (ViolinData.Point* p = points)
{
ImPlotNative.ImPlot_PlotShaded_FloatPtrFloatPtrFloatPtr(label_id, &p->X, &p->Y, &p->Y2, points.Length, ImPlotShadedFlags.None, 0, sizeof(ViolinData.Point));
}
}
}
}
}
private sealed class SearchableComboData<T> where T : class private sealed class SearchableComboData<T> where T : class
{ {
public readonly ImmutableArray<T> items; public readonly ImmutableArray<T> items;
+92
View File
@@ -0,0 +1,92 @@
using Dalamud.Interface.Utility.Raii;
using ImPlotNET;
using System;
using System.Numerics;
namespace Craftimizer.Plugin;
public static class ImRaii2
{
private struct EndUnconditionally : ImRaii.IEndObject, IDisposable
{
private Action EndAction { get; }
public bool Success { get; }
public bool Disposed { get; private set; }
public EndUnconditionally(Action endAction, bool success)
{
EndAction = endAction;
Success = success;
Disposed = false;
}
public void Dispose()
{
if (!Disposed)
{
EndAction();
Disposed = true;
}
}
}
private struct EndConditionally : ImRaii.IEndObject, IDisposable
{
public bool Success { get; }
public bool Disposed { get; private set; }
private Action EndAction { get; }
public EndConditionally(Action endAction, bool success)
{
EndAction = endAction;
Success = success;
Disposed = false;
}
public void Dispose()
{
if (!Disposed)
{
if (Success)
{
EndAction();
}
Disposed = true;
}
}
}
public static ImRaii.IEndObject GroupPanel(string name, float width, out float internalWidth)
{
internalWidth = ImGuiUtils.BeginGroupPanel(name, width);
return new EndUnconditionally(ImGuiUtils.EndGroupPanel, true);
}
public static ImRaii.IEndObject Plot(string title_id, Vector2 size, ImPlotFlags flags)
{
return new EndConditionally(new Action(ImPlot.EndPlot), ImPlot.BeginPlot(title_id, size, flags));
}
public static ImRaii.IEndObject PushStyle(ImPlotStyleVar idx, Vector2 val)
{
ImPlot.PushStyleVar(idx, val);
return new EndUnconditionally(ImPlot.PopStyleVar, true);
}
public static ImRaii.IEndObject PushStyle(ImPlotStyleVar idx, float val)
{
ImPlot.PushStyleVar(idx, val);
return new EndUnconditionally(ImPlot.PopStyleVar, true);
}
public static ImRaii.IEndObject PushColor(ImPlotCol idx, Vector4 col)
{
ImPlot.PushStyleColor(idx, col);
return new EndUnconditionally(ImPlot.PopStyleColor, true);
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ public sealed class MacroClipboard : Window, IDisposable
private void DrawMacro(int idx, string macro) private void DrawMacro(int idx, string macro)
{ {
using var id = ImRaii.PushId(idx); using var id = ImRaii.PushId(idx);
using var panel = ImGuiUtils.GroupPanel($"Macro {idx + 1}", -1, out var availWidth); using var panel = ImRaii2.GroupPanel($"Macro {idx + 1}", -1, out var availWidth);
var cursor = ImGui.GetCursorPos(); var cursor = ImGui.GetCursorPos();
+56 -58
View File
@@ -79,31 +79,48 @@ public sealed class MacroEditor : Window, IDisposable
private readonly record struct SimulationReliablity private readonly record struct SimulationReliablity
{ {
public record struct ParamReliability public sealed class ParamReliability
{ {
private List<int> DataList { get; }
private ImGuiUtils.ViolinData? ViolinData { get; set; }
public int Max { get; private set; } public int Max { get; private set; }
public int Min { get; private set; } public int Min { get; private set; }
public float Median { get; private set; }
public float Average { get; private set; } public float Average { get; private set; }
public ParamReliability() public ParamReliability()
{ {
Min = int.MaxValue; DataList = new();
} }
public void Add(int value) public void Add(int value)
{ {
Max = Math.Max(Max, value); DataList.Add(value);
Min = Math.Min(Min, value);
Average += value;
} }
public void Finalize(int count) public void FinalizeData()
{ {
if (count == 0) if (DataList.Count == 0)
Average = Max = Min = 0; {
Average = Median = Max = Min = 0;
return;
}
Max = DataList.Max();
Min = DataList.Min();
if (DataList.Count % 2 == 0)
Median = (float)DataList.Order().Skip(DataList.Count / 2 - 1).Take(2).Average();
else else
Average /= count; Median = DataList.Order().ElementAt(DataList.Count / 2);
Average = (float)DataList.Average();
} }
public ImGuiUtils.ViolinData? GetViolinData(float barMax, int resolution, double bandwidth) =>
ViolinData ??=
Min != Max ?
new(DataList, 0, barMax, resolution, bandwidth) :
null;
} }
public readonly ParamReliability Progress = new(); public readonly ParamReliability Progress = new();
@@ -132,9 +149,9 @@ public sealed class MacroEditor : Window, IDisposable
Quality.Add(state.Quality); Quality.Add(state.Quality);
Param.Add(getParam(state)); Param.Add(getParam(state));
} }
Progress.Finalize(iterCount); Progress.FinalizeData();
Quality.Finalize(iterCount); Quality.FinalizeData();
Param.Finalize(iterCount); Param.FinalizeData();
} }
} }
@@ -160,7 +177,8 @@ public sealed class MacroEditor : Window, IDisposable
} }
public SimulationReliablity GetReliability(in SimulationState initialState, IEnumerable<ActionType> actionSet, RecipeData recipeData) => public SimulationReliablity GetReliability(in SimulationState initialState, IEnumerable<ActionType> actionSet, RecipeData recipeData) =>
Reliability ??= new(initialState, actionSet, Service.Configuration.ReliabilitySimulationCount, recipeData); Reliability ??=
new(initialState, actionSet, Service.Configuration.ReliabilitySimulationCount, recipeData);
}; };
private List<SimulatedActionStep> Macro { get; set; } = new(); private List<SimulatedActionStep> Macro { get; set; } = new();
@@ -195,7 +213,7 @@ public sealed class MacroEditor : Window, IDisposable
private CancellationTokenSource? popupImportUrlTokenSource; private CancellationTokenSource? popupImportUrlTokenSource;
private MacroImport.RetrievedMacro? popupImportUrlMacro; private MacroImport.RetrievedMacro? popupImportUrlMacro;
public MacroEditor(CharacterStats characterStats, RecipeData recipeData, CrafterBuffs buffs, IEnumerable<ActionType> actions, Action<IEnumerable<ActionType>>? setter) : base("Craftimizer Macro Editor", WindowFlags, false) public MacroEditor(CharacterStats characterStats, RecipeData recipeData, CrafterBuffs buffs, IEnumerable<ActionType> actions, Action<IEnumerable<ActionType>>? setter) : base("Craftimizer Macro Editor", WindowFlags)
{ {
CharacterStats = characterStats; CharacterStats = characterStats;
RecipeData = recipeData; RecipeData = recipeData;
@@ -1000,7 +1018,7 @@ public sealed class MacroEditor : Window, IDisposable
continue; continue;
var actions = category.GetActions(); var actions = category.GetActions();
using var panel = ImGuiUtils.GroupPanel(category.GetDisplayName(), -1, out var availSpace); using var panel = ImRaii2.GroupPanel(category.GetDisplayName(), -1, out var availSpace);
var itemsPerRow = (int)MathF.Floor((availSpace + spacing) / (imageSize + spacing)); var itemsPerRow = (int)MathF.Floor((availSpace + spacing) / (imageSize + spacing));
var itemCount = actions.Count; var itemCount = actions.Count;
var iterCount = (int)(Math.Ceiling((float)itemCount / itemsPerRow) * itemsPerRow); var iterCount = (int)(Math.Ceiling((float)itemCount / itemsPerRow) * itemsPerRow);
@@ -1076,7 +1094,7 @@ public sealed class MacroEditor : Window, IDisposable
} }
} }
using (var panel = ImGuiUtils.GroupPanel("Buffs", -1, out _)) using (var panel = ImRaii2.GroupPanel("Buffs", -1, out _))
{ {
using var _font = ImRaii.PushFont(AxisFont.ImFont); using var _font = ImRaii.PushFont(AxisFont.ImFont);
@@ -1134,7 +1152,7 @@ public sealed class MacroEditor : Window, IDisposable
var barSize = totalSize - textSize - spacing; var barSize = totalSize - textSize - spacing;
foreach (var bar in bars) foreach (var bar in bars)
{ {
using var panel = ImGuiUtils.GroupPanel(bar.Name, totalSize, out _); using var panel = ImRaii2.GroupPanel(bar.Name, totalSize, out _);
if (bar.Condition is { } condition) if (bar.Condition is { } condition)
{ {
using (var g = ImRaii.Group()) using (var g = ImRaii.Group())
@@ -1155,45 +1173,25 @@ public sealed class MacroEditor : Window, IDisposable
} }
else else
{ {
if (bar.Reliability is { } reliability) var pos = ImGui.GetCursorPos();
{ using (var color = ImRaii.PushColor(ImGuiCol.PlotHistogram, bar.Color))
// blend rgb colors, assume alpha is always 1
static Vector4 BlendColor(Vector4 A, Vector4 B)
{
return new(
A.X * (1 - B.W) + B.X * B.W,
A.Y * (1 - B.W) + B.Y * B.W,
A.Z * (1 - B.W) + B.Z * B.W,
1);
}
var relBars = new (float Value, Vector4 Color)[]
{
(bar.Value, bar.Color),
(reliability.Average, BlendColor(bar.Color, new(.5f,.5f,.5f,.6f))),
(reliability.Min, BlendColor(bar.Color, new(0,0,0,.6f))),
(reliability.Max, BlendColor(bar.Color, new(1,1,1,.6f))),
}.DistinctBy(v => Math.Clamp(v.Value, 0, bar.Max)).OrderByDescending(v => v.Value);
var i = 0;
var pos = ImGui.GetCursorPos();
foreach (var relBar in relBars)
{
ImGui.SetCursorPos(pos);
{
using var frameColor = ImRaii.PushColor(ImGuiCol.FrameBg, Vector4.Zero, i != 0);
using var color = ImRaii.PushColor(ImGuiCol.PlotHistogram, relBar.Color);
ImGui.ProgressBar(Math.Clamp(relBar.Value / bar.Max, 0, 1), new(barSize, ImGui.GetFrameHeight()), string.Empty);
}
if (i++ == 0)
{
if (ImGui.IsItemHovered())
ImGui.SetTooltip($"Min: {reliability.Min}\nAvg: {reliability.Average:0.##}\nMax: {reliability.Max}");
}
}
}
else
{
using var color = ImRaii.PushColor(ImGuiCol.PlotHistogram, bar.Color);
ImGui.ProgressBar(Math.Clamp(bar.Value / bar.Max, 0, 1), new(barSize, ImGui.GetFrameHeight()), string.Empty); ImGui.ProgressBar(Math.Clamp(bar.Value / bar.Max, 0, 1), new(barSize, ImGui.GetFrameHeight()), string.Empty);
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenOverlapped))
{
if (bar.Reliability is { } reliability)
{
if (reliability.GetViolinData(bar.Max, (int)(barSize / 2), 0.02) is { } violinData)
{
ImGui.SetCursorPos(pos);
ImGuiUtils.ViolinPlot(violinData, new(barSize, ImGui.GetFrameHeight()));
if (ImGui.IsItemHovered())
ImGui.SetTooltip(
$"Min: {reliability.Min}\n" +
$"Med: {reliability.Median:0.##}\n" +
$"Avg: {reliability.Average:0.##}\n" +
$"Max: {reliability.Max}");
}
}
} }
ImGui.SameLine(0, spacing); ImGui.SameLine(0, spacing);
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
@@ -1217,7 +1215,7 @@ public sealed class MacroEditor : Window, IDisposable
var imageSize = ImGui.GetFrameHeight() * 2; var imageSize = ImGui.GetFrameHeight() * 2;
var lastState = InitialState; var lastState = InitialState;
using var panel = ImGuiUtils.GroupPanel("Macro", -1, out var availSpace); using var panel = ImRaii2.GroupPanel("Macro", -1, out var availSpace);
ImGui.Dummy(new(0, imageSize)); ImGui.Dummy(new(0, imageSize));
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
@@ -1412,7 +1410,7 @@ public sealed class MacroEditor : Window, IDisposable
{ {
bool submittedText, submittedUrl; bool submittedText, submittedUrl;
using (var panel = ImGuiUtils.GroupPanel("##text", -1, out var availWidth)) using (var panel = ImRaii2.GroupPanel("##text", -1, out var availWidth))
{ {
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
ImGuiUtils.TextCentered("Paste your macro here"); ImGuiUtils.TextCentered("Paste your macro here");
@@ -1424,7 +1422,7 @@ public sealed class MacroEditor : Window, IDisposable
submittedText = ImGui.Button("Import", new(availWidth, 0)); submittedText = ImGui.Button("Import", new(availWidth, 0));
} }
using (var panel = ImGuiUtils.GroupPanel("##url", -1, out var availWidth)) using (var panel = ImRaii2.GroupPanel("##url", -1, out var availWidth))
{ {
var availOffset = ImGui.GetContentRegionAvail().X - availWidth; var availOffset = ImGui.GetContentRegionAvail().X - availWidth;
+1 -1
View File
@@ -111,7 +111,7 @@ public sealed class MacroList : Window, IDisposable
var stateNullable = GetMacroState(macro); var stateNullable = GetMacroState(macro);
using var panel = ImGuiUtils.GroupPanel(macro.Name, -1, out var availWidth); using var panel = ImRaii2.GroupPanel(macro.Name, -1, out var availWidth);
var stepsAvailWidthOffset = ImGui.GetContentRegionAvail().X - availWidth; var stepsAvailWidthOffset = ImGui.GetContentRegionAvail().X - availWidth;
var spacing = ImGui.GetStyle().ItemSpacing.Y; var spacing = ImGui.GetStyle().ItemSpacing.Y;
var miniRowHeight = (windowHeight - spacing) / 2f; var miniRowHeight = (windowHeight - spacing) / 2f;
+2 -2
View File
@@ -216,7 +216,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
ImGui.Separator(); ImGui.Separator();
var panelWidth = availWidth - ImGui.GetStyle().ItemSpacing.X * 2; var panelWidth = availWidth - ImGui.GetStyle().ItemSpacing.X * 2;
using (var panel = ImGuiUtils.GroupPanel("Best Saved Macro", panelWidth, out _)) using (var panel = ImRaii2.GroupPanel("Best Saved Macro", panelWidth, out _))
{ {
var stepsPanelWidthOffset = ImGui.GetContentRegionAvail().X - panelWidth; var stepsPanelWidthOffset = ImGui.GetContentRegionAvail().X - panelWidth;
if (BestSavedMacro is { } savedMacro) if (BestSavedMacro is { } savedMacro)
@@ -228,7 +228,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
DrawMacro(null, null, stepsPanelWidthOffset, true); DrawMacro(null, null, stepsPanelWidthOffset, true);
} }
using (var panel = ImGuiUtils.GroupPanel("Suggested Macro", panelWidth, out _)) using (var panel = ImRaii2.GroupPanel("Suggested Macro", panelWidth, out _))
{ {
var stepsPanelWidthOffset = ImGui.GetContentRegionAvail().X - panelWidth; var stepsPanelWidthOffset = ImGui.GetContentRegionAvail().X - panelWidth;
if (BestSuggestedMacro is { } suggestedMacro) if (BestSuggestedMacro is { } suggestedMacro)
+17 -5
View File
@@ -191,7 +191,7 @@ public sealed class Settings : Window, IDisposable
ImGui.SetTooltip("Disabled temporarily for testing"); ImGui.SetTooltip("Disabled temporarily for testing");
DrawOption( DrawOption(
"Show Only One Macro Stat", "Show Only One Macro Stat in Crafting Log",
"Only one stat will be shown for a macro. If a craft will be finished, quality\n" + "Only one stat will be shown for a macro. If a craft will be finished, quality\n" +
"is shown. Otherwise, progress is shown. Durability and remaining CP will be\n" + "is shown. Otherwise, progress is shown. Durability and remaining CP will be\n" +
"hidden.", "hidden.",
@@ -200,9 +200,21 @@ public sealed class Settings : Window, IDisposable
ref isDirty ref isDirty
); );
DrawOption(
"Reliability Trial Count",
"When testing for reliability of a macro in the editor, this many trials will be\n" +
"run. You should set this value to at least 100 to get a reliable spread of data.\n" +
"If it's too low, you may not find an outlier, and the average might be skewed.",
Config.ReliabilitySimulationCount,
5,
5000,
v => Config.ReliabilitySimulationCount = v,
ref isDirty
);
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
using (var panel = ImGuiUtils.GroupPanel("Copying Settings", -1, out _)) using (var panel = ImRaii2.GroupPanel("Copying Settings", -1, out _))
{ {
DrawOption( DrawOption(
"Macro Copy Method", "Macro Copy Method",
@@ -380,7 +392,7 @@ public sealed class Settings : Window, IDisposable
var config = configRef; var config = configRef;
using (var panel = ImGuiUtils.GroupPanel("General", -1, out _)) using (var panel = ImRaii2.GroupPanel("General", -1, out _))
{ {
if (ImGui.Button("Reset to Default", OptionButtonSize)) if (ImGui.Button("Reset to Default", OptionButtonSize))
{ {
@@ -501,7 +513,7 @@ public sealed class Settings : Window, IDisposable
); );
} }
using (var panel = ImGuiUtils.GroupPanel("Advanced", -1, out _)) using (var panel = ImRaii2.GroupPanel("Advanced", -1, out _))
{ {
DrawOption( DrawOption(
"Score Storage Threshold", "Score Storage Threshold",
@@ -538,7 +550,7 @@ public sealed class Settings : Window, IDisposable
); );
} }
using (var panel = ImGuiUtils.GroupPanel("Score Weights (Advanced)", -1, out _)) using (var panel = ImRaii2.GroupPanel("Score Weights (Advanced)", -1, out _))
{ {
ImGui.TextWrapped("All values should add up to 1. Otherwise, the Score Storage Threshold should be changed."); ImGui.TextWrapped("All values should add up to 1. Otherwise, the Score Storage Threshold should be changed.");
ImGuiHelpers.ScaledDummy(10); ImGuiHelpers.ScaledDummy(10);
+6
View File
@@ -8,6 +8,12 @@
"resolved": "2.1.12", "resolved": "2.1.12",
"contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg==" "contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg=="
}, },
"MathNet.Numerics": {
"type": "Direct",
"requested": "[5.0.0, )",
"resolved": "5.0.0",
"contentHash": "pg1W2VwaEQMAiTpGK840hZgzavnqjlCMTVSbtVCXVyT+7AX4mc1o89SPv4TBlAjhgCOo9c1Y+jZ5m3ti2YgGgA=="
},
"Meziantou.Analyzer": { "Meziantou.Analyzer": {
"type": "Direct", "type": "Direct",
"requested": "[2.0.106, )", "requested": "[2.0.106, )",