2022-01-12 15:08:41 +00:00

512 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, Assort> 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 data = ItemTemplateHelper.GetTemplateById(liveAssort._tpl);
if (data is null)
{
LoggingHelpers.LogInfo($"Assort not found skipping: {liveAssort._tpl}");
continue;
}
var itemName = data._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("live and existing assorts match :)");
}
}
}
private static void CheckAssortValues(Dictionary<Trader, Assort> assortData, Dictionary<Trader, Assort> 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, "Existing");
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, string assortSource)
{
if (ItemIsMoney(offlineBarterItems.First()._tpl))
{
LoggingHelpers.LogInfo($"{assortSource} assort is money trade");
}
else
{
LoggingHelpers.LogInfo($"{assortSource} 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, Assort.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, 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.LogNewLine();
}
else
{
assortLoyaltyLevel = assort.loyal_level_items[assortId];
}
return assortLoyaltyLevel;
}
private static void CheckUpdValues(Item assort, Assort.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 Assort.Item GetLiveAssort(Assort 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<Assort.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.GetQuestData();
return QuestHelper.GetQuestAssortUnlocks(liveQuests.Values);
}
}
}