Wouldn't ordering of those construction ships in the _ascending_ order of their needed-construction-time-per-gate be enough?
It would if I wrote a custom function just for construction ships. At the moment one function determines the assignment types for every class, based on its type, then the function below runs all the commander assignments at once. Quick example of how you can do so much more with C# in a few lines of code, especially using LINQ.
// list of all unassigned naval officers or those in junior officer positions
List<Commander> AvailableCommanders = Aurora.Commanders.Values.Where(x => x.CommanderType == AuroraCommanderType.Naval && x.CommanderRace == this && (x.CommandType == AuroraCommandType.None || x.CommandType == AuroraCommandType.ExecutiveOfficer || x.CommandType == AuroraCommandType.ChiefEngineer || x.CommandType == AuroraCommandType.TacticalOfficer || x.CommandType == AuroraCommandType.ScienceOfficer || x.CommandType == AuroraCommandType.CAG)).ToList();
if (AvailableCommanders.Count == 0) return;
// ships without a commander
List<Ship> AvailableShips = RacialShips.Where(x => x.ReturnCommander(AuroraCommandType.Ship) == null).OrderBy(x => x.Class.CommanderPriority).ThenBy(x => x.PrimaryAssignmentPriority).ThenByDescending(x => x.SecondaryAssignmentPriority).ToList();
foreach (Ship s in AvailableShips)
{
Commander c = AvailableCommanders.Where(x => x.BonusList.ContainsKey(s.PrimaryBonusType) && x.CommanderRank == s.Class.RankRequired).OrderByDescending(x => x.ReturnBonusValue(s.PrimaryBonusType)).FirstOrDefault();
if (c != null)
{
c.AssignCommanderToShip(s, AuroraCommandType.Ship);
AvailableCommanders.Remove(c);
if (AvailableCommanders.Count == 0) break;
}
}