public GunGroup(ProjectileGun[] guns, double caliber, double demandPerGun) { this.Guns = guns; this.Caliber = caliber; this.DemandPerGun = demandPerGun; this.DemandTotal = demandPerGun * guns.Length; }
private static GunGroup[][] ConvertSets(int[][][] combos, ProjectileGun[] guns, Tuple<double, double>[][] caliberRanges, Func<Tuple<double, double>, double> caliberFunc) { GunGroup[][] retVal = new GunGroup[combos.Length][]; for (int i = 0; i < combos.Length; i++) { GunGroup[] set = new GunGroup[combos[i].Length]; for (int j = 0; j < combos[i].Length; j++) { double caliber = caliberFunc(caliberRanges[i][j]); ProjectileGun[] gunSet = combos[i][j]. Select(o => guns[o]). ToArray(); double demand = GetAmmoVolume(caliber); set[j] = new GunGroup(gunSet, caliber, demand); } retVal[i] = set; } return retVal; }
private static GunGroup[][] GetAllSetCombos(int[][] majorSets, ProjectileGun[] guns) { // singles // unique sets + remainder singles int[][][] fullSets = UtilityCore.AllCombosEnumerator(majorSets).ToArray(); Tuple<double, double>[][] caliberRanges = fullSets. Select(o => o.Select(p => GetCaliberRange(guns, p)).ToArray()). ToArray(); if (caliberRanges.SelectMany(o => o).Any(o => o.Item1 > o.Item2)) { throw new ApplicationException("Invalid caliber range. majorSets was probably built wrong"); } // Turn each full set into a gungroup[] List<GunGroup[]> retVal = new List<GunGroup[]>(); retVal.AddRange(ConvertSets(fullSets, guns, caliberRanges, o => o.Item1)); // min retVal.AddRange(ConvertSets(fullSets, guns, caliberRanges, o => o.Item2)); // max retVal.AddRange(ConvertSets(fullSets, guns, caliberRanges, o => (o.Item1 + o.Item2) / 2)); // avg Random rand = StaticRandom.GetRandomForThread(); for (int cntr = 0; cntr < 10; cntr++) { retVal.AddRange(ConvertSets(fullSets, guns, caliberRanges, o => rand.NextDouble(o.Item1, o.Item2))); // rand } return retVal.ToArray(); }
private static Tuple<double, double> GetCaliberRange(ProjectileGun[] guns, int[] indices) { return Tuple.Create( indices.Max(o => guns[o].CaliberRange.Item1), // Item1 is as small as the gun can go. So max(item1) will find the gun that is the bottleneck (the largest of the small range) indices.Min(o => guns[o].CaliberRange.Item2)); //return Tuple.Create( // indices.Min(o => guns[o].Caliber), // can't just use caliber. Some guns may have a standard caliber that is outside the range of other guns in the set // indices.Max(o => guns[o].Caliber)); }
private static int[][] GetMajorSets(ProjectileGun[] guns) { if (guns.Length == 1) { return new[] { new[] { 0 } }; } // Get all the min/max boundries of the guns IEnumerable<double> boundries = guns. SelectMany(o => new[] { o.CaliberRange.Item1, o.CaliberRange.Item2 }). Distinct(). OrderBy(o => o); // Go through each boundry, and see which guns straddle it List<int[]> gunsWithBoundry = new List<int[]>(); foreach (double boundry in boundries) { int[] matches = Enumerable.Range(0, guns.Length). Where(o => guns[o].CaliberRange.Item1 <= boundry && guns[o].CaliberRange.Item2 >= boundry). OrderBy(o => o). ToArray(); gunsWithBoundry.Add(matches); } // Dedupe, remove subsets GetMajorSets_Consolidate(gunsWithBoundry); return gunsWithBoundry.ToArray(); }