Separate randomisation and object positioning logic

--- osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs
+++ osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs
@@ -25,6 +25,7 @@
         public override string Description => "It never gets boring!";

         private static readonly float playfield_diagonal = OsuPlayfield.BASE_SIZE.LengthFast;
+        private static readonly Vector2 playfield_centre = OsuPlayfield.BASE_SIZE / 2;

         /// <summary>
         /// Number of previous hitobjects to be shifted together when another object is being moved.
@@ -44,102 +45,124 @@

             rng = new Random((int)Seed.Value);

+            var randomObjects = randomiseObjects(hitObjects);
+
             RandomObjectInfo previous = null;

+            for (int i = 0; i < hitObjects.Count; i++)
+            {
+                var hitObject = hitObjects[i];
+
+                var current = randomObjects[i];
+
+                if (hitObject is Spinner)
+                {
+                    previous = null;
+                    continue;
+                }
+
+                applyRandomisation(getAbsoluteAngle(hitObjects, i - 1), previous, current);
+
+                // Move hit objects back into the playfield if they are outside of it
+                Vector2 shift = Vector2.Zero;
+
+                switch (hitObject)
+                {
+                    case HitCircle circle:
+                        shift = clampHitCircleToPlayfield(circle, current);
+                        break;
+
+                    case Slider slider:
+                        shift = clampSliderToPlayfield(slider, current);
+                        break;
+                }
+
+                if (shift != Vector2.Zero)
+                {
+                    var toBeShifted = new List<OsuHitObject>();
+
+                    for (int j = i - 1; j >= i - preceding_hitobjects_to_shift && j >= 0; j--)
+                    {
+                        // only shift hit circles
+                        if (!(hitObjects[j] is HitCircle)) break;
+
+                        toBeShifted.Add(hitObjects[j]);
+                    }
+
+                    if (toBeShifted.Count > 0)
+                        applyDecreasingShift(toBeShifted, shift);
+                }
+
+                previous = current;
+            }
+        }
+
+        private List<RandomObjectInfo> randomiseObjects(IEnumerable<OsuHitObject> hitObjects)
+        {
+            var randomObjects = new List<RandomObjectInfo>();
+            RandomObjectInfo previous = null;
             float rateOfChangeMultiplier = 0;

-            for (int i = 0; i < hitObjects.Count; i++)
-            {
-                var hitObject = hitObjects[i];
-
+            foreach (OsuHitObject hitObject in hitObjects)
+            {
                 var current = new RandomObjectInfo(hitObject);
+                randomObjects.Add(current);

                 // rateOfChangeMultiplier only changes every 5 iterations in a combo
                 // to prevent shaky-line-shaped streams
                 if (hitObject.IndexInCurrentCombo % 5 == 0)
                     rateOfChangeMultiplier = (float)rng.NextDouble() * 2 - 1;

-                if (hitObject is Spinner)
-                {
-                    previous = null;
-                    continue;
-                }
-
-                applyRandomisation(rateOfChangeMultiplier, previous, current);
-
-                // Move hit objects back into the playfield if they are outside of it
-                Vector2 shift = Vector2.Zero;
-
-                switch (hitObject)
-                {
-                    case HitCircle circle:
-                        shift = clampHitCircleToPlayfield(circle, current);
-                        break;
-
-                    case Slider slider:
-                        shift = clampSliderToPlayfield(slider, current);
-                        break;
-                }
-
-                if (shift != Vector2.Zero)
-                {
-                    var toBeShifted = new List<OsuHitObject>();
-
-                    for (int j = i - 1; j >= i - preceding_hitobjects_to_shift && j >= 0; j--)
-                    {
-                        // only shift hit circles
-                        if (!(hitObjects[j] is HitCircle)) break;
-
-                        toBeShifted.Add(hitObjects[j]);
-                    }
-
-                    if (toBeShifted.Count > 0)
-                        applyDecreasingShift(toBeShifted, shift);
+                if (previous == null)
+                {
+                    current.Distance = (float)(rng.NextDouble() * OsuPlayfield.BASE_SIZE.X / 2);
+                    current.RelativeAngle = (float)(rng.NextDouble() * 2 * Math.PI - Math.PI);
+                }
+                else
+                {
+                    current.Distance = Vector2.Distance(previous.EndPositionOriginal, current.PositionOriginal);
+
+                    // The max. angle (relative to the angle of the vector pointing from the 2nd last to the last hit object)
+                    // is proportional to the distance between the last and the current hit object
+                    // to allow jumps and prevent too sharp turns during streams.
+
+                    // Allow maximum jump angle when jump distance is more than half of playfield diagonal length
+                    current.RelativeAngle = rateOfChangeMultiplier * 2 * (float)Math.PI * Math.Min(1f, current.Distance / (playfield_diagonal * 0.5f));
                 }

                 previous = current;
             }
+
+            return randomObjects;
+        }
+
+        private float getAbsoluteAngle(IReadOnlyList<OsuHitObject> hitObjects, int hitObjectIndex)
+        {
+            if (hitObjectIndex < 0) return 0;
+
+            Vector2 previousPosition = hitObjectIndex == 0 ? playfield_centre : hitObjects[hitObjectIndex - 1].EndPosition;
+            Vector2 relativePosition = hitObjects[hitObjectIndex].Position - previousPosition;
+            return (float)Math.Atan2(relativePosition.Y, relativePosition.X);
         }

         /// <summary>
         /// Returns the final position of the hit object
         /// </summary>
         /// <returns>Final position of the hit object</returns>
-        private void applyRandomisation(float rateOfChangeMultiplier, RandomObjectInfo previous, RandomObjectInfo current)
-        {
-            if (previous == null)
-            {
-                var playfieldSize = OsuPlayfield.BASE_SIZE;
-
-                current.AngleRad = (float)(rng.NextDouble() * 2 * Math.PI - Math.PI);
-                current.PositionRandomised = new Vector2((float)rng.NextDouble() * playfieldSize.X, (float)rng.NextDouble() * playfieldSize.Y);
-
-                return;
-            }
-
-            float distanceToPrev = Vector2.Distance(previous.EndPositionOriginal, current.PositionOriginal);
-
-            // The max. angle (relative to the angle of the vector pointing from the 2nd last to the last hit object)
-            // is proportional to the distance between the last and the current hit object
-            // to allow jumps and prevent too sharp turns during streams.
-
-            // Allow maximum jump angle when jump distance is more than half of playfield diagonal length
-            double randomAngleRad = rateOfChangeMultiplier * 2 * Math.PI * Math.Min(1f, distanceToPrev / (playfield_diagonal * 0.5f));
-
-            current.AngleRad = (float)randomAngleRad + previous.AngleRad;
-            if (current.AngleRad < 0)
-                current.AngleRad += 2 * (float)Math.PI;
+        private void applyRandomisation(float previousAbsoluteAngle, RandomObjectInfo previous, RandomObjectInfo current)
+        {
+            float absoluteAngle = previousAbsoluteAngle + current.RelativeAngle;

             var posRelativeToPrev = new Vector2(
-                distanceToPrev * (float)Math.Cos(current.AngleRad),
-                distanceToPrev * (float)Math.Sin(current.AngleRad)
+                current.Distance * (float)Math.Cos(absoluteAngle),
+                current.Distance * (float)Math.Sin(absoluteAngle)
             );

-            posRelativeToPrev = OsuHitObjectGenerationUtils.RotateAwayFromEdge(previous.EndPositionRandomised, posRelativeToPrev);
-
-            current.AngleRad = (float)Math.Atan2(posRelativeToPrev.Y, posRelativeToPrev.X);
-
-            current.PositionRandomised = previous.EndPositionRandomised + posRelativeToPrev;
+            Vector2 lastEndPosition = previous?.EndPositionRandomised ?? playfield_centre;
+
+            posRelativeToPrev = OsuHitObjectGenerationUtils.RotateAwayFromEdge(lastEndPosition, posRelativeToPrev);
+
+            current.PositionRandomised = lastEndPosition + posRelativeToPrev;
         }

         /// <summary>
@@ -287,7 +310,8 @@

         private class RandomObjectInfo
         {
-            public float AngleRad { get; set; }
+            public float RelativeAngle { get; set; }
+            public float Distance { get; set; }

             public Vector2 PositionOriginal { get; }
             public Vector2 PositionRandomised { get; set; }
@@ -299,7 +323,6 @@
             {
                 PositionRandomised = PositionOriginal = hitObject.Position;
                 EndPositionRandomised = EndPositionOriginal = hitObject.EndPosition;
-                AngleRad = 0;
             }
         }
     }


Account for headless nulls (but how?)

Account for headless nulls (but how?)

--- osu.Game/Graphics/Backgrounds/Triangles.cs
+++ osu.Game/Graphics/Backgrounds/Triangles.cs
@@ -249,7 +249,7 @@
             {
                 base.Dispose(isDisposing);

-                vertexBatch.Dispose();
+                vertexBatch?.Dispose();
             }
         }


Use avatar_url from user first instead of a.ppy.sh in DrawableAvatar

--- osu.Game/Users/Drawables/DrawableAvatar.cs
+++ osu.Game/Users/Drawables/DrawableAvatar.cs
@@ -5,6 +5,7 @@
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Sprites;
 using osu.Framework.Graphics.Textures;
+using osu.Game.Online.API;

 namespace osu.Game.Users.Drawables
 {
@@ -12,6 +13,9 @@
     public class DrawableAvatar : Sprite
     {
         private readonly User user;
+
+        [Resolved(CanBeNull=true)]
+        private IAPIProvider api { get; set; }

         /// <summary>
         /// A simple, non-interactable avatar sprite for the specified user.
@@ -30,9 +34,11 @@
         [BackgroundDependencyLoader]
         private void load(LargeTextureStore textures)
         {
-            if (user != null && user.Id > 1)
+            if (api != null && user?.AvatarUrl != null)
+                Texture = textures.Get(user.AvatarUrl.StartsWith('/') ? $"{api.WebsiteRootUrl}{user.AvatarUrl}" : user.AvatarUrl);
+            else if (user != null && user.Id > 1)
                 Texture = textures.Get($@"https://a.ppy.sh/{user.Id}");
-
+
             Texture ??= textures.Get(@"Online/avatar-guest");
         }


Update osu.Game/Users/Drawables/DrawableAvatar.cs

Co-Authored-By: Dean Herbert <1db828bcd41de75377dce59825af73ae7fca5651@ppy.sh>

--- osu.Game/Users/Drawables/DrawableAvatar.cs
+++ osu.Game/Users/Drawables/DrawableAvatar.cs
@@ -68,7 +68,7 @@
             if (!OpenOnClick.Value)
                 return;

-            if (user != null && user.Id != 1)
+            if (user?.Id > 1)
                 game?.ShowUser(user.Id);
         }


Removed whitespace (test SourceTree config is correct for github)

--- pMixins.TheorySandbox/MasterWrapperBase.cs
+++ pMixins.TheorySandbox/MasterWrapperBase.cs
@@ -224,6 +224,5 @@
                 invocationComplete(eventArgs);

         }
-
     }
 }


Comment only

Comment only

--- Diphap.JsNetBridge.Mvc/AspMvcInfo.cs
+++ Diphap.JsNetBridge.Mvc/AspMvcInfo.cs
@@ -108,12 +108,12 @@

         }

-        readonly public AssemblyResolver AssemblyResolver;
-
-        /// <summary>
-        /// Instanciate information about AspMvc Application.
-        /// </summary>
-        /// <param name="appAspNetPath"></param>
+        readonly public AssemblyResolver AssemblyResolver;
+
+        /// <summary>
+        /// Instanciate information about AspMvc Application.
+        /// </summary>
+        /// <param name="asp_net"></param>
         /// <param name="typeSetList"></param>
         /// <returns></returns>
         public AspMvcInfo(Assembly asp_net, IList<AssemblySet> typeSetList)
@@ -187,8 +187,7 @@
         /// <summary>
         /// Instanciate information about AspMvc Application.
         /// </summary>
-        /// <param name="appAspNetPath"></param>
-        /// <param name="typeSetList"></param>
+        /// <param name="asp_net"></param>
         /// <returns></returns>
         public AspMvcInfo(Assembly asp_net)
             : this(asp_net, new AssemblySet[] { })


*Build completed* message

*Build completed* message

--- src/core/Bari.Core/cs/Commands/BuildCommand.cs
+++ src/core/Bari.Core/cs/Commands/BuildCommand.cs
@@ -6,6 +6,7 @@
 using Bari.Core.Exceptions;
 using Bari.Core.Generic;
 using Bari.Core.Model;
+using Bari.Core.UI;

 namespace Bari.Core.Commands
 {
@@ -21,6 +22,7 @@
         private readonly IFileSystemDirectory targetRoot;
         private readonly IEnumerable<IProjectBuilderFactory> projectBuilders;
         private readonly ICommandTargetParser targetParser;
+        private readonly IUserOutput output;

         /// <summary>
         /// Gets the name of the command. This is the string which can be used on the command line interface
@@ -69,12 +71,13 @@
         /// <param name="projectBuilders">The set of registered project builder factories</param>
         /// <param name="targetRoot">Build target root directory </param>
         /// <param name="targetParser">Command target parser implementation to be used</param>
-        public BuildCommand(IBuildContextFactory buildContextFactory, IEnumerable<IProjectBuilderFactory> projectBuilders, [TargetRoot] IFileSystemDirectory targetRoot, ICommandTargetParser targetParser)
+        public BuildCommand(IBuildContextFactory buildContextFactory, IEnumerable<IProjectBuilderFactory> projectBuilders, [TargetRoot] IFileSystemDirectory targetRoot, ICommandTargetParser targetParser, IUserOutput output)
         {
             this.buildContextFactory = buildContextFactory;
             this.projectBuilders = projectBuilders;
             this.targetRoot = targetRoot;
             this.targetParser = targetParser;
+            this.output = output;
         }

         /// <summary>
@@ -149,8 +152,8 @@
                     MergeOutputForProduct(productTarget.Product, outputs);
                 }
             }
-
-            log.InfoFormat("Build completed.");
+
+            output.Message("Build completed.");
         }

         private void MergeOutputForProduct(Product product, ISet<TargetRelativePath> outputs)


Added JSON config file parsing to AtlasEngine. Primarily loads Systems in a {Key, Value} as {Interface/Class, Instance} design to allow for custom System implementations.

--- ECS/Components/Engine/AtlasEngine.cs
+++ ECS/Components/Engine/AtlasEngine.cs
@@ -5,14 +5,17 @@
 using Atlas.ECS.Entities;
 using Atlas.ECS.Entities.Messages;
 using Atlas.ECS.Families;
+using Atlas.ECS.Objects;
 using Atlas.ECS.Systems;
 using Atlas.ECS.Systems.Messages;
+using Newtonsoft.Json.Linq;
 using System;
 using System.Collections.Generic;
+using System.IO;

 namespace Atlas.ECS.Components
 {
-	public abstract class AtlasEngine : AtlasComponent, IEngine
+	public sealed class AtlasEngine : AtlasComponent, IEngine
 	{
 		#region Static Singleton

@@ -22,44 +25,49 @@

 		#region Fields

+		//ECS Groups
 		private readonly Group<IEntity> entities = new Group<IEntity>();
 		private readonly Group<IFamily> families = new Group<IFamily>();
 		private readonly Group<ISystem> systems = new Group<ISystem>();

+		//ECS Dictionaries
 		private readonly Dictionary<string, IEntity> entitiesGlobalName = new Dictionary<string, IEntity>();
 		private readonly Dictionary<Type, IFamily> familiesType = new Dictionary<Type, IFamily>();
 		private readonly Dictionary<Type, ISystem> systemsType = new Dictionary<Type, ISystem>();

+		//Reference Counting
 		private readonly Dictionary<Type, int> familiesReference = new Dictionary<Type, int>();
 		private readonly Dictionary<Type, int> systemsReference = new Dictionary<Type, int>();

+		//Update State
 		private bool updateLock = false;
 		private ISystem currentSystem;
 		private TimeStep updateState = TimeStep.None;

+		//Variable Time
 		private float maxVariableTime = 0.25f;
 		private float deltaVariableTime = 0;
 		private float totalVariableTime = 0;

+		//Fixed Time
 		private int lagFixedTime = 0;
 		private float deltaFixedTime = 1f / 60f;
 		private float totalFixedTime = 0;

+		//Configuration
+		private string configPath = "";
+		private JToken config;
+
 		#endregion

 		#region Compose/Dispose

-		public AtlasEngine(float deltaFixedTime, float maxVariableTime) : this()
-		{
-			DeltaFixedTime = deltaFixedTime;
-			MaxVariableTime = maxVariableTime;
-		}
-
-		public AtlasEngine()
+		public AtlasEngine(string configPath = "EngineConfig.json")
 		{
 			if(instance != null)
 				throw new InvalidOperationException($"A new {GetType().Name} instance cannot be instantiated when one already exists.");
 			instance = this;
+			ConfigPath = string.IsNullOrWhiteSpace(configPath) ? "EngineConfig.json" : configPath;
 		}

 		protected override void Destroying()
@@ -100,6 +108,36 @@

 		#endregion

+		#region Configuration
+
+		public string ConfigPath
+		{
+			get { return configPath; }
+			set
+			{
+				if(configPath == value)
+					return;
+				configPath = value;
+				ParseConfig();
+			}
+		}
+
+		private void ParseConfig()
+		{
+			ConfigCreator.Create(configPath);
+			config = JToken.Parse(File.ReadAllText(configPath));
+			DeltaFixedTime = ParseValue(nameof(DeltaFixedTime), DeltaFixedTime);
+			MaxVariableTime = ParseValue(nameof(MaxVariableTime), MaxVariableTime);
+		}
+
+		private T ParseValue<T>(string path, T defaultValue)
+			where T : struct
+		{
+			return config.SelectToken(path)?.Value<T>() ?? defaultValue;
+		}
+
+		#endregion
+
 		#region Entities

 		#region Add/Remove
@@ -199,9 +237,24 @@

 		#region Create

-		protected virtual ISystem CreateSystem(Type type)
-		{
-			return Activator.CreateInstance(type) as ISystem;
+		private ISystem CreateSystem(Type type)
+		{
+			var systems = config.SelectToken("Systems") as JArray;
+			foreach(var system in systems)
+			{
+				if(system.SelectToken("Key").Value<string>() != type.FullName)
+					continue;
+
+				var fullName = system.SelectToken("Value").Value<string>();
+				var assembly = fullName.Split('.')[0];
+
+				type = Type.GetType($"{fullName}, {assembly}", true, true);
+				var instance = (ISystem)Activator.CreateInstance(type);
+				instance.Priority = systems.IndexOf(system);
+
+				return instance;
+			}
+			throw new NullReferenceException($"Couldn't find a System to instantiate for {type.FullName}.");
 		}

 		#endregion
@@ -327,7 +380,7 @@

 		#region Create

-		protected virtual IFamily<TFamilyMember> CreateFamily<TFamilyMember>()
+		private IFamily<TFamilyMember> CreateFamily<TFamilyMember>()
 			where TFamilyMember : class, IFamilyMember, new()
 		{
 			return new AtlasFamily<TFamilyMember>();


Increase version

Increase version

--- EEPhysics/Properties/AssemblyInfo.cs
+++ EEPhysics/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.2.3.0")]
-[assembly: AssemblyFileVersion("1.2.3.0")]
+[assembly: AssemblyVersion("1.2.4.0")]
+[assembly: AssemblyFileVersion("1.2.4.0")]


Fixed card loading

Fixed card loading

--- FlashCards.Core/ViewModel/CardView.cs
+++ FlashCards.Core/ViewModel/CardView.cs
@@ -95,7 +95,7 @@
             this.SideB.Text = card.SideB.Text;
             if (card.SideB.InkStrokes != null)
             {
-                this.SideB.Strokes = card.SideA.InkStrokes;
+                this.SideB.Strokes = card.SideB.InkStrokes;
             }
         }


Check method parameter types strongly.

Check method parameter types strongly.

--- Freesia/Internal/Reflection/Helper.cs
+++ Freesia/Internal/Reflection/Helper.cs
@@ -50,6 +50,7 @@
                     if (@params[i].ParameterType != argTypes[i]) return null;
                 }
             }
+            if (!m.IsGenericMethodDefinition) return m;
             return m.MakeGenericMethod(m.GetGenericArguments().Select(x => generics[x.Name]).ToArray());
         }

@@ -60,6 +61,13 @@
                 .Where(m => m.GetParameters().Length == argTypes.Length)
                 .Select(m => MakePreferredMethod(m, argTypes))
                 .FirstOrDefault(x => x != null);
+        }
+
+        private static bool MatchArgTypes(MethodInfo m, Type[] argTypes)
+        {
+            var paramTypes = m.GetParameters();
+            if (paramTypes.Length != argTypes.Length) return false;
+            return paramTypes.Select(p => p.ParameterType).SequenceEqual(argTypes);
         }

 #if false // may be unused
@@ -90,6 +98,7 @@
             var name = methodName.ToLowerInvariant();
             return EnumerableMethods.Value.Where(m => m.Name.ToLowerInvariant() == name)
                 .Where(m => m.GetParameters().Length == argTypes.Length)
+                .Where(m => m.IsGenericMethodDefinition || MatchArgTypes(m, argTypes))
                 .Select(m => MakePreferredMethod(m, argTypes))
                 .FirstOrDefault(x => x != null) ?? FindPreferredExtraMethod(methodName, argTypes);
         }


Ignore Nop AST node to translate to SyntaxInfo.

--- Freesia/Internal/SyntaxHighlighter.cs
+++ Freesia/Internal/SyntaxHighlighter.cs
@@ -162,6 +162,7 @@
         private static IEnumerable<SyntaxInfo> HighlightOne(ASTNode node)
         {
             if (node == null) yield break;
+            if (node.Token.Type == TokenType.Nop) yield break;
             var info = TranslateSyntaxInfo(node.Token);
             var lhs = HighlightOne(node.Left).ToList();
             var rhs = HighlightOne(node.Right).ToList();


Updated an issue in the demo where an exception was being thrown from Gorgon_DeviceLost when data was too large for the locked image stream.  Turns out the backup image wasn't being resized on device reset.

git-svn-id: 64cc320d9ecd7aad470f8b18be342a8e58536f88@350 a61f9e97-bd4c-0410-8c65-85b29eaa70ff

--- Examples/Input/INeedYourInput/MainForm.cs
+++ Examples/Input/INeedYourInput/MainForm.cs
@@ -228,12 +228,21 @@
 		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
 		private void Gorgon_DeviceLost(object sender, EventArgs e)
 		{
+			try
+			{
+				// Copy to the backup image.
+				using (var backBufferBox = _backBuffer.GetImageData())
+				{
+					using (var backupBox = _backup.GetImageData())
+						backupBox.Write(backBufferBox.ToArray());
+				}
+			}
+			catch (Exception ex)
+			{
+				UI.ErrorBox(this, ex);
+			}
 			// Copy to the backup image.
-			using (var backBufferBox = _backBuffer.GetImageData())
-			{
-				using (var backupBox = _backup.GetImageData())
-					backupBox.Write(backBufferBox.ToArray());
-			}
+			//_backBuffer.CopyToImage(_backup);
 		}

 		/// <summary>
@@ -251,7 +260,9 @@
 			if (_backup != null)
 				_backBuffer.CopyFromImage(_backup);

-			_mouse.SetPositionRange(0, 0, Gorgon.Screen.Width, Gorgon.Screen.Height);
+			_mouse.SetPositionRange(0, 0, Gorgon.Screen.Width, Gorgon.Screen.Height);
+
+			_backup.SetDimensions(Gorgon.Screen.Width, Gorgon.Screen.Height);
 		}

 		/// <summary>


Now Pool objects are resetted immediatly after the Release (if they are holding references to living object this should help the GC's job)

--- _scripts/Utils/MiniPool.cs
+++ _scripts/Utils/MiniPool.cs
@@ -29,12 +29,10 @@
             T obj;

             if( pool.Count == 0)
-                obj = new T();
+                (obj = new T()).Reset();

             else
                 obj = pool.Pop();
-
-            obj.Reset();

             return obj;
         }
@@ -47,17 +45,20 @@
         public T Current()
         {
             if (pool.Count == 0)
-                pool.Push( new T());
+            {
+                T temp = new T();
+                temp.Reset();
+                pool.Push( temp);
+            }

             T obj = pool.Peek();
-
-            obj.Reset();

             return obj;
         }

         public void Release( T item)
         {
+            item.Reset();
             pool.Push( item);
         }
     }


Reverting unintentional checkin of beta code.

--- ExoWeb/Templates/MicrosoftAjax/Content.cs
+++ ExoWeb/Templates/MicrosoftAjax/Content.cs
@@ -14,8 +14,6 @@
 	internal class Content : Control
 	{
 		public Binding Data { get; internal set; }
-
-		public Binding DataType { get; internal set; }

 		public Binding Template { get; internal set; }

@@ -46,17 +44,16 @@
 			// Get the data associated with the content control
 			var dataBinding = Data.Evaluate(page);
 			var templateBinding = Template != null ? Template.Evaluate(page) : null;
-			var dataTypeBinding = DataType != null ? DataType.Evaluate(page) : null;

 			// Output the original template if the data binding expression could not be evaluated
-			if ((!dataBinding.IsValid && (dataTypeBinding == null || !dataTypeBinding.IsValid)) || (templateBinding != null && !templateBinding.IsValid))
+			if (!dataBinding.IsValid || (templateBinding != null && !templateBinding.IsValid))
 			{
 				Abort(page, templateNames, writer);
 				return;
 			}

 			// Just render an empty content element if the data is null
-			if (dataBinding.IsValid && dataBinding.Value == null)
+			if (dataBinding.Value == null)
 			{
 				RenderStartTag(page, writer, ifBinding, dataBinding);
 				RenderEndTag(writer);
@@ -64,41 +61,16 @@
 			}

 			// Get the binding data
-			object data = null;
-			object realData = null;
-			ModelProperty property = null;
-			bool isAdapter = false;
-			ModelType referenceType = null;
-			Type valueType = null;
-			bool isList = false;
+			var data = dataBinding.Value;
+			var isAdapter = data is Adapter;
+			var realData = isAdapter ? ((Adapter)data).RawValue : data;
+			var property = dataBinding.Property;
+			var referenceType = realData is ModelInstance ? ((ModelInstance)realData).Type :
+								property is ModelReferenceProperty ? ((ModelReferenceProperty)property).PropertyType : null;
+			var valueType = realData != null && !(realData is ModelInstance || realData is IEnumerable<ModelInstance>) ? realData.GetType() :
+							property is ModelValueProperty ?  ((ModelValueProperty)property).PropertyType : null;
+			var isList = (property != null && property.IsList) || (realData is IEnumerable && !(realData is string));

-			// Valid binding
-			if (dataBinding.IsValid)
-			{
-				data = dataBinding.Value;
-				isAdapter = data is Adapter;
-				realData = isAdapter ? ((Adapter)data).RawValue : data;
-				property = dataBinding.Property;
-				referenceType = realData is ModelInstance ? ((ModelInstance)realData).Type :
-								property is ModelReferenceProperty ? ((ModelReferenceProperty)property).PropertyType : null;
-				valueType = realData != null && !(realData is ModelInstance || realData is IEnumerable<ModelInstance>) ? realData.GetType() :
-							property is ModelValueProperty ? ((ModelValueProperty)property).PropertyType : null;
-				isList = (property != null && property.IsList) || (realData is IEnumerable && !(realData is string));
-			}
-
-			// Datatype hint only
-			else
-			{
-				var dataType = dataTypeBinding.Value as String;
-				isAdapter = Data is Binding.AdapterExtension || dataType == "ExoWeb.View.Adapter";
-				isList = dataType.EndsWith("[]");
-				if (isList)
-					dataType = dataType.Substring(0, dataType.Length - 2);
-				valueType =	dataType == "String" ? typeof(string) :	dataType == "Number" ? typeof(decimal) : dataType == "Date" ? typeof(DateTime) : dataType == "Boolean" ? typeof(bool) : null;
-				if (valueType == null)
-					referenceType = ModelContext.Current.GetModelType(dataType);
-			}
-
 			// Evaluate content:template binding to get this content control's declare template(s)
 			var templates = templateBinding != null && templateBinding.DisplayValue != null ? templateBinding.DisplayValue.Split(' ') : new string[0];


Understanding what part of nbench run badly on appveyour

--- GridGomain.Tests.Stress/NBenchTest.cs
+++ GridGomain.Tests.Stress/NBenchTest.cs
@@ -1,5 +1,7 @@
 using System;
 using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
 using NBench;
 using Pro.NBench.xUnit.XunitExtensions;
 using Xunit.Abstractions;
@@ -9,11 +11,13 @@
     {
         private const string TotalCommandsExecutedCounter = nameof(TotalCommandsExecutedCounter);
         private Counter _counter;
+        private ITestOutputHelper _testOutputHelper;

         public NBenchTest(ITestOutputHelper output)
         {
             Trace.Listeners.Clear();
-            Trace.Listeners.Add(new XunitTraceListener(output));
+            _testOutputHelper = output;
+            Trace.Listeners.Add(new XunitTraceListener(_testOutputHelper));
         }

         [PerfSetup]
@@ -22,6 +26,31 @@
             _counter = context.GetCounter(TotalCommandsExecutedCounter);
         }

+
+        [NBenchFact]
+        [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.",
+            NumberOfIterations = 5, RunMode = RunMode.Iterations,
+            RunTimeMilliseconds = 1000, TestMode = TestMode.Test)]
+        [CounterThroughputAssertion(TotalCommandsExecutedCounter, MustBe.GreaterThan, 400)]
+
+        public void SimpleFact()
+        {
+            try
+            {
+                var executingAssembly = Assembly.GetExecutingAssembly();
+                var allTypes = executingAssembly.GetReferencedAssemblies()
+                                                .Select(Assembly.Load)
+                                                .Concat(new[] { executingAssembly })
+                                                .SelectMany(a => a.GetTypes())
+                                                .ToArray();
+            }
+            catch(Exception ex)
+            {
+               // foreach(var e in ex.LoaderExceptions)
+                    _testOutputHelper.WriteLine(ex.ToString());
+            }
+            _testOutputHelper.WriteLine("ok");
+        }
         [NBenchFact]
         [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.",
             NumberOfIterations = 5, RunMode = RunMode.Iterations,


Add GetBusinessRulesResults override

Add GetBusinessRulesResults override

--- Facile.Core/Extensions/IRuleExtensions.cs
+++ Facile.Core/Extensions/IRuleExtensions.cs
@@ -19,6 +19,12 @@
             }
         }

+        public static IEnumerable<ValidationResult> GetBusinessRulesResults(this IEnumerable<IRule> businessRules)
+        {
+            return IRuleExtensions.GetBusinessRulesResults(businessRules, string.Empty);
+        }
+
+
         public static IRule IfAllValidThenValidate(this IEnumerable<IRule> r, params IRule[] rules)
         {
             return new ValidRuleContainer().IfValidThenValidate(r.ToArray()).IfValidThenValidate(rules);


Fixed bug where the player would get instantly put into the menu when trying to escape out from the drill

--- HoardeGame/GameStates/Singleplayer.cs
+++ HoardeGame/GameStates/Singleplayer.cs
@@ -301,14 +301,14 @@

             keyLabel.Text = Player.ChestKeys.ToString();

+            if (!Drilling && inputProvider.Back)
+            {
+                stateManager.Switch(stateManager.GameStates.First(state => state.GetType() == typeof(MainMenu)));
+            }
+
             if (Drilling && (inputProvider.KeyPressed(Keys.Escape) || inputProvider.ButtonPressed(Buttons.B)))
             {
                 Drilling = false;
-            }
-
-            if (!Drilling && inputProvider.Back)
-            {
-                stateManager.Switch(stateManager.GameStates.First(state => state.GetType() == typeof(MainMenu)));
             }
         }


Fixed #37, access bug with closed modifier

--- Interpreter/Evaluator.cs
+++ Interpreter/Evaluator.cs
@@ -601,12 +601,23 @@

             if (varObj is FileInterpreter)
             {
+                var fileVariable = GetVariable(varname, (varObj as FileInterpreter).FAccess);
+
+                if (fileVariable.Access == AccessTypes.CLOSED)
+                {
+                    throw new Exception($"The access to variable {varname} was denied!");
+                }
+
+                if (fileVariable is Variable)
+                {
+                    return (fileVariable as Variable).Value;
+                }
+
                 var output = interpreter.Output;
                 interpreter.Output = new NoOutput();
                 var fileInterpreter = varObj as FileInterpreter;
-                var result = interpreter.InterpretLine(varname, fileInterpreter.FAccess,fileInterpreter);
+                var result = interpreter.InterpretLine(varname, fileInterpreter.FAccess, fileInterpreter);
                 interpreter.Output = output;
-
                 return result;
             }
             throw new Exception($"Variable {obj} is not of type object!");


These are covered as well.

These are covered as well.

--- src/SparkPost/DataMapper.cs
+++ src/SparkPost/DataMapper.cs
@@ -31,8 +31,6 @@
         {
             return WithCommonConventions(transmission, new Dictionary<string, object>
             {
-                ["metadata"] = transmission.Metadata.Count > 0 ? transmission.Metadata : null,
-                ["substitution_data"] = transmission.SubstitutionData.Count > 0 ? transmission.SubstitutionData : null,
                 ["recipients"] = BuildTheRecipientRequestFrom(transmission)
             });
         }


Bumped version

Bumped version

--- Twice/Properties/AssemblyInfo.cs
+++ Twice/Properties/AssemblyInfo.cs
@@ -17,7 +17,7 @@
 [assembly: ComVisible( false )]
 [assembly: ThemeInfo( ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly )]
 [assembly: LogMinimalMessage]
-[assembly: AssemblyVersion( "0.6.1.0" )]
-[assembly: AssemblyFileVersion( "0.6.1.0" )]
+[assembly: AssemblyVersion( "0.6.2.0" )]
+[assembly: AssemblyFileVersion( "0.6.2.0" )]
 [assembly: InternalsVisibleTo( "Twice.Tests" )]
 [assembly: InternalsVisibleTo( "DynamicProxyGenAssembly2" )]


Fix Trim() not using the comparison parameter

--- Tyrrrz.Extensions/Ext.Strings.cs
+++ Tyrrrz.Extensions/Ext.Strings.cs
@@ -152,7 +152,7 @@
             if (sub == null)
                 throw new ArgumentNullException(nameof(sub));

-            return str.TrimStart(sub).TrimEnd(sub);
+            return str.TrimStart(sub, comparison).TrimEnd(sub, comparison);
         }

         /// <summary>


Typo & precisions for tooltips on info tab.

--- src/TabGuiUtilityOptions.cs
+++ src/TabGuiUtilityOptions.cs
@@ -34,10 +34,8 @@

         protected virtual void DrawOptions()
         {
-            //TODO: reset all filters to their default state
-
             ListingStandard.CheckboxLabeled("Allow Live Filtering", ref _allowLiveFiltering,
-                "Allow filtering without pressing the \"Filter\" button.");
+                "[Warning: CPU heavy] Allow filtering without pressing the \"Filter\" button.");
             _userData.AllowLiveFiltering = _allowLiveFiltering;

             //TODO: allow unimplemented biomes
@@ -52,7 +50,7 @@
             PrepareLanding.Instance.TileHighlighter.ShowDebugTileId = _showDebugTileId;

             ListingStandard.CheckboxLabeled("Bypass TileHighlighter Maximum", ref _bypassMaxHighlightedTiles,
-                $"Allow to highlight more than {TileHighlighter.MaxHighlightedTiles} tiles.");
+                $"Allow highlighting more than {TileHighlighter.MaxHighlightedTiles} tiles.");
             PrepareLanding.Instance.TileHighlighter.BypassMaxHighlightedTiles = _bypassMaxHighlightedTiles;
         }
     }


possible fix for UI thread exception (#1274)

--- ARKBreedingStats/uiControls/CustomMessageBox.cs
+++ ARKBreedingStats/uiControls/CustomMessageBox.cs
@@ -1,4 +1,5 @@
-using System.Drawing;
+using System;
+using System.Drawing;
 using System.Windows.Forms;

 namespace ARKBreedingStats.uiControls
@@ -74,7 +75,9 @@
             var message = Text + "\n\n" + LabelMessage.Text;
             if (string.IsNullOrEmpty(message)) return;

-            Clipboard.SetText(message);
+            if (ActiveForm != null)
+                ActiveForm.Invoke(new Action(() => { Clipboard.SetText(message); }));
+            else Clipboard.SetText(message);
         }

         private void CustomMessageBox_SizeChanged(object sender, System.EventArgs e)


According to the template row height set the new row height.

根据模板行高度设置新行高度。

--- ExcelReport/SheetFormatterContext.cs
+++ ExcelReport/SheetFormatterContext.cs
@@ -66,6 +66,7 @@
                 Sheet.ShiftRows(insertRowIndex, Sheet.LastRowNum, 1, true, false);
             }
             var newRow = Sheet.CreateRow(GetCurrentRowIndex(templateRowIndex + 1));
+            newRow.Height = templateRow.Height;
             _increaseRowsCount++;
             foreach (var cell in templateRow.Cells)
             {


Update PersonServiceTests.cs

Update PersonServiceTests.cs

Update to set entity state.

--- AWSample.IntegrationTests/PersonServiceTests.cs
+++ AWSample.IntegrationTests/PersonServiceTests.cs
@@ -43,7 +43,11 @@
             foreach(BusinessEntityContactModel bcm in person.BusinessEntityContacts)
             {
                 bcm.ModifiedDate = new DateTime(2014, 12, 12);
+                bcm.EntityState = Domain.EntityStateType.Modified;
             }
+
+            if (person.BusinessEntityContacts.Count > 0)
+                person.EntityState = Domain.EntityStateType.Modified;

             service.UpdateBusinessContacts(person);
             person = service.GetList(item => item.BusinessEntityID == 1521, null, new List<Expression<Func<PersonModel, object>>>() { item => item.BusinessEntityContacts }).SingleOrDefault();


Correct txt provider

Correct txt provider

--- Analytics/Providers/Html/HtmlDocumentHandler.cs
+++ Analytics/Providers/Html/HtmlDocumentHandler.cs
@@ -6,6 +6,8 @@
 using HtmlAgilityPack;
 using System;
 using System.IO;
+using System.Linq;
+using System.Net;

 namespace BibleNote.Analytics.Providers.Html
 {
@@ -33,8 +35,11 @@

                 if (ext == ".txt")
                 {
-                    //todo: надо обернуть каждый обзац в

-                    //и надо по-другому проверять, что файл содержит только текст
+                    html = string.Concat(
+                        html.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries)
+                            .Select(p => $"
{p}
"));
+
+                    //todo: надо по-другому проверять, что файл содержит только текст
                 }
             }
             else if (documentId is WebDocumentId webDocumentId)


Added namespace capability (no implementation yet)

--- AngleSharp/Parser/Css/CssSelectorConstructor.cs
+++ AngleSharp/Parser/Css/CssSelectorConstructor.cs
@@ -735,6 +735,11 @@
 					state = State.Class;
                     break;

+                case Specification.Pipe:
+                    //TODO Insert namespace selector using
+                    //the previously added selector (ident, or *)
+                    break;
+
                 default:
                     valid = false;
                     break;


Added comment about GetEntities function

--- GameEngine/DataStructures/QuadTreeNode.cs
+++ GameEngine/DataStructures/QuadTreeNode.cs
@@ -196,7 +196,7 @@
             if (Entities.Count > 0)
             {
                 foreach (Entity entity in Entities)
-                    if (!result.Contains(entity))
+                    if (!result.Contains(entity))           // TODO: This needs to be removed. It is slow and should not be here
                         result.Add(entity);
             }
             else


Fixed wrong GenerateCode call in BCVertexExprPopBinarySet (C --> CS)

--- Graph/Vertex/BCVertexExprPopBinaryMath.cs
+++ Graph/Vertex/BCVertexExprPopBinaryMath.cs
@@ -225,22 +225,22 @@
 					codebuilder.AppendLine("sa(sp()*" + Paren(SecondExpression.GenerateCodeC(g, true), NeedsParen()) + ");");
 					break;
 				case BinaryMathType.DIV:
-					codebuilder.AppendLine("sa(td(sp()," + SecondExpression.GenerateCodeCSharp(g, false) + "));");
+					codebuilder.AppendLine("sa(td(sp()," + SecondExpression.GenerateCodeC(g, false) + "));");
 					break;
 				case BinaryMathType.GT:
-					codebuilder.AppendLine("sa((sp()>" + Paren(SecondExpression.GenerateCodeCSharp(g, false), NeedsParen()) + ")?1:0);");
+					codebuilder.AppendLine("sa((sp()>" + Paren(SecondExpression.GenerateCodeC(g, false), NeedsParen()) + ")?1:0);");
 					break;
 				case BinaryMathType.LT:
-					codebuilder.AppendLine("sa((sp()<" + Paren(SecondExpression.GenerateCodeCSharp(g, false), NeedsParen()) + ")?1:0);");
+					codebuilder.AppendLine("sa((sp()<" + Paren(SecondExpression.GenerateCodeC(g, false), NeedsParen()) + ")?1:0);");
 					break;
 				case BinaryMathType.GET:
-					codebuilder.AppendLine("sa((sp()>=" + Paren(SecondExpression.GenerateCodeCSharp(g, false), NeedsParen()) + ")?1:0);");
+					codebuilder.AppendLine("sa((sp()>=" + Paren(SecondExpression.GenerateCodeC(g, false), NeedsParen()) + ")?1:0);");
 					break;
 				case BinaryMathType.LET:
-					codebuilder.AppendLine("sa((sp()<=" + Paren(SecondExpression.GenerateCodeCSharp(g, false), NeedsParen()) + ")?1:0);");
+					codebuilder.AppendLine("sa((sp()<=" + Paren(SecondExpression.GenerateCodeC(g, false), NeedsParen()) + ")?1:0);");
 					break;
 				case BinaryMathType.MOD:
-					codebuilder.AppendLine("sa(tm(sp()," + SecondExpression.GenerateCodeCSharp(g, false) + "));");
+					codebuilder.AppendLine("sa(tm(sp()," + SecondExpression.GenerateCodeC(g, false) + "));");
 					break;
 				default:
 					throw new Exception("uwotm8");


#9 Player's hand or other children colliders are ignored by player's main collider.

--- Assets/Characters/Scripts/FPSInputController.cs
+++ Assets/Characters/Scripts/FPSInputController.cs
@@ -16,6 +16,10 @@
 	void  Awake (){
 		motor = GetComponent<CharacterMotor>();
 		avatar = transform.FindChild("Avatar").gameObject;
+	}
+
+	void Start() {
+		IgnorePlayerColliders ();
 	}

 	// Update is called once per frame
@@ -72,4 +76,15 @@
 			avatar.animation.CrossFade("Walk");
 		}
 	}
+
+	// Prevent colliders on player from colliding with each other i.e. hand colliders with body collider
+	void IgnorePlayerColliders () {
+		Collider[] cols = GetComponentsInChildren<Collider>();
+
+		foreach (Collider col in cols) {
+			if (col != collider) {
+				Physics.IgnoreCollision(col, collider);
+			}
+		}
+	}
 }


Refactor Discard.GetCards to return all cards matching the predicate

--- Assets/Scripts/HarryPotterUnity/Game/Discard.cs
+++ Assets/Scripts/HarryPotterUnity/Game/Discard.cs
@@ -69,10 +69,9 @@
             }
         }

-        public IEnumerable<GenericCard> GetCardsOfType(Predicate<GenericCard> predicate, int amount)
+        public List<GenericCard> GetCards(Predicate<GenericCard> predicate)
         {
-            //TODO: Randomize this
-            return _cards.FindAll(predicate).Take(amount);
+            return _cards.FindAll(predicate).ToList();
         }

         private void AdjustCardSpacing()


hauteur pop particule

hauteur pop particule


fix #6 add lock to Ensure...

fix #6 add lock to Ensure...

--- AzureBlobFileSystem/AzureBlobStorageProvider.cs
+++ AzureBlobFileSystem/AzureBlobStorageProvider.cs
@@ -14,6 +14,7 @@
     public class AzureBlobStorageProvider  : IStorageProvider
     {
         private readonly CloudStorageAccount _storageAccount;
+        private Object _lock = new Object();
         public CloudBlobClient BlobClient { get; private set; }
         public IList<CloudBlobContainer> Containers { get; private set; }
         public Func<string, CloudBlobContainer> ContainerFactory;
@@ -30,18 +31,22 @@
         {
             var containerName = path.Split('/').First();

-            var container = Containers.SingleOrDefault(c => c.Name == containerName);
-
-            if (container == null)
-            {
-                container = BlobClient.GetContainerReference(containerName);
-
-                if (!container.Exists())
-                {
-                    container = ContainerFactory(containerName);
-                }
-
-                Containers.Add(container);
+            CloudBlobContainer container;
+            lock (_lock)
+            {
+                container = Containers.SingleOrDefault(c => c.Name == containerName);
+
+                if (container == null)
+                {
+                    container = BlobClient.GetContainerReference(containerName);
+
+                    if (!container.Exists())
+                    {
+                        container = ContainerFactory(containerName);
+                    }
+
+                    Containers.Add(container);
+                }
             }

             if (path.StartsWith("/") || path.StartsWith("http://") || path.StartsWith("https://"))


Changed warning to message, as xml doc fragments without content are ok.

--- CLR/Source/CommonBuildTools/MergeXMLDocsTask.cs
+++ CLR/Source/CommonBuildTools/MergeXMLDocsTask.cs
@@ -69,7 +69,7 @@
                      }
                      else
                      {
-                        this.Log.LogWarning( "The XML fragment file {0} does not seem to contain any documentation.", fragmentFN );
+                        this.Log.LogMessage( "The XML fragment file {0} does not seem to contain any documentation.", fragmentFN );
                      }
                   }
                   else


[packages,boost,1.60.0] Clang regex compiled needed visibility to resolve link time missing symbols

--- packages/boost_1_60_0/bam/Scripts/RegEx.cs
+++ packages/boost_1_60_0/bam/Scripts/RegEx.cs
@@ -45,6 +45,15 @@
             base.Init(parent);

             this.BoostSource.AddFiles("$(packagedir)/libs/regex/src/*.cpp");
+
+            this.BoostSource.PrivatePatch(settings =>
+                {
+                    var clangCompiler = settings as ClangCommon.ICommonCompilerSettings;
+                    if (null != clangCompiler)
+                    {
+                        clangCompiler.Visibility = ClangCommon.EVisibility.Default; // TODO: don't know why, but templated do_assign functions were missing at link without this
+                    }
+                });
         }
     }
 }


[packages,Boost,1.60.0] Added RegEx test

--- packages/boost_1_60_0/bam/Scripts/RegEx.cs
+++ packages/boost_1_60_0/bam/Scripts/RegEx.cs
@@ -70,4 +70,41 @@
                     });
         }
     }
-}
+
+    namespace tests
+    {
+        class capturestest :
+            GenericBoostTest
+        {
+            protected override void
+            Init(
+                Bam.Core.Module parent)
+            {
+                base.Init(parent);
+
+                this.TestSource.AddFiles("$(packagedir)/libs/regex/test/captures/*.cpp");
+                this.CompileAndLinkAgainst<RegEx>(this.TestSource);
+
+                this.TestSource.PrivatePatch(settings =>
+                    {
+                        var compiler = settings as C.ICommonCompilerSettings;
+                        compiler.PreprocessorDefines.Add("BOOST_REGEX_MATCH_EXTRA", "1");
+                    });
+            }
+        }
+
+        [Bam.Core.ModuleGroup("Thirdparty/Boost/tests")]
+        sealed class RegExTests :
+            Publisher.Collation
+        {
+            protected override void
+            Init(
+                Bam.Core.Module parent)
+            {
+                base.Init(parent);
+
+                var anchor = this.Include<capturestest>(C.Cxx.ConsoleApplication.Key, EPublishingType.ConsoleApplication);
+                this.Include<RegEx>(C.Cxx.DynamicLibrary.Key, ".", anchor);
+            }
+        }
+    }}


FInal commit for the night after adding log messages

--- aaBackupConsole/Program.cs
+++ aaBackupConsole/Program.cs
@@ -528,7 +528,7 @@

             try
             {
-                log.Debug("Checking and correcting filename");
+                log.Debug("Checking and correcting filename " + BackupFileName + " to use .CAB");
                 // Inspect the filename.  Correct the extension if necessary
                 BackupFileName = System.IO.Path.ChangeExtension(BackupFileName, ".CAB");

@@ -568,7 +568,7 @@
         {
             try
             {
-
+                log.Debug("Checking and correcting filename " + BackupFileName + " to use .AAPKG");
                 // Inspect the filename.  Correct the extension if necessary
                 BackupFileName = System.IO.Path.ChangeExtension(BackupFileName, ".AAPKG");

@@ -596,6 +596,7 @@
         {
             try
             {
+                log.Debug("Checking and correcting filename " + BackupFileName + " to use .CSV");
                 // Inspect the filename.  Correct the extension if necessary
                 BackupFileName = System.IO.Path.ChangeExtension(BackupFileName, ".CSV");

@@ -603,6 +604,13 @@

                 // Call complete backup routine
                 _Galaxy.ExportAll(EExportType.exportAsCSV, BackupFileName);
+
+                if (_Galaxy.CommandResult.Successful != true)
+                {
+                    // Failed to retrieve any objects from the query
+                    log.Error("Error while executing BackupCompleteCSV");
+                    return -2;
+                }

                 log.Info("Backup CSV Complete");

@@ -629,33 +637,48 @@
                 log.Info("Starting Objects Backup to " + _BackupFileName);

                 // If the returned length is ok then stuff the objects into an array
-                if (ObjectList.Length == 0)
+                if (ObjectList.Length <= 0)
                 {
                     // Object List not Long Enough
+                    log.Error("Object list length = 0");
                     return -3;
                 }

                 // Take the comma Separated values and split them into an array
                 ObjectArray = ObjectList.Split(',');

+                log.Debug("QueryObjectsByName for Templates");
                 // Now get the template Objects into a GObjects set
                 GalaxyObjects = _Galaxy.QueryObjectsByName(EgObjectIsTemplateOrInstance.gObjectIsTemplate, ref ObjectArray);

+                if (_Galaxy.CommandResult.Successful != true)
+                {
+                    // Failed to retrieve any objects from the query
+                    log.Error("Error while querying templates by tagname");
+                    return -5;
+                }
+
+                log.Debug("QueryObjectsByName for Instances");
                 // Get Instance Objects.  We have to do this in two steps b/c we can't query templates and instances at the same time
                 GalaxyObjects.AddFromCollection(_Galaxy.QueryObjectsByName(EgObjectIsTemplateOrInstance.gObjectIsInstance, ref ObjectArray));

+                log.Debug("Verify GalaxyObject <> Null, Galaxy Command Success, and Galaxy Objet Count > 0");
                 if ((GalaxyObjects == null) || (_Galaxy.CommandResult.Successful != true) || (GalaxyObjects.count == 0))
                 {
                     // Failed to retrieve any objects from the query
                     log.Error("Failed to retrieve objects to export.");
-                    return -4;
-                }
-
-
-
+                    return -5;
+                }
+
+                log.Debug("Calling the BackupToFile function");
                 // Perform Backup of the Objects in the Group
-                BackupToFile(ExportType, GalaxyObjects, BackupFileName);
-
+                if (BackupToFile(ExportType, GalaxyObjects, BackupFileName) != 0)
+                {
+                    log.Error("Error executing BackupToFile");
+                    return -6;
+                }
+
+                // Success
                 return 0;

             }


Remove diagnostic contract nonsense

Remove diagnostic contract nonsense

Whoever decided that this was a good IntelliSense completion should be
thrown out the airlock.

--- KSPNameGen/KSPNameGen.cs
+++ KSPNameGen/KSPNameGen.cs
@@ -23,7 +23,6 @@

 using System;
 using System.IO;
-using System.Diagnostics.Contracts;
 using System.Linq;
 using System.Threading;

@@ -553,9 +552,6 @@

 		static string Generate(string param)
 		{
-			Contract.Requires(param != null);
-			if (param == null)
-				return null;
 			bool toggle = random.Next(20) == 0;
 			switch (param)
 			{


Tested ItemManagementController

Tested ItemManagementController

--- CRP.Mvc/Controllers/ItemManagementController.cs
+++ CRP.Mvc/Controllers/ItemManagementController.cs
@@ -274,7 +274,7 @@

         /// <summary>
         /// GET: /ItemManagement/Edit/{id}
-        /// Tested main page, but not all tabs 20200505
+        /// Tested main page, but not all tabs 20200505. Tested all tabs 20200511
         /// </summary>
         /// <param name="id"></param>
         /// <returns></returns>
@@ -695,6 +695,11 @@
             return RedirectToAction("Details", "ItemManagement", new {id = transaction.Item.Id});
         }

+        /// <summary>
+        /// Tested 20200511
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
         [PageTracker]
         public ActionResult Copy(int id)
         {


remove picking framebuffer

remove picking framebuffer

--- CSharpGL/ColorCodedPicking/ColorCodedPicking.cs
+++ CSharpGL/ColorCodedPicking/ColorCodedPicking.cs
@@ -53,7 +53,7 @@
             return Pick(arg, rect, pickableElements);
         }

-        private static Framebuffer pickingFramebuffer;
+        //private static Framebuffer pickingFramebuffer;

         /// <summary>
         /// Color Coded Picking
@@ -71,19 +71,19 @@
             if (pickableElements.Length == 0) { return result; }
             if (!PickedSomething(rect, arg.CanvasRect)) { return result; }

-            if (pickingFramebuffer == null
-                || pickingFramebuffer.Width != arg.CanvasRect.Width
-                || pickingFramebuffer.Height != arg.CanvasRect.Height)
-            {
-                if (pickingFramebuffer != null) { pickingFramebuffer.Dispose(); }
-
-                pickingFramebuffer = InitializePickingFramebuffer(
-                  arg.CanvasRect.Width, arg.CanvasRect.Height);
-            }
-            pickingFramebuffer.Bind();
+            //if (pickingFramebuffer == null
+            //    || pickingFramebuffer.Width != arg.CanvasRect.Width
+            //    || pickingFramebuffer.Height != arg.CanvasRect.Height)
+            //{
+            //    if (pickingFramebuffer != null) { pickingFramebuffer.Dispose(); }
+
+            //    pickingFramebuffer = InitializePickingFramebuffer(
+            //      arg.CanvasRect.Width, arg.CanvasRect.Height);
+            //}
+            //pickingFramebuffer.Bind();
             Render4Picking(arg, pickableElements);
             List<Tuple<Point, uint>> stageVertexIdList = ReadPixels(rect, arg.CanvasRect.Height);
-            pickingFramebuffer.Unbind();
+            //pickingFramebuffer.Unbind();
             foreach (var tuple in stageVertexIdList)
             {
                 int x = tuple.Item1.X;


Removed pointless overload, rearranged some method parameters to group with similar ones and make more sense.

--- CSharpTradeOffers/Trading/EconServiceHandler.cs
+++ CSharpTradeOffers/Trading/EconServiceHandler.cs
@@ -94,38 +94,12 @@
         /// <summary>
         /// Accepts a specified trade offer.
         /// </summary>
-        /// <param name="tradeId">A TradeId object containing the id of the trade to accept.</param>
-        /// <param name="container">Auth Cookies MUST be passed here, the function will fail if not.</param>
-        /// <param name="partnerId">The AccountId of the person to trade with.</param>
-        /// <param name="serverid">Almost always 1, not quite sure what other numbers do.</param>
-        /// <returns>The TradeId of the offer that was accepted.</returns>
-        public Trade AcceptTradeOffer(Trade tradeId, CookieContainer container, uint partnerId, string serverid)
-        {
-            container.Add(new Cookie("bCompletedTradeOfferTutorial", "true") {Domain = "steamcommunity.com"});
-            const string url = "https://steamcommunity.com/tradeoffer/{0}/accept";
-            var data = new Dictionary<string, string>
-            {
-                {"sessionid", Web.Web.SessionId},
-                {"serverid", serverid},
-                {"tradeofferid", tradeId.TradeId.ToString()},
-                {"partner", SteamIdOperations.ConvertAccountIdToUlong(partnerId).ToString()},
-                {"captcha", string.Empty}
-            };
-            return
-                JsonConvert.DeserializeObject<Trade>(
-                    WebUtility.UrlDecode(_web.Fetch(string.Format(url, tradeId.TradeId), "POST",
-                        data, container, false, "https://steamcommunity.com/tradeoffer/" + tradeId.TradeId + "/").ReadStream()));
-        }
-
-        /// <summary>
-        /// Accepts a specified trade offer.
-        /// </summary>
         /// <param name="tradeId">A ulong representing the trade to accept.</param>
         /// <param name="container">Auth Cookies MUST be passed here, the function will fail if not.</param>
         /// <param name="partnerId">The AccountId of the person to trade with.</param>
         /// <param name="serverid">Almost always 1, not quite sure what other numbers do.</param>
         /// <returns>The TradeId of the offer that was accepted.</returns>
-        public Trade AcceptTradeOffer(ulong tradeId, CookieContainer container, uint partnerId, string serverid)
+        public Trade AcceptTradeOffer(uint tradeId, uint partnerId, CookieContainer container, string serverid)
         {
             container.Add(new Cookie("bCompletedTradeOfferTutorial", "true") {Domain = "steamcommunity.com"});
             const string url = "https://steamcommunity.com/tradeoffer/{0}/accept";
@@ -147,13 +121,13 @@
         /// Sends a trade offer to the specified recipient.
         /// </summary>
         /// <param name="partnerSid">The SteamId64 (ulong) of the person to send the offer to.</param>
-        /// <param name="container">Auth Cookies MUST be passed here, the function will fail if not.</param>
         /// <param name="tradeoffermessage">An optional message to be sent with the offer. Can be null.</param>
         /// <param name="serverid">Almost always 1, not quite sure what other numbers do.</param>
         /// <param name="offer">A TradeOffer object containing the trade parameters.</param>
+        /// <param name="container">Auth Cookies MUST be passed here, the function will fail if not.</param>
         /// <returns>A SendOfferResponse object.</returns>
-        public SendOfferResponse SendTradeOffer(ulong partnerSid, CookieContainer container, string tradeoffermessage,
-            string serverid, TradeOffer offer)
+        public SendOfferResponse SendTradeOffer(ulong partnerSid, string tradeoffermessage,
+            string serverid, TradeOffer offer, CookieContainer container)
         {
             const string url = "https://steamcommunity.com/tradeoffer/new/send";
             container.Add(new Cookie("bCompletedTradeOfferTutorial", "true") {Domain = "steamcommunity.com"});
@@ -177,14 +151,14 @@
         /// Modifies an existing trade offer.
         /// </summary>
         /// <param name="partnerSid">The SteamId64 (ulong) of the person whose offer will be modified.</param>
-        /// <param name="container">Auth Cookies MUST be passed here, the function will fail if not.</param>
         /// <param name="tradeoffermessage">An otpional message to be sent with the trade offer. Can be null.</param>
         /// <param name="serverid">Almost always 1, not quite sure what other numbers do.</param>
         /// <param name="tradeofferidCountered">The TradeId of the offer to counter or modify.</param>
         /// <param name="offer">A TradeOffer object containing the trade parameters. </param>
+        /// <param name="container">Auth Cookies MUST be passed here, the function will fail if not.</param>
         /// <returns>A SendOfferResponse object.</returns>
-        public SendOfferResponse ModifyTradeOffer(ulong partnerSid, CookieContainer container, string tradeoffermessage,
-            string serverid, uint tradeofferidCountered, TradeOffer offer)
+        public SendOfferResponse ModifyTradeOffer(ulong partnerSid, string tradeoffermessage,
+            string serverid, uint tradeofferidCountered, TradeOffer offer, CookieContainer container)
         {
             const string url = "https://steamcommunity.com/tradeoffer/new/send";
             container.Add(new Cookie("bCompletedTradeOfferTutorial", "true") {Domain = "steamcommunity.com"});


Fix responsible master on approving claim

--- JoinRpg.Services.Impl/ClaimServiceImpl.cs
+++ JoinRpg.Services.Impl/ClaimServiceImpl.cs
@@ -117,6 +117,7 @@

       var now = DateTime.UtcNow;
       claim.MasterAcceptedDate = now;
+      claim.ResponsibleMasterUserId = claim.ResponsibleMasterUserId ?? currentUserId;
       claim.AddCommentImpl(currentUserId, null, commentText, now, true, false);

       foreach (var otherClaim in claim.OtherClaimsForThisPlayer())
@@ -172,6 +173,8 @@
       claim.MasterAcceptedDate = null;
       claim.MasterDeclinedDate = null;

+      claim.ResponsibleMasterUserId = claim.ResponsibleMasterUserId ?? currentUserId;
+
       if (claim.CharacterId != null && claim.OtherClaimsForThisCharacter().Any(c => c.IsApproved))
       {
         claim.CharacterId = null;


Cleanup

Cleanup

--- src/test/Test.Deployment/PackageUnpackSpecs.cs
+++ src/test/Test.Deployment/PackageUnpackSpecs.cs
@@ -6,9 +6,12 @@
 {
     public class when_unpacking_a_package
     {
-        Because of = () =>
-                     DeploymentHelper.unpack(TestData.OutputDir,DeploymentHelper.getPackageFromFile(TestData.GetPackageFile("v1","helloworld")));
+        static DeploymentHelper.DeploymentPackage _package;
+        static readonly string OutputDir = TestData.OutputDir + "HelloWorld";

-        It should_extract_the_package = () => Directory.Exists(TestData.OutputDir + "App").ShouldBeTrue();
+        Establish context = () => _package = DeploymentHelper.getPackageFromFile(TestData.GetPackageFile("v1", "helloworld"));
+        Because of = () => DeploymentHelper.unpack(OutputDir, _package);
+
+        It should_extract_the_package = () => Directory.Exists(OutputDir + "\\App").ShouldBeTrue();
     }
 }


"disabled" json field can have environment variable, fix issue #2428

--- Kudu.Core/Helpers/PostDeploymentHelper.cs
+++ Kudu.Core/Helpers/PostDeploymentHelper.cs
@@ -33,7 +33,7 @@
         // for mocking or override behavior
         public static Func<HttpClient> HttpClientFactory
         {
-            get {  return _httpClientFactory ?? new Func<HttpClient>(() => new HttpClient()); }
+            get { return _httpClientFactory ?? new Func<HttpClient>(() => new HttpClient()); }
             set { _httpClientFactory = value; }
         }

@@ -251,9 +251,9 @@
             }
             finally
             {
-                Trace(TraceEventType.Information,
-                      "Requesting auto swap to '{0}' slot with '{1}' id {2}",
-                      slotSwapName,
+                Trace(TraceEventType.Information,
+                      "Requesting auto swap to '{0}' slot with '{1}' id {2}",
+                      slotSwapName,
                       operationId,
                       exception == null ? "successful." : "failed with " + exception.Message);
             }
@@ -275,11 +275,25 @@
                 var json = (Dictionary<string, object>)serializer.DeserializeObject(File.ReadAllText(functionJson));

                 object value;
-                var disabled = json.TryGetValue("disabled", out value) && (bool)value;
-                if (disabled)
-                {
-                    Trace(TraceEventType.Verbose, "Function {0} is disabled", functionName);
-                    return Enumerable.Empty<Dictionary<string, object>>();
+                // https://github.com/Azure/azure-webjobs-sdk-script/blob/a9bafba78a3a8092bfd61a8c7093200dae867efb/src/WebJobs.Script/Host/ScriptHost.cs#L1476-L1498
+                if (json.TryGetValue("disabled", out value))
+                {
+                    string stringValue = value.ToString();
+                    bool disabled;
+                    // if "disabled" is not a boolean, we try to expend it as an environment variable
+                    if (!Boolean.TryParse(stringValue, out disabled))
+                    {
+                        string expandValue = System.Environment.GetEnvironmentVariable(stringValue);
+                        // "1"/"true" -> true, else false
+                        disabled = string.Equals(expandValue, "1", StringComparison.OrdinalIgnoreCase) ||
+                                   string.Equals(expandValue, "true", StringComparison.OrdinalIgnoreCase);
+                    }
+
+                    if (disabled)
+                    {
+                        Trace(TraceEventType.Verbose, "Function {0} is disabled", functionName);
+                        return Enumerable.Empty<Dictionary<string, object>>();
+                    }
                 }

                 var excluded = json.TryGetValue("excluded", out value) && (bool)value;


Refactor PresentableBase class.

Refactor PresentableBase class.


Changed page header to h3 to be consistent with other pages.

--- crisischeckin/crisicheckinweb/Views/Account/Register.cshtml
+++ crisischeckin/crisicheckinweb/Views/Account/Register.cshtml
@@ -3,9 +3,10 @@
 @{
   ViewBag.Title = "Create new account...";
 }
-
@ViewBag.Title.

+
@ViewBag.Title

+
   @using (Html.BeginForm())
   {


Comment

Comment

--- MagicdrawMigrator/MDMigratorController.cs
+++ MagicdrawMigrator/MDMigratorController.cs
@@ -40,12 +40,12 @@
 			if (mdPackage !=null)
 			{

-				//correctors.Add(new OCLConstraintsCorrector(magicDrawReader,model,mdPackage));
-				//correctors.Add(new AssociationTableCorrector(magicDrawReader,model,mdPackage));
-//				correctors.Add(new FixCallBehaviorActionCorrector(magicDrawReader,model,mdPackage));
+				correctors.Add(new OCLConstraintsCorrector(magicDrawReader,model,mdPackage));
+				correctors.Add(new AssociationTableCorrector(magicDrawReader,model,mdPackage));
+				correctors.Add(new FixCallBehaviorActionCorrector(magicDrawReader,model,mdPackage));
 				correctors.Add(new ConvertPropertiesToAttributes(magicDrawReader,model,mdPackage));
-//				correctors.Add(new SetStructureCorrector(magicDrawReader,model, mdPackage));
-//				correctors.Add(new SetStatesOnObjects(magicDrawReader,model, mdPackage));
+				correctors.Add(new SetStructureCorrector(magicDrawReader,model, mdPackage));
+				correctors.Add(new SetStatesOnObjects(magicDrawReader,model, mdPackage));


optimize requests on PROPPATCH

optimize requests on PROPPATCH

--- MailRuCloud/MailRuCloudApi/MailRuCloud.cs
+++ MailRuCloud/MailRuCloudApi/MailRuCloud.cs
@@ -588,8 +588,9 @@
         /// </summary>
         /// <param name="file">File info.</param>
         /// <param name="removeShareDescription">Also remove share description file (.share.wdmrc)</param>
-        /// <returns>True or false operation result.</returns>
-        public virtual async Task<bool> Remove(File file, bool removeShareDescription = true)
+        /// <param name="doInvalidateCache"></param>
+        /// <returns>True or false operation result.</returns>
+        public virtual async Task<bool> Remove(File file, bool removeShareDescription = true, bool doInvalidateCache = true)
         {
             // remove all parts if file splitted
             var qry = file.Files
@@ -617,14 +618,19 @@
                 else
                 {
                     //remove share description (.wdmrc.share)
-                    if (await GetItem(file.FullPath + PublishInfo.SharedFilePostfix) is File sharefile)
-                        await Remove(sharefile, false);
+                    if (removeShareDescription)
+                    {
+                        if (await GetItem(file.FullPath + PublishInfo.SharedFilePostfix) is File sharefile)
+                            await Remove(sharefile, false);
+                    }
                 }

             }

-            _itemCache.Invalidate(file.Path, file.FullPath);
+            if (doInvalidateCache)
+                _itemCache.Invalidate(file.Path, file.FullPath);
+
             return res;
         }

@@ -906,7 +912,7 @@
                 return true;

             //DANGER! but no way, we need to delete file and add it back with required datetime
-            var removed = await Remove(file, false);
+            var removed = await Remove(file, false, false);
             if (removed)
             {
                 var added = await new MobAddFileRequest(CloudApi, file.FullPath, file.Hash, file.Size, dateTime)
@@ -914,6 +920,8 @@
             }

             file.LastWriteTimeUtc = dateTime;
+
+            _itemCache.Invalidate(file.Path, file.FullPath);

             return true;
         }


Ui test

Ui test

--- MinaGlosor.Web/Views/Welcome/Index.cshtml
+++ MinaGlosor.Web/Views/Welcome/Index.cshtml
@@ -1,24 +1,44 @@
-@{
-    Layout = "";
-    Bundles.Reference("bootstrap");
-}<!DOCTYPE HTML>
-
-
-        <meta name="viewport" content="width=device-width, initial-scale=1.0">
-        <meta charset="utf-8">
-        <title>Mina Glosor</title>
-        @Bundles.RenderStylesheets()
-
-
-

-

-

-                    Välkommen! Du måste börja med att skapa ett konto för administratören.
-                    Med hjälp av det kommer du kunna hantera användarkonton.
-

-

-

+

+    Välkommen! Du måste börja med att skapa ett konto för administratören.
+    Med hjälp av det kommer du kunna hantera användarkonton.
+

+<form method="POST" name="adminform">
+

+

+

+
+                    Ange e-postadress
+
+                <input type="email" class="form-control" name="useremail" />

-
-+

+

+

+

+
+                    Ange lösenord
+
+                <input type="password" class="form-control" name="password"/>
+

+

+

+

+

+

+
+                    Upprepa lösenordet
+
+                <input type="password" class="form-control" name="passwordConfirm"/>
+
+                    Lösenorden måste vara lika
+
+

+

+

+

+

+            <input class="btn btn-primary" type="submit" value="Spara" />
+

+

+</form>


Fix incorrect explosion position on default skin

--- osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs
+++ osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs
@@ -64,14 +64,14 @@
                 hitTarget.Anchor = hitTarget.Origin = Anchor.TopLeft;

                 Padding = new MarginPadding { Top = hitPosition };
-                Explosions.Padding = new MarginPadding { Top = DefaultNotePiece.NOTE_HEIGHT };
+                Explosions.Padding = new MarginPadding { Top = DefaultNotePiece.NOTE_HEIGHT / 2 };
             }
             else
             {
                 hitTarget.Anchor = hitTarget.Origin = Anchor.BottomLeft;

                 Padding = new MarginPadding { Bottom = hitPosition };
-                Explosions.Padding = new MarginPadding { Bottom = DefaultNotePiece.NOTE_HEIGHT };
+                Explosions.Padding = new MarginPadding { Bottom = DefaultNotePiece.NOTE_HEIGHT / 2 };
             }
         }
     }


Only parse statistics when not null

Only parse statistics when not null

--- osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs
+++ osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs
@@ -40,33 +40,36 @@
                 Mods = mods,
             };

-            foreach (var kvp in Statistics)
+            if (Statistics != null)
             {
-                switch (kvp.Key)
+                foreach (var kvp in Statistics)
                 {
-                    case @"count_geki":
-                        scoreInfo.SetCountGeki(kvp.Value);
-                        break;
+                    switch (kvp.Key)
+                    {
+                        case @"count_geki":
+                            scoreInfo.SetCountGeki(kvp.Value);
+                            break;

-                    case @"count_300":
-                        scoreInfo.SetCount300(kvp.Value);
-                        break;
+                        case @"count_300":
+                            scoreInfo.SetCount300(kvp.Value);
+                            break;

-                    case @"count_katu":
-                        scoreInfo.SetCountKatu(kvp.Value);
-                        break;
+                        case @"count_katu":
+                            scoreInfo.SetCountKatu(kvp.Value);
+                            break;

-                    case @"count_100":
-                        scoreInfo.SetCount100(kvp.Value);
-                        break;
+                        case @"count_100":
+                            scoreInfo.SetCount100(kvp.Value);
+                            break;

-                    case @"count_50":
-                        scoreInfo.SetCount50(kvp.Value);
-                        break;
+                        case @"count_50":
+                            scoreInfo.SetCount50(kvp.Value);
+                            break;

-                    case @"count_miss":
-                        scoreInfo.SetCountMiss(kvp.Value);
-                        break;
+                        case @"count_miss":
+                            scoreInfo.SetCountMiss(kvp.Value);
+                            break;
+                    }
                 }
             }


proper handling of empty lines

proper handling of empty lines

--- ModComponentMapper/src/GearSpawnReader.cs
+++ ModComponentMapper/src/GearSpawnReader.cs
@@ -90,7 +90,7 @@
                 }

                 var trimmedLine = eachLine.ToLower().Trim();
-                if (trimmedLine.StartsWith("#"))
+                if (trimmedLine.Length == 0 || trimmedLine.StartsWith("#"))
                 {
                     continue;
                 }


acount controller

acount controller

--- MomWorld/Controllers/AccountController.cs
+++ MomWorld/Controllers/AccountController.cs
@@ -469,10 +469,21 @@
         }

         public ActionResult GetDetail(string id)
+
         {
             return Json(UserManager.FindByName(id), JsonRequestBehavior.AllowGet);
         }

+        public ActionResult UsersManage()
+        {
+            return View();
+        }
+
+
+        public ActionResult PostsManage()
+        {
+            return View();
+        }
         #region Helpers
         // Used for XSRF protection when adding external logins
         private const string XsrfKey = "XsrfId";


Add back accidentally removed remove

Add back accidentally removed remove

--- osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs
+++ osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs
@@ -160,6 +160,8 @@
         /// <param name="blueprint">The blueprint.</param>
         internal void HandleDeselected(SelectionBlueprint blueprint)
         {
+            selectedBlueprints.Remove(blueprint);
+
             EditorBeatmap.SelectedHitObjects.Remove(blueprint.HitObject);

             UpdateVisibility();


Red close buttons

Red close buttons

--- LmpClient/Base/Window.cs
+++ LmpClient/Base/Window.cs
@@ -181,8 +181,15 @@

         protected void DrawCloseButton(Action closeAction, Rect rect)
         {
+            var prev = GUI.backgroundColor;
+            GUI.backgroundColor = Color.red;
+
             if (GUI.Button(new Rect(rect.width - 25, 4, 20, 20), CloseIcon, CloseButtonStyle))
-                closeAction.Invoke();
+            {
+                closeAction.Invoke();
+            }
+
+            GUI.backgroundColor = prev;
         }

         protected void DrawRefreshButton(Action refreshAction)


Rip Naam's sanity

Rip Naam's sanity

--- ModCore/Commands/Star.cs
+++ ModCore/Commands/Star.cs
@@ -59,7 +59,7 @@
                     await ctx.RespondAsync("You have never been given a star.");
                     return;
                 }
-                var unique = messages.Select(x => x.Id).Distinct().Count();
+                var unique = messages.Select(x => x.MessageId).Distinct().Count();

                 await ctx.RespondAsync($"You have been given: "
                     + messages.Count()


Added support for extended basic information

--- NtApiDotNet/NtProcess.cs
+++ NtApiDotNet/NtProcess.cs
@@ -323,7 +323,7 @@
     }

     [StructLayout(LayoutKind.Sequential)]
-    public class ProcessBasicInformation
+    public struct ProcessBasicInformation
     {
         public int ExitStatus;
         public IntPtr PebBaseAddress;
@@ -331,6 +331,29 @@
         public int BasePriority;
         public IntPtr UniqueProcessId;
         public IntPtr InheritedFromUniqueProcessId;
+    }
+
+    [Flags]
+    public enum ProcessExtendedBasicInformationFlags
+    {
+        None = 0,
+        IsProtectedProcess = 0x00000001,
+        IsWow64Process = 0x00000002,
+        IsProcessDeleting = 0x00000004,
+        IsCrossSessionCreate = 0x00000008,
+        IsFrozen = 0x00000010,
+        IsBackground = 0x00000020,
+        IsStronglyNamed = 0x00000040,
+        IsSecureProcess = 0x00000080,
+        IsSubsystemProcess = 0x00000100,
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct ProcessExtendedBasicInformation
+    {
+        public IntPtr Size;
+        public ProcessBasicInformation BasicInfo;
+        public ProcessExtendedBasicInformationFlags Flags;
     }

     [StructLayout(LayoutKind.Sequential)]
@@ -730,21 +753,43 @@
     public class NtProcess : NtObjectWithDuplicate<NtProcess, ProcessAccessRights>
     {
         private int? _pid;
-        private int? _ppid;
-        private IntPtr? _peb;
-
-        private void PopulateBasicInformation()
-        {
-            using (SafeStructureInOutBuffer<ProcessBasicInformation> basic_info = new SafeStructureInOutBuffer<ProcessBasicInformation>())
-            {
-                int return_length = 0;
-                NtSystemCalls.NtQueryInformationProcess(Handle, ProcessInfoClass.ProcessBasicInformation,
-                  basic_info, basic_info.Length, out return_length).ToNtException();
-                ProcessBasicInformation result = basic_info.Result;
-                _pid = result.UniqueProcessId.ToInt32();
-                _ppid = result.InheritedFromUniqueProcessId.ToInt32();
-                _peb = result.PebBaseAddress;
-            }
+        private ProcessExtendedBasicInformation? _extended_info;
+
+        private ProcessExtendedBasicInformation GetExtendedBasicInfo()
+        {
+            if (!_extended_info.HasValue)
+            {
+                if (!IsAccessGranted(ProcessAccessRights.QueryLimitedInformation))
+                {
+                    _extended_info = new ProcessExtendedBasicInformation();
+                }
+                else
+                {
+                    try
+                    {
+                        using (var buf = QueryFixed<ProcessExtendedBasicInformation>(ProcessInfoClass.ProcessBasicInformation))
+                        {
+                            _extended_info = buf.Result;
+                        }
+                    }
+                    catch (NtException)
+                    {
+                        using (var buf = QueryFixed<ProcessBasicInformation>(ProcessInfoClass.ProcessBasicInformation))
+                        {
+                            ProcessExtendedBasicInformation result = new ProcessExtendedBasicInformation();
+                            result.BasicInfo = buf.Result;
+                            _extended_info = result;
+                        }
+                    }
+                }
+            }
+
+            return _extended_info.Value;
+        }
+
+        private ProcessBasicInformation GetBasicInfo()
+        {
+            return GetExtendedBasicInfo().BasicInfo;
         }

         private SafeStructureInOutBuffer<T> Query<T>(ProcessInfoClass info_class) where T : new()
@@ -893,9 +938,11 @@
         {
             get
             {
-                if (!_pid.HasValue)
-                    PopulateBasicInformation();
-                return _pid.Value;
+                if (_pid.HasValue)
+                {
+                    return _pid.Value;
+                }
+                return GetBasicInfo().UniqueProcessId.ToInt32();
             }
         }

@@ -906,9 +953,7 @@
         {
             get
             {
-                if (!_ppid.HasValue)
-                    PopulateBasicInformation();
-                return _ppid.Value;
+                return GetBasicInfo().InheritedFromUniqueProcessId.ToInt32();
             }
         }

@@ -919,9 +964,7 @@
         {
             get
             {
-                if (!_peb.HasValue)
-                    PopulateBasicInformation();
-                return _peb.Value;
+                return GetBasicInfo().PebBaseAddress;
             }
         }

@@ -932,11 +975,8 @@
         {
             get
             {
-                using (SafeStructureInOutBuffer<ProcessBasicInformation> basic_info = new SafeStructureInOutBuffer<ProcessBasicInformation>())
+                using (var basic_info = QueryFixed<ProcessBasicInformation>(ProcessInfoClass.ProcessBasicInformation))
                 {
-                    int return_length = 0;
-                    NtSystemCalls.NtQueryInformationProcess(Handle, ProcessInfoClass.ProcessBasicInformation,
-                      basic_info, basic_info.Length, out return_length).ToNtException();
                     return basic_info.Result.ExitStatus;
                 }
             }
@@ -1205,6 +1245,17 @@
         }

         /// <summary>
+        /// Get extended process flags.
+        /// </summary>
+        public ProcessExtendedBasicInformationFlags ExtendedFlags
+        {
+            get
+            {
+                return GetExtendedBasicInfo().Flags;
+            }
+        }
+
+        /// <summary>
         /// Open an actual handle to the current process rather than the pseudo one used for Current
         /// </summary>
         /// <returns>The process object</returns>


Updated/Added tests.

Updated/Added tests.

--- tests/FileTests.cs
+++ tests/FileTests.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Net.Configuration;
 using System.Text;
 using System.Threading.Tasks;
 using B2Net.Http;
@@ -11,8 +12,9 @@
 namespace B2Net.Tests {
 	[TestClass]
 	public class FileTests : BaseTest {
-		B2Bucket TestBucket = new B2Bucket();
-		B2Client Client = null;
+		private B2Bucket TestBucket = new B2Bucket();
+		private B2Client Client = null;
+		private List<B2File> FilesToDelete = new List<B2File>();

 		[TestInitialize]
 		public void Initialize() {
@@ -26,12 +28,11 @@
 			var fileName = "B2Test.txt";
 			var fileData = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName));
 			var file = Client.Files.Upload(fileData, fileName, TestBucket.BucketId).Result;
+			// Clean up.
+			FilesToDelete.Add(file);

 			var list = Client.Files.GetList(bucketId: TestBucket.BucketId).Result.Files;

-			// Delete file
-			var deletedFile = Client.Files.Delete(file.FileId, file.FileName).Result;
-
 			Assert.AreEqual(1, list.Count, list.Count + " files found.");
 		}

@@ -41,16 +42,14 @@
 			var fileData = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName));
 			string hash = Utilities.GetSHA1Hash(fileData);
 			var file = Client.Files.Upload(fileData, fileName, TestBucket.BucketId).Result;
+			// Clean up.
+			FilesToDelete.Add(file);

 			Assert.AreEqual(hash, file.ContentSHA1, "File hashes did not match.");
-
-			// Clean up. We have to delete the file before we can delete the bucket
+
 			var hiddenFile = Client.Files.Hide(file.FileName, TestBucket.BucketId).Result;

 			Assert.IsTrue(hiddenFile.Action == "hide");
-
-			// Clean up. We have to delete the file before we can delete the bucket
-			var deletedFile = Client.Files.Delete(hiddenFile.FileId, hiddenFile.FileName).Result;
 		}

 		[TestMethod]
@@ -62,8 +61,44 @@

 			Assert.AreEqual(hash, file.ContentSHA1, "File hashes did not match.");

-			// Clean up. We have to delete the file before we can delete the bucket
-			var deletedFile = Client.Files.Delete(file.FileId, file.FileName).Result;
+			// Clean up.
+			FilesToDelete.Add(file);
+		}
+
+		[TestMethod]
+		public void FileDownloadNameTest() {
+			var fileName = "B2Test.txt";
+			var fileData = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName));
+			string hash = Utilities.GetSHA1Hash(fileData);
+			var file = Client.Files.Upload(fileData, fileName, TestBucket.BucketId).Result;
+			// Clean up.
+			FilesToDelete.Add(file);
+
+			Assert.AreEqual(hash, file.ContentSHA1, "File hashes did not match.");
+
+			// Test download
+			var download = Client.Files.DownloadByName(file.FileName, TestBucket.BucketName).Result;
+			var downloadHash = Utilities.GetSHA1Hash(download.FileData);
+
+			Assert.AreEqual(hash, downloadHash);
+		}
+
+		[TestMethod]
+		public void FileDownloadIdTest() {
+			var fileName = "B2Test.txt";
+			var fileData = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName));
+			string hash = Utilities.GetSHA1Hash(fileData);
+			var file = Client.Files.Upload(fileData, fileName, TestBucket.BucketId).Result;
+			// Clean up.
+			FilesToDelete.Add(file);
+
+			Assert.AreEqual(hash, file.ContentSHA1, "File hashes did not match.");
+
+			// Test download
+			var download = Client.Files.DownloadById(file.FileId).Result;
+			var downloadHash = Utilities.GetSHA1Hash(download.FileData);
+
+			Assert.AreEqual(hash, downloadHash);
 		}

 		[TestMethod]
@@ -78,7 +113,7 @@
 			// Clean up. We have to delete the file before we can delete the bucket
 			var deletedFile = Client.Files.Delete(file.FileId, file.FileName).Result;

-			Assert.AreEqual(file.FileId, deletedFile.FileId);
+			Assert.AreEqual(file.FileId, deletedFile.FileId, "The deleted file id did not match.");
 		}

 		[TestMethod]
@@ -87,13 +122,12 @@
 			var fileData = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName));
 			string hash = Utilities.GetSHA1Hash(fileData);
 			var file = Client.Files.Upload(fileData, fileName, TestBucket.BucketId).Result;
+			// Clean up.
+			FilesToDelete.Add(file);

 			Assert.AreEqual(hash, file.ContentSHA1, "File hashes did not match.");

 			var versions = Client.Files.GetVersions(file.FileName, file.FileId, bucketId: TestBucket.BucketId).Result;
-
-			// Clean up. We have to delete the file before we can delete the bucket
-			var deletedFile = Client.Files.Delete(file.FileId, file.FileName).Result;

 			Assert.AreEqual(1, versions.Files.Count);
 		}
@@ -104,19 +138,21 @@
 			var fileData = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName));
 			string hash = Utilities.GetSHA1Hash(fileData);
 			var file = Client.Files.Upload(fileData, fileName, TestBucket.BucketId).Result;
+			// Clean up.
+			FilesToDelete.Add(file);

 			Assert.AreEqual(hash, file.ContentSHA1, "File hashes did not match.");

 			var info = Client.Files.GetInfo(file.FileId).Result;
-
-			// Clean up. We have to delete the file before we can delete the bucket
-			var deletedFile = Client.Files.Delete(file.FileId, file.FileName).Result;

 			Assert.AreEqual(file.UploadTimestamp, info.UploadTimestamp);
 		}

 		[TestCleanup]
 		public void Cleanup() {
+			foreach (B2File b2File in FilesToDelete) {
+				var deletedFile = Client.Files.Delete(b2File.FileId, b2File.FileName).Result;
+			}
 			var deletedBucket = Client.Buckets.Delete(TestBucket.BucketId).Result;
 		}
 	}


Localization fixes

Localization fixes

--- PearXLib/Localization.cs
+++ PearXLib/Localization.cs
@@ -80,8 +80,9 @@
 				if (s.Substring(0, 1) == "#") continue;

 				int p = s.IndexOf("=", StringComparison.Ordinal);
-				s.Replace("\\n\\", "\n");
-				nms.Add(s.Substring(0, p), s.Substring(p + 1, s.Length - p - 1));
+				string sFilt = s.Remove(0, p + 1);
+				sFilt = sFilt.Replace("\\n", "\n");
+				nms.Add(s.Substring(0, p), sFilt);
 			}
 		}
 	}


Removed unused class.

Removed unused class.

--- Perspex/PerspexObject.cs
+++ Perspex/PerspexObject.cs
@@ -582,12 +582,5 @@
                     new PerspexPropertyChangedEventArgs(property, oldValue, newValue));
             }
         }
-
-        private class Binding
-        {
-            public object Observable { get; set; }
-
-            public IDisposable Dispose { get; set; }
-        }
     }
 }


Forgot some debug output

Forgot some debug output

--- src/Generator.cs
+++ src/Generator.cs
@@ -186,8 +186,7 @@
 				int index_opening_bracket = type_str.IndexOf ("[");
 				int index_closing_bracket = type_str.IndexOf ("]");
 				string number = type_str.Substring (index_opening_bracket+1, index_closing_bracket - index_opening_bracket-1);
-				Console.WriteLine (type_str);
-				Console.WriteLine (number);
+
 				if (number != "") {
 					int ret_val = -1;
 					if (int.TryParse (number, out ret_val)) {
@@ -205,7 +204,7 @@
 			while (!FileReader.EndOfStream)
 			{
 				string line = FileReader.ReadLine ();
-				//Console.WriteLine (line);
+
 				if(line.StartsWith("#"))
 					{
 					//DO NOTHING
@@ -213,13 +212,11 @@
 				else if (line.Trim () != "") {
 					string[] splitted = line.Split (new string[]{ " " }, StringSplitOptions.RemoveEmptyEntries);
 					if (IsArray (splitted [0])) {
-						Console.BackgroundColor = ConsoleColor.Blue;
-						Console.WriteLine (line);
-						Console.ResetColor ();
+
 						int fixedArraySize = IsFixedSizeArray (splitted [0]);
 						string nativeType = splitted [0].Remove (splitted [0].IndexOf ("["), splitted[0].IndexOf("]")-splitted[0].IndexOf("[")+1);
 						string csType = GetPrimitiveType (nativeType);
-						Console.WriteLine (nativeType);
+
 						if (!(csType.Trim () == "")) {
 							csType = "rosidl_generator_c__primitive_array_" + nativeType;
 							string memberName = splitted [1];
@@ -234,7 +231,7 @@

 							if (fixedArraySize > 0) {
 								Console.BackgroundColor = ConsoleColor.Blue;
-								Console.WriteLine ("Found fixed size array" + GetPrimitiveType (nativeType));
+
 								Console.ResetColor ();
 								member.isFixedSizeArray = true;
 								member.fixedSizeArraySize = fixedArraySize;
@@ -372,7 +369,7 @@
 				} else {
 					ClassString.AppendLine ("         public " + item.type + "_t " + item.name + ";");
 				}
-				Console.WriteLine (item.name + " " + item.type);
+
 				switch (item.type) {
 				case "rosidl_generator_c__String":
 					WrapperClassString.AppendLine ("        public string "+ item.name);


Update VSCode.cs

Update VSCode.cs

Bump to download

--- Plugins/Editor/VSCode.cs
+++ Plugins/Editor/VSCode.cs
@@ -4,7 +4,7 @@
  * Seamless support for Microsoft Visual Studio Code in Unity
  *
  * Version:
- *   2.5
+ *   2.6
  *
  * Authors:
  *   Matthew Davey <matthew.davey@dotbunny.com>
@@ -25,7 +25,7 @@
         /// <summary>
         /// Current Version Number
         /// </summary>
-        public const float Version = 2.5f;
+        public const float Version = 2.6f;

         /// <summary>
         /// Current Version Code


Ability to add parameters to a Request other than the ones explicitly exposed.

--- Rally.RestApi/Request.cs
+++ Rally.RestApi/Request.cs
@@ -199,6 +199,22 @@

 		#endregion

+        #region AddParameter
+	    /// <summary>
+	    /// Ability to add parameters other than the ones explicitly exposed.
+	    /// </summary>
+	    /// <param name="key"></param>
+	    /// <param name="value"></param>
+	    /// <returns>true if added. false if the key already existed</returns>
+	    public bool AddParameter(string key, string value)
+	    {
+	        if (GetParameterValue(key, null) != null)
+	            return false;
+	        Parameters[key] = value;
+	        return true;
+	    }
+	    #endregion
+
 		#region Helper: GetParameterValue
 		private dynamic GetParameterValue(string keyValue, object defaultValue = null)
 		{


Fixed bug with subreddit header image

Fixed bug with subreddit header image

--- RedditSharp/Subreddit.cs
+++ RedditSharp/Subreddit.cs
@@ -226,7 +226,7 @@
                 formid = "image-upload",
                 img_type = imageType == ImageType.PNG ? "png" : "jpg",
                 upload = "",
-                header = true
+                header = 1
             });
             formData.AddFile("file", "foo.png", file, imageType == ImageType.PNG ? "image/png" : "image/jpeg");
             formData.Finish();


システムエクスクルーシブメッセージの1バイト目が取り除かれていなかった問題を修正

--- src/IO/MidiIn.cs
+++ src/IO/MidiIn.cs
@@ -283,7 +283,7 @@
                     {
                         if (this.ReceivedExclusiveMessage != null)
                         {
-                            var data = this.exclusiveQueue.SelectMany(a => a).Concat(buffer.Take(length));
+                            var data = this.exclusiveQueue.SelectMany(a => a).Concat(buffer.Take(length)).Skip(1);
                             this.ReceivedExclusiveMessage(this, new ReceivedExclusiveMessageEventArgs(data.ToArray(), this));
                         }


modify: 不要なdefaultケースを削除

modify: 不要なdefaultケースを削除

--- src/IO/MidiIn.cs
+++ src/IO/MidiIn.cs
@@ -299,9 +299,6 @@

                 case NativeMethods.MIM_CLOSE:
                     this.Closed?.Invoke(this, new EventArgs());
-                    break;
-
-                default:
                     break;
             }
         }


Fixed a StackOverflowException in the standard mapper's Reset() method (which erroneously called Load(), which called Reset(), which called Load(), which called Reset(), ...).

--- Sega/Mappers/Standard.cs
+++ Sega/Mappers/Standard.cs
@@ -170,7 +170,6 @@

 			// Clear cartridge RAM.
 			this.cartridgeRam = new byte[0x4000];
-			this.Load(new byte[0]);

 			// Write default mapper values.
 			this.WriteMemory(0xFFFC, 0);


Begin implementing fixing Y coordinate for connected paths if they are not really underground

--- SetStationDepthLength.cs
+++ SetStationDepthLength.cs
@@ -86,7 +86,7 @@
             var updatedPaths = new List<BuildingInfo.PathInfo>();
             foreach (var path in info.m_paths)
             {
-                if (path.m_nodes.All(n => n.y < 0) && path != lowestHighPath)
+                if (AllNodesUnderGround(path) && path != lowestHighPath)
                 {
                     DipPath(path, offsetDepthDist);
                 }
@@ -131,11 +131,6 @@
                 newCurveTargets.Add(new Vector3());
             newCurveTargets[0] = GetMiddle(path);
             path.m_curveTargets = newCurveTargets.ToArray();
-        }
-
-        private static Vector3 GetMiddle(BuildingInfo.PathInfo path)
-        {
-            return (path.m_nodes.First() + path.m_nodes.Last()) / 2;
         }

         private static IEnumerable<BuildingInfo.PathInfo> GenerateSteps(BuildingInfo.PathInfo path, float depth)
@@ -202,33 +197,50 @@
             SetCurveTargets(path);
             var newBeginning = path.m_nodes.First();
             var newEnd = path.m_nodes.Last();
-            ChangeConnectedPathsLength(assetPaths, beginning, newBeginning - beginning, processedConnectedPaths);
-            ChangeConnectedPathsLength(assetPaths, end, newEnd - end, processedConnectedPaths);
-
-        }
-
-        private static void ChangeConnectedPathsLength(IList<BuildingInfo.PathInfo> assetPaths, Vector3 nodePoint, Vector3 delta, ICollection<int> processedPaths)
+            ChangeConnectedPaths(assetPaths, beginning, newBeginning - beginning, processedConnectedPaths);
+            ChangeConnectedPaths(assetPaths, end, newEnd - end, processedConnectedPaths);
+
+        }
+
+        private static void ChangeConnectedPaths(IList<BuildingInfo.PathInfo> assetPaths, Vector3 nodePoint, Vector3 delta, ICollection<int> processedConnectedPaths)
         {
             for (var pathIndex = 0; pathIndex < assetPaths.Count; pathIndex++)
             {
                 var path = assetPaths[pathIndex];
-                if (path.m_netInfo == null || path.m_netInfo.IsUndergroundMetroStationTrack())
-                {
-                    processedPaths.Add(pathIndex);
+                if (path?.m_netInfo == null || path.m_netInfo.IsUndergroundMetroStationTrack())
+                {
+                    processedConnectedPaths.Add(pathIndex);
                     continue;
                 }
-                if (processedPaths.Contains(pathIndex) || !path.m_nodes.Where(n => n == nodePoint).Any())
+                if (processedConnectedPaths.Contains(pathIndex) || !path.m_nodes.Where(n => n == nodePoint).Any())
                 {
                     continue;
                 }
                 var beginning = path.m_nodes.First();
                 var end = path.m_nodes.Last();
                 ShiftPath(path, delta);
-                processedPaths.Add(pathIndex);
+                processedConnectedPaths.Add(pathIndex);
+                if (path.m_netInfo.m_netAI.IsUnderground())
+                {
+                    for (var i = 0; i < path.m_nodes.Length; i++)
+                    {
+                        if (!(path.m_nodes[i].y > -12f) || path.m_nodes[i] == nodePoint)
+                        {
+                            continue;
+                        }
+                        path.m_nodes[i] = new Vector3
+                        {
+                            x = path.m_nodes[i].x,
+                            y = -12f,
+                            z = path.m_nodes[i].z
+                        };
+                        SetCurveTargets(path);
+                    }
+                }
                 var newBeginning = path.m_nodes.First();
                 var newEnd = path.m_nodes.Last();
-                ChangeConnectedPathsLength(assetPaths, beginning, newBeginning - beginning, processedPaths);
-                ChangeConnectedPathsLength(assetPaths, end, newEnd - end, processedPaths);
+                ChangeConnectedPaths(assetPaths, beginning, newBeginning - beginning, processedConnectedPaths);
+                ChangeConnectedPaths(assetPaths, end, newEnd - end, processedConnectedPaths);
             }
         }

@@ -253,5 +265,15 @@
             return info.m_paths.Where(p => p.m_nodes.Any(n => pairs.Contains(n)) && p.m_netInfo.IsUndergroundMetroStationTrack())
                     .ToArray();
         }
+
+        private static Vector3 GetMiddle(BuildingInfo.PathInfo path)
+        {
+            return (path.m_nodes.First() + path.m_nodes.Last()) / 2;
+        }
+
+        private static bool AllNodesUnderGround(BuildingInfo.PathInfo path)
+        {
+            return path.m_nodes.All(n => n.y < 0);
+        }
     }
 }