public Contract(long ownerID, short statusID) { _ownerID = ownerID; _statusID = statusID; _pickupStationID = 0; _destinationStationID = 0; _collateral = 0; _reward = 0; _expectedProfit = 0; _totalVolume = 0; _issueDate = DateTime.Now; _items = new ContractItemList(); _type = ContractType.Courier; }
public Contract(long ownerID, short statusID, long pickupStationID, long destinationStationID, decimal collateral, decimal reward, decimal expectedProfit, DateTime issueDate, ContractItemList items, ContractType type) { _ownerID = ownerID; _statusID = statusID; _pickupStationID = pickupStationID; _destinationStationID = destinationStationID; _collateral = collateral; _reward = reward; _expectedProfit = expectedProfit; _issueDate = issueDate; _items = items; _type = type; }
public static ContractItemList GetContractItems(Contract contract) { ContractItemList retVal = new ContractItemList(); EMMADataSet.ContractItemDataTable table = new EMMADataSet.ContractItemDataTable(); contractItemsTableAdapter.FillByContractID(table, contract.ID); foreach (EMMADataSet.ContractItemRow item in table) { retVal.Add(new ContractItem(item, contract)); } return retVal; }
public ContractList GenerateContracts(long ownerID, long pickupStation, long destinationStation, bool autoCon) { ContractList retVal = new ContractList(); ContractItemList items = new ContractItemList(); Dictionary<int, long> assetsUsed = new Dictionary<int, long>(); decimal totVolume = 0, totCollateral = 0, totProfit = 0; ReportGroupSettings settings = UserAccount.CurrentGroup.Settings; decimal maxVolume = settings.AutoCon_MaxVolume; decimal maxCollateral = settings.AutoCon_MaxCollateral; bool allowStackSpliting = settings.AutoCon_AllowStackSplitting; string collateralBasedOn = settings.CollateralBasedOn; decimal collateralPerc = settings.CollateralPercentage; string rewardBasedOn = settings.RewardBasedOn; decimal minReward = settings.MinReward; decimal minRewardPerc = settings.MinRewardPercentage; decimal minAllowedCollateral = settings.AutoCon_MinCollateral; decimal minAllowedReward = settings.AutoCon_MinReward; decimal minAllowedVolume = settings.AutoCon_MinVolume; decimal maxReward = settings.MaxReward; decimal maxRewardPerc = settings.MaxRewardPercentage; decimal lowSecRewardBonus = settings.LowSecPickupBonusPerc; decimal rewardPerJump = settings.RewardPercPerJump; decimal rewardPerVol = settings.VolumeBasedRewardPerc; decimal flatRewardPerJump = settings.RewardPerJump; decimal flatRewardPerVol = settings.RewardPerVolume; decimal baseReward = settings.PickupReward; EveDataSet.mapSolarSystemsRow pickupSystemData = SolarSystems.GetSystem( Stations.GetStation(pickupStation).solarSystemID); int diag_contracts = 0; //bool corp = false; bool complete = true; bool relax = false; //APICharacter character = UserAccount.CurrentGroup.GetCharacter(ownerID, ref corp); // Get the list of assets available for auto-contracting at this station. Diagnostics.StartTimer("GenerateContract"); Diagnostics.StartTimer("GenerateContract.Part1"); EMMADataSet.AssetsDataTable assets = Assets.GetAutoConAssets( ownerID, pickupStation, true); Diagnostics.StopTimer("GenerateContract.Part1"); int lastAssetCount = -1; // Had to remove this condition. // Consider the case where 9 mil units of trit are sat at a station. // Max volume limit is set to 30k m3 so the autocontractor wants to create // 3 contracts for 3 mil units each. // However, this condition will cause the system to drop into the infinite loop // diagnostics after the first contract. while (assets.Count > 0) // && lastAssetCount != assets.Count) { complete = true; relax = false; totVolume = 0; totProfit = 0; totCollateral = 0; assetsUsed = new Dictionary<int, long>(); items = new ContractItemList(); Contract contract = new Contract(ownerID, 5, pickupStation, destinationStation, 0, 0, 0, DateTime.UtcNow, new ContractItemList(), ContractType.Courier); lastAssetCount = assets.Count; foreach (EMMADataSet.AssetsRow asset in assets) { decimal buyPrice = 0, sellPrice = 0, unitCollateral = 0; int itemID = asset.ItemID; decimal itemVolume = (decimal)Items.GetItemVolume(itemID); long quantity = asset.Quantity; // Check if we can use the full volume of these items without breaching the max volume // limit. if (autoCon && totVolume + (decimal)(quantity * itemVolume) > maxVolume && totVolume < maxVolume) { // Reduce the quantity of items being addded if they would exceed the // volume limit quantity = (int)Math.Round((maxVolume - totVolume) / (decimal)itemVolume, 0, MidpointRounding.AwayFromZero) - 1; // This check will prevent infinite loops when the volume of a single item is greater // than the max allowed contract volume. if (maxVolume < itemVolume && totVolume == 0) { relax = true; quantity = 1; } complete = false; } else if (totVolume >= maxVolume) { complete = false; } Diagnostics.StartTimer("GenerateContract.Part2"); // Get estimated sell price for the items being added to the contract. sellPrice = GetSellPrice(itemID, destinationStation); Diagnostics.StopTimer("GenerateContract.Part2"); Diagnostics.StartTimer("GenerateContract.Part6"); // Get average buy price for the items being added to the contract. buyPrice = GetBuyPrice(ownerID, itemID, pickupStation, quantity, asset.Quantity - quantity); Diagnostics.StopTimer("GenerateContract.Part6"); Diagnostics.StartTimer("GenerateContract.Part3"); // calculate the collateral value of the items being added. unitCollateral = CalcCollateral(collateralBasedOn, collateralPerc, buyPrice, sellPrice); long lastQuantity = quantity; while (autoCon && totCollateral + (unitCollateral * quantity) > maxCollateral && !relax && totCollateral < maxCollateral) { // Reduce the quantity of items being addded if they would exceed the // collateral limit quantity = (int)Math.Round((maxCollateral - totCollateral) / (decimal)unitCollateral, MidpointRounding.AwayFromZero) - 1; // This check will prevent infinite loops when the collateral for a single item is greater // than the max allowed collateral. if (maxCollateral < unitCollateral && totCollateral == 0) { relax = true; quantity = 1; } complete = false; // Catch a possible infinite loop. if (lastQuantity == quantity) { relax = true; quantity = 1; } lastQuantity = quantity; // Recalculate buy price and collateral. //buyPrice = GetBuyPrice(ownerID, itemID, pickupStation, quantity, asset.Quantity - quantity); //unitCollateral = CalcCollateral(collateralBasedOn, collateralPerc, buyPrice, sellPrice); } if (totCollateral >= maxCollateral) { complete = false; } Diagnostics.StopTimer("GenerateContract.Part3"); if ((quantity == asset.Quantity || allowStackSpliting || relax) && quantity > 0) { // Get up the values for the items being added and add them to the contract totals. totVolume += (decimal)(quantity * itemVolume); totCollateral += quantity * unitCollateral; totProfit += quantity * sellPrice - quantity * buyPrice; if (assetsUsed.ContainsKey(itemID)) { // If we've already added an item with this id then just add the new quantity // to the old contract item object... assetsUsed[itemID] += quantity; for (int i = 0; i < items.Count;i++ ) { ContractItem itemData = items[i]; if (itemData.ItemID == itemID) { itemData.Quantity += (int)quantity; i = items.Count; } } } else { // ...Otherwise create a new contract item and add it to the list. assetsUsed.Add(itemID, quantity); items.Add(new ContractItem(itemID, (int)quantity, sellPrice, buyPrice, contract)); } } } Diagnostics.StartTimer("GenerateContract.Part4"); // Get the distance between the pickup and destination stations int numJumps = SolarSystemDistances.GetDistanceBetweenStations(pickupStation, destinationStation); Diagnostics.StopTimer("GenerateContract.Part4"); // Calculate the reward that will be given from completing the contract. decimal reward = CalcReward(rewardBasedOn, totCollateral, totProfit, minReward, maxReward, minRewardPerc, maxRewardPerc, rewardPerJump, rewardPerVol, lowSecRewardBonus, numJumps, totVolume, Stations.IsLowSec(pickupStation), flatRewardPerJump, flatRewardPerVol, baseReward); contract.Items = items; contract.Reward = reward; contract.Collateral = totCollateral; contract.ExpectedProfit = totProfit; diag_contracts++; // Add the contract to the list if (!autoCon || (reward > minAllowedReward && totCollateral > minAllowedCollateral && totVolume > minAllowedVolume)) { retVal.Add(contract); } //else //{ // UpdateStatus(0, 0, "", // "A contract (" + diag_contracts + ") has been generated that does not meet the minimum " + // "requirements." + // (reward <= minAllowedReward ? " The reward (" + reward + ") is less than " + // minAllowedReward + "." : "") + // (totCollateral <= minAllowedCollateral ? " The collateral (" + totCollateral + // ") is less than " + minAllowedCollateral + "." : "") + // (totVolume <= minAllowedVolume ? " The volume (" + totVolume + ") is less than " + // minAllowedVolume + "." : ""), // false); //} Diagnostics.StartTimer("GenerateContract.Part5"); if (!complete) { // If we have not used all items at this location then // remove the items we have used from the list of current assets. Dictionary<int, long>.Enumerator enumerator = assetsUsed.GetEnumerator(); while (enumerator.MoveNext()) { DataRow[] rows = assets.Select("ItemID = " + enumerator.Current.Key); if (rows.Length > 0) { long q_remain = enumerator.Current.Value; for (int i = 0; i < rows.Length; i++) { if (q_remain > 0) { EMMADataSet.AssetsRow assetData = rows[i] as EMMADataSet.AssetsRow; long diff = q_remain - assetData.Quantity; if (diff >= 0) { q_remain -= assetData.Quantity; assets.RemoveAssetsRow(assetData); } else { assetData.Quantity -= (int)q_remain; q_remain = 0; } } } } } } else { // otherwise, just clear the list of assets. assets.Clear(); } Diagnostics.StopTimer("GenerateContract.Part5"); } #region Diagnostic dump if we've caught an infinite loop. if (assets.Count != 0) { UpdateStatus(0, 0, "Error: Infinite loop detected", "Please send your 'logging/exceptionlog.txt' file to [email protected]. " + "Warning, this file will contain information about your in-game assets.", true); StringBuilder errorText = new StringBuilder( "Infinite loop detected during auto-contrator execution, diagnostics to follow:"); errorText.Append("\r\n\t"); errorText.Append("Assets Remaining:"); foreach (EMMADataSet.AssetsRow asset in assets) { errorText.Append("\r\n\t\t"); errorText.Append(Items.GetItemName(asset.ItemID).Replace(",", " ")); errorText.Append(","); errorText.Append(asset.Quantity); errorText.Append(","); errorText.Append(Items.GetItemVolume(asset.ItemID)); } errorText.Append("\r\n\t"); errorText.Append("Contracts created:"); if (retVal.Count == 0) { errorText.Append("\r\n\t\t"); errorText.Append("NONE"); } foreach (Contract contract in retVal) { errorText.Append("\r\n\t\t"); errorText.Append("ID: "); errorText.Append(contract.ID); errorText.Append("\r\n\t\t\t"); errorText.Append("Collateral: "); errorText.Append(contract.Collateral); errorText.Append("\r\n\t\t\t"); errorText.Append("Reward: "); errorText.Append(contract.Reward); errorText.Append("\r\n\t\t\t"); errorText.Append("Total Volume: "); errorText.Append(contract.TotalVolume); errorText.Append("\r\n\t\t\t"); errorText.Append("Profit: "); errorText.Append(contract.ExpectedProfit); errorText.Append("\r\n\t\t\t"); errorText.Append("Contract Items:"); foreach (ContractItem item in contract.Items) { errorText.Append("\r\n\t\t\t\t"); errorText.Append(item.Item); errorText.Append(","); errorText.Append(item.Quantity); errorText.Append(","); errorText.Append(item.ItemVolume); } } errorText.Append("\r\n\t"); errorText.Append("Max Volume: "); errorText.Append(maxVolume); errorText.Append("\r\n\t"); errorText.Append("Max Collateral: "); errorText.Append(maxCollateral); errorText.Append("\r\n\t"); errorText.Append("Max Reward: "); errorText.Append(maxReward); errorText.Append("\r\n\t"); errorText.Append("Max Reward Percentage: "); errorText.Append(maxRewardPerc); errorText.Append("\r\n\t"); errorText.Append("Min Allowed Collateral: "); errorText.Append(minAllowedCollateral); errorText.Append("\r\n\t"); errorText.Append("Min Allowed Reward: "); errorText.Append(minAllowedReward); errorText.Append("\r\n\t"); errorText.Append("Min Allowed Volume: "); errorText.Append(minAllowedVolume); errorText.Append("\r\n\t"); errorText.Append("Min Reward: "); errorText.Append(minReward); errorText.Append("\r\n\t"); errorText.Append("Min Reward Percentage: "); errorText.Append(minRewardPerc); errorText.Append("\r\n\t"); errorText.Append("Allow stack splitting: "); errorText.Append(allowStackSpliting); throw new EMMAException(ExceptionSeverity.Error, errorText.ToString()); } #endregion DiagnosticUpdate("", "Complete time: " + Diagnostics.GetRunningTime("GenerateContract").ToString()); DiagnosticUpdate("", "Time loading assets: " + Diagnostics.GetRunningTime("GenerateContract.Part1").ToString()); DiagnosticUpdate("", "Get item sell prices: " + Diagnostics.GetRunningTime("GenerateContract.Part2").ToString()); DiagnosticUpdate("", "Get item buy prices: " + Diagnostics.GetRunningTime("GenerateContract.Part6").ToString()); DiagnosticUpdate("", "Calc and restrict collateral: " + Diagnostics.GetRunningTime("GenerateContract.Part3").ToString()); DiagnosticUpdate("", "Get route length: " + Diagnostics.GetRunningTime("GenerateContract.Part4").ToString()); DiagnosticUpdate("", "Remove used assets: " + Diagnostics.GetRunningTime("GenerateContract.Part5").ToString()); DiagnosticUpdate("", "Total contracts generated: " + diag_contracts); return retVal; }