-
Notifications
You must be signed in to change notification settings - Fork 173
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
538 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
namespace EDEngineer.Models | ||
{ | ||
public class MaterialTrade | ||
{ | ||
public MaterialTrade(Entry traded, Entry needed, int tradedNeeded, int missing, bool willBeEnough, int alreadyNeeded) | ||
{ | ||
Traded = traded; | ||
Needed = needed; | ||
TradedNeeded = tradedNeeded; | ||
Missing = missing; | ||
WillBeEnough = willBeEnough; | ||
AlreadyNeeded = alreadyNeeded; | ||
} | ||
|
||
public Entry Traded { get; } | ||
public Entry Needed { get; } | ||
public int TradedNeeded { get; } | ||
public int Missing { get; } | ||
public bool WillBeEnough { get; } | ||
public int AlreadyNeeded { get; } | ||
|
||
public decimal? Consumption => Traded.Count == AlreadyNeeded ? (decimal?) null : (TradedNeeded / (decimal) (Traded.Count - AlreadyNeeded)) * 100m; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using EDEngineer.Models.State; | ||
using EDEngineer.Models.Utils; | ||
|
||
namespace EDEngineer.Models | ||
{ | ||
public static class MaterialTrader | ||
{ | ||
public static IEnumerable<MaterialTrade> FindPossibleTrades(StateCargo cargo, Dictionary<Entry, int> missingIngredients, Dictionary<EntryData, int> deduced) | ||
{ | ||
var ingredients = cargo.Ingredients.Values | ||
.Where(i => i.Count > 0 && | ||
i.Data.Group.HasValue && | ||
i.Data.Rarity.Rank() != null && | ||
!missingIngredients.ContainsKey(i)).ToList(); | ||
|
||
var allTrades = AllTrades(missingIngredients, ingredients, deduced).ToList(); | ||
|
||
var coveredTrades = allTrades.Where(trade => trade.WillBeEnough).OrderBy(trade => trade.TradedNeeded).ToList(); | ||
var incompleteTrades = allTrades.Where(trade => !trade.WillBeEnough).OrderBy(trade => trade.TradedNeeded).ToList(); | ||
|
||
var coveredIngredients = new HashSet<EntryData>(); | ||
foreach (var currentTrade in coveredTrades) | ||
{ | ||
if (currentTrade.Traded.Count - currentTrade.TradedNeeded - deduced.GetOrDefault(currentTrade.Traded.Data) < 0) | ||
{ | ||
continue; | ||
} | ||
|
||
coveredIngredients.Add(currentTrade.Needed.Data); | ||
|
||
if (deduced.ContainsKey(currentTrade.Traded.Data)) | ||
{ | ||
deduced[currentTrade.Traded.Data] += currentTrade.TradedNeeded; | ||
} | ||
else | ||
{ | ||
deduced[currentTrade.Traded.Data] = currentTrade.TradedNeeded; | ||
} | ||
|
||
yield return currentTrade; | ||
} | ||
|
||
foreach (var currentTrade in incompleteTrades) | ||
{ | ||
if (coveredIngredients.Contains(currentTrade.Needed.Data)) | ||
{ | ||
continue; | ||
} | ||
|
||
if (deduced.ContainsKey(currentTrade.Traded.Data)) | ||
{ | ||
deduced[currentTrade.Traded.Data] += currentTrade.TradedNeeded; | ||
} | ||
else | ||
{ | ||
deduced[currentTrade.Traded.Data] = currentTrade.TradedNeeded; | ||
} | ||
|
||
yield return currentTrade; | ||
} | ||
} | ||
|
||
private static IEnumerable<MaterialTrade> AllTrades(Dictionary<Entry, int> missingIngredients, | ||
List<Entry> ingredients, Dictionary<EntryData, int> deduced) | ||
{ | ||
foreach (var missingIngredient in missingIngredients) | ||
{ | ||
var ingredient = missingIngredient.Key; | ||
var missingSize = missingIngredient.Value; | ||
|
||
if (missingSize <= 0 || | ||
!ingredient.Data.Group.HasValue || | ||
ingredient.Data.Group.In(Group.Thargoid, Group.Guardian, Group.Commodities) || | ||
!ingredient.Data.Rarity.Rank().HasValue) | ||
{ | ||
continue; | ||
} | ||
|
||
var group = ingredient.Data.Group.Value; | ||
// ReSharper disable PossibleInvalidOperationException | ||
var targetRank = ingredient.Data.Rarity.Rank().Value; | ||
|
||
// find same group ingredients | ||
var sameGroupIngredients = ingredients.Where(i => i.Data.Group == group).ToList(); | ||
foreach (var sameGroup in sameGroupIngredients) | ||
{ | ||
var sourceRank = sameGroup.Data.Rarity.Rank().Value; | ||
var rankDifference = sourceRank - targetRank; | ||
int needed; | ||
if (rankDifference > 0) | ||
{ | ||
needed = (int) Math.Ceiling(missingSize / Math.Pow(3, rankDifference)); | ||
} | ||
else | ||
{ | ||
needed = (int) (Math.Pow(6, Math.Abs(rankDifference)) * missingSize); | ||
} | ||
|
||
var willBeEnough = needed + deduced.GetOrDefault(sameGroup.Data) <= sameGroup.Count; | ||
yield return new MaterialTrade(sameGroup, ingredient, needed, missingSize, willBeEnough, deduced.GetOrDefault(sameGroup.Data)); | ||
} | ||
|
||
// find other group ingredients | ||
var differentGroupIngredients = ingredients.Where(i => i.Data.Group != group && i.Data.Kind == ingredient.Data.Kind && i.Data.Subkind == ingredient.Data.Subkind).ToList(); | ||
foreach (var otherGroup in differentGroupIngredients) | ||
{ | ||
var sourceRank = otherGroup.Data.Rarity.Rank().Value; | ||
var rankDifference = sourceRank - targetRank; | ||
int needed; | ||
if (rankDifference > 0) | ||
{ | ||
needed = (int)(2 * missingSize * Math.Pow(3, rankDifference)); | ||
} | ||
else if (rankDifference == 0) | ||
{ | ||
needed = 6 * missingSize; | ||
} | ||
else | ||
{ | ||
continue; | ||
} | ||
|
||
var willBeEnough = needed + deduced.GetOrDefault(otherGroup.Data) <= otherGroup.Count; | ||
yield return new MaterialTrade(otherGroup, ingredient, needed, missingSize, willBeEnough, deduced.GetOrDefault(otherGroup.Data)); | ||
} | ||
// ReSharper restore PossibleInvalidOperationException | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using EDEngineer.Models; | ||
using EDEngineer.Models.State; | ||
using EDEngineer.Utils.System; | ||
using Moq; | ||
using Newtonsoft.Json; | ||
using NFluent; | ||
using NUnit.Framework; | ||
|
||
namespace EDEngineer.Tests | ||
{ | ||
[TestFixture] | ||
public class MaterialTraderTests | ||
{ | ||
private StateCargo cargo; | ||
private List<EntryData> entries; | ||
|
||
[SetUp] | ||
public void Setup() | ||
{ | ||
entries = JsonConvert.DeserializeObject<List<EntryData>>(IOUtils.GetEntryDatasJson()); | ||
cargo = new StateCargo(entries, Mock.Of<ILanguage>(), StateCargo.COUNT_COMPARER); | ||
} | ||
|
||
[TestCase(1, 6)] | ||
[TestCase(2, 36)] | ||
[TestCase(3, 216)] | ||
[TestCase(4, 1296)] | ||
public void Simple_upgrade_trade(int rank, int expected) | ||
{ | ||
var group = Group.Alloys; | ||
var alloys = entries.Where(e => e.Group == group) | ||
.OrderBy(e => e.Rarity) | ||
.ToList(); | ||
|
||
var firstGrade = alloys[0]; | ||
var secondGrade = new Entry(alloys[rank]); | ||
|
||
cargo.IncrementCargo(firstGrade.Name, expected * 2); | ||
|
||
var missingIngredients = new Dictionary<Entry, int> | ||
{ | ||
[secondGrade] = 1 | ||
}; | ||
|
||
var trades = MaterialTrader.FindPossibleTrades(cargo, missingIngredients, new Dictionary<EntryData, int>()).ToList(); | ||
|
||
Check.That(trades.Count).IsEqualTo(1); | ||
|
||
var trade = trades[0]; | ||
|
||
Check.That(trade.Traded.Data).IsEqualTo(firstGrade); | ||
Check.That(trade.TradedNeeded).IsEqualTo(expected); | ||
} | ||
|
||
[TestCase(1, 3)] | ||
[TestCase(2, 9)] | ||
[TestCase(3, 27)] | ||
[TestCase(4, 81)] | ||
public void Simple_downgrade_trade(int rank, int expected) | ||
{ | ||
var group = Group.Alloys; | ||
var alloys = entries.Where(e => e.Group == group) | ||
.OrderBy(e => e.Rarity) | ||
.ToList(); | ||
|
||
var firstGrade = alloys[rank]; | ||
var secondGrade = new Entry(alloys[0]); | ||
|
||
cargo.IncrementCargo(firstGrade.Name, expected * 2); | ||
|
||
var missingIngredients = new Dictionary<Entry, int> | ||
{ | ||
[secondGrade] = 1 | ||
}; | ||
|
||
var trades = MaterialTrader.FindPossibleTrades(cargo, missingIngredients, new Dictionary<EntryData, int>()).ToList(); | ||
|
||
Check.That(trades.Count).IsEqualTo(1); | ||
|
||
var trade = trades[0]; | ||
|
||
Check.That(trade.Traded.Data).IsEqualTo(firstGrade); | ||
Check.That(trade.TradedNeeded).IsEqualTo(expected); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.