Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,7 @@ private void InitRelayManager()
_builder.RegisterType<ReprocessSessionMember>();
_builder.RegisterType<ReprocessSession>();

_builder.RegisterType<ProductionCostReader>().As<IProductionCostReader>();
_builder.RegisterType<ProductionDataAccess>().OnActivated(e =>
{
e.Instance.Init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,8 @@ private int GetStandingPoints(Character character)
//Overload method for price/sec
public virtual double GetPricePerSecond(int targetDefinition)
{
var mod = Math.Max(1, ProductionDataAccess.GetProductionPriceModifier(targetDefinition));
mod = Math.Min(10, mod);
return GetPricePerSecond() * mod;
var mod = ProductionDataAccess.GetProductionPriceModifier(targetDefinition);
return GetPricePerSecond() * mod.Clamp(1, 10);
}

public virtual double GetPricePerSecond()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ public interface IProductionDataAccess
IDictionary<int, ItemResearchLevel> ResearchLevels { get; }
ILookup<int, ProductionComponent> ProductionComponents { get; }
IDictionary<CategoryFlags, double> ProductionDurations { get; }
IDictionary<CategoryFlags, ProductionCost> ProductionCostByCategory { get; }
IDictionary<int, ProductionCost> ProductionCostByTechLevel { get; }
IDictionary<int, double> ProductionCost { get; }
IDictionary<int, CalibrationDefault> CalibrationDefaults { get; }

ProductionDecalibration GetDecalibration(int targetDefinition);
Expand Down
66 changes: 64 additions & 2 deletions src/Perpetuum/Services/ProductionEngine/ProductionCost.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@

using System.Collections.Generic;
using System.Linq;
using Perpetuum.Data;
using Perpetuum.EntityFramework;
using Perpetuum.ExportedTypes;

namespace Perpetuum.Services.ProductionEngine
{
public class ProductionCost
Expand All @@ -8,4 +13,61 @@ public class ProductionCost
public int? tierLevel;
public double costModifier;
}
}

public interface IProductionCostReader
{
IEnumerable<ProductionCost> ProductionCost { get; }
ProductionCost GetProductionCostByED(EntityDefault ed);
double GetProductionCostModByED(EntityDefault ed);
}

public class ProductionCostReader : IProductionCostReader
{
private const double MIN = 1.0;
private const double MAX = 10.0;

public IEnumerable<ProductionCost> ProductionCost
{
get { return _costTable.Values; }
}
private readonly IDictionary<int, ProductionCost> _costTable;
public ProductionCostReader()
{
_costTable = Database.CreateCache<int, ProductionCost>("productioncost", "id", r =>
{
var cost = new ProductionCost
{
categoryFlag = r.GetValue<long?>(k.category),
tierType = r.GetValue<int?>(k.tierType),
tierLevel = r.GetValue<int?>(k.tierLevel),
costModifier = r.GetValue<double>("costmodifier")
};
return cost;
});
}

/// <summary>
/// Map an EntityDefault to a ProductionCost based on matching CategoryFlags, tierType, tierLevel.
/// Tiebreaker logic is weighted such that a match on Category > TierLevel > TierType
/// And where a match on TierLevel and Type will not outweigh Category
/// </summary>
/// <param name="ed">EntityDefault</param>
/// <returns>ProductionCost</returns>
public ProductionCost GetProductionCostByED(EntityDefault ed)
{
var matchScores = ProductionCost.GroupBy(c =>
(((CategoryFlags)(c.categoryFlag ?? 0) == ed.CategoryFlags) ? 5 : 0) +
(((TierType)(c.tierType ?? 0) == ed.Tier.type) ? 1 : 0) +
(((c.tierLevel ?? 0) == ed.Tier.level) ? 3 : 0));

var bestMatchScore = matchScores.Max(x => x.Key);
return matchScores.FirstOrDefault(x => x.Key == bestMatchScore).Select(g => g).FirstOrDefault();
}

public double GetProductionCostModByED(EntityDefault ed)
{
var prodCost = GetProductionCostByED(ed) ?? (new ProductionCost { costModifier = MIN });
return prodCost.costModifier.Clamp(MIN, MAX);
}
}
}
52 changes: 8 additions & 44 deletions src/Perpetuum/Services/ProductionEngine/ProductionDataAccess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ public class ProductionDataAccess : IProductionDataAccess
private IDictionary<int, ItemResearchLevel> _researchlevels;
private ILookup<int, ProductionComponent> _productionComponents;
private IDictionary<CategoryFlags, double> _productionDurations;
private IDictionary<CategoryFlags, ProductionCost> _productionCostByCategory;
private IDictionary<int, ProductionCost> _productionCostByTechLevel;
private IDictionary<int, CalibrationDefault> _calibrationDefaults;
private IDictionary<CategoryFlags, ProductionDecalibration> _productionDecalibrations;
private IProductionCostReader _productionCostReader;

public ProductionDataAccess(IEntityDefaultReader entityDefaultReader)
public ProductionDataAccess(IEntityDefaultReader entityDefaultReader, IProductionCostReader costReader)
{
_entityDefaultReader = entityDefaultReader;
_productionCostReader = costReader;
}

public void Init()
Expand Down Expand Up @@ -68,46 +68,11 @@ public void Init()
return level;
}, ItemResearchLevelFilter);

_productionCostByCategory = Database.CreateCache<CategoryFlags, ProductionCost>("productioncost", k.category, r =>
ProductionCost = new Dictionary<int, double>();
foreach (var ed in EntityDefault.All)
{
var cost = new ProductionCost
{
categoryFlag = r.GetValue<long?>(k.category),
tierType = r.GetValue<int?>(k.tierType),
tierLevel = r.GetValue<int?>(k.tierLevel),
costModifier = r.GetValue<double>("costmodifier")
};
return cost;
}, ProductionCostCategoryFilter);

_productionCostByTechLevel = Database.CreateCache<int, ProductionCost>("productioncost", k.tierLevel, r =>
{
var cost = new ProductionCost
{
categoryFlag = r.GetValue<long?>(k.category),
tierType = r.GetValue<int?>(k.tierType),
tierLevel = r.GetValue<int?>(k.tierLevel),
costModifier = r.GetValue<double>("costmodifier")
};
return cost;
}, ProductionCostTechFilter);
}

public bool ProductionCostCategoryFilter(IDataRecord record)
{
long? categoryFlag = record.GetValue<long?>(k.category);
if (categoryFlag == null)
return false;
CategoryFlags flag = (CategoryFlags)categoryFlag;
return flag.IsCategoryExists();
}

public bool ProductionCostTechFilter(IDataRecord record)
{
int? level = record.GetValue<int?>(k.tierLevel);
if (level == null)
return false;
return level > 0;
ProductionCost.Add(ed.Definition, _productionCostReader.GetProductionCostModByED(ed));
}
}

public bool ItemResearchLevelFilter(IDataRecord record)
Expand Down Expand Up @@ -135,9 +100,8 @@ public bool ItemResearchLevelFilter(IDataRecord record)
public IDictionary<int, ItemResearchLevel> ResearchLevels => _researchlevels;
public ILookup<int, ProductionComponent> ProductionComponents => _productionComponents;
public IDictionary<CategoryFlags, double> ProductionDurations => _productionDurations;
public IDictionary<CategoryFlags, ProductionCost> ProductionCostByCategory => _productionCostByCategory;
public IDictionary<int, ProductionCost> ProductionCostByTechLevel => _productionCostByTechLevel;
public IDictionary<int, CalibrationDefault> CalibrationDefaults => _calibrationDefaults;
public IDictionary<int, double> ProductionCost { get; private set; }

public ProductionDecalibration GetDecalibration(int targetDefinition)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,25 @@ public static double GetProductionDuration(this IProductionDataAccess dataAccess
return 1.0;
}

/// <summary>
/// Applies EntityDefault specific cost modifiers based on tech level/type and category
/// </summary>
/// <param name="dataAccess"></param>
/// <param name="targetDefinition"></param>
/// <returns>factor to multiply cost</returns>
public static double GetProductionPriceModifier(this IProductionDataAccess dataAccess, int targetDefinition)
{
var modifier = 1.0;
if (!EntityDefault.TryGet(targetDefinition, out EntityDefault ed))
{
Logger.Error("definition was not found: " + targetDefinition);
return 1.0;
return modifier;
}

var modifier = 1.0;

if (dataAccess.ProductionCostByCategory.TryGetValue(ed.CategoryFlags, out ProductionCost costByCat))
if (dataAccess.ProductionCost.TryGetValue(ed.Definition, out double value))
{
modifier = costByCat.costModifier;
modifier = value;
}
else if (dataAccess.ProductionCostByTechLevel.TryGetValue(ed.Tier.level, out ProductionCost costByLevel))
{
modifier = costByLevel.costModifier;
}

return modifier;
}

Expand Down