504 lines
19 KiB
C#
504 lines
19 KiB
C#
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.LogSuccess("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, assort._tpl, 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(LiveAssort trader, string templateId, int expectedLoyaltyLevel)
|
|
{
|
|
var liveAssorts = trader.items;
|
|
var liveLoyaltyLevels = trader.loyal_level_items;
|
|
|
|
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 = liveLoyaltyLevels.Where(x => liveAssortsIds.Contains(x.Key)).ToList();
|
|
|
|
// Same loyalty level + multiple found
|
|
if (liveLoyaltyLevelsForTemplateId.All(x => x.Value == expectedLoyaltyLevel) && liveLoyaltyLevelsForTemplateId.Count > 1)
|
|
{
|
|
// Both have same loyalty level, cant proceed;
|
|
LoggingHelpers.LogError($"Multiple ({liveLoyaltyLevelsForTemplateId.Count}) live assorts for this tpId found at same Level ({expectedLoyaltyLevel}) - Unable to distinguish: {templateId} ({ItemTemplateHelper.GetTemplateById(templateId)._name}) ");
|
|
|
|
LoggingHelpers.LogNewLine();
|
|
return null;
|
|
}
|
|
|
|
var loyaltyLevelItemThatMatches = liveLoyaltyLevelsForTemplateId.Where(x => x.Value == expectedLoyaltyLevel);
|
|
if (loyaltyLevelItemThatMatches != null && loyaltyLevelItemThatMatches.Count() > 1)
|
|
{
|
|
LoggingHelpers.LogWarning($"({loyaltyLevelItemThatMatches.Count()}) live items found, choosing first one in list");
|
|
}
|
|
|
|
if (loyaltyLevelItemThatMatches == null)
|
|
{
|
|
// Both have same loyalty level, cant proceed;
|
|
LoggingHelpers.LogError($"No live assort for this tpId found at same level - Unable proceed: {templateId} ({ItemTemplateHelper.GetTemplateById(templateId)._name})");
|
|
LoggingHelpers.LogNewLine();
|
|
return null;
|
|
}
|
|
|
|
return liveAssorts.Find(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);
|
|
}
|
|
}
|
|
}
|