public double ComputeErrorAgainstSeed(Utilities.LoggingCallback logger = null) { var error = 0.0; { var err = BlockSetInfo.TotalRawResources; logger?.Invoke("Raw resources {0:e}. Err {1:e}", BlockSetInfo.TotalRawResources, err); error += err; } // Block counts { var countCopy = new Dictionary <SupportedBlockTypes, int>(SupportedBlockTypesEquality.Instance); foreach (var kv in Seed.BlockCountRequirements) { countCopy[kv.Key] = 0; } foreach (var kv in BlockSetInfo.BlockCountByType) { var def = MyDefinitionManager.Static.GetCubeBlockDefinition(kv.Key); foreach (var kt in Seed.BlockCountRequirements) { if (kt.Key.IsOfType(def)) { countCopy.AddValue(kt.Key, kv.Value); } } } foreach (var kv in countCopy) { var target = Seed.BlockCountRequirement(kv.Key); var err = ErrorFunction(target.Count, kv.Value, 1e5, 0.1) * target.Multiplier; logger?.Invoke("Block {0} count current {1:e} vs {2:e}. Err {3:e}", kv.Key, kv.Value, target.Count, err); error += err; } } var powerReq = new ProceduralConstructionSeed.TradeRequirements(0, 0); foreach (var kv in Seed.ProductionStorage) { var id = kv.Key; var req = kv.Value; if (id == MyResourceDistributorComponent.ElectricityId) { powerReq = req; continue; } if (id.TypeId == typeof(MyObjectBuilder_GasProperties)) { var storageCurrent = BlockSetInfo.TotalGasStorage(id); var ce = ErrorFunction(req.Storage, storageCurrent, 10, 1e-5) * req.StorageErrorMultiplier; logger?.Invoke("Gas {0} storage current {1:e} vs {2:e}. Err {3:e}", id.SubtypeName, storageCurrent, req.Storage, ce); error += ce; } var throughputCurrent = BlockSetInfo.TotalProduction(id); var te = ErrorFunction(req.Throughput, throughputCurrent, 1, 1e-6) * req.ThroughputErrorMultiplier; logger?.Invoke("{0} throughput current {1:e} vs {2:e}. Store {3:e}. Err {4:e}", id, throughputCurrent, req.Throughput, req.Storage, te); error += te; } error /= Seed.LocalStorage.Count(); // inventory: var errInventory = ErrorFunction(Seed.StorageVolume, BlockSetInfo.TotalInventoryCapacity, 1e3, 1e-3); logger?.Invoke("Inventory capacity current {0:e} vs {1:e}. Err {2:e}", BlockSetInfo.TotalInventoryCapacity, Seed.StorageVolume, errInventory); error += errInventory; // power: // throughput is extra power available. Total power consumption is (consumption - production). var errPowerThroughput = ErrorFunction(powerReq.Throughput, -BlockSetInfo.TotalPowerNetConsumption, 1e9, 0) * powerReq.ThroughputErrorMultiplier; var errPowerStorage = ErrorFunction(powerReq.Storage, BlockSetInfo.TotalPowerStorage, 1e7, 0) * powerReq.StorageErrorMultiplier; logger?.Invoke("Power throughput current {0:e} vs {1:e}. Err {2:e}", -BlockSetInfo.TotalPowerNetConsumption, powerReq.Throughput, errPowerThroughput); logger?.Invoke("Power capacity current {0:e} vs {1:e}. Err {2:e}", BlockSetInfo.TotalPowerStorage, powerReq.Storage, errPowerStorage); error += errPowerThroughput; error += errPowerStorage; return(error); }
public static ReservedSpace ParseReservedSpace(float gridSize, MyObjectBuilder_CubeBlock src, string[] args, Utilities.LoggingCallback log = null) { var optional = false; var shared = false; var nSet = false; var pSet = false; var nExt = Vector3.Zero; var pExt = Vector3.Zero; foreach (var arg in args) { if (arg.StartsWithICase("NE:")) { Vector3 tmp; if (PartDummyUtils.TryParseVector(arg.Substring(3), out tmp)) { nSet = true; nExt = tmp; } else { log?.Invoke("Failed to decode negative extent argument \"{0}\"", arg); } } else if (arg.StartsWithICase("PE:")) { Vector3 tmp; if (PartDummyUtils.TryParseVector(arg.Substring(3), out tmp)) { pSet = true; pExt = tmp; } else { log?.Invoke("Failed to decode positive extent argument \"{0}\"", arg); } } else if (arg.Equals("share", StringComparison.CurrentCultureIgnoreCase) || arg.Equals("shared", StringComparison.CurrentCultureIgnoreCase)) { shared = true; } else if (arg.Equals("opt", StringComparison.CurrentCultureIgnoreCase) || arg.Equals("optional", StringComparison.CurrentCultureIgnoreCase) || arg.Equals("hint", StringComparison.CurrentCultureIgnoreCase)) { optional = true; } else { log?.Invoke("Failed to decode argument \"{0}\"", arg); } } if (!nSet || !pSet) { var sense = src as MyObjectBuilder_SensorBlock; if (sense != null) { if (!nSet) { nExt = (Vector3)sense.FieldMin / gridSize; } if (!pSet) { pExt = (Vector3)sense.FieldMax / gridSize; } } else { log?.Invoke("Isn't a sensor block and isn't fully specified"); } } var srcTra = new MatrixI(src.BlockOrientation).GetFloatMatrix(); nExt = Vector3.TransformNormal(nExt, srcTra); pExt = Vector3.TransformNormal(pExt, srcTra); return(new ReservedSpace() { Box = new BoundingBox(nExt, pExt), IsOptional = optional, IsShared = shared }); }