Compare commits

...

No commits in common. "master" and "8278a8db0dbb5923065b1d4dfd75039fa952c095" have entirely different histories.

17 changed files with 138 additions and 1926 deletions

View File

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7</TargetFramework>
<TargetFramework>net5</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="2.0.1" />
<PackageReference Include="Microsoft.ML" Version="1.6.0"/>
</ItemGroup>
</Project>

View File

@ -2,15 +2,16 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7</TargetFramework>
<TargetFramework>net5</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ConsoleTables" Version="2.5.0"/>
<PackageReference Include="CsvHelper" Version="30.0.1"/>
<PackageReference Include="Microsoft.ML" Version="2.0.1"/>
<PackageReference Include="ConsoleTables" Version="2.4.2"/>
<PackageReference Include="CsvHelper" Version="27.1.1"/>
<PackageReference Include="Microsoft.ML" Version="1.6.0"/>
<PackageReference Include="MimeKitLite" Version="2.15.1"/>
</ItemGroup>
<ItemGroup>

View File

@ -11,6 +11,7 @@ using CsvHelper.Configuration;
using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.ML.Transforms.Text;
using MimeKit;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using NoSoliciting.Interface;
@ -20,8 +21,6 @@ namespace NoSoliciting.Trainer {
private static readonly string[] StopWords = {
"discord",
"gg",
"twitch",
"tv",
"lgbt",
"lgbtq",
"lgbtqia",
@ -41,6 +40,7 @@ namespace NoSoliciting.Trainer {
Interactive,
InteractiveFull,
Normalise,
Import,
}
[Serializable]
@ -56,6 +56,51 @@ namespace NoSoliciting.Trainer {
public string? SuggestedClassification { get; set; }
}
private static void Import(string path) {
var allData = new List<Data>();
var opts = new ParserOptions {
CharsetEncoding = Encoding.UTF8,
};
foreach (var emlPath in Directory.GetFiles(path, "*.eml")) {
var message = MimeMessage.Load(opts, new FileStream(emlPath, FileMode.Open));
var lines = message.TextBody
.Split('\r', '\n')
.SkipWhile(line => !line.StartsWith("JSON: "))
.Select(line => line.Replace("JSON: ", "").Replace(" ", "").Trim())
.ToArray();
if (lines.Length == 0) {
continue;
}
var json = string.Join("", lines);
var jsonText = Encoding.UTF8.GetString(Convert.FromBase64String(json));
var report = JsonConvert.DeserializeObject<ReportInput>(jsonText);
var content = XivString.GetText(report.Content);
var data = new Data(report.Type, content) {
Category = report.SuggestedClassification,
};
data.Message = data.Message
.Replace("\r\n", " ")
.Replace('\r', ' ')
.Replace('\n', ' ');
allData.Add(data);
}
var writer = new StringWriter();
using var csv = new CsvWriter(writer, new CsvConfiguration(CultureInfo.InvariantCulture) {
HeaderValidated = null,
Encoding = Encoding.UTF8,
});
csv.WriteRecords(allData
.OrderBy(data => data.Category)
.ThenBy(data => data.Channel)
.ThenBy(data => data.Message));
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine(writer.ToString());
}
private static void Main(string[] args) {
var mode = args[0] switch {
"test" => Mode.Test,
@ -63,9 +108,15 @@ namespace NoSoliciting.Trainer {
"interactive" => Mode.Interactive,
"interactive-full" => Mode.InteractiveFull,
"normalise" => Mode.Normalise,
"import" => Mode.Import,
_ => throw new ArgumentException("invalid argument"),
};
if (mode == Mode.Import) {
Import(args[1]);
return;
}
if (mode == Mode.Normalise) {
Console.WriteLine("Ready");
@ -174,9 +225,7 @@ namespace NoSoliciting.Trainer {
.Append(ctx.Transforms.Conversion.ConvertType("HasPlot", nameof(Data.Computed.ContainsPlot)))
.Append(ctx.Transforms.Conversion.ConvertType("HasNumbers", nameof(Data.Computed.ContainsHousingNumbers)))
.Append(ctx.Transforms.Concatenate("Features", "FeaturisedMessage", "CPartyFinder", "CShout", "CTrade", "HasWard", "HasPlot", "HasNumbers", "CSketch"))
// macro 81.8 micro 84.6 (Tf weighting) - slow
// .Append(ctx.MulticlassClassification.Trainers.SdcaMaximumEntropy(exampleWeightColumnName: "Weight", l1Regularization: 0, l2Regularization: 0, maximumNumberOfIterations: 2_500))
.Append(ctx.MulticlassClassification.Trainers.SdcaMaximumEntropy(exampleWeightColumnName: "Weight", l1Regularization: 0, l2Regularization: 0, maximumNumberOfIterations: null))
.Append(ctx.MulticlassClassification.Trainers.SdcaMaximumEntropy(exampleWeightColumnName: "Weight"))
.Append(ctx.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
var train = mode switch {

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@ namespace NoSoliciting {
private void OnCommand(string command, string args) {
if (command == "/prmt") {
this.Plugin.ChatGui.PrintError($"[{Plugin.Name}] The /prmt command is deprecated and will be removed. Please use /nosol instead.");
this.Plugin.ChatGui.PrintError($"[{this.Plugin.Name}] The /prmt command is deprecated and will be removed. Please use /nosol instead.");
}
if (args == "report") {

View File

@ -1,7 +1,7 @@
using System;
using System.Linq;
using Dalamud.ContextMenu;
using NoSoliciting.Resources;
using XivCommon.Functions.ContextMenu;
namespace NoSoliciting {
public class ContextMenu : IDisposable {
@ -10,14 +10,14 @@ namespace NoSoliciting {
internal ContextMenu(Plugin plugin) {
this.Plugin = plugin;
this.Plugin.DalamudContextMenu.OnOpenGameObjectContextMenu += this.OnOpenContextMenu;
this.Plugin.Common.Functions.ContextMenu.OpenContextMenu += this.OnOpenContextMenu;
}
public void Dispose() {
this.Plugin.DalamudContextMenu.OnOpenGameObjectContextMenu -= this.OnOpenContextMenu;
this.Plugin.Common.Functions.ContextMenu.OpenContextMenu -= this.OnOpenContextMenu;
}
private void OnOpenContextMenu(GameObjectContextMenuOpenArgs args) {
private void OnOpenContextMenu(ContextMenuOpenArgs args) {
if (args.ParentAddonName != "LookingForGroup") {
return;
}
@ -27,10 +27,10 @@ namespace NoSoliciting {
}
var label = Language.ReportToNoSoliciting;
args.AddCustomItem(new GameObjectContextMenuItem(label, this.Report));
args.Items.Add(new NormalContextMenuItem(label, this.Report));
}
private void Report(GameObjectContextMenuItemSelectedArgs args) {
private void Report(ContextMenuItemSelectedArgs args) {
if (args.ContentIdLower == 0) {
return;
}

View File

@ -2,6 +2,7 @@
using Dalamud.Game.Gui.PartyFinder.Types;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Logging;
using NoSoliciting.Interface;
using NoSoliciting.Ml;
@ -103,10 +104,10 @@ namespace NoSoliciting {
args.Visible = false;
if (this.Plugin.Config.LogFilteredPfs) {
Plugin.Log.Info($"Filtered PF listing from {listing.Name.TextValue} ({reason}): {listing.Description.TextValue}");
PluginLog.Log($"Filtered PF listing from {listing.Name.TextValue} ({reason}): {listing.Description.TextValue}");
}
} catch (Exception ex) {
Plugin.Log.Error($"Error in PF listing event: {ex}");
PluginLog.LogError($"Error in PF listing event: {ex}");
}
}
@ -165,7 +166,7 @@ namespace NoSoliciting {
this.Plugin.AddMessageHistory(history);
if (filter && this.Plugin.Config.LogFilteredChat) {
Plugin.Log.Info($"Filtered chat message ({history.FilterReason ?? "unknown"}): {text}");
PluginLog.Log($"Filtered chat message ({history.FilterReason ?? "unknown"}): {text}");
}
return filter;
@ -201,7 +202,7 @@ namespace NoSoliciting {
var category = this.Plugin.MlFilter.ClassifyMessage((ushort) ChatType.None, desc);
if (category != MessageCategory.Normal && this.Plugin.Config.MlEnabledOn(category, ChatType.None)) {
return (category, Enum.GetName(category));
return (category, null);
}
return (null, null);

View File

@ -1,9 +1,9 @@
using Lumina.Excel.GeneratedSheets;
using Dalamud.Data;
using Lumina.Excel.GeneratedSheets;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Dalamud.Plugin.Services;
using NoSoliciting.Ml;
namespace NoSoliciting {
@ -87,7 +87,7 @@ namespace NoSoliciting {
return null;
}
public static int MaxItemLevelAttainable(IDataManager data) {
public static int MaxItemLevelAttainable(DataManager data) {
if (MaxItemLevel > 0) {
return MaxItemLevel;
}

View File

@ -6,6 +6,7 @@ using System.Numerics;
using System.Threading.Tasks;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Logging;
using ImGuiNET;
using NoSoliciting.Ml;
using NoSoliciting.Resources;
@ -65,7 +66,7 @@ namespace NoSoliciting.Interface {
ImGui.SetNextWindowSize(new Vector2(1_000, 350), ImGuiCond.FirstUseEver);
var windowTitle = string.Format(Language.Reporting, Plugin.Name);
var windowTitle = string.Format(Language.Reporting, this.Plugin.Name);
if (!ImGui.Begin($"{windowTitle}###NoSoliciting reporting", ref this._showReporting)) {
ImGui.End();
return;
@ -223,7 +224,7 @@ namespace NoSoliciting.Interface {
ImGui.SetNextWindowSize(new Vector2(350, -1));
var modalTitle = string.Format(Language.ReportModalTitle, Plugin.Name);
var modalTitle = string.Format(Language.ReportModalTitle, this.Plugin.Name);
if (!ImGui.BeginPopupModal($"{modalTitle}###modal-message-{message.Id}")) {
return false;
}
@ -440,11 +441,11 @@ namespace NoSoliciting.Interface {
var status = resp == "{\"message\":\"ok\"}" ? ReportStatus.Successful : ReportStatus.Failure;
if (status == ReportStatus.Failure) {
Plugin.Log.Warning($"Failed to report message:\n{resp}");
PluginLog.LogWarning($"Failed to report message:\n{resp}");
}
this.LastReportStatus = status;
Plugin.Log.Info(resp == null
PluginLog.Log(resp == null
? "Report not sent. ML model not set."
: $"Report sent. Response: {resp}");

View File

@ -44,7 +44,7 @@ namespace NoSoliciting.Interface {
}
public void Draw() {
var windowTitle = string.Format(Language.Settings, Plugin.Name);
var windowTitle = string.Format(Language.Settings, this.Plugin.Name);
if (!this.ShowSettings || !ImGui.Begin($"{windowTitle}###NoSoliciting settings", ref this._showSettings)) {
return;
}

View File

@ -3,9 +3,9 @@ using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Data;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.Services;
using Lumina.Excel.GeneratedSheets;
using NoSoliciting.Ml;
@ -208,7 +208,7 @@ namespace NoSoliciting {
_ => (byte) type,
};
public static string Name(this ChatType type, IDataManager data) {
public static string Name(this ChatType type, DataManager data) {
switch (type) {
case ChatType.None:
return "Party Finder";

View File

@ -5,6 +5,7 @@ using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Dalamud.Logging;
using NoSoliciting.Interface;
using NoSoliciting.Resources;
using YamlDotNet.Core;
@ -42,7 +43,7 @@ namespace NoSoliciting.Ml {
return (MessageCategory) category;
}
Plugin.Log.Warning($"Unknown message category: {prediction}");
PluginLog.LogWarning($"Unknown message category: {prediction}");
return MessageCategory.Normal;
}
@ -52,7 +53,7 @@ namespace NoSoliciting.Ml {
// download and parse the remote manifest
var manifest = await DownloadManifest();
if (manifest == null) {
Plugin.Log.Warning("Could not download manifest. Will attempt to fall back on cached version.");
PluginLog.LogWarning("Could not download manifest. Will attempt to fall back on cached version.");
}
// model zip file data
@ -95,7 +96,7 @@ namespace NoSoliciting.Ml {
var hash = sha.ComputeHash(data);
while (!hash.SequenceEqual(correctHash) && retries < maxRetries) {
Plugin.Log.Warning($"Model checksum did not match. Redownloading (attempt {retries + 1}/{maxRetries})");
PluginLog.Warning($"Model checksum did not match. Redownloading (attempt {retries + 1}/{maxRetries})");
retries += 1;
data = await DownloadModel(manifest!.Value.manifest!.ModelUrl);
@ -137,8 +138,8 @@ namespace NoSoliciting.Ml {
var data = await client.DownloadDataTaskAsync(url);
return data;
} catch (WebException e) {
Plugin.Log.Error("Could not download newest model.");
Plugin.Log.Error(e.ToString());
PluginLog.LogError("Could not download newest model.");
PluginLog.LogError(e.ToString());
LastError = e.Message;
return null;
}
@ -166,8 +167,8 @@ namespace NoSoliciting.Ml {
LastError = null;
return (LoadYaml<Manifest>(data), data);
} catch (Exception e) when (e is WebException or YamlException) {
Plugin.Log.Error("Could not download newest model manifest.");
Plugin.Log.Error(e.ToString());
PluginLog.LogError("Could not download newest model manifest.");
PluginLog.LogError(e.ToString());
LastError = e.Message;
return null;
}

View File

@ -3,57 +3,52 @@
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<Version>3.0.8</Version>
<TargetFramework>net7-windows</TargetFramework>
<Version>3.0.1</Version>
<TargetFramework>net5-windows</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x64</PlatformTarget>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
</PropertyGroup>
<PropertyGroup>
<DalamudLibPath>$(AppData)\XIVLauncher\addon\Hooks\dev</DalamudLibPath>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))'">
<DalamudLibPath>$(DALAMUD_HOME)</DalamudLibPath>
<Dalamud>$(AppData)\XIVLauncher\addon\Hooks\dev</Dalamud>
</PropertyGroup>
<PropertyGroup Condition="'$(IsCI)' == 'true'">
<DalamudLibPath>$(HOME)/dalamud</DalamudLibPath>
<Dalamud>$(HOME)/dalamud</Dalamud>
</PropertyGroup>
<ItemGroup>
<Reference Include="Dalamud">
<HintPath>$(DalamudLibPath)\Dalamud.dll</HintPath>
<HintPath>$(Dalamud)\Dalamud.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ImGui.NET">
<HintPath>$(DalamudLibPath)\ImGui.NET.dll</HintPath>
<HintPath>$(Dalamud)\ImGui.NET.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Lumina">
<HintPath>$(DalamudLibPath)\Lumina.dll</HintPath>
<HintPath>$(Dalamud)\Lumina.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Lumina.Excel">
<HintPath>$(DalamudLibPath)\Lumina.Excel.dll</HintPath>
<HintPath>$(Dalamud)\Lumina.Excel.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>$(DalamudLibPath)\Newtonsoft.Json.dll</HintPath>
<HintPath>$(Dalamud)\Newtonsoft.Json.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dalamud.ContextMenu" Version="1.3.1"/>
<PackageReference Include="DalamudPackager" Version="2.1.12"/>
<PackageReference Include="Fody" Version="6.8.0" PrivateAssets="all"/>
<PackageReference Include="Microsoft.ML" Version="2.0.1"/>
<PackageReference Include="Resourcer.Fody" Version="1.8.1" PrivateAssets="all"/>
<PackageReference Include="XivCommon" Version="9.0.0"/>
<PackageReference Include="YamlDotNet" Version="13.4.0"/>
<PackageReference Include="DalamudLinter" Version="1.0.3"/>
<PackageReference Include="DalamudPackager" Version="2.1.4"/>
<PackageReference Include="Fody" Version="6.5.3" PrivateAssets="all"/>
<PackageReference Include="Microsoft.ML" Version="1.6.0"/>
<PackageReference Include="Resourcer.Fody" Version="1.8.0" PrivateAssets="all"/>
<PackageReference Include="XivCommon" Version="3.0.2"/>
<PackageReference Include="YamlDotNet" Version="11.2.1"/>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\Language.resx">
@ -71,4 +66,7 @@
<DependentUpon>NoSoliciting.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<Content Include="..\icon.png" Link="images/icon.png" CopyToOutputDirectory="PreserveNewest" Visible="false"/>
</ItemGroup>
</Project>

View File

@ -1,4 +1,4 @@
author: Anna
author: ascclemens
name: NoSoliciting
punchline: Adblock for FFXIV.
description: |-
@ -14,6 +14,6 @@ description: |-
- Trade ads
- Community ads
- Any PF with an item level over the max
repo_url: https://git.anna.lgbt/anna/NoSoliciting
repo_url: https://git.sr.ht/~jkcclemens/NoSoliciting
# Use higher priority to filter messages before other plugins get them.
load_priority: 100

View File

@ -6,9 +6,14 @@ using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Dalamud;
using Dalamud.ContextMenu;
using Dalamud.Data;
using Dalamud.Game.ClientState;
using Dalamud.Game.Command;
using Dalamud.Game.Gui;
using Dalamud.Game.Gui.PartyFinder;
using Dalamud.Game.Gui.Toast;
using Dalamud.IoC;
using Dalamud.Plugin.Services;
using Dalamud.Logging;
using NoSoliciting.Interface;
using NoSoliciting.Ml;
using NoSoliciting.Resources;
@ -19,37 +24,33 @@ namespace NoSoliciting {
public class Plugin : IDalamudPlugin {
private bool _disposedValue;
internal static string Name => "NoSoliciting";
public string Name => "NoSoliciting";
private Filter Filter { get; }
[PluginService]
internal static IPluginLog Log { get; private set; } = null!;
[PluginService]
internal DalamudPluginInterface Interface { get; init; } = null!;
[PluginService]
private IClientState ClientState { get; init; } = null!;
private ClientState ClientState { get; init; } = null!;
[PluginService]
internal IChatGui ChatGui { get; init; } = null!;
internal ChatGui ChatGui { get; init; } = null!;
[PluginService]
internal IPartyFinderGui PartyFinderGui { get; init; } = null!;
internal PartyFinderGui PartyFinderGui { get; init; } = null!;
[PluginService]
internal IDataManager DataManager { get; init; } = null!;
internal DataManager DataManager { get; init; } = null!;
[PluginService]
internal ICommandManager CommandManager { get; init; } = null!;
internal CommandManager CommandManager { get; init; } = null!;
[PluginService]
internal IToastGui ToastGui { get; init; } = null!;
internal ToastGui ToastGui { get; init; } = null!;
internal PluginConfiguration Config { get; }
internal XivCommonBase Common { get; }
internal DalamudContextMenu DalamudContextMenu { get; }
internal PluginUi Ui { get; }
private Commands Commands { get; }
private ContextMenu ContextMenu { get; }
@ -77,8 +78,7 @@ namespace NoSoliciting {
this.ConfigureLanguage();
this.Interface.LanguageChanged += this.OnLanguageUpdate;
this.Common = new XivCommonBase(this.Interface, Hooks.PartyFinderListings);
this.DalamudContextMenu = new DalamudContextMenu(this.Interface);
this.Common = new XivCommonBase(Hooks.PartyFinder | Hooks.ContextMenu);
this.Ui = new PluginUi(this);
this.Commands = new Commands(this);
@ -92,7 +92,7 @@ namespace NoSoliciting {
try {
FilterUtil.MaxItemLevelAttainable(this.DataManager);
} catch (Exception ex) {
Plugin.Log.Error(ex, "Exception while computing max item level");
PluginLog.LogError(ex, "Exception while computing max item level");
}
}
@ -107,7 +107,6 @@ namespace NoSoliciting {
this.ContextMenu.Dispose();
this.Commands.Dispose();
this.Ui.Dispose();
this.DalamudContextMenu.Dispose();
this.Common.Dispose();
this.Interface.LanguageChanged -= this.OnLanguageUpdate;
}
@ -149,7 +148,7 @@ namespace NoSoliciting {
}
this.MlStatus = MlFilterStatus.Initialised;
Log.Info("Machine learning model loaded");
PluginLog.Log("Machine learning model loaded");
});
}

View File

@ -44,17 +44,13 @@ namespace NoSoliciting {
public Dictionary<MessageCategory, HashSet<ChatType>> MlFilters { get; set; } = new() {
[MessageCategory.RmtGil] = new HashSet<ChatType> {
ChatType.None,
ChatType.Say,
ChatType.Shout,
},
[MessageCategory.RmtContent] = new HashSet<ChatType> {
ChatType.None,
ChatType.Say,
ChatType.Shout,
},
[MessageCategory.Phishing] = new HashSet<ChatType> {
ChatType.None,
ChatType.TellIncoming,
},
[MessageCategory.Roleplaying] = new HashSet<ChatType> {
@ -76,18 +72,12 @@ namespace NoSoliciting {
},
[MessageCategory.Trade] = new HashSet<ChatType> {
ChatType.None,
ChatType.Shout,
ChatType.Yell,
},
[MessageCategory.Community] = new HashSet<ChatType> {
ChatType.None,
ChatType.Shout,
ChatType.Yell,
},
[MessageCategory.Fluff] = new HashSet<ChatType> {
ChatType.None,
ChatType.Shout,
ChatType.Yell,
},
};

View File

@ -1,201 +0,0 @@
{
"version": 1,
"dependencies": {
"net7.0-windows7.0": {
"Dalamud.ContextMenu": {
"type": "Direct",
"requested": "[1.3.1, )",
"resolved": "1.3.1",
"contentHash": "ptAxut5PiLnzZ4G/KQdHJVcyklC/BF3otHJ7zYVUPiKBjsOCoF0n/6h2jK7e+8ev2Y1yAY3Wtx2GuXLFQgt9Uw=="
},
"DalamudPackager": {
"type": "Direct",
"requested": "[2.1.12, )",
"resolved": "2.1.12",
"contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg=="
},
"Fody": {
"type": "Direct",
"requested": "[6.8.0, )",
"resolved": "6.8.0",
"contentHash": "hfZ/f8Mezt8aTkgv9nsvFdYoQ809/AqwsJlOGOPYIfBcG2aAIG3v3ex9d8ZqQuFYyMoucjRg4eKy3VleeGodKQ=="
},
"Microsoft.ML": {
"type": "Direct",
"requested": "[2.0.1, )",
"resolved": "2.0.1",
"contentHash": "yD5kWZfisykwiGG66wJToSicY9MP847Grl8kLALQyqyiyQjr408ChdGW1JG7D0wHN7Zbs1KkCZvidi6pMFYR/A==",
"dependencies": {
"Microsoft.ML.CpuMath": "2.0.1",
"Microsoft.ML.DataView": "2.0.1",
"Newtonsoft.Json": "13.0.1",
"System.CodeDom": "4.5.0",
"System.Collections.Immutable": "1.5.0",
"System.Memory": "4.5.3",
"System.Reflection.Emit.Lightweight": "4.3.0",
"System.Threading.Channels": "4.7.1"
}
},
"Resourcer.Fody": {
"type": "Direct",
"requested": "[1.8.1, )",
"resolved": "1.8.1",
"contentHash": "FPeK4jKyyX5+mIjTnHNReGZk2/2xDhmu44UsBI5w9WEhbr4oTMmht3rnBr46A+GCGepC4+2N41K4vExDYiGNVQ==",
"dependencies": {
"Fody": "6.6.4"
}
},
"XivCommon": {
"type": "Direct",
"requested": "[9.0.0, )",
"resolved": "9.0.0",
"contentHash": "avaBp3FmSCi/PiQhntCeBDYOHejdyTWmFtz4pRBVQQ8vHkmRx+YTk1la9dkYBMlXxRXKckEdH1iI1Fu61JlE7w=="
},
"YamlDotNet": {
"type": "Direct",
"requested": "[13.4.0, )",
"resolved": "13.4.0",
"contentHash": "XkqTRgpt/tkqX9sOKcdPAZLVMktR5sBFwt7aK/PP061k9yoUntr/Qc8o9KshjSte34WYTIuCrpBs1+LwR7dFdA=="
},
"Microsoft.ML.CpuMath": {
"type": "Transitive",
"resolved": "2.0.1",
"contentHash": "UjxC9Ju6QPqyvTkj4ggsvnsqKYnbGO1TEypDzKDiIPBGlU/t7Pvx+oV9DDVhZzDKvb34zpLhAm/g79oBuJS3aw=="
},
"Microsoft.ML.DataView": {
"type": "Transitive",
"resolved": "2.0.1",
"contentHash": "w+GkAXlxaut65Lm+Fbp34YTfp0/9jGRn9uiVlL7Lls0/v+4IJM7SMTHfhvegPU48cyI6K2kzaK9j2Va/labhTA==",
"dependencies": {
"System.Collections.Immutable": "1.5.0",
"System.Memory": "4.5.3"
}
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
},
"Microsoft.NETCore.Targets": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.1",
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
},
"System.CodeDom": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "gqpR1EeXOuzNQWL7rOzmtdIz3CaXVjSQCiaGOs2ivjPwynKSJYm39X81fdlp7WuojZs/Z5t1k5ni7HtKQurhjw=="
},
"System.Collections.Immutable": {
"type": "Transitive",
"resolved": "1.5.0",
"contentHash": "EXKiDFsChZW0RjrZ4FYHu9aW6+P4MCgEDCklsVseRfhoO0F+dXeMSsMRAlVXIo06kGJ/zv+2w1a2uc2+kxxSaQ=="
},
"System.IO": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.3",
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
},
"System.Reflection": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Emit.ILGeneration": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==",
"dependencies": {
"System.Reflection": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Emit.Lightweight": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==",
"dependencies": {
"System.Reflection": "4.3.0",
"System.Reflection.Emit.ILGeneration": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Text.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Threading.Channels": {
"type": "Transitive",
"resolved": "4.7.1",
"contentHash": "6akRtHK/wab3246t4p5v3HQrtQk8LboOt5T4dtpNgsp3zvDeM4/Gx8V12t0h+c/W9/enUrilk8n6EQqdQorZAA=="
},
"System.Threading.Tasks": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"nosoliciting.interface": {
"type": "Project",
"dependencies": {
"Microsoft.ML": "[2.0.1, )"
}
}
}
}
}