Delete GenericWalker.cs

Delete GenericWalker.cs

--- GenericWalker.cs
+++ GenericWalker.cs
@@ -1,443 +0,0 @@
-//
-//Copyright 2016 David Beales
-//
-//Licensed under the Apache License, Version 2.0 (the "License");
-//you may not use this file except in compliance with the License.
-//You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-//Unless required by applicable law or agreed to in writing, software
-//distributed under the License is distributed on an "AS IS" BASIS,
-//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//See the License for the specific language governing permissions and
-//limitations under the License.
-//
-using System;
-using System.ComponentModel;
-using System.Drawing;
-using System.Text;
-using System.Windows.Forms;
-using System.Reflection;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using APE.Capture;
-using APE.Communication;
-using System.Threading;
-using System.Drawing.Imaging;
-using System.Security.Principal;
-using NM = APE.Native.NativeMethods;
-using System.Collections;
-
-namespace APE.Language
-{
-    /// <summary>
-    /// Automation class used to automate controls derived from the following:
-    /// LatentZero.Capstone.Controls.Walker.WalkerControl
-    /// LzGenericWalker.GenericWalker
-    /// </summary>
-    public sealed class GUIGenericWalker : GUIFocusableObject
-    {
-        /// <summary>
-        /// Constructor used for non-form controls
-        /// </summary>
-        /// <param name="parentForm">The top level form the control belongs to</param>
-        /// <param name="descriptionOfControl">A description of the control which would make sense to a human.
-        /// <para/>This text is used in the logging method.  For example: OK button</param>
-        /// <param name="identParams">One or more identifier object(s) used to locate the control.
-        /// <para/>Normally you would just use the name identifier</param>
-        public GUIGenericWalker(GUIForm parentForm, string descriptionOfControl, params Identifier[] identParams)
-            : base(parentForm, descriptionOfControl, identParams)
-        {
-        }
-
-        /// <summary>
-        /// Gets the number of characters after which the drop down appears for the default search
-        /// </summary>
-        /// <returns>The number of characters</returns>
-        public int GetSearchAfter()
-        {
-            //TODO support prefix .N .D .F etc rather than just the default
-            int after = -1;
-            if (Identity.TypeNameSpace == "LzGenericWalker")
-            {
-                GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
-                GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "Driver", MemberTypes.Property);
-                GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "_m_oWalkerState", MemberTypes.Field);
-                GUI.m_APE.AddQueryMessageReflect(DataStores.Store2, DataStores.Store3, "m_oDefaultSearch", MemberTypes.Field);
-                GUI.m_APE.AddQueryMessageReflect(DataStores.Store3, DataStores.Store4, "After", MemberTypes.Property);
-                GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store4);
-                GUI.m_APE.SendMessages(EventSet.APE);
-                GUI.m_APE.WaitForMessages(EventSet.APE);
-                //Get the value(s) returned MUST be done straight after the WaitForMessages call;
-                after = GUI.m_APE.GetValueFromMessage();
-            }
-            else
-            {
-                GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
-                GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "Driver", MemberTypes.Property);
-                GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "GetType", MemberTypes.Method);
-                GUI.m_APE.AddQueryMessageReflect(DataStores.Store2, DataStores.Store3, "Name", MemberTypes.Property);
-                GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store3);
-                GUI.m_APE.SendMessages(EventSet.APE);
-                GUI.m_APE.WaitForMessages(EventSet.APE);
-                //Get the value(s) returned MUST be done straight after the WaitForMessages call;
-                string name = GUI.m_APE.GetValueFromMessage();
-
-                if (name.Contains("DatabaseWalkerDriver"))
-                {
-                    //DatabaseWalkerDriver
-                    //DynamicFilterDatabaseWalkerDriver
-                    GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "Driver", MemberTypes.Property);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "m_walkerType", MemberTypes.Field);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store2, DataStores.Store3, "DefaultSearch", MemberTypes.Property);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store3, DataStores.Store4, "SearchAfter", MemberTypes.Property);
-                    GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store4);
-                    GUI.m_APE.SendMessages(EventSet.APE);
-                    GUI.m_APE.WaitForMessages(EventSet.APE);
-                    //Get the value(s) returned MUST be done straight after the WaitForMessages call;
-                    after = GUI.m_APE.GetValueFromMessage();
-                }
-                else if (name.Contains("MinervaWalkerDriver"))
-                {
-                    //MinervaWalkerDriverBase
-                    //MinervaWalkerDriverInstrument
-                    GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "Driver", MemberTypes.Property);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "m_state", MemberTypes.Field);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store2, DataStores.Store3, "m_oDefaultSearch", MemberTypes.Field);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store3, DataStores.Store4, "After", MemberTypes.Property);
-                    GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store4);
-                    GUI.m_APE.SendMessages(EventSet.APE);
-                    GUI.m_APE.WaitForMessages(EventSet.APE);
-                    //Get the value(s) returned MUST be done straight after the WaitForMessages call;
-                    dynamic afterOrNull = GUI.m_APE.GetValueFromMessage();
-
-                    if (afterOrNull == null)
-                    {
-                        //Setup the state variable
-                        GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
-                        GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "Driver", MemberTypes.Property);
-                        GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "WalkerType", MemberTypes.Property);
-                        GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store9, "GetWalkerStateFromAPI", MemberTypes.Method, new Parameter(GUI.m_APE, DataStores.Store2), new Parameter(GUI.m_APE, ""), new Parameter(GUI.m_APE, false));
-                        GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store3, "m_state", MemberTypes.Field);
-                        GUI.m_APE.AddQueryMessageReflect(DataStores.Store3, DataStores.Store4, "m_oDefaultSearch", MemberTypes.Field);
-                        GUI.m_APE.AddQueryMessageReflect(DataStores.Store4, DataStores.Store5, "After", MemberTypes.Property);
-                        GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store5);
-                        GUI.m_APE.SendMessages(EventSet.APE);
-                        GUI.m_APE.WaitForMessages(EventSet.APE);
-                        //Get the value(s) returned MUST be done straight after the WaitForMessages call;
-                        after = GUI.m_APE.GetValueFromMessage();
-                    }
-                    else
-                    {
-                        after = afterOrNull;
-                    }
-                }
-                else
-                {
-                    throw new Exception("Unsupported walker type name:" + Name);
-                }
-            }
-
-            return after;
-        }
-
-        /// <summary>
-        /// Sets the text of the generic walker control using the default search
-        /// </summary>
-        /// <param name="text">The text to set the control to</param>
-        public void SetText(string text)
-        {
-            int after = GetSearchAfter();
-            if (after == -1)
-            {
-                throw new Exception("Failed to determine after how many characters the walker dropdown should appear");
-            }
-            SetText(text, after);
-        }
-
-        /// <summary>
-        /// Sets the text of the generic walker control
-        /// </summary>
-        /// <param name="text">The text to set the control to</param>
-        /// <param name="searchAfter">The number of characters after which the drop down appears</param>
-        public void SetText(string text, int searchAfter)
-        {
-            //TODO support prefix .N .D .F etc
-            Stopwatch timer;
-            string currentText;
-
-            Input.Block();
-            try
-            {
-                IntPtr textboxHandle;
-
-                if (Identity.TypeNameSpace == "LzGenericWalker")
-                {
-                    GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "txtText", MemberTypes.Field);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "Handle", MemberTypes.Property);
-                    GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store2);
-                    GUI.m_APE.SendMessages(EventSet.APE);
-                    GUI.m_APE.WaitForMessages(EventSet.APE);
-                    //Get the value(s) returned MUST be done straight after the WaitForMessages call
-                    textboxHandle = GUI.m_APE.GetValueFromMessage();
-                }
-                else
-                {
-                    GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "WalkerTextBox", MemberTypes.Property);
-                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "Handle", MemberTypes.Property);
-                    GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store2);
-                    GUI.m_APE.SendMessages(EventSet.APE);
-                    GUI.m_APE.WaitForMessages(EventSet.APE);
-                    //Get the value(s) returned MUST be done straight after the WaitForMessages call
-                    textboxHandle = GUI.m_APE.GetValueFromMessage();
-                }
-
-                GUITextBox textbox = new GUITextBox(ParentForm, Identity.Description + " textbox", new Identifier(Identifiers.Handle, textboxHandle));
-
-                currentText = textbox.Text;
-
-                if (text == currentText)
-                {
-                    GUI.Log("Ensure " + Identity.Description + " is set to " + text, LogItemType.Action);
-                }
-                else
-                {
-                    if (currentText != "")
-                    {
-                        textbox.SingleClick(MouseButton.Left);
-                        //textbox.MouseDoubleClick(MouseButton.Left);
-
-                        //Select everything in the textbox
-                        base.SendKeys("{HOME}+{END}");
-
-                        string selectedText;
-
-                        //wait for .selectedText to = Text
-                        timer = Stopwatch.StartNew();
-                        while (true)
-                        {
-                            //Get the selectedText property
-                            GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, textboxHandle);
-                            GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "SelectedText", MemberTypes.Property);
-                            GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store1);
-                            GUI.m_APE.SendMessages(EventSet.APE);
-                            GUI.m_APE.WaitForMessages(EventSet.APE);
-                            //Get the value(s) returned MUST be done straight after the WaitForMessages call
-                            selectedText = GUI.m_APE.GetValueFromMessage();
-
-                            if (currentText == selectedText)
-                            {
-                                break;
-                            }
-
-                            if (timer.ElapsedMilliseconds > GUI.m_APE.TimeOut)
-                            {
-                                throw new Exception("Failed to select all the text of the " + Description);
-                            }
-
-                            Thread.Sleep(15);
-                        }
-                    }
-
-                    // Get an array of each character token for example a or {+}
-                    string[] tokens = Tokenise(text);
-                    string unescapedText = Unescape(text);
-
-                    switch (tokens.Length)
-                    {
-                        case 0:
-                            break;
-                        case int tokensLength when tokensLength < searchAfter:
-                            GUI.Log("Type [" + unescapedText.Substring(0, tokensLength) + "] into the " + Identity.Description, LogItemType.Action);
-                            base.SendKeysInternal(string.Join("", tokens));
-                            break;
-                        default:
-                            //Send first <searchAfter> characters
-                            GUI.Log("Type [" + unescapedText.Substring(0, searchAfter) + "] into the " + Identity.Description, LogItemType.Action);
-                            string[] initialTokens = new string[searchAfter];
-                            for (int token = 0; token < searchAfter; token++)
-                            {
-                                initialTokens[token] = tokens[token];
-                                tokens[token] = "";
-                            }
-                            base.SendKeysInternal(string.Join("", initialTokens));
-
-                            //Wait for popup
-                            GUI.Log("Wait for the generic walker popup to appear", LogItemType.Action);
-                            timer = Stopwatch.StartNew();
-                            bool isDropped = false;
-                            while (true)
-                            {
-                                //Get the state of the popup control
-                                if (Identity.TypeNameSpace == "LzGenericWalker")
-                                {
-                                    GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
-                                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "IsDropped", MemberTypes.Property);
-                                    GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store1);
-                                    GUI.m_APE.SendMessages(EventSet.APE);
-                                    GUI.m_APE.WaitForMessages(EventSet.APE);
-                                    //Get the value(s) returned MUST be done straight after the WaitForMessages call
-                                    isDropped = GUI.m_APE.GetValueFromMessage();
-                                }
-                                else
-                                {
-                                    string PopupState;
-                                    GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
-                                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "PopupState", MemberTypes.Property);
-                                    GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "ToString", MemberTypes.Method);
-                                    GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store2);
-                                    GUI.m_APE.SendMessages(EventSet.APE);
-                                    GUI.m_APE.WaitForMessages(EventSet.APE);
-                                    //Get the value(s) returned MUST be done straight after the WaitForMessages call
-                                    PopupState = GUI.m_APE.GetValueFromMessage();
-                                    if (PopupState == "Open")
-                                    {
-                                        isDropped = true;
-                                    }
-                                }
-
-                                if (isDropped)
-                                {
-                                    if (Identity.TypeNameSpace == "LzGenericWalker")
-                                    {
-                                        WaitForTimer("tmrResize");
-                                    }
-                                    break;
-                                }
-
-                                if (timer.ElapsedMilliseconds > GUI.m_APE.TimeOut)
-                                {
-                                    throw new Exception("Failed to find the " + Description + " dropdown");
-                                }
-
-                                Thread.Sleep(15);
-                            }
-
-                            //Send rest of characters
-                            if (tokens.Length > searchAfter)
-                            {
-                                GUI.Log("Type [" + unescapedText.Substring(searchAfter) + "] into the " + Identity.Description, LogItemType.Action);
-                                base.SendKeysInternal(string.Join("", tokens));
-                            }
-                            break;
-                    }
-
-                    //wait for .Text to == text
-                    timer = Stopwatch.StartNew();
-                    while (true)
-                    {
-                        currentText = textbox.Text;
-
-                        if (currentText == unescapedText)
-                        {
-                            break;
-                        }
-
-                        if (timer.ElapsedMilliseconds > GUI.m_APE.TimeOut)
-                        {
-                            throw new Exception("Failed to set the text of the " + Description);
-                        }
-
-                        Thread.Sleep(15);
-                    }
-
-                    GUI.Log("Press Enter to set the value", LogItemType.Action);
-                    base.SendKeysInternal("{Enter}");
-
-                    if (Identity.TypeNameSpace == "LzGenericWalker")
-                    {
-                        WaitForTimer("tmrDelayedEvent");
-                    }
-                }
-            }
-            finally
-            {
-                Input.Unblock();
-            }
-        }
-
-        private void WaitForTimer(string timerName)
-        {
-            Stopwatch timer = Stopwatch.StartNew();
-            while (true)
-            {
-                // Wait for the tmrDelayedEvent to be disabled
-                GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
-                GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, timerName, MemberTypes.Field);
-                GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "Enabled", MemberTypes.Property);
-                GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store2);
-                GUI.m_APE.SendMessages(EventSet.APE);
-                GUI.m_APE.WaitForMessages(EventSet.APE);
-                //Get the value(s) returned MUST be done straight after the WaitForMessages call
-                bool timerEnabled = GUI.m_APE.GetValueFromMessage();
-
-                if (!timerEnabled)
-                {
-                    GUI.WaitForInputIdle(this);
-                    break;
-                }
-
-                if (timer.ElapsedMilliseconds > GUI.m_APE.TimeOut)
-                {
-                    throw new Exception(timerName + " failed to become disabled for the " + Description);
-                }
-
-                Thread.Sleep(15);
-            }
-        }
-
-        private string[] Tokenise(string escapedText)
-        {
-            ArrayList tokens = new ArrayList(escapedText.Length);
-            string character;
-            for (int characterIndex = 0; characterIndex < escapedText.Length; characterIndex++)
-            {
-                if (escapedText.Substring(characterIndex, 1) == "{")
-                {
-                    if (escapedText.Substring(characterIndex + 1, 1) == "}")
-                    {
-                        character = escapedText.Substring(characterIndex, 3);
-                        characterIndex = characterIndex + 2;
-                    }
-                    else
-                    {
-                        int endIndex = escapedText.IndexOf("}", characterIndex);
-                        character = escapedText.Substring(characterIndex, endIndex - characterIndex + 1);
-                        characterIndex = endIndex;
-                    }
-                }
-                else
-                {
-                    character = escapedText.Substring(characterIndex, 1);
-                }
-
-                tokens.Add(character);
-            }
-
-            tokens.TrimToSize();
-            return (string[])tokens.ToArray(typeof(string));
-        }
-
-        private string Unescape(string escapedText)
-        {
-            string unescapedText = escapedText;
-            unescapedText = unescapedText.Replace("{{}", "{");
-            unescapedText = unescapedText.Replace("{}}", "}");
-            unescapedText = unescapedText.Replace("{(}", "(");
-            unescapedText = unescapedText.Replace("{)}", ")");
-            unescapedText = unescapedText.Replace("{{}", "{");
-            unescapedText = unescapedText.Replace("{+}", "+");
-            unescapedText = unescapedText.Replace("{^}", "^");
-            unescapedText = unescapedText.Replace("{%}", "%");
-            unescapedText = unescapedText.Replace("{~}", "~");
-            unescapedText = unescapedText.Replace("{[}", "[");
-            unescapedText = unescapedText.Replace("{]}", "]");
-            return unescapedText;
-        }
-    }
-}


Correctly match options that begins with numbers (eg '[[00_00]]').

--- YarnParser/Lexer.cs
+++ YarnParser/Lexer.cs
@@ -122,6 +122,11 @@
 			// So, we need to mark certain rules as "this token can start a line"

 			public bool canBeginLine;
+
+			public override string ToString ()
+			{
+				return string.Format ("TokenRule: {0}", type.ToString());
+			}
 		}

 		// The list of all known token types
@@ -165,12 +170,8 @@

 			// Set up a regex if we have a rule for it
 			if (rule != null) {
-				// We add a ^ at the start of the regex to ensure that the rule matches
-				// against the start of the text we're trying to evaluate -
-				// this prevents rules from matching further into the line
-				// (ie a token rule that looks for "+" should not find it in
-				// the string "1 + 2" but it should find it in "+ 2"
-				newTokenRule.regex = new Regex("^"+rule);
+
+				newTokenRule.regex = new Regex(rule);
 			}

 			newTokenRule.canBeginLine = canBeginLine;
@@ -264,11 +265,11 @@
 			}

 			// Keeps track of how much of the line we have left to parse
-			var remainingString = input;
-
-			int columnNumber = 0;
+
+			int columnNumber = lineIndentation;
 			// Consume the string
-			while (remainingString.Length > 0) {
+
+			while (columnNumber < input.Length) {

 				// Keep track of whether we successfully found a rule to parse the next token
 				var matched = false;
@@ -276,8 +277,13 @@
 				foreach (var tokenRule in tokenRules) {

 					// Is the next chunk of text a token?
-					if (tokenRule.regex != null &&
-					    tokenRule.regex.IsMatch(remainingString)) {
+					if (tokenRule.regex != null) {
+
+						// Get more detailed info
+						var match = tokenRule.regex.Match(input, columnNumber);
+
+						if (match.Success == false || match.Index > columnNumber)
+							continue;

 						// Bail out if this is the first token and we aren't allowed to
 						// match this rule at the start
@@ -285,8 +291,7 @@
 							continue;
 						}

-						// Get more detailed info
-						var match = tokenRule.regex.Match(remainingString);
+

 						// Record the token only if we care
@@ -314,12 +319,10 @@
 						// Update the column number
 						columnNumber += match.Length;

-						// Discard these characters - we're moving on
-						remainingString = remainingString.Remove(0, match.Length);
-
+
 						// Record that we successfully found a type for this token
 						matched = true;
-
+
 						// We've matched a token type, stop trying to
 						// match it against others
 						break;
@@ -364,7 +367,7 @@
 				.discard = true;

 			// Basic syntax
-			AddTokenRule(TokenType.Number, "(\\d+\\.\\d*|\\d+)");
+			AddTokenRule(TokenType.Number, "((?<!\\[\\[)\\d+)");
 			AddTokenRule(TokenType.BeginCommand, "\\<\\<", canBeginLine:true);
 			AddTokenRule(TokenType.EndCommand, "\\>\\>");
 			AddTokenRule(TokenType.Variable, "\\$[A-z]+");
@@ -414,7 +417,7 @@
 			// Free text - match anything except command or option syntax
 			// This always goes last so that anything else will preferably
 			// match it
-			AddTokenRule(TokenType.Text, "^[^\\<\\>\\[\\]\\|]*", canBeginLine:true);
+			AddTokenRule(TokenType.Text, "[^\\<\\>\\[\\]\\|]*", canBeginLine:true);
 		}
 	}


dont bother checking further if server count wrong

--- test/Rafty.UnitTests/LeaderTests.cs
+++ test/Rafty.UnitTests/LeaderTests.cs
@@ -175,17 +175,22 @@

             bool TestPeerStates()
             {
-                var passed = 0;
+                var correctState = 0;
+
+                if(leader.PeerStates.Count != 4)
+                {
+                    return false;
+                }

                 leader.PeerStates.ForEach(pS =>
                 {
                     if(leader.PeerStates.Count == 4 && pS.NextIndex.NextLogIndexToSendToPeer == 1 && pS.MatchIndex.IndexOfHighestKnownReplicatedLog == 0)
                     {
-                        passed++;
-                    }
-                });
-
-                return passed == leader.PeerStates.Count;
+                        correctState++;
+                    }
+                });
+
+                return correctState == leader.PeerStates.Count;
             }

             var result = WaitFor(1000).Until(() => TestPeerStates());


New internal release version 1.0.30-alpha.

--- SharedAssemblyInfo.cs
+++ SharedAssemblyInfo.cs
@@ -11,5 +11,5 @@

 [assembly: ComVisible(false)]

-[assembly: AssemblyVersion("1.0.29.0")]
-[assembly: AssemblyFileVersion("1.0.29.0")]
+[assembly: AssemblyVersion("1.0.30.0")]
+[assembly: AssemblyFileVersion("1.0.30.0")]


add: DeviceInfo#ctorに例外処理を追加

add: DeviceInfo#ctorに例外処理を追加

--- Sharp98/DeviceInfo.cs
+++ Sharp98/DeviceInfo.cs
@@ -60,6 +60,15 @@

         public DeviceInfo(DeviceType type, uint clock, PanFlag pan)
         {
+            if (!Enum.IsDefined(typeof(DeviceType), type))
+                throw new ArgumentOutOfRangeException(nameof(type));
+
+            if (clock == 0)
+                throw new ArgumentOutOfRangeException(nameof(clock));
+
+            if (!Enum.IsDefined(typeof(PanFlag), pan))
+                throw new ArgumentOutOfRangeException(nameof(pan));
+
             this.type = type;
             this.clock = clock;
             this.pan = pan;


Update Exercise8C.cs

Update Exercise8C.cs

--- Sheet-8/Exercise8C.cs
+++ Sheet-8/Exercise8C.cs
@@ -1 +1,23 @@
+using System;

+namespace Exercise8C
+{
+	class MainClass
+	{
+		public static void Main (string[] args)
+		{
+			Console.WriteLine ("Please enter your first name: ");
+			String firstName = Console.ReadLine ();
+
+			Console.WriteLine ("Please enter your last name: ");
+			String lastName = Console.ReadLine ();
+
+			String firstNameTrim = firstName.Substring(1, 2).ToUpper();
+			String lastNameTrim = lastName.Substring(1, 2);
+
+			String trim = firstNameTrim + lastNameTrim;
+
+			Console.WriteLine (trim);
+		}
+	}
+}


Fix tests

Fix tests

--- Source/Tests/Mocks.cs
+++ Source/Tests/Mocks.cs
@@ -224,9 +224,9 @@
 			{
 				_roomEvents = new Mock<IRoomEvents> ();
 				_roomEvents.Setup(r => r.OnAfterFadeIn).Returns(new Mock<IEvent> ().Object);
-				_roomEvents.Setup(r => r.OnAfterFadeOut).Returns(new Mock<IEvent> ().Object);
-				_roomEvents.Setup(r => r.OnBeforeFadeIn).Returns(new Mock<IEvent> ().Object);
-				_roomEvents.Setup(r => r.OnBeforeFadeOut).Returns(new Mock<IEvent> ().Object);
+				_roomEvents.Setup(r => r.OnAfterFadeOut).Returns(new Mock<IBlockingEvent> ().Object);
+				_roomEvents.Setup(r => r.OnBeforeFadeIn).Returns(new Mock<IBlockingEvent> ().Object);
+				_roomEvents.Setup(r => r.OnBeforeFadeOut).Returns(new Mock<IBlockingEvent> ().Object);
 			}
 			return _roomEvents;
 		}


Extract the SelectImpl method

Extract the SelectImpl method

This removed the duplicated codes.

--- Src/Albedo/Methods.cs
+++ Src/Albedo/Methods.cs
@@ -79,29 +79,8 @@
         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "The expression is strongly typed in order to prevent the caller from passing any sort of expression. It doesn't fully capture everything the caller might throw at it, but it does constrain the caller as well as possible. This enables the developer to get a compile-time exception instead of a run-time exception in most cases where an invalid expression is being supplied.")]
         public MethodInfo Select(
             Expression<Action<T>> methodSelector)
-        {
-            if (methodSelector == null)
-                throw new ArgumentNullException("methodSelector");
-
-            var methodCallExp = methodSelector.Body as MethodCallExpression;
-            if (methodCallExp == null)
-                throw new ArgumentException("The expression's body must be a MethodCallExpression. The code block supplied should invoke a method.\nExample: x => x.Foo().", "methodSelector");
-
-            var method = methodCallExp.Method;
-            if (method.ReflectedType == typeof(T))
-                return method;
-
-            if (method.IsGenericMethod)
-            {
-                return methodCallExp.Object.Type.GetMethod(
-                    method.Name,
-                    method.GetGenericMethodDefinition().GetParameters().Select(x => x.ParameterType).ToArray())
-                .MakeGenericMethod(method.GetGenericArguments());
-            }
-
-            return methodCallExp.Object.Type.GetMethod(
-                method.Name,
-                method.GetParameters().Select(x => x.ParameterType).ToArray());
+        {
+            return SelectImpl(methodSelector);
         }

         /// <summary>
@@ -153,30 +132,41 @@
         /// <seealso cref="Methods{T}" />
         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "The expression is strongly typed in order to prevent the caller from passing any sort of expression. It doesn't fully capture everything the caller might throw at it, but it does constrain the caller as well as possible. This enables the developer to get a compile-time exception instead of a run-time exception in most cases where an invalid expression is being supplied.")]
         public MethodInfo Select<TResult>(
-            Expression<Func<T, TResult>> methodSelector)
-        {
-            if (methodSelector == null)
-                throw new ArgumentNullException("methodSelector");
-
-            var methodCallExp = methodSelector.Body as MethodCallExpression;
-            if (methodCallExp == null)
-                throw new ArgumentException("The expression's body must be a MethodCallExpression. The code block supplied should invoke a method.\nExample: x => x.Foo().", "methodSelector");
-
+            Expression<Func<T, TResult>> methodSelector)
+        {
+            return SelectImpl(methodSelector);
+        }
+
+        private static MethodInfo SelectImpl<TFunc>(Expression<TFunc> methodSelector)
+        {
+            if (methodSelector == null)
+            {
+                throw new ArgumentNullException("methodSelector");
+            }
+
+            var methodCallExp = methodSelector.Body as MethodCallExpression;
+            if (methodCallExp == null)
+            {
+                throw new ArgumentException("The expression's body must be a MethodCallExpression. The code block supplied should invoke a method.\nExample: x => x.Foo().", "methodSelector");
+            }
+
             var method = methodCallExp.Method;
             if (method.ReflectedType == typeof(T))
+            {
                 return method;
+            }

             if (method.IsGenericMethod)
             {
                 return methodCallExp.Object.Type.GetMethod(
                     method.Name,
                     method.GetGenericMethodDefinition().GetParameters().Select(x => x.ParameterType).ToArray())
-                .MakeGenericMethod(method.GetGenericArguments());
+                    .MakeGenericMethod(method.GetGenericArguments());
             }

             return methodCallExp.Object.Type.GetMethod(
                 method.Name,
-                method.GetParameters().Select(x => x.ParameterType).ToArray());
-        }
+                method.GetParameters().Select(x => x.ParameterType).ToArray());
+        }
     }
 }


Added Bind and Unbind commands to Tapeti.Cmd

--- Tapeti.Cmd/Program.cs
+++ Tapeti.Cmd/Program.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
@@ -153,7 +154,7 @@
         [Verb("removequeue", HelpText = "Removes a durable queue.")]
         public class RemoveQueueOptions : CommonOptions
         {
-            [Option('q', "queue", Required = true, HelpText = "The name of the queue to declare.")]
+            [Option('q', "queue", Required = true, HelpText = "The name of the queue to remove.")]
             public string QueueName { get; set; }

             [Option("confirm", HelpText = "Confirms the removal of the specified queue. If not provided, an interactive prompt will ask for confirmation.", Default = false)]
@@ -164,10 +165,32 @@
         }

+        [Verb("bindqueue", HelpText = "Add a binding to a queue.")]
+        public class BindQueueOptions : CommonOptions
+        {
+            [Option('q', "queue", Required = true, HelpText = "The name of the queue to add the binding(s) to.")]
+            public string QueueName { get; set; }
+
+            [Option('b', "bindings", Required = false, HelpText = "One or more bindings to add to the queue. Format: <exchange>:<routingKey>")]
+            public IEnumerable<string> Bindings { get; set; }
+        }
+
+
+        [Verb("unbindqueue", HelpText = "Remove a binding from a queue.")]
+        public class UnbindQueueOptions : CommonOptions
+        {
+            [Option('q', "queue", Required = true, HelpText = "The name of the queue to remove the binding(s) from.")]
+            public string QueueName { get; set; }
+
+            [Option('b', "bindings", Required = false, HelpText = "One or more bindings to remove from the queue. Format: <exchange>:<routingKey>")]
+            public IEnumerable<string> Bindings { get; set; }
+        }
+

         public static int Main(string[] args)
         {
-            return Parser.Default.ParseArguments<ExportOptions, ImportOptions, ShovelOptions, PurgeOptions, ExampleOptions, DeclareQueueOptions, RemoveQueueOptions>(args)
+            return Parser.Default.ParseArguments<ExportOptions, ImportOptions, ShovelOptions, PurgeOptions, ExampleOptions,
+                    DeclareQueueOptions, RemoveQueueOptions, BindQueueOptions, UnbindQueueOptions>(args)
                 .MapResult(
                     (ExportOptions o) => ExecuteVerb(o, RunExport),
                     (ImportOptions o) => ExecuteVerb(o, RunImport),
@@ -176,6 +199,8 @@
                     (PurgeOptions o) => ExecuteVerb(o, RunPurge),
                     (DeclareQueueOptions o) => ExecuteVerb(o, RunDeclareQueue),
                     (RemoveQueueOptions o) => ExecuteVerb(o, RunRemoveQueue),
+                    (BindQueueOptions o) => ExecuteVerb(o, RunBindQueue),
+                    (UnbindQueueOptions o) => ExecuteVerb(o, RunUnbindQueue),
                     errs =>
                     {
                         if (!Debugger.IsAttached)
@@ -465,16 +490,7 @@
         private static void RunDeclareQueue(DeclareQueueOptions options)
         {
             // Parse early to fail early
-            var bindings = options.Bindings
-                .Select(b =>
-                {
-                    var parts = b.Split(':');
-                    if (parts.Length != 2)
-                        throw new InvalidOperationException($"Invalid binding format: {b}");
-
-                    return new Tuple<string, string>(parts[0], parts[1]);
-                })
-                .ToArray();
+            var bindings = ParseBindings(options.Bindings);

             using (var connection = GetConnection(options))
             using (var channel = connection.CreateModel())
@@ -537,5 +553,51 @@
                 ? $"Empty or non-existent queue '{options.QueueName}' removed."
                 : $"{messageCount} message{(messageCount != 1 ? "s" : "")} purged while removing '{options.QueueName}'.");
         }
+
+
+        private static void RunBindQueue(BindQueueOptions options)
+        {
+            var bindings = ParseBindings(options.Bindings);
+
+            using (var connection = GetConnection(options))
+            using (var channel = connection.CreateModel())
+            {
+                foreach (var (exchange, routingKey) in bindings)
+                    channel.QueueBind(options.QueueName, exchange, routingKey);
+            }
+
+            Console.WriteLine($"{bindings.Length} binding{(bindings.Length != 1 ? "s" : "")} added to queue {options.QueueName}.");
+        }
+
+
+        private static void RunUnbindQueue(UnbindQueueOptions options)
+        {
+            var bindings = ParseBindings(options.Bindings);
+
+            using (var connection = GetConnection(options))
+            using (var channel = connection.CreateModel())
+            {
+                foreach (var (exchange, routingKey) in bindings)
+                    channel.QueueUnbind(options.QueueName, exchange, routingKey);
+            }
+
+            Console.WriteLine($"{bindings.Length} binding{(bindings.Length != 1 ? "s" : "")} removed from queue {options.QueueName}.");
+        }
+
+
+
+        private static Tuple<string, string>[] ParseBindings(IEnumerable<string> bindings)
+        {
+            return bindings
+                .Select(b =>
+                {
+                    var parts = b.Split(':');
+                    if (parts.Length != 2)
+                        throw new InvalidOperationException($"Invalid binding format: {b}");
+
+                    return new Tuple<string, string>(parts[0], parts[1]);
+                })
+                .ToArray();
+        }
     }
 }


Small cleansing

Small cleansing

--- UniLib/FieldAction.cs
+++ UniLib/FieldAction.cs
@@ -45,7 +45,7 @@
         }

         /// <summary>
-        /// To string method.
+        /// ToString method.
         /// </summary>
         /// <returns></returns>
         public override string ToString()
@@ -55,32 +55,18 @@
                 return String.Empty;
             }

-            return (NewSize > 0) ?
-                TableName + "." + FieldName + " -> " + NewState.ToString() + "(" + NewSize + ")" :
-                TableName + "." + FieldName + " -> " + NewState.ToString();
+            return String.Format((NewSize > 0) ? "{0}.{1} -> {2}({3})" : "{0}.{1} -> {2}",
+                TableName, FieldName, NewState.ToString(), NewSize);
         }

-//        static private Regex _SplitLines = new Regex(@"
-//(#[^\r\n]*[\r\n]+)*                                    # ignore comment lines
-//(?<Line>.)",
-//            RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
-//        static private Regex _ParseLine = new Regex(
-//@"(#[^\r\n]*[\r\n]+)*\s*                               # ignore comment lines starting from #
-//(?<TableName>[a-zA-Z0-9_]+)                            # the table name
-//\s*\.\s*                                               # the dot between table and field name and ignores whitespace
-//(?<FieldName>[a-zA-Z0-9_]+)                            # the field name
-//\s*->\s*                                               # the arrow sign
-//(?<NewState>(Unicode)|(Ansi))\s*                       # Unicode or Ansi
-//(\(\s*(?<NewSize>[0-9]+)\)\s*)?                        # the new size",
-
         static private Regex _ParseLine = new Regex(
-            @"(\#[^\r\n]*[\r\n]+)*\s*          # ignore comment lines starting from #
-            (?<TableName>[a-zA-Z0-9_]+)        # the table name
+            @"(\#[^\r\n]*[\r\n]+)*\s*          # ignore comment lines starting from # and ending with newline
+            (?<TableName>[a-zA-Z0-9_]+)        # matches table name
             \s*\.\s*                           # the dot between table and field name and ignores whitespace
-            (?<FieldName>[a-zA-Z0-9_]+)        # the field name
+            (?<FieldName>[a-zA-Z0-9_]+)        # matches the field name
             \s*->\s*                           # the arrow sign
-            (?<NewState>(Unicode)|(Ansi))\s*   # Unicode or Ansi
-            (\(\s*(?<NewSize>[0-9]+)\)\s*)?    # the new size",
+            (?<NewState>(Unicode)|(Ansi))\s*   # Matches state: Unicode or Ansi
+            (\(\s*(?<NewSize>[0-9]+)\)\s*)?    # the new size, if present",
             RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);

         /// <summary>


use single version fetcher thread by default.
do not ignore branched files, bcause them can hold only valid content

git-svn-id: 01ac0d183c104cf54ce39ed9b1391f103af87890@22398 01c7c80d-d356-5740-a48b-b9b5f862b89e

--- VssVersionsBuilder.cs
+++ VssVersionsBuilder.cs
@@ -76,7 +76,7 @@
 			using(var wr = File.CreateText(DataFileName))
 			using(var log = File.CreateText(LogFileName))
 			{
-				Split(files, 5)
+				Split(files, opts.VersionFetchThreads)
 					.Select(slice => BuildListAsync(opts, threadIndex++, slice, log, r => {
 						lock(lockHandle)
 						{
@@ -96,7 +96,7 @@
 			Console.WriteLine("Build files versions list complete. Take: {0}", stopWatch.Elapsed);
 		}

-		Thread BuildListAsync(Options opts, int index, List<string> files, StreamWriter log, Action<List<FileRevision>> result)
+		Thread BuildListAsync(Options opts, int index, ICollection<string> files, TextWriter log, Action<List<FileRevision>> result)
 		{
 			var t = new Thread(delegate(object state) {

@@ -109,11 +109,11 @@
 					try{
 						IVSSItem item = db.VSSItem[spec];

-						Console.WriteLine("[{0}] [{1:D5}/{2:D5}] {3}", index, ++findex, files.Count, item.Spec);
+						Console.WriteLine("[{0}] [{1,5}/{2,5}] {3}", (char)('a' + index), ++findex, files.Count, item.Spec);

 						foreach (IVSSVersion ver in item.Versions)
 						{
-							if(ver.Action.StartsWith("Labeled ") || ver.Action.StartsWith("Branched "))
+							if(ver.Action.StartsWith("Labeled "))
 								continue;

 							if(!ver.Action.StartsWith("Checked in ") && !ver.Action.StartsWith("Created ") && !ver.Action.StartsWith("Archived ") && !ver.Action.StartsWith("Rollback to"))
@@ -128,7 +128,7 @@
 							if(opts.UserMappings.TryGetValue(user, out u))
 								user = u;

-							revisions.Add(new FileRevision { FileSpec = item.Spec, At = ver.Date.ToUniversalTime(), Comment = ver.Comment, VssVersion = ver.VersionNumber, User = user, Physical = item.Physical });
+							revisions.Add(new FileRevision { FileSpec = item.Spec, At = ver.Date.ToUniversalTime(), Comment = ver.Comment, VssVersion = ver.VersionNumber, User = user, Physical = ver.VSSItem.Physical });
 						}
 					}
 					catch(Exception ex)


Fix unit tests

Fix unit tests

--- .Src/Extend.Testing/Utilities/Tree/TreeNodeTest.cs
+++ .Src/Extend.Testing/Utilities/Tree/TreeNodeTest.cs
@@ -1470,7 +1470,7 @@
         {
             var target = new TreeNode<String>( "1" );
             var actual = target.ToString();
-            Assert.AreEqual( "Depth: 0 - Value: 1, Children: 0, Parent: [[NULL]]", actual );
+            Assert.AreEqual( "[Depth: 0 - Value: '1', Children: 0]", actual );
         }

         [Test]
@@ -1480,8 +1480,7 @@
             var node = new TreeNode<String>( "a" );
             target.Add( node );
             var actual = node.ToString();
-            Assert.AreEqual( "Depth: 1 - Value: a, Children: 0, Parent: [Depth: 0 - Value: 1, Children: 3, Parent: [[NULL]]]",
-                             actual );
+            Assert.AreEqual( "    [Depth: 1 - Value: 'a', Children: 0]", actual );
         }

         [Test]


Fix: TileableComponent now loads scale properly on initialize.

--- Framework/Tiles/TileableComponent.cs
+++ Framework/Tiles/TileableComponent.cs
@@ -225,6 +225,7 @@
         /// <inheritdoc/>
         protected override void Initialize() {
             this.TransformChanged += this.Self_TransformChanged;
+            this._worldGrid.Reset();
             this.ResetBoundingArea();
             this.ResetTileBoundingAreas();
             this.ResetMinimumTile();


Making CloneTests pass on computers in different time zones.

--- GitTfsTest/Integration/CloneTests.cs
+++ GitTfsTest/Integration/CloneTests.cs
@@ -1,10 +1,12 @@
 using System;
-using System.IO;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using Sep.Git.Tfs.Core.TfsInterop;

 namespace Sep.Git.Tfs.Test.Integration
 {
+    //NOTE: All timestamps in these tests must specify a time zone. If they don't, the local time zone will be used in the DateTime,
+    //      but the commit timestamp will use the ToUniversalTime() version of the DateTime.
+    //      This will cause the hashes to differ on computers in different time zones.
     [TestClass]
     public class CloneTests
     {
@@ -32,7 +34,7 @@
         {
             h.SetupFake(r =>
             {
-                r.Changeset(1, "Project created from template", DateTime.Parse("2012-01-01 12:12:12"))
+                r.Changeset(1, "Project created from template", DateTime.Parse("2012-01-01 12:12:12 -05:00"))
                     .Change(TfsChangeType.Add, TfsItemType.Folder, "$/MyProject");
             });
             h.Run("clone", h.TfsUrl, "$/MyProject");
@@ -49,9 +51,9 @@
         {
             h.SetupFake(r =>
             {
-                r.Changeset(1, "Project created from template", DateTime.Parse("2012-01-01 12:12:12"))
+                r.Changeset(1, "Project created from template", DateTime.Parse("2012-01-01 12:12:12 -05:00"))
                     .Change(TfsChangeType.Add, TfsItemType.Folder, "$/MyProject");
-                r.Changeset(2, "First commit", DateTime.Parse("2012-01-02 12:12:12"))
+                r.Changeset(2, "First commit", DateTime.Parse("2012-01-02 12:12:12 -05:00"))
                     .Change(TfsChangeType.Add, TfsItemType.Folder, "$/MyProject/Folder")
                     .Change(TfsChangeType.Add, TfsItemType.File, "$/MyProject/Folder/File.txt", "File contents")
                     .Change(TfsChangeType.Add, TfsItemType.File, "$/MyProject/README", "tldr");


Renamed Browser to BrowserUI in the NotificationIcon.

--- NotificationWebView.ChromiumUI/NotificationIcon.xaml.cs
+++ NotificationWebView.ChromiumUI/NotificationIcon.xaml.cs
@@ -19,22 +19,22 @@
 	/// </summary>
 	public partial class NotificationIcon : ResourceDictionary
 	{
-		public MainWindow Browser { get; set; }
+		public MainWindow BrowserUI { get; set; }

 		public NotificationIcon()
 		{
-			Browser = new MainWindow();
+			BrowserUI = new MainWindow();
 		}

 		public void ToggleBrowser()
 		{
-			if(!Browser.IsVisible)
+			if(!BrowserUI.IsVisible)
 			{
-				Browser.SlideUp();
+				BrowserUI.SlideUp();
 			}
 			else
 			{
-				Browser.SlideDown();
+				BrowserUI.SlideDown();
 			}
 		}


Updating tests to stop using obsolete method

--- Octokit.Tests/Reactive/ObservableReleasesClientTests.cs
+++ Octokit.Tests/Reactive/ObservableReleasesClientTests.cs
@@ -105,7 +105,7 @@

                 releasesClient.Edit("fake", "repo", 1, data);

-                gitHubClient.Release.Received(1).Edit("fake", "repo", 1, data);
+                gitHubClient.Repository.Release.Received(1).Edit("fake", "repo", 1, data);
             }

             [Fact]
@@ -132,7 +132,7 @@

                 client.Delete("fake", "repo", 1);

-                gitHubClient.Release.Received(1).Delete("fake", "repo", 1);
+                gitHubClient.Repository.Release.Received(1).Delete("fake", "repo", 1);
             }

             [Fact]
@@ -186,7 +186,7 @@

                 releasesClient.UploadAsset(release, upload);

-                gitHubClient.Release.Received(1).UploadAsset(release, upload);
+                gitHubClient.Repository.Release.Received(1).UploadAsset(release, upload);
             }

             [Fact]
@@ -212,7 +212,7 @@

                 client.GetAsset("fake", "repo", 1);

-                gitHubClient.Release.Received(1).GetAsset("fake", "repo", 1);
+                gitHubClient.Repository.Release.Received(1).GetAsset("fake", "repo", 1);
             }

             [Fact]
@@ -238,7 +238,7 @@

                 client.EditAsset("fake", "repo", 1, data);

-                gitHubClient.Release.Received(1).EditAsset("fake", "repo", 1, data);
+                gitHubClient.Repository.Release.Received(1).EditAsset("fake", "repo", 1, data);
             }

             [Fact]


Simplify naming

Simplify naming

--- Gui/GUIWidget.cs
+++ Gui/GUIWidget.cs
@@ -3296,7 +3296,11 @@
 			return one.TabIndex.CompareTo(two.TabIndex);
 		}

-		private void AddAllTabStopsRecursive(List<GuiWidget> allWidgetsThatAreTabStops)
+		/// <summary>
+		/// Gets all active descendants marked as TabStops
+		/// </summary>
+		/// <param name="tabStops">The list to populate</param>
+		private void ActiveTabStops(List<GuiWidget> tabStops)
 		{
 			foreach (GuiWidget child in Children)
 			{
@@ -3304,13 +3308,13 @@
 					&& child.Selectable
 					&& child.Enabled)
 				{
-					child.AddAllTabStopsRecursive(allWidgetsThatAreTabStops);
-				}
-			}
-
-			if (TabStop)
-			{
-				allWidgetsThatAreTabStops.Add(this);
+					child.ActiveTabStops(tabStops);
+				}
+			}
+
+			if (this.TabStop)
+			{
+				tabStops.Add(this);
 			}
 		}

@@ -3318,7 +3322,6 @@
 		{
 			if (Parent != null)
 			{
-				var allWidgetsThatAreTabStops = new List<GuiWidget>();

 				GuiWidget topParent = Parent;
 				while (topParent != null && topParent.Parent != null)
@@ -3326,23 +3329,24 @@
 					topParent = topParent.Parent;
 				}

-				topParent.AddAllTabStopsRecursive(allWidgetsThatAreTabStops);
-
-				if (allWidgetsThatAreTabStops.Count > 0)
-				{
-					allWidgetsThatAreTabStops.Sort(SortOnTabIndex);
-
-					int currentIndex = allWidgetsThatAreTabStops.IndexOf(this);
-					int nextIndex = (currentIndex + andvanceAmount) % allWidgetsThatAreTabStops.Count;
+				var tabStops = new List<GuiWidget>();
+				topParent.ActiveTabStops(tabStops);
+
+				if (tabStops.Count > 0)
+				{
+					tabStops.Sort(SortOnTabIndex);
+
+					int currentIndex = tabStops.IndexOf(this);
+					int nextIndex = (currentIndex + andvanceAmount) % tabStops.Count;
 					if (nextIndex < 0)
 					{
-						nextIndex += allWidgetsThatAreTabStops.Count;
+						nextIndex += tabStops.Count;
 					}

 					if (currentIndex != nextIndex)
 					{
-						allWidgetsThatAreTabStops[nextIndex].Focus();
-						allWidgetsThatAreTabStops[nextIndex].OnKeyDown(new KeyEventArgs(Keys.A | Keys.Control));
+						tabStops[nextIndex].Focus();
+						tabStops[nextIndex].OnKeyDown(new KeyEventArgs(Keys.A | Keys.Control));
 					}
 				}
 			}


task scheduler

task scheduler

--- Antd/Views/page-scheduler.cshtml
+++ Antd/Views/page-scheduler.cshtml
@@ -32,32 +32,156 @@
 @{Layout = "_layout.cshtml";}

 @section MainContent {
+    @functions{
+        public string[] DaysOfTheWeek = new string[] {
+            "Monday",
+	        "Tuesday",
+	        "Wednesday",
+	        "Thursday",
+	        "Friday",
+	        "Saturday",
+	        "Sunday"
+        };
+
+        public string[] MonthsOfTheYear = new string[] {
+            "January",
+            "February",
+            "March",
+            "April",
+            "May",
+            "June",
+            "July",
+            "August",
+            "September",
+            "October",
+            "November",
+            "December"
+        };
+
+        public string GetMonthNumber(string month) {
+            int index = Array.IndexOf(MonthsOfTheYear, month);
+            return (index + 1).ToString();
+        }
+    }
+
     <form action="/jobs" method="POST" enctype="multipart/form-data">
-

-

-

-                    Job
+

+

+

+                    Job Alias
+

+

                     <input type="text" name="Alias">

-

+

+

+

                     Command
+

+

                     <input type="text" name="Command">

-

+

+

+

                     Arguments
+

+

                     <input type="text" name="Arguments">

-

-                    Interval
-                    <input type="number" name="Interval">
-

-

+

+

+

+                    Start Time
+

+

+                    <select id="CronStartTimeHour">
+                        @for (int i = 0; i < 24; i++) {
+                            <option value="@i.ToString()" >@i.ToString() </option>
+                        }
+                    </select>
+                    <select id="CronStartTimeMinute">
+                        @for (int i = 0; i < 60; i++) {
+                            <option value="@i.ToString()" >@i.ToString() </option>
+                        }
+                    </select>
+

+

+

+

+                    Minutes
+

+

+
Every

+                    <input id="CronMinutes" type="text" />
+
minute(s)

+

+

+

+

+                    Hours
+

+

+
Every

+                    <input id="CronHours" type="text" />
+
hour(s)

+

+

+

+

+                    Select Days
+

+

+                    <input name="CronDays" id="CronDaysPeriodic" type="radio" checked />
+                    -
+
Every

+                    <input id="CronDays" type="text" value="1" />
+
day(s)

+

+

+

+

                     &nbsp
-                    <input id="submit" class="bg-blue fg-white" type="submit" value="Submit">
+

+

+                    <input name="CronDays" id="CronDaysDaysOfWeek" type="radio" />
+                    -
+                @foreach (string day in DaysOfTheWeek) {
+                    <input class="cronDayOfTheWeek" type="checkbox" checked="checked" value="@day.Substring(0, 3).ToUpper()"/>
+
@day

+                }
+

+

+

+

+                    Select Month
+

+

+                    @foreach (string month in MonthsOfTheYear) {
+                        <input class="cronMonthOfTheYear" type="checkbox" checked="checked" value="@GetMonthNumber(month)"/>
+
@month

+                    }
+

+

+

+

+                    <input id="ShowCronResult" class="bg-yellow fg-white" type="button" value="Cron Result" style="width: 90%; height: 34px;" />
+

+

+                    <input name="CronResult" id="CronResult" type="text" style="width: 90%; border-width: 0 0 2px 0 !important; border-color: lightgray !important;" />
+

+

+

+

+

+                    &nbsp
+                    <input id="submit" class="bg-blue fg-white" type="submit" value="Submit" style="width: 90%; height: 34px;">

     </form>
+

+

@Model.Message

@@ -84,4 +208,77 @@
             }

+}
+
+@section Scripts {
+
 }


Removed outdated comment

Removed outdated comment

--- Apruve/Apruve/Models/LineItem.cs
+++ Apruve/Apruve/Models/LineItem.cs
@@ -21,9 +21,6 @@
         public string sku { get; set; }
         public string vendor { get; set; }
         public string view_product_url { get; set; }
-
-        // for subscriptions:
-

         // set by apruve:
         public string id { get; set; }


(DifFormat): throw exceptions on base image failures.

--- ArcFormats/MnoViolet/ImageDIF.cs
+++ ArcFormats/MnoViolet/ImageDIF.cs
@@ -77,7 +77,7 @@
                 return null;
             var files = VFS.GetFiles (base_name+".*");
             if (!files.Any())
-                return null;
+                throw new FileNotFoundException (string.Format ("Base image '{0}' not found"), base_name);
             var base_entry = files.First();
             using (var input = VFS.OpenSeekableStream (base_entry))
             {
@@ -85,7 +85,7 @@
                 // prevented here unless we save state in a static member.
                 var format = ImageFormat.FindFormat (input, base_entry.Name);
                 if (null == format)
-                    return null;
+                    throw new InvalidFormatException (string.Format ("Unable to interpret base image '{0}'", base_name));
                 format.Item2.FileName = base_entry.Name;
                 return new DifMetaData
                 {
@@ -122,7 +122,7 @@
             if (base_bitmap.Format.BitsPerPixel != 24)
                 base_bitmap = new FormatConvertedBitmap (base_bitmap, PixelFormats.Bgr24, null, 0);

-            int src_stride = base_bitmap.PixelWidth * 3;
+            int src_stride = base_bitmap.PixelWidth * 3; // XXX
             int dst_stride = (src_stride + 3) & ~3;
             var pixels = new byte[dst_stride * base_bitmap.PixelHeight];
             int row_offset = 0;


trying to import spritesheet ass-first

trying to import spritesheet ass-first

--- Assets/Editor/DefaultImporter.cs
+++ Assets/Editor/DefaultImporter.cs
@@ -62,16 +62,20 @@
 		Debug.Log("Got improter: " + textureImporter);
 		textureImporter.spriteImportMode = SpriteImportMode.Multiple;
 		textureImporter.name = pathObj;
-		textureImporter.spriteBorder = new Vector4(paddingX, paddingY, paddingX, paddingY);
+		// textureImporter.spriteBorder = new Vector4(paddingX, paddingY, paddingX, paddingY);

         List<SpriteMetaData> metaDataList = new List<SpriteMetaData>();
-
+        var sheetHeight = (rows - 1) * (spriteHeight + paddingY);
         for (int i = 0; i < rows; i++)
         {
             for (int j = 0; j < cols; j++)
             {
                 var metaData = new SpriteMetaData();
-                metaData.rect = new Rect(j * spriteWidth + j * paddingX, i * spriteHeight + i * paddingY, spriteWidth, spriteHeight);
+                metaData.rect = new Rect(
+                    j * spriteWidth + j * paddingX,
+                    sheetHeight - (i * spriteHeight + i * paddingY),
+                    spriteWidth,
+                    spriteHeight);
 				metaData.border = new Vector4(paddingX, paddingY, paddingX, paddingY);
                 metaData.pivot = metaData.rect.center;
 				metaData.name = String.Format("{0}_{1}_{2}", pathObj, (rows - i), (cols - j));


Reduced rendertime in DrawTerrain significantly by limiting the tiles to be rendered to be the tiles on screen.

--- CitySimulator/SfmlCityRenderer.cs
+++ CitySimulator/SfmlCityRenderer.cs
@@ -1,4 +1,5 @@
-using SFML.Graphics;
+using System;
+using SFML.Graphics;
 using SFML.Window;

 namespace CitySimulator {
@@ -23,8 +24,16 @@
                 Size = new Vector2f(1, 1) * _tileSize,
             };

-            for (var x = 0; x < _cityMap.Width; x++) {
-                for (var y = 0; y < _cityMap.Height; y++) {
+            var view = target.GetView();
+
+            var x0 = (int)Math.Floor(Math.Max(0, (view.Center.X - view.Size.X / 2) / _tileSize));
+            var x1 = (int)Math.Ceiling(Math.Min(_cityMap.Width, (view.Center.X + view.Size.X / 2) / _tileSize));
+
+            var y0 = (int)Math.Floor(Math.Max(0, (view.Center.Y - view.Size.Y / 2) / _tileSize));
+            var y1 = (int)Math.Ceiling(Math.Min(_cityMap.Width, (view.Center.Y + view.Size.Y / 2) / _tileSize));
+
+            for (var x = x0; x < x1; x++) {
+                for (var y = y0; y < y1; y++) {
                     shape.Position = new Vector2f(x, y) * _tileSize;

                     switch (_cityMap.Terrain[x, y]) {
@@ -41,9 +50,7 @@
                             shape.FillColor = new Color(64, 128, 0);
                             break;
                     }
-

-
                     target.Draw(shape);
                 }
             }


updated UsersAsyncService

updated UsersAsyncService

--- WhenItsDone/Lib/WhenItsDone.Services/UsersAsyncService.cs
+++ WhenItsDone/Lib/WhenItsDone.Services/UsersAsyncService.cs
@@ -90,7 +90,7 @@
             this.asyncRepository.Update(foundUser);
             using (var unitOfWork = base.UnitOfWorkFactory.CreateUnitOfWork())
             {
-                if (unitOfWork.SaveChanges() != 0)
+                if (unitOfWork.SaveChangesAsync().Result != 0)
                 {
                     return foundUser;
                 }
@@ -112,14 +112,41 @@
         {
             Guard.WhenArgument(username, nameof(username)).IsNullOrEmpty().Throw();

-            var foundUser = this.asyncRepository.GetAll(user => user.Username == username).Result.FirstOrDefault();
+            var foundUser = this.asyncRepository.GetCurrentUserIncludingMedicalInformation(username);
             if (foundUser == null)
             {
                 throw new ArgumentException(string.Format("User {0} could not be found.", username));
             }

+            int heightInCmParsedValue;
+            if (int.TryParse(heightInCm, out heightInCmParsedValue))
+            {
+                foundUser.MedicalInformation.HeightInCm = heightInCmParsedValue;
+            }

-            throw new NotImplementedException();
+            int weightInKgParsedValue;
+            if (int.TryParse(weightInKg, out weightInKgParsedValue))
+            {
+                foundUser.MedicalInformation.WeightInKg = weightInKgParsedValue;
+            }
+
+            if (foundUser.MedicalInformation.HeightInCm.HasValue && foundUser.MedicalInformation.WeightInKg.HasValue)
+            {
+                foundUser.MedicalInformation.BMI = (int)(foundUser.MedicalInformation.WeightInKg / foundUser.MedicalInformation.HeightInCm * foundUser.MedicalInformation.HeightInCm);
+            }
+
+            this.asyncRepository.Update(foundUser);
+            using (var unitOfWork = base.UnitOfWorkFactory.CreateUnitOfWork())
+            {
+                if (unitOfWork.SaveChangesAsync().Result != 0)
+                {
+                    return foundUser;
+                }
+                else
+                {
+                    throw new ArgumentException("Could not update medical information");
+                }
+            }
         }
     }
 }


allocating stat points reminder now sends you to the right place

--- Assets/Scripts/Game/Camp/Camp.cs
+++ Assets/Scripts/Game/Camp/Camp.cs
@@ -45,7 +45,7 @@
                     if (partyMember.Stats.HasStatPoints) {
                         root.AddText(
                             string.Format(
-                                "<color=cyan>{0}</color> has unallocated stat points. Points can be allocated in the <color=yellow>Characters</color> page.",
+                                "<color=cyan>{0}</color> has unallocated stat points. Points can be allocated in the <color=yellow>Party</color> page.",
                                 partyMember.Look.DisplayName));
                     }
                 }


Re-implemented dashing for PlayerAnimator

--- Assets/Scripts/PlayerAnimator.cs
+++ Assets/Scripts/PlayerAnimator.cs
@@ -14,15 +14,17 @@

         public string walking = "Walking";

+        public string attackingSideways = "AttackSideways";
+
         public string attackingUp = "AttackUp";
-
-        public string attacking = "AttackSideways";

         public string attackingDown = "AttackDown";

-        public string dashingLeft = "DashLeft";
+        public string dashingSideways = "DashSideways";

-        public string dashingRight = "DashRight";
+        public string dashingUp = "DashUp";
+
+        public string dashingDown = "DashDown";

         public string hit = "Hit";

@@ -59,7 +61,7 @@
             if (attackDir.sqrMagnitude > attackDirThreshold)
             {
                 var attackSideways = Mathf.Abs(attackDir.x) > attackDirThreshold;
-                _animator.SetBool(this.attacking, attackSideways);
+                _animator.SetBool(this.attackingSideways, attackSideways);
                 if (attackSideways)
                 {
                     // sideways attacks are prioritized first
@@ -76,7 +78,7 @@
             }
             else
             {
-                _animator.SetBool(this.attacking, false);
+                _animator.SetBool(this.attackingSideways, false);
                 _animator.SetBool(this.attackingUp, false);
                 _animator.SetBool(this.attackingDown, false);
             }
@@ -84,9 +86,25 @@
             var dashDir = _mover.dashVelocity;
             if (dashDir.sqrMagnitude > dashDirThreshold)
             {
-                var left = dashDir.x < 0f;
-                _animator.SetBool(this.dashingLeft, left);
-                _animator.SetBool(this.dashingRight, !left);
+                var dashSideways = Mathf.Abs(dashDir.x) > dashDirThreshold;
+                _animator.SetBool(this.dashingSideways, dashSideways);
+                if (dashSideways)
+                {
+                    var left = dashDir.x < 0f;
+                    _spriteRenderer.flipX = left;
+                }
+                else if (Mathf.Abs(dashDir.z) > dashDirThreshold)
+                {
+                    var up = dashDir.z > 0f;
+                    _animator.SetBool(this.dashingUp, up);
+                    _animator.SetBool(this.dashingDown, !up);
+                }
+            }
+            else
+            {
+                _animator.SetBool(this.dashingSideways, false);
+                _animator.SetBool(this.dashingUp, false);
+                _animator.SetBool(this.dashingDown, false);
             }

             _animator.SetBool(this.hit, _player.isHit);


slight jump grace period

slight jump grace period

--- Assets/Scripts/RunnerBehavior.cs
+++ Assets/Scripts/RunnerBehavior.cs
@@ -25,6 +25,7 @@
     private float _slideTime;
     private bool _groundHitPlayed;
     private bool isDead = false;
+    private float jumpEnabledTimer;

     private SpriteRenderer _graphic;

@@ -89,7 +90,16 @@
             _characterController2D.warpToGrounded();
         }

-        if (Input.GetKeyDown(KeyCode.W) && _characterController2D.isGrounded)
+        if (_characterController2D.isGrounded)
+        {
+            jumpEnabledTimer = 0.1f;
+        }
+        else
+        {
+            jumpEnabledTimer -= Time.deltaTime;
+        }
+
+        if (Input.GetKeyDown(KeyCode.W) && jumpEnabledTimer > 0)
         {
             _groundHitPlayed = true;
             audio.PlayOneShot(feedback[0]);


Reduced amount of allocations in FormationManager

--- Assets/Ships/FormationManager.cs
+++ Assets/Ships/FormationManager.cs
@@ -8,25 +8,23 @@
 public class FormationManager
 {
 	[SerializeField]
-	private HashSet<int> followRequests;
+	private List<int> followRequests;

 	[SerializeField]
-	private IDictionary<int, int> followerPositions;
+	private Dictionary<int, int> followerPositions;

 	public ICollection<int> followers { get { return followerPositions.Keys; } }

 	public FormationManager()
 	{
-		followRequests = new HashSet<int>();
+		followRequests = new List<int>();
 		followerPositions = new Dictionary<int, int>();
 	}

 	public void Update()
 	{
 		//remove any followers that didn't renew their follow status
-		var currentFollowers = new LinkedList<int>(followerPositions.Keys);
-
-		foreach (int currentFollower in currentFollowers)
+		foreach (int currentFollower in followerPositions.Keys)
 		{
 			if (!followRequests.Contains(currentFollower))
 			{
@@ -37,30 +35,27 @@
 				followRequests.Remove(currentFollower);
 			}
 		}
-
-		//update to only include old
-		currentFollowers = new LinkedList<int>(followerPositions.Keys);
+
+		//update to only include old
+		var currentFollowers = new LinkedList<int>(followerPositions.Keys);

 		//followRequests now only contains unique new followers
-		var newFollowers = new List<int>(followRequests);
-		followRequests.Clear();
-
 		/* add new followers alternately to the "left" and "right" (back and front of
 		 the list) */
-		var newFollowerCount = newFollowers.Count();
+		var newFollowerCount = followRequests.Count();
 		for (int newFollowerIt = 0; newFollowerIt < newFollowerCount; ++newFollowerIt)
 		{
 			if (newFollowerIt % 2 == 0)
 			{
-				currentFollowers.AddLast(newFollowers[newFollowerIt]);
+				currentFollowers.AddLast(followRequests[newFollowerIt]);
 			}
 			else
 			{
-				currentFollowers.AddFirst(newFollowers[newFollowerIt]);
+				currentFollowers.AddFirst(followRequests[newFollowerIt]);
 			}
 		}

-		followerPositions = new Dictionary<int, int>();
+		followerPositions.Clear();

 		var followerIds = currentFollowers.ToArray();
 		var count = currentFollowers.Count();
@@ -79,6 +74,8 @@

 	public int IncludeFollower(int followerId)
 	{
+        Debug.Assert(!followRequests.Contains(followerId), "should not receive duplicate follow requests");
+
 		followRequests.Add(followerId);

 		//return the current position if this id is already registered


fix compile error

fix compile error

--- Assets/Slua/Editor/LuaCodeGen.cs
+++ Assets/Slua/Editor/LuaCodeGen.cs
@@ -66,7 +66,7 @@
 #if UNITY_EDITOR_WIN
 					System.Diagnostics.Process.Start("debugger\\win\\ldb.exe", string.Format("-host {0} -port {1}", ip, port));
 #else
-						System.Diagnostics.Process.Start(string.Format("debugger\\mac\\ldb",string.Format("-host {0} -port {1}", ip, port));
+						System.Diagnostics.Process.Start("debugger\\mac\\ldb",string.Format("-host {0} -port {1}", ip, port));
 #endif
 				}
 				catch (Exception)


fix #26

fix #26

--- Assets/Slua/Editor/LuaCodeGen.cs
+++ Assets/Slua/Editor/LuaCodeGen.cs
@@ -487,10 +487,9 @@
                 return op;
             }
 			LuaDLL.lua_pop(l,1);
-
+			l = LuaState.get(l).L;
             ua = ($ARGS) =>
             {
-				l = LuaState.get(l).L;
                 int error = pushTry(l);
 ";


Fix xml parser

Fix xml parser

--- Common/Xml/ConfigNodeXmlParser.cs
+++ Common/Xml/ConfigNodeXmlParser.cs
@@ -69,7 +69,8 @@
                                 }
                                 else
                                 {
-                                    writer.WriteLine(GetDepthTabs(xmlReader.Depth - 1) + xmlReader.Name);
+                                    var nodeName = xmlReader.GetAttribute(AttributeName);
+                                    writer.WriteLine(GetDepthTabs(xmlReader.Depth - 1) + nodeName);
                                     writer.WriteLine(GetDepthTabs(xmlReader.Depth - 1) + "{");
                                     if (xmlReader.IsEmptyElement)
                                         writer.WriteLine(GetDepthTabs(xmlReader.Depth - 1) + "}");


Add hack for HOF cards

Add hack for HOF cards

--- HearthDb/Card.cs
+++ HearthDb/Card.cs
@@ -37,7 +37,21 @@

 		public Race Race => (Race)Entity.GetTag(CARDRACE);

-		public CardSet Set => (CardSet)Entity.GetTag(CARD_SET);
+		public CardSet Set
+		{
+			get
+			{
+				// HACK to fix missing set value on Hall of Fame cards
+				if(new[]
+				{
+					CardIds.Collectible.Mage.IceBlock,
+					CardIds.Collectible.Neutral.ColdlightOracle,
+					CardIds.Collectible.Neutral.MoltenGiant
+				}.Contains(Id))
+					return CardSet.HOF;
+				return (CardSet)Entity.GetTag(CARD_SET);
+			}
+		}

 		public Faction Faction => (Faction)Entity.GetTag(FACTION);


Switched order

Switched order

--- CruDapper/Mappers/DbMapperBase.cs
+++ CruDapper/Mappers/DbMapperBase.cs
@@ -12,8 +12,8 @@
         Provider provider;
         public DbMapperBase(string ConnectionName, Provider provider)
         {
-            this.ConnectionName = ConnectionName;
             this.provider = provider;
+            this.ConnectionName = ConnectionName;
         }

         protected ConnectionBridge _connectionBridge;


Fixed string datetime bug

Fixed string datetime bug

--- DBLike/Client/Threads/Uploader.cs
+++ DBLike/Client/Threads/Uploader.cs
@@ -155,7 +155,8 @@
                                     string targetPath = "";

                                     // add time to new name
-                                    string dateString = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
+                                    //string dateString = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
+                                    string dateString = DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm:ss");
                                     string[] fileNameArr = sourcePath.Split('.');
                                     string newFileName = fileNameArr[0] + " ( conflict copy " + dateString + ")." + fileNameArr[1];
                                     targetPath = newFileName;


Fix worldspawn handling in PreprocessMap

Fixes processing for maps whose first line isn't the opening brace of
the worldspawn entity.

--- Quinstance/Program.cs
+++ Quinstance/Program.cs
@@ -387,20 +387,22 @@
                 throw new InvalidDataException("Unsupported .map version! Expected Valve 220, got \"" + mapversion + "\" from " + map_in);

             List<string> lines_out = new List<string>();
-            lines_out.Add("world");
-            lines_out.Add("{");
-
-            // Starting from 1 skips over Quake maps' first open brace, which
-            // would otherwise turn worldspawn into its own 'entity' block.
-            for (int i = 1; i < lines_in.Count; ++i) {
+            for (int i = 0; i < lines_in.Count; ++i) {
                 string line_in = lines_in[i],
                        trimmed = line_in.Trim();

+                if (trimmed == "")
+                    continue;
+
                 if (trimmed == "{") {
-                    if (lines_in[i + 1].Trim().StartsWith("\"")) {
+                    string line_next = lines_in[i + 1].Trim();
+                    if (line_next.EndsWith("\"worldspawn\"") && line_next.StartsWith("\"classname\"")) {
+                        lines_out.Add("world");
+                        lines_out.Add(line_in);
+                    } else if (line_next.StartsWith("\"")) {
                         lines_out.Add("entity");
                         lines_out.Add(line_in);
-                    } else if (lines_in[i + 1].Trim().StartsWith("(")) {
+                    } else if (line_next.StartsWith("(")) {
                         lines_out.Add("solid");
                         lines_out.Add(line_in);
                     }


Fix copy/paste mistake in union test code

--- Dasher.Tests/DeserialiserTests.cs
+++ Dasher.Tests/DeserialiserTests.cs
@@ -591,14 +591,13 @@
         {
             var bytes = PackBytes(packer => packer.PackMapHeader(1)
                 .Pack(nameof(ValueWrapper<Union<int, double>>.Value))
-                .PackArrayHeader(3)
-                    .Pack("String")
+                .PackArrayHeader(2)
+                    .Pack("Unknown")
                     .Pack("Hello"));

-            var ex = Assert.Throws<DeserialisationException>(() => new Deserialiser<ValueWrapper<Union<int, string>>>().Deserialise(bytes));
-
-            Assert.Equal(@"Union array should have 2 elements (not 3) for property ""value"" of type ""Dasher.Union`2[System.Int32,System.String]""",
-                ex.Message);
+            var ex = Assert.Throws<Exception>(() => new Deserialiser<ValueWrapper<Union<int, string>>>().Deserialise(bytes));
+
+            Assert.Equal("No match on union type", ex.Message);
         }

         [Fact]


Full Deck extractions.

Full Deck extractions.

--- RReplay/Model/Deck.cs
+++ RReplay/Model/Deck.cs
@@ -1,6 +1,7 @@
 using System;
+using System.Collections;
 using System.Collections.Generic;
-
+using System.Windows;

 namespace RReplay.Model
 {
@@ -9,6 +10,27 @@
         NATO = 0x0,
         PACT = 0x1
     }
+
+    public struct TwoTransportUnit
+    {
+        public byte Veterancy;
+        public ushort UnitID;
+        public ushort TransportID;
+        public ushort LandingCraftID;
+    };
+
+    public struct OneTransportUnit
+    {
+        public byte Veterancy;
+        public ushort UnitID;
+        public ushort TransportID;
+    };
+
+    public struct Unit
+    {
+        public byte Veterancy;
+        public ushort UnitID;
+    };

     public class Deck
     {
@@ -16,6 +38,13 @@
         private byte specialization;
         private byte era;
         private CoalitionEnum coalition;
+        private byte twoTransportsUnits;
+        private byte oneTransportsUnits;
+        private byte units;
+
+        public List<TwoTransportUnit> TwoTransportUnitsList;
+        public List<OneTransportUnit> OneTransportUnitsList;
+        public List<Unit> UnitsList;

         public string Country
         {
@@ -76,23 +105,113 @@
         {
             var base64EncodedBytes = System.Convert.FromBase64String(deckCode);

-            byte firstByte = Buffer.GetByte(base64EncodedBytes, 0);
-            byte secondByte = Buffer.GetByte(base64EncodedBytes, 1);
-
-            if( firstByte >> 7 == 0)
-            {
-                coalition = CoalitionEnum.NATO;
+            var bitArray = new BitArray(base64EncodedBytes);
+            var bitArrayInversed = new BitArray(bitArray.Length);
+
+            // If it's little endian inverse every 8 bits
+            if ( BitConverter.IsLittleEndian )
+            {
+                for ( int i = 0; i < bitArray.Length / 8; i++ )
+                {
+                    for ( int j = 0; j < 8; j++ )
+                    {
+                        bitArrayInversed[i * 8 + j] = bitArray[i * 8 + 7 - j];
+                    }
+                }
             }
             else
             {
-                coalition = CoalitionEnum.PACT;
-            }
-
-            country = (byte)((firstByte & 0x7F) << 1 | secondByte >> 7);
-
-            specialization = (byte)((secondByte & 0x70) >> 4);
-            era = (byte)((secondByte & 0xC) >> 2);
-
+                bitArrayInversed = bitArray;
+            }
+
+            int posArray = 0;
+
+            // First bit is the coalition
+            coalition = (CoalitionEnum)GetBits<byte>(bitArrayInversed, 1, ref posArray);
+
+            // Next 8 bits is the nation
+            country = GetBits<byte>(bitArrayInversed, 8, ref posArray);
+
+            // Next 3 bits is the specialization
+            specialization = GetBits<byte>(bitArrayInversed, 3, ref posArray);
+
+            // next 2 bits is the era
+            era = GetBits<byte>(bitArrayInversed, 2, ref posArray);
+
+            // next 4 bits is the number of two transports units
+            twoTransportsUnits = GetBits<byte>(bitArrayInversed, 4, ref posArray);
+
+            // next 5 bits is the number of two transports units
+            oneTransportsUnits = GetBits<byte>(bitArrayInversed, 5, ref posArray);
+
+            TwoTransportUnitsList = new List<TwoTransportUnit>(twoTransportsUnits);
+
+            for (byte i = 0; i < twoTransportsUnits; i++ )
+            {
+                TwoTransportUnit unit;
+
+                unit.Veterancy = GetBits<byte>(bitArrayInversed, 3, ref posArray);
+
+                unit.UnitID = GetBits<ushort>(bitArrayInversed, 10, ref posArray);
+
+                unit.TransportID = GetBits<ushort>(bitArrayInversed, 10, ref posArray);
+
+                unit.LandingCraftID = GetBits<ushort>(bitArrayInversed, 10, ref posArray);
+
+                TwoTransportUnitsList.Add(unit);
+            }
+
+            OneTransportUnitsList = new List<OneTransportUnit>(oneTransportsUnits);
+
+            for ( byte i = 0; i < oneTransportsUnits; i++ )
+            {
+                OneTransportUnit unit;
+
+                unit.Veterancy = GetBits<byte>(bitArrayInversed, 3, ref posArray);
+
+                unit.UnitID = GetBits<ushort>(bitArrayInversed, 10, ref posArray);
+
+                unit.TransportID = GetBits<ushort>(bitArrayInversed, 10, ref posArray);
+
+                OneTransportUnitsList.Add(unit);
+            }
+
+            units = (byte)((bitArrayInversed.Length - posArray) / 13);
+
+            UnitsList = new List<Unit>(units);
+
+            for (byte i = 0; i < units; i++ )
+            {
+                Unit unit;
+
+                unit.Veterancy = GetBits<byte>(bitArrayInversed, 3, ref posArray);
+
+                unit.UnitID = GetBits<ushort>(bitArrayInversed, 10, ref posArray);
+                UnitsList.Add(unit);
+            }
+        }
+
+        /// <summary>
+        /// Read numberOfBits of bits from bitArray and increase startingPosArray by numberOfBits
+        /// </summary>
+        /// <typeparam name="T">An unsigned integer lower than 16 bits</typeparam>
+        /// <param name="bitArray">The array where to read the bits</param>
+        /// <param name="numberOfBits">The number of bits to read</param>
+        /// <param name="startingPosArray">The starting position to read</param>
+        /// <returns>An unsigned integer</returns>
+        private T GetBits<T>(BitArray bitArray, byte numberOfBits , ref int startingPosArray)
+        {
+            ushort bits = 0;
+
+            for ( byte j = 0; j < numberOfBits; j++ )
+            {
+                if ( bitArray[startingPosArray++] )
+                {
+                    bits |= (ushort)(1 << (numberOfBits - 1) - j);
+                }
+            }
+
+            return (T)Convert.ChangeType(bits, typeof(T));
         }

         public static Dictionary<byte, string> SpecializationDictionary = new Dictionary<byte, string>


Added Linq to Sql with changetracking disabled test

--- RawBencher/Program.cs
+++ RawBencher/Program.cs
@@ -55,6 +55,10 @@
 			for(int i = 0; i < loopAmount; i++)
 			{
 				FetchSalesOrderHeaderL2S();
+			}
+			for(int i = 0; i < loopAmount; i++)
+			{
+				FetchSalesOrderHeaderL2SNoTracking();
 			}
 			for(int i = 0; i < loopAmount; i++)
 			{
@@ -392,6 +396,29 @@
 		}

+		private static void FetchSalesOrderHeaderL2SNoTracking()
+		{
+			var frameworkName = CreateFrameworkName("Linq to Sql v{0} (v{1}), using no tracking", typeof(System.Data.Linq.DataContext));
+			var sw = new Stopwatch();
+			sw.Start();
+			List<L2S.Bencher.EntityClasses.SalesOrderHeader> headers = null;
+			var ctx = new L2SBencherDataContext();
+			ctx.ObjectTrackingEnabled = false;
+			headers = ctx.SalesOrderHeaders.ToList();
+			sw.Stop();
+			ReportResult(frameworkName, sw.ElapsedMilliseconds, headers.Count);
+
+			foreach(var e in headers)
+			{
+				if(e.SalesOrderId <= 0)
+				{
+					Console.WriteLine("L2S: Data is empty");
+					break;
+				}
+			}
+		}
+
+
 		private static void FetchSalesOrderHeaderNH()
 		{
 			var frameworkName = CreateFrameworkName("NHibernate v{0} (v{1})", typeof(ISession));


(minor) bugfix: use a thread safe collection for progress reporters This only affects how progress is reported, not a serious bug, but if the program starts really slow the old way could in theory crash (occurs in debug mode sometimes) because the reporters aren't all added at the first instance (1 second) the reporters are used.

--- A-vs-An/WikipediaAvsAnTrieExtractor/Program.cs
+++ A-vs-An/WikipediaAvsAnTrieExtractor/Program.cs
@@ -39,7 +39,7 @@
             return 0;
         }

-        static readonly List<Func<string>> ProgressReporters = new List<Func<string>>();
+        static readonly ConcurrentBag<Func<string>> ProgressReporters = new ConcurrentBag<Func<string>>();
         const int PageBlocksQueueSize = 20;
         const int SightingBlocksQueueSize = 200;
         const int PagesPerBlock = 1000;


Fix VMWare IP issue.

Fix VMWare IP issue.

--- RemoteTaskServer/Api/Services/Network/NetworkService.cs
+++ RemoteTaskServer/Api/Services/Network/NetworkService.cs
@@ -29,9 +29,16 @@

         public static IPAddress GetAddress()
         {
+            //if VMware or VMPlayer installed, we get the wrong address, so try getting the physical first.
+            var address = GetPhysicalIpAdress();
+            //Default since we couldn't.
+            if (string.IsNullOrEmpty(address))
+            {
+                address = GetIPv4Address();
+            }
             var bindLocal = (bool) Settings.Get("Network").BindLocal;

-            return bindLocal ? IPAddress.Parse(GetIPv4Address()) : IPAddress.Any;
+            return bindLocal ? IPAddress.Parse(address) : IPAddress.Any;
         }

         private static string GetReverseDns(string ip, int timeout)
@@ -47,7 +54,24 @@
                 return ip;
             }
         }
-
+        public static string GetPhysicalIpAdress()
+        {
+            foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
+            {
+                var addr = ni.GetIPProperties().GatewayAddresses.FirstOrDefault();
+                if (addr == null || addr.Address.ToString().Equals("0.0.0.0")) continue;
+                if (ni.NetworkInterfaceType != NetworkInterfaceType.Wireless80211 &&
+                    ni.NetworkInterfaceType != NetworkInterfaceType.Ethernet) continue;
+                foreach (var ip in ni.GetIPProperties().UnicastAddresses)
+                {
+                    if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
+                    {
+                        return ip.Address.ToString();
+                    }
+                }
+            }
+            return string.Empty;
+        }
         public static List<NetworkDevices> ConnectedDevices()
         {


allow default value on PluginBootstrapper

--- SS.Integration.Adapter.WindowsService/AdapterService.cs
+++ SS.Integration.Adapter.WindowsService/AdapterService.cs
@@ -38,7 +38,7 @@
         [Import]
         public IAdapterPlugin PlatformConnector { get; set; }

-        [Import]
+        [Import(AllowDefault = true)]
         public IPluginBootstrapper<NinjectModule> PluginBootstrapper { get; set; }

         public AdapterService()


Delay disconnection for match over for 10m

--- SS.Integration.Adapter/Actors/StreamHealthCheckActor.cs
+++ SS.Integration.Adapter/Actors/StreamHealthCheckActor.cs
@@ -52,6 +52,7 @@

         private int lastProcessedSequence = 0;
         private DateTime lastExecute = DateTime.MinValue;
+	    private DateTime? matchOverDetectedTime;

         #endregion

@@ -110,12 +111,8 @@

 			//return;

-	        if (msg.Resource.IsMatchOver)
-	        {
-		        Context.Parent.Tell(new StopStreamingMsg());
-						return;
-
-					}
+	        if (StopStreamingDueToMatchOver(msg))
+		        return;

             if (!ValidateTime())
@@ -167,7 +164,28 @@

         }

-        private bool ValidateTime()
+	    private bool StopStreamingDueToMatchOver(StreamHealthCheckMsg msg)
+	    {
+		    if (msg.Resource.IsMatchOver)
+		    {
+			    if (matchOverDetectedTime == null)
+			    {
+				    matchOverDetectedTime = DateTime.Now;
+			    }
+			    else
+			    {
+				    if (matchOverDetectedTime.Value.AddMinutes(10) > DateTime.Now)
+				    {
+					    Context.Parent.Tell(new StopStreamingMsg());
+					    return true;
+				    }
+			    }
+		    }
+
+		    return false;
+	    }
+
+	    private bool ValidateTime()
         {
             if ((DateTime.UtcNow - lastExecute).TotalSeconds < Configuration.Settings.MinimalHealthcheckInterval)
             {


add HideDisplayName XML support

add HideDisplayName XML support

--- Signum.Entities.Extensions/Dashboard/DashboardEntity.cs
+++ Signum.Entities.Extensions/Dashboard/DashboardEntity.cs
@@ -148,6 +148,7 @@
             DashboardPriority = DashboardPriority,
             AutoRefreshPeriod = this.AutoRefreshPeriod,
             DisplayName = "Clone {0}".FormatWith(this.DisplayName),
+            HideDisplayName = this.HideDisplayName,
             CombineSimilarRows = this.CombineSimilarRows,
             CacheQueryConfiguration = this.CacheQueryConfiguration?.Clone(),
             Parts = Parts.Select(p => p.Clone()).ToMList(),
@@ -162,6 +163,7 @@
             new XAttribute("DisplayName", DisplayName),
             EntityType == null ? null! : new XAttribute("EntityType", ctx.TypeToName(EntityType)),
             Owner == null ? null! : new XAttribute("Owner", Owner.Key()),
+            HideDisplayName == false ? null! : new XAttribute("HideDisplayName", HideDisplayName.ToString()),
             DashboardPriority == null ? null! : new XAttribute("DashboardPriority", DashboardPriority.Value.ToString()),
             EmbeddedInEntity == null ? null! : new XAttribute("EmbeddedInEntity", EmbeddedInEntity.Value.ToString()),
             new XAttribute("CombineSimilarRows", CombineSimilarRows),
@@ -177,6 +179,7 @@
         DisplayName = element.Attribute("DisplayName")!.Value;
         EntityType = element.Attribute("EntityType")?.Let(a => ctx.GetTypeLite(a.Value));
         Owner = element.Attribute("Owner")?.Let(a => Lite.Parse<Entity>(a.Value));
+        HideDisplayName = element.Attribute("HideDisplayName")?.Let(a => bool.Parse(a.Value)) ?? false;
         DashboardPriority = element.Attribute("DashboardPriority")?.Let(a => int.Parse(a.Value));
         EmbeddedInEntity = element.Attribute("EmbeddedInEntity")?.Let(a => a.Value.ToEnum<DashboardEmbedededInEntity>());
         CombineSimilarRows = element.Attribute("CombineSimilarRows")?.Let(a => bool.Parse(a.Value)) ?? false;


New failing tests to make pass

New failing tests to make pass

--- SimpleExpression/SimpleExpression.UnitTests/AstTests.cs
+++ SimpleExpression/SimpleExpression.UnitTests/AstTests.cs
@@ -57,16 +57,104 @@
         }

         [TestMethod]
-        public void AstTests_Group()
+        public void AstTests_SimpleGroup()
         {
-            var chain = new List<IConverter> { new Group(), new Text(), new Text(), new Together() };
+            var chain = new List<IConverter> { new Group(), new Text(), new Together() };
             var root = builder.GenerateAst(chain);

             Assert.IsTrue(root != null);
             Assert.IsTrue(root.Parent == null);
-            Assert.IsTrue(root is GroupNode);
+
             var groupNode = root as GroupNode;
+            Assert.IsNotNull(groupNode);
+            Assert.IsTrue(groupNode.Children.Count == 1);
+        }
+
+        [TestMethod]
+        public void AstTests_GroupAndConcat()
+        {
+            var chain = new List<IConverter>
+                {
+                    new Group(),
+                        new Text(),
+                        new Text(),
+                    new Together()
+                };
+            var root = builder.GenerateAst(chain);
+
+            Assert.IsTrue(root != null);
+            Assert.IsTrue(root.Parent == null);
+
+            var groupNode = root as GroupNode;
+            Assert.IsNotNull(groupNode);
+            Assert.IsTrue(groupNode.Children.Count == 1);
+
+            var concatNode = groupNode.Children[0] as ConcatNode;
+            Assert.IsNotNull(concatNode);
             Assert.IsTrue(groupNode.Children.Count == 2);
+        }
+
+        [TestMethod]
+        public void AstTests_GroupContainsGroup()
+        {
+            var chain = new List<IConverter>
+                {
+                    new Group(),
+                        new Group(),
+                            new Text(),
+                        new Together(),
+                    new Together()
+                };
+            var root = builder.GenerateAst(chain);
+
+            Assert.IsTrue(root != null);
+            Assert.IsTrue(root.Parent == null);
+
+            var groupNode = root as GroupNode;
+            Assert.IsNotNull(groupNode);
+            Assert.IsTrue(groupNode.Children.Count == 1);
+
+            var subGroupNode = groupNode.Children[0] as GroupNode;
+            Assert.IsNotNull(subGroupNode);
+            Assert.IsTrue(groupNode.Children.Count == 1);
+        }
+
+        [TestMethod]
+        public void AstTests_GroupConcatAndContainsGroupConcat()
+        {
+            var chain = new List<IConverter>
+                {
+                    new Group(),
+                        new Text(),
+                        new Group(),
+                            new Text(),
+                            new Text(),
+                        new Together(),
+                    new Together()
+                };
+            var root = builder.GenerateAst(chain);
+
+            Assert.IsTrue(root != null);
+            Assert.IsTrue(root.Parent == null);
+
+            var groupNode = root as GroupNode;
+            Assert.IsNotNull(groupNode);
+            Assert.IsTrue(groupNode.Children.Count == 1);
+
+            var concatNode = groupNode.Children[0] as ConcatNode;
+            Assert.IsNotNull(concatNode);
+            Assert.IsTrue(groupNode.Children.Count == 2);
+
+            var textNode = concatNode.Children[0] as TextNode;
+            Assert.IsNotNull(textNode);
+
+            var subGroupNode = concatNode.Children[1] as GroupNode;
+            Assert.IsNotNull(subGroupNode);
+            Assert.IsTrue(subGroupNode.Children.Count == 1);
+
+            var subConcatNode = subGroupNode.Children[0] as ConcatNode;
+            Assert.IsNotNull(subConcatNode);
+            Assert.IsTrue(subConcatNode.Children.Count == 2);
         }
     }
 }


show query error

show query error

--- samples/Program.cs
+++ samples/Program.cs
@@ -157,6 +157,9 @@
                         , typeof(object)
                      )
                   ).Compile()();
+
+                  if (returnValue is IEnumerable)
+                     returnValue = ((IEnumerable)returnValue).Cast<object>().ToArray();
                };

                if (continueOnError) {
@@ -192,9 +195,6 @@

                } else {

-                  if (returnValue is IEnumerable)
-                     returnValue = ((IEnumerable)returnValue).Cast<object>().ToArray();
-
                   ConsoleColor color = Console.ForegroundColor;
                   Console.ForegroundColor = ConsoleColor.DarkGray;


sensusservicehelper - set animation on script modals

--- Sensus.Shared/SensusServiceHelper.cs
+++ Sensus.Shared/SensusServiceHelper.cs
@@ -1406,7 +1406,7 @@

 							bool animate = navigationResult == InputGroupPage.NavigationResult.Submit || navigationResult == InputGroupPage.NavigationResult.Cancel;

-							await navigation.PopModalAsync();
+							await navigation.PopModalAsync(animate);

 							if (navigationResult == InputGroupPage.NavigationResult.Backward)
 							{


Fix debug health test delay.

Fix debug health test delay.

--- SensusService/SensusServiceHelper.cs
+++ SensusService/SensusServiceHelper.cs
@@ -69,7 +69,7 @@

 #if DEBUG || UNIT_TESTING
         // test every 30 seconds in debug
-        public const int HEALTH_TEST_DELAY_MS = 30000000;
+        public const int HEALTH_TEST_DELAY_MS = 30000;
 #elif RELEASE
         // test every 15 minutes in release
         public const int HEALTH_TEST_DELAY_MS = 900000;


Fixed: File not found - ico.png

Fixed: File not found - ico.png

--- WinAlfred/Msg.xaml.cs
+++ WinAlfred/Msg.xaml.cs
@@ -65,7 +65,7 @@
             tbSubTitle.Text = subTitle;
             if (!File.Exists(icopath))
             {
-                icopath = AppDomain.CurrentDomain.BaseDirectory + "Images\\ico.png";
+                icopath = AppDomain.CurrentDomain.BaseDirectory + "Images\\app.png";
             }
             imgIco.Source = new BitmapImage(new Uri(icopath));
             Show();


Add code task

Add code task

--- RemoveEmptyEntries.cs
+++ RemoveEmptyEntries.cs
@@ -84,6 +84,7 @@
 						File.Delete (file + ".out");
 					}
 					else {
+						// TODO: Detect comments and schema removal
 						// replace original file
 						Console.WriteLine ("Empty entries removed from: {0}", file);
 						File.Delete (file);


Give labels.

Give labels.

--- samples/mmk/mmk.cs
+++ samples/mmk/mmk.cs
@@ -127,6 +127,8 @@
 			Controls.Add (cb);
 		}

+		static readonly string [] key_labels = {"c", "c+", "d", "d+", "e", "", "f", "f+", "g", "g+", "a", "a+", "b", ""};
+
 		void SetupKeyboardLayout (KeyMap map)
 		{
 			keymap = map;
@@ -135,8 +137,11 @@

 			// offset 4, 10, 18 are not mapped, so skip those numbers
 			var hl = new List<Button> ();
+			int labelStringIndex = key_labels.Length - 5;
 			for (int i = 0; i < keymap.HighKeys.Length; i++) {
 				var b = new NoteButton ();
+				b.Text = key_labels [labelStringIndex % key_labels.Length];
+				labelStringIndex++;
 				if (!IsNotableIndex (i)) {
 					b.Enabled = false;
 					b.Visible = false;
@@ -147,8 +152,11 @@
 			}
 			high_buttons = hl.ToArray ();
 			var ll = new List<Button> ();
+			labelStringIndex = key_labels.Length - 5;
 			for (int i = 0; i < keymap.LowKeys.Length; i++) {
 				var b = new NoteButton ();
+				b.Text = key_labels [labelStringIndex % key_labels.Length];
+				labelStringIndex++;
 				if (!IsNotableIndex (i)) {
 					b.Enabled = false;
 					b.Visible = false;


fix usage of this/base in static

fix usage of this/base in static

--- Hooks.cs
+++ Hooks.cs
@@ -312,7 +312,7 @@
 			{
 				Effect.server.Run(ce.pickupEffect.resourcePath, ce.transform.position, ce.transform.up, null, false);
 			}
-			msg.player.xp.Add(Definitions.CollectWorldItem, this.xpScale, base.ShortPrefabName, 0uL);
+			msg.player.xp.Add(Definitions.CollectWorldItem, ce.xpScale, ce.ShortPrefabName, 0uL);
 			ce.Kill(BaseNetworkable.DestroyMode.None);
 		}