Added MinBy, MaxBy, MinByOrDefault and MaxByOrDefault methods and replaced calls of the style OrderBy[Descending]().First[OrDefault]() which is not as performant.

This commit is contained in:
RoosterDragon
2014-05-22 01:30:48 +01:00
parent db08357e36
commit 0ea3509ee4
16 changed files with 90 additions and 47 deletions

View File

@@ -162,7 +162,7 @@ namespace OpenRA.Editor
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); } foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
var templateOrder = tileset.EditorTemplateOrder ?? new string[] { }; var templateOrder = tileset.EditorTemplateOrder ?? new string[] { };
foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category).OrderBy(t => templateOrder.ToList().IndexOf(t.Key))) foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category).OrderBy(t => Array.IndexOf(templateOrder, t.Key)))
{ {
var category = tc.Key ?? "(Uncategorized)"; var category = tc.Key ?? "(Uncategorized)";
var categoryHeader = new Label var categoryHeader = new Label

View File

@@ -131,6 +131,54 @@ namespace OpenRA
for (;;) { yield return t; t = f(t); } for (;;) { yield return t; t = f(t); }
} }
public static T MinBy<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
{
return ts.CompareBy(selector, 1, true);
}
public static T MaxBy<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
{
return ts.CompareBy(selector, -1, true);
}
public static T MinByOrDefault<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
{
return ts.CompareBy(selector, 1, false);
}
public static T MaxByOrDefault<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
{
return ts.CompareBy(selector, -1, false);
}
static T CompareBy<T, U>(this IEnumerable<T> ts, Func<T, U> selector, int modifier, bool throws)
{
var comparer = Comparer<U>.Default;
T t;
U u;
using (var e = ts.GetEnumerator())
{
if (!e.MoveNext())
if (throws)
throw new ArgumentException("Collection must not be empty.", "ts");
else
return default(T);
t = e.Current;
u = selector(t);
while (e.MoveNext())
{
T nextT = e.Current;
U nextU = selector(nextT);
if (comparer.Compare(nextU, u) * modifier < 0)
{
t = nextT;
u = nextU;
}
}
return t;
}
}
public static int NextPowerOf2(int v) public static int NextPowerOf2(int v)
{ {
--v; --v;

View File

@@ -156,8 +156,7 @@ namespace OpenRA.FileSystem
var index = type == PackageHashType.CRC32 ? crcHashIndex : classicHashIndex; var index = type == PackageHashType.CRC32 ? crcHashIndex : classicHashIndex;
var folder = index[PackageEntry.HashFilename(filename, type)] var folder = index[PackageEntry.HashFilename(filename, type)]
.Where(x => x.Exists(filename)) .Where(x => x.Exists(filename))
.OrderBy(x => x.Priority) .MinByOrDefault(x => x.Priority);
.FirstOrDefault();
if (folder != null) if (folder != null)
return folder.GetContent(filename); return folder.GetContent(filename);
@@ -196,8 +195,7 @@ namespace OpenRA.FileSystem
{ {
var folder = MountedFolders var folder = MountedFolders
.Where(x => x.Exists(filename + ext)) .Where(x => x.Exists(filename + ext))
.OrderByDescending(x => x.Priority) .MaxByOrDefault(x => x.Priority);
.FirstOrDefault();
if (folder != null) if (folder != null)
{ {

View File

@@ -21,8 +21,7 @@ namespace OpenRA.Orders
{ {
var underCursor = world.ScreenMap.ActorsAt(mi) var underCursor = world.ScreenMap.ActorsAt(mi)
.Where(a => !world.FogObscures(a) && a.HasTrait<ITargetable>()) .Where(a => !world.FogObscures(a) && a.HasTrait<ITargetable>())
.OrderByDescending(a => a.Info.SelectionPriority()) .WithHighestSelectionPriority();
.FirstOrDefault();
Target target; Target target;
if (underCursor != null) if (underCursor != null)
@@ -31,8 +30,7 @@ namespace OpenRA.Orders
{ {
var frozen = world.ScreenMap.FrozenActorsAt(world.RenderPlayer, mi) var frozen = world.ScreenMap.FrozenActorsAt(world.RenderPlayer, mi)
.Where(a => a.Info.Traits.Contains<ITargetableInfo>()) .Where(a => a.Info.Traits.Contains<ITargetableInfo>())
.OrderByDescending(a => a.Info.SelectionPriority()) .WithHighestSelectionPriority();
.FirstOrDefault();
target = frozen != null ? Target.FromFrozenActor(frozen) : Target.FromCell(xy); target = frozen != null ? Target.FromFrozenActor(frozen) : Target.FromCell(xy);
} }
@@ -61,8 +59,7 @@ namespace OpenRA.Orders
var useSelect = false; var useSelect = false;
var underCursor = world.ScreenMap.ActorsAt(mi) var underCursor = world.ScreenMap.ActorsAt(mi)
.Where(a => !world.FogObscures(a) && a.HasTrait<ITargetable>()) .Where(a => !world.FogObscures(a) && a.HasTrait<ITargetable>())
.OrderByDescending(a => a.Info.SelectionPriority()) .WithHighestSelectionPriority();
.FirstOrDefault();
if (underCursor != null && (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any())) if (underCursor != null && (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any()))
{ {
@@ -78,8 +75,7 @@ namespace OpenRA.Orders
{ {
var frozen = world.ScreenMap.FrozenActorsAt(world.RenderPlayer, mi) var frozen = world.ScreenMap.FrozenActorsAt(world.RenderPlayer, mi)
.Where(a => a.Info.Traits.Contains<ITargetableInfo>()) .Where(a => a.Info.Traits.Contains<ITargetableInfo>())
.OrderByDescending(a => a.Info.SelectionPriority()) .WithHighestSelectionPriority();
.FirstOrDefault();
target = frozen != null ? Target.FromFrozenActor(frozen) : Target.FromCell(xy); target = frozen != null ? Target.FromFrozenActor(frozen) : Target.FromCell(xy);
} }
@@ -161,5 +157,15 @@ namespace OpenRA.Orders
var selectableInfo = a.Traits.GetOrDefault<SelectableInfo>(); var selectableInfo = a.Traits.GetOrDefault<SelectableInfo>();
return selectableInfo != null ? selectableInfo.Priority : int.MinValue; return selectableInfo != null ? selectableInfo.Priority : int.MinValue;
} }
public static Actor WithHighestSelectionPriority(this IEnumerable<Actor> actors)
{
return actors.MaxByOrDefault(a => a.Info.SelectionPriority());
}
public static FrozenActor WithHighestSelectionPriority(this IEnumerable<FrozenActor> actors)
{
return actors.MaxByOrDefault(a => a.Info.SelectionPriority());
}
} }
} }

View File

@@ -535,7 +535,7 @@ namespace OpenRA.Server
LobbyInfo.Clients.RemoveAll(c => c.Bot != null && c.BotControllerClientIndex == toDrop.PlayerIndex); LobbyInfo.Clients.RemoveAll(c => c.Bot != null && c.BotControllerClientIndex == toDrop.PlayerIndex);
var nextAdmin = LobbyInfo.Clients.Where(c1 => c1.Bot == null) var nextAdmin = LobbyInfo.Clients.Where(c1 => c1.Bot == null)
.OrderBy(c => c.Index).FirstOrDefault(); .MinByOrDefault(c => c.Index);
if (nextAdmin != null) if (nextAdmin != null)
{ {

View File

@@ -106,8 +106,7 @@ namespace OpenRA.Widgets
var underCursor = world.ScreenMap.ActorsAt(worldRenderer.Viewport.ViewToWorldPx(Viewport.LastMousePos)) var underCursor = world.ScreenMap.ActorsAt(worldRenderer.Viewport.ViewToWorldPx(Viewport.LastMousePos))
.Where(a => !world.FogObscures(a) && a.HasTrait<IToolTip>()) .Where(a => !world.FogObscures(a) && a.HasTrait<IToolTip>())
.OrderByDescending(a => a.Info.SelectionPriority()) .WithHighestSelectionPriority();
.FirstOrDefault();
if (underCursor != null) if (underCursor != null)
{ {
@@ -118,8 +117,7 @@ namespace OpenRA.Widgets
var frozen = world.ScreenMap.FrozenActorsAt(world.RenderPlayer, worldRenderer.Viewport.ViewToWorldPx(Viewport.LastMousePos)) var frozen = world.ScreenMap.FrozenActorsAt(world.RenderPlayer, worldRenderer.Viewport.ViewToWorldPx(Viewport.LastMousePos))
.Where(a => a.TooltipName != null) .Where(a => a.TooltipName != null)
.OrderByDescending(a => a.Info.SelectionPriority()) .WithHighestSelectionPriority();
.FirstOrDefault();
if (frozen != null) if (frozen != null)
{ {

View File

@@ -93,8 +93,7 @@ namespace OpenRA.Widgets
if (multiClick) if (multiClick)
{ {
var unit = World.ScreenMap.ActorsAt(xy) var unit = World.ScreenMap.ActorsAt(xy)
.OrderByDescending(a => a.Info.SelectionPriority()) .WithHighestSelectionPriority();
.FirstOrDefault();
var newSelection2 = SelectActorsInBox(World, worldRenderer.Viewport.TopLeft, worldRenderer.Viewport.BottomRight, var newSelection2 = SelectActorsInBox(World, worldRenderer.Viewport.TopLeft, worldRenderer.Viewport.BottomRight,
a => unit != null && a.Info.Name == unit.Info.Name && a.Owner == unit.Owner); a => unit != null && a.Info.Name == unit.Info.Name && a.Owner == unit.Owner);

View File

@@ -35,13 +35,12 @@ namespace OpenRA
public static Actor ClosestTo(this IEnumerable<Actor> actors, Actor a) public static Actor ClosestTo(this IEnumerable<Actor> actors, Actor a)
{ {
var pos = a.CenterPosition; return actors.ClosestTo(a.CenterPosition);
return actors.OrderBy(b => (b.CenterPosition - pos).LengthSquared).FirstOrDefault();
} }
public static Actor ClosestTo(this IEnumerable<Actor> actors, WPos pos) public static Actor ClosestTo(this IEnumerable<Actor> actors, WPos pos)
{ {
return actors.OrderBy(a => (a.CenterPosition - pos).LengthSquared).FirstOrDefault(); return actors.MinByOrDefault(a => (a.CenterPosition - pos).LengthSquared);
} }
public static IEnumerable<Actor> FindActorsInCircle(this World world, WPos origin, WRange r) public static IEnumerable<Actor> FindActorsInCircle(this World world, WPos origin, WRange r)

View File

@@ -213,7 +213,7 @@ namespace OpenRA.Mods.Cnc.Widgets
if (CurrentQueue == null) if (CurrentQueue == null)
return; return;
var buildableItems = CurrentQueue.BuildableItems().OrderBy(a => a.Traits.Get<BuildableInfo>().BuildPaletteOrder); var buildableItems = CurrentQueue.BuildableItems();
// Background // Background
foreach (var rect in icons.Keys) foreach (var rect in icons.Keys)

View File

@@ -298,7 +298,7 @@ namespace OpenRA.Mods.RA.AI
// Try to maintain 20% excess power // Try to maintain 20% excess power
if (!HasAdequatePower()) if (!HasAdequatePower())
return buildableThings.Where(a => GetPowerProvidedBy(a) > 0) return buildableThings.Where(a => GetPowerProvidedBy(a) > 0)
.OrderByDescending(a => GetPowerProvidedBy(a)).FirstOrDefault(); .MaxByOrDefault(a => GetPowerProvidedBy(a));
if (playerResource.AlertSilo) if (playerResource.AlertSilo)
return GetBuildingInfoByCommonName("Silo", p); return GetBuildingInfoByCommonName("Silo", p);
@@ -365,9 +365,13 @@ namespace OpenRA.Mods.RA.AI
case BuildingType.Refinery: case BuildingType.Refinery:
var tilesPos = world.FindTilesInCircle(baseCenter, MaxBaseDistance) var tilesPos = world.FindTilesInCircle(baseCenter, MaxBaseDistance)
.Where(a => resourceTypes.Contains(world.GetTerrainType(new CPos(a.X, a.Y)))) .Where(a => resourceTypes.Contains(world.GetTerrainType(new CPos(a.X, a.Y))));
.OrderBy(a => (a.CenterPosition - baseCenter.CenterPosition).LengthSquared); if (tilesPos.Any())
return tilesPos.Any() ? findPos(tilesPos.First().CenterPosition, baseCenter) : null; {
var pos = tilesPos.MinBy(a => (a.CenterPosition - baseCenter.CenterPosition).LengthSquared);
return findPos(pos.CenterPosition, baseCenter);
}
return null;
case BuildingType.Building: case BuildingType.Building:
for (var k = 0; k < maxBaseDistance; k++) for (var k = 0; k < maxBaseDistance; k++)
@@ -426,8 +430,7 @@ namespace OpenRA.Mods.RA.AI
var leastLikedEnemies = liveEnemies var leastLikedEnemies = liveEnemies
.GroupBy(e => aggro[e].Aggro) .GroupBy(e => aggro[e].Aggro)
.OrderByDescending(g => g.Key) .MaxByOrDefault(g => g.Key);
.FirstOrDefault();
var enemy = (leastLikedEnemies != null) ? var enemy = (leastLikedEnemies != null) ?
leastLikedEnemies.Random(random) : liveEnemies.FirstOrDefault(); leastLikedEnemies.Random(random) : liveEnemies.FirstOrDefault();
@@ -457,12 +460,9 @@ namespace OpenRA.Mods.RA.AI
{ {
var allEnemyUnits = world.Actors var allEnemyUnits = world.Actors
.Where(unit => p.Stances[unit.Owner] == Stance.Enemy && !unit.HasTrait<Husk>() && .Where(unit => p.Stances[unit.Owner] == Stance.Enemy && !unit.HasTrait<Husk>() &&
unit.HasTrait<ITargetable>()).ToList(); unit.HasTrait<ITargetable>());
if (allEnemyUnits.Count > 0) return allEnemyUnits.ClosestTo(pos);
return allEnemyUnits.ClosestTo(pos);
return null;
} }
internal Actor FindClosestEnemy(WPos pos, WRange radius) internal Actor FindClosestEnemy(WPos pos, WRange radius)

View File

@@ -93,7 +93,7 @@ namespace OpenRA.Mods.RA.Activities
var restrictTo = maximumDistance == null ? null : self.World.FindTilesInCircle(self.Location, maximumDistance.Value); var restrictTo = maximumDistance == null ? null : self.World.FindTilesInCircle(self.Location, maximumDistance.Value);
if (maximumDistance != null) if (maximumDistance != null)
destination = restrictTo.OrderBy(x => (x - destination).Length).First(); destination = restrictTo.MinBy(x => (x - destination).LengthSquared);
var pos = self.Trait<IPositionable>(); var pos = self.Trait<IPositionable>();
if (pos.CanEnterCell(destination) && self.Owner.Shroud.IsExplored(destination)) if (pos.CanEnterCell(destination) && self.Owner.Shroud.IsExplored(destination))

View File

@@ -69,8 +69,7 @@ namespace OpenRA.Mods.RA.Air
var side = new WVec(-fwd.Y, fwd.X, fwd.Z); var side = new WVec(-fwd.Y, fwd.X, fwd.Z);
var approachDelta = self.CenterPosition - approachStart; var approachDelta = self.CenterPosition - approachStart;
var sideTowardBase = new[] { side, -side } var sideTowardBase = new[] { side, -side }
.OrderBy(a => WVec.Dot(a, approachDelta)) .MinBy(a => WVec.Dot(a, approachDelta));
.First();
// Calculate the tangent line that joins the turning circles at the current and approach positions // Calculate the tangent line that joins the turning circles at the current and approach positions
var cp = self.CenterPosition + turnRadius * sideTowardBase / 1024; var cp = self.CenterPosition + turnRadius * sideTowardBase / 1024;

View File

@@ -77,9 +77,7 @@ namespace OpenRA.Mods.RA
? world.SharedRandom.Next(available.Count) ? world.SharedRandom.Next(available.Count)
: available // pick the most distant spawnpoint from everyone else : available // pick the most distant spawnpoint from everyone else
.Select((k, i) => Pair.New(k, i)) .Select((k, i) => Pair.New(k, i))
.OrderByDescending(a => taken.Sum(t => (t - a.First).LengthSquared)) .MaxBy(a => taken.Sum(t => (t - a.First).LengthSquared)).Second;
.Select(a => a.Second)
.First();
var sp = available[n]; var sp = available[n];
available.RemoveAt(n); available.RemoveAt(n);

View File

@@ -134,9 +134,8 @@ namespace OpenRA.Mods.RA
var underCursor = world.ScreenMap.ActorsAt(mi) var underCursor = world.ScreenMap.ActorsAt(mi)
.Where(a => !world.FogObscures(a)) .Where(a => !world.FogObscures(a))
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() .MaxByOrDefault(a => a.Info.Traits.Contains<SelectableInfo>()
? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue) ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue);
.FirstOrDefault();
if (mi.Button == Game.mouseButtonPreference.Action && underCursor == null) if (mi.Button == Game.mouseButtonPreference.Action && underCursor == null)
{ {

View File

@@ -132,7 +132,7 @@ namespace OpenRA.Mods.RA
while ((to - z).X > 5 || (to - z).X < -5 || (to - z).Y > 5 || (to - z).Y < -5) while ((to - z).X > 5 || (to - z).X < -5 || (to - z).Y > 5 || (to - z).Y < -5)
{ {
var step = steps.Where(t => (to - (z + new float2(t[0], t[1]))).LengthSquared < (to - z).LengthSquared) var step = steps.Where(t => (to - (z + new float2(t[0], t[1]))).LengthSquared < (to - z).LengthSquared)
.OrderBy(t => Math.Abs(float2.Dot(z + new float2(t[0], t[1]), q) + c)).First(); .MinBy(t => Math.Abs(float2.Dot(z + new float2(t[0], t[1]), q) + c));
var pos = wr.Position((z + new float2(step[2], step[3])).ToInt2()); var pos = wr.Position((z + new float2(step[2], step[3])).ToInt2());
rs.Add(new SpriteRenderable(s.GetSprite(step[4]), pos, WVec.Zero, 0, pal, 1f, true)); rs.Add(new SpriteRenderable(s.GetSprite(step[4]), pos, WVec.Zero, 0, pal, 1f, true));

View File

@@ -222,8 +222,7 @@ namespace OpenRA.Utility
if (!remap.ContainsKey(i)) if (!remap.ContainsKey(i))
remap[i] = fullIndexRange remap[i] = fullIndexRange
.Where(a => !remap.ContainsValue(a)) .Where(a => !remap.ContainsValue(a))
.OrderBy(a => ColorDistance(destPalette.Values[a], srcPalette.Values[i])) .MinBy(a => ColorDistance(destPalette.Values[a], srcPalette.Values[i]));
.First();
var srcImage = ShpReader.Load(args[3]); var srcImage = ShpReader.Load(args[3]);