2021-01-30 21:02:37 +00:00
|
|
|
|
using System;
|
2021-02-12 16:55:16 +00:00
|
|
|
|
using System.Diagnostics;
|
2021-01-30 21:02:37 +00:00
|
|
|
|
using System.IO;
|
2021-02-12 16:55:16 +00:00
|
|
|
|
using System.Threading.Tasks;
|
2021-01-30 21:02:37 +00:00
|
|
|
|
using JKang.IpcServiceFramework.Hosting;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Microsoft.Extensions.Hosting;
|
|
|
|
|
using Microsoft.ML;
|
|
|
|
|
using NoSoliciting.Interface;
|
|
|
|
|
using NoSoliciting.Internal.Interface;
|
|
|
|
|
|
|
|
|
|
namespace NoSoliciting.MessageClassifier {
|
|
|
|
|
internal static class Program {
|
2021-02-12 16:55:16 +00:00
|
|
|
|
private static void Main(string[] args) {
|
|
|
|
|
if (!int.TryParse(args[0], out var gamePid)) {
|
|
|
|
|
Console.WriteLine("No game PID provided.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var gameName = args[1];
|
2021-03-02 17:53:56 +00:00
|
|
|
|
var pipeId = args[2];
|
2021-02-12 16:55:16 +00:00
|
|
|
|
|
|
|
|
|
var host = Host.CreateDefaultBuilder()
|
2021-01-30 21:02:37 +00:00
|
|
|
|
.ConfigureServices(services => {
|
|
|
|
|
services.AddSingleton<IClassifier, ClassifierService>();
|
|
|
|
|
})
|
|
|
|
|
.ConfigureIpcHost(builder => {
|
|
|
|
|
builder.AddNamedPipeEndpoint<IClassifier>(options => {
|
2021-03-02 17:53:56 +00:00
|
|
|
|
options.PipeName = $"NoSoliciting.MessageClassifier-{pipeId}";
|
2021-01-30 21:02:37 +00:00
|
|
|
|
options.Serializer = new BetterIpcSerialiser();
|
|
|
|
|
});
|
|
|
|
|
})
|
2021-02-12 16:55:16 +00:00
|
|
|
|
.Build();
|
|
|
|
|
|
|
|
|
|
Task.Run(async () => {
|
|
|
|
|
while (true) {
|
|
|
|
|
Process process;
|
|
|
|
|
try {
|
|
|
|
|
process = Process.GetProcessById(gamePid);
|
|
|
|
|
} catch (Exception) {
|
|
|
|
|
await host.StopAsync();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (process.ProcessName != gameName) {
|
|
|
|
|
await host.StopAsync();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await Task.Delay(5_000);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
host.Run();
|
2021-01-30 21:02:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal class ClassifierService : IClassifier, IDisposable {
|
|
|
|
|
private MLContext Context { get; set; } = null!;
|
|
|
|
|
private ITransformer Model { get; set; } = null!;
|
|
|
|
|
private DataViewSchema Schema { get; set; } = null!;
|
|
|
|
|
private PredictionEngine<Data, Prediction>? PredictionEngine { get; set; }
|
|
|
|
|
|
|
|
|
|
public void Initialise(byte[] data) {
|
|
|
|
|
if (this.PredictionEngine != null) {
|
|
|
|
|
this.PredictionEngine.Dispose();
|
|
|
|
|
this.PredictionEngine = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.Context = new MLContext();
|
|
|
|
|
this.Context.ComponentCatalog.RegisterAssembly(typeof(Data).Assembly);
|
|
|
|
|
using var stream = new MemoryStream(data);
|
|
|
|
|
var model = this.Context.Model.Load(stream, out var schema);
|
|
|
|
|
this.Model = model;
|
|
|
|
|
this.Schema = schema;
|
|
|
|
|
this.PredictionEngine = this.Context.Model.CreatePredictionEngine<Data, Prediction>(this.Model, this.Schema);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string Classify(ushort channel, string message) {
|
|
|
|
|
return this.PredictionEngine?.Predict(new Data(channel, message))?.Category ?? "UNKNOWN";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose() {
|
|
|
|
|
this.PredictionEngine?.Dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|