2023-09-18 16:30:24 +01:00
using System.Collections.Concurrent ;
using Common.Models.Input ;
2021-08-13 16:22:10 +01:00
using Newtonsoft.Json.Linq ;
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
{
2023-08-15 12:05:31 +01:00
static readonly JsonSerializerOptions serialiserOptions = new ( ) { } ;
2021-11-26 14:50:07 +00:00
2023-09-18 16:30:24 +01:00
public static List < Datum > ParseAsync ( string dumpPath , HashSet < 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
2023-09-18 16:30:24 +01:00
var parsedBotsDict = new HashSet < Datum > ( ) ;
var dictionaryLock = new object ( ) ;
2023-09-18 17:15:30 +01:00
2021-11-26 14:50:07 +00:00
int totalDupeCount = 0 ;
2023-09-18 17:15:30 +01:00
2023-09-18 16:30:24 +01:00
var tasks = new List < Task > ( 50 ) ;
foreach ( var file in botFiles )
2021-11-26 14:50:07 +00:00
{
2023-09-18 16:30:24 +01:00
tasks . Add ( Task . Factory . StartNew ( ( ) = >
2023-08-15 09:29:16 +00:00
{
2023-09-18 16:30:24 +01:00
var splitFilePath = file . Split ( "\\" ) ;
2021-08-12 17:19:54 +01:00
2023-09-18 16:30:24 +01:00
int dupeCount = 0 ;
var rawInputString = File . ReadAllText ( file ) ;
2021-08-12 17:19:54 +01:00
2023-09-18 16:30:24 +01:00
List < Datum > bots = null ;
try
2021-11-26 14:50:07 +00:00
{
2023-09-18 16:30:24 +01:00
bots = ParseJson ( rawInputString ) . ToList ( ) ;
2023-08-15 09:29:16 +00:00
}
2023-09-18 16:30:24 +01:00
catch ( Exception ex )
2023-08-15 09:29:16 +00:00
{
2023-09-18 16:30:24 +01:00
Console . WriteLine ( $"File parse fucked up: {file}" ) ;
throw ;
2021-08-12 16:52:06 +01:00
}
2023-08-15 09:29:16 +00:00
2023-09-18 16:30:24 +01:00
if ( bots = = null | | bots . Count = = 0 )
2021-08-12 16:52:06 +01:00
{
2023-09-18 16:30:24 +01:00
Console . WriteLine ( $"Skipping file: {splitFilePath.Last()}. no bots found, " ) ;
return ;
2023-08-15 09:29:16 +00:00
}
2023-08-15 12:05:31 +01:00
2023-09-18 16:30:24 +01:00
//Console.WriteLine($"parsing: {bots.Count} bots in file {splitFilePath.Last()}");
foreach ( var bot in bots )
2023-08-15 09:29:16 +00:00
{
2023-09-18 16:30:24 +01:00
// I have no idea
if ( bot . _id = = "6483938c53cc9087c70eae86" )
{
Console . WriteLine ( "oh no" ) ;
}
// We dont know how to parse this bot type, need to add it to types enum
if ( ! botTypes . Contains ( bot . Info . Settings . Role . ToLower ( ) ) )
{
continue ;
}
lock ( dictionaryLock )
{
// Bot already exists in dictionary, skip
if ( parsedBotsDict . Contains ( bot ) )
{
//var existingBot = parsedBotsDict[bot._id];
dupeCount + + ;
continue ;
}
if ( ! parsedBotsDict . Contains ( bot ) )
{
// Null out data we don't need for generating bots to save RAM
bot . Stats = null ;
bot . Encyclopedia = null ;
bot . Hideout = null ;
bot . ConditionCounters = null ;
bot . Bonuses = null ;
bot . BackendCounters = null ;
bot . InsuredItems = null ;
parsedBotsDict . Add ( bot ) ;
}
}
2021-08-12 16:52:06 +01:00
}
2023-09-18 16:30:24 +01:00
totalDupeCount + = dupeCount ;
} ) ) ;
}
2021-08-12 16:52:06 +01:00
2023-09-18 16:30:24 +01:00
Task . WaitAll ( tasks . ToArray ( ) ) ;
2021-11-26 14:50:07 +00:00
stopwatch . Stop ( ) ;
2023-09-18 17:15:30 +01:00
2023-09-18 16:30:24 +01:00
LoggingHelpers . LogToConsole ( $"Cleaned and Parsed: {parsedBotsDict.Count} bots. {totalDupeCount} dupes were ignored. Took {LoggingHelpers.LogTimeTaken(stopwatch.Elapsed.TotalSeconds)} seconds" ) ;
2021-11-26 14:50:07 +00:00
2023-09-18 16:30:24 +01:00
return parsedBotsDict . ToList ( ) ;
2021-11-26 14:50:07 +00:00
}
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
}
}