Added extra SetValue methods and non-throwing methods.

--- NtApiDotNet/NtKey.cs
+++ NtApiDotNet/NtKey.cs
@@ -477,11 +477,25 @@
         /// <param name="value_name">The name of the value</param>
         /// <param name="type">The type of the value</param>
         /// <param name="data">The raw value data</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        /// <returns>The NT status code.</returns>
+        public NtStatus SetValue(string value_name, RegistryValueType type, byte[] data, bool throw_on_error)
+        {
+            return NtSystemCalls.NtSetValueKey(Handle, new UnicodeString(value_name ?? string.Empty),
+                0, type, data, data.Length).ToNtException(throw_on_error);
+        }
+
+        /// <summary>
+        /// Set a resistry value
+        /// </summary>
+        /// <param name="value_name">The name of the value</param>
+        /// <param name="type">The type of the value</param>
+        /// <param name="data">The raw value data</param>
         /// <exception cref="NtException">Thrown on error.</exception>
         public void SetValue(string value_name, RegistryValueType type, byte[] data)
         {
-            NtSystemCalls.NtSetValueKey(Handle, new UnicodeString(value_name ?? String.Empty),
-                0, type, data, data.Length).ToNtException();
+            SetValue(value_name, type, data);
         }

         /// <summary>
@@ -490,10 +504,74 @@
         /// <param name="value_name">The name of the value</param>
         /// <param name="type">The type of the value</param>
         /// <param name="data">The value data</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        /// <returns>The NT status code.</returns>
+        public NtStatus SetValue(string value_name, RegistryValueType type, string data, bool throw_on_error)
+        {
+            return SetValue(value_name, type, Encoding.Unicode.GetBytes(data), throw_on_error);
+        }
+
+        /// <summary>
+        /// Set a string resistry value as REG_SZ.
+        /// </summary>
+        /// <param name="value_name">The name of the value</param>
+        /// <param name="data">The value data</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        /// <returns>The NT status code.</returns>
+        public NtStatus SetValue(string value_name, string data, bool throw_on_error)
+        {
+            return SetValue(value_name, RegistryValueType.String, data, throw_on_error);
+        }
+
+        /// <summary>
+        /// Set a string resistry value
+        /// </summary>
+        /// <param name="value_name">The name of the value</param>
+        /// <param name="type">The type of the value</param>
+        /// <param name="data">The value data</param>
         /// <exception cref="NtException">Thrown on error.</exception>
         public void SetValue(string value_name, RegistryValueType type, string data)
         {
-            SetValue(value_name, type, Encoding.Unicode.GetBytes(data));
+            SetValue(value_name, type, data, true);
+        }
+
+        /// <summary>
+        /// Set a string resistry value as REG_SZ.
+        /// </summary>
+        /// <param name="value_name">The name of the value</param>
+        /// <param name="data">The value data</param>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        public void SetValue(string value_name, string data)
+        {
+            SetValue(value_name, data, true);
+        }
+
+        /// <summary>
+        /// Set a list of strings as a resistry value.
+        /// </summary>
+        /// <param name="value_name">The name of the value</param>
+        /// <param name="data">The list of strings to set.</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        /// <returns>The NT status code.</returns>
+        public NtStatus SetValue(string value_name, IEnumerable<string> data, bool throw_on_error)
+        {
+            string value = string.Join("\0", data) + "\0";
+
+            return SetValue(value_name, RegistryValueType.MultiString, value, throw_on_error);
+        }
+
+        /// <summary>
+        /// Set a list of strings as a resistry value.
+        /// </summary>
+        /// <param name="value_name">The name of the value</param>
+        /// <param name="data">The list of strings to set.</param>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        public void SetValue(string value_name, IEnumerable<string> data)
+        {
+            SetValue(value_name, data, true);
         }

         /// <summary>
@@ -501,10 +579,36 @@
         /// </summary>
         /// <param name="value_name">The name of the value</param>
         /// <param name="data">The value data</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        /// <returns>The NT status code.</returns>
+        public NtStatus SetValue(string value_name, uint data, bool throw_on_error)
+        {
+            return SetValue(value_name, RegistryValueType.Dword, BitConverter.GetBytes(data), throw_on_error);
+        }
+
+        /// <summary>
+        /// Set a QWORD resistry value
+        /// </summary>
+        /// <param name="value_name">The name of the value</param>
+        /// <param name="data">The value data</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        /// <returns>The NT status code.</returns>
+        public NtStatus SetValue(string value_name, ulong data, bool throw_on_error)
+        {
+            return SetValue(value_name, RegistryValueType.Qword, BitConverter.GetBytes(data), throw_on_error);
+        }
+
+        /// <summary>
+        /// Set a DWORD resistry value
+        /// </summary>
+        /// <param name="value_name">The name of the value</param>
+        /// <param name="data">The value data</param>
         /// <exception cref="NtException">Thrown on error.</exception>
         public void SetValue(string value_name, uint data)
         {
-            SetValue(value_name, RegistryValueType.Dword, BitConverter.GetBytes(data));
+            SetValue(value_name, data, true);
         }

         /// <summary>
@@ -515,17 +619,29 @@
         /// <exception cref="NtException">Thrown on error.</exception>
         public void SetValue(string value_name, ulong data)
         {
-            SetValue(value_name, RegistryValueType.Qword, BitConverter.GetBytes(data));
+            SetValue(value_name, data, true);
         }

         /// <summary>
         /// Delete a registry value
         /// </summary>
         /// <param name="value_name">The name of the value</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        /// <returns>The NT status code.</returns>
+        public NtStatus DeleteValue(string value_name, bool throw_on_error)
+        {
+            return NtSystemCalls.NtDeleteValueKey(Handle, new UnicodeString(value_name ?? string.Empty)).ToNtException(throw_on_error);
+        }
+
+        /// <summary>
+        /// Delete a registry value
+        /// </summary>
+        /// <param name="value_name">The name of the value</param>
         /// <exception cref="NtException">Thrown on error.</exception>
         public void DeleteValue(string value_name)
         {
-            NtSystemCalls.NtDeleteValueKey(Handle, new UnicodeString(value_name ?? String.Empty)).ToNtException();
+            DeleteValue(value_name, true);
         }

         /// <summary>
@@ -668,9 +784,22 @@
         /// appropriate create flags)
         /// </summary>
         /// <param name="target">The symbolic link target.</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <returns>The NT status code.</returns>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        public NtStatus SetSymbolicLinkTarget(string target, bool throw_on_error)
+        {
+            return SetValue("SymbolicLinkValue", RegistryValueType.Link, Encoding.Unicode.GetBytes(target), throw_on_error);
+        }
+
+        /// <summary>
+        /// Set a symbolic link target for this key (must have been created with
+        /// appropriate create flags)
+        /// </summary>
+        /// <param name="target">The symbolic link target.</param>
         public void SetSymbolicLinkTarget(string target)
         {
-            SetValue("SymbolicLinkValue", RegistryValueType.Link, Encoding.Unicode.GetBytes(target));
+            SetSymbolicLinkTarget(target, true);
         }

         /// <summary>
@@ -748,9 +877,36 @@
         /// Rename key.
         /// </summary>
         /// <param name="new_name">The new name for the key.</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <returns>The NT status code.</returns>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        public NtStatus Rename(string new_name, bool throw_on_error)
+        {
+            return NtSystemCalls.NtRenameKey(Handle, new UnicodeString(new_name)).ToNtException(throw_on_error);
+        }
+
+        /// <summary>
+        /// Rename key.
+        /// </summary>
+        /// <param name="new_name">The new name for the key.</param>
+        /// <exception cref="NtException">Thrown on error.</exception>
         public void Rename(string new_name)
         {
-            NtSystemCalls.NtRenameKey(Handle, new UnicodeString(new_name)).ToNtException();
+            Rename(new_name, true);
+        }
+
+        /// <summary>
+        /// Save the opened key into a file.
+        /// </summary>
+        /// <param name="file">The file to save to.</param>
+        /// <param name="flags">Save key flags</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <returns>The NT status code.</returns>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        public NtStatus Save(NtFile file, SaveKeyFlags flags, bool throw_on_error)
+        {
+            return NtSystemCalls.NtSaveKeyEx(Handle, file.Handle,
+                flags).ToNtException(throw_on_error);
         }

         /// <summary>
@@ -760,8 +916,29 @@
         /// <param name="flags">Save key flags</param>
         public void Save(NtFile file, SaveKeyFlags flags)
         {
-            NtSystemCalls.NtSaveKeyEx(Handle, file.Handle,
-                flags).ToNtException();
+            Save(file, flags, true);
+        }
+
+        /// <summary>
+        /// Save the opened key into a file.
+        /// </summary>
+        /// <param name="path">The file path to save to.</param>
+        /// <param name="flags">Save key flags</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <returns>The NT status code.</returns>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        public NtStatus Save(string path, SaveKeyFlags flags, bool throw_on_error)
+        {
+            using (var file = NtFile.Create(path, null, FileAccessRights.GenericWrite | FileAccessRights.Synchronize,
+                FileAttributes.Normal, FileShareMode.None, FileOpenOptions.SynchronousIoNonAlert, FileDisposition.Create, null, throw_on_error))
+            {
+                if (!file.IsSuccess)
+                {
+                    return file.Status;
+                }
+
+                return Save(file.Result, flags, throw_on_error);
+            }
         }

         /// <summary>
@@ -771,11 +948,7 @@
         /// <param name="flags">Save key flags</param>
         public void Save(string path, SaveKeyFlags flags)
         {
-            using (NtFile file = NtFile.Create(path, null, FileAccessRights.GenericWrite | FileAccessRights.Synchronize,
-                FileAttributes.Normal, FileShareMode.None, FileOpenOptions.SynchronousIoNonAlert, FileDisposition.Create, null))
-            {
-                Save(file, flags);
-            }
+            Save(path, flags, true);
         }

         /// <summary>
@@ -785,6 +958,19 @@
         public void Save(string path)
         {
             Save(path, SaveKeyFlags.StandardFormat);
+        }
+
+        /// <summary>
+        /// Restore key from a file.
+        /// </summary>
+        /// <param name="file">The file to restore from</param>
+        /// <param name="flags">Restore key flags</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <returns>The NT status code.</returns>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        public NtStatus Restore(NtFile file, RestoreKeyFlags flags, bool throw_on_error)
+        {
+            return NtSystemCalls.NtRestoreKey(Handle, file.Handle, flags).ToNtException(throw_on_error);
         }

         /// <summary>
@@ -794,7 +980,28 @@
         /// <param name="flags">Restore key flags</param>
         public void Restore(NtFile file, RestoreKeyFlags flags)
         {
-            NtSystemCalls.NtRestoreKey(Handle, file.Handle, flags).ToNtException();
+            Restore(file, flags, true);
+        }
+
+        /// <summary>
+        /// Restore key from a file.
+        /// </summary>
+        /// <param name="path">The file path to restore from</param>
+        /// <param name="flags">Restore key flags</param>
+        /// <param name="throw_on_error">True to throw on error.</param>
+        /// <returns>The NT status code.</returns>
+        /// <exception cref="NtException">Thrown on error.</exception>
+        public NtStatus Restore(string path, RestoreKeyFlags flags, bool throw_on_error)
+        {
+            using (var file = NtFile.Open(path, null, FileAccessRights.GenericRead | FileAccessRights.Synchronize,
+                    FileShareMode.Read, FileOpenOptions.SynchronousIoNonAlert, throw_on_error))
+            {
+                if (!file.IsSuccess)
+                {
+                    return file.Status;
+                }
+                return Restore(file.Result, flags, throw_on_error);
+            }
         }

         /// <summary>
@@ -831,7 +1038,7 @@
         }

         /// <summary>
-        /// Wait for a change on thie registry key.
+        /// Wait for a change on the registry key.
         /// </summary>
         /// <param name="completion_filter">Specify what changes will be notified.</param>
         /// <param name="watch_tree">True to watch the entire tree.</param>


Writing NyaaSpam help

Writing NyaaSpam help

--- NyaaSpam/NyaaSpam.cs
+++ NyaaSpam/NyaaSpam.cs
@@ -27,7 +27,15 @@
         get
         {
             return new Dictionary<string, string>()
-            {};
+            {
+                {"nyaa", "See \"nyaa add|del|show\" for help."},
+                {"nyaa add", "add <pattern...> - Adds pattern(s), seperated by \",\". Unless enclosed in quotation " +
+                    "marks (\"), in which case the pattern is added verbatim. (Ex: nyaa add show1, show2)"},
+                {"nyaa del", "del <index...> - Removes pattern(s) inidicated by given indices. Can be seperated by " +
+                    "\",\" and accepts ranges given as \"x-y\". (Ex: nyaa del 4, 7, 0-2)"},
+                {"nyaa show", "show [index...] - Gives an overview of all patterns that are checked for. If given " +
+                    "an index/indices it will show just those. (Ex: nyaa show) (Ex: nyaa show 4, 7, 0-2)"}
+            };
         }
     }


Fix flaky ClientDisconnect freb tests. (#1488)

--- test/Common.FunctionalTests/Inprocess/FrebTests.cs
+++ test/Common.FunctionalTests/Inprocess/FrebTests.cs
@@ -1,6 +1,7 @@
 // Copyright (c) .NET Foundation. All rights reserved.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

+using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
@@ -24,15 +25,15 @@
             _fixture = fixture;
         }

-        public static ISet<string[]> FrebChecks()
+        public static IList<FrebLogItem> FrebChecks()
         {
-            var set = new HashSet<string[]>();
-            set.Add(new string[] { "ANCM_INPROC_EXECUTE_REQUEST_START" });
-            set.Add(new string[] { "ANCM_INPROC_EXECUTE_REQUEST_COMPLETION", "1" });
-            set.Add(new string[] { "ANCM_INPROC_ASYNC_COMPLETION_START" });
-            set.Add(new string[] { "ANCM_INPROC_ASYNC_COMPLETION_COMPLETION", "0" });
-            set.Add(new string[] { "ANCM_INPROC_MANAGED_REQUEST_COMPLETION" });
-            return set;
+            var list = new List<FrebLogItem>();
+            list.Add(new FrebLogItem("ANCM_INPROC_EXECUTE_REQUEST_START"));
+            list.Add(new FrebLogItem("ANCM_INPROC_EXECUTE_REQUEST_COMPLETION", "1"));
+            list.Add(new FrebLogItem("ANCM_INPROC_ASYNC_COMPLETION_START"));
+            list.Add(new FrebLogItem("ANCM_INPROC_ASYNC_COMPLETION_COMPLETION", "0"));
+            list.Add(new FrebLogItem("ANCM_INPROC_MANAGED_REQUEST_COMPLETION"));
+            return list;
         }

         [ConditionalFact]
@@ -45,10 +46,7 @@

             StopServer();

-            foreach (var data in FrebChecks())
-            {
-                AssertFrebLogs(result, data);
-            }
+            AssertFrebLogs(result, FrebChecks());
         }

         [ConditionalFact]
@@ -61,7 +59,7 @@

             StopServer();

-            AssertFrebLogs(result, "ANCM_INPROC_ASYNC_COMPLETION_COMPLETION", "2");
+            AssertFrebLogs(result, new FrebLogItem("ANCM_INPROC_ASYNC_COMPLETION_COMPLETION", "2"));
         }

         [ConditionalFact]
@@ -83,7 +81,9 @@

             StopServer();

-            AssertFrebLogs(result, "ANCM_INPROC_REQUEST_DISCONNECT");
+            // The order of freb logs is based on when the requests are complete.
+            // This is non-deterministic here, so we need to check both freb files for a request that was disconnected.
+            AssertFrebLogs(result, new FrebLogItem("ANCM_INPROC_REQUEST_DISCONNECT"), new FrebLogItem("ANCM_INPROC_MANAGED_REQUEST_COMPLETION"));
         }

         private async Task<IISDeploymentResult> SetupFrebApp()
@@ -96,22 +96,69 @@
             return result;
         }

-        private void AssertFrebLogs(IISDeploymentResult result, params string[] data)
+        private void AssertFrebLogs(IISDeploymentResult result, params FrebLogItem[] expectedFrebEvents)
+        {
+            AssertFrebLogs(result, (IEnumerable<FrebLogItem>)expectedFrebEvents);
+        }
+
+        private void AssertFrebLogs(IISDeploymentResult result, IEnumerable<FrebLogItem> expectedFrebEvents)
+        {
+            var frebEvent = GetFrebLogItems(result);
+            foreach (var expectedEvent in expectedFrebEvents)
+            {
+                Assert.Contains(expectedEvent, frebEvent);
+            }
+        }
+
+        private IEnumerable<FrebLogItem> GetFrebLogItems(IISDeploymentResult result)
         {
             var folderPath = Helpers.GetFrebFolder(_logFolderPath, result);
-            var fileString = Directory.GetFiles(folderPath).Where(f => f.EndsWith("xml")).OrderBy(x => x).Last();
+            var xmlFiles = Directory.GetFiles(folderPath).Where(f => f.EndsWith("xml"));
+            var frebEvents = new List<FrebLogItem>();

-            var xDocument = XDocument.Load(fileString).Root;
-            var nameSpace = (XNamespace)"http://schemas.microsoft.com/win/2004/08/events/event";
-            var elements = xDocument.Descendants(nameSpace + "Event");
-            var element = elements.Where(el => el.Descendants(nameSpace + "RenderingInfo").Single().Descendants(nameSpace + "Opcode").Single().Value == data[0]);
+            foreach (var xmlFile in xmlFiles)
+            {
+                var xDocument = XDocument.Load(xmlFile).Root;
+                var nameSpace = (XNamespace)"http://schemas.microsoft.com/win/2004/08/events/event";
+                var eventElements = xDocument.Descendants(nameSpace + "Event");
+                foreach (var eventElement in eventElements)
+                {
+                    var eventElementWithOpCode = eventElement.Descendants(nameSpace + "RenderingInfo").Single().Descendants(nameSpace + "Opcode").Single();
+                    var requestStatus = eventElement.Element(nameSpace + "EventData").Descendants().Where(el => el.Attribute("Name").Value == "requestStatus").SingleOrDefault();
+                    frebEvents.Add(new FrebLogItem(eventElementWithOpCode.Value, requestStatus?.Value));
+                }
+            }

-            Assert.Single(element);
+            return frebEvents;
+        }

-            if (data.Length > 1)
+        public class FrebLogItem
+        {
+            private string _opCode;
+            private string _requestStatus;
+
+            public FrebLogItem(string opCode)
             {
-                var requestStatus = element.Single().Element(nameSpace + "EventData").Descendants().Where(el => el.Attribute("Name").Value == "requestStatus").Single();
-                Assert.Equal(data[1], requestStatus.Value);
+                _opCode = opCode;
+            }
+
+            public FrebLogItem(string opCode, string requestStatus)
+            {
+                _opCode = opCode;
+                _requestStatus = requestStatus;
+            }
+
+            public override bool Equals(object obj)
+            {
+                var item = obj as FrebLogItem;
+                return item != null &&
+                       _opCode == item._opCode &&
+                       _requestStatus == item._requestStatus;
+            }
+
+            public override int GetHashCode()
+            {
+                return HashCode.Combine(_opCode, _requestStatus);
             }
         }
     }


add binder tests.

add binder tests.

--- test/DotNetCore.CAP.Test/ModelBinderFactoryTest.cs
+++ test/DotNetCore.CAP.Test/ModelBinderFactoryTest.cs
@@ -25,8 +25,8 @@
         [InlineData(nameof(Sample.UriParam))]
         public void CreateSimpleTypeBinderTest(string methodName)
         {
-            var datetimeMethod = typeof(Sample).GetRuntimeMethods().Single(x => x.Name == methodName);
-            var binder = _factory.CreateBinder(datetimeMethod.GetParameters()[0]);
+            var methodInfo = typeof(Sample).GetRuntimeMethods().Single(x => x.Name == methodName);
+            var binder = _factory.CreateBinder(methodInfo.GetParameters()[0]);
             Assert.NotNull(binder);
             Assert.True(binder is SimpleTypeModelBinder);
             Assert.False(binder is ComplexTypeModelBinder);
@@ -36,8 +36,8 @@
         [InlineData(nameof(Sample.ComplexTypeParam))]
         public void CreateComplexTypeBinderTest(string methodName)
         {
-            var datetimeMethod = typeof(Sample).GetRuntimeMethods().Single(x => x.Name == methodName);
-            var binder = _factory.CreateBinder(datetimeMethod.GetParameters()[0]);
+            var methodInfo = typeof(Sample).GetRuntimeMethods().Single(x => x.Name == methodName);
+            var binder = _factory.CreateBinder(methodInfo.GetParameters()[0]);
             Assert.NotNull(binder);
             Assert.False(binder is SimpleTypeModelBinder);
             Assert.True(binder is ComplexTypeModelBinder);


Update Russia tests

Update Russia tests

--- test/TimeZoneNames.Tests/TimeZoneCountriesTests.cs
+++ test/TimeZoneNames.Tests/TimeZoneCountriesTests.cs
@@ -59,18 +59,17 @@

             var expected = new[]
             {
-                "Europe/Kaliningrad",
-                "Europe/Moscow",
-                "Europe/Volgograd",
-                "Europe/Samara",
-                "Asia/Yekaterinburg",
-                "Asia/Omsk",
-                "Asia/Novosibirsk",
-                "Asia/Irkutsk",
-                "Asia/Chita",
-                "Asia/Vladivostok",
-                "Asia/Sakhalin",
-                "Asia/Kamchatka"
+                "Europe/Kaliningrad",  // +02:00
+                "Europe/Moscow",       // +03:00
+                "Europe/Samara",       // +04:00
+                "Asia/Yekaterinburg",  // +05:00
+                "Asia/Omsk",           // +06:00
+                "Asia/Novosibirsk",    // +07:00
+                "Asia/Irkutsk",        // +08:00
+                "Asia/Chita",          // +09:00
+                "Asia/Vladivostok",    // +10:00
+                "Asia/Sakhalin",       // +11:00
+                "Asia/Kamchatka"       // +12:00
             };

             Assert.Equal(expected, zones);


Added ToList for points and shapes cache

--- Test2d.Editor/Editor/Helpers/SelectionHelper.cs
+++ Test2d.Editor/Editor/Helpers/SelectionHelper.cs
@@ -215,7 +215,7 @@
                             {
                                 var shape = _editor.Renderers[0].State.SelectedShape;
                                 var shapes = Enumerable.Repeat(shape, 1);
-                                _pointsCache = Editor.GetAllPoints(shapes, ShapeState.Connector).Distinct();
+                                _pointsCache = Editor.GetAllPoints(shapes, ShapeState.Connector).Distinct().ToList();
                             }
                         }
                         break;
@@ -224,7 +224,7 @@
                             if (!state.HasFlag(ShapeState.Locked) && !state.HasFlag(ShapeState.Connector))
                             {
                                 var shape = _editor.Renderers[0].State.SelectedShape;
-                                var shapes = Enumerable.Repeat(shape, 1);
+                                var shapes = Enumerable.Repeat(shape, 1).ToList();
                                 _shapesCache = shapes;
                             }
                         }
@@ -240,12 +240,12 @@
                 {
                     case MoveMode.Point:
                         {
-                            _pointsCache = Editor.GetAllPoints(shapes, ShapeState.Connector).Distinct();
+                            _pointsCache = Editor.GetAllPoints(shapes, ShapeState.Connector).Distinct().ToList();
                         }
                         break;
                     case MoveMode.Shape:
                         {
-                            _shapesCache = shapes;
+                            _shapesCache = shapes.ToList();
                         }
                         break;
                 }


Fix Live Delta only showing when losing time to PB

Resolves #664

--- LiveSplit/LiveSplit.Core/Model/LiveSplitStateHelper.cs
+++ LiveSplit/LiveSplit.Core/Model/LiveSplitStateHelper.cs
@@ -121,11 +121,11 @@
                 var curSegment = GetLiveSegmentTime(state, state.CurrentSplitIndex, method);
                 var bestSegment = state.Run[state.CurrentSplitIndex].BestSegmentTime[method];
                 var bestSegmentDelta = GetLiveSegmentDelta(state, state.CurrentSplitIndex, BestSegmentsComparisonGenerator.ComparisonName, method);
-                var personalBestDelta = GetLiveSegmentDelta(state, state.CurrentSplitIndex, Run.PersonalBestComparisonName, method);
+                var comparisonDelta = GetLiveSegmentDelta(state, state.CurrentSplitIndex, comparison, method);

                 if (showWhenBehind && currentTime > curSplit
                     || useBestSegment && bestSegment != null && curSegment > bestSegment && bestSegmentDelta > TimeSpan.Zero
-                    || personalBestDelta > TimeSpan.Zero)
+                    || comparisonDelta > TimeSpan.Zero)
                     return currentTime - curSplit;
             }
             return null;


Obstacle spawning!

Obstacle spawning!

--- Tubular/Assets/Scripts/Objects/ObjectSpawner.cs
+++ Tubular/Assets/Scripts/Objects/ObjectSpawner.cs
@@ -1,11 +1,20 @@
 using UnityEngine;
 using System.Collections;

-public class ObstacleSpawner : MonoBehaviour {
+public class ObjectSpawner : MonoBehaviour {
     /// <summary>
     /// List of all object bundles that will be chosen from to spawn.
     /// </summary>
     public SpawnBundle[] bundles;
+
+    /// <summary>
+    /// Chance per second that somsthing will spawn.
+    /// </summary>
+    [Tooltip("Chance per second that something will spawn, out of 1")]
+    [Range(0f, 1f)]
+    public float SpawnChance = 0.01f;
+
+    private float TimeSinceLastCheck = 0f;

     /// <summary>
     /// A bundle of things that can be spawned.
@@ -24,6 +33,19 @@

     // Update is called once per frame
     void Update() {
+        TimeSinceLastCheck += Time.deltaTime;

+        if(TimeSinceLastCheck > 1.0f) {
+            while (TimeSinceLastCheck > 1.0f) {
+                if (Random.value < SpawnChance) {
+                    SpawnBundle bundleToUse = bundles[Random.Range(0, bundles.Length)];
+                    GameObject newGO = GameObject.Instantiate<GameObject>(bundleToUse.prefab);
+                    newGO.transform.SetParent(transform);
+                    newGO.transform.localPosition = new Vector3(Random.Range(bundleToUse.maxDistFromCenter * -1f, bundleToUse.maxDistFromCenter), 0, 0);
+                }
+
+                TimeSinceLastCheck -= 1.0f;
+            }
+        }
     }
 }


XamlCSS: DomElement: run AddIfNotAdded() after UpdateTreeAssociation()

--- XamlCSS/Dom/DomElement.cs
+++ XamlCSS/Dom/DomElement.cs
@@ -50,10 +50,10 @@
             this.classList = GetClassList(dependencyObject);
             this.assemblyQualifiedNamespaceName = GetAssemblyQualifiedNamespaceName(dependencyObject.GetType());

-            AddIfNotAdded();
-
             UpdateTreeAssociation();
             UpdateIsReady();
+
+            AddIfNotAdded();
         }

         protected void ElementLoaded(object element)


Update Edit.cshtml

Update Edit.cshtml

--- Tyvj/Views/Solution/Edit.cshtml
+++ Tyvj/Views/Solution/Edit.cshtml
@@ -23,6 +23,10 @@
             {
                 @Html.AntiForgeryToken()

+
标题

+

+                        <input type="text" name="Title" class="textbox" />
+

解题思路

                         <textarea name="Content" class="ckeditor">@Model.Content</textarea>


Just testing something

Just testing something

--- UnitTests/IntegerFormatTests.cs
+++ UnitTests/IntegerFormatTests.cs
@@ -163,7 +163,6 @@
             //Assert
             result.ShouldEqual(testInteger.ToString("E", CultureInfo.CreateSpecificCulture("fr-FR")));
         }
-
         [Test]
         public void Format_WhenInvoked_ShouldReturnExponentialFormattedStringWithCultureAndPrecision()
         {


Add SignalR registration

Add SignalR registration

--- src/App.Server/Startup.cs
+++ src/App.Server/Startup.cs
@@ -1,8 +1,5 @@
 // Copyright (c) KriaSoft, LLC.  All rights reserved.
 // Licensed under the Apache License, Version 2.0.  See LICENSE.txt in the project root for license information.
-
-using System;
-using System.Threading.Tasks;

 using Microsoft.Owin;
 using Owin;
@@ -15,7 +12,10 @@
     {
         public void Configuration(IAppBuilder app)
         {
-            // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
+            //// For more information on how to configure your application, visit
+            //// http://go.microsoft.com/fwlink/?LinkID=316888
+
+            app.MapSignalR();
         }
     }
 }


reorganize code

reorganize code


BL-11490 Preserve cover color of Sources

* other than our built-in templates

--- src/BloomExe/Book/Book.cs
+++ src/BloomExe/Book/Book.cs
@@ -136,13 +136,13 @@
 			// to get inserted properly. So we make sure there is one.
 			GetOrCreateUserModifiedStyleElementFromStorage();

-			//if we're showing the user a shell/template book, pick a color for it
-			//If it is editable, then we don't want to change to the next color, we
-			//want to use the color that we used for the sample shell/template we
-			//showed them previously.
-			if (!info.IsEditable)
-			{
-				SelectNextCoverColor(); // we only increment when showing a template or shell
+			// If we're showing the user one of our built-in templates (like Basic Book), pick a color for it.
+			// If it is editable or from bloomlibrary or a BloomPack, then we don't want to change to the next color,
+			// we want to use the color that we used for the sample shell/template we showed them previously.
+			// (BL-11490 Even shells or downloaded books should preserve the original cover color.)
+			if (!info.IsEditable && Path.GetDirectoryName(info.FolderPath) == BloomFileLocator.FactoryTemplateBookDirectory)
+			{
+				SelectNextCoverColor(); // we only increment when showing a built-in template
 				InitCoverColor();
 			}


Fix compile error.

Fix compile error.

--- backend/src/Squidex.Domain.Apps.Core.Operations/Tags/TagsExport.cs
+++ backend/src/Squidex.Domain.Apps.Core.Operations/Tags/TagsExport.cs
@@ -7,7 +7,7 @@

 namespace Squidex.Domain.Apps.Core.Tags
 {
-    public sealed class TagsExport
+    public class TagsExport
     {
         public Dictionary<string, Tag>? Tags { get; set; }


suite: add missing arch in heading info for micromips-alu-instructions-EB.s.cs

--- suite/MC/Mips/micromips-alu-instructions-EB.s.cs
+++ suite/MC/Mips/micromips-alu-instructions-EB.s.cs
@@ -1,4 +1,4 @@
-# CS_MODE_32+CS_MODE_BIG_ENDIAN+CS_MODE_MICRO, None
+# CS_ARCH_MIPS, CS_MODE_32+CS_MODE_BIG_ENDIAN+CS_MODE_MICRO, None
 0x00,0xe6,0x49,0x10 = add $9, $6, $7
 0x11,0x26,0x45,0x67 = addi $9, $6, 17767
 0x31,0x26,0xc5,0x67 = addiu $9, $6, -15001


添加了 GetEnumType(...) 和 Format(...) 这两个方法。一般人我不告诉他..

--- src/Common/EnumUtility.cs
+++ src/Common/EnumUtility.cs
@@ -36,6 +36,36 @@
 {
 	public static class EnumUtility
 	{
+		public static Type GetEnumType(Type type)
+		{
+			if(type == null)
+				return null;
+
+			if(type.IsEnum)
+				return type;
+
+			if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>) && type.GetGenericArguments()[0].IsEnum)
+				return type.GetGenericArguments()[0];
+
+			return null;
+		}
+
+		public static string Format(object value, string format)
+		{
+			if(value == null)
+				return string.Empty;
+
+			var enumType = GetEnumType(value.GetType());
+
+			if(enumType != null)
+				return GetEnumEntry((Enum)value).ToString(format);
+
+			if(string.IsNullOrWhiteSpace(format))
+				return string.Format("{0}", value);
+			else
+				return string.Format("{0:" + format + "}", value);
+		}
+
 		/// <summary>
 		/// 获取指定枚举项对应的<see cref="EnumEntry"/>描述对象。
 		/// </summary>


Support ReactiveObject

Support ReactiveObject

--- src/Core2D/ViewLocator.cs
+++ src/Core2D/ViewLocator.cs
@@ -3,6 +3,7 @@
 using Avalonia.Controls;
 using Avalonia.Controls.Templates;
 using Core2D.ViewModels;
+using ReactiveUI;

 namespace Core2D
 {
@@ -21,7 +22,7 @@

         public bool Match(object data)
         {
-            return data is ViewModelBase;
+            return data is ViewModelBase or ReactiveObject;
         }
     }
 }


Using symbol for (c)

Using symbol for (c)

--- src/Elmah/AssemblyInfo.cs
+++ src/Elmah/AssemblyInfo.cs
@@ -34,7 +34,7 @@
 [assembly: AssemblyDescription("Error Logging Modules and Handlers (ELMAH) for ASP.NET")]
 [assembly: AssemblyCompany("")]
 [assembly: AssemblyProduct("ELMAH")]
-[assembly: AssemblyCopyright("Copyright (c) 2004, Atif Aziz. All rights reserved.")]
+[assembly: AssemblyCopyright("Copyright \u00a9 2004, Atif Aziz. All rights reserved.")]
 [assembly: AssemblyCulture("")]

 [assembly: AssemblyVersion("2.0.11227.0")]


Add failing tests

Add failing tests

--- test/AvaloniaEdit.Tests/Text/TextLineRunTests.cs
+++ test/AvaloniaEdit.Tests/Text/TextLineRunTests.cs
@@ -37,6 +37,36 @@
         }

         [Test]
+        public void Tab_Line_Run_Should_Have_Same_Width_As_Indentation_Size()
+        {
+            using var app = UnitTestApplication.Start(new TestServices().With(
+                renderInterface: new MockPlatformRenderInterface(),
+                fontManagerImpl: new MockFontManagerImpl(),
+                formattedTextImpl: Mock.Of<IFormattedTextImpl>()));
+
+            SimpleTextSource s1 = new SimpleTextSource(
+                "\ta",
+                CreateDefaultTextProperties());
+
+            SimpleTextSource s2 = new SimpleTextSource(
+                "    a",
+                CreateDefaultTextProperties());
+
+            var textParagraphProperties = new TextParagraphProperties()
+            {
+                DefaultIncrementalTab = 4 * MockGlyphTypeface.GlyphAdvance,
+                Indent = 4
+            };
+
+            TextLineRun run1 = TextLineRun.Create(s1, 0, 0, 2, textParagraphProperties);
+            TextLineRun run2 = TextLineRun.Create(s2, 0, 0, 5, textParagraphProperties);
+
+            Assert.AreEqual(
+                run1.GetDistanceFromCharacter(1),
+                run2.GetDistanceFromCharacter(4));
+        }
+
+        [Test]
         public void Tab_Line_Run_Should_Have_Fixed_Glyph_Width()
         {
             using var app = UnitTestApplication.Start(new TestServices().With(
@@ -183,20 +213,17 @@
         }

         [Test]
-        public void Tab_Glyph_Run_Shuld_Have_Valid_Bounds()
-        {
-            using var app = UnitTestApplication.Start(new TestServices().With(
-                renderInterface: new MockPlatformRenderInterface(),
-                fontManagerImpl: new MockFontManagerImpl(),
-                formattedTextImpl: Mock.Of<IFormattedTextImpl>()));
-
-            double runWidth = 50;
+        public void Tab_Glyph_Run_Shuld_Have_Zero_Width()
+        {
+            using var app = UnitTestApplication.Start(new TestServices().With(
+                renderInterface: new MockPlatformRenderInterface(),
+                fontManagerImpl: new MockFontManagerImpl(),
+                formattedTextImpl: Mock.Of<IFormattedTextImpl>()));
+
             double runHeight = 20;

             Mock<TextLine> textLineMock = new Mock<TextLine>();
             textLineMock.Setup(
-                t => t.WidthIncludingTrailingWhitespace).Returns(runWidth);
-            textLineMock.Setup(
                 t => t.Height).Returns(runHeight);

             TabTextElement tabTextElement = new TabTextElement(textLineMock.Object);
@@ -207,7 +234,7 @@

             Size runSize = tabRun.GetSize(double.PositiveInfinity);

-            Assert.AreEqual(runWidth, runSize.Width, "Wrong run width");
+            Assert.AreEqual(0, runSize.Width, "Wrong run width");
             Assert.AreEqual(runHeight, runSize.Height, "Wrong run height");
         }


Bug fix: erase db before StartVersion unit test

--- test/Evolve.IntegrationTest.SQLServer/MigrationTest.cs
+++ test/Evolve.IntegrationTest.SQLServer/MigrationTest.cs
@@ -71,6 +71,11 @@
             Assert.True(evolve.NbSchemaErased == evolve.Schemas.Count(), $"{evolve.Schemas.Count()} schemas should have been erased, not {evolve.NbSchemaErased}.");
             Assert.True(evolve.NbMigration == 1, $"1 migration should have been applied, not {evolve.NbMigration}.");

+            // Erase sucessfull
+            evolve.IsEraseDisabled = false;
+            evolve.Erase();
+            Assert.True(evolve.NbSchemaErased == evolve.Schemas.Count(), $"{evolve.Schemas.Count()} schemas should have been erased, not {evolve.NbSchemaErased}.");
+
             // StartVersion = 2.0
             evolve.Locations = new List<string> { TestContext.MigrationFolder }; // Migrate Sql_Scripts\Migration
             evolve.StartVersion = new MigrationVersion("2.0");


Disallow Loop and Then on endless TransformSequences

--- osu.Framework/Graphics/Transforms/TransformSequence.cs
+++ osu.Framework/Graphics/Transforms/TransformSequence.cs
@@ -24,6 +24,8 @@
         private double currentTime;
         private double endTime;

+        private bool hasEnd => endTime != double.PositiveInfinity;
+
         public TransformSequence(T origin)
         {
             if (origin == null)
@@ -33,12 +35,27 @@
             startTime = currentTime = endTime = origin.TransformStartTime;
         }

+        private void onLoopingTransform()
+        {
+            // As soon as we have an infinitely looping transform,
+            // completion no longer makes sense.
+            if (last != null)
+                last.OnComplete = null;
+
+            last = null;
+            endTime = double.PositiveInfinity;
+            hasCompleted = false;
+        }
+
         public TransformSequence<T> Append(Transform transform)
         {
             transforms.Add(transform);

             transform.OnComplete = null;
             transform.OnAbort = onTransformAborted;
+
+            if (transform.IsLooping)
+                onLoopingTransform();

             // Update last transform for completion callback
             if (transform.EndTime > endTime)
@@ -124,6 +141,9 @@

         public TransformSequence<T> Loop(double pause = 0)
         {
+            if (!hasEnd)
+                throw new InvalidOperationException($"Can not perform {nameof(Loop)} on an endless {nameof(TransformSequence<T>)}.");
+
             var iterDuration = endTime - startTime + pause;
             foreach (var t in transforms)
             {
@@ -131,13 +151,17 @@
                 t.LoopDelay = iterDuration;
             }

+            onLoopingTransform();
             return this;
         }

         public TransformSequence<T> Loop(int numIters, double pause = 0)
         {
             if (numIters < 1)
-                throw new InvalidOperationException($"May not loop for fewer than 1 iteration ({numIters} attempted).");
+                throw new InvalidOperationException($"May not {nameof(Loop)} for fewer than 1 iteration ({numIters} attempted).");
+
+            if (!hasEnd)
+                throw new InvalidOperationException($"Can not perform {nameof(Loop)} on an endless {nameof(TransformSequence<T>)}.");

             var iterDuration = endTime - startTime + pause;
             var toLoop = transforms.ToArray();
@@ -195,6 +219,9 @@

         private TransformSequence<T> then(double nextDelay, IEnumerable<Generator> nextChildGenerators)
         {
+            if (!hasEnd)
+                throw new InvalidOperationException($"Can not perform {nameof(Then)} on an endless {nameof(TransformSequence<T>)}.");
+
             // After a then statement, future transforms are appended after our last one finished
             // plus the specified extra delay.
             endTime += nextDelay;
@@ -206,13 +233,20 @@

         public TransformSequence<T> Then(params Generator[] childGenerators) => then(0, childGenerators);

-        public void Then(Action<T> func) => subscribeComplete(() => func(origin));
+        public void Then(Action<T> func)
+        {
+            if (!hasEnd)
+                throw new InvalidOperationException($"Can not perform {nameof(Then)} on an endless {nameof(TransformSequence<T>)}.");
+
+            subscribeComplete(() => func(origin));
+        }

         public void Catch(Action<T> func) => subscribeAbort(() => func(origin));

         public void Finally(Action<T> func)
         {
-            Then(func);
+            if (hasEnd)
+                Then(func);
             Catch(func);
         }
     }


Fire SelectionKeyPressed event on pressing Key.Up and Key.Down

--- osu.Framework/Graphics/UserInterface/DropdownHeader.cs
+++ osu.Framework/Graphics/UserInterface/DropdownHeader.cs
@@ -1,15 +1,20 @@
 // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE

-using OpenTK.Graphics;
+using System;
 using osu.Framework.Graphics.Containers;
 using osu.Framework.Graphics.Shapes;
+using osu.Framework.Input.EventArgs;
 using osu.Framework.Input.States;
+using OpenTK.Graphics;
+using OpenTK.Input;

 namespace osu.Framework.Graphics.UserInterface
 {
     public abstract class DropdownHeader : ClickableContainer
     {
+        public event Action<SelectionChange> SelectionKeyPressed;
+
         protected Container Background;
         protected Container Foreground;

@@ -72,5 +77,30 @@
             Background.Colour = BackgroundColour;
             base.OnHoverLost(state);
         }
+
+        public override bool HandleKeyboardInput => IsHovered;
+
+        protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
+        {
+            switch (args.Key)
+            {
+                case Key.Up:
+                    SelectionKeyPressed?.Invoke(SelectionChange.Previous);
+                    return true;
+                case Key.Down:
+                    SelectionKeyPressed?.Invoke(SelectionChange.Next);
+                    return true;
+                default:
+                    return base.OnKeyDown(state, args);
+            }
+        }
+
+        public enum SelectionChange
+        {
+            Previous,
+            Next,
+            First,
+            Last
+        }
     }
 }


Trim whitespace

Trim whitespace

--- osu.Framework/Graphics/Visualisation/DrawVisualiser.cs
+++ osu.Framework/Graphics/Visualisation/DrawVisualiser.cs
@@ -235,7 +235,6 @@
                 .Concat(type.GetFields(BindingFlags.Instance | BindingFlags.Public))                            // And all fields
                 .OrderBy(member => member.Name)
                 .Select(member => new PropertyItem(member, d)));
-
         }

         private void updateHoveredDrawable()


Unbind event on disposal

Unbind event on disposal

--- osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs
+++ osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs
@@ -70,5 +70,13 @@
         protected override RoomManager CreateRoomManager() => new MultiplayerRoomManager();

         protected override LoungeSubScreen CreateLounge() => new MultiplayerLoungeSubScreen();
+
+        protected override void Dispose(bool isDisposing)
+        {
+            base.Dispose(isDisposing);
+
+            if (client != null)
+                client.RoomUpdated -= onRoomUpdated;
+        }
     }
 }


Simplify `TotalScoreCounter` tick playback logic

--- osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs
+++ osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs
@@ -26,32 +26,35 @@

         protected override Easing RollingEasing => AccuracyCircle.ACCURACY_TRANSFORM_EASING;

-        private readonly bool playSound;
-        private bool isTicking;
+        private readonly bool playSamples;
+
         private readonly Bindable<double> tickPlaybackRate = new Bindable<double>();
+
         private double lastSampleTime;
+
         private DrawableSample sampleTick;

-        public TotalScoreCounter(bool playSound = false)
+        public TotalScoreCounter(bool playSamples = false)
         {
             // Todo: AutoSize X removed here due to https://github.com/ppy/osu-framework/issues/3369
             AutoSizeAxes = Axes.Y;
             RelativeSizeAxes = Axes.X;
-            this.playSound = playSound;
+
+            this.playSamples = playSamples;
         }

         [BackgroundDependencyLoader]
         private void load(AudioManager audio)
         {
             AddInternal(sampleTick = new DrawableSample(audio.Samples.Get(@"Results/score-tick-lesser")));
-            lastSampleTime = Time.Current;
         }

         protected override void LoadComplete()
         {
             base.LoadComplete();

-            Current.BindValueChanged(startTickingPlayback);
+            if (playSamples)
+                Current.BindValueChanged(_ => startTicking());
         }

         protected override LocalisableString FormatCount(long count) => count.ToString("N0");
@@ -65,39 +68,36 @@
             s.Spacing = new Vector2(-5, 0);
         });

-        protected override void Update()
+        public override long DisplayedCount
         {
-            base.Update();
+            get => base.DisplayedCount;
+            set
+            {
+                if (base.DisplayedCount == value)
+                    return;

-            if (playSound && isTicking) playTickSample();
+                base.DisplayedCount = value;
+
+                if (playSamples && Time.Current > lastSampleTime + tickPlaybackRate.Value)
+                {
+                    sampleTick?.Play();
+                    lastSampleTime = Time.Current;
+                }
+            }
         }

-        private void startTickingPlayback(ValueChangedEvent<long> _)
+        private void startTicking()
         {
             const double tick_debounce_rate_start = 10f;
             const double tick_debounce_rate_end = 100f;
             const double tick_volume_start = 0.5f;
             const double tick_volume_end = 1.0f;
-            double tickDuration = RollingDuration - AccuracyCircle.ACCURACY_TRANSFORM_DELAY - AccuracyCircle.RANK_CIRCLE_TRANSFORM_DELAY;
+
+            double tickDuration = RollingDuration;

             this.TransformBindableTo(tickPlaybackRate, tick_debounce_rate_start);
             this.TransformBindableTo(tickPlaybackRate, tick_debounce_rate_end, tickDuration, Easing.OutSine);
             sampleTick.VolumeTo(tick_volume_start).Then().VolumeTo(tick_volume_end, tickDuration, Easing.OutSine);
-
-            Scheduler.AddDelayed(stopTickingPlayback, tickDuration);
-
-            isTicking = true;
-        }
-
-        private void stopTickingPlayback() => isTicking = false;
-
-        private void playTickSample()
-        {
-            if (Time.Current > lastSampleTime + tickPlaybackRate.Value)
-            {
-                sampleTick?.Play();
-                lastSampleTime = Time.Current;
-            }
         }
     }
 }


Schedule continuation

Schedule continuation

--- osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs
+++ osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs
@@ -86,7 +86,7 @@
                 Task.Run(() =>
                 {
                     playableBeatmap = beatmapManager.GetWorkingBeatmap(newScore.Beatmap).GetPlayableBeatmap(newScore.Ruleset, newScore.Mods ?? Array.Empty<Mod>());
-                }, loadCancellation.Token).ContinueWith(t =>
+                }, loadCancellation.Token).ContinueWith(t => Schedule(() =>
                 {
                     var rows = new FillFlowContainer
                     {
@@ -125,7 +125,7 @@
                         spinner.Hide();
                         content.Add(d);
                     }, localCancellationSource.Token);
-                }, localCancellationSource.Token);
+                }), localCancellationSource.Token);
             }
         }


Update 0041_WhiteDrawScript.cs

Update 0041_WhiteDrawScript.cs

Small bug fix: "CalcResult" is called again at the end of "Perform" (make sure not to damage/heal mp twice)

--- Memoria.Scripts/Sources/Battle/0041_WhiteDrawScript.cs
+++ Memoria.Scripts/Sources/Battle/0041_WhiteDrawScript.cs
@@ -34,6 +34,8 @@
                 SBattleCalculator.CalcResult(_v);
                 BattleState.Unit2DReq(unit);
             }
+            _v.Caster.Flags = 0;
+            _v.Caster.MpDamage = 0;
         }
     }
-}+}


- Added comments

- Added comments

git-svn-id: 61c3ae23f3a6520e9bc357b51591209af2ede9d8@31 45b04e34-05f1-4d87-a130-40a8491d5c8b

--- Mosa/Runtime/CompilerFramework/ConstantFoldingStage.cs
+++ Mosa/Runtime/CompilerFramework/ConstantFoldingStage.cs
@@ -14,8 +14,8 @@
 namespace Mosa.Runtime.CompilerFramework
 {
     /// <summary>
-    /// Performs IR expansion of instructions to more machine specific representations of
-    /// individual operations.
+    /// Performs IR constant folding of arithmetic instructions to optimize
+    /// the code down to fewer calculations.
     /// </summary>
     public sealed class ConstantFoldingStage : IMethodCompilerStage
     {
@@ -34,34 +34,48 @@

             bool remove = false;

+            // Loop through all blocks
             foreach (BasicBlock block in blockProvider)
             {
                 bool nothing_left = false;
+                // Loop over instructionlist until there is nothing
+                // left to fold.
                 while (!nothing_left)
                 {
                     nothing_left = true;
+                    // Iterate over all instructions within this block
+                    // and look for places to fold.
                     List<Instruction> instructions = block.Instructions;
                     for (int i = 0; i < instructions.Count; i++)
                     {
                         Instruction instruction = instructions[i];
-                        Operand[] op = new Operand[1];
+                        Operand op = null;

+                        // Watch out for arithmetic instructions as they
+                        // are the only place where constant folding is needed.
                         if (instruction is IL.ArithmeticInstruction)
                         {
                             Operand first = instruction.Operands[0];
                             Operand second = instruction.Operands[1];

+                            // To fold, we need an arithmetic instruction operating
+                            // on 2 constants.
                             if (first is ConstantOperand && second is ConstantOperand)
                             {
+                                // Check for type of instruction
                                 if (instruction is IL.AddInstruction)
-                                    Add(ref op[0], first as ConstantOperand, second as ConstantOperand, instruction.Results[0].StackType);
+                                    op = Add(first as ConstantOperand, second as ConstantOperand, instruction.Results[0].StackType);
                                 else if (instruction is IL.SubInstruction)
-                                    Sub(ref op[0], first as ConstantOperand, second as ConstantOperand, instruction.Results[0].StackType);
+                                    op = Sub(first as ConstantOperand, second as ConstantOperand, instruction.Results[0].StackType);
                                 else if (instruction is IL.MulInstruction)
-                                    Mul(ref op[0], first as ConstantOperand, second as ConstantOperand, instruction.Results[0].StackType);
+                                    op = Mul(first as ConstantOperand, second as ConstantOperand, instruction.Results[0].StackType);
                                 else if (instruction is IL.DivInstruction)
-                                    Div(ref op[0], first as ConstantOperand, second as ConstantOperand, instruction.Results[0].StackType);
+                                    op = Div(first as ConstantOperand, second as ConstantOperand, instruction.Results[0].StackType);
+
+                                // We folded, so replace the current instruction
                                 remove = true;
+
+                                // We folded, so check the block again
                                 nothing_left = false;
                             }
                         }
@@ -69,11 +83,15 @@
                         // Shall we remove this instruction?
                         if (true == remove)
                         {
+                            // Remove the arithmetic instruction and replace it
+                            // by a store instruction
                             Instruction new_instruction = new IL.StlocInstruction(Mosa.Runtime.CompilerFramework.IL.OpCode.Stloc);
                             new_instruction.Results = new Operand[1];
                             new_instruction.Results[0] = instruction.Results[0];
-                            new_instruction.Operands[0] = op[0];
+                            new_instruction.Operands[0] = op;
                             instructions[i] = new_instruction;
+
+                            // Reset flag
                             remove = false;
                         }
                     }
@@ -85,79 +103,95 @@

         #region Internals

-        private void Add(ref Operand op, ConstantOperand first, ConstantOperand second, StackTypeCode type)
+        /// <summary>
+        /// Fold 2 constants by adding them
+        /// </summary>
+        /// <param name="first">First constant to fold</param>
+        /// <param name="second">Second constant to fold</param>
+        /// <param name="type">Stacktype for the result</param>
+        private Operand Add(ConstantOperand first, ConstantOperand second, StackTypeCode type)
         {
             switch (type)
             {
                 case StackTypeCode.N:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Internal), (int)first.Value + (int)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Internal), (int)first.Value + (int)second.Value);
                 case StackTypeCode.Int32:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (Int32)first.Value + (Int32)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (Int32)first.Value + (Int32)second.Value);
                 case StackTypeCode.Int64:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I8), (Int64)first.Value + (Int64)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I8), (Int64)first.Value + (Int64)second.Value);
                 case StackTypeCode.F:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.R8), (double)first.Value + (double)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.R8), (double)first.Value + (double)second.Value);
+                default:
+                    throw new NotSupportedException();
             }
         }

-        private void Sub(ref Operand op, ConstantOperand first, ConstantOperand second, StackTypeCode type)
+        /// <summary>
+        /// Fold 2 constants by substracting them
+        /// </summary>
+        /// <param name="first">First constant to fold</param>
+        /// <param name="second">Second constant to fold</param>
+        /// <param name="type">Stacktype for the result</param>
+        private Operand Sub(ConstantOperand first, ConstantOperand second, StackTypeCode type)
         {
             switch (type)
             {
                 case StackTypeCode.N:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Internal), (int)first.Value - (int)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Internal), (int)first.Value - (int)second.Value);
                 case StackTypeCode.Int32:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (Int32)first.Value - (Int32)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (Int32)first.Value - (Int32)second.Value);
                 case StackTypeCode.Int64:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I8), (Int64)first.Value - (Int64)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I8), (Int64)first.Value - (Int64)second.Value);
                 case StackTypeCode.F:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.R8), (double)first.Value - (double)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.R8), (double)first.Value - (double)second.Value);
+                default:
+                    throw new NotSupportedException();
             }
         }

-        private void Mul(ref Operand op, ConstantOperand first, ConstantOperand second, StackTypeCode type)
+        /// <summary>
+        /// Fold 2 constants by multiplying them
+        /// </summary>
+        /// <param name="first">First constant to fold</param>
+        /// <param name="second">Second constant to fold</param>
+        /// <param name="type">Stacktype for the result</param>
+        private Operand Mul(ConstantOperand first, ConstantOperand second, StackTypeCode type)
         {
             switch (type)
             {
                 case StackTypeCode.N:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Internal), (int)first.Value * (int)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Internal), (int)first.Value * (int)second.Value);
                 case StackTypeCode.Int32:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (Int32)first.Value * (Int32)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (Int32)first.Value * (Int32)second.Value);
                 case StackTypeCode.Int64:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I8), (Int64)first.Value * (Int64)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I8), (Int64)first.Value * (Int64)second.Value);
                 case StackTypeCode.F:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.R8), (double)first.Value * (double)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.R8), (double)first.Value * (double)second.Value);
+                default:
+                    throw new NotSupportedException();
             }
         }

-        private void Div(ref Operand op, ConstantOperand first, ConstantOperand second, StackTypeCode type)
+        /// <summary>
+        /// Fold 2 constants by dividing them
+        /// </summary>
+        /// <param name="first">First constant to fold</param>
+        /// <param name="second">Second constant to fold</param>
+        /// <param name="type">Stacktype for the result</param>
+        private Operand Div(ConstantOperand first, ConstantOperand second, StackTypeCode type)
         {
             switch (type)
             {
                 case StackTypeCode.N:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Internal), (int)first.Value / (int)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Internal), (int)first.Value / (int)second.Value);
                 case StackTypeCode.Int32:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (Int32)first.Value / (Int32)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (Int32)first.Value / (Int32)second.Value);
                 case StackTypeCode.Int64:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I8), (Int64)first.Value / (Int64)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I8), (Int64)first.Value / (Int64)second.Value);
                 case StackTypeCode.F:
-                    op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.R8), (double)first.Value / (double)second.Value);
-                    break;
+                    return new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.R8), (double)first.Value / (double)second.Value);
+                default:
+                    throw new NotSupportedException();
             }
         }
         #endregion // Internals


Bumped version

Bumped version

Signed-off-by: Martin Evans <fbe68550a3878a44ead7fa06f7b29f9942900ad3@gmail.com>

--- Myre/Myre.Graphics.Pipeline/Properties/AssemblyInfo.cs
+++ Myre/Myre.Graphics.Pipeline/Properties/AssemblyInfo.cs
@@ -28,4 +28,4 @@
 //      Build Number
 //      Revision
 //
-[assembly: AssemblyVersion("4.0.1")]
+[assembly: AssemblyVersion("4.0.2")]


Method for summing call costs

Method for summing call costs

--- PART/Source/Core/Data/Applications/DataProviderCall.cs
+++ PART/Source/Core/Data/Applications/DataProviderCall.cs
@@ -98,6 +98,19 @@
             }
         }

+        public static decimal SumCost(DateTime fromDate, DateTime? toDate, string provider, string operation)
+        {
+            using (ApplicationDataContext dataContext = new ApplicationDataContext())
+            {
+                var pred = CreatePredicate(dataContext, fromDate, toDate, provider, operation);
+                var ret= dataContext.DataProviderCalls
+                    .Where(pred)
+                    .Select(le => le.Cost);
+                var s = ret.ToArray();
+                    return s.Sum();
+            }
+        }
+
         public static List<DataProviderCall> LoadByPage(DateTime fromDate, DateTime? toDate, string provider, string operation, int startRow, int pageSize)
         {
             using (ApplicationDataContext dataContext = new ApplicationDataContext())


fix: license metadata tooltip

fix: license metadata tooltip

--- PackageExplorer/Converters/LicenseMetadataConverter.cs
+++ PackageExplorer/Converters/LicenseMetadataConverter.cs
@@ -34,11 +34,24 @@
                 }
                 else
                 {
-                    return new StringBuilder()
-                        .AppendLine($"{Resources.Dialog_LicenseExpression} {metadata.LicenseExpression}")
-                        .AppendLine($"{Resources.Dialog_LicenseExpression} {metadata.Type}")
-                        .AppendLine($"{Resources.Dialog_LicenseExpressionVersion} {metadata.Version}")
-                        .ToString().TrimEnd();
+                    var sb = new StringBuilder();
+
+                    if (metadata.Type == LicenseType.Expression)
+                    {
+                        sb
+                            .AppendLine($"{Resources.Dialog_LicenseExpression} {metadata.LicenseExpression}")
+                            .AppendLine($"{Resources.Dialog_LicenseExpressionType} {metadata.Type}")
+                            .AppendLine($"{Resources.Dialog_LicenseExpressionVersion} {metadata.Version}");
+                    }
+                    else if (metadata.Type == LicenseType.File)
+                    {
+                        sb
+                            .AppendLine($"License: {metadata.License}")
+                            .AppendLine($"Type: {metadata.Type}")
+                            .AppendLine($"License Url: {metadata.LicenseUrl}");
+                    }
+
+                    return sb.ToString().TrimEnd();
                 }
             }


removed outdated StorageContainer path

removed outdated StorageContainer path

git-svn-id: 53f2a8ff3606f182ef4420064c1f4a5cdcbe6bb1@2454 bb9bf1cf-960d-0410-9a3a-baeba60cf407

--- Projects/AxiomDemos/Source/Browser/Xbox/Common/Game.cs
+++ Projects/AxiomDemos/Source/Browser/Xbox/Common/Game.cs
@@ -68,11 +68,8 @@

         public void Run()
         {
-#if !( XBOX || XBOX360 )
-            titleLocation = String.Empty;
-#else
-            titleLocation = StorageContainer.TitleLocation + "\\";
-#endif
+            //TODO: remove all references to titleLocation
+            titleLocation = string.Empty;

             try
             {


Format

Format

--- src/HolzShots/MainForm.cs
+++ src/HolzShots/MainForm.cs
@@ -3,8 +3,6 @@
 using System.Data;
 using System.Diagnostics;
 using System.Windows.Forms;
-using System.Windows.Input;
-using HolzShots.Composition.Command;
 using HolzShots.Input;
 using HolzShots.Input.Actions;
 using HolzShots.Windows.Forms;
@@ -203,15 +201,9 @@
             if (_application.CommandManager.IsRegisteredCommand(commandToRun.CommandName))
                 await _application.CommandManager.Dispatch(commandToRun, UserSettings.Current).ConfigureAwait(true); // Can throw exceptions and silently kill the application
         }
-        private void OpenAbout(object sender, EventArgs e)
-        {
-            AboutForm.Instance.Show();
-        }
-
-        private void OpenFeedbackAndIssues(object sender, EventArgs e)
-        {
-            IO.HolzShotsPaths.OpenLink(LibraryInformation.IssuesUrl);
-        }
+
+        private void OpenAbout(object sender, EventArgs e) => AboutForm.Instance.Show();
+        private void OpenFeedbackAndIssues(object sender, EventArgs e) => IO.HolzShotsPaths.OpenLink(LibraryInformation.IssuesUrl);

         private void ExitApplication(object sender, EventArgs e)
         {


Match indentation levels

Match indentation levels

--- osu.Framework.Tests/Visual/TestCaseGridContainer.cs
+++ osu.Framework.Tests/Visual/TestCaseGridContainer.cs
@@ -86,10 +86,10 @@
                 grid.Content = new Drawable[][] { new[] { new FillBox(), new FillBox(), new FillBox() } };
                 grid.RowDimensions = grid.ColumnDimensions = new[]
                 {
-                        new Dimension(0) { Size = 50 },
-                        new Dimension(1) { Size = 100 },
-                        new Dimension(2) { Size = 150 }
-                    };
+                    new Dimension(0) { Size = 50 },
+                    new Dimension(1) { Size = 100 },
+                    new Dimension(2) { Size = 150 }
+                };
             });

             AddStep("3-cell row (relative)", () =>
@@ -98,10 +98,10 @@
                 grid.Content = new Drawable[][] { new[] { new FillBox(), new FillBox(), new FillBox() } };
                 grid.RowDimensions = grid.ColumnDimensions = new[]
                 {
-                        new Dimension(0) { Size = 0.1f, Relative = true },
-                        new Dimension(1) { Size = 0.2f, Relative = true },
-                        new Dimension(2) { Size = 0.3f, Relative = true }
-                    };
+                    new Dimension(0) { Size = 0.1f, Relative = true },
+                    new Dimension(1) { Size = 0.2f, Relative = true },
+                    new Dimension(2) { Size = 0.3f, Relative = true }
+                };
             });

             AddStep("3-cell row (mixed)", () =>
@@ -110,9 +110,9 @@
                 grid.Content = new Drawable[][] { new[] { new FillBox(), new FillBox(), new FillBox() } };
                 grid.RowDimensions = grid.ColumnDimensions = new[]
                 {
-                        new Dimension(0) { Size = 50 },
-                        new Dimension(1) { Size = 0.2f, Relative = true },
-                    };
+                    new Dimension(0) { Size = 50 },
+                    new Dimension(1) { Size = 0.2f, Relative = true },
+                };
             });

             AddStep("3-cell column (auto)", () =>


[trunk] Adding commented out, but useful, debugging of the command line processor execution

--- packages/CommandLineProcessor/dev/Scripts/Processor.cs
+++ packages/CommandLineProcessor/dev/Scripts/Processor.cs
@@ -114,6 +114,18 @@
             }

             Opus.Core.Log.Detail("{0} {1}", executablePath, processStartInfo.Arguments);
+#if false
+            // useful debugging of the command line processor
+            Opus.Core.Log.Detail("Curdir : {0}", processStartInfo.WorkingDirectory);
+            if (processStartInfo.EnvironmentVariables.Count > 0)
+            {
+                Opus.Core.Log.Detail("Envvars");
+                foreach (string envVar in processStartInfo.EnvironmentVariables.Keys)
+                {
+                    Opus.Core.Log.Detail("{0} = {1}", envVar, processStartInfo.EnvironmentVariables[envVar]);
+                }
+            }
+#endif

             System.Diagnostics.Process process = null;
             try


Add clarification comment

Add clarification comment

--- osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs
+++ osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs
@@ -119,6 +119,7 @@

         private void applyCustomUpdateState(DrawableHitObject hitObject, ArmedState state)
         {
+            // ensure that the hold note is also faded out when the head/tail/any tick is missed.
             if (state == ArmedState.Miss)
                 missFadeTime.Value ??= hitObject.HitStateUpdateTime;
         }


Remove underline from breadcrumb display

--- osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs
+++ osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs
@@ -25,6 +25,7 @@
             {
                 Text.Font = Text.Font.With(size: 14);
                 Chevron.Y = 3;
+                Bar.Height = 0;
             }
         }
     }


Localise rankings overlay header.

Localise rankings overlay header.

--- osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs
+++ osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs
@@ -5,6 +5,9 @@
 using osu.Framework.Bindables;
 using osu.Game.Rulesets;
 using osu.Game.Users;
+using osu.Game.Resources.Localisation.Web;
+using osu.Framework.Localisation;
+using System;

 namespace osu.Game.Overlays.Rankings
 {
@@ -29,13 +32,14 @@
         {
             public RankingsTitle()
             {
-                Title = "ranking";
+                Title = PageTitleStrings.MainRankingControllerDefault;
                 Description = "find out who's the best right now";
                 IconTexture = "Icons/Hexacons/rankings";
             }
         }
     }

+    [LocalisableEnum(typeof(RankingsScopeEnumLocalisationMapper))]
     public enum RankingsScope
     {
         Performance,
@@ -43,4 +47,28 @@
         Score,
         Country
     }
+
+    public class RankingsScopeEnumLocalisationMapper : EnumLocalisationMapper<RankingsScope>
+    {
+        public override LocalisableString Map(RankingsScope value)
+        {
+            switch (value)
+            {
+                case RankingsScope.Performance:
+                    return RankingsStrings.TypePerformance;
+
+                case RankingsScope.Spotlights:
+                    return RankingsStrings.TypeCharts;
+
+                case RankingsScope.Score:
+                    return RankingsStrings.TypeScore;
+
+                case RankingsScope.Country:
+                    return RankingsStrings.TypeCountry;
+
+                default:
+                    throw new ArgumentOutOfRangeException(nameof(value), value, null);
+            }
+        }
+    }
 }


Unsubscribe from API state change event.

--- osu.Game/Screens/Select/Leaderboards/Leaderboard.cs
+++ osu.Game/Screens/Select/Leaderboards/Leaderboard.cs
@@ -197,6 +197,9 @@

             if (osuGame != null)
                 osuGame.Ruleset.ValueChanged -= handleRulesetChange;
+
+            if (api != null)
+                api.OnStateChange -= handleApiStateChange;
         }

         private GetScoresRequest getScoresRequest;


Version 0.8.1

Version 0.8.1

--- src/MasterAssemblyInfo.cs
+++ src/MasterAssemblyInfo.cs
@@ -4,6 +4,6 @@
 [assembly: AssemblyCompany("Anil Mujagić")]
 [assembly: AssemblyCopyright("© Anil Mujagić")]

-[assembly: AssemblyVersion("0.8.0.0")]
-[assembly: AssemblyFileVersion("0.8.0.0")]
-[assembly: AssemblyInformationalVersion("0.8.0")]
+[assembly: AssemblyVersion("0.8.1.0")]
+[assembly: AssemblyFileVersion("0.8.1.0")]
+[assembly: AssemblyInformationalVersion("0.8.1")]


Added in more stuff! ...and bug fixes

Added in more stuff! ...and bug fixes

Added in mod, cleaned up code, added in implicit multiplication with
brackets, and general bug fixes (as well as spelling fixes)

next build: implicit multiplication with functions

--- src/MathEvaluator/Calc.cs
+++ src/MathEvaluator/Calc.cs
@@ -34,6 +34,7 @@
         public const string CEIL  = "ceil";
         public const string ROUND = "round";
         public const string ABS   = "abs";
+        public const string MOD   = "mod";
     }

     private static class Constants
@@ -48,7 +49,7 @@
     }

     //Evaluator evaluates the tokens into a doubleing-point number
-    private static double Evaluator(Queue<Object> str)
+    private static double Evaluator(Queue<object> str)
     {
         Stack<double> Stack = new Stack<double>();

@@ -66,7 +67,7 @@
             #region operators
             else
             {
-                Object current = str.ElementAt(TokenCounter);
+                object current = str.ElementAt(TokenCounter);
                 double temp;

                 if (current is string)
@@ -76,11 +77,19 @@
                         if (Stack.Count < 2) throw new Exception("Maldeformed expression");
                         Stack.Push(Math.Pow(Stack.Pop(), 1/Stack.Pop()));
                     }
+                    else if (current.Equals(Functions.MOD))
+                    {
+                        if (Stack.Count < 2) throw new Exception("Maldeformed expression");
+                        temp = Stack.Pop();
+                        if(temp == 0.0) throw new DivideByZeroException("Division by zero in expression");
+                        Stack.Push(Stack.Pop() % temp);
+                    }
                     else
                     {
                         if (Stack.Count < 1) throw new Exception("Maldeformed expression");
                         temp = Stack.Pop();

+                        //perform the function
                         if (current.Equals(Functions.LOG)) Stack.Push(Math.Log10(temp));
                         else if (current.Equals(Functions.LN)) Stack.Push(Math.Log(temp));
                         else if (current.Equals(Functions.SQRT)) Stack.Push(Math.Sqrt(temp));
@@ -115,16 +124,16 @@
             #endregion
         }

-        if (Stack.Count > 1) throw new Exception("too many values entered");
+        if (Stack.Count > 1) throw new Exception("Maldeformed expression");

         return (double)Stack.Pop();
     }

     //ToRPN converts the tokens into an RPN queue (using the Shunting Yard Algorithm)
-    private static Queue<Object> ToRPN(Queue<Object> str)
-    {
-        Stack<Object> Stack = new Stack<Object>();
-        Queue<Object> Queue = new Queue<Object>();
+    private static Queue<object> ToRPN(Queue<object> str)
+    {
+        Stack<object> Stack = new Stack<object>();
+        Queue<object> Queue = new Queue<object>();

         for (int TokenCounter = 0; TokenCounter < str.Count; TokenCounter++)
         {
@@ -133,20 +142,31 @@
             if (str.ElementAt(TokenCounter) is double) Queue.Enqueue(str.ElementAt(TokenCounter));
             #endregion

-            //if the token is a left parenthesis, push it onto the stack
-                //TODO: if there is something like "15(...)", make it "15 * (...)"
+            //if the token is a left parentheses, push it onto the stack
             #region Left Paren
-            else if (str.ElementAt(TokenCounter).Equals(Symbols.LEFT_PAREN)) Stack.Push(Symbols.LEFT_PAREN);
+            else if (str.ElementAt(TokenCounter).Equals(Symbols.LEFT_PAREN))
+            {
+                //if it's something like "15(5 + 2)" the 15 should be multiplied to make the expression "15 * (5 + 2)"
+                //fix this later, but the only way I can think of doing this is going back, appending a '*', and continuing
+                if (TokenCounter >= 1 && (str.ElementAt(TokenCounter - 1) is double || str.ElementAt(TokenCounter - 1).Equals(Symbols.RIGHT_PAREN)))
+                {
+                    List<object> list = new List<object>(str);
+                    list.Insert(TokenCounter, Symbols.MUL);
+                    str = new Queue<object>(list);
+                    TokenCounter--;
+                }
+                else Stack.Push(Symbols.LEFT_PAREN);
+            }
             #endregion
             #region Right Paren
             else if (str.ElementAt(TokenCounter).Equals(Symbols.RIGHT_PAREN))
             {
                 bool IsParenMatched = false;

-                //Until the token at the top of the stack is a left parenthesis, pop operators off the stack onto the output queue.
+                //Until the token at the top of the stack is a left parentheses, pop operators off the stack onto the output queue.
                 while (Stack.Count > 0 && !IsParenMatched)
                 {
-                    //Pop the left parenthesis from the stack, but not onto the output queue.
+                    //Pop the left parentheses from the stack, but not onto the output queue.
                     if (Stack.Peek().Equals(Symbols.LEFT_PAREN))
                     {
                         Stack.Pop();
@@ -155,7 +175,7 @@
                     else Queue.Enqueue(Stack.Pop());
                 }

-                //If the stack runs out without finding a left parenthesis, then there are mismatched parentheses.
+                //If the stack runs out without finding a left parentheses, then there are mismatched parentheses.
                 if (!IsParenMatched) throw new Exception("Parentheses mismatch");
             }
             #endregion
@@ -163,10 +183,12 @@
             #region characters
             else
             {
-                Object current = str.ElementAt(TokenCounter);
+                object current = str.ElementAt(TokenCounter);
+
+                //Use the shunting yard algorithm to turn this into an RPN queue

                 /* HIGHEST PRECEDENCE */
-                if(current.Equals(Symbols.MOD) || current.Equals(Symbols.MUL) || current.Equals(Symbols.DIV))
+                if (current.Equals(Symbols.MOD) || current.Equals(Symbols.MUL) || current.Equals(Symbols.DIV))
                 {
                     while (Stack.Count > 0 &&
                         !Stack.Peek().Equals(Symbols.LEFT_PAREN) &&
@@ -174,7 +196,7 @@
                     {
                         Queue.Enqueue(Stack.Pop());
                     }
-
+
                 }

                 /* LOWEST PRECEDENCE */
@@ -207,11 +229,11 @@
     }

     //Parser tokenizes the input string for evaluating
-    private static Queue<Object> Parser(string str)
+    private static Queue<object> Parser(string str)
     {
         if (str == null || str.Length == 0) throw new ArgumentException("Empty string");

-        Queue<Object> Queue = new Queue<object>();
+        Queue<object> Queue = new Queue<object>();
         StringBuilder Stringbuilder = new StringBuilder(new string(str.Where(x => !Char.IsWhiteSpace(x)).ToArray()));

@@ -240,31 +262,6 @@

                         if (TokenCounter + 1 >= Stringbuilder.Length) break;
                     }
-                }
-
-                //two tokens in a row and the second token being '-' means it a negative number
-                //eg: "1 * - 1" means tokens  {"1", "*", "-1" } not {"1","*","-", "1"}
-
-                bool negate = false;
-                //if we're at the beginning
-                if (TokenCounter == 2)
-                {
-                    if (Queue.ElementAt(Queue.Count - 1).Equals(Symbols.SUB)) negate = true;
-                }
-                //otherwise
-                else if(TokenCounter > 2)
-                {
-                    if (Queue.ElementAt(Queue.Count - 1).Equals(Symbols.SUB) && !(Queue.ElementAt(Queue.Count - 2) is double)) negate = true;
-                }
-
-                if (negate)
-                {
-                    ParseDigits = Symbols.SUB + ParseDigits;
-
-                    //because you can only remove the start of a queue, reverse it, dequeue, and reverse that
-                    Queue = new Queue<object>(Queue.Reverse());
-                    Queue.Dequeue();
-                    Queue = new Queue<object>(Queue.Reverse());
                 }
                 Queue.Enqueue(double.Parse(ParseDigits));
             }
@@ -299,6 +296,7 @@
                     case Functions.CEIL:
                     case Functions.ROUND:
                     case Functions.ABS:
+                    case Functions.MOD:
                         Queue.Enqueue(word);
                         break;

@@ -411,6 +409,11 @@
         return Queue;
     }

+    /// <summary>
+    /// Calculates a mathematical expression
+    /// </summary>
+    /// <param name="str">A valid mathematical expression</param>
+    /// <returns>The result of the calculation</returns>
     public static double Calculate(string str)
     {
         try


added NancyContext.ModelValidationResult

--- src/Nancy/NancyContext.cs
+++ src/Nancy/NancyContext.cs
@@ -1,12 +1,13 @@
-using Nancy.Responses.Negotiation;
-using Nancy.Security;

 namespace Nancy
 {
     using System;
     using System.Collections.Generic;
     using System.Linq;
-    using Diagnostics;
+    using Nancy.Diagnostics;
+    using Nancy.Responses.Negotiation;
+    using Nancy.Security;
+    using Nancy.Validation;

     /// <summary>
     /// Nancy context.
@@ -14,6 +15,8 @@
     public sealed class NancyContext : IDisposable
     {
         private Request request;
+
+        private ModelValidationResult modelValidationResult;

         /// <summary>
         /// Initializes a new instance of the <see cref="NancyContext"/> class.
@@ -82,6 +85,15 @@
         public dynamic ViewBag { get; private set; }

         /// <summary>
+        /// Gets or sets the model validation result.
+        /// </summary>
+        public ModelValidationResult ModelValidationResult
+        {
+            get { return this.modelValidationResult ?? new ModelValidationResult(null); }
+            set { this.modelValidationResult = value; }
+        }
+
+        /// <summary>
         /// Context of content negotiation (if relevent)
         /// </summary>
         public NegotiationContext NegotiationContext { get; set; }