Decompiled source of high baller v2.5.1

HighBaller_IL2CPP.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using DealOptimizer_IL2CPP;
using DealOptimizer_IL2CPP.Models;
using DealOptimizer_IL2CPP.Services;
using HarmonyLib;
using Il2CppFishNet;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Economy;
using Il2CppScheduleOne.GameTime;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Levelling;
using Il2CppScheduleOne.Messaging;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.NPCs.Relation;
using Il2CppScheduleOne.Persistence;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Product;
using Il2CppScheduleOne.Product.Packaging;
using Il2CppScheduleOne.Quests;
using Il2CppScheduleOne.UI;
using Il2CppScheduleOne.UI.Handover;
using Il2CppScheduleOne.UI.Phone;
using Il2CppScheduleOne.UI.Phone.ContactsApp;
using Il2CppScheduleOne.UI.Phone.Messages;
using Il2CppScheduleOne.UI.Phone.ProductManagerApp;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "HighBaller_IL2CPP", "2.5.3", "zocke1r", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("HighBaller_IL2CPP")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5b175bb85251367c65555e925ae2112563bf5625")]
[assembly: AssemblyProduct("HighBaller_IL2CPP")]
[assembly: AssemblyTitle("HighBaller_IL2CPP")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DealOptimizer_IL2CPP
{
	public static class BuildInfo
	{
		public const string Name = "HighBaller_IL2CPP";

		public const string Author = "zocke1r";

		public const string Version = "2.5.3";
	}
	public class Core : MelonMod
	{
		public class InitialOfferData
		{
			public string ProductId { get; set; }

			public int Quantity { get; set; }

			public float Payment { get; set; }
		}

		public static class DealCalculator
		{
			public static float CalculateSuccessProbability(Customer customer, ProductDefinition product, int quantity, float price, InitialOfferData initialOfferData)
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				CustomerData customerData = customer.CustomerData;
				float valueProposition = Customer.GetValueProposition(Registry.GetItem<ProductDefinition>(initialOfferData.ProductId), initialOfferData.Payment / (float)initialOfferData.Quantity);
				float productEnjoyment = customer.GetProductEnjoyment(product, StandardsMethod.GetCorrespondingQuality(customerData.Standards));
				float num = Mathf.InverseLerp(-1f, 1f, productEnjoyment);
				float valueProposition2 = Customer.GetValueProposition(product, price / (float)quantity);
				float num2 = Mathf.Pow((float)quantity / (float)initialOfferData.Quantity, 0.6f);
				float num3 = Mathf.Lerp(0f, 2f, num2 * 0.5f);
				float num4 = Mathf.Lerp(1f, 0f, Mathf.Abs(num3 - 1f));
				if (valueProposition2 * num4 > valueProposition)
				{
					return 1f;
				}
				if (valueProposition2 < 0.12f)
				{
					return 0f;
				}
				float num5 = productEnjoyment * valueProposition;
				float num6 = num * num4 * valueProposition2;
				if (num6 > num5)
				{
					return 1f;
				}
				float num7 = num5 - num6;
				float num8 = Mathf.Lerp(0f, 1f, num7 / 0.2f);
				float num9 = Mathf.Lerp(0f, 0.2f, Mathf.Max(customer.CurrentAddiction, customer.NPC.RelationData.NormalizedRelationDelta));
				float num10 = num8 - num9;
				return Mathf.Clamp01((0.9f - num10) / 0.9f);
			}

			public static (float maxSpend, float dailyAverage) CalculateSpendingLimits(Customer customer)
			{
				CustomerData customerData = customer.CustomerData;
				float adjustedWeeklySpend = customerData.GetAdjustedWeeklySpend(customer.NPC.RelationData.RelationDelta / 5f);
				List<EDay> orderDays = customerData.GetOrderDays(customer.CurrentAddiction, customer.NPC.RelationData.RelationDelta / 5f);
				float num = adjustedWeeklySpend / (float)orderDays.Count;
				return (num * 3f, num);
			}

			public static int FindOptimalPrice(Customer customer, ProductDefinition product, int quantity, float currentPrice, float maxSpend, float minSuccessProbability = -1f, InitialOfferData initialOfferData = null, bool log = false)
			{
				if (minSuccessProbability < 0f)
				{
					minSuccessProbability = Config.MinSuccessProbability.Value;
				}
				int num = (int)currentPrice;
				int num2 = (int)maxSpend;
				int num3 = (int)currentPrice;
				int num4 = 20;
				int i = 0;
				if (initialOfferData == null)
				{
					initialOfferData = new InitialOfferData
					{
						ProductId = customer.OfferedContractInfo.Products.entries[0].ProductID,
						Quantity = customer.OfferedContractInfo.Products.entries[0].Quantity,
						Payment = customer.OfferedContractInfo.Payment
					};
				}
				if (log)
				{
					Melon<Core>.Logger.Msg($"Initial Offer Data: ProductId: {initialOfferData.ProductId}, Quantity: {initialOfferData.Quantity}, Payment: {initialOfferData.Payment}");
					Melon<Core>.Logger.Msg($"Binary Search Start - Product: {((ItemDefinition)product).ID}, Price: {currentPrice}, MaxSpend: {maxSpend}, Quantity: {quantity}, MinProbability: {minSuccessProbability}, Low: {num}, High: {num2}");
				}
				for (; i < num4; i++)
				{
					if (num >= num2)
					{
						break;
					}
					int num5 = (num + num2) / 2;
					if (CalculateSuccessProbability(customer, product, quantity, num5, initialOfferData) >= minSuccessProbability)
					{
						num = num5 + 1;
						if (num == num2)
						{
							num3 = ((CalculateSuccessProbability(customer, product, quantity, num5 + 1, initialOfferData) > minSuccessProbability) ? (num5 + 1) : num5);
							break;
						}
						num3 = num5;
					}
					else
					{
						num2 = num5;
					}
				}
				if (log)
				{
					Melon<Core>.Logger.Msg("Binary Search Complete:");
					Melon<Core>.Logger.Msg($"  Final bestFailingPrice: {num3}");
					Melon<Core>.Logger.Msg($"  Final Probability: {CalculateSuccessProbability(customer, product, quantity, num3, initialOfferData)}");
				}
				return num3;
			}

			public static (int optimalQuantity, int optimalPrice) FindOptimalQuantity(Customer customer, ProductDefinition product, int initialQuantity, float initialPrice, InitialOfferData initialOfferData = null)
			{
				float item = CalculateSpendingLimits(customer).maxSpend;
				if (!Config.IncreaseQuantityEnabled.Value)
				{
					int item2 = FindOptimalPrice(customer, product, initialQuantity, initialPrice, item, -1f, initialOfferData);
					return (initialQuantity, item2);
				}
				int num = initialQuantity;
				int num2 = (int)initialPrice;
				int i = 0;
				int num3 = 20;
				int num4 = FindOptimalPrice(customer, product, initialQuantity, initialPrice, item, -1f, initialOfferData);
				num = initialQuantity;
				num2 = num4;
				if ((double)num2 >= Math.Floor(item * 0.99f))
				{
					return (num, num2);
				}
				int num5 = initialQuantity;
				for (; i < num3; i++)
				{
					num5++;
					int num6 = FindOptimalPrice(customer, product, num5, initialPrice, item, -1f, initialOfferData);
					if (num6 <= num2)
					{
						break;
					}
					num = num5;
					num2 = num6;
					if ((double)num2 >= Math.Floor(item * 0.99f))
					{
						break;
					}
				}
				return (num, num2);
			}
		}

		private static class DisplayHelper
		{
			public static void UpdateCounterOfferDisplayText(string text, string reasonText)
			{
				Instance.uiHandler.UpdateCounterOfferDisplayText(text, reasonText);
			}
		}

		[HarmonyPatch(typeof(CounterofferInterface), "SetProduct")]
		private static class CounterofferInterfaceChangeProductPatch
		{
			private static void Postfix(ProductDefinition newProduct)
			{
				MessagesApp instance = PlayerSingleton<MessagesApp>.Instance;
				Melon<Core>.Logger.Msg("CounterofferInterfaceChangeProductPatch: " + ((ItemDefinition)newProduct).Name);
				OfferData offerData = GetOfferData();
				Customer customer = offerData.Customer;
				int quantity = offerData.Quantity;
				float price = offerData.Price;
				(int optimalQuantity, int optimalPrice) tuple = DealCalculator.FindOptimalQuantity(customer, newProduct, quantity, price * 0.25f);
				int item = tuple.optimalQuantity;
				int item2 = tuple.optimalPrice;
				int num = quantity;
				if ((float)item2 != price)
				{
					instance.CounterofferInterface.ChangePrice((float)(item2 - (int)price));
					instance.CounterofferInterface.ChangeQuantity(item - num);
				}
			}
		}

		[HarmonyPatch(typeof(CounterofferInterface), "Open")]
		private static class CounterofferInterfacePostOpenPatch
		{
			private static void Postfix(ProductDefinition product, int quantity, float price, MSGConversation _conversation, Action<ProductDefinition, int, float> _orderConfirmedCallback)
			{
				MessagesApp instance = PlayerSingleton<MessagesApp>.Instance;
				(int optimalQuantity, int optimalPrice) tuple = DealCalculator.FindOptimalQuantity(CustomerHelper.GetCustomerFromConversation(_conversation), product, quantity, price);
				int item = tuple.optimalQuantity;
				int item2 = tuple.optimalPrice;
				if ((float)item2 > price)
				{
					instance.CounterofferInterface.ChangePrice((float)(item2 - (int)price));
					instance.CounterofferInterface.ChangeQuantity(item - quantity);
				}
			}
		}

		[HarmonyPatch(typeof(CounterofferInterface), "ChangePrice")]
		private static class CounterofferInterfacePostChangePricePatch
		{
			private static void Postfix(float change)
			{
				OfferPriceChangeCheckNoLog();
			}
		}

		[HarmonyPatch(typeof(CounterofferInterface), "ChangeQuantity")]
		private static class CounterofferInterfacePostChangeQuantityPatch
		{
			private static void Postfix(int change)
			{
				MessagesApp instance = PlayerSingleton<MessagesApp>.Instance;
				if (!((Object)(object)instance == (Object)null) && instance.CounterofferInterface.IsOpen)
				{
					Customer customerFromMessagesApp = CustomerHelper.GetCustomerFromMessagesApp(instance);
					float item = DealCalculator.CalculateSpendingLimits(customerFromMessagesApp).maxSpend;
					CounterofferInterface counterofferInterface = instance.CounterofferInterface;
					int quantity = int.Parse(counterofferInterface.ProductLabel.text.Split("x ")[0]);
					string text = counterofferInterface.PriceInput.text;
					float num = ((text == "") ? 0f : float.Parse(text));
					ProductDefinition item2 = Registry.GetItem<ProductDefinition>(((ItemDefinition)counterofferInterface.selectedProduct).ID);
					int num2 = DealCalculator.FindOptimalPrice(customerFromMessagesApp, item2, quantity, num * 0.25f, item, -1f, null, log: true);
					if (!Mathf.Approximately((float)num2, num))
					{
						counterofferInterface.ChangePrice((float)(num2 - (int)num));
					}
					OfferPriceChangeCheckNoLog();
				}
			}
		}

		private class OfferData
		{
			public Customer Customer { get; }

			public ProductDefinition Product { get; }

			public int Quantity { get; }

			public float Price { get; }

			public OfferData(Customer customer, ProductDefinition product, int quantity, float price)
			{
				Customer = customer;
				Product = product;
				Quantity = quantity;
				Price = price;
			}
		}

		[HarmonyPatch(typeof(ProductManager), "SendPrice")]
		private static class ProductManagerSetPricePatch
		{
			private static void Postfix(string productID, float value)
			{
				Melon<Core>.Logger.Msg($"ProductManager: Set price: {value} for {productID}");
				if ((Object)(object)UIHandler.SelectedProduct != (Object)null && ((ItemDefinition)UIHandler.SelectedProduct.Definition).ID == productID)
				{
					optimalPriceCache.Remove(productID);
					Instance.uiHandler.UpdateSalesInfoPanel(UIHandler.SelectedProduct, value);
				}
			}
		}

		[HarmonyPatch(typeof(ProductManagerApp), "SelectProduct")]
		private static class ProductManagerSelectProductPatch
		{
			public static void Prefix(ProductManagerApp __instance, ProductEntry entry)
			{
				productManagerApp = __instance;
			}

			private static void Postfix(ProductEntry entry)
			{
				Instance.uiHandler.UpdateSalesInfoPanel(entry);
			}
		}

		[HarmonyPatch(typeof(ContactsDetailPanel), "Open")]
		public static class ContactsDetailPanelOpenPatch
		{
			[HarmonyPostfix]
			public static void Postfix(NPC npc)
			{
				if (!((Object)(object)npc == (Object)null))
				{
					Melon<Core>.Logger.Msg($"RelationCircle: {npc.ID}, Name: {npc.fullName}, RelationDelta: {npc.RelationData.RelationDelta}, Unlocked: {npc.RelationData.Unlocked}");
					Customer customerFromNPC = CustomerHelper.GetCustomerFromNPC(npc);
					if ((Object)(object)customerFromNPC == (Object)null)
					{
						Melon<Core>.Logger.Msg("Not a customer");
						Instance.uiHandler.UpdateContactInfoPanel(null);
					}
					else
					{
						Instance.uiHandler.UpdateContactInfoPanel(customerFromNPC);
					}
				}
			}
		}

		public class CustomerAppeal
		{
			public Customer Customer { get; set; }

			public float Appeal { get; set; }

			public PaymentQuantityResult PaymentQuantity { get; set; }
		}

		[HarmonyPatch(typeof(Customer), "OfferContract")]
		public static class OfferContractPatch
		{
			public static void Postfix(Customer __instance, ContractInfo info, MethodBase __originalMethod)
			{
				if (Config.AutoCounterOfferEnabled.Value)
				{
					Melon<Core>.Logger.Msg("Customer: " + ((Object)__instance.customerData).name + ", Contract: " + info.Products.entries[0].ProductID);
					Entry entry = info.Products.entries[0];
					ProductDefinition product = __instance.OrderableProducts.Find(Predicate<ProductDefinition>.op_Implicit((Func<ProductDefinition, bool>)((ProductDefinition p) => ((ItemDefinition)p).ID == entry.ProductID)));
					var (quantity, num) = DealCalculator.FindOptimalQuantity(__instance, product, entry.Quantity, info.Payment);
					new DelayedCounterOffer(__instance, product, quantity, num).Start();
				}
			}
		}

		[HarmonyPatch(typeof(Customer), "EvaluateCounteroffer")]
		public static class EvaluateCounterOfferPatch
		{
			public static void Postfix(Customer __instance, bool __result)
			{
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0106: Unknown result type (might be due to invalid IL or missing references)
				//IL_0110: Unknown result type (might be due to invalid IL or missing references)
				//IL_013f: Unknown result type (might be due to invalid IL or missing references)
				//IL_014b: Expected O, but got Unknown
				//IL_015d: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: Unknown result type (might be due to invalid IL or missing references)
				if (!Config.AutoContractAcceptedEnabled.Value)
				{
					return;
				}
				if (!__result)
				{
					Melon<Core>.Logger.Warning("Counter failed");
					return;
				}
				Melon<Core>.Logger.Msg($"Customer: {((Object)__instance.customerData).name}, Contract: {__result}, Counteroffer: {__instance.OfferedContractInfo.IsCounterOffer}");
				int value = Config.AutoContractAcceptedWindow.Value;
				Melon<Core>.Logger.Msg($"Conversation: {__instance.NPC.MSGConversation}");
				string text = "";
				EDealWindow window;
				switch (value)
				{
				case 1:
					window = (EDealWindow)0;
					text = "Morning";
					break;
				case 2:
					window = (EDealWindow)1;
					text = "Afternoon";
					break;
				case 3:
					window = (EDealWindow)2;
					text = "Night";
					break;
				case 4:
					window = (EDealWindow)3;
					text = "Late Night";
					break;
				default:
					window = (EDealWindow)3;
					text = "Late Night";
					Melon<Core>.Logger.Warning("AutoContractAcceptedWindow is not correctly set!\nDefaulting to Late Night \nCorrect Values: 1 = Morning, 2 = Afternoon, 3 = Night, 4 = Late Night");
					break;
				}
				__instance.NPC.MSGConversation.SendMessage(new Message(text, (ESenderType)0, true, -1), true, true);
				__instance.NPC.MSGConversation.ClearResponses(true);
				new DelayedScheduler(__instance, window).Start();
			}
		}

		[HarmonyPatch(typeof(LevelManager), "AddXP")]
		public static class LevelManagerLoggingPatch
		{
			public static void Postfix(int xp)
			{
				Melon<Core>.Logger.Msg($"LevelManager: AddXP: {xp}");
			}
		}

		private bool listening;

		private UIHandler uiHandler;

		private static Dictionary<string, (float bestPrice, float spenderScore)> optimalPriceCache = new Dictionary<string, (float, float)>();

		public static ProductManager productManager;

		public static ProductManagerApp productManagerApp;

		public static Core Instance { get; private set; }

		private static bool DefinitelyLessThan(float a, float b)
		{
			return (double)(b - a) > (double)((Math.Abs(a) < Math.Abs(b)) ? Math.Abs(b) : Math.Abs(a)) * 1E-15;
		}

		private static OfferData GetOfferData()
		{
			MessagesApp instance = PlayerSingleton<MessagesApp>.Instance;
			Customer customerFromMessagesApp = CustomerHelper.GetCustomerFromMessagesApp(instance);
			ProductDefinition item = Registry.GetItem<ProductDefinition>(customerFromMessagesApp.OfferedContractInfo.Products.entries[0].ProductID);
			int quantity = int.Parse(instance.CounterofferInterface.ProductLabel.text.Split("x ")[0]);
			string text = instance.CounterofferInterface.PriceInput.text;
			float price = ((text == "") ? 0f : float.Parse(text));
			return new OfferData(customerFromMessagesApp, item, quantity, price);
		}

		public static void OfferPriceChangeCheckNoLog()
		{
			EvaluateCounterOffer(GetOfferData());
		}

		private void OfferPriceChangeCheckWithLog()
		{
			OfferData offerData = GetOfferData();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append('\n');
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(16, 1, stringBuilder2);
			handler.AppendLiteral("Customer Name: ");
			handler.AppendFormatted(((Object)offerData.Customer).name);
			handler.AppendLiteral("\n");
			stringBuilder3.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(10, 1, stringBuilder2);
			handler.AppendLiteral("Product: ");
			handler.AppendFormatted(((ItemDefinition)offerData.Product).ID);
			handler.AppendLiteral("\n");
			stringBuilder4.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2);
			handler.AppendLiteral("Quantity: ");
			handler.AppendFormatted(offerData.Quantity);
			handler.AppendLiteral("\n");
			stringBuilder5.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2);
			handler.AppendLiteral("Price: ");
			handler.AppendFormatted(offerData.Price);
			handler.AppendLiteral("\n");
			stringBuilder6.Append(ref handler);
			EvaluateCounterOffer(stringBuilder, offerData);
			((MelonBase)this).LoggerInstance.Msg(stringBuilder.ToString());
		}

		private static void EvaluateCounterOffer(OfferData offerData)
		{
			float item = DealCalculator.CalculateSpendingLimits(offerData.Customer).maxSpend;
			decimal value = Math.Round((decimal)item, 2);
			if (offerData.Price >= item)
			{
				DisplayHelper.UpdateCounterOfferDisplayText("Guaranteed Failure", $"Exceeded Max Spend ({value})");
				return;
			}
			ProductDefinition selectedProduct = PlayerSingleton<MessagesApp>.Instance.CounterofferInterface.selectedProduct;
			InitialOfferData initialOfferData = new InitialOfferData
			{
				ProductId = offerData.Customer.OfferedContractInfo.Products.entries[0].ProductID,
				Quantity = offerData.Customer.OfferedContractInfo.Products.entries[0].Quantity,
				Payment = offerData.Customer.OfferedContractInfo.Payment
			};
			decimal value2 = Math.Round((decimal)(DealCalculator.CalculateSuccessProbability(offerData.Customer, selectedProduct, offerData.Quantity, offerData.Price, initialOfferData) * 100f), 3);
			DisplayHelper.UpdateCounterOfferDisplayText($"Probability of success: {value2}%", $"Price per unit: {offerData.Price / (float)offerData.Quantity}\nMax Spend: {value}");
		}

		private void EvaluateCounterOffer(StringBuilder stringBuilder, OfferData offerData)
		{
			(float maxSpend, float dailyAverage) tuple = DealCalculator.CalculateSpendingLimits(offerData.Customer);
			float item = tuple.maxSpend;
			float item2 = tuple.dailyAverage;
			decimal value = Math.Round((decimal)item, 2);
			stringBuilder.Append('\n');
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(24, 1, stringBuilder2);
			handler.AppendLiteral("Adjusted Weekly Spend: ");
			handler.AppendFormatted(offerData.Customer.CustomerData.GetAdjustedWeeklySpend(offerData.Customer.NPC.RelationData.RelationDelta / 5f));
			handler.AppendLiteral("\n");
			stringBuilder3.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2);
			handler.AppendLiteral("Order Days: ");
			handler.AppendFormatted(offerData.Customer.CustomerData.GetOrderDays(offerData.Customer.CurrentAddiction, offerData.Customer.NPC.RelationData.RelationDelta / 5f).Count);
			handler.AppendLiteral("\n");
			stringBuilder4.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(22, 1, stringBuilder2);
			handler.AppendLiteral("Average Daily Spend: ");
			handler.AppendFormatted(item2);
			handler.AppendLiteral("\n");
			stringBuilder5.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(33, 1, stringBuilder2);
			handler.AppendLiteral("Daily Spend Threshold (3x Avg): ");
			handler.AppendFormatted(value);
			handler.AppendLiteral("\n");
			stringBuilder6.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder7 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(19, 1, stringBuilder2);
			handler.AppendLiteral("Min Weekly Spend: ");
			handler.AppendFormatted(offerData.Customer.customerData.MinWeeklySpend);
			handler.AppendLiteral("\n");
			stringBuilder7.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder8 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(19, 1, stringBuilder2);
			handler.AppendLiteral("Max Weekly Spend: ");
			handler.AppendFormatted(offerData.Customer.customerData.MaxWeeklySpend);
			handler.AppendLiteral("\n");
			stringBuilder8.Append(ref handler);
			string text = "";
			Enumerator<ProductDefinition> enumerator = offerData.Customer.OrderableProducts.GetEnumerator();
			while (enumerator.MoveNext())
			{
				ProductDefinition current = enumerator.Current;
				text += $"[Name: {((ItemDefinition)current).Name}, Price: {current.Price}, Market: {current.MarketValue}],\n";
			}
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder9 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(21, 1, stringBuilder2);
			handler.AppendLiteral("Orderable Products: ");
			handler.AppendFormatted(text);
			handler.AppendLiteral("\n");
			stringBuilder9.Append(ref handler);
			if (offerData.Price >= item)
			{
				stringBuilder.Append("\nGuaranteed Failure - order must be less than 3x average daily spend\n");
				DisplayHelper.UpdateCounterOfferDisplayText("Guaranteed Failure", $"Exceeded Max Spend ({value})");
				return;
			}
			InitialOfferData initialOfferData = new InitialOfferData
			{
				ProductId = offerData.Customer.OfferedContractInfo.Products.entries[0].ProductID,
				Quantity = offerData.Customer.OfferedContractInfo.Products.entries[0].Quantity,
				Payment = offerData.Customer.OfferedContractInfo.Payment
			};
			decimal value2 = Math.Round((decimal)(DealCalculator.CalculateSuccessProbability(offerData.Customer, offerData.Product, offerData.Quantity, offerData.Price, initialOfferData) * 100f), 3);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder10 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(27, 1, stringBuilder2);
			handler.AppendLiteral("\nProbability of success: ");
			handler.AppendFormatted(value2);
			handler.AppendLiteral("%\n");
			stringBuilder10.Append(ref handler);
			DisplayHelper.UpdateCounterOfferDisplayText($"Probability of success: {value2}%", "");
		}

		public override void OnInitializeMelon()
		{
			Instance = this;
			uiHandler = new UIHandler();
			Config.Initialize();
			((MelonBase)this).LoggerInstance.Msg("Initialized Mod");
		}

		public override void OnGUI()
		{
			uiHandler.OnGUI();
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (sceneName == "Main")
			{
				try
				{
					productManager = Object.FindObjectsOfType<ProductManager>()[0];
					Melon<Core>.Logger.Msg($"ProductManager: {productManager}");
				}
				catch (Exception ex)
				{
					Melon<Core>.Logger.Error("Error finding ProductManager: " + ex.Message);
				}
			}
			((MelonMod)this).OnSceneWasLoaded(buildIndex, sceneName);
		}

		public static float EvaluatePriceAcceptance(ProductDefinition product, List<CustomerAppeal> customerAppeals, float price)
		{
			float num = 0f;
			foreach (CustomerAppeal customerAppeal in customerAppeals)
			{
				Customer customer = customerAppeal.Customer;
				if (customerAppeal.Appeal < 0.05f)
				{
					continue;
				}
				float item = DealCalculator.CalculateSpendingLimits(customer).maxSpend;
				PaymentQuantityResult paymentQuantityResult = CustomerHelper.CalculatePaymentQuantity(product, customer, price);
				InitialOfferData initialOfferData = new InitialOfferData
				{
					ProductId = ((ItemDefinition)product).ID,
					Quantity = paymentQuantityResult.Quantity,
					Payment = paymentQuantityResult.Payment
				};
				var (num2, num3) = DealCalculator.FindOptimalQuantity(customer, product, paymentQuantityResult.Quantity, paymentQuantityResult.Payment, initialOfferData);
				if (num3 != 0 && num2 != 0)
				{
					float num4 = (float)num3 / (float)Math.Floor(item);
					_ = 1f;
					if (num4 >= Config.MinSuccessProbability.Value)
					{
						num += num4;
					}
				}
			}
			return num;
		}

		public static (float bestPrice, float spenderScore) GetOptimalPrice(ProductDefinition product, List<CustomerAppeal> customerAppeals, float initialPrice, float minPrice, float maxPrice, Action<(float bestPrice, float spenderScore)> callback = null)
		{
			if (optimalPriceCache.TryGetValue(((ItemDefinition)product).ID, out (float, float) value))
			{
				callback?.Invoke(value);
				return value;
			}
			new DelayedPriceCalculator(product, customerAppeals, initialPrice, minPrice, maxPrice, delegate((float bestPrice, float spenderScore) result)
			{
				optimalPriceCache[((ItemDefinition)product).ID] = result;
				callback?.Invoke(result);
			}).Start();
			return (initialPrice, 0f);
		}

		public override void OnSceneWasUnloaded(int buildIndex, string sceneName)
		{
			if (listening)
			{
				listening = false;
			}
		}

		public override void OnUpdate()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			SceneManager.GetActiveScene();
			Scene activeScene = SceneManager.GetActiveScene();
			bool num = ((Scene)(ref activeScene)).name == "Main";
			MessagesApp instance = PlayerSingleton<MessagesApp>.Instance;
			if (num && !listening && (Object)(object)instance != (Object)null)
			{
				Subscribe();
			}
		}

		private UnityAction Subscribe()
		{
			UnityAction<string> changeListener = UnityAction<string>.op_Implicit((Action<string>)delegate
			{
				OfferPriceChangeCheckWithLog();
			});
			((UnityEvent<string>)(object)PlayerSingleton<MessagesApp>.Instance.CounterofferInterface.PriceInput.onValueChanged).AddListener(changeListener);
			((MelonBase)this).LoggerInstance.Msg("Attached listener");
			listening = true;
			return UnityAction.op_Implicit((Action)delegate
			{
				((UnityEvent<string>)(object)PlayerSingleton<MessagesApp>.Instance.CounterofferInterface.PriceInput.onValueChanged).RemoveListener(changeListener);
			});
		}
	}
	public static class Config
	{
		private static MelonPreferences_Category DealOptimizerCategory;

		public static MelonPreferences_Entry<float> MinSuccessProbability;

		public static MelonPreferences_Entry<bool> PriceOptimizationEnabled;

		public static MelonPreferences_Entry<bool> CounterOfferDarkModeEnabled;

		private static MelonPreferences_Category DealOptimizerCategory_Automation;

		public static MelonPreferences_Entry<bool> AutoCounterOfferEnabled;

		public static MelonPreferences_Entry<bool> AutoContractAcceptedEnabled;

		public static MelonPreferences_Entry<int> AutoContractAcceptedWindow;

		public static MelonPreferences_Entry<bool> IncreaseQuantityEnabled;

		public static MelonPreferences_Entry<bool> AutoHandoverEnabled;

		public static MelonPreferences_Entry<bool> AutoInstantDealEnabled;

		private static MelonPreferences_Category DealOptimizerCategory_Features;

		public static MelonPreferences_Entry<bool> DelayAutoResponseDuringSave;

		public static void Initialize()
		{
			DealOptimizerCategory = MelonPreferences.CreateCategory("HighBaller_IL2CPP");
			MinSuccessProbability = DealOptimizerCategory.CreateEntry<float>("MinSuccessProbability", 0.98f, "Minimum Success Probability", "The minimum probability of success required for a deal (0.0 to 1.0)", false, false, (ValueValidator)null, (string)null);
			PriceOptimizationEnabled = DealOptimizerCategory.CreateEntry<bool>("PriceOptimizationEnabled", false, "Price Optimization Enabled", "Whether to enable price optimization", false, false, (ValueValidator)null, (string)null);
			CounterOfferDarkModeEnabled = DealOptimizerCategory.CreateEntry<bool>("CounterOfferDarkModeEnabled", true, "Counter Offer Dark Mode Enabled", "Whether to enable counter offer dark mode", false, false, (ValueValidator)null, (string)null);
			((MelonEventBase<LemonAction<float, float>>)(object)MinSuccessProbability.OnEntryValueChanged).Subscribe((LemonAction<float, float>)delegate
			{
				Melon<Core>.Logger.Msg($"Minimum success probability changed to: {MinSuccessProbability.Value}");
			}, 0, false);
			DealOptimizerCategory_Automation = MelonPreferences.CreateCategory("HighBaller_IL2CPP_Automation");
			AutoCounterOfferEnabled = DealOptimizerCategory_Automation.CreateEntry<bool>("AutoCounterOfferEnabled", false, "Enable Auto Counter Offer", "Whether to enable auto counter offer", false, false, (ValueValidator)null, (string)null);
			AutoContractAcceptedEnabled = DealOptimizerCategory_Automation.CreateEntry<bool>("AutoContractAcceptedEnabled", false, "Enable Auto Deal Scheduling", "Whether to enable auto deal scheduling", false, false, (ValueValidator)null, (string)null);
			AutoContractAcceptedWindow = DealOptimizerCategory_Automation.CreateEntry<int>("AutoContractAcceptedWindow", 4, "Auto Deal Time Window (1 = Morning, 2 = Afternoon, 3 = Night, 4 = Late Night)", "The window to auto accept deal", false, false, (ValueValidator)null, (string)null);
			IncreaseQuantityEnabled = DealOptimizerCategory_Automation.CreateEntry<bool>("IncreaseQuantityEnabled", false, "Increase Quantity till max spend is reached", "If enabled, the quantity will be increased until the max spend is reached", false, false, (ValueValidator)null, (string)null);
			AutoHandoverEnabled = DealOptimizerCategory_Automation.CreateEntry<bool>("AutoHandoverEnabled", false, "Enable automatic handovers", "Whether to enable automatic handover", false, false, (ValueValidator)null, (string)null);
			DealOptimizerCategory_Features = MelonPreferences.CreateCategory("HighBaller_IL2CPP_Features");
			DelayAutoResponseDuringSave = DealOptimizerCategory_Features.CreateEntry<bool>("DelayAutoResponseDuringSave", true, "Don't send auto responses during save", "Whether to delay auto response during save", false, false, (ValueValidator)null, (string)null);
		}
	}
	public class DelayedCounterOffer
	{
		[CompilerGenerated]
		private sealed class <DelayedCounterOfferCoroutine>d__7 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public DelayedCounterOffer <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedCounterOfferCoroutine>d__7(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Expected O, but got Unknown
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: Expected O, but got Unknown
				int num = <>1__state;
				DelayedCounterOffer delayedCounterOffer = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Melon<Core>.Logger.Msg("Delayed counter offer started");
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					break;
				case 2:
					<>1__state = -1;
					break;
				}
				if (Singleton<SaveManager>.Instance.IsSaving)
				{
					Melon<Core>.Logger.Msg("Waiting for save to finish");
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 2;
					return true;
				}
				Melon<Core>.Logger.Msg("Delayed counter offer ended");
				delayedCounterOffer.customer.SendCounteroffer(delayedCounterOffer.product, delayedCounterOffer.quantity, delayedCounterOffer.price);
				MelonCoroutines.Stop(delayedCounterOffer.coroutineToken);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private Customer customer;

		private ProductDefinition product;

		private int quantity;

		private float price;

		private object coroutineToken;

		public DelayedCounterOffer(Customer customer, ProductDefinition product, int quantity, float price)
		{
			this.customer = customer;
			this.product = product;
			this.quantity = quantity;
			this.price = price;
		}

		public void Start()
		{
			coroutineToken = MelonCoroutines.Start(DelayedCounterOfferCoroutine());
		}

		[IteratorStateMachine(typeof(<DelayedCounterOfferCoroutine>d__7))]
		private IEnumerator DelayedCounterOfferCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedCounterOfferCoroutine>d__7(0)
			{
				<>4__this = this
			};
		}
	}
	public class DelayedScheduler
	{
		[CompilerGenerated]
		private sealed class <DelayedSchedulerCoroutine>d__5 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public DelayedScheduler <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedSchedulerCoroutine>d__5(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Expected O, but got Unknown
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: Expected O, but got Unknown
				//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_0170: Unknown result type (might be due to invalid IL or missing references)
				//IL_018b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0204: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				DelayedScheduler delayedScheduler = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Melon<Core>.Logger.Msg("Delayed scheduling started");
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					break;
				case 2:
					<>1__state = -1;
					break;
				}
				if (Singleton<SaveManager>.Instance.IsSaving)
				{
					Melon<Core>.Logger.Msg("Waiting for save to finish");
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 2;
					return true;
				}
				Melon<Core>.Logger.Msg("Delayed scheduling ended");
				DealWindowInfo windowInfo = DealWindowInfo.GetWindowInfo(delayedScheduler.window);
				ContractInfo offeredContractInfo = delayedScheduler.customer.OfferedContractInfo;
				Melon<Core>.Logger.Msg($"Payment: {offeredContractInfo.Payment}, Quantity: {offeredContractInfo.Products.GetTotalQuantity()}, ProductID: {offeredContractInfo.Products.entries[0].ProductID}, Quantity: {offeredContractInfo.Products.entries[0].Quantity}");
				delayedScheduler.customer.OfferedContractInfo.DeliveryWindow.WindowStartTime = windowInfo.StartTime;
				delayedScheduler.customer.OfferedContractInfo.DeliveryWindow.WindowEndTime = windowInfo.EndTime;
				Melon<Core>.Logger.Msg($"Window: {windowInfo.StartTime} - {windowInfo.EndTime}");
				delayedScheduler.customer.PlayContractAcceptedReaction();
				Melon<Core>.Logger.Msg("Played contract accepted reaction");
				delayedScheduler.customer.SendContractAccepted(delayedScheduler.window, true);
				Melon<Core>.Logger.Msg("Sent contract accepted");
				if (!InstanceFinder.IsServer)
				{
					Melon<Core>.Logger.Msg("Clearing contract");
					delayedScheduler.customer.OfferedContractInfo = null;
				}
				MelonCoroutines.Stop(delayedScheduler.coroutineToken);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private Customer customer;

		private EDealWindow window;

		private object coroutineToken;

		public DelayedScheduler(Customer customer, EDealWindow window)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			this.customer = customer;
			this.window = window;
		}

		public void Start()
		{
			coroutineToken = MelonCoroutines.Start(DelayedSchedulerCoroutine());
		}

		[IteratorStateMachine(typeof(<DelayedSchedulerCoroutine>d__5))]
		private IEnumerator DelayedSchedulerCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedSchedulerCoroutine>d__5(0)
			{
				<>4__this = this
			};
		}
	}
	public class DelayedPriceCalculator
	{
		[CompilerGenerated]
		private sealed class <CalculatePriceCoroutine>d__12 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public DelayedPriceCalculator <>4__this;

			private int <low>5__2;

			private int <high>5__3;

			private int <bestPrice>5__4;

			private float <spenderScore>5__5;

			private int <iterations>5__6;

			private int <maxIterations>5__7;

			private int <price>5__8;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CalculatePriceCoroutine>d__12(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fe: Expected O, but got Unknown
				//IL_0165: Unknown result type (might be due to invalid IL or missing references)
				//IL_016f: Expected O, but got Unknown
				int num = <>1__state;
				DelayedPriceCalculator delayedPriceCalculator = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Melon<Core>.Logger.Msg("Starting delayed price calculation for " + ((ItemDefinition)delayedPriceCalculator.product).Name);
					<low>5__2 = Mathf.FloorToInt(delayedPriceCalculator.minPrice);
					<high>5__3 = Mathf.CeilToInt(delayedPriceCalculator.maxPrice);
					<bestPrice>5__4 = Mathf.RoundToInt(delayedPriceCalculator.initialPrice);
					<spenderScore>5__5 = Core.EvaluatePriceAcceptance(delayedPriceCalculator.product, delayedPriceCalculator.customerAppeals, <bestPrice>5__4);
					<iterations>5__6 = 0;
					<maxIterations>5__7 = 20;
					goto IL_017f;
				case 1:
					<>1__state = -1;
					goto IL_017f;
				case 2:
					{
						<>1__state = -1;
						<price>5__8++;
						break;
					}
					IL_017f:
					if (<iterations>5__6 < <maxIterations>5__7 && <high>5__3 - <low>5__2 > 1 && !delayedPriceCalculator.isCancelled)
					{
						int num2 = <low>5__2 + (<high>5__3 - <low>5__2) / 3;
						int num3 = <high>5__3 - (<high>5__3 - <low>5__2) / 3;
						float num4 = Core.EvaluatePriceAcceptance(delayedPriceCalculator.product, delayedPriceCalculator.customerAppeals, num2);
						float num5 = Core.EvaluatePriceAcceptance(delayedPriceCalculator.product, delayedPriceCalculator.customerAppeals, num3);
						if (num4 > <spenderScore>5__5)
						{
							<bestPrice>5__4 = num2;
							<spenderScore>5__5 = num4;
						}
						if (num5 > <spenderScore>5__5)
						{
							<bestPrice>5__4 = num3;
							<spenderScore>5__5 = num5;
						}
						if (num4 > num5)
						{
							<high>5__3 = num3;
						}
						else
						{
							<low>5__2 = num2;
						}
						<iterations>5__6++;
						<>2__current = (object)new WaitForSeconds(0.01f);
						<>1__state = 1;
						return true;
					}
					<price>5__8 = <low>5__2;
					break;
				}
				if (<price>5__8 <= <high>5__3 && !delayedPriceCalculator.isCancelled)
				{
					float num6 = Core.EvaluatePriceAcceptance(delayedPriceCalculator.product, delayedPriceCalculator.customerAppeals, <price>5__8);
					if (num6 > <spenderScore>5__5)
					{
						<bestPrice>5__4 = <price>5__8;
						<spenderScore>5__5 = num6;
					}
					<>2__current = (object)new WaitForSeconds(0.01f);
					<>1__state = 2;
					return true;
				}
				if (!delayedPriceCalculator.isCancelled)
				{
					Melon<Core>.Logger.Msg($"Price calculation complete for {((ItemDefinition)delayedPriceCalculator.product).Name}: {<bestPrice>5__4}");
					delayedPriceCalculator.callback((<bestPrice>5__4, <spenderScore>5__5));
				}
				delayedPriceCalculator.isCalculating = false;
				MelonCoroutines.Stop(delayedPriceCalculator.coroutineToken);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private ProductDefinition product;

		private List<Core.CustomerAppeal> customerAppeals;

		private float initialPrice;

		private float minPrice;

		private float maxPrice;

		private Action<(float bestPrice, float spenderScore)> callback;

		private object coroutineToken;

		private bool isCalculating;

		private bool isCancelled;

		public DelayedPriceCalculator(ProductDefinition product, List<Core.CustomerAppeal> customerAppeals, float initialPrice, float minPrice, float maxPrice, Action<(float bestPrice, float spenderScore)> callback)
		{
			this.product = product;
			this.customerAppeals = customerAppeals;
			this.initialPrice = initialPrice;
			this.minPrice = minPrice;
			this.maxPrice = maxPrice;
			this.callback = callback;
		}

		public void Start()
		{
			if (!isCalculating)
			{
				isCalculating = true;
				isCancelled = false;
				coroutineToken = MelonCoroutines.Start(CalculatePriceCoroutine());
			}
		}

		public void Cancel()
		{
			isCancelled = true;
			if (coroutineToken != null)
			{
				MelonCoroutines.Stop(coroutineToken);
				coroutineToken = null;
			}
			isCalculating = false;
		}

		[IteratorStateMachine(typeof(<CalculatePriceCoroutine>d__12))]
		private IEnumerator CalculatePriceCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CalculatePriceCoroutine>d__12(0)
			{
				<>4__this = this
			};
		}
	}
	public class InventoryOfferService
	{
		private static float GetOfferSuccessChance(Customer customer, List<ItemInstance> items, float askingPrice)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			float num = customer.CustomerData.GetAdjustedWeeklySpend(customer.NPC.RelationData.RelationDelta / 5f) / (float)customer.CustomerData.GetOrderDays(customer.CurrentAddiction, customer.NPC.RelationData.RelationDelta / 5f).Count;
			float num2 = 0f;
			int num3 = 0;
			for (int i = 0; i < items.Count; i++)
			{
				if (items[i] is ProductItemInstance)
				{
					ItemInstance obj = items[i];
					ProductItemInstance val = (ProductItemInstance)(object)((obj is ProductItemInstance) ? obj : null);
					if (!((Object)(object)val.AppliedPackaging == (Object)null))
					{
						? val2 = customer;
						ItemDefinition definition = items[i].Definition;
						float num4 = Mathf.InverseLerp(-1f, 1f, ((Customer)val2).GetProductEnjoyment((ProductDefinition)(object)((definition is ProductDefinition) ? definition : null), ((QualityItemInstance)val).Quality));
						num2 += num4 * (float)((ItemInstance)val).Quantity * (float)val.Amount;
						num3 += ((ItemInstance)val).Quantity * val.Amount;
					}
				}
			}
			if (num3 == 0)
			{
				return 0f;
			}
			float num5 = num2 / (float)num3;
			float num6 = askingPrice / (float)num3;
			float num7 = 0f;
			for (int j = 0; j < items.Count; j++)
			{
				if (items[j] is ProductItemInstance)
				{
					ItemInstance obj2 = items[j];
					ProductItemInstance val3 = (ProductItemInstance)(object)((obj2 is ProductItemInstance) ? obj2 : null);
					if (!((Object)(object)val3.AppliedPackaging == (Object)null))
					{
						ItemDefinition definition2 = ((ItemInstance)val3).Definition;
						float valueProposition = Customer.GetValueProposition((ProductDefinition)(object)((definition2 is ProductDefinition) ? definition2 : null), num6);
						num7 += valueProposition * (float)val3.Amount * (float)((ItemInstance)val3).Quantity;
					}
				}
			}
			double num8 = (double)num7 / (double)num3;
			float num9 = askingPrice / num;
			float item = 1f;
			if ((double)num9 > 1.0)
			{
				item = Mathf.Clamp((float)(1.0 - (double)Mathf.Sqrt(num9) / 4.0), 0.01f, 1f);
			}
			List<float> list = new List<float>
			{
				num5 + customer.CurrentAddiction * 0.25f,
				Mathf.Pow((float)num8, 1.5f),
				item
			};
			list.Sort();
			if (!((double)list[0] < 0.009999999776482582) && !((double)num9 > 3.0))
			{
				return (float)((double)list[0] * 0.699999988079071 + (double)list[1] * 0.20000000298023224 + (double)list[2] * 0.10000000149011612);
			}
			return 0f;
		}

		public static float GetOptimalPrice(Customer customer, List<ItemInstance> items, float targetSuccessChance = 0.9f)
		{
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			float num = customer.CustomerData.GetAdjustedWeeklySpend(customer.NPC.RelationData.RelationDelta / 5f) / (float)customer.CustomerData.GetOrderDays(customer.CurrentAddiction, customer.NPC.RelationData.RelationDelta / 5f).Count;
			float num2 = 0f;
			int num3 = 0;
			for (int i = 0; i < items.Count; i++)
			{
				ItemInstance obj = items[i];
				ProductItemInstance val = (ProductItemInstance)(object)((obj is ProductItemInstance) ? obj : null);
				if (val != null)
				{
					Melon<Core>.Logger.Msg($"ProductItem: {((ItemInstance)val).ID} - {((ItemInstance)val).Quantity} - {((ItemInstance)val).Definition.Name}");
					if (!((Object)(object)val.AppliedPackaging == (Object)null))
					{
						? val2 = customer;
						ItemDefinition definition = items[i].Definition;
						float num4 = Mathf.InverseLerp(-1f, 1f, ((Customer)val2).GetProductEnjoyment((ProductDefinition)(object)((definition is ProductDefinition) ? definition : null), ((QualityItemInstance)val).Quality));
						Melon<Core>.Logger.Msg($"Enjoyment: {num4}");
						num2 += num4 * (float)((ItemInstance)val).Quantity * (float)val.Amount;
						num3 += ((ItemInstance)val).Quantity * val.Amount;
					}
				}
			}
			if (num3 == 0)
			{
				return 0f;
			}
			float avgEnjoyment = num2 / (float)num3;
			float addictionBoost = customer.CurrentAddiction * 0.25f;
			float num5 = 1f;
			float num6 = num * 2f;
			float num7 = (num5 + num6) / 2f;
			float num8 = 0f;
			for (int j = 0; j < 20; j++)
			{
				num8 = CalculateSuccessChance(customer, items, num7, num, avgEnjoyment, addictionBoost, num3);
				if (Math.Abs(num8 - targetSuccessChance) < 0.01f)
				{
					break;
				}
				if (num8 < targetSuccessChance)
				{
					num6 = num7;
				}
				else
				{
					num5 = num7;
				}
				num7 = (num5 + num6) / 2f;
			}
			return num7;
		}

		private static float CalculateSuccessChance(Customer customer, List<ItemInstance> items, float askingPrice, float weeklySpendPerDay, float avgEnjoyment, float addictionBoost, int totalUnits)
		{
			float num = askingPrice / (float)totalUnits;
			float num2 = 0f;
			foreach (ItemInstance item2 in items)
			{
				ProductItemInstance val = (ProductItemInstance)(object)((item2 is ProductItemInstance) ? item2 : null);
				if (val != null)
				{
					float num3 = num2;
					ItemDefinition definition = ((ItemInstance)val).Definition;
					num2 = num3 + Customer.GetValueProposition((ProductDefinition)(object)((definition is ProductDefinition) ? definition : null), num) * (float)val.Amount * (float)((ItemInstance)val).Quantity;
				}
			}
			float num4 = num2 / (float)totalUnits;
			float num5 = askingPrice / weeklySpendPerDay;
			float item = 1f;
			if ((double)num5 > 1.0)
			{
				item = Mathf.Clamp(1f - Mathf.Sqrt(num5) / 4f, 0.01f, 1f);
			}
			List<float> list = new List<float>
			{
				avgEnjoyment + addictionBoost,
				Mathf.Pow(num4, 1.5f),
				item
			};
			list.Sort();
			if (list[0] < 0.01f || (double)num5 > 3.0)
			{
				return 0f;
			}
			return list[0] * 0.7f + list[1] * 0.2f + list[2] * 0.1f;
		}

		public static List<OfferProduct> FindOptimalInventoryOffer(Customer customer, float targetSuccessChance = 0.9f)
		{
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			float num = customer.CustomerData.GetAdjustedWeeklySpend(customer.NPC.RelationData.RelationDelta / 5f) / (float)customer.CustomerData.GetOrderDays(customer.CurrentAddiction, customer.NPC.RelationData.RelationDelta / 5f).Count * 3f;
			Melon<Core>.Logger.Msg($"Customer max spend: {num:F2}");
			List<OfferProduct> list = new List<OfferProduct>();
			foreach (ItemSlot item in (Il2CppArrayBase<ItemSlot>)(object)Player.Local.Inventory)
			{
				ItemInstance itemInstance = item.ItemInstance;
				if (itemInstance == null)
				{
					continue;
				}
				ProductItemInstance val = ((Il2CppObjectBase)itemInstance).TryCast<ProductItemInstance>();
				if (val != null && (Object)(object)val.AppliedPackaging != (Object)null && ((ItemInstance)val).Quantity > 0)
				{
					Instance logger = Melon<Core>.Logger;
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(49, 3);
					defaultInterpolatedStringHandler.AppendLiteral("Processing inventory item: ");
					defaultInterpolatedStringHandler.AppendFormatted(itemInstance.ID);
					defaultInterpolatedStringHandler.AppendLiteral(", Type: ");
					defaultInterpolatedStringHandler.AppendFormatted(((MemberInfo)((Object)itemInstance).GetIl2CppType()).Name);
					defaultInterpolatedStringHandler.AppendLiteral(", Definition: ");
					ItemDefinition definition = itemInstance.Definition;
					object value;
					if (definition == null)
					{
						value = null;
					}
					else
					{
						Type il2CppType = ((Object)definition).GetIl2CppType();
						value = ((il2CppType != null) ? ((MemberInfo)il2CppType).Name : null);
					}
					defaultInterpolatedStringHandler.AppendFormatted((string?)value);
					logger.Msg(defaultInterpolatedStringHandler.ToStringAndClear());
					OfferProduct offerProduct = new OfferProduct(val, customer);
					if (offerProduct.CustomerEnjoyment >= 0f)
					{
						list.Add(offerProduct);
						Melon<Core>.Logger.Msg($"Added available product: {offerProduct.Name}, Enjoyment: {offerProduct.CustomerEnjoyment:F2}, Quality: {offerProduct.Quality}, Quantity: {offerProduct.Quantity}");
					}
					else
					{
						Melon<Core>.Logger.Msg($"Skipping product: {offerProduct.Name} - {offerProduct.CustomerEnjoyment:F2}, Quality: {offerProduct.Quality}, Quantity: {offerProduct.Quantity}");
					}
				}
			}
			if (list.Count == 0)
			{
				Melon<Core>.Logger.Warning("No suitable products found in inventory for this customer");
				return new List<OfferProduct>();
			}
			list.Sort(delegate(OfferProduct a, OfferProduct b)
			{
				int num8 = b.CustomerEnjoyment.CompareTo(a.CustomerEnjoyment);
				return (num8 != 0) ? num8 : b.Price.CompareTo(a.Price);
			});
			float num2 = 0f;
			List<OfferProduct> list2 = new List<OfferProduct>();
			List<OfferProduct> list3 = new List<OfferProduct>();
			list3.Add(list[0]);
			float num3 = CalculateOptimalPrice(customer, list3, targetSuccessChance);
			float num4 = num3 / num;
			Melon<Core>.Logger.Msg($"Initial product optimal price: {num3:F2}, Ratio to max spend: {num4:F2}");
			if (num4 > 1f && list[0].Quantity > 1)
			{
				int quantity = list[0].Quantity;
				int num5 = 1;
				int num6 = quantity;
				int num7 = num6 / 2;
				while (num5 <= num6)
				{
					list[0].Quantity = num7;
					num3 = CalculateOptimalPrice(customer, list3, targetSuccessChance);
					num4 = num3 / num;
					if (Math.Abs(num4 - 1f) < 0.05f)
					{
						break;
					}
					if (num4 > 1f)
					{
						num6 = num7 - 1;
					}
					else
					{
						num5 = num7 + 1;
					}
					num7 = (num5 + num6) / 2;
				}
				list[0].Quantity = quantity;
				OfferProduct offerProduct2 = new OfferProduct(list[0]);
				offerProduct2.Quantity = num7;
				list2.Clear();
				list2.Add(offerProduct2);
				num2 = num4;
			}
			else if (num4 <= 1f)
			{
				list2 = new List<OfferProduct>(list3);
				num2 = num4;
				for (int i = 1; i < list.Count; i++)
				{
					list3.Add(list[i]);
					num3 = CalculateOptimalPrice(customer, list3, targetSuccessChance);
					num4 = num3 / num;
					Melon<Core>.Logger.Msg($"Adding product {i}, new price: {num3:F2}, Ratio: {num4:F2}");
					if (num4 <= 1f && num4 > num2)
					{
						list2 = new List<OfferProduct>(list3);
						num2 = num4;
						Melon<Core>.Logger.Msg("Found better combination");
					}
					if (num4 > 1f)
					{
						list3.RemoveAt(list3.Count - 1);
					}
				}
			}
			num3 = CalculateOptimalPrice(customer, list2, targetSuccessChance);
			Melon<Core>.Logger.Msg($"Final optimal combination has {list2.Count} products with price {num3:F2} ({num2 * 100f:F0}% of customer's max spend)");
			return list2;
		}

		public static float CalculateOptimalPrice(Customer customer, List<OfferProduct> items, float targetSuccessChance)
		{
			float num = customer.CustomerData.GetAdjustedWeeklySpend(customer.NPC.RelationData.RelationDelta / 5f) / (float)customer.CustomerData.GetOrderDays(customer.CurrentAddiction, customer.NPC.RelationData.RelationDelta / 5f).Count;
			float num2 = 0f;
			int num3 = 0;
			foreach (OfferProduct item in items)
			{
				num2 += item.CustomerEnjoyment * (float)item.Quantity * (float)item.Amount;
				num3 += item.Quantity * item.Amount;
			}
			if (num3 == 0)
			{
				return 0f;
			}
			float avgEnjoyment = num2 / (float)num3;
			float addictionBoost = customer.CurrentAddiction * 0.25f;
			float num4 = 1f;
			float num5 = num * 2f;
			float num6 = (num4 + num5) / 2f;
			float num7 = 0f;
			for (int i = 0; i < 20; i++)
			{
				num7 = CalculateSuccessChance(customer, items, num6, num, avgEnjoyment, addictionBoost, num3);
				if (Math.Abs(num7 - targetSuccessChance) < 0.01f)
				{
					break;
				}
				if (num7 < targetSuccessChance)
				{
					num5 = num6;
				}
				else
				{
					num4 = num6;
				}
				num6 = (num4 + num5) / 2f;
			}
			return num6;
		}

		private static float CalculateSuccessChance(Customer customer, List<OfferProduct> items, float askingPrice, float weeklySpendPerDay, float avgEnjoyment, float addictionBoost, int totalUnits)
		{
			float num = askingPrice / (float)totalUnits;
			float num2 = 0f;
			foreach (OfferProduct item2 in items)
			{
				if ((Object)(object)item2.ProductDefinition != (Object)null)
				{
					num2 += Customer.GetValueProposition(item2.ProductDefinition, num) * (float)item2.Amount * (float)item2.Quantity;
				}
				else
				{
					Melon<Core>.Logger.Warning("ProductDefinition is null for item: " + item2.Name);
				}
			}
			float num3 = num2 / (float)totalUnits;
			float num4 = askingPrice / weeklySpendPerDay;
			float item = 1f;
			if ((double)num4 > 1.0)
			{
				item = Mathf.Clamp(1f - Mathf.Sqrt(num4) / 4f, 0.01f, 1f);
			}
			List<float> list = new List<float>
			{
				avgEnjoyment + addictionBoost,
				Mathf.Pow(num3, 1.5f),
				item
			};
			list.Sort();
			if (list[0] < 0.01f || (double)num4 > 3.0)
			{
				return 0f;
			}
			return list[0] * 0.7f + list[1] * 0.2f + list[2] * 0.1f;
		}
	}
	public static class HandoverScreenOpenPatch
	{
		public static void Postfix(HandoverScreen __instance, Contract contract, Customer customer, EMode mode, Action<EHandoverOutcome, List<ItemInstance>, float> callback, Func<List<ItemInstance>, float, float> successChanceMethod)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)mode != 2 || !Config.AutoHandoverEnabled.Value)
			{
				return;
			}
			Instance logger = Melon<Core>.Logger;
			object obj;
			if (customer == null)
			{
				obj = null;
			}
			else
			{
				NPC nPC = customer.NPC;
				obj = ((nPC != null) ? nPC.fullName : null);
			}
			logger.Msg("HandoverScreen opened in Offer mode for customer: " + (string?)obj);
			List<OfferProduct> list = InventoryOfferService.FindOptimalInventoryOffer(customer);
			if (list.Count == 0)
			{
				Melon<Core>.Logger.Warning("No optimal items found for offer");
				return;
			}
			float num = InventoryOfferService.CalculateOptimalPrice(customer, list, 0.9f);
			if (num <= 0f)
			{
				Melon<Core>.Logger.Warning("Could not calculate a valid price");
				return;
			}
			Melon<Core>.Logger.Msg($"Found optimal items: {list.Count} items for {num:F2}");
			foreach (OfferProduct item in list)
			{
				Melon<Core>.Logger.Msg("Processing offer product: " + (item?.Name ?? "null") + ", ID: " + (item?.ID ?? "null"));
				foreach (ItemSlot item2 in (Il2CppArrayBase<ItemSlot>)(object)Player.Local.Inventory)
				{
					ItemInstance val = ((item2 != null) ? item2.ItemInstance : null);
					if (val == null)
					{
						Melon<Core>.Logger.Warning("Found null item in inventory slot");
					}
					else
					{
						if (!(val.ID == item.ID))
						{
							continue;
						}
						ProductItemInstance val2 = ((Il2CppObjectBase)val).TryCast<ProductItemInstance>();
						if (val2 == null)
						{
							Melon<Core>.Logger.Warning("Failed to cast item " + val.ID + " to ProductItemInstance");
							continue;
						}
						if (!((Object)(object)val2.AppliedPackaging == (Object)null))
						{
							((Il2CppArrayBase<ItemSlotUI>)(object)__instance.CustomerSlotUIs)[0].assignedSlot.AddItem(val, false);
							Melon<Core>.Logger.Msg($"Added item to handover selection: {val.ID}, Quantity: {val.Quantity}");
							break;
						}
						Melon<Core>.Logger.Warning("Item " + val.ID + " has null AppliedPackaging");
					}
				}
			}
			__instance.PriceSelector.SetPrice((float)(int)num);
			Melon<Core>.Logger.Msg($"Set handover price to: {num:F2}");
		}
	}
	public class UIHandler
	{
		private class PanelState
		{
			public bool IsVisible;

			public bool IsDragging;

			public Vector2 Position;

			public Vector2 DragOffset;

			public Vector2 ScrollPosition;

			public string Content;

			public string Title;

			public PanelState(string title)
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				IsVisible = false;
				IsDragging = false;
				Position = new Vector2(20f, 20f);
				DragOffset = Vector2.zero;
				ScrollPosition = Vector2.zero;
				Content = "";
				Title = title;
			}
		}

		private GUIStyle displayTextStyle;

		private static string counterOfferDisplayText = "";

		private static GUIStyle salesPanelStyle;

		private static GUIStyle salesHeaderStyle;

		private static GUIStyle salesTextStyle;

		private GUIStyle sectionHeaderStyle;

		private GUIStyle infoLabelStyle;

		private GUIStyle infoValueStyle;

		private PanelState salesPanel;

		private PanelState contactPanel;

		private DelayedPriceCalculator currentPriceCalculator;

		public static ProductEntry SelectedProduct { get; set; } = null;


		public static Customer SelectedCustomer { get; set; } = null;


		public UIHandler()
		{
			InitializeStyles();
			salesPanel = new PanelState("Sales Information");
			contactPanel = new PanelState("Contact Information");
		}

		private void InitializeStyles()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Expected O, but got Unknown
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Expected O, but got Unknown
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Expected O, but got Unknown
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Expected O, but got Unknown
			displayTextStyle = new GUIStyle(GUIStyle.op_Implicit("label"));
			displayTextStyle.fontSize = 18;
			displayTextStyle.normal.background = Texture2D.whiteTexture;
			displayTextStyle.alignment = (TextAnchor)4;
			salesPanelStyle = new GUIStyle(GUIStyle.op_Implicit("box"));
			salesPanelStyle.normal.background = Texture2D.whiteTexture;
			salesPanelStyle.normal.textColor = Color.white;
			salesPanelStyle.padding = new RectOffset(10, 10, 10, 10);
			salesHeaderStyle = new GUIStyle(GUIStyle.op_Implicit("label"));
			salesHeaderStyle.fontSize = 20;
			salesHeaderStyle.fontStyle = (FontStyle)1;
			salesHeaderStyle.normal.textColor = Color.white;
			salesHeaderStyle.alignment = (TextAnchor)4;
			salesTextStyle = new GUIStyle(GUIStyle.op_Implicit("label"));
			salesTextStyle.fontSize = 14;
			salesTextStyle.normal.textColor = Color.white;
			salesTextStyle.wordWrap = true;
			salesTextStyle.padding = new RectOffset(10, 0, 0, 0);
			sectionHeaderStyle = new GUIStyle(GUIStyle.op_Implicit("label"));
			sectionHeaderStyle.fontSize = 16;
			sectionHeaderStyle.fontStyle = (FontStyle)1;
			sectionHeaderStyle.normal.textColor = new Color(0.9f, 0.9f, 1f);
			sectionHeaderStyle.padding = new RectOffset(0, 0, 10, 5);
			infoLabelStyle = new GUIStyle(GUIStyle.op_Implicit("label"));
			infoLabelStyle.fontSize = 14;
			infoLabelStyle.fontStyle = (FontStyle)1;
			infoLabelStyle.normal.textColor = new Color(0.8f, 0.8f, 0.8f);
			infoLabelStyle.padding = new RectOffset(10, 0, 2, 2);
			infoValueStyle = new GUIStyle(GUIStyle.op_Implicit("label"));
			infoValueStyle.fontSize = 14;
			infoValueStyle.normal.textColor = new Color(1f, 0.95f, 0.8f);
			infoValueStyle.padding = new RectOffset(10, 0, 2, 8);
		}

		private string FormatCurrency(float amount)
		{
			return amount.ToString("C2", CultureInfo.GetCultureInfo("en-US"));
		}

		public void UpdateCounterOfferDisplayText(string text, string reasonText)
		{
			counterOfferDisplayText = text + "\n" + reasonText;
		}

		private string FormatSalesInfo(ProductEntry entry, float? overridePrice = null)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("<section>Product Details</section>");
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(39, 1, stringBuilder2);
			handler.AppendLiteral("<label>Product:</label> <value>");
			handler.AppendFormatted(((ItemDefinition)entry.Definition).Name);
			handler.AppendLiteral("</value>");
			stringBuilder3.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(42, 1, stringBuilder2);
			handler.AppendLiteral("<label>Base Price:</label> <value>");
			handler.AppendFormatted(FormatCurrency(entry.Definition.Price));
			handler.AppendLiteral("</value>");
			stringBuilder4.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(44, 1, stringBuilder2);
			handler.AppendLiteral("<label>Market Value:</label> <value>");
			handler.AppendFormatted(FormatCurrency(entry.Definition.MarketValue));
			handler.AppendLiteral("</value>");
			stringBuilder5.AppendLine(ref handler);
			if (overridePrice.HasValue && overridePrice.Value != entry.Definition.Price)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder6 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(45, 1, stringBuilder2);
				handler.AppendLiteral("<label>Current Price:</label> <value>");
				handler.AppendFormatted(FormatCurrency(overridePrice.Value));
				handler.AppendLiteral("</value>");
				stringBuilder6.AppendLine(ref handler);
			}
			stringBuilder.AppendLine();
			List<Customer> unlockedCustomers = Customer.UnlockedCustomers;
			List<Core.CustomerAppeal> list = new List<Core.CustomerAppeal>();
			for (int i = 0; i < unlockedCustomers.Count; i++)
			{
				list.Add(new Core.CustomerAppeal
				{
					Customer = unlockedCustomers[i],
					Appeal = CustomerHelper.GetProductAppeal(entry.Definition, unlockedCustomers[i], overridePrice),
					PaymentQuantity = CustomerHelper.CalculatePaymentQuantity(entry.Definition, unlockedCustomers[i], overridePrice)
				});
			}
			List<Core.CustomerAppeal> list2 = list.OrderByDescending((Core.CustomerAppeal ca) => ca.Appeal).ToList();
			List<Core.CustomerAppeal> list3 = list2.FindAll((Core.CustomerAppeal ca) => ca.Appeal > 0.05f);
			float value = Core.EvaluatePriceAcceptance(entry.Definition, list2, overridePrice ?? entry.Definition.Price);
			stringBuilder.AppendLine("<section>Market Analysis</section>");
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder7 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(51, 1, stringBuilder2);
			handler.AppendLiteral("<label>Potential Customers:</label> <value>");
			handler.AppendFormatted(list3.Count);
			handler.AppendLiteral("</value>");
			stringBuilder7.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder8 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(50, 1, stringBuilder2);
			handler.AppendLiteral("<label>Average Order Size:</label> <value>");
			handler.AppendFormatted((list3.Count > 0) ? list3.Average((Core.CustomerAppeal ca) => ca.PaymentQuantity.Quantity) : 0.0, "F1");
			handler.AppendLiteral("</value>");
			stringBuilder8.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder9 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(47, 1, stringBuilder2);
			handler.AppendLiteral("<label>Average Payment:</label> <value>");
			handler.AppendFormatted((list3.Count > 0) ? FormatCurrency(list3.Average((Core.CustomerAppeal ca) => ca.PaymentQuantity.Payment)) : FormatCurrency(0f));
			handler.AppendLiteral("</value>");
			stringBuilder9.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder10 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(46, 1, stringBuilder2);
			handler.AppendLiteral("<label>Per-Unit Price:</label> <value>");
			handler.AppendFormatted((list3.Count > 0) ? FormatCurrency(list3.Average((Core.CustomerAppeal ca) => ca.PaymentQuantity.Payment / (float)ca.PaymentQuantity.Quantity)) : FormatCurrency(0f));
			handler.AppendLiteral("</value>");
			stringBuilder10.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder11 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(49, 1, stringBuilder2);
			handler.AppendLiteral("<label>Max Spender Score:</label> <value>");
			handler.AppendFormatted(value, "F2");
			handler.AppendLiteral("</value>");
			stringBuilder11.AppendLine(ref handler);
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("<section>Appeal Statistics</section>");
			stringBuilder.AppendLine("<label>Customer Appeal:</label>");
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder12 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(24, 1, stringBuilder2);
			handler.AppendLiteral("<value>Average: ");
			handler.AppendFormatted((list3.Count > 0) ? list3.Average((Core.CustomerAppeal ca) => ca.Appeal) : 0f, "F2");
			handler.AppendLiteral("</value>");
			stringBuilder12.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder13 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(20, 1, stringBuilder2);
			handler.AppendLiteral("<value>Min: ");
			handler.AppendFormatted((list3.Count > 0) ? list3.Min((Core.CustomerAppeal ca) => ca.Appeal) : 0f, "F2");
			handler.AppendLiteral("</value>");
			stringBuilder13.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder14 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(20, 1, stringBuilder2);
			handler.AppendLiteral("<value>Max: ");
			handler.AppendFormatted((list3.Count > 0) ? list3.Max((Core.CustomerAppeal ca) => ca.Appeal) : 0f, "F2");
			handler.AppendLiteral("</value>");
			stringBuilder14.AppendLine(ref handler);
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("<label>Overall Appeal:</label>");
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder15 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(24, 1, stringBuilder2);
			handler.AppendLiteral("<value>Average: ");
			handler.AppendFormatted((list2.Count > 0) ? list2.Average((Core.CustomerAppeal ca) => ca.Appeal) : 0f, "F2");
			handler.AppendLiteral("</value>");
			stringBuilder15.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder16 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(20, 1, stringBuilder2);
			handler.AppendLiteral("<value>Min: ");
			handler.AppendFormatted((list2.Count > 0) ? list2.Min((Core.CustomerAppeal ca) => ca.Appeal) : 0f, "F2");
			handler.AppendLiteral("</value>");
			stringBuilder16.AppendLine(ref handler);
			stringBuilder.AppendLine();
			if (Config.PriceOptimizationEnabled.Value)
			{
				float num = overridePrice ?? entry.Definition.Price;
				float minPrice = num * 0.5f;
				float maxPrice = num * 2f;
				stringBuilder.AppendLine("<section>Price Optimization</section>");
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder17 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(46, 1, stringBuilder2);
				handler.AppendLiteral("<label>Original Price:</label> <value>");
				handler.AppendFormatted(FormatCurrency(entry.Definition.Price));
				handler.AppendLiteral("</value>");
				stringBuilder17.AppendLine(ref handler);
				stringBuilder.AppendLine("<label>Optimal Price:</label> <value>Calculating...</value>");
				stringBuilder.AppendLine("<label>Price Change:</label> <value>Calculating...</value>");
				currentPriceCalculator = new DelayedPriceCalculator(entry.Definition, list2, num, minPrice, maxPrice, delegate((float bestPrice, float spenderScore) result)
				{
					float item = result.bestPrice;
					string[] array = salesPanel.Content.Split('\n');
					for (int j = 0; j < array.Length; j++)
					{
						if (array[j].Contains("Optimal Price:"))
						{
							array[j] = "<label>Optimal Price:</label> <value>" + FormatCurrency(item) + "</value>";
						}
						else if (array[j].Contains("Price Change:"))
						{
							array[j] = $"<label>Price Change:</label> <value>{(item - entry.Definition.Price) / entry.Definition.Price * 100f:F1}%</value>";
						}
					}
					salesPanel.Content = string.Join("\n", array);
				});
				currentPriceCalculator.Start();
			}
			return stringBuilder.ToString();
		}

		private List<EDay> GetSortedOrderDays(List<EDay> orderDays, EDay currentDay)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			List<EDay> list = new List<EDay>();
			for (int i = 0; i < orderDays.Count; i++)
			{
				list.Add(orderDays[i]);
			}
			list.Sort(delegate(EDay a, EDay b)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Expected I4, but got Unknown
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Expected I4, but got Unknown
				int num = a - currentDay;
				int num2 = b - currentDay;
				if (num < 0)
				{
					num += 7;
				}
				if (num2 < 0)
				{
					num2 += 7;
				}
				return num.CompareTo(num2);
			});
			return list;
		}

		private string FormatCustomerInfo(Customer customer, CustomerData customerData, NPCRelationData relationData, EDay currentDay)
		{
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("<section>Customer Details</section>");
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(36, 1, stringBuilder2);
			handler.AppendLiteral("<label>Name:</label> <value>");
			handler.AppendFormatted(customer.NPC.fullName);
			handler.AppendLiteral("</value>");
			stringBuilder3.AppendLine(ref handler);
			if ((Object)(object)customer.AssignedDealer != (Object)null)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder4 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(48, 2, stringBuilder2);
				handler.AppendLiteral("<label>Assigned Dealer:</label> <value>");
				handler.AppendFormatted(((NPC)customer.AssignedDealer).FirstName);
				handler.AppendLiteral(" ");
				handler.AppendFormatted(((NPC)customer.AssignedDealer).LastName);
				handler.AppendLiteral("</value>");
				stringBuilder4.AppendLine(ref handler);
			}
			stringBuilder.AppendLine();
			List<EDay> orderDays = customerData.GetOrderDays(customer.CurrentAddiction, relationData.RelationDelta / 5f);
			stringBuilder.AppendLine("<section>Financial Information</section>");
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(41, 1, stringBuilder2);
			handler.AppendLiteral("<label>Max Spend:</label> <value>");
			handler.AppendFormatted(FormatCurrency(customerData.MaxWeeklySpend));
			handler.AppendLiteral("</value>");
			stringBuilder5.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(41, 1, stringBuilder2);
			handler.AppendLiteral("<label>Min Spend:</label> <value>");
			handler.AppendFormatted(FormatCurrency(customerData.MinWeeklySpend));
			handler.AppendLiteral("</value>");
			stringBuilder6.AppendLine(ref handler);
			float amount = customerData.GetAdjustedWeeklySpend(relationData.RelationDelta / 5f) * 3f / (float)orderDays.Count;
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder7 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(58, 2, stringBuilder2);
			handler.AppendLiteral("<label>Max Daily Spend:</label> <value>");
			handler.AppendFormatted(FormatCurrency(amount));
			handler.AppendLiteral(" (");
			handler.AppendFormatted(customerData.GetAdjustedWeeklySpend(relationData.RelationDelta / 5f) / customerData.GetAdjustedWeeklySpend(1f) * 100f, "F2");
			handler.AppendLiteral("% of Max)</value>");
			stringBuilder7.AppendLine(ref handler);
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("<section>Schedule Information</section>");
			List<EDay> sortedOrderDays = GetSortedOrderDays(orderDays, currentDay);
			stringBuilder.AppendLine("<label>Next Order Days:</label>");
			for (int i = 0; i < sortedOrderDays.Count; i++)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder8 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(19, 2, stringBuilder2);
				handler.AppendLiteral("<value>  ");
				handler.AppendFormatted(i + 1);
				handler.AppendLiteral(". ");
				handler.AppendFormatted<EDay>(sortedOrderDays[i]);
				handler.AppendLiteral("</value>");
				stringBuilder8.AppendLine(ref handler);
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("<section>Product Preferences</section>");
			var list = CustomerHelper.GetProductsFromCustomer(customer).Select((CustomerHelper.ProductOrders p, int index) => new
			{
				ProductInfo = p,
				Index = index
			}).ToList();
			if (list.Count == 0)
			{
				if ((Object)(object)customer.AssignedDealer == (Object)null)
				{
					stringBuilder.AppendLine("<value>Won't buy anything</value>");
				}
				else
				{
					stringBuilder.AppendLine("<value>Dealer has no appealing products for sale</value>");
				}
			}
			foreach (var item in list)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder9 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(32, 4, stringBuilder2);
				handler.AppendLiteral("<value>");
				handler.AppendFormatted(((ItemDefinition)item.ProductInfo.Product).Name);
				handler.AppendLiteral(" - ");
				handler.AppendFormatted(item.ProductInfo.PaymentQuantity.Payment, "C");
				handler.AppendLiteral(" × ");
				handler.AppendFormatted(item.ProductInfo.PaymentQuantity.Quantity);
				handler.AppendLiteral(" (Appeal: ");
				handler.AppendFormatted(item.ProductInfo.PaymentQuantity.Appeal, "F3");
				handler.AppendLiteral(")</value>");
				stringBuilder9.AppendLine(ref handler);
			}
			stringBuilder.AppendLine();
			return stringBuilder.ToString();
		}

		private void HandlePanelDragging(PanelState panel, Rect dragRect, Event currentEvent)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Invalid comparison between Unknown and I4
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if ((int)currentEvent.type == 0 && ((Rect)(ref dragRect)).Contains(currentEvent.mousePosition))
			{
				panel.IsDragging = true;
				panel.DragOffset = currentEvent.mousePosition - panel.Position;
				currentEvent.Use();
			}
			else if ((int)currentEvent.type == 1)
			{
				panel.IsDragging = false;
			}
			if (panel.IsDragging && (int)currentEvent.type == 3)
			{
				panel.Position = currentEvent.mousePosition - panel.DragOffset;
				currentEvent.Use();
			}
		}

		private void DrawPanel(PanelState panel, float width, float height)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			if (!panel.IsVisible)
			{
				return;
			}
			Rect dragRect = default(Rect);
			((Rect)(ref dragRect))..ctor(panel.Position.x, panel.Position.y, width, 40f);
			HandlePanelDragging(panel, dragRect, Event.current);
			panel.Position.x = Mathf.Clamp(panel.Position.x, 0f, (float)Screen.width - width);
			panel.Position.y = Mathf.Clamp(panel.Position.y, 0f, (float)Screen.height - height);
			GUI.backgroundColor = Color.black;
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, new Color(0.15f, 0.15f, 0.2f, 0.95f));
			val.Apply();
			GUI.DrawTexture(new Rect(panel.Position.x, panel.Position.y, width, height), (Texture)(object)val);
			string[] array = panel.Content.Split('\n');
			float num = panel.Position.y + 40f;
			float num2 = width - 20f;
			panel.ScrollPosition = GUI.BeginScrollView(new Rect(panel.Position.x, num, width, height - 40f), panel.ScrollPosition, new Rect(0f, 0f, num2, (float)(array.Length * 25)));
			num = 0f;
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (text.StartsWith("<section>"))
				{
					string text2 = text.Replace("<section>", "").Replace("</section>", "");
					GUI.Label(new Rect(10f, num, num2, 25f), text2, sectionHeaderStyle);
					num += 30f;
				}
				else if (text.Contains("<label>"))
				{
					string text3 = "";
					string text4 = "";
					int num3 = text.IndexOf("<label>") + 7;
					int num4 = text.IndexOf("</label>");
					if (num3 >= 7 && num4 > num3)
					{
						text3 = text.Substring(num3, num4 - num3);
					}
					int num5 = text.IndexOf("<value>") + 7;
					int num6 = text.IndexOf("</value>");
					if (num5 >= 7 && num6 > num5)
					{
						text4 = text.Substring(num5, num6 - num5);
					}
					if (!string.IsNullOrEmpty(text3))
					{
						GUI.Label(new Rect(10f, num, 140f, 20f), text3, infoLabelStyle);
						if (!string.IsNullOrEmpty(text4))
						{
							GUI.Label(new Rect(160f, num, num2 - 160f, 20f), text4, infoValueStyle);
						}
						num += 25f;
					}
				}
				else if (text.StartsWith("<value>"))
				{
					string text5 = text.Replace("<value>", "").Replace("</value>", "");
					GUI.Label(new Rect(20f, num, num2 - 20f, 20f), text5, infoValueStyle);
					num += 25f;
				}
				else if (!string.IsNullOrWhiteSpace(text))
				{
					GUI.Label(new Rect(10f, num, num2, 20f), text, infoValueStyle);
					num += 25f;
				}
			}
			GUI.EndScrollView();
			GUI.Box(new Rect(panel.Position.x, panel.Position.y, width, 40f), "", salesPanelStyle);
			GUI.Label(new Rect(panel.Position.x, panel.Position.y, width, 40f), panel.Title + " (Drag to Move)", salesHeaderStyle);
			if (GUI.Button(new Rect(panel.Position.x + width - 30f, panel.Position.y + 5f, 25f, 25f), "X"))
			{
				panel.IsVisible = false;
				panel.Position = new Vector2(20f, 20f);
				if (panel == salesPanel)
				{
					SelectedProduct = null;
				}
				else if (panel == contactPanel)
				{
					SelectedCustomer = null;
				}
			}
			Object.Destroy((Object)(object)val);
		}

		public void UpdateSalesInfoPanel(ProductEntry entry, float? overridePrice = null)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (currentPriceCalculator != null)
			{
				currentPriceCalculator.Cancel();
				currentPriceCalculator = null;
			}
			SelectedProduct = entry;
			salesPanel.IsVisible = true;
			salesPanel.ScrollPosition = Vector2.zero;
			salesPanel.Content = FormatSalesInfo(entry, overridePrice);
		}

		public void UpdateContactInfoPanel(Customer customer)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)customer == (Object)null)
			{
				contactPanel.IsVisible = false;
				return;
			}
			EDay currentDay = NetworkSingleton<TimeManager>.Instance.CurrentDay;
			SelectedCustomer = customer;
			contactPanel.IsVisible = true;
			contactPanel.ScrollPosition = Vector2.zero;
			contactPanel.Content = FormatCustomerInfo(customer, customer.customerData, customer.NPC.RelationData, currentDay);
		}

		private void DrawSalesInfoPanel()
		{
			DrawPanel(salesPanel, 400f, 800f);
		}

		private void DrawContactInfoPanel()
		{
			DrawPanel(contactPanel, 400f, 700f);
		}

		public void OnGUI()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			SceneManager.GetActiveScene();
			Scene activeScene = SceneManager.GetActiveScene();
			if (!(((Scene)(ref activeScene)).name == "Main"))
			{
				return;
			}
			Phone instance = PlayerSingleton<Phone>.Instance;
			if (!((Object)(object)instance != (Object)null) || !instance.IsOpen)
			{
				return;
			}
			bool isOpen = PlayerSingleton<HomeScreen>.Instance.isOpen;
			bool flag = (Object)(object)PlayerSingleton<MessagesApp>.Instance != (Object)null && PlayerSingleton<MessagesApp>.Instance.CounterofferInterface.IsOpen;
			if (!isOpen && flag)
			{
				if (Config.CounterOfferDarkModeEnabled.Value)
				{
					GUI.backgroundColor = new Color(0.15f, 0.15f, 0.2f, 0.95f);
					displayTextStyle.normal.textColor = Color.white;
				}
				else
				{
					displayTextStyle.normal.textColor = Color.black;
				}
				GUI.Label(new Rect((float)(Screen.width / 2 - 190), (float)(Screen.height / 2 - 250), 380f, 70f), counterOfferDisplayText, displayTextStyle);
				GUI.backgroundColor = Color.white;
			}
			if ((Object)(object)Core.productManagerApp != (Object)null && ((App<ProductManagerApp>)(object)Core.productManagerApp).isOpen && salesPanel.IsVisible)
			{
				DrawSalesInfoPanel();
			}
			if ((Object)(object)PlayerSingleton<ContactsApp>.Instance != (Object)null && ((App<ContactsApp>)(object)PlayerSingleton<ContactsApp>.Instance).isOpen && contactPanel.IsVisible)
			{
				DrawContactInfoPanel();
			}
		}
	}
}
namespace DealOptimizer_IL2CPP.Services
{
	public static class CustomerHelper
	{
		public class ProductOrders
		{
			public ProductDefinition Product { get; set; }

			public PaymentQuantityResult PaymentQuantity { get; set; }
		}

		public static Customer GetCustomerFromConversation(MSGConversation conversation)
		{
			string contactName = conversation.contactName;
			return Customer.UnlockedCustomers.Find(Predicate<Customer>.op_Implicit((Func<Customer, bool>)((Customer cust) => cust.NPC.fullName == contactName)));
		}

		public static Customer GetCustomerFromMessagesApp(MessagesApp messagesApp)
		{
			return GetCustomerFromConversation(messagesApp.currentConversation);
		}

		public static float GetProductAppeal(ProductDefinition product, Customer customer, float? overridePrice = null)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			float productEnjoyment = customer.GetProductEnjoyment(product, StandardsMethod.GetCorrespondingQuality(customer.customerData.Standards));
			float num = (overridePrice ?? product.Price) / product.MarketValue;
			float num2 = Mathf.Lerp(1f, -1f, num / 2f);
			return productEnjoyment + num2;
		}

		public static PaymentQuantityResult CalculatePaymentQuantity(ProductDefinition product, Customer customer, float? overridePrice = null)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			CustomerData customerData = customer.customerData;
			if ((Object)(object)product == (Object)null)
			{
				return null;
			}
			EQuality correspondingQuality = StandardsMethod.GetCorrespondingQuality(customerData.Standards);
			float num = overridePrice ?? product.Price;
			float productAppeal = GetProductAppeal(product, customer, overridePrice);
			if (productAppeal < 0.05f)
			{
				return new PaymentQuantityResult
				{
					Payment = 0f,
					Quantity = 0,
					Quality = correspondingQuality,
					Appeal = productAppeal
				};
			}
			float productEnjoyment = customer.GetProductEnjoyment(product, correspondingQuality);
			int num2 = 7;
			if ((Object)(object)customer.AssignedDealer == (Object)null)
			{
				num2 = customerData.GetOrderDays(customer.CurrentAddiction, customer.NPC.RelationData.RelationDelta / 5f).Count;
			}
			float num3 = customerData.GetAdjustedWeeklySpend(customer.NPC.RelationData.RelationDelta / 5f) / (float)num2 * Mathf.Lerp(0.66f, 1.5f, productEnjoyment);
			float num4 = num * Mathf.Lerp(0.66f, 1.5f, productEnjoyment);
			int num5 = Mathf.RoundToInt(num3 / num);
			num5 = Mathf.Clamp(num5, 1, 1000);
			if (num5 >= 14)
			{
				num5 = Mathf.RoundToInt((float)(num5 / 5)) * 5;
			}
			float payment = Mathf.RoundToInt(num4 * (float)num5 / 5f) * 5;
			return new PaymentQuantityResult
			{
				Payment = payment,
				Quantity = num5,
				Quality = correspondingQuality,
				Appeal = productAppeal
			};
		}

		public static Customer GetCustomerFromNPC(NPC npc)
		{
			return Customer.UnlockedCustomers.Find(Predicate<Customer>.op_Implicit((Func<Customer, bool>)((Customer cust) => (Object)(object)cust.NPC == (Object)(object)npc)));
		}

		public static IEnumerable<ProductOrders> GetProductsFromCustomer(Customer customer)
		{
			List<ProductOrders> list = new List<ProductOrders>();
			Enumerator<ProductDefinition> enumerator = customer.OrderableProducts.GetEnumerator();
			while (enumerator.MoveNext())
			{
				ProductDefinition current = enumerator.Current;
				if (!(CalculatePaymentQuantity(current, customer).Appeal < 0.05f))
				{
					list.Add(new ProductOrders
					{
						Product = current,
						PaymentQuantity = CalculatePaymentQuantity(current, customer)
					});
				}
			}
			list.Sort((ProductOrders a, ProductOrders b) => b.PaymentQuantity.Appeal.CompareTo(a.PaymentQuantity.Appeal));
			return list.Take(4);
		}
	}
	public class ProductPackage<T>
	{
		public int PackageSize { get; }

		public T Slot { get; }

		public int AvailableQuantity { get; }

		public EQuality Quality { get; }

		public int TotalUnits => PackageSize * AvailableQuantity;

		public ProductPackage(int packageSize, T slot, int quantity, EQuality quality)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			PackageSize = packageSize;
			Slot = slot;
			AvailableQuantity = quantity;
			Quality = quality;
		}
	}
	[HarmonyPatch(typeof(Customer), "HandoverChosen")]
	public static class HandoverService
	{
		public static bool Prefix(Customer __instance)
		{
			return doDeal(__instance);
		}

		private static bool doDeal(Customer customer)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.AutoHandoverEnabled.Value)
			{
				return true;
			}
			Contract currentContract = customer.CurrentContract;
			object obj;
			if (currentContract == null)
			{
				obj = null;
			}
			else
			{
				ProductList productList = currentContract.ProductList;
				obj = ((productList != null) ? productList.entries : null);
			}
			if (obj == null || customer.CurrentContract.ProductList.entries.Count == 0)
			{
				return true;
			}
			Melon<Core>.Logger.Msg("Customer: " + customer.NPC.fullName);
			Entry obj2 = customer.CurrentContract.ProductList.entries[0];
			string productID = obj2.ProductID;
			int quantity = obj2.Quantity;
			if (quantity <= 0)
			{
				return true;
			}
			EQuality minQuality = StandardsMethod.GetCorrespondingQuality(customer.CustomerData.Standards);
			List<ProductPackage<ItemSlot>> list = new List<ProductPackage<ItemSlot>>();
			foreach (ItemSlot item in (Il2CppArrayBase<ItemSlot>)(object)Player.Local.Inventory)
			{
				ItemInstance itemInstance = item.ItemInstance;
				if (itemInstance == null)
				{
					continue;
				}
				Melon<Core>.Logger.Msg($"Item: {itemInstance.ID} - {itemInstance.Quantity} - {itemInstance.Definition.Category}");
				if (itemInstance != null && itemInstance.ID == productID && itemInstance.Quantity > 0)
				{
					ProductItemInstance val = ((Il2CppObjectBase)itemInstance).TryCast<ProductItemInstance>();
					if (val != null && (Object)(object)val.packaging != (Object)null && ((QualityItemInstance)val).Quality >= minQuality)
					{
						Melon<Core>.Logger.Msg($"ProductItem: {itemInstance.ID} - {itemInstance.Quantity} - {((ItemDefinition)val.