public static Dictionary <Design, long> FillCarriers(StaticsDB statics, PlayerProcessor playerProc, Dictionary <Design, long> shipGroups) { var designStats = playerProc.DesignStats; var uncarried = new PriorityQueue <KeyValuePair <Design, long> >(); var carriedTows = new Stack <KeyValuePair <Design, long> >(); var carryOrder = shipGroups.Keys. OrderBy(x => statics.ShipFormulas.GalaxySpeed.Evaluate( new Var(SpeedKey, designStats[x].GalaxySpeed). And(SizeKey, designStats[x].Size). And(TowKey, designStats[x].TowCapacity). And(LaneKey, false).Get )). ThenByDescending(x => designStats[x].Size); foreach (var design in carryOrder) { var carryCapacity = designStats[design].CarryCapacity * shipGroups[design]; var tooBig = new List <KeyValuePair <Design, long> >(); while (carryCapacity > 0 && uncarried.Count > 0) { var priority = uncarried.PeekPriority(); var sameSpeed = new PriorityQueue <KeyValuePair <Design, long> >(); while (uncarried.Count > 0 && uncarried.PeekPriority() == priority) { var group = uncarried.Dequeue(); sameSpeed.Enqueue(group, designStats[group.Key].Size); } while (carryCapacity > 0 && sameSpeed.Count > 0) { var group = sameSpeed.Dequeue(); var maxTransportable = (long)Math.Floor(carryCapacity / designStats[group.Key].Size); if (designStats[group.Key].Size > designStats[design].CarryCapacity) { maxTransportable = 0; } var transported = Math.Min(maxTransportable, group.Value); var untransported = group.Value - transported; carryCapacity -= transported * designStats[group.Key].Size; if (untransported > 0) { tooBig.Add(new KeyValuePair <Design, long>(group.Key, untransported)); } if (designStats[group.Key].TowCapacity > 0 && transported > 0) { carriedTows.Push(new KeyValuePair <Design, long>(group.Key, transported)); } } tooBig.AddRange(sameSpeed); } uncarried.Enqueue(new KeyValuePair <Design, long>(design, shipGroups[design]), designStats[design].GalaxySpeed); foreach (var untransported in tooBig) { uncarried.Enqueue(untransported, designStats[untransported.Key].GalaxySpeed); } } var result = uncarried.ToDictionary(x => x.Key, x => x.Value); var nonIsSize = uncarried.Where(x => x.Key.IsDrive == null).Sum(x => designStats[x.Key].Size * x.Value); nonIsSize -= uncarried.Where(x => x.Key.IsDrive != null).Sum(x => designStats[x.Key].TowCapacity * x.Value); while (nonIsSize > 0 && carriedTows.Count > 0) { var towGroup = carriedTows.Pop(); var usedTows = (long)Math.Min(Math.Floor(nonIsSize / designStats[towGroup.Key].TowCapacity), towGroup.Value); if (usedTows <= 0) { continue; } if (!result.ContainsKey(towGroup.Key)) { result.Add(towGroup.Key, 0); } result[towGroup.Key] += usedTows; nonIsSize -= usedTows * designStats[towGroup.Key].TowCapacity; } return(result); }
private void makeDesign(StaticsDB statics, StatesDB states, string id, PredefinedDesign predefDesign, PlayerProcessor playerProc) { var design = states.Designs.FirstOrDefault(x => x.IdCode == id); if (design == null) { var techLevels = new Var(). Init(statics.DevelopmentTopics.Select(x => x.IdCode), false). Init(statics.ResearchTopics.Select(x => x.IdCode), false).Get; var hull = statics.Hulls[predefDesign.HullCode].MakeHull(techLevels); var specials = predefDesign.SpecialEquipment.OrderBy(x => x.Key).Select( x => statics.SpecialEquipment[x.Key].MakeBest(techLevels, x.Value) ).ToList(); var armor = AComponentType.MakeBest(statics.Armors.Values, techLevels); //TODO(0.5) get id from template var reactor = ReactorType.MakeBest(techLevels, hull, specials, statics); //TODO(0.5) get id from template var isDrive = predefDesign.HasIsDrive ? IsDriveType.MakeBest(techLevels, hull, reactor, specials, statics) : null; //TODO(0.5) get id from template var sensor = AComponentType.MakeBest(statics.Sensors.Values, techLevels); //TODO(0.5) get id from template var shield = predefDesign.ShieldCode != null ? statics.Shields[predefDesign.ShieldCode].MakeBest(techLevels) : null; var equipment = predefDesign.MissionEquipment.Select( x => statics.MissionEquipment[x.Key].MakeBest(techLevels, x.Value) ).ToList(); var thruster = AComponentType.MakeBest(statics.Thrusters.Values, techLevels); //TODO(0.5) get id from template design = new Design( id, playerProc.Player, false, true, predefDesign.Name, predefDesign.HullImageIndex, armor, hull, isDrive, reactor, sensor, shield, equipment, specials, thruster ); design.CalcHash(statics); states.Designs.Add(design); } playerProc.Analyze(design, statics); }
private void makeDesign(StaticsDB statics, StatesDB states, string id, PredefinedDesign designData, PlayerProcessor playerProc) { var design = states.Designs.FirstOrDefault(x => x.IdCode == id); if (design == null) { var armor = new Component <ArmorType>(statics.Armors[designData.Armor.IdCode], designData.Armor.Level); var hull = new Component <HullType>(statics.Hulls[designData.Hull.IdCode], designData.Hull.Level); var reactor = new Component <ReactorType>(statics.Reactors[designData.Reactor.IdCode], designData.Reactor.Level); var sensor = new Component <SensorType>(statics.Sensors[designData.Sensors.IdCode], designData.Sensors.Level); var thruster = new Component <ThrusterType>(statics.Thrusters[designData.Thrusters.IdCode], designData.Thrusters.Level); var isDrive = designData.IsDrive != null ? new Component <IsDriveType>(statics.IsDrives[designData.IsDrive.IdCode], designData.IsDrive.Level) : null; var shield = designData.Shield != null ? new Component <ShieldType>(statics.Shields[designData.Shield.IdCode], designData.Shield.Level) : null; var equipment = designData.MissionEquipment.Select( x => new Component <MissionEquipmentType>(statics.MissionEquipment[x.IdCode], x.Level, x.Amount) ).ToList(); var specials = designData.SpecialEquipment.Select( x => new Component <SpecialEquipmentType>(statics.SpecialEquipment[x.IdCode], x.Level, x.Amount) ).ToList(); design = new Design( id, playerProc.Player, false, designData.Name, designData.HullImageIndex, designData.UsesFuel, armor, hull, isDrive, reactor, sensor, thruster, shield, equipment, specials ); design.CalcHash(statics); states.Designs.Add(design); } playerProc.Analyze(design, statics); }