2021-09-18 22:36:59 +01:00
using Common.Models.Input ;
2021-08-13 16:22:10 +01:00
using Newtonsoft.Json.Linq ;
2023-08-15 09:29:16 +00:00
using System.Collections.Concurrent ;
2021-08-12 16:52:06 +01:00
using System.Collections.Generic ;
using System.Diagnostics ;
using System.IO ;
using System.Linq ;
2021-11-26 14:50:07 +00:00
using System.Text.Json ;
2021-08-31 18:52:28 +01:00
using System.Threading.Tasks ;
2021-08-12 16:52:06 +01:00
2021-11-26 14:50:07 +00:00
namespace Common.Bots ;
public static class BotParser
2021-08-12 16:52:06 +01:00
{
2021-11-26 14:50:07 +00:00
static JsonSerializerOptions serialiserOptions = new JsonSerializerOptions { } ;
2023-08-15 09:29:16 +00:00
public static async Task < List < Datum > > ParseAsync ( string dumpPath , string [ ] botTypes )
2021-08-12 16:52:06 +01:00
{
2021-11-26 14:50:07 +00:00
var stopwatch = Stopwatch . StartNew ( ) ;
2021-08-12 16:52:06 +01:00
2021-11-26 14:50:07 +00:00
DiskHelpers . CreateDirIfDoesntExist ( dumpPath ) ;
2021-08-12 16:52:06 +01:00
2021-11-26 14:50:07 +00:00
var botFiles = Directory . GetFiles ( dumpPath , "*.json" , SearchOption . TopDirectoryOnly ) . ToList ( ) ;
LoggingHelpers . LogToConsole ( $"{botFiles.Count} bot dump files found" ) ;
2021-08-12 16:52:06 +01:00
2021-11-26 14:50:07 +00:00
var parsedBotsDict = new Dictionary < string , Datum > ( 10000 ) ;
int totalDupeCount = 0 ;
2021-08-12 16:52:06 +01:00
2021-11-26 14:50:07 +00:00
ParallelOptions parallelOptions = new ( )
{
2023-08-15 09:29:16 +00:00
MaxDegreeOfParallelism = 1
2021-11-26 14:50:07 +00:00
} ;
2023-08-15 09:29:16 +00:00
await Parallel . ForEachAsync ( botFiles , parallelOptions , async ( file , token ) = >
2021-11-26 14:50:07 +00:00
{
var splitFilePath = file . Split ( "\\" ) ;
2021-08-13 16:22:10 +01:00
2021-11-26 14:50:07 +00:00
int dupeCount = 0 ;
var rawInputString = await ReadFileContentsAsync ( file ) ;
2021-08-13 16:22:10 +01:00
2023-08-15 09:29:16 +00:00
//var json = rawInputString;
//if (rawInputString.Contains("location\":1,"))
//{
// json = PruneMalformedBsgJson(rawInputString, splitFilePath.Last());
//}
List < Datum > bots = null ;
try
{
bots = ParseJson ( rawInputString ) . ToList ( ) ;
}
catch ( Exception ex )
2021-11-26 14:50:07 +00:00
{
2023-08-15 09:29:16 +00:00
Console . WriteLine ( $"file parse fucked up: {file}" ) ;
throw ;
2021-11-26 14:50:07 +00:00
}
2021-08-12 17:19:54 +01:00
2023-08-15 09:29:16 +00:00
2021-11-26 14:50:07 +00:00
if ( bots = = null | | bots . Count = = 0 )
{
Console . WriteLine ( $"skipping file: {splitFilePath.Last()}. no bots found, " ) ;
return ;
}
2021-08-12 17:19:54 +01:00
2021-11-26 14:50:07 +00:00
Console . WriteLine ( $"parsing: {bots.Count} bots in file {splitFilePath.Last()}" ) ;
foreach ( var bot in bots )
{
2023-08-15 09:29:16 +00:00
if ( bot . _id = = "6483938c53cc9087c70eae86" )
2021-11-26 14:50:07 +00:00
{
2023-08-15 09:29:16 +00:00
Console . WriteLine ( "oh no" ) ;
}
if ( ! botTypes . Contains ( bot . Info . Settings . Role . ToLower ( ) ) )
{
continue ;
2021-08-12 16:52:06 +01:00
}
2023-08-15 09:29:16 +00:00
if ( parsedBotsDict . ContainsKey ( bot . _id ) )
2021-08-12 16:52:06 +01:00
{
2023-08-15 09:29:16 +00:00
//var existingBot = parsedBotsDict[bot._id];
2021-11-26 14:50:07 +00:00
dupeCount + + ;
2023-08-15 09:29:16 +00:00
continue ;
}
if ( ! parsedBotsDict . ContainsKey ( bot . _id ) )
{
parsedBotsDict . Add ( bot . _id , bot ) ;
2021-08-12 16:52:06 +01:00
}
2021-11-26 14:50:07 +00:00
}
2021-08-12 16:52:06 +01:00
2021-11-26 14:50:07 +00:00
totalDupeCount + = dupeCount ;
} ) ;
2021-08-12 16:52:06 +01:00
2021-11-26 14:50:07 +00:00
stopwatch . Stop ( ) ;
LoggingHelpers . LogToConsole ( $"Cleaned and Parsed: {parsedBotsDict.Count} bots. {totalDupeCount} dupes were ignored. Took {LoggingHelpers.LogTimeTaken(stopwatch.Elapsed.TotalSeconds)} seconds" ) ;
2021-08-12 16:52:06 +01:00
2021-11-26 14:50:07 +00:00
return ( parsedBotsDict . Select ( x = > x . Value ) ) . ToList ( ) ;
}
private static async Task < string > ReadFileContentsAsync ( string file )
{
using var reader = File . OpenText ( file ) ;
return await reader . ReadToEndAsync ( ) ;
}
private static string PruneMalformedBsgJson ( string json , string fileName )
{
// Bsg send json where an item has a location of 1 but it should be an object with x/y/z coords
var o = JObject . Parse ( json ) ;
var jItemsToReplace = o . SelectTokens ( "$.data[*].Inventory.items[?(@.location == 1)].location" ) ;
//var jItemsToReplace = o.SelectTokens("$.data[*].Inventory.items[?(@.location == 1 && @.slotId == 'cartridges')].location");
2021-08-12 16:52:06 +01:00
2021-11-26 14:50:07 +00:00
if ( jItemsToReplace ! = null & & jItemsToReplace . Any ( ) )
{
LoggingHelpers . LogToConsole ( $"file {fileName} has {jItemsToReplace.Count()} json issues, cleaning up." , ConsoleColor . Yellow ) ;
foreach ( var item in jItemsToReplace )
2021-08-13 16:22:10 +01:00
{
2021-11-26 14:50:07 +00:00
var obj = new { x = 1 , y = 0 , r = 0 } ;
item . Replace ( JToken . FromObject ( obj ) ) ;
2021-08-13 16:22:10 +01:00
}
2021-08-12 16:52:06 +01:00
}
2021-11-26 14:50:07 +00:00
var returnString = o . ToString ( ) ;
2021-08-12 16:52:06 +01:00
2021-11-26 14:50:07 +00:00
o = null ;
jItemsToReplace = null ;
2021-08-31 18:52:28 +01:00
2021-11-26 14:50:07 +00:00
return returnString ;
}
2023-08-15 09:29:16 +00:00
private static IEnumerable < Datum > ParseJson ( string json )
2021-11-26 14:50:07 +00:00
{
var deSerialisedObject = JsonSerializer . Deserialize < Root > ( json , serialiserOptions ) ;
return deSerialisedObject . data ;
2021-08-12 16:52:06 +01:00
}
}