prototype for assort verification
This commit is contained in:
parent
03e778c7c6
commit
2e7a4cf358
AssortValidator.Common.Models
AssortValidator.Common
Assets
AssortValidator.Common.csprojHelpers
AssortHelper.csDiskHelpers.csInputFileHelper.csItemTemplateHelper.csLoggingHelpers.csQuestHelper.csTraderHelper.csValueCheckerHelper.cs
Models
AssortValidator
AssortValidator.csproj
README.mdExamples
jaeger.resp.client.trading.api.getTraderAssort.5c0647fdd443bc2504c2d371_2021-09-03_06-50-00.jsonmechanic.resp.client.trading.api.getTraderAssort.5a7c2eca46aef81a7ca2145d_2021-09-03_06-49-40.jsonpeacekeeper.resp.client.trading.api.getTraderAssort.5935c25fb3acc3127c3d8cd9_2021-09-03_06-49-32.jsonprapaor.resp.client.trading.api.getTraderAssort.54cb50c76803fa8b248b4571_2021-09-03_06-49-10.jsonragman.resp.client.trading.api.getTraderAssort.5ac3b934156ae10c4430e83c_2021-09-03_06-49-48.jsonresp.client.quest.list_2021-09-03_06-49-04.jsonskier.resp.client.trading.api.getTraderAssort.58330581ace78e27b8b10cee_2021-09-03_06-49-24.jsontherapist.resp.client.trading.api.getTraderAssort.54cb57776803fa99248b456e_2021-09-03_06-49-19.json
Program.cs@ -0,0 +1,7 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
14
AssortValidator.Common.Models/TraderType.cs
Normal file
14
AssortValidator.Common.Models/TraderType.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace AssortValidator.Common.Models
|
||||||
|
{
|
||||||
|
public enum Trader
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
Prapor = 1,
|
||||||
|
Therapist = 2,
|
||||||
|
Skier = 3,
|
||||||
|
Peacekeeper = 4,
|
||||||
|
Mechanic = 5,
|
||||||
|
Ragman = 6,
|
||||||
|
Jaeger = 7
|
||||||
|
}
|
||||||
|
}
|
248814
AssortValidator.Common/Assets/items.json
Normal file
248814
AssortValidator.Common/Assets/items.json
Normal file
File diff suppressed because it is too large
Load Diff
17
AssortValidator.Common/AssortValidator.Common.csproj
Normal file
17
AssortValidator.Common/AssortValidator.Common.csproj
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AssortValidator.Common.Models\AssortValidator.Common.Models.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Assets\items.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
117
AssortValidator.Common/Helpers/AssortHelper.cs
Normal file
117
AssortValidator.Common/Helpers/AssortHelper.cs
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
using AssortHelpers.Common.Helpers;
|
||||||
|
using AssortValidator.Common.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace AssortValidator.Common.Helpers
|
||||||
|
{
|
||||||
|
public static class AssortHelper
|
||||||
|
{
|
||||||
|
private static Dictionary<Trader, Assort> _assortDataCache;
|
||||||
|
private static Dictionary<Trader, LiveAssort> _assortLiveDataCache;
|
||||||
|
|
||||||
|
public static Dictionary<Trader, Assort> GetAssortData()
|
||||||
|
{
|
||||||
|
if (_assortDataCache == null)
|
||||||
|
{
|
||||||
|
_assortDataCache = new Dictionary<Trader, Assort>();
|
||||||
|
foreach (var filePath in InputFileHelper.GetInputFilePaths().Where(x => x.EndsWith("\\assort.json")))
|
||||||
|
{
|
||||||
|
var traderType = GetTraderType(filePath);
|
||||||
|
var json = File.ReadAllText(filePath);
|
||||||
|
var parsedAssorts = JsonSerializer.Deserialize<Assort>(json);
|
||||||
|
|
||||||
|
if (traderType != Trader.Unknown)
|
||||||
|
{
|
||||||
|
_assortDataCache.Add(traderType, parsedAssorts);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _assortDataCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Trader GetTraderType(string filePath)
|
||||||
|
{
|
||||||
|
if (filePath.Contains("54cb50c76803fa8b248b4571"))
|
||||||
|
{
|
||||||
|
return Trader.Prapor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePath.Contains("54cb57776803fa99248b456e"))
|
||||||
|
{
|
||||||
|
return Trader.Therapist;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePath.Contains("58330581ace78e27b8b10cee"))
|
||||||
|
{
|
||||||
|
return Trader.Skier;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePath.Contains("5935c25fb3acc3127c3d8cd9"))
|
||||||
|
{
|
||||||
|
return Trader.Peacekeeper;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePath.Contains("5a7c2eca46aef81a7ca2145d"))
|
||||||
|
{
|
||||||
|
return Trader.Mechanic;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePath.Contains("5ac3b934156ae10c4430e83c"))
|
||||||
|
{
|
||||||
|
return Trader.Ragman;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePath.Contains("5c0647fdd443bc2504c2d371"))
|
||||||
|
{
|
||||||
|
return Trader.Jaeger;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Trader.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<Trader, LiveAssort> GetLiveAssortData()
|
||||||
|
{
|
||||||
|
if (_assortLiveDataCache == null)
|
||||||
|
{
|
||||||
|
_assortLiveDataCache = new Dictionary<Trader, LiveAssort>();
|
||||||
|
foreach (var filePath in InputFileHelper.GetInputFilePaths().Where(x => x.Contains("resp.client.trading.api.getTraderAssort")))
|
||||||
|
{
|
||||||
|
var traderType = GetTraderType(filePath);
|
||||||
|
var json = File.ReadAllText(filePath);
|
||||||
|
var parsedAssorts = JsonSerializer.Deserialize<LiveAssortRoot>(json);
|
||||||
|
|
||||||
|
if (traderType != Trader.Unknown)
|
||||||
|
{
|
||||||
|
_assortLiveDataCache.Add(traderType, parsedAssorts.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _assortLiveDataCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assume level 1 if it doesnt exist
|
||||||
|
/// </summary>
|
||||||
|
public static int GetAssortLoyaltyLevel(string assortId, Assort assort)
|
||||||
|
{
|
||||||
|
int assortLoyaltyLevel = 1;
|
||||||
|
if (!assort.loyal_level_items.ContainsKey(assortId))
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogWarning($"No offline loyalty level record found for itemId: {assortId} assuming level 1");
|
||||||
|
LoggingHelpers.LogInfo("");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assortLoyaltyLevel = assort.loyal_level_items[assortId];
|
||||||
|
}
|
||||||
|
|
||||||
|
return assortLoyaltyLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
AssortValidator.Common/Helpers/DiskHelpers.cs
Normal file
21
AssortValidator.Common/Helpers/DiskHelpers.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace AssortHelpers.Helpers
|
||||||
|
{
|
||||||
|
public static class DiskHelpers
|
||||||
|
{
|
||||||
|
public static void CreateDirIfDoesntExist(string path)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists($"{path}"))
|
||||||
|
{
|
||||||
|
//create dump dir
|
||||||
|
Directory.CreateDirectory($"{path}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] GetJsonFiles(string path)
|
||||||
|
{
|
||||||
|
return Directory.GetFiles(path, "*.json", SearchOption.AllDirectories);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
AssortValidator.Common/Helpers/InputFileHelper.cs
Normal file
21
AssortValidator.Common/Helpers/InputFileHelper.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using AssortHelpers.Helpers;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AssortHelpers.Common.Helpers
|
||||||
|
{
|
||||||
|
public static class InputFileHelper
|
||||||
|
{
|
||||||
|
private static List<string> _inputFilePaths;
|
||||||
|
|
||||||
|
public static void SetInputFiles(string path)
|
||||||
|
{
|
||||||
|
_inputFilePaths = DiskHelpers.GetJsonFiles(path).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> GetInputFilePaths()
|
||||||
|
{
|
||||||
|
return _inputFilePaths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
AssortValidator.Common/Helpers/ItemTemplateHelper.cs
Normal file
78
AssortValidator.Common/Helpers/ItemTemplateHelper.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using AssortValidator.Common.Helpers;
|
||||||
|
using AssortValidator.Common.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace AssortValidator.Common
|
||||||
|
{
|
||||||
|
public static class ItemTemplateHelper
|
||||||
|
{
|
||||||
|
private static Dictionary<string, ItemLookup> _itemCache;
|
||||||
|
|
||||||
|
public static Dictionary<string, ItemLookup> Items
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_itemCache == null)
|
||||||
|
{
|
||||||
|
var itemsFilePath = $"{Directory.GetCurrentDirectory()}\\Assets\\items.json";
|
||||||
|
if (!File.Exists(itemsFilePath))
|
||||||
|
{
|
||||||
|
throw new Exception($"Missing items.json under assets ({itemsFilePath})");
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemsJson = File.ReadAllText(itemsFilePath);
|
||||||
|
_itemCache = JsonSerializer.Deserialize<Dictionary<string, ItemLookup>>(itemsJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _itemCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemLookup GetTemplateById(string templateId)
|
||||||
|
{
|
||||||
|
if (templateId == "5449016a4bdc2d6f028b456f")
|
||||||
|
{
|
||||||
|
return new ItemLookup
|
||||||
|
{
|
||||||
|
_id = templateId,
|
||||||
|
_name = "Roubles",
|
||||||
|
_parent = "543be5dd4bdc2deb348b4569",
|
||||||
|
_type = ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (templateId == "569668774bdc2da2298b4568")
|
||||||
|
{
|
||||||
|
return new ItemLookup
|
||||||
|
{
|
||||||
|
_id = templateId,
|
||||||
|
_name = "Euros",
|
||||||
|
_parent = "543be5dd4bdc2deb348b4569",
|
||||||
|
_type = ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (templateId == "5696686a4bdc2da3298b456a")
|
||||||
|
{
|
||||||
|
return new ItemLookup
|
||||||
|
{
|
||||||
|
_id = templateId,
|
||||||
|
_name = "Dollars",
|
||||||
|
_parent = "543be5dd4bdc2deb348b4569",
|
||||||
|
_type = ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Items.ContainsKey(templateId))
|
||||||
|
{
|
||||||
|
return Items[templateId];
|
||||||
|
}
|
||||||
|
|
||||||
|
LoggingHelpers.LogToConsole($"Could not locate item template with id {templateId}", ConsoleColor.Red);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
AssortValidator.Common/Helpers/LoggingHelpers.cs
Normal file
79
AssortValidator.Common/Helpers/LoggingHelpers.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AssortValidator.Common.Helpers
|
||||||
|
{
|
||||||
|
public static class LoggingHelpers
|
||||||
|
{
|
||||||
|
public static string LogTimeTaken(double totalSeconds)
|
||||||
|
{
|
||||||
|
return Math.Round(totalSeconds, 2, MidpointRounding.ToEven).ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogWarning(string message)
|
||||||
|
{
|
||||||
|
Console.BackgroundColor = ConsoleColor.DarkYellow;
|
||||||
|
Console.ForegroundColor = ConsoleColor.Black;
|
||||||
|
|
||||||
|
LogMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogInfo(string message)
|
||||||
|
{
|
||||||
|
Console.BackgroundColor = ConsoleColor.Gray;
|
||||||
|
Console.ForegroundColor = ConsoleColor.Black;
|
||||||
|
|
||||||
|
LogMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogSuccess(string message)
|
||||||
|
{
|
||||||
|
Console.BackgroundColor = ConsoleColor.Green;
|
||||||
|
Console.ForegroundColor = ConsoleColor.Black;
|
||||||
|
|
||||||
|
LogMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogError(string message)
|
||||||
|
{
|
||||||
|
Console.BackgroundColor = ConsoleColor.Red;
|
||||||
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
|
|
||||||
|
LogMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogToConsole(string message, ConsoleColor backgroundColour = ConsoleColor.Green)
|
||||||
|
{
|
||||||
|
Console.BackgroundColor = backgroundColour;
|
||||||
|
Console.ForegroundColor = ConsoleColor.Black;
|
||||||
|
|
||||||
|
LogMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ResetConsoleColours()
|
||||||
|
{
|
||||||
|
Console.BackgroundColor = ConsoleColor.Black;
|
||||||
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogNewLine()
|
||||||
|
{
|
||||||
|
ResetConsoleColours();
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogHeading(string message)
|
||||||
|
{
|
||||||
|
Console.BackgroundColor = ConsoleColor.Cyan;
|
||||||
|
Console.ForegroundColor = ConsoleColor.Black;
|
||||||
|
|
||||||
|
LogMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void LogMessage(string message)
|
||||||
|
{
|
||||||
|
Console.Write(message);
|
||||||
|
ResetConsoleColours();
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
287
AssortValidator.Common/Helpers/QuestHelper.cs
Normal file
287
AssortValidator.Common/Helpers/QuestHelper.cs
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
using AssortHelpers.Common.Helpers;
|
||||||
|
using AssortValidator.Common.Helpers.Models;
|
||||||
|
using AssortValidator.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace AssortValidator.Common.Helpers
|
||||||
|
{
|
||||||
|
public static class QuestHelper
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<string, string> questNames = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "5936d90786f7742b1420ba5b", "Debut" },
|
||||||
|
{ "5936da9e86f7742d65037edf", "Checking"},
|
||||||
|
{ "59674cd986f7744ab26e32f2", "Shootout picnic"},
|
||||||
|
{ "59674eb386f774539f14813a", "Delivery from the past"},
|
||||||
|
{ "5967530a86f77462ba22226b", "Bad rep evidence"},
|
||||||
|
{ "59675d6c86f7740a842fc482", "Ice cream cones"},
|
||||||
|
{ "59675ea386f77414b32bded2", "Postman Pat"},
|
||||||
|
{ "596760e186f7741e11214d58", "Postman Pat, p. 2"},
|
||||||
|
{ "5967725e86f774601a446662", "Shaking up teller"},
|
||||||
|
{ "5967733e86f774602332fc84", "Shortage"},
|
||||||
|
{ "59689ee586f7740d1570bbd5", "Sanitary Standards, p. 1"},
|
||||||
|
{ "59689fbd86f7740d137ebfc4", "Operation Aquarius"},
|
||||||
|
{ "5968eb3186f7741dde183a4d", "Operation Aquarius, p. 2"},
|
||||||
|
{ "5969f90786f77420d2328015", "Painkiller"},
|
||||||
|
{ "5969f9e986f7741dde183a50", "Pharmacist"},
|
||||||
|
{ "596a0e1686f7741ddf17dbee", "Supply plans"},
|
||||||
|
{ "596a101f86f7741ddb481582", "Kind of sabotage" },
|
||||||
|
{ "596a1e6c86f7741ddc2d3206", "General wares"},
|
||||||
|
{ "596a204686f774576d4c95de", "Sanitary Standards, p. 2"},
|
||||||
|
{ "596a218586f77420d232807c", "Car repair"},
|
||||||
|
{ "596b36c586f77450d6045ad2", "Supplier"},
|
||||||
|
{ "596b43fb86f77457ca186186", "The Extortionist"},
|
||||||
|
{ "596b455186f77457cb50eccb", "Stirrup"},
|
||||||
|
{ "5979ed3886f77431307dc512", "What’s on the flash drive?"},
|
||||||
|
{ "5979eee086f774311955e614", "Golden swag"},
|
||||||
|
{ "5979f8bb86f7743ec214c7a6", "Polikhim hobo"},
|
||||||
|
{ "5979f9ba86f7740f6c3fe9f2", "Chemical, p.1"},
|
||||||
|
{ "597a0b2986f77426d66c0633", "Chemical, p. 2"},
|
||||||
|
{ "597a0e5786f77426d66c0636", "Chemical, p. 3"},
|
||||||
|
{ "597a0f5686f774273b74f676", "Chemical, p. 4"},
|
||||||
|
{ "597a160786f77477531d39d2", "Out of curiosity"},
|
||||||
|
{ "597a171586f77405ba6887d3", "Big customer"},
|
||||||
|
{ "59c124d686f774189b3c843f", "BP depot"},
|
||||||
|
{ "59c50a9e86f7745fef66f4ff", "The Punisher"},
|
||||||
|
{ "59c50c8886f7745fed3193bf", "The Punisher. Part 2."},
|
||||||
|
{ "59c512ad86f7741f0d09de9b", "The Punisher. Part 3."},
|
||||||
|
{ "59c9392986f7742f6923add2", "Trust regain"},
|
||||||
|
{ "59c93e8e86f7742a406989c4", "Loyalty buyout"},
|
||||||
|
{ "59ca1a6286f774509a270942", "No offence"},
|
||||||
|
{ "59ca264786f77445a80ed044", "The Punisher. Part 4."},
|
||||||
|
{ "59ca29fb86f77445ab465c87", "The Punisher. Part 5."},
|
||||||
|
{ "59ca2eb686f77445a80ed049", "The Punisher. Part 6."},
|
||||||
|
{ "59f9da6786f774714230d751", ""},
|
||||||
|
{ "5a03153686f77442d90e2171", "Spa Tour. Part 1"},
|
||||||
|
{ "5a03173786f77451cb427172", "Spa Tour. Part 2"},
|
||||||
|
{ "5a0327ba86f77456b9154236", "Spa Tour. Part 3" },
|
||||||
|
{ "5a03296886f774569778596a", "Spa Tour. Part 4"},
|
||||||
|
{ "5a0449d586f77474e66227b7", "Spa Tour. Part 5"},
|
||||||
|
{ "5a27b75b86f7742e97191958", "Fishing Gear"},
|
||||||
|
{ "5a27b7a786f774579c3eb376", "Tigr Safari"},
|
||||||
|
{ "5a27b7d686f77460d847e6a6", " Scrap Metal"},
|
||||||
|
{ "5a27b80086f774429a5d7e20", "Eagle Eye"},
|
||||||
|
{ "5a27b87686f77460de0252a8", "Humanitarian Supplies"},
|
||||||
|
{ "5a27b9de86f77464e5044585", "The Cult. Part 1"},
|
||||||
|
{ "5a27ba1c86f77461ea5a3c56", "The Cult. Part 2"},
|
||||||
|
{ "5a27ba9586f7741b543d8e85", "Spa Tour. Part 6"},
|
||||||
|
{ "5a27bafb86f7741c73584017", "Spa Tour. Part 7"},
|
||||||
|
{ "5a27bb1e86f7741f27621b7e", "Cargo X. Part 1"},
|
||||||
|
{ "5a27bb3d86f77411ea361a21", "Cargo X. Part 2"},
|
||||||
|
{ "5a27bb5986f7741dfb660900", "Cargo X. Part 3"},
|
||||||
|
{ "5a27bb8386f7741c770d2d0a", "Wet Job. Part 1"},
|
||||||
|
{ "5a27bbf886f774333a418eeb", "Wet Job. Part 2"},
|
||||||
|
{ "5a27bc1586f7741f6d40fa2f", "Wet Job. Part 3"},
|
||||||
|
{ "5a27bc3686f7741c73584026", "Wet Job. Part 4"},
|
||||||
|
{ "5a27bc6986f7741c7358402b", "Wet Job. Part 5"},
|
||||||
|
{ "5a27bc8586f7741b543d8ea4", "Wet Job. Part 6"},
|
||||||
|
{ "5a27c99a86f7747d2c6bdd8e", "Friend from the West. Part 1"},
|
||||||
|
{ "5a27d2af86f7744e1115b323", "Friend from the West. Part 2"},
|
||||||
|
{ "5a5642ce86f77445c63c3419", "Hippocratic Vow"},
|
||||||
|
{ "5a68661a86f774500f48afb0", "Health Care Privacy. Part 1"},
|
||||||
|
{ "5a68663e86f774501078f78a", "Health Care Privacy. Part 2"},
|
||||||
|
{ "5a68665c86f774255929b4c7", "Health Care Privacy. Part 3"},
|
||||||
|
{ "5a68667486f7742607157d28", "Health Care Privacy. Part 4"},
|
||||||
|
{ "5a68669a86f774255929b4d4", "Health Care Privacy. Part 5"},
|
||||||
|
{ "5ac23c6186f7741247042bad", "Gunsmith. Part 1"},
|
||||||
|
{ "5ac2426c86f774138762edfe", "Gunsmith. Part 2"},
|
||||||
|
{ "5ac2428686f77412450b42bf", "Gunsmith. Part 3"},
|
||||||
|
{ "5ac242ab86f77412464f68b4", "Gunsmith. Part 5"},
|
||||||
|
{ "5ac244c486f77413e12cf945", "Gunsmith. Part 6"},
|
||||||
|
{ "5ac244eb86f7741356335af1", "Gunsmith. Part 4"},
|
||||||
|
{ "5ac345dc86f774288030817f", "Farming. Part 1" },
|
||||||
|
{ "5ac3460c86f7742880308185", "Farming. Part 2" },
|
||||||
|
{ "5ac3462b86f7741d6118b983", "Farming. Part 3" },
|
||||||
|
{ "5ac3464c86f7741d651d6877", "Farming. Part 4" },
|
||||||
|
{ "5ac3467986f7741d6224abc2", "Signal. Part 1" },
|
||||||
|
{ "5ac346a886f7744e1b083d67", "Signal. Part 2" },
|
||||||
|
{ "5ac346cf86f7741d63233a02", "Signal. Part 3" },
|
||||||
|
{ "5ac346e886f7741d6118b99b", "Signal. Part 4" },
|
||||||
|
{ "5ac3475486f7741d6224abd3", "Bad habit" },
|
||||||
|
{ "5ac3477486f7741d651d6885", "Scout" },
|
||||||
|
{ "5ac3479086f7742880308199", "Insider" },
|
||||||
|
{ "5ae3267986f7742a413592fe", "Gunsmith. Part 7" },
|
||||||
|
{ "5ae3270f86f77445ba41d4dd", "Gunsmith. Part 8" },
|
||||||
|
{ "5ae3277186f7745973054106", "Gunsmith. Part 9" },
|
||||||
|
{ "5ae327c886f7745c7b3f2f3f", "Gunsmith. Part 10" },
|
||||||
|
{ "5ae3280386f7742a41359364", "Gunsmith. Part 11" },
|
||||||
|
{ "5ae448a386f7744d3730fff0", "Only business" },
|
||||||
|
{ "5ae448bf86f7744d733e55ee", "Make ULTRA Great Again" },
|
||||||
|
{ "5ae448e586f7744dcf0c2a67", "Big sale" },
|
||||||
|
{ "5ae448f286f77448d73c0131", "The Blood of War" },
|
||||||
|
{ "5ae4490786f7744ca822adcc", "Dressed to kill" },
|
||||||
|
{ "5ae4493486f7744efa289417", "Database. Part 1" },
|
||||||
|
{ "5ae4493d86f7744b8e15aa8f", "Database. Part 2" },
|
||||||
|
{ "5ae4495086f77443c122bc40", "Sew it good. Part 1" },
|
||||||
|
{ "5ae4495c86f7744e87761355", "Sew it good. Part 2" },
|
||||||
|
{ "5ae4496986f774459e77beb6", "Sew it good. Part 3" },
|
||||||
|
{ "5ae4497b86f7744cf402ed00", "Sew it good. Part 4" },
|
||||||
|
{ "5ae4498786f7744bde357695", "The key to success" },
|
||||||
|
{ "5ae4499a86f77449783815db", "Charisma brings success" },
|
||||||
|
{ "5ae449a586f7744bde357696", "No fuss needed" },
|
||||||
|
{ "5ae449b386f77446d8741719", "Gratitude" },
|
||||||
|
{ "5ae449c386f7744bde357697", "Sales Night" },
|
||||||
|
{ "5ae449d986f774453a54a7e1", "Supervisor" },
|
||||||
|
{ "5b47749f86f7746c5d6a5fd4", "Gunsmith. Part 12" },
|
||||||
|
{ "5b47799d86f7746c5d6a5fd8", "Gunsmith. Part 13" },
|
||||||
|
{ "5b477b6f86f7747290681823", "Gunsmith. Part 14" },
|
||||||
|
{ "5b477f7686f7744d1b23c4d2", "Gunsmith. Part 15" },
|
||||||
|
{ "5b47825886f77468074618d3", "Gunsmith. Part 16" },
|
||||||
|
{ "5b47876e86f7744d1c353205", "The Blood of War Part 2" },
|
||||||
|
{ "5b47891f86f7744d1b23c571", "Living high is not a crime" },
|
||||||
|
{ "5b478b1886f7744d1b23c57d", "Hot delivery" },
|
||||||
|
{ "5b478d0f86f7744d190d91b5", "Minibus" },
|
||||||
|
{ "5b478eca86f7744642012254", "\"Vitamins\" p.1" },
|
||||||
|
{ "5b478ff486f7744d184ecbbf", "\"Vitamins\" p. 2" },
|
||||||
|
{ "5b47926a86f7747ccc057c15", "Informed means armed" },
|
||||||
|
{ "5b4794cb86f774598100d5d4", "Lend lease" },
|
||||||
|
{ "5b4795fb86f7745876267770", "Chumming" },
|
||||||
|
{ "5bc4776586f774512d07cf05", "\"The Tarkov shooter\" Part 1"},
|
||||||
|
{ "5bc479e586f7747f376c7da3", "\"The Tarkov shooter\" Part 2"},
|
||||||
|
{ "5bc47dbf86f7741ee74e93b9", "\"The Tarkov shooter\". Part 3" },
|
||||||
|
{ "5bc480a686f7741af0342e29", "\"The Tarkov shooter\". Part 4" },
|
||||||
|
{ "5bc4826c86f774106d22d88b", "\"The Tarkov shooter\". Part 5" },
|
||||||
|
{ "5bc4836986f7740c0152911c", "\"The Tarkov shooter\". Part 6" },
|
||||||
|
{ "5bc4856986f77454c317bea7", "\"The Tarkov shooter\". Part 7" },
|
||||||
|
{ "5bc4893c86f774626f5ebf3e", "\"The Tarkov shooter\". Part 8" },
|
||||||
|
{ "5c0bbaa886f7746941031d82", "Bullshit" },
|
||||||
|
{ "5c0bc91486f7746ab41857a2", "Silent caliber" },
|
||||||
|
{ "5c0bd01e86f7747cdd799e56", "Insomnia" },
|
||||||
|
{ "5c0bd94186f7747a727f09b2", "Test drive. Pt. 1" },
|
||||||
|
{ "5c0bdb5286f774166e38eed4", "Flint" },
|
||||||
|
{ "5c0bde0986f77479cf22c2f8", "A Shooter Born in Heaven" },
|
||||||
|
{ "5c0be13186f7746f016734aa", "Psycho Sniper" },
|
||||||
|
{ "5c0be5fc86f774467a116593", "Private clinic" },
|
||||||
|
{ "5c0d0d5086f774363760aef2", "Athlete" },
|
||||||
|
{ "5c0d0f1886f77457b8210226", "Lend lease. Part 2" },
|
||||||
|
{ "5c0d190cd09282029f5390d8", "Grenadier" },
|
||||||
|
{ "5c0d1c4cd0928202a02a6f5c", "Decontamination service" },
|
||||||
|
{ "5c0d4c12d09282029f539173", "Peacekeeping mission" },
|
||||||
|
{ "5c0d4e61d09282029f53920e", "The guide" },
|
||||||
|
{ "5c10f94386f774227172c572", "The Blood of War Pt. 3" },
|
||||||
|
{ "5c1128e386f7746565181106", "Fertilizers" },
|
||||||
|
{ "5c112d7e86f7740d6f647486", "Scavenger" },
|
||||||
|
{ "5c1141f386f77430ff393792", "Living high is not a crime Pt.2" },
|
||||||
|
{ "5c1234c286f77406fa13baeb", "Setup" },
|
||||||
|
{ "5c12452c86f7744b83469073", "Perfect mediator" },
|
||||||
|
{ "5c139eb686f7747878361a6f", "Import" },
|
||||||
|
{ "5c51aac186f77432ea65c552", "Collector" },
|
||||||
|
{ "5d2495a886f77425cd51e403", "Introduction" },
|
||||||
|
{ "5d24b81486f77439c92d6ba8", "Acquaintance" },
|
||||||
|
{ "5d25aed386f77442734d25d2", "The survivalist path. Unprotected, but dangerous"},
|
||||||
|
{ "5d25b6be86f77444001e1b89", "The survivalist path. Thrifty" },
|
||||||
|
{ "5d25bfd086f77442734d3007", "The survivalist path. Zhivchik" },
|
||||||
|
{ "5d25c81b86f77443e625dd71", "The survivalist path. Wounded beast" },
|
||||||
|
{ "5d25cf2686f77443e75488d4", "The survivalist path. Tough guy" },
|
||||||
|
{ "5d25d2c186f77443e35162e5", "The survivalist path. Cold blooded" },
|
||||||
|
{ "5d25dae186f77443e55d2f78", "The survivalist path. Zatoichi" },
|
||||||
|
{ "5d25e29d86f7740a22516326", "The survivalist path. Eagle-owl" },
|
||||||
|
{ "5d25e2a986f77409dd5cdf2a", "The survivalist path. Combat medic" },
|
||||||
|
{ "5eaaaa7c93afa0558f3b5a1c", "The survivalist path. Junkie" },
|
||||||
|
{ "5d25e2b486f77409de05bba0", "Huntsman path. Secured perimeter" },
|
||||||
|
{ "5d25e2c386f77443e7549029", "Huntsman path. The trophy" },
|
||||||
|
{ "5d25e2cc86f77443e47ae019", "Huntsman path. Woods cleaning" },
|
||||||
|
{ "5d25e2d886f77442734d335e", "Huntsman path. Controller" },
|
||||||
|
{ "5d25e2e286f77444001e2e48", "Huntsman path. Sell-out" },
|
||||||
|
{ "5d25e2ee86f77443e35162ea", "Huntsman path. Woods keeper" },
|
||||||
|
{ "5d25e43786f7740a212217fa", "Huntsman path. Justice" },
|
||||||
|
{ "5d25e44386f77409453bce7b", "Huntsman path. Evil watchman" },
|
||||||
|
{ "5d25e44f86f77443e625e385", "Huntsman path. Eraser" },
|
||||||
|
{ "5d25e45e86f77408251c4bfa", "Huntsman path. Eraser pt. 2" },
|
||||||
|
{ "5d25e46e86f77409453bce7c", "Ambulance" },
|
||||||
|
{ "5d25e48186f77443e625e386", "Courtesy visit" },
|
||||||
|
{ "5d25e48d86f77408251c4bfb", "Shady business" },
|
||||||
|
{ "5d25e4ad86f77443e625e387", "Nostalgia" },
|
||||||
|
{ "5d25e4b786f77408251c4bfc", "Fishing place" },
|
||||||
|
{ "5d25e4ca86f77409dd5cdf2c", "Hunting trip" },
|
||||||
|
{ "5d25e4d586f77443e625e388", "Reserv" },
|
||||||
|
{ "5d4bec3486f7743cac246665", "Regulated materials" },
|
||||||
|
{ "5d6fb2c086f77449da599c24", "An apple a day - keeps the doctor away" },
|
||||||
|
{ "5d6fbc2886f77449d825f9d3", "Mentor" },
|
||||||
|
{ "5dc53acb86f77469c740c893", "The stylish one" },
|
||||||
|
{ "5e381b0286f77420e3417a74", "Textile. Part 1" },
|
||||||
|
{ "5e4d515e86f77438b2195244", "Textile. Part 2" },
|
||||||
|
{ "5ede55112c95834b583f052a", "Bunker. Part 1" },
|
||||||
|
{ "5ede567cfa6dc072ce15d6e3", "Bunker. Part 2" },
|
||||||
|
{ "5eda19f0edce541157209cee", "Anesthesia" },
|
||||||
|
{ "5edab4b1218d181e29451435", "Huntsman path. Sadist" },
|
||||||
|
{ "5edab736cc183c769d778bc2", "Colleagues. Pt.1" },
|
||||||
|
{ "5edaba7c0c502106f869bc02", "Colleagues. Pt.2" },
|
||||||
|
{ "5edac34d0bb72a50635c2bfa", "Colleagues. Pt.3" },
|
||||||
|
{ "5edabd13218d181e29451442", "Rigged game" },
|
||||||
|
{ "5edac020218d181e29451446", "Samples" },
|
||||||
|
{ "5edac63b930f5454f51e128b", "TerraGroup employee" },
|
||||||
|
{ "5f04886a3937dc337a6b8238", "The chemistry closet" },
|
||||||
|
{ "5fd9fad9c1ce6b1a3b486d00", "Search Mission"},
|
||||||
|
{ "600302d73b897b11364cd161", "Hunter"},
|
||||||
|
{ "6086c852c945025d41566124", "Revision"},
|
||||||
|
{ "608a768d82e40b3c727fd17d", "Pest control" },
|
||||||
|
{ "6089736efa70fc097863b8f6", "Back door" },
|
||||||
|
{ "6089743983426423753cd58a", "Safe corridor" },
|
||||||
|
{ "608974af4b05530f55550c21", "Inventory check" },
|
||||||
|
{ "608974d01a66564e74191fc0", "Fuel matter" },
|
||||||
|
{ "60896bca6ee58f38c417d4f2", "No place for renegades" },
|
||||||
|
{ "60896e28e4a85c72ef3fa301", "Disease history" },
|
||||||
|
{ "60896b7bfa70fc097863b8f5", "Documents" },
|
||||||
|
{ "6089732b59b92115597ad789", "Surplus goods" },
|
||||||
|
{ "60896888e4a85c72ef3fa300", "Experience exchange" },
|
||||||
|
{ "60c0c018f7afb4354815096a", "Tagilla"},
|
||||||
|
{ "60e71dc0a94be721b065bbfc", "Intimidator" },
|
||||||
|
{ "60e71dc67fcf9c556f325056", "level 55 quest" },
|
||||||
|
{ "60e71e8ed54b755a3b53eb67", "Huntsman Path - Relentless" },
|
||||||
|
{ "60e729cf5698ee7b05057439", "Swift One" },
|
||||||
|
{ "60effd818b669d08a35bfad5", "The Choice" }
|
||||||
|
};
|
||||||
|
private static QuestRoot _liveQuestData;
|
||||||
|
|
||||||
|
public static QuestRoot GetLiveQuestData(string filename = "resp.client.quest.list")
|
||||||
|
{
|
||||||
|
if (_liveQuestData == null)
|
||||||
|
{
|
||||||
|
var questFilePath = InputFileHelper.GetInputFilePaths().FirstOrDefault(x => x.Contains(filename));
|
||||||
|
var questDataJson = File.ReadAllText(questFilePath);
|
||||||
|
_liveQuestData = JsonSerializer.Deserialize<QuestRoot>(questDataJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _liveQuestData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<QuestAssortUnlock> GetQuestAssortUnlocks(List<Quest> quests)
|
||||||
|
{
|
||||||
|
var results = new List<QuestAssortUnlock>();
|
||||||
|
|
||||||
|
foreach (var quest in quests)
|
||||||
|
{
|
||||||
|
foreach (var assortUnlockReward in quest.rewards.Success.Where(x=>x.type == "AssortmentUnlock"))
|
||||||
|
{
|
||||||
|
results.Add(new QuestAssortUnlock{
|
||||||
|
QuestId = quest._id,
|
||||||
|
QuestName = QuestHelper.GetQuestNameById(quest._id),
|
||||||
|
TraderId = assortUnlockReward.traderId,
|
||||||
|
TraderType = TraderHelper.GetTraderTypeById(assortUnlockReward.traderId),
|
||||||
|
AssortId = assortUnlockReward.items[0]._id,
|
||||||
|
AssortTemplateId = assortUnlockReward.items[0]._tpl,
|
||||||
|
LoyaltyLevel = assortUnlockReward.loyaltyLevel.GetValueOrDefault(0)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetQuestNameById(string id)
|
||||||
|
{
|
||||||
|
if (questNames.ContainsKey(id))
|
||||||
|
{
|
||||||
|
return questNames[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown Quest";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
AssortValidator.Common/Helpers/TraderHelper.cs
Normal file
44
AssortValidator.Common/Helpers/TraderHelper.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using AssortValidator.Common.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssortValidator.Common.Helpers
|
||||||
|
{
|
||||||
|
public static class TraderHelper
|
||||||
|
{
|
||||||
|
private static Dictionary<Trader, string> _traders;
|
||||||
|
|
||||||
|
public static Dictionary<Trader, string> GetTraders()
|
||||||
|
{
|
||||||
|
if (_traders == null)
|
||||||
|
{
|
||||||
|
_traders = new Dictionary<Trader, string>
|
||||||
|
{
|
||||||
|
{ Trader.Prapor, "54cb50c76803fa8b248b4571" },
|
||||||
|
{ Trader.Therapist, "54cb57776803fa99248b456e"},
|
||||||
|
{ Trader.Skier, "58330581ace78e27b8b10cee"},
|
||||||
|
{ Trader.Peacekeeper, "5935c25fb3acc3127c3d8cd9"},
|
||||||
|
{ Trader.Mechanic, "5a7c2eca46aef81a7ca2145d"},
|
||||||
|
{ Trader.Ragman, "5ac3b934156ae10c4430e83c"},
|
||||||
|
{ Trader.Jaeger, "5c0647fdd443bc2504c2d371"}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return _traders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Trader GetTraderTypeById(string traderId)
|
||||||
|
{
|
||||||
|
Trader returnType = 0;
|
||||||
|
foreach (var item in GetTraders())
|
||||||
|
{
|
||||||
|
if (item.Value == traderId)
|
||||||
|
{
|
||||||
|
returnType = item.Key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
AssortValidator.Common/Helpers/ValueCheckerHelper.cs
Normal file
41
AssortValidator.Common/Helpers/ValueCheckerHelper.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
namespace AssortValidator.Common.Helpers
|
||||||
|
{
|
||||||
|
public static class ValueCheckerHelper
|
||||||
|
{
|
||||||
|
public static void CheckValuesMatch(string firstValue, string secondValue, string message, string associatedId = "", bool performTemplateIdLookup = false)
|
||||||
|
{
|
||||||
|
if (firstValue != secondValue)
|
||||||
|
{
|
||||||
|
if (performTemplateIdLookup)
|
||||||
|
{
|
||||||
|
firstValue = $"{firstValue} ({ItemTemplateHelper.GetTemplateById(firstValue)._name})";
|
||||||
|
secondValue = $"{secondValue} ({ItemTemplateHelper.GetTemplateById(secondValue)._name})";
|
||||||
|
}
|
||||||
|
if (associatedId == string.Empty)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogWarning($"WARNING {message}: '{firstValue}', expected '{secondValue}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogWarning($"WARNING {associatedId} {message}: '{firstValue}', expected '{secondValue}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//LoggingHelpers.LogSuccess($"MATCH {firstValue} - {secondValue}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CheckValuesMatch(int firstValue, int secondValue, string message, string associatedId = "")
|
||||||
|
{
|
||||||
|
if (firstValue != secondValue)
|
||||||
|
{
|
||||||
|
if (associatedId == string.Empty)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogWarning($"WARNING {message}: '{firstValue}', expected '{secondValue}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogWarning($"WARNING {associatedId} {message}: '{firstValue}', expected '{secondValue}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
AssortValidator.Common/Models/Assort.cs
Normal file
36
AssortValidator.Common/Models/Assort.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssortValidator.Common.Models
|
||||||
|
{
|
||||||
|
public class Assort
|
||||||
|
{
|
||||||
|
public List<Item> items { get; set; }
|
||||||
|
public Dictionary<string, List<List<BarterDetails>>> barter_scheme { get; set; }
|
||||||
|
public Dictionary<string, int> loyal_level_items { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BarterDetails
|
||||||
|
{
|
||||||
|
public int count { get; set; }
|
||||||
|
public string _tpl { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Item
|
||||||
|
{
|
||||||
|
public string _id { get; set; }
|
||||||
|
public string _tpl { get; set; }
|
||||||
|
public string parentId { get; set; }
|
||||||
|
public string slotId { get; set; }
|
||||||
|
public Upd upd { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Upd
|
||||||
|
{
|
||||||
|
public bool UnlimitedCount { get; set; }
|
||||||
|
public int? StackObjectsCount { get; set; }
|
||||||
|
public int? BuyRestrictionMax { get; set; }
|
||||||
|
public int? BuyRestrictionCurrent { get; set; }
|
||||||
|
}
|
||||||
|
}
|
55
AssortValidator.Common/Models/Items.cs
Normal file
55
AssortValidator.Common/Models/Items.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssortValidator.Common.Models
|
||||||
|
{
|
||||||
|
public class ItemsLibRoot
|
||||||
|
{
|
||||||
|
public List<Dictionary<string, ItemLookup>> items { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ItemLookup
|
||||||
|
{
|
||||||
|
public string _id { get; set; }
|
||||||
|
public string _name { get; set; }
|
||||||
|
public string _parent { get; set; }
|
||||||
|
public string _type { get; set; }
|
||||||
|
public Props _props { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Props
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string ShortName { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public List<Chamber> Chambers { get; set; }
|
||||||
|
public List<Slot> Slots { get; set; }
|
||||||
|
public string defAmmo { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Chamber
|
||||||
|
{
|
||||||
|
public string _name { get; set; }
|
||||||
|
public string _id { get; set; }
|
||||||
|
public string _parent { get; set; }
|
||||||
|
public ChamberProps _props { get; set; }
|
||||||
|
public bool _required { get; set; }
|
||||||
|
public bool _mergeSlotWithChildren { get; set; }
|
||||||
|
public string _proto { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Slot
|
||||||
|
{
|
||||||
|
public string _name { get; set; }
|
||||||
|
public bool _required { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ChamberProps
|
||||||
|
{
|
||||||
|
public List<Filter> filters { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Filter
|
||||||
|
{
|
||||||
|
public List<string> filter { get; set; }
|
||||||
|
}
|
||||||
|
}
|
41
AssortValidator.Common/Models/LiveAssort.cs
Normal file
41
AssortValidator.Common/Models/LiveAssort.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssortValidator.Common.Models
|
||||||
|
{
|
||||||
|
public class LiveAssortRoot
|
||||||
|
{
|
||||||
|
public int err { get; set; }
|
||||||
|
public object errmsg { get; set; }
|
||||||
|
public LiveAssort data { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LiveAssort
|
||||||
|
{
|
||||||
|
public int nextResupply { get; set; }
|
||||||
|
public List<Item> items { get; set; }
|
||||||
|
public Dictionary<string, List<List<BarterDetails>>> barter_scheme { get; set; }
|
||||||
|
public Dictionary<string, int> loyal_level_items { get; set; }
|
||||||
|
|
||||||
|
public class BarterDetails
|
||||||
|
{
|
||||||
|
public double count { get; set; }
|
||||||
|
public string _tpl { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Item
|
||||||
|
{
|
||||||
|
public string _id { get; set; }
|
||||||
|
public string _tpl { get; set; }
|
||||||
|
public string parentId { get; set; }
|
||||||
|
public string slotId { get; set; }
|
||||||
|
public Upd upd { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Upd
|
||||||
|
{
|
||||||
|
public int? BuyRestrictionMax { get; set; }
|
||||||
|
public int BuyRestrictionCurrent { get; set; }
|
||||||
|
public int StackObjectsCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
113
AssortValidator.Common/Models/Quest.cs
Normal file
113
AssortValidator.Common/Models/Quest.cs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssortValidator.Models
|
||||||
|
{
|
||||||
|
public class QuestRoot
|
||||||
|
{
|
||||||
|
public int err { get; set; }
|
||||||
|
public object errmsg { get; set; }
|
||||||
|
public List<Quest> data { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Quest
|
||||||
|
{
|
||||||
|
public string _id { get; set; }
|
||||||
|
public bool canShowNotificationsInGame { get; set; }
|
||||||
|
public Conditions conditions { get; set; }
|
||||||
|
public string traderId { get; set; }
|
||||||
|
public string location { get; set; }
|
||||||
|
public string image { get; set; }
|
||||||
|
public string type { get; set; }
|
||||||
|
public bool isKey { get; set; }
|
||||||
|
public bool restartable { get; set; }
|
||||||
|
public bool instantComplete { get; set; }
|
||||||
|
public bool secretQuest { get; set; }
|
||||||
|
public int min_level { get; set; }
|
||||||
|
public Rewards rewards { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Conditions
|
||||||
|
{
|
||||||
|
public string _parent { get; set; }
|
||||||
|
public ConditionProps _props { get; set; }
|
||||||
|
public List<AvailableFor> AvailableForFinish { get; set; }
|
||||||
|
public List<AvailableFor> AvailableForStart { get; set; }
|
||||||
|
//public List<object> Fail { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConditionProps
|
||||||
|
{
|
||||||
|
public string compareMethod { get; set; }
|
||||||
|
public string id { get; set; }
|
||||||
|
public object target { get; set; }
|
||||||
|
public string value { get; set; }
|
||||||
|
public Counter counter { get; set; }
|
||||||
|
public int index { get; set; }
|
||||||
|
public string parentId { get; set; }
|
||||||
|
public string type { get; set; }
|
||||||
|
public int? dogtagLevel { get; set; }
|
||||||
|
public int? maxDurability { get; set; }
|
||||||
|
public int? minDurability { get; set; }
|
||||||
|
public List<object> visibilityConditions { get; set; }
|
||||||
|
public List<int> status { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Counter
|
||||||
|
{
|
||||||
|
//public List<Condition> conditions { get; set; }
|
||||||
|
public string id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AvailableFor
|
||||||
|
{
|
||||||
|
public string _parent { get; set; }
|
||||||
|
public AvailableForProps _props { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AvailableForProps
|
||||||
|
{
|
||||||
|
public int dogtagLevel { get; set; }
|
||||||
|
public string id { get; set; }
|
||||||
|
public int? index { get; set; }
|
||||||
|
public int? maxDurability { get; set; }
|
||||||
|
public int? minDurability { get; set; }
|
||||||
|
public string parentId { get; set; }
|
||||||
|
public bool resetOnSessionEnd { get; set; }
|
||||||
|
public object target { get; set; }
|
||||||
|
//public int value { get; set; }
|
||||||
|
public List<object> visibilityConditions { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Rewards
|
||||||
|
{
|
||||||
|
public List<RewardStatus> Started { get; set; }
|
||||||
|
public List<RewardStatus> Success { get; set; }
|
||||||
|
public List<RewardStatus> Fail { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RewardStatus
|
||||||
|
{
|
||||||
|
public string value { get; set; }
|
||||||
|
public string id { get; set; }
|
||||||
|
public string type { get; set; }
|
||||||
|
public int index { get; set; }
|
||||||
|
public string target { get; set; }
|
||||||
|
public List<QuestRewardItem> items { get; set; }
|
||||||
|
public int? loyaltyLevel { get; set; }
|
||||||
|
public string traderId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class QuestRewardItem
|
||||||
|
{
|
||||||
|
public string _id { get; set; }
|
||||||
|
public string _tpl { get; set; }
|
||||||
|
public QuestRewardUpd upd { get; set; }
|
||||||
|
public string parentId { get; set; }
|
||||||
|
public string slotId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class QuestRewardUpd
|
||||||
|
{
|
||||||
|
public int StackObjectsCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
15
AssortValidator.Common/Models/QuestAssortUnlock.cs
Normal file
15
AssortValidator.Common/Models/QuestAssortUnlock.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using AssortValidator.Common.Models;
|
||||||
|
|
||||||
|
namespace AssortValidator.Common.Helpers.Models
|
||||||
|
{
|
||||||
|
public class QuestAssortUnlock
|
||||||
|
{
|
||||||
|
public string QuestId { get; set; }
|
||||||
|
public string QuestName { get; set; }
|
||||||
|
public string TraderId { get; set; }
|
||||||
|
public Trader TraderType { get; set; }
|
||||||
|
public string AssortId { get; set; }
|
||||||
|
public string AssortTemplateId { get; set; }
|
||||||
|
public int LoyaltyLevel { get; set; }
|
||||||
|
}
|
||||||
|
}
|
37
AssortValidator.sln
Normal file
37
AssortValidator.sln
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.31624.102
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssortValidator", "AssortValidator\AssortValidator.csproj", "{A45962A4-FE77-4053-8263-AD209953DA92}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssortValidator.Common", "AssortValidator.Common\AssortValidator.Common.csproj", "{EA2B693F-8F4E-409B-81EE-5074CAF7D2CC}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssortValidator.Common.Models", "AssortValidator.Common.Models\AssortValidator.Common.Models.csproj", "{8B03A259-DFCF-40EB-801F-721A6E935244}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{A45962A4-FE77-4053-8263-AD209953DA92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A45962A4-FE77-4053-8263-AD209953DA92}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A45962A4-FE77-4053-8263-AD209953DA92}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A45962A4-FE77-4053-8263-AD209953DA92}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{EA2B693F-8F4E-409B-81EE-5074CAF7D2CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{EA2B693F-8F4E-409B-81EE-5074CAF7D2CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{EA2B693F-8F4E-409B-81EE-5074CAF7D2CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EA2B693F-8F4E-409B-81EE-5074CAF7D2CC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8B03A259-DFCF-40EB-801F-721A6E935244}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8B03A259-DFCF-40EB-801F-721A6E935244}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8B03A259-DFCF-40EB-801F-721A6E935244}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8B03A259-DFCF-40EB-801F-721A6E935244}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {C68472E2-0B38-4DEC-87AF-F65AD46B5030}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
13
AssortValidator/AssortValidator.csproj
Normal file
13
AssortValidator/AssortValidator.csproj
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AssortValidator.Common.Models\AssortValidator.Common.Models.csproj" />
|
||||||
|
<ProjectReference Include="..\AssortValidator.Common\AssortValidator.Common.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
4254
AssortValidator/Examples/jaeger.resp.client.trading.api.getTraderAssort.5c0647fdd443bc2504c2d371_2021-09-03_06-50-00.json
Normal file
4254
AssortValidator/Examples/jaeger.resp.client.trading.api.getTraderAssort.5c0647fdd443bc2504c2d371_2021-09-03_06-50-00.json
Normal file
File diff suppressed because it is too large
Load Diff
8951
AssortValidator/Examples/mechanic.resp.client.trading.api.getTraderAssort.5a7c2eca46aef81a7ca2145d_2021-09-03_06-49-40.json
Normal file
8951
AssortValidator/Examples/mechanic.resp.client.trading.api.getTraderAssort.5a7c2eca46aef81a7ca2145d_2021-09-03_06-49-40.json
Normal file
File diff suppressed because it is too large
Load Diff
7855
AssortValidator/Examples/peacekeeper.resp.client.trading.api.getTraderAssort.5935c25fb3acc3127c3d8cd9_2021-09-03_06-49-32.json
Normal file
7855
AssortValidator/Examples/peacekeeper.resp.client.trading.api.getTraderAssort.5935c25fb3acc3127c3d8cd9_2021-09-03_06-49-32.json
Normal file
File diff suppressed because it is too large
Load Diff
6305
AssortValidator/Examples/prapaor.resp.client.trading.api.getTraderAssort.54cb50c76803fa8b248b4571_2021-09-03_06-49-10.json
Normal file
6305
AssortValidator/Examples/prapaor.resp.client.trading.api.getTraderAssort.54cb50c76803fa8b248b4571_2021-09-03_06-49-10.json
Normal file
File diff suppressed because it is too large
Load Diff
2397
AssortValidator/Examples/ragman.resp.client.trading.api.getTraderAssort.5ac3b934156ae10c4430e83c_2021-09-03_06-49-48.json
Normal file
2397
AssortValidator/Examples/ragman.resp.client.trading.api.getTraderAssort.5ac3b934156ae10c4430e83c_2021-09-03_06-49-48.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
4727
AssortValidator/Examples/skier.resp.client.trading.api.getTraderAssort.58330581ace78e27b8b10cee_2021-09-03_06-49-24.json
Normal file
4727
AssortValidator/Examples/skier.resp.client.trading.api.getTraderAssort.58330581ace78e27b8b10cee_2021-09-03_06-49-24.json
Normal file
File diff suppressed because it is too large
Load Diff
1259
AssortValidator/Examples/therapist.resp.client.trading.api.getTraderAssort.54cb57776803fa99248b456e_2021-09-03_06-49-19.json
Normal file
1259
AssortValidator/Examples/therapist.resp.client.trading.api.getTraderAssort.54cb57776803fa99248b456e_2021-09-03_06-49-19.json
Normal file
File diff suppressed because it is too large
Load Diff
493
AssortValidator/Program.cs
Normal file
493
AssortValidator/Program.cs
Normal file
@ -0,0 +1,493 @@
|
|||||||
|
using AssortHelpers.Common.Helpers;
|
||||||
|
using AssortHelpers.Helpers;
|
||||||
|
using AssortValidator.Common;
|
||||||
|
using AssortValidator.Common.Helpers;
|
||||||
|
using AssortValidator.Common.Helpers.Models;
|
||||||
|
using AssortValidator.Common.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AssortValidator
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var inputPath = CreateWorkingFolders();
|
||||||
|
InputFileHelper.SetInputFiles(inputPath);
|
||||||
|
|
||||||
|
var assortData = AssortHelper.GetAssortData();
|
||||||
|
var liveAssortData = AssortHelper.GetLiveAssortData();
|
||||||
|
|
||||||
|
ListAssortFilesFound(assortData);
|
||||||
|
|
||||||
|
ListAssortsInLiveNotInOffline(assortData, liveAssortData);
|
||||||
|
|
||||||
|
CheckAssortValues(assortData, liveAssortData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ListAssortFilesFound(Dictionary<Trader, Assort> assortData)
|
||||||
|
{
|
||||||
|
foreach (var trader in Enum.GetValues(typeof(Trader)).Cast<Trader>())
|
||||||
|
{
|
||||||
|
var traderFound = assortData.ContainsKey(trader);
|
||||||
|
if (traderFound)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogSuccess($"Trader: {trader} found");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"Trader: {trader} NOT found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ListAssortsInLiveNotInOffline(Dictionary<Trader, Assort> assortData, Dictionary<Trader, LiveAssort> liveAssortData)
|
||||||
|
{
|
||||||
|
foreach (var trader in liveAssortData)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogInfo($"Checking Trader: {trader.Key}");
|
||||||
|
LoggingHelpers.LogInfo($"Live assort count: {trader.Value.items.Count}");
|
||||||
|
|
||||||
|
var missingAssortCount = 0;
|
||||||
|
var missingItems = new List<string>();
|
||||||
|
foreach (var liveAssort in trader.Value.items.Where(x => x.parentId == "hideout"))
|
||||||
|
{
|
||||||
|
var offlineAssort = assortData[trader.Key].items.FirstOrDefault(x=>x._tpl == liveAssort._tpl);
|
||||||
|
if (offlineAssort == null)
|
||||||
|
{
|
||||||
|
missingAssortCount++;
|
||||||
|
var itemName = ItemTemplateHelper.GetTemplateById(liveAssort._tpl)._name;
|
||||||
|
int assortLoyaltyLevel = GetAssortLoyaltyLevel(liveAssort._id, trader.Value);
|
||||||
|
|
||||||
|
var liveBarterData = trader.Value.barter_scheme.FirstOrDefault(x => x.Key == liveAssort._id).Value;
|
||||||
|
var firstItemIsMoney = ItemIsMoney(liveBarterData.First().First()._tpl);
|
||||||
|
|
||||||
|
var isMoneyMessage = firstItemIsMoney ? "money trade" : "barter trade";
|
||||||
|
missingItems.Add($"{liveAssort._tpl} - {itemName} - Level {assortLoyaltyLevel} - {isMoneyMessage}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (missingAssortCount > 0)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogInfo($"Assorts in live but not in offline: {missingAssortCount}");
|
||||||
|
foreach (var item in missingItems)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"{item}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError("no missing assorts found in offline when compared to live :)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CheckAssortValues(Dictionary<Trader, Assort> assortData, Dictionary<Trader, LiveAssort> liveAssortData)
|
||||||
|
{
|
||||||
|
List<QuestAssortUnlock> questAssortUnlocks = GetQuestsThatUnlockAssorts();
|
||||||
|
foreach (var trader in assortData)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogHeading($"Checking Trader: {trader.Key}");
|
||||||
|
|
||||||
|
var correspondingLiveTrader = liveAssortData[trader.Key];
|
||||||
|
if (correspondingLiveTrader == null)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"Unable to find live trader: {trader.Key}");
|
||||||
|
LoggingHelpers.LogNewLine();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var assort in trader.Value.items.Where(x=>x.parentId == "hideout"))
|
||||||
|
{
|
||||||
|
var itemName = ItemTemplateHelper.GetTemplateById(assort._tpl)._name;
|
||||||
|
int assortLoyaltyLevel = AssortHelper.GetAssortLoyaltyLevel(assort._id, trader.Value);
|
||||||
|
|
||||||
|
LoggingHelpers.LogInfo($"{trader.Key}: itemId: {assort._id} - tpId: {assort._tpl} ({itemName}) Level {assortLoyaltyLevel}");
|
||||||
|
LogUnlockQuest(questAssortUnlocks, assort, assortLoyaltyLevel);
|
||||||
|
|
||||||
|
var liveAssort = GetLiveAssort(correspondingLiveTrader.items, assort._tpl, correspondingLiveTrader.loyal_level_items, assortLoyaltyLevel);
|
||||||
|
if (liveAssort == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if upd objects match ( both exist or both dont exist)
|
||||||
|
if (!DoesLiveAssortUpdMatchOffline(assort, liveAssort, itemName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var offlineBarterData = trader.Value.barter_scheme.FirstOrDefault(x => x.Key == assort._id).Value;
|
||||||
|
var liveBarterData = correspondingLiveTrader.barter_scheme.FirstOrDefault(x => x.Key == liveAssort._id).Value;
|
||||||
|
if (assort.upd != null)
|
||||||
|
{
|
||||||
|
CheckUpdValues(assort, liveAssort);
|
||||||
|
|
||||||
|
// Iterate over assort barter items
|
||||||
|
// Assorts live barter data
|
||||||
|
|
||||||
|
for (int i = 0; i < offlineBarterData.Count; i++)
|
||||||
|
{
|
||||||
|
var liveItem = liveBarterData[i];
|
||||||
|
|
||||||
|
// Create list of offline barter items for assort
|
||||||
|
var offlineBarterItems = new List<BarterDetails>();
|
||||||
|
foreach (var foundItem in offlineBarterData)
|
||||||
|
{
|
||||||
|
foreach (var item in foundItem)
|
||||||
|
{
|
||||||
|
offlineBarterItems.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogAssortType(offlineBarterItems);
|
||||||
|
|
||||||
|
if (offlineBarterItems.Count != liveItem.Count)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"assort {assort._id} barter item count mismatch, found {offlineBarterItems.Count}, expected {liveItem.Count}");
|
||||||
|
LoggingHelpers.LogError("Found:");
|
||||||
|
foreach (var foundItem in offlineBarterItems)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"{foundItem._tpl} ({ItemTemplateHelper.GetTemplateById(foundItem._tpl)._name}) x{foundItem.count}");
|
||||||
|
|
||||||
|
}
|
||||||
|
LoggingHelpers.LogError("Expected:");
|
||||||
|
foreach (var missingItem in liveItem)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"{missingItem._tpl} ({ItemTemplateHelper.GetTemplateById(missingItem._tpl)._name}) x{missingItem.count}");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over the barter requirement items
|
||||||
|
for (int j = 0; j < offlineBarterData[i].Count; j++)
|
||||||
|
{
|
||||||
|
// Check live barter item exists
|
||||||
|
if (j > liveItem.Count - 1)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"assort {assort._id} live barter item requirement missing");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var liveSubItem = liveItem[j];
|
||||||
|
var subItem = liveItem[j];
|
||||||
|
|
||||||
|
ValueCheckerHelper.CheckValuesMatch(subItem._tpl, liveSubItem._tpl, "barter item template ids dont match");
|
||||||
|
ValueCheckerHelper.CheckValuesMatch(subItem.count.ToString(), liveSubItem.count.ToString(), "barter item counts dont match");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckAssortCost(offlineBarterData, liveBarterData);
|
||||||
|
|
||||||
|
LoggingHelpers.LogNewLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log the quest type: money or barter trade
|
||||||
|
/// </summary>
|
||||||
|
private static void LogAssortType(List<BarterDetails> offlineBarterItems)
|
||||||
|
{
|
||||||
|
if (ItemIsMoney(offlineBarterItems.First()._tpl))
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogInfo("assort is money trade");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogInfo("assort is barter trade");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void LogUnlockQuest(List<QuestAssortUnlock> questAssortUnlocks, Item assort, int assortLoyaltyLevel)
|
||||||
|
{
|
||||||
|
var questAssortUnlockData = questAssortUnlocks.FirstOrDefault(x => x.AssortTemplateId == assort._tpl && x.LoyaltyLevel == assortLoyaltyLevel);
|
||||||
|
if (questAssortUnlockData != null)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogInfo($"Assort likely unlocked by quest: {questAssortUnlockData.QuestName} ({questAssortUnlockData.QuestId})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ItemIsMoney(string templateId)
|
||||||
|
{
|
||||||
|
return ItemTemplateHelper.GetTemplateById(templateId)._parent == "543be5dd4bdc2deb348b4569"; // money type
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool DoesLiveAssortUpdMatchOffline(Item assort, LiveAssort.Item correspondingLiveAssort, string itemName)
|
||||||
|
{
|
||||||
|
if (assort.upd != null && correspondingLiveAssort.upd == null)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"assort {assort._id} ({itemName}) has a upd object, live does not. skipping assort");
|
||||||
|
LoggingHelpers.LogNewLine();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no parent id = not a gun item
|
||||||
|
if (assort.parentId == null && assort.upd == null && correspondingLiveAssort.upd != null)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"assort {assort._id} ({itemName}) does not have a upd object, live does. skipping assort");
|
||||||
|
LoggingHelpers.LogNewLine();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetAssortLoyaltyLevel(string assortId, LiveAssort assort)
|
||||||
|
{
|
||||||
|
int assortLoyaltyLevel = 1;
|
||||||
|
if (!assort.loyal_level_items.ContainsKey(assortId))
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogWarning($"No offline loyalty level record found for itemId: {assortId} assuming level 1");
|
||||||
|
LoggingHelpers.LogNewLine();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assortLoyaltyLevel = assort.loyal_level_items[assortId];
|
||||||
|
}
|
||||||
|
|
||||||
|
return assortLoyaltyLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CheckUpdValues(Item assort, LiveAssort.Item correspondingLiveAssort)
|
||||||
|
{
|
||||||
|
if (assort.upd.StackObjectsCount.HasValue && !assort.upd.UnlimitedCount)
|
||||||
|
{
|
||||||
|
var liveStackCount = GetRoundedStackCount(correspondingLiveAssort.upd.StackObjectsCount);
|
||||||
|
ValueCheckerHelper.CheckValuesMatch(assort.upd.StackObjectsCount.Value, liveStackCount, $"stackobjectCount does not match live. orig: ({correspondingLiveAssort.upd.StackObjectsCount})");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check count is 999999 if unlimited count is true
|
||||||
|
if (assort.upd.UnlimitedCount)
|
||||||
|
{
|
||||||
|
ValueCheckerHelper.CheckValuesMatch(assort.upd.StackObjectsCount.Value, 999999, "unlimited count does not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check max buy restriction matches
|
||||||
|
ValueCheckerHelper.CheckValuesMatch(assort.upd.BuyRestrictionMax.GetValueOrDefault(0), correspondingLiveAssort.upd.BuyRestrictionMax.GetValueOrDefault(0), "BuyRestrictionMax does not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LiveAssort.Item GetLiveAssort(List<LiveAssort.Item> liveAssorts, string templateId, Dictionary<string, int> loyaltyLevels, int expectedLoyaltyLevel)
|
||||||
|
{
|
||||||
|
var liveAssortsWithTemplateId = liveAssorts.Where(x => x._tpl == templateId).ToList();
|
||||||
|
|
||||||
|
if (liveAssortsWithTemplateId.Count == 0)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"Unable to find live assort tpId: {templateId} ({ItemTemplateHelper.GetTemplateById(templateId)._name})");
|
||||||
|
LoggingHelpers.LogError($"Skipping assort");
|
||||||
|
LoggingHelpers.LogNewLine();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only one item, break out early and return
|
||||||
|
if (liveAssortsWithTemplateId.Count == 1)
|
||||||
|
{
|
||||||
|
return liveAssortsWithTemplateId.First();
|
||||||
|
}
|
||||||
|
|
||||||
|
// More than one assort found
|
||||||
|
// Gather assort ids and use them to get loyalty level records
|
||||||
|
var liveAssortsIds = liveAssortsWithTemplateId.Select(x => x._id);
|
||||||
|
var liveloyaltyLevelsForTemplateId = loyaltyLevels.Where(x => liveAssortsIds.Contains(x.Key)).ToList();
|
||||||
|
|
||||||
|
if (liveloyaltyLevelsForTemplateId.All(x => x.Value == expectedLoyaltyLevel) && liveloyaltyLevelsForTemplateId.Count > 1)
|
||||||
|
{
|
||||||
|
// Both have same loyalty level, cant proceed;
|
||||||
|
LoggingHelpers.LogError($"Unable to find live assort item: {templateId} ({ItemTemplateHelper.GetTemplateById(templateId)._name}) ");
|
||||||
|
LoggingHelpers.LogNewLine();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<KeyValuePair<string, int>> loyaltyLevelItemThatMatches = liveloyaltyLevelsForTemplateId.Where(x => x.Value == expectedLoyaltyLevel);
|
||||||
|
if (loyaltyLevelItemThatMatches == null)
|
||||||
|
{
|
||||||
|
// Both have same loyalty level, cant proceed;
|
||||||
|
LoggingHelpers.LogError($"Unable to find live assort item: {templateId} ({ItemTemplateHelper.GetTemplateById(templateId)._name})");
|
||||||
|
LoggingHelpers.LogNewLine();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return liveAssorts.FirstOrDefault(x => x._id == loyaltyLevelItemThatMatches.FirstOrDefault().Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetRoundedStackCount(int stackObjectsCount)
|
||||||
|
{
|
||||||
|
//TODO: automate this with math.round
|
||||||
|
if (stackObjectsCount < 6)
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 11)
|
||||||
|
{
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 21)
|
||||||
|
{
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 51)
|
||||||
|
{
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 101)
|
||||||
|
{
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 201)
|
||||||
|
{
|
||||||
|
return 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 501)
|
||||||
|
{
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 1001)
|
||||||
|
{
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 2001)
|
||||||
|
{
|
||||||
|
return 2000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 3001)
|
||||||
|
{
|
||||||
|
return 3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 4001)
|
||||||
|
{
|
||||||
|
return 4000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 5001)
|
||||||
|
{
|
||||||
|
return 5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 6001)
|
||||||
|
{
|
||||||
|
return 6000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 10001)
|
||||||
|
{
|
||||||
|
return 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 15001)
|
||||||
|
{
|
||||||
|
return 15000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 20001)
|
||||||
|
{
|
||||||
|
return 20000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 25001)
|
||||||
|
{
|
||||||
|
return 25000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 50001)
|
||||||
|
{
|
||||||
|
return 50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 70001)
|
||||||
|
{
|
||||||
|
return 70000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 85001)
|
||||||
|
{
|
||||||
|
return 85000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 100001)
|
||||||
|
{
|
||||||
|
return 100000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 150001)
|
||||||
|
{
|
||||||
|
return 150000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 200001)
|
||||||
|
{
|
||||||
|
return 200000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 500001)
|
||||||
|
{
|
||||||
|
return 500000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 700001)
|
||||||
|
{
|
||||||
|
return 700000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 1000001)
|
||||||
|
{
|
||||||
|
return 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackObjectsCount < 5000001)
|
||||||
|
{
|
||||||
|
return 5000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 9999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CheckAssortCost(List<List<BarterDetails>> offlineBarterData, List<List<LiveAssort.BarterDetails>> liveBarterData)
|
||||||
|
{
|
||||||
|
var firstBarterItem = offlineBarterData.First().First();
|
||||||
|
var firstOfflineItemIsMoney = ItemIsMoney(firstBarterItem._tpl);
|
||||||
|
|
||||||
|
var firstLiveBarterItem = liveBarterData.First().First();
|
||||||
|
var firstLiveItemIsMoney = ItemIsMoney(firstLiveBarterItem._tpl);
|
||||||
|
|
||||||
|
if (firstOfflineItemIsMoney != firstLiveItemIsMoney)
|
||||||
|
{
|
||||||
|
LoggingHelpers.LogError($"item cost mismatch. Offline item is money: {firstOfflineItemIsMoney}. Live item is money: {firstLiveItemIsMoney}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstOfflineItemIsMoney && firstOfflineItemIsMoney)
|
||||||
|
{
|
||||||
|
var liveCount = int.Parse(Math.Round(firstLiveBarterItem.count).ToString());
|
||||||
|
ValueCheckerHelper.CheckValuesMatch(firstBarterItem.count, liveCount, "costs do not match");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CreateWorkingFolders()
|
||||||
|
{
|
||||||
|
var workingPath = Directory.GetCurrentDirectory();
|
||||||
|
// create input folder
|
||||||
|
var inputPath = $"{workingPath}//input";
|
||||||
|
DiskHelpers.CreateDirIfDoesntExist(inputPath);
|
||||||
|
|
||||||
|
return inputPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<QuestAssortUnlock> GetQuestsThatUnlockAssorts()
|
||||||
|
{
|
||||||
|
var liveQuests = QuestHelper.GetLiveQuestData();
|
||||||
|
return QuestHelper.GetQuestAssortUnlocks(liveQuests.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
README.md
13
README.md
@ -1,2 +1,15 @@
|
|||||||
# AssortVerifier
|
# AssortVerifier
|
||||||
|
|
||||||
|
Reads through your trader assorts and compares them to live dump data. Will output to the console any inconsistencies.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Place files in: AssortValidator\bin\Debug\netcoreapp3.1\input
|
||||||
|
|
||||||
|
### Files needed
|
||||||
|
1. resp.client.trading.api.getTraderAssort.xxxxxx (one for each trader)
|
||||||
|
2. resp.client.quest.list.xxxxxx
|
||||||
|
3. a folder for each trader from aki server with the assort file inside.
|
||||||
|
e.g. 5a7c2eca46aef81a7ca2145d / assort.json
|
||||||
|
54cb57776803fa99248b456e / assort.json
|
||||||
|
(copy and paste your trader folders from server / asets / database)
|
Loading…
x
Reference in New Issue
Block a user