2021-09-10 17:57:24 +01:00
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
{
2021-09-11 21:31:19 +01:00
LoggingHelpers . LogSuccess ( "no missing assorts found in offline when compared to live :)" ) ;
2021-09-10 17:57:24 +01:00
}
}
}
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 ) ;
2021-09-11 21:31:19 +01:00
var liveAssort = GetLiveAssort ( correspondingLiveTrader , assort . _tpl , assortLoyaltyLevel ) ;
2021-09-10 17:57:24 +01:00
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" ) ;
}
2021-09-11 21:31:19 +01:00
private static LiveAssort . Item GetLiveAssort ( LiveAssort trader , string templateId , int expectedLoyaltyLevel )
2021-09-10 17:57:24 +01:00
{
2021-09-11 21:31:19 +01:00
var liveAssorts = trader . items ;
var liveLoyaltyLevels = trader . loyal_level_items ;
2021-09-10 17:57:24 +01:00
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 ) ;
2021-09-11 21:31:19 +01:00
var liveLoyaltyLevelsForTemplateId = liveLoyaltyLevels . Where ( x = > liveAssortsIds . Contains ( x . Key ) ) . ToList ( ) ;
2021-09-10 17:57:24 +01:00
2021-09-11 21:31:19 +01:00
// Same loyalty level + multiple found
if ( liveLoyaltyLevelsForTemplateId . All ( x = > x . Value = = expectedLoyaltyLevel ) & & liveLoyaltyLevelsForTemplateId . Count > 1 )
2021-09-10 17:57:24 +01:00
{
// Both have same loyalty level, cant proceed;
2021-09-11 21:31:19 +01:00
LoggingHelpers . LogError ( $"Multiple ({liveLoyaltyLevelsForTemplateId.Count}) live assorts for this tpId found at same Level ({expectedLoyaltyLevel}) - Unable to distinguish: {templateId} ({ItemTemplateHelper.GetTemplateById(templateId)._name}) " ) ;
2021-09-10 17:57:24 +01:00
LoggingHelpers . LogNewLine ( ) ;
return null ;
}
2021-09-11 21:31:19 +01:00
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" ) ;
}
2021-09-10 17:57:24 +01:00
if ( loyaltyLevelItemThatMatches = = null )
{
// Both have same loyalty level, cant proceed;
2021-09-11 21:31:19 +01:00
LoggingHelpers . LogError ( $"No live assort for this tpId found at same level - Unable proceed: {templateId} ({ItemTemplateHelper.GetTemplateById(templateId)._name})" ) ;
2021-09-10 17:57:24 +01:00
LoggingHelpers . LogNewLine ( ) ;
return null ;
}
2021-09-11 21:31:19 +01:00
return liveAssorts . Find ( x = > x . _id = = loyaltyLevelItemThatMatches . FirstOrDefault ( ) . Key ) ;
2021-09-10 17:57:24 +01:00
}
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 ) ;
}
}
}