customizable sessionnumber on auth

customizable sessionnumber on auth

--- Synology/Auth/AuthRequest.cs
+++ Synology/Auth/AuthRequest.cs
@@ -6,7 +6,7 @@
 {
 	public class AuthRequest : SynologyRequest
 	{
-		readonly string _sessionNumber;
+		private string _sessionNumber;

 		internal AuthRequest(SynologyConnection connection) : base(connection, "auth.cgi", "SYNO.API.Auth")
 		{
@@ -14,10 +14,11 @@
 			_sessionNumber = string.Format("session{0}", rand.Next());
 		}

-		public ResultData<LoginResult> Login(string username, string password, string otpCode = null)
+		public ResultData<LoginResult> Login(string username, string password, string otpCode = null, string sessionName = null)
 		{
-			var parameters = new[]
-			{
+			_sessionNumber = sessionName ?? _sessionNumber;
+
+			var parameters = new[] {
 				new QueryStringParameter("otp_code", otpCode),
 				new QueryStringParameter("account", username),
 				new QueryStringParameter("passwd", password),
@@ -38,8 +39,7 @@

 		public ResultData Logout()
 		{
-			var parameters = new[]
-			{
+			var parameters = new[] {
 				new QueryStringParameter("session", _sessionNumber),
 			};


Delete AssemblyInfo.cs

Delete AssemblyInfo.cs

--- Singleplayer/Game/Properties/AssemblyInfo.cs
+++ Singleplayer/Game/Properties/AssemblyInfo.cs
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Game")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Game")]
-[assembly: AssemblyCopyright("Copyright ©  2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components.  If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("843a7662-1d8d-4a7e-904a-b37ba358392c")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]


[ci skip] Updating ServerBuildInfo_Dynamic.cs

1.32.4102.20211102235001-master-2a59dc0

--- Source/ACE.Server/ServerBuildInfo_Dynamic.cs
+++ Source/ACE.Server/ServerBuildInfo_Dynamic.cs
@@ -4,17 +4,17 @@
     public static partial class ServerBuildInfo
     {
         public static string Branch = "master";
-        public static string Commit = "f06ee93884109eb5e4e7e5bcc39ddc0453c358c6";
+        public static string Commit = "2a59dc089ab671c14c12928e26170a76ffe3551f";

         public static string Version = "1.32";
-        public static string Build   = "4101";
+        public static string Build   = "4102";

         public static int BuildYear   = 2021;
         public static int BuildMonth  = 11;
-        public static int BuildDay    = 01;
-        public static int BuildHour   = 16;
-        public static int BuildMinute = 23;
-        public static int BuildSecond = 51;
+        public static int BuildDay    = 02;
+        public static int BuildHour   = 23;
+        public static int BuildMinute = 50;
+        public static int BuildSecond = 01;
     }
 }


[ci skip] Updating ServerBuildInfo_Dynamic.cs

1.46.4257.20220822035327-master-5b6de5d

--- Source/ACE.Server/ServerBuildInfo_Dynamic.cs
+++ Source/ACE.Server/ServerBuildInfo_Dynamic.cs
@@ -4,17 +4,17 @@
     public static partial class ServerBuildInfo
     {
         public static string Branch = "master";
-        public static string Commit = "3fd3bed72aa3ea9b4b5c177905972586888aeecd";
+        public static string Commit = "5b6de5ddac1667c5a32aa806327ccd804ec6f751";

-        public static string Version = "1.45";
-        public static string Build   = "4256";
+        public static string Version = "1.46";
+        public static string Build   = "4257";

         public static int BuildYear   = 2022;
         public static int BuildMonth  = 08;
         public static int BuildDay    = 22;
         public static int BuildHour   = 03;
-        public static int BuildMinute = 48;
-        public static int BuildSecond = 28;
+        public static int BuildMinute = 53;
+        public static int BuildSecond = 27;
     }
 }


[ci skip] Updating ServerBuildInfo_Dynamic.cs

1.3.3394.20200525060437-master-de1dce5

--- Source/ACE.Server/ServerBuildInfo_Dynamic.cs
+++ Source/ACE.Server/ServerBuildInfo_Dynamic.cs
@@ -4,17 +4,17 @@
     public static partial class ServerBuildInfo
     {
         public static string Branch = "master";
-        public static string Commit = "c3692e787fa9effae97ebc64fa1a01d1bfc12267";
+        public static string Commit = "de1dce5348181069974ca4eb2ae69e00c051068f";

         public static string Version = "1.3";
-        public static string Build   = "3393";
+        public static string Build   = "3394";

         public static int BuildYear   = 2020;
         public static int BuildMonth  = 05;
         public static int BuildDay    = 25;
         public static int BuildHour   = 06;
-        public static int BuildMinute = 01;
-        public static int BuildSecond = 29;
+        public static int BuildMinute = 04;
+        public static int BuildSecond = 37;
     }
 }


Add IDigiMarket interface

Add IDigiMarket interface

--- Common/DigiMarket.cs
+++ Common/DigiMarket.cs
@@ -3,7 +3,14 @@

 namespace Common
 {
-    public class DigiMarket : MarshalByRefObject
+    public interface IDigiMarket
+    {
+        RegisterError Register(String username, String password);
+        LoginError Login(String username, String password);
+        LogoutError Logout(String username, String password);
+    }
+
+    public class DigiMarket : MarshalByRefObject, IDigiMarket
     {
         public readonly decimal Quotation = 1;
         public readonly Dictionary<String, User> Users = new Dictionary<string, User>();


[ci skip] Updating ServerBuildInfo_Dynamic.cs

1.12.3615.20200915161248-master-a8b1439

--- Source/ACE.Server/ServerBuildInfo_Dynamic.cs
+++ Source/ACE.Server/ServerBuildInfo_Dynamic.cs
@@ -4,17 +4,17 @@
     public static partial class ServerBuildInfo
     {
         public static string Branch = "master";
-        public static string Commit = "0fe6865423446a6fc98432fa69e088a79f65b523";
+        public static string Commit = "a8b1439839f0a3ade62337ea215f9e44378eada8";

         public static string Version = "1.12";
-        public static string Build   = "3613";
+        public static string Build   = "3615";

         public static int BuildYear   = 2020;
         public static int BuildMonth  = 09;
         public static int BuildDay    = 15;
-        public static int BuildHour   = 02;
-        public static int BuildMinute = 36;
-        public static int BuildSecond = 38;
+        public static int BuildHour   = 16;
+        public static int BuildMinute = 12;
+        public static int BuildSecond = 48;
     }
 }


Read a WHIP packet much more directly

Read a WHIP packet much more directly

No more duplication of data in memory, other than to copy the data bytes into the main buffer.

--- Source/LibWhipLru/Server/ClientRequestMsg.cs
+++ Source/LibWhipLru/Server/ClientRequestMsg.cs
@@ -27,6 +27,7 @@
 using InWorldz.Whip.Client;
 using System.Text;
 using static InWorldz.Whip.Client.ClientRequestMsg;
+using System;

 namespace LibWhipLru.Server {
 	public class ClientRequestMsg : IByteArrayAppendable {
@@ -36,67 +37,84 @@
 		private const short UUID_TAG_LOCATION = 1;
 		private const short UUID_LEN = 32;

-		private readonly List<byte> _rawMessageData = new List<byte>();
+		private long _bytesRead;

+		public RequestType Type { get; private set; }
+		private bool _typeIsReady;
 		public Guid AssetId { get; private set; }
+		private bool _assetIdIsReady;
 		public byte[] Data;
+		private int _dataWritePointer = 0;
 		public bool IsReady { get; private set; }
-		public RequestType Type { get; private set; }
-
-		private int _dataSize;

 		public string GetHeaderSummary() {
 			return $"Type: {Type}, AssetID: {AssetId}, Size: {Data?.Length}";
 		}

+		/// <summary>
+		/// Adds the incoming raw data to the message.
+		/// </summary>
+		/// <returns><c>true</c>, if all expected data is received, <c>false</c> otherwise.</returns>
+		/// <param name="data">Data.</param>
 		public bool AddRange(byte[] data) {
-			if (IsReady) { // Refuse to append more data once loaded.
-				throw new System.InvalidOperationException("You cannot reuse messages!");
+			if (data.Length < HEADER_SIZE) { // Only allow packets big enough to contain the whole header.
+				throw new ArgumentOutOfRangeException(nameof(data), $"Data buffer MUST be at least {HEADER_SIZE} bytes long.");
 			}

-			_rawMessageData.AddRange(data);
+			if (IsReady) { // Refuse to append more data once loaded.
+				throw new InvalidOperationException("You cannot reuse messages!");
+			}

-			if (_rawMessageData.Count >= HEADER_SIZE) {
-				var header = _rawMessageData.GetRange(0, HEADER_SIZE).ToArray();
+			_bytesRead += data.Length;

-				// We've enough of the header to determine size.
-				_dataSize = InWorldz.Whip.Client.Util.NTOHL(header, DATA_SIZE_MARKER_LOC);
-				var packetSize = HEADER_SIZE + _dataSize;
-
-				if (packetSize > REQUEST_TYPE_LOC && _rawMessageData.Count >= packetSize) {
-					// Load the class up with the data.
-					var type = header[REQUEST_TYPE_LOC];
-					if (typeof(RequestType).IsEnumDefined(type)) {
-						Type = (RequestType)type;
-					}
-					else {
-						throw new AssetProtocolError($"Invalid result type in server response. Header summary: {GetHeaderSummary(header)}");
-					}
-
-					var idString = Encoding.ASCII.GetString(header, UUID_TAG_LOCATION, UUID_LEN);
-					UUID id;
-					if (UUID.TryParse(idString, out id)) {
-						AssetId = id;
-					}
-					else {
-						throw new AssetProtocolError($"Invalid UUID in server response. Header summary: {GetHeaderSummary(header)}");
-					}
-
-					Data = _rawMessageData?.GetRange(HEADER_SIZE, _dataSize).ToArray();
-
-					_rawMessageData.Clear();
-
-					IsReady = true;
-
-					// If all the expected data has arrived, return true, else false.
+			if (!_typeIsReady && _bytesRead >= REQUEST_TYPE_LOC + 1) {
+				var type = data[REQUEST_TYPE_LOC];
+				if (typeof(RequestType).IsEnumDefined(type)) {
+					Type = (RequestType)type;
+					_typeIsReady = true;
+				}
+				else {
+					throw new AssetProtocolError($"Invalid result type in server response. Type value sent: {type}");
 				}
 			}

+			if (!_assetIdIsReady && _bytesRead >= UUID_TAG_LOCATION + UUID_LEN) {
+				var idString = Encoding.ASCII.GetString(data, UUID_TAG_LOCATION, UUID_LEN);
+				Guid id;
+				if (Guid.TryParse(idString, out id)) {
+					AssetId = id;
+					_assetIdIsReady = true;
+				}
+				else {
+					throw new AssetProtocolError($"Invalid UUID in server response. Header summary: Type = {Type}, AssetId = {idString}");
+				}
+			}
+
+			if (Data == null && _bytesRead >= DATA_SIZE_MARKER_LOC + 4) {
+				var dataSize = Math.Max(0, InWorldz.Whip.Client.Util.NTOHL(data, DATA_SIZE_MARKER_LOC)); // No, you don't get to send me negative numbers.
+				Data = new byte[dataSize];
+
+				var bytesToRead = Math.Min(dataSize, data.Length - HEADER_SIZE);
+
+				if (dataSize > 0) {
+					// We are processing a packet of data that has the header.
+					Buffer.BlockCopy(data, HEADER_SIZE, Data, 0, bytesToRead);
+				}
+
+				_dataWritePointer = bytesToRead;
+			}
+			else {
+				// Processing a pure data packet.
+				var bytesToRead = Math.Min(data.Length, Data.Length - _dataWritePointer);
+
+				Buffer.BlockCopy(data, 0, Data, _dataWritePointer, bytesToRead);
+
+				_dataWritePointer += bytesToRead;
+			}
+
+			IsReady = _dataWritePointer >= Data.Length;
+
 			return IsReady;
-		}
-
-		private static string GetHeaderSummary(byte[] header) {
-			return $"Type: {header[REQUEST_TYPE_LOC]}, AssetID: {Encoding.ASCII.GetString(header, UUID_TAG_LOCATION, UUID_LEN)}, Size: {InWorldz.Whip.Client.Util.NTOHL(header, DATA_SIZE_MARKER_LOC)}";
 		}
 	}
 }


Fixed incorrect output for filter values

--- SMProxy/Program.cs
+++ SMProxy/Program.cs
@@ -93,7 +93,7 @@
             {
                 string values = "";
                 foreach (byte b in Filter)
-                    values += "0x" + b + ",";
+                    values += "0x" + b.ToString("x") + ",";
                 outputLogger.WriteLine("Output filter: " + values.Remove(values.Length - 1));
             }
             if (SuppressClient)


fix dakuryon cage debuff?

fix dakuryon cage debuff?

--- TCC.Core/Data/Abnormality.cs
+++ TCC.Core/Data/Abnormality.cs
@@ -2,7 +2,6 @@
 {
     public class Abnormality
     {
-        //Bitmap iconBitmap;
         public string IconName { get; set; }
         public uint Id { get; set; }
         public string Name { get; set; }
@@ -20,6 +19,7 @@
             IsShow = isShow;
             Infinity = infinity;
             Type = prop;
+            if (!IsBuff && prop == AbnormalityType.Buff) Type = AbnormalityType.Debuff;
         }

         public void SetIcon(string iconName)


Adjusting timing tolerance for html test

--- Sp.Api.Portal.Html.Acceptance/LicenseTags.cs
+++ Sp.Api.Portal.Html.Acceptance/LicenseTags.cs
@@ -30,7 +30,7 @@

 				// Wait for page to populate and then click edit to pop up the editor for a random license row
 				Func<ReadOnlyCollection<IWebElement>> findLicenseRows = () => driver.FindElementsByCssSelector( "#license-list tr" );
-				IWebElement licenseRowToEdit = (new WebDriverWait( driver, TimeSpan.FromSeconds( 2 ) ).Until( d2 =>
+				IWebElement licenseRowToEdit = (new WebDriverWait( driver, TimeSpan.FromSeconds( 5 ) ).Until( d2 =>
 				{
 					ReadOnlyCollection<IWebElement> loadedRows = findLicenseRows();
 					if ( loadedRows.Count == 0 ) // Not loaded yet
@@ -62,10 +62,10 @@
 				new WebDriverWait( driver, TimeSpan.FromSeconds( 3 ) ).Until( d2 => ContainsSequenceOfColumnsContaining( valuesInputted, findLicenseRowEditedOrDefault() ) );

 				// Verify everything can show when we get everything fresh from the server
-				new WebDriverWaitIgnoringNestedTimeouts( driver, TimeSpan.FromSeconds( 4 ) ).Until( d =>
+				new WebDriverWaitIgnoringNestedTimeouts( driver, TimeSpan.FromSeconds( 5 ) ).Until( d =>
 				{
 					driver.FindElementByCssSelector( ".section_title a" ).Click();
-					return new WebDriverWait( driver, TimeSpan.FromSeconds( 2 ) ).Until( d2 =>
+					return new WebDriverWait( driver, TimeSpan.FromSeconds( 5 ) ).Until( d2 =>
 					{
 						var editedRow = findLicenseRowEditedOrDefault();
 						if ( editedRow == null ) // rows not loaded yet


Improved error message display in Nancy

Improved error message display in Nancy

--- Src/Nancy.ViewEngines.Veil/VeilViewEngine.cs
+++ Src/Nancy.ViewEngines.Veil/VeilViewEngine.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
+using System.Reflection;
 using Veil;

 namespace Nancy.ViewEngines.Veil
@@ -54,9 +55,18 @@
         {
             return (writer, model) =>
             {
-                var message = StaticConfiguration.DisableErrorTraces ? "Error details are currently disabled. Please set StaticConfiguration.DisableErrorTraces = false; to enable." : e.ToString();
-                writer.Write(ErrorTemplate.Value.Replace("[DETAILS]", e.ToString()));
+                var message = GetErrorMessage(e);
+                writer.Write(ErrorTemplate.Value.Replace("[DETAILS]", message));
             };
+        }
+
+        private static string GetErrorMessage(Exception e)
+        {
+            if (StaticConfiguration.DisableErrorTraces) return "Error details are currently disabled. Please set StaticConfiguration.DisableErrorTraces = false; to enable.";
+            if (e is TargetInvocationException) return GetErrorMessage(e.InnerException);
+            if (e is VeilParserException) return e.Message;
+            if (e is VeilCompilerException) return e.Message;
+            return e.ToString();
         }

         private static Lazy<string> ErrorTemplate = new Lazy<string>(() =>


Removed implementation

Removed implementation

--- Core/Domain/Order.cs
+++ Core/Domain/Order.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Collections.Generic;
 using System.Linq;

@@ -10,13 +11,8 @@
         public Order(Customer customer)
         {
             _customer = customer;
-            _orderLines = new List<OrderLine>();
         }

-        public Order()
-        {
-            _orderLines = new List<OrderLine>();
-        }
         public OrderStatus Status { get; private set; }

         public Customer Customer
@@ -36,44 +32,27 @@

         public decimal Total
         {
-            get
-            {
-                var sum = _orderLines.Sum(ol => ol.Price);
-                return sum - Discount;
-            }
+            get { throw new NotImplementedException(); }
         }

-        public decimal Shipping { get { return Total > 500 ? 0 : 125; } }
+        public decimal Shipping { get { throw new NotImplementedException(); } }

         public decimal Discount
         {
             get
             {
-                var sum = _orderLines.Sum(ol => ol.Price);
-                if (sum > 10000m) return sum * 0.1m;
-                return 0;
+                throw new NotImplementedException();
             }
         }

         public void SetStatus(OrderStatus newOrderStatus)
         {
-            if (Status == OrderStatus.Shipped && newOrderStatus == OrderStatus.Canceled)
-            {
-                throw new InvalidStatusChangeException();
-            }
-
-            if (Status == OrderStatus.ReadyForShipping && newOrderStatus == OrderStatus.Canceled)
-            {
-                var invoice = new Invoice();
-                invoice.AddInvoiceItem(new InvoiceItem { Cost = this.Total * 0.1m});
-                Customer.AddInvoice(invoice);
-            }
-            Status = newOrderStatus;
+            throw new NotImplementedException();
         }

         public void AddOrderLine(OrderLine orderLine)
         {
-            _orderLines.Add(orderLine);
+            throw new NotImplementedException();
         }
     }
 }


Fix for checking the default voice

Fix for checking the default voice

--- Talkinator/Talkinator/Views/TalkPage.xaml.cs
+++ Talkinator/Talkinator/Views/TalkPage.xaml.cs
@@ -88,7 +88,7 @@
         private void GetVoices()
         {
             var voices = SpeechSynthesizer.AllVoices;
-            var currentVoice = synth.Voice;
+            var currentVoice = SpeechSynthesizer.DefaultVoice;

             foreach (VoiceInformation voice in voices.OrderBy(v => v.Language))
             {


More tests, improved test framework

More tests, improved test framework

--- Tests/SyMathTests/Program.cs
+++ Tests/SyMathTests/Program.cs
@@ -13,7 +13,20 @@
             Expression T = Equal.New(Expr, Result);
             Expression TE = T.Evaluate();

-            if (!TE.IsTrue())
+            bool passed = TE.IsTrue();
+            if (!passed)
+            {
+                // Special case for NSolve since it does not produce exact results.
+                Expression pattern = "NSolve[x, y]";
+                MatchContext m = pattern.Matches(Expr);
+                if (m != null)
+                {
+                    IEnumerable<Equal> f = Set.MembersOf(m["x"]).Cast<Equal>();
+                    passed = f.All(i => Call.Abs((i.Left - i.Right).Evaluate(Set.MembersOf(Result).Cast<Arrow>())) < 1e-3);
+                }
+            }
+
+            if (!passed)
                 System.Console.WriteLine("{0}", Arrow.New(T, TE).ToPrettyString());
             return TE.IsTrue();
         }
@@ -25,12 +38,29 @@
                 // Basic operations.
                 { "IsInteger[2]", "1" },
                 { "IsInteger[2.1]", "0" },
+                { "Floor[1]", "1" },
+                { "Floor[1.1]", "1" },
+                { "Floor[0.9]", "0" },
+                { "Floor[0.1]", "0" },
+                { "Floor[0]", "0" },
+                { "Floor[-0.1]", "-1" },
+                { "Floor[-0.9]", "-1" },
+                { "Floor[-1]", "-1" },
+                { "Floor[-1.1]", "-2" },
+                { "Ceiling[1]", "1" },
+                { "Ceiling[1.1]", "2" },
+                { "Ceiling[0.9]", "1" },
+                { "Ceiling[0.1]", "1" },
+                { "Ceiling[0]", "0" },
+                { "Ceiling[-0.1]", "0" },
+                { "Ceiling[-0.9]", "0" },
+                { "Ceiling[-1]", "-1" },
+                { "Ceiling[-1.1]", "-1" },
                 { "Cos[0]", "1" },
                 { "Sin[0]", "0" },
                 { "Sqrt[4]", "2" },
                 { "-1.0", "-1" },
                 { "-1.2e1", "-12" },
-                { "-1.2e-1", "-.12" },
                 { "Abs[e - 2.7183] < 0.01", "1" },
                 { "Abs[Pi - 3.1416] < 0.01", "1" },
                 //{ "f'[t]", "D[f[t], t]" },
@@ -67,8 +97,10 @@
                 { "Expand[(x + 1)*(x - 1)]", "x^2 - 1" },
                 { "Expand[(x + 1)^3]", "x^3 + 3*x^2 + 3*x + 1" },
                 { "Expand[(x + 1)^5]", "x^5 + 5*x^4 + 10*x^3 + 10*x^2 + 5*x + 1" },
+                { "Expand[(x + 1)^7]", "x^7 + 7*x^6 + 21*x^5 + 35*x^4 + 35*x^3 + 21*x^2 + 7*x + 1" },
                 { "Expand[a*(b + c)]", "a*b + a*c" },
                 { "Expand[(a + b)*(c + d)]", "a*c + a*d + b*c + b*d" },
+                { "Expand[(a + b)*(c + d)*(f + g)]", "a*c*f + a*d*f + b*c*f + b*d*f + a*c*g + a*d*g + b*c*g + b*d*g" },
                 { "Expand[1/(s^3 + s), s]", "1/s - s/(s^2 + 1)" },

                 // Factor.
@@ -78,44 +110,58 @@
                 { "Factor[A*Exp[x] + B*Exp[x] + C*Sin[x] + D*Sin[x]]", "(A + B)*Exp[x] + (C + D)*Sin[x]" },
                 { "Factor[A*Exp[x] + B*Exp[x] + A*Sin[x] + B*Sin[x]]", "(A + B)*(Exp[x] + Sin[x])" },

-                // Hyperbolic functions.
-                { "Exp[x] + Exp[-x]", "2*Cosh[x]" },
-                { "Exp[2*x] - Exp[-2*x]", "2*Sinh[2*x]" },
-                { "(Exp[x] - Exp[-x])/(Exp[x] + Exp[-x])", "Tanh[x]" },
-                { "(Exp[2*x] + Exp[-2*x])/(Exp[2*x] - Exp[-2*x])", "Coth[2*x]" },
-                { "2/(Exp[x] + Exp[-x])", "Sech[x]" },
-                { "3/(Exp[2*x] - Exp[-2*x])", "1.5*Csch[2*x]" },
-
-                // Trig functions.
-                { "Sin[x]/Cos[x]", "Tan[x]" },
-                { "Cos[x^2]/Sin[x^2]", "Cot[x^2]" },
-                { "Tan[x]*Cos[x]", "Sin[x]" },
-                { "Sin[x]^2 + Cos[x]^2", "1" },
-                { "y*Sin[x]^2 + y*Cos[x]^2", "y" },
+                //// Hyperbolic functions.
+                //{ "Exp[x] + Exp[-x]", "2*Cosh[x]" },
+                //{ "Exp[2*x] - Exp[-2*x]", "2*Sinh[2*x]" },
+                //{ "(Exp[x] - Exp[-x])/(Exp[x] + Exp[-x])", "Tanh[x]" },
+                //{ "(Exp[2*x] + Exp[-2*x])/(Exp[2*x] - Exp[-2*x])", "Coth[2*x]" },
+                //{ "2/(Exp[x] + Exp[-x])", "Sech[x]" },
+                //{ "3/(Exp[2*x] - Exp[-2*x])", "1.5*Csch[2*x]" },
+
+                //// Trig functions.
+                //{ "Sin[x]/Cos[x]", "Tan[x]" },
+                //{ "Cos[x^2]/Sin[x^2]", "Cot[x^2]" },
+                //{ "Tan[x]*Cos[x]", "Sin[x]" },
+                //{ "Sin[x]^2 + Cos[x]^2", "1" },
+                //{ "y*Sin[x]^2 + y*Cos[x]^2", "y" },

                 // Derivatives.
-                { "D[A*x + B*x^2, x]", "A + 2*B*x" },
                 { "D[Sin[x], x]", "Cos[x]" },
                 { "D[Cos[x], x]", "-Sin[x]" },
                 { "D[Tan[x], x]", "Sec[x]^2" },
+                { "D[Sec[x], x]", "Sec[x]*Tan[x]" },
+                { "D[Csc[x], x]", "-Csc[x]*Cot[x]" },
+                { "D[Cot[x], x]", "-Csc[x]^2" },
+
+                { "D[Sinh[A*x], x]", "A*Cosh[A*x]" },
+                { "D[Cosh[A*x + B], x]", "A*Sinh[A*x + B]" },
+                { "D[Tanh[A*x^2 + B*x + C], x]", "(2*A*x + B)*Sech[A*x^2 + B*x + C]^2" },
+                { "D[Sech[x], x]", "-Sech[x]*Tanh[x]" },
+                { "D[Csch[x], x]", "-Csch[x]*Coth[x]" },
+                { "D[Coth[x], x]", "-Csch[x]^2" },
+
+                { "D[A*x + B*x^2, x]", "A + 2*B*x" },
+                { "D[(x^2 + 1)^5, x]", "5*(2*x)*(x^2 + 1)^4" },
                 { "D[Ln[x], x]", "1/x" },
+                { "D[Ln[Abs[x]], x]", "Abs[x]/x^2" },
                 { "D[(x + 1)^2, x]", "2*(x + 1)" },
                 { "D[Exp[x^2], x]", "Exp[x^2]*2*x" },
+                { "D[Exp[x^5], x]", "Exp[x^5]*5*x^4" },

                 // Solve.
                 { "Solve[y == A*x + B, x]", "x -> (y - B)/A" },
                 { "Solve[{2*x + 4*y == 8, x == 2*y + 3}, {x, y}]", "{x -> 7/2, y -> 1/4}" },
-
+
                 // NSolve.
                 { "NSolve[x == Cos[x], x->0.5]", "x->0.739085" },
                 { "NSolve[2 == Exp[x] - Exp[-x], x->0.5]", "x->0.881374" },
                 { "NSolve[{y == x^2, x^2 + y^2 == 1}, {x->1, y->1}]", "{x->0.786, y->0.618}" },
-                { "NSolve[{y == x^2, x^2 + y^2 == 1, z == x + y}, {x->1, y->1, z->1}]", "{x->0.786, y->0.618, z->1.386}" },
-                { "NSolve[{z == x^2, x^2 + y^2 == 1, z == y}, {x->1, y->1, z->1}]", "{x->0.786, y->0.618, z->0.618}" },
-                { "NSolve[{Exp[x + y] == 1, Exp[x - 2*y] == 2}, {x->0.5, y->0.5}]", "{x->0.1505, y->-0.1505}" },
-                { "NSolve[(((0.01*Vo) + (-0.01*1) + (1E-12*Exp[(38.6847*Vo)]) + (-1E-12*Exp[(-38.6847*Vo)]))==0), Vo->0.57, 1e-6]", "Vo->0.573208" },
-                { "NSolve[(((0.01*Vo) + (-0.01*1) + (1E-12*Exp[(38.6847*Vo)]) + (-1E-12*Exp[(-38.6847*Vo)]))==0), Vo->0, 1e-6]", "Vo->0.573208" },
-                { "NSolve[(Ln[((0.01*Vo) + (1E-12*Exp[(38.6847*Vo)]) + (-1E-12*Exp[(-38.6847*Vo)]))]==Ln[0.01]), Vo->0.01, 1e-6]", "Vo->0.573208" },
+                { "NSolve[{y == x^2, x^2 + y^2 == 1, z == x + y}, {x->1, y->1, z->1}]", "{x->0.786151, y->0.618034, z->1.40419}" },
+                { "NSolve[{z == x^2, x^2 + y^2 == 1, z == y}, {x->1, y->1, z->1}]", "{x->0.786151, y->0.618034, z->0.618034}" },
+                { "NSolve[{Exp[x + y] == 1, Exp[x - 2*y] == 2}, {x->0.5, y->0.5}]", "{x->0.231049, y->-0.231049}" },
+                { "NSolve[(((0.01*Vo) + (-0.01*1) + (1E-12*Exp[(38.6847*Vo)]) + (-1E-12*Exp[(-38.6847*Vo)]))==0), Vo->0.57]", "Vo->0.573208" },
+                { "NSolve[(((0.01*Vo) + (-0.01*1) + (1E-12*Exp[(38.6847*Vo)]) + (-1E-12*Exp[(-38.6847*Vo)]))==0), Vo->0]", "Vo->0.573208" },
+                { "NSolve[(Ln[((0.01*Vo) + (1E-12*Exp[(38.6847*Vo)]) + (-1E-12*Exp[(-38.6847*Vo)]))]==Ln[0.01]), Vo->0.01]", "Vo->0.573208" },

                 // DSolve.
                 { "DSolve[D[y[t], t]==y[t], y[t], y[0]->1, t]", "y[t]->Exp[t]" },
@@ -125,7 +171,7 @@
                 { "DSolve[D[D[y[t], t], t]==1, y[t], {y[0]->0, (D[y[t], t]:t->0)->0}, t]", "y[t]->t^2/2" },
                 { "DSolve[D[y[t], t]==-y[t], y[t], y[0]->1, t]", "y[t]->Exp[-t]" },
                 { "DSolve[D[y[t], t]==2*y[t], y[t], y[0]->1, t]", "y[t]->Exp[2*t]" },
-                { "DSolve[D[y[t], t]==y[t]/3, y[t], y[0]->1, t]", "y[t]->Exp[t/3]" },
+                { "DSolve[D[y[t], t]==y[t]/3, y[t], y[0]->C, t]", "y[t]->C*Exp[t/3]" },
                 { "DSolve[D[y[t], t] + y[t]==0, y[t], y[0]->1, t]", "y[t]->Exp[-t]" },
                 { "DSolve[D[y[t], t]==Sin[t], y[t], y[0]->0, t]", "y[t]->1 - Cos[t]" },

@@ -140,10 +186,14 @@
             timer.Start();

             int passed = 0;
+            int total = 0;
             foreach (KeyValuePair<Expression, Expression> i in Tests)
+            {
                 passed += Test(i.Key, i.Value) ? 1 : 0;
-
-            System.Console.WriteLine("{0} of {1} passed", passed, Tests.Count);
+                total += 1;
+            }
+
+            System.Console.WriteLine("{0} of {1} passed", passed, total);

             System.Console.WriteLine("{0} ms", timer.ElapsedMilliseconds);
             System.Console.WriteLine("TransformCalls: {0}", TransformSet.TransformCalls);


testing commit

testing commit

added a TODO

--- ThePrincessBard/ThePrincessBard/Animation.cs
+++ ThePrincessBard/ThePrincessBard/Animation.cs
@@ -19,6 +19,8 @@
     /// Currently, this class assumes that each frame of animation is
     /// as wide as each animation is tall. The number of frames in the
     /// animation are inferred from this.
+    ///
+    /// TODO: change to variable width/height/framenumber
     /// </remarks>
     class Animation
     {


Change ThreadPool to Thread

Change ThreadPool to Thread

--- Services/Upload.cs
+++ Services/Upload.cs
@@ -14,6 +14,9 @@
 {
     public class Upload
     {
+        private const string STATIC_UPLOAD_URL = "https://static.md/api/v2/upload/";
+        private const string STATIC_TOKEN_URL = "https://static.md/api/v2/get-token/";
+
         public delegate void SuccessCallback(Models.StaticMd.Image image);
         public delegate void ErrorCallback(string error);
         public delegate void CompleteCallback();
@@ -52,7 +55,12 @@
         // Upload image by using separate thread
         public void uploadImageAsync(Image image)
         {
-            ThreadPool.QueueUserWorkItem(q => this.detectThreadWork(image));
+            ThreadStart start = new ThreadStart(() => this.detectThreadWork(image));
+            Thread thread = new Thread(start);
+            thread.IsBackground = true;
+            thread.Start();
+
+            Helpers.Thread.addThread(thread);
         }

         // Upload image without separate thread
@@ -64,7 +72,12 @@
         // Upload image files by using separate thread
         public void uploadImageFilesAsync(List<Models.ImageFile> imageFiles)
         {
-            ThreadPool.QueueUserWorkItem(q => this.detectThreadWork(imageFiles));
+            ThreadStart start = new ThreadStart(() => this.detectThreadWork(imageFiles));
+            Thread thread = new Thread(start);
+            thread.IsBackground = true;
+            thread.Start();
+
+            Helpers.Thread.addThread(thread);
         }

         // Upload image files
@@ -172,7 +185,7 @@
         {
             this.sleepBeforeUpload(token);

-            var request = (HttpWebRequest)WebRequest.Create("https://static.md/api/v2/upload/");
+            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(STATIC_UPLOAD_URL);
             request.Proxy = null;

             const string boundary = "----B0unDAry";
@@ -195,16 +208,16 @@
             request.Accept = "application/json";
             request.Headers.Add("Accept-Language", "en");

-            using (var stream = request.GetRequestStream())
+            using (Stream stream = request.GetRequestStream())
             {
                 stream.Write(postFieldsBytes, 0, postFieldsBytes.Length);
                 stream.Write(imageUpload.bytes, 0, imageUpload.bytes.Length);
                 stream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
             }

-            var response = (HttpWebResponse)request.GetResponse();
-
-            var jsonResponse = new StreamReader(response.GetResponseStream()).ReadToEnd();
+            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+
+            string jsonResponse = new StreamReader(response.GetResponseStream()).ReadToEnd();

             return parseImage(jsonResponse);
         }
@@ -220,12 +233,12 @@
         // Get token
         private Models.StaticMd.Token getToken(string md5)
         {
-            var request = (HttpWebRequest)WebRequest.Create("https://static.md/api/v2/get-token/");
+            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(STATIC_TOKEN_URL);
             request.Proxy = null;

-            var postData = "md5=" + Uri.EscapeUriString(md5);
-
-            var data = Encoding.ASCII.GetBytes(postData);
+            string postData = "md5=" + Uri.EscapeUriString(md5);
+
+            byte[] data = Encoding.ASCII.GetBytes(postData);
             request.Method = "POST";
             request.ContentType = "application/x-www-form-urlencoded";
             request.ContentLength = data.Length;
@@ -234,14 +247,14 @@
             request.Accept = "application/json";
             request.Headers.Add("Accept-Language", "en");

-            using (var stream = request.GetRequestStream())
+            using (Stream stream = request.GetRequestStream())
             {
                 stream.Write(data, 0, data.Length);
             }

-            var response = (HttpWebResponse)request.GetResponse();
-
-            var jsonResponse = new StreamReader(response.GetResponseStream()).ReadToEnd();
+            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+
+            string jsonResponse = new StreamReader(response.GetResponseStream()).ReadToEnd();

             return parseToken(jsonResponse);
         }


Make rumble more robust.

Make rumble more robust.

--- VRGIN/Controls/Handlers/BodyRumbleHandler.cs
+++ VRGIN/Controls/Handlers/BodyRumbleHandler.cs
@@ -19,6 +19,19 @@
             base.OnStart();

             _Controller = GetComponent<Controller>();
+        }
+
+        protected override void OnLevel(int level)
+        {
+            base.OnLevel(level);
+            OnStop();
+
+        }
+
+        protected void OnDisable()
+        {
+            OnStop();
+
         }

         protected void OnTriggerEnter(Collider collider)
@@ -51,10 +64,16 @@

                 if (_TouchCounter == 0)
                 {
-                    _Rumble.Close();
-                    _Rumble = null;
+                    OnStop();
                 }
             }
         }
+
+        protected void OnStop()
+        {
+            _TouchCounter = 0;
+            _Rumble.Close();
+            _Rumble = null;
+        }
     }
 }


Changed The organization of the VendingService class

--- VendingMachineKata/Service/VendingService.cs
+++ VendingMachineKata/Service/VendingService.cs
@@ -80,12 +80,12 @@
         /// Add the inserted coins to the existing pool of coins
         /// </summary>
         /// <param name="coinsInserted"></param>
-        public static void AddToExistingChange(double[] coinsInserted)
+        public static void AddToExistingChange(Coin[] coinsInserted)
         {
             //The customer has inserted a few coins as well. Add them to the pool of coins that already exist and then tender change
-            foreach (double coinValue in coinsInserted)
+            foreach (Coin Coin in coinsInserted)
             {
-                CoinValues[coinValue]++; //Increment the corresponding coin value
+                AcceptedCoinsDictionary.Keys.Where(key => key.Equals(key, Coin)).First().Count++; //Increment the corresponding coin value
             }

         }


Забыл за константы в тестах

Забыл за константы в тестах

--- VkNet.Tests/Categories/GroupsCategoryTest.cs
+++ VkNet.Tests/Categories/GroupsCategoryTest.cs
@@ -75,8 +75,7 @@
 		[Test]
 		public void Leave_WrongGid_ReturnTrue()
 		{
-			const string url =
-				"https://api.vk.com/method/groups.leave?gid=-1&access_token=token";
+			const string url = "https://api.vk.com/method/groups.leave?gid=0&access_token=token";
 			const string json =
 				@"{
 					'response': 1
@@ -294,7 +293,7 @@
 		[Test]
 		public void Get_NormalCaseDefaultFields_ReturnOnlyGroupIds()
 		{
-			const string url = "https://api.vk.com/method/groups.get?uid=4793858&extended=0&offset=0&count=1000&v=5.28&access_token=token";
+			const string url = "https://api.vk.com/method/groups.get?uid=4793858&extended=0&offset=0&v=5.28&access_token=token";
 			const string json =
 				@"{
 					'response': [
@@ -454,7 +453,7 @@
 		[Test]
 		public void IsMember_WrongGid_ThrowsInvalidParameterException()
 		{
-			const string url = "https://api.vk.com/method/groups.isMember?gid=-1&uid=4793858&access_token=token";
+			const string url = "https://api.vk.com/method/groups.isMember?gid=0&uid=4793858&access_token=token";
 			const string json =
 				@"{
 					'error': {
@@ -493,7 +492,7 @@
 		[Test]
 		public void IsMember_WrongUid_ReturnFalse()
 		{
-			const string url = "https://api.vk.com/method/groups.isMember?gid=637247&uid=-1&access_token=token";
+			const string url = "https://api.vk.com/method/groups.isMember?gid=637247&uid=0&access_token=token";
 			const string json =
 				@"{
 					'response': 0
@@ -610,7 +609,7 @@
 		[Test]
 		public void GetMembers_InvalidGid_ThrowsInvalidParameterException()
 		{
-			const string url = "https://api.vk.com/method/groups.getMembers?gid=-1&access_token=token";
+			const string url = "https://api.vk.com/method/groups.getMembers?gid=0&access_token=token";
 			const string json =
 				@"{
 					'error': {
@@ -663,7 +662,7 @@
 		[Test]
 		public void Search_DefaultCase_ListOfGroups()
 		{
-			const string url = "https://api.vk.com/method/groups.search?q=Music&sort=0&access_token=token";
+			const string url = "https://api.vk.com/method/groups.search?q=Music&future=0&sort=0&access_token=token";
 			const string json =
 				@"{
 					'response': [
@@ -728,7 +727,7 @@
 		[Test]
 		public void Search_DefaulCaseAllParams_ListOfGroups()
 		{
-			const string url = "https://api.vk.com/method/groups.search?q=Music&offset=20&count=3&sort=0&access_token=token";
+			const string url = "https://api.vk.com/method/groups.search?q=Music&offset=20&count=3&future=0&sort=0&access_token=token";
 			const string json =
 				@"{
 					'response': [
@@ -816,7 +815,8 @@
 		[Test]
 		public void Search_GroupsNotFounded_EmptyList()
 		{
-			const string url = "https://api.vk.com/method/groups.search?q=ThisQueryDoesNotExistAtAll&offset=20&count=3&sort=0&access_token=token";
+			const string url = "https://api.vk.com/method/groups.search?q=ThisQueryDoesNotExistAtAll&offset=20&count=3&future=0&sort=0&access_token=token";
+
 			const string json =
 				@"{
 					'response': [
@@ -880,7 +880,7 @@
 		[Test]
 		public void GetById_InvalidGid_ThrowsInvalidParameterException()
 		{
-			const string url = "https://api.vk.com/method/groups.getById?gid=-1&access_token=token";
+			const string url = "https://api.vk.com/method/groups.getById?gid=0&access_token=token";
 			const string json =
 				@"{
 					'error': {
@@ -915,7 +915,8 @@
 		[Test]
 		public void GetById_Multiple_InvalidGids_ThrowsInvalidParameterException()
 		{
-			const string url = "https://api.vk.com/method/groups.getById?gids=-1&access_token=token";
+			const string url = "https://api.vk.com/method/groups.getById?gids=0&access_token=token";
+
 			const string json =
 				@"{
 					'error': {


fix bug

fix bug

--- Vostok.Core/RetriableCall/ExceptionFinder.cs
+++ Vostok.Core/RetriableCall/ExceptionFinder.cs
@@ -28,7 +28,7 @@
             var ex = rootEx;
             while (ex != null && !condition(ex))
             {
-                if (!(rootEx is AggregateException aggregateEx))
+                if (!(ex is AggregateException aggregateEx))
                     ex = ex.InnerException;
                 else
                 {
@@ -38,6 +38,7 @@
                         if (exInner != null)
                             return exInner;
                     }
+                    return null;
                 }
             }
             return ex;


game over logic

game over logic

--- Awesome-Game/Assets/Scripts/Stem.cs
+++ Awesome-Game/Assets/Scripts/Stem.cs
@@ -17,7 +17,7 @@

 	// Update is called once per frame
 	void FixedUpdate () {
-        if (Growing) {
+        if (Growing && !GameController.control.gameOver) {
             this.transform.localScale += new Vector3(0, pc.GetGrowthSpeed(), 0);
         } else {
             this.transform.localScale += new Vector3(0.001f, 0f, 0);


FIX CIT-785 Hide EDIT button for all users in hub

--- Web/Areas/Hub/Views/Shared/DisplayHub.cshtml
+++ Web/Areas/Hub/Views/Shared/DisplayHub.cshtml
@@ -19,13 +19,13 @@
     <h4 class="page-header">@Html.Translate(title)
     @Html.Label("Owner", mdl.Owner) - @Html.Label("WH", mdl.Name) @Html.Translate(" Hub ")

-    @{
+    @*@{
         if(usr.UserAllowedHubs.Count > 1)
         {
             @Html.HubSelectionLink(Html.Translate("Change Warehouse"), Url.Action("HubList", "CurrentHub"), Html.Translate("Change Hub"))
         }

-   } </h4>
+   }*@ </h4>
 </div>


Only signed in users can edit

Only signed in users can edit

--- Website/OCM.Web/Controllers/POIController.cs
+++ Website/OCM.Web/Controllers/POIController.cs
@@ -196,7 +196,7 @@
                     viewModel.DataQualityReport = new DataAnalysisManager().GetDataQualityReport(poi);
                     //}

-                    ViewBag.UserCanEditPOI = true;
+                    ViewBag.UserCanEditPOI = false;
                     if (IsUserSignedIn)
                     {
                         var user = new UserManager().GetUser((int)UserID);


[Fix]: Make Borderlands 2 functions decompilable.

--- Core/UnFunction.cs
+++ Core/UnFunction.cs
@@ -75,6 +75,14 @@

 		protected override void Deserialize()
 		{
+#if BORDERLANDS2
+			if( Package.Build == UnrealPackage.GameBuild.ID.Borderlands2 )
+			{
+				var size = _Buffer.ReadUShort();
+				_Buffer.Skip( size * 2 );
+			}
+#endif
+
 			base.Deserialize();

 			/*if( Package.Version > 63 )


DNN-4611 Cannot disable password banned list updated passwordreset to validate banned passwords

--- Website/admin/Security/PasswordReset.ascx.cs
+++ Website/admin/Security/PasswordReset.ascx.cs
@@ -102,6 +102,23 @@
                 return;
             }

+            //Check New Password is not same as username or banned
+            var settings = new MembershipPasswordSettings(User.PortalID);
+
+            if (settings.EnableBannedList)
+            {
+                var m = new MembershipPasswordController();
+                if (m.FoundBannedPassword(txtPassword.Text) || txtUsername.Text == txtPassword.Text)
+                {
+                    resetMessages.Visible = true;
+                    var failed = Localization.GetString("PasswordResetFailed");
+                    LogFailure(failed);
+                    lblHelp.Text = failed;
+                    return;
+                }
+
+            }
+
             if (UserController.ChangePasswordByToken(PortalSettings.PortalId, txtUsername.Text, txtPassword.Text, ResetToken) == false)
             {
                 resetMessages.Visible = true;


Store off previous DL offset so header offsets display correctly

--- BlastCorpsEditor/BlastCorpsLevel.cs
+++ BlastCorpsEditor/BlastCorpsLevel.cs
@@ -9,6 +9,7 @@
       public Int32 gravity;
       public Int32 u1C; // TODO: identify
       public UInt32[] offsets = new UInt32[42];
+      public UInt32 dlOffset;
    }

    public class BlastCorpsItem
@@ -392,7 +393,7 @@
       private void decodeHeader(byte[] data)
       {
          // save offset of display list which will be used for header offset 0x78 and up
-         UInt32 dlOffset = (UInt32)data.Length;
+         header.dlOffset = (UInt32)data.Length;

          // read in 12 u16s
          for (uint i = 0; i < header.u16s.Length; i++)
@@ -406,11 +407,6 @@
          for (uint i = 0; i < header.offsets.Length; i++)
          {
             header.offsets[i] = BE.U32(data, 0x20 + i * 4);
-            // for 0x78 and up, save offset relative to display list
-            if (0x20 + i * 4 >= 0x78)
-            {
-               header.offsets[i] -= dlOffset;
-            }
          }
       }

@@ -1255,7 +1251,7 @@
          {
             if (i * 4 + 0x20 >= 0x78)
             {
-               UInt32 dlOffset = (UInt32)(header.offsets[i] + startDL);
+               UInt32 dlOffset = (UInt32)(header.offsets[i] + startDL - header.dlOffset);
                offset += BE.ToBytes(dlOffset, data, offset);
             }
          }


Fix broken add directory

Fix broken add directory

more logic problems!

--- Sounds/MainForm.cs
+++ Sounds/MainForm.cs
@@ -323,14 +323,14 @@
                 foreach (var f in Directory.EnumerateFiles(name).OrderBy(x => x)
                     .Concat(Directory.EnumerateDirectories(name).OrderBy(x => x)))
                 {
-                    didAdd = didAdd || AddItem(f, false);
+                    didAdd = AddItem(f, false) || didAdd;
                 }
             }
             else
             {
                 foreach (var f in Directory.EnumerateFiles(name).OrderBy(x => x))
                 {
-                    didAdd = didAdd || AddFile(f, false);
+                    didAdd = AddFile(f, false) || didAdd;
                 }
             }
             if (didAdd && update)


improve menu functionality, better play

improve menu functionality, better play

--- Sounds/MainForm.cs
+++ Sounds/MainForm.cs
@@ -94,27 +94,32 @@
             {
                 // not needed
             }
-        }
-
-        public void PlayAndSet()
-        {
-            if (playing)
+            finally
+            {
+                UpdateMenus();
+            }
+        }
+
+        public void PlayAndSet(bool playSelected)
+        {
+            if (!playSelected && Paused)
             {
                 mp.Play();
+                UpdateMenus();
             }
             else
             {
+                if (listView1.SelectedItems.Count > 0)
+                {
+                    activeFile = (TagLib.File)listView1.SelectedItems[0].Tag;
+                }
+                else if (listView1.Items.Count > 0)
+                {
+                    activeFile = (TagLib.File)listView1.Items[0].Tag;
+                }
+                else return;
+
                 playing = true;
-
-                if (listView1.SelectedItems.Count > 0)
-                {
-                    activeFile = (TagLib.File)listView1.SelectedItems[0].Tag;
-                }
-                else if (listView1.Items.Count > 0)
-                {
-                    activeFile = (TagLib.File)listView1.Items[0].Tag;
-                }
-                else return;

                 PlayActive();
             }
@@ -125,11 +130,13 @@
             mp.Open(new Uri(activeFile.Name));
             mp.Play();
             UpdateUI();
+            UpdateMenus();
         }

         public void Pause()
         {
             mp.Pause();
+            UpdateMenus();
         }

         // Metadata and such
@@ -182,9 +189,17 @@
         public void UpdateMenus()
         {
             var selected = listView1.SelectedItems.Count > 0;
+            var any = listView1.Items.Count > 0;
+
             removeSelectedToolStripMenuItem.Enabled = selected;
             propertiesToolStripMenuItem.Enabled = selected;
-            playToolStripMenuItem.Enabled = !playing && selected;
+            shuffleToolStripMenuItem.Enabled = any;
+
+            playToolStripMenuItem.Enabled = playing ? Paused : any;
+            pauseToolStripMenuItem.Enabled = playing ? !Paused : false;
+            stopToolStripMenuItem.Enabled = playing;
+            previousToolStripMenuItem.Enabled = playing;
+            nextToolStripMenuItem.Enabled = playing;
         }

         public void Stop()
@@ -196,6 +211,7 @@
             activeFile = null;

             UpdateUI();
+            UpdateMenus();
         }

         public void Previous()
@@ -283,7 +299,7 @@

         private void playToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            PlayAndSet();
+            PlayAndSet(false);
         }

         private void pauseToolStripMenuItem_Click(object sender, EventArgs e)
@@ -390,7 +406,7 @@

         private void listView1_ItemActivate(object sender, EventArgs e)
         {
-            PlayAndSet();
+            PlayAndSet(true);
         }

         private void addDirectoryToolStripMenuItem_Click(object sender, EventArgs e)


BUG FIX: NullReferenceException occurs during constructor call (https://sourceforge.net/tracker/index.php?func=detail&aid=1731957&group_id=110642&atid=659401)

--- WinFormsUI/Docking/DockPanel.FocusManager.cs
+++ WinFormsUI/Docking/DockPanel.FocusManager.cs
@@ -438,7 +438,7 @@
                 if (ActivePane != null && ActivePane.DockState == DockState.Document)
                     value = ActivePane;

-                if (value == null)
+                if (value == null && DockPanel.DockWindows != null)
                 {
                     if (ActiveDocumentPane == null)
                         value = DockPanel.DockWindows[DockState.Document].DefaultPane;


android filenames

android filenames

--- Source/Filename.cs
+++ Source/Filename.cs
@@ -32,7 +32,10 @@
 		public string File
 		{
 			get { return m_strFilename; }
-			set { m_strFilename = value; }
+			set
+			{
+				m_strFilename = value.Replace('\\', '/');
+			}
 		}

 		#endregion //Properties
@@ -41,13 +44,8 @@

 		static Filename()
 		{
-#if WINDOWS
 			//Get the current working directory
 			SetCurrentDirectory();
-#else
-			//xbox doesnt support current working directory
-			ProgramLocation = "";
-#endif
 		}

 		/// <summary>
@@ -62,7 +60,9 @@
 		/// </summary>
 		static public void SetCurrentDirectory()
 		{
+#if WINDOWS
 			ProgramLocation = Directory.GetCurrentDirectory() + @"\";
+#endif
 		}

 		/// <summary>
@@ -84,8 +84,12 @@
 				{
 					break;
 				}
-
+
+#if ANDROID
+				progBuilder.AppendFormat(@"{0}/", pathinfo[i]);
+#else
 				progBuilder.AppendFormat(@"{0}\", pathinfo[i]);
+#endif
 			}

 			ProgramLocation = progBuilder.ToString();
@@ -118,9 +122,13 @@
 			//take the program location and append the filename to the end
 			StringBuilder fileBuilder = new StringBuilder();
 			fileBuilder.Append(ProgramLocation);
+#if ANDROID
+			fileBuilder.Append(@"Content/");
+#else
 			fileBuilder.Append(@"Content\");
+#endif
 			fileBuilder.Append(strRelFilename);
-			m_strFilename = fileBuilder.ToString();
+			File = fileBuilder.ToString();
 		}

 		/// <summary>
@@ -138,7 +146,11 @@
 				//put the path back together
 				for (int i = 0; i < pathinfo.Length - 1; i++)
 				{
+#if ANDROID
+					strTotalPath.AppendFormat(@"{0}/", pathinfo[i]);
+#else
 					strTotalPath.AppendFormat(@"{0}\", pathinfo[i]);
+#endif
 				}
 			}

@@ -178,7 +190,12 @@
 			{
 				if (!String.IsNullOrEmpty(pathinfo[iContentFolderIndex]))
 				{
+#if ANDROID
+					strRelativePath.AppendFormat(@"{0}/", pathinfo[iContentFolderIndex]);
+#else
 					strRelativePath.AppendFormat(@"{0}\", pathinfo[iContentFolderIndex]);
+#endif
+
 				}
 				iContentFolderIndex++;
 			}


Changes

Changes

--- WindowsIotLedDriver/TLC5947ControllerBase.cs
+++ WindowsIotLedDriver/TLC5947ControllerBase.cs
@@ -56,8 +56,14 @@
             m_controller = new LedController(this, ControlerUpdateType.AllSlots); // #todo set this when known.

             GpioController controller = GpioController.GetDefault();
-            pin = controller.OpenPin(5);
+            pin = controller.OpenPin(6);
             pin.SetDriveMode(GpioPinDriveMode.Output);
+
+
+            GpioPin pin2 = controller.OpenPin(5);
+            pin2.SetDriveMode(GpioPinDriveMode.Output);
+            pin2.Write(GpioPinValue.High);
+            pin2.Write(GpioPinValue.Low);

             //for (int i = 0; i < 50; i++)
             //{


CA-293322: Fix blocked unclustered network setting change

Signed-off-by: Ji Jiang <9feecbbdbbba2b823412e2acc0d6c9f5114f41ad@citrix.com>

--- XenAdmin/Dialogs/NetworkingPropertiesPage.cs
+++ XenAdmin/Dialogs/NetworkingPropertiesPage.cs
@@ -176,7 +176,7 @@
                 Host host = network.Connection.Resolve(pif.host);

                 ClusteringEnabled = network.Connection.Cache.Cluster_hosts.Any(cluster =>
-                    cluster.host.opaque_ref == pif.host.opaque_ref && cluster.enabled);
+                    cluster.PIF.opaque_ref == pif.opaque_ref && cluster.enabled);

                 if (ClusteringEnabled)
                 {


- Use HeightfieldTerrainShape with floats in VehicleDemo.

--- demos/SlimDX/VehicleDemo/Physics.cs
+++ demos/SlimDX/VehicleDemo/Physics.cs
@@ -65,7 +65,7 @@
             Vector3 worldMin = new Vector3(-10000, -10000, -10000);
             Vector3 worldMax = new Vector3(10000, 10000, 10000);
             Broadphase = new AxisSweep3(worldMin, worldMax);
-            //broadphase = new DbvtBroadphase();
+            //Broadphase = new DbvtBroadphase();

             World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, Solver, collisionConf);

@@ -153,25 +153,39 @@

                 int width = 40, length = 40;
                 //int width = 128, length = 128; // Debugging is too slow for this
-                float scale = 15.0f;
-                float maxHeight = 20.0f;
-                float heightScale = maxHeight / 500f;
-                bool flipQuadEdges = false;
-
-                FileStream file = new FileStream(heightfieldFile, FileMode.Open, FileAccess.Read);
-                HeightfieldTerrainShape heightterrainShape = new HeightfieldTerrainShape(width, length, file, heightScale, 0, maxHeight, upIndex, PhyScalarType.PhyUChar, flipQuadEdges);
+                float maxHeight = 10.0f;
+                float heightScale = maxHeight / 256.0f;
+                Vector3 scale = new Vector3(20.0f, maxHeight, 20.0f);
+
+                //PhyScalarType scalarType = PhyScalarType.PhyUChar;
+                //FileStream file = new FileStream(heightfieldFile, FileMode.Open, FileAccess.Read);
+
+                // Use float data
+                PhyScalarType scalarType = PhyScalarType.PhyFloat;
+                byte[] terr = new byte[width*length*4];
+                MemoryStream file = new MemoryStream(terr);
+                BinaryWriter writer = new BinaryWriter(file);
+                for (i = 0; i < width; i++ )
+                    for (int j = 0; j < length; j++)
+                        writer.Write((float)((maxHeight / 2) + 4 * Math.Sin(j * 0.5f) * Math.Cos(i)));
+                writer.Flush();
+                file.Position = 0;
+
+                HeightfieldTerrainShape heightterrainShape = new HeightfieldTerrainShape(width, length,
+                    file, heightScale, 0, maxHeight, upIndex, scalarType, false);
                 heightterrainShape.SetUseDiamondSubdivision(true);

                 groundShape = heightterrainShape;
-                groundShape.LocalScaling = new Vector3(scale, 1, scale);
-
-                tr = Matrix.Translation(-scale / 2, 10, -scale / 2);
-                vehicleTr = Matrix.Translation(new Vector3(0,3,0));
+                groundShape.LocalScaling = new Vector3(scale.X, 1, scale.Z);
+
+                tr = Matrix.Translation(new Vector3(-scale.X / 2, scale.Y / 2, -scale.Z / 2));
+                vehicleTr = Matrix.Translation(new Vector3(20,3,-3));

                 // Create graphics object

                 file.Position = 0;
+                BinaryReader reader = new BinaryReader(file);

                 int totalTriangles = (width - 1) * (length - 1) * 2;
                 int totalVerts = width * length;
@@ -182,11 +196,24 @@
                 {
                     for (int j = 0; j < length; j++)
                     {
-                        float height = heightScale * file.ReadByte();
-
-                        data.Write((j - length * 0.5f) * scale);
+                        float height;
+                        if (scalarType == PhyScalarType.PhyFloat)
+                        {
+                            // heightScale isn't applied internally for float data
+                            height = reader.ReadSingle();
+                        }
+                        else if (scalarType == PhyScalarType.PhyUChar)
+                        {
+                            height = file.ReadByte() * heightScale;
+                        }
+                        else
+                        {
+                            height = 0.0f;
+                        }
+
+                        data.Write((j - length * 0.5f) * scale.X);
                         data.Write(height);
-                        data.Write((i - width * 0.5f) * scale);
+                        data.Write((i - width * 0.5f) * scale.Z);

                         // Normals will be calculated later
                         data.Write(0.0f);
@@ -216,6 +243,7 @@

             CollisionShapes.PushBack(groundShape);

+
             //create ground object
             LocalCreateRigidBody(0, tr, groundShape);


partyonly typo

partyonly typo

--- Data/WindowData.cs
+++ Data/WindowData.cs
@@ -404,7 +404,7 @@
             xml.Root.Add(new XElement("excel_save_directory", ExcelSaveDirectory));
             xml.Root.Add(new XElement("always_visible", AlwaysVisible));
             xml.Root.Add(new XElement("scale", Scale));
-            xml.Root.Add(new XElement("partyonly", Scale));
+            xml.Root.Add(new XElement("partyonly", PartyOnly));
             xml.Root.Add(new XElement("showhealcrit", ShowHealCrit));

             _filestream.SetLength(0);
@@ -417,4 +417,4 @@
             _filestream.Close();
         }
     }
-}+}


Add BindDescriptorSet method

Add BindDescriptorSet method

Binds a single DescriptorSet without having to use a list

--- CSGL.Vulkan/Vulkan/CommandBuffer.cs
+++ CSGL.Vulkan/Vulkan/CommandBuffer.cs
@@ -134,6 +134,13 @@

         public void BindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, PipelineLayout layout, uint firstSet, List<DescriptorSet> descriptorSets) {
             BindDescriptorSets(pipelineBindPoint, layout, firstSet, descriptorSets, null);
+        }
+
+        public void BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, PipelineLayout layout, uint firstSet, DescriptorSet descriptorSet) {
+            unsafe {
+                VkDescriptorSet set = descriptorSet.Native;
+                Device.Commands.cmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout.Native, firstSet, 1, (IntPtr)(&set), 0, IntPtr.Zero);
+            }
         }

         public void Draw(uint vertexCount, uint instanceCount, uint firstVertex, uint firstInstance) {


- Fixed forward mode bug

- Fixed forward mode bug

--- LOSLight.cs
+++ LOSLight.cs
@@ -285,6 +285,10 @@
 					}
 				}
 				else {
+					meshVertices.Add(previousTempPoint - position);
+					previousVectexIndex = currentVertexIndex;
+					currentVertexIndex = meshVertices.Count - 1;
+					AddNewTriangle (ref triangles, 0, currentVertexIndex, previousVectexIndex);
 					AddNewTriangle(ref triangles, 0, 5, currentVertexIndex);
 				}
 			}


Removing 'zzz' from method name

Removing 'zzz' from method name

Trashing test code.

--- Collections/Paging/PagingHelpers.cs
+++ Collections/Paging/PagingHelpers.cs
@@ -13,7 +13,7 @@
 		/// <param name="page">the 1 indexed page number you are interested in, cannot be zero or negative</param>
 		/// <param name="pageSize">the size of the page you want, cannot be zero or negative</param>
 		/// <returns>A queryable of the page of entities with counts appended.</returns>
-		public static IQueryable<EntityWithCount<T>> GetPageWithTotalzzz<T>(this IQueryable<T> entities, int page, int pageSize) where T : class
+		public static IQueryable<EntityWithCount<T>> GetPageWithTotal<T>(this IQueryable<T> entities, int page, int pageSize) where T : class
 		{
 			if (entities == null)
 			{


Reversed order for link resolve

Reversed order for link resolve

--- Contentful.Core/ContentfulClient.cs
+++ Contentful.Core/ContentfulClient.cs
@@ -230,9 +230,8 @@
             var links = entryToken.SelectTokens("$.fields..sys").ToList();

             //Walk through and add any included entries as direct links.
-            for (var i = links.Count - 1; i >= 0; i--)
-            {
-                var linkToken = links[i];
+            foreach (var linkToken in links)
+            {
                 var linkId = ((JValue)linkToken["id"]).Value.ToString();
                 JToken replacementToken = null;
                 if (processedIds.Contains(linkId))


Note on named Bag Part usage

Note on named Bag Part usage

--- Controllers/PersonListController.cs
+++ Controllers/PersonListController.cs
@@ -119,6 +119,7 @@
                 ////person.Alter<BagPart>("The technical name of the BagPart instance.", part => ...);
                 // Or you can create a content part class inheriting from BagPart that has the same name as the BagPart
                 // instance.
+                // Similarly, instead of As<TPart>() you need to use Get<TPart>("TechnicalName").

                 // Once you're done you have to save the content item explicitly. Remember when we saved Books with
                 // ISession.Save()? This is something similar for content items.


Fixes issue with mouse.effect.none

Fixes issue with mouse.effect.none

--- Corale.Colore/Core/NativeWrapper.cs
+++ Corale.Colore/Core/NativeWrapper.cs
@@ -159,6 +159,11 @@
         /// <remarks>This is currently only valid for <see cref="Razer.Mouse.Effects.Effect.None" />.</remarks>
         internal static Guid CreateMouseEffect(Razer.Mouse.Effects.Effect effect)
         {
+            if (effect == Razer.Mouse.Effects.Effect.None)
+            {
+                return CreateMouseEffect(effect, new Razer.Mouse.Effects.None(Razer.Mouse.Led.All));
+            }
+
             return CreateMouseEffect(effect, IntPtr.Zero);
         }


Simplified the state machine

Simplified the state machine

By trusting that Work is never scheduled twice (note: if you need that,
clone the Work), and by trusting that a Work can be rescheduled after
completed the implementation of GCMonitor is improved by using a single
Work instance in GCProbe. This means that GCProbe will not generate
garbage.

--- Core/Theraot/Threading/GCMonitor.cs
+++ Core/Theraot/Threading/GCMonitor.cs
@@ -10,12 +10,10 @@
     {
         private const int INT_CapacityHint = 1024;
         private const int INT_MaxProbingHint = 32;
-        private const int INT_StatusFinished = 3;
+        private const int INT_StatusFinished = 1;
         private const int INT_StatusNotReady = -2;
         private const int INT_StatusPending = -1;
         private const int INT_StatusReady = 0;
-        private const int INT_StatusRequested = 2;
-        private const int INT_StatusRunning = 1;
         private static WeakDelegateSet _collectedEventHandlers;
         private static int _status = INT_StatusNotReady;

@@ -94,8 +92,8 @@

         private static void RaiseCollected()
         {
-            var check = Interlocked.CompareExchange(ref _status, INT_StatusRunning, INT_StatusRequested);
-            if (check == INT_StatusRequested)
+            var check = Thread.VolatileRead(ref _status);
+            if (check == INT_StatusReady)
             {
                 try
                 {
@@ -118,6 +116,13 @@
         [global::System.Diagnostics.DebuggerNonUserCode]
         private sealed class GCProbe : CriticalFinalizerObject
         {
+            private Work _work;
+
+            public GCProbe()
+            {
+                _work = WorkContext.DefaultContext.AddWork(GCMonitor.RaiseCollected);
+            }
+
             ~GCProbe()
             {
                 try
@@ -128,11 +133,11 @@
                 {
                     try
                     {
-                        var check = Interlocked.CompareExchange(ref _status, INT_StatusRequested, INT_StatusReady);
+                        var check = Thread.VolatileRead(ref _status);
                         if (check == INT_StatusReady)
                         {
                             GC.ReRegisterForFinalize(this);
-                            WorkContext.DefaultContext.AddWork(GCMonitor.RaiseCollected).Start();
+                            _work.Start();
                         }
                     }
                     catch


Update Main_frm.cs

Update Main_frm.cs

updated urls for tournament and rankings tab.

--- Main_frm.cs
+++ Main_frm.cs
@@ -150,11 +150,11 @@
                     if (browser.Url == null)
                     {
                         if (tab.Name == "Tournament Room")
-                            browser.Navigate(" http://widget01.mibbit.com/?settings=1d3b9b4a953ff06aa383b6608dde1815&server=liberty.mainframe-irc.net&channel=%23ygopt");
+                            browser.Navigate("http://dev.ygopro-online.net/launcher/tournamentchat.php");
                         else if (tab.Name == "Youtube")
                             browser.Navigate("https://www.youtube.com/user/blub2blb");
                         else if (tab.Name == "Ranking")
-                            browser.Navigate("http://h2092539.stratoserver.net/ranking/ranking.php");
+                            browser.Navigate("http://angelofcode.com/tears/ranking/ranking.php");
                     }
                 }
             }


Added overloads into class CacheDictionary<TKey, TValue>

--- DataAccess/Cache/CacheDictionary.cs
+++ DataAccess/Cache/CacheDictionary.cs
@@ -58,6 +58,29 @@
 			return cntRemoved;
 		}

+		public bool TryRemove(TKey key)
+		{
+			CacheItem<TValue> existingItem;
+
+			return TryRemove(key, out existingItem);
+		}
+
+		public bool TryGetValue(TKey key, out TValue value)
+		{
+			CacheItem<TValue> existingItem;
+
+			if (TryGetValue(key, out existingItem))
+			{
+				value = existingItem.Value;
+				return true;
+			}
+			else
+			{
+				value = default(TValue);
+				return false;
+			}
+		}
+
 		public bool TryGetValue(TKey key, TimeSpan validityPeriod, out TValue value)
 		{
 			CacheItem<TValue> existingItem;
@@ -71,6 +94,26 @@

 			value = default(TValue);
 			return false;
+		}
+
+		public TValue GetOrAdd(TKey key, TValue value)
+		{
+			CacheItem<TValue> existingItem;
+
+			if (TryGetValue(key, out existingItem))
+				return existingItem.Value;
+			else
+			{
+				if (value != null)
+					TryAdd(key, value);
+
+				return value;
+			}
+		}
+
+		public int RemoveExpiredKeys(TimeSpan validityPeriod)
+		{
+			return TryRemove(GetExpiredKeys(validityPeriod).ToList());
 		}

 		public IEnumerable<TKey> GetExpiredKeys(TimeSpan validityPeriod)


Show warning for Obsolete

Show warning for Obsolete

--- Enum.cs
+++ Enum.cs
@@ -3,7 +3,7 @@

 namespace QcloudSharp
 {
-    [Obsolete("QcloudSharp.Enum is deprecated, please use QcloudSharp.Enums.",true)]
+    [Obsolete("QcloudSharp.Enum is deprecated, please use QcloudSharp.Enums.")]
     public static class Enum : Enums
     {
         public static string ToEndpoint(Endpoint en)


method to prepare graphic properties in all constructors

--- Icon.cs
+++ Icon.cs
@@ -21,21 +21,25 @@
         {
             // create new image
             image = new Bitmap(WIDTH, HEIGHT, PixelFormat.Format32bppArgb);
-            image.SetResolution(72.0f, 72.0f); // fix DPI
-
-            g = Graphics.FromImage(image);
-
-            g.PageUnit = GraphicsUnit.Pixel;
-            g.SmoothingMode = SmoothingMode.None;
-            g.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
-            g.TextContrast = 0;
+            prepareGraphics();
         }

         public Icon(string parentFile)
         {
             // use existing image
-            this.image = new Bitmap(ImageTools.loadFromFile(parentFile));
-            this.g = Graphics.FromImage(image);
+            image = new Bitmap(ImageTools.loadFromFile(parentFile));
+            prepareGraphics();
+        }
+
+        protected void prepareGraphics()
+        {
+            image.SetResolution(72.0f, 72.0f); // fix DPI
+
+            g = Graphics.FromImage(image);
+            g.PageUnit = GraphicsUnit.Pixel;
+            g.SmoothingMode = SmoothingMode.None;
+            g.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
+            g.TextContrast = 0;
         }

         public void Save(string outputFile)
@@ -52,7 +56,7 @@
             }
             catch (Exception e)
             {
-                Console.WriteLine("\nError during appling layer: " + layer.Method);
+                Console.WriteLine("Error during appling layer: " + layer.Method);
                 Console.WriteLine(e.Message + "\n");
             }
         }


Added new filters to test > 3x3 matrices


Add optional property to tab.cs

Add optional property to tab.cs

--- DocuSign.Integrations.Client/Tab.cs
+++ DocuSign.Integrations.Client/Tab.cs
@@ -94,6 +94,10 @@
         /// </summary>
         public bool anchorIgnoreIfNotPresent { get; set; }
         /// <summary>
+        ///When set to ‘true’, the signerAttachmentTab is optional and not required to complete the envelope.
+        /// </summary>
+        public string optional { get; set; }
+        /// <summary>
         ///The font size used for the information in
         ///the tab. Possible values are: Size7,
         ///Size8, Size9, Size10, Size11, Size12,


added another field for PVisualizer

added another field for PVisualizer

--- Src/Pc/Compiler.cs
+++ Src/Pc/Compiler.cs
@@ -85,6 +85,12 @@
             private set;
         }

+        public Dictionary<string, PProgram> ParsedPrograms // used only by PVisualizer
+        {
+            get;
+            private set;
+        }
+
         public Compiler(CommandLineOptions options)
         {
             Options = options;
@@ -170,6 +176,8 @@
                     parserWorkQueue.Enqueue(fullFileName);
                 }
             }
+
+            ParsedPrograms = parsedPrograms;

             //// Step 1. Serialize the parsed object graph into a Formula model and install it. Should not fail.
             InstallResult instResult;


Changed namespace to TinySharp

Changed namespace to TinySharp

--- Tiny.cs
+++ Tiny.cs
@@ -4,7 +4,7 @@
 using System.Text;
 using System.Security.Cryptography;

-namespace TinyProj
+namespace TinySharp
 {
     /// <summary>
     /// A reversable base62 ID obfuscater


-fixed up phantom sync code location when RTP payload is empty

--- TsPacket.cs
+++ TsPacket.cs
@@ -174,6 +174,12 @@
         private static int FindSync(IList<byte> tsData, int offset)
         {
             if (tsData == null) throw new ArgumentNullException(nameof(tsData));
+
+            //not big enough to be any kind of single TS packet
+            if (tsData.Count < 188)
+            {
+                return -1;
+            }

             try
             {


"Paste" must happen in a transaction

"Paste" must happen in a transaction

git-svn-id: 53f3c0fc50e56599d49cd3470d1ba0222ad3846f@8021 4a90e977-6436-4932-9605-20e10c2b6fb3

--- EditorController/EditableScripts.cs
+++ EditorController/EditableScripts.cs
@@ -269,11 +269,13 @@

         public void Paste(int index)
         {
+            m_controller.StartTransaction("Paste script");
             foreach (IScript script in m_controller.GetClipboardScript())
             {
                 m_underlyingScript.Insert(index, m_controller.ScriptFactory.Clone(script));
                 index++;
             }
+            m_controller.EndTransaction();
         }
     }
 }


UOErebor: Fixed potion cooldown when drinking via sphere command - script must take a look into backpack's nested containers.

--- ExampleScripts/UOErebor/potions.csx
+++ ExampleScripts/UOErebor/potions.csx
@@ -132,7 +132,7 @@
             if (args.Message.Equals(potion.Command, StringComparison.OrdinalIgnoreCase))
             {
                 Trace.Log("command found");
-                if (UO.Items.InBackPack().Matching(potion.Spec).Any())
+                if (UO.Items.InBackPack(true).Matching(potion.Spec).Any())
                 {
                     Trace.Log("potion found in backpack");
                     StartPotion(potion);


Add test Notes.UpdateTest.WithExistingTags

--- FTF.Tests.XUnit/Notes/UpdateTest.cs
+++ FTF.Tests.XUnit/Notes/UpdateTest.cs
@@ -35,6 +35,21 @@
         }

         [Fact]
+        public void WithExistingTags()
+        {
+            App.Notes.Create("Note with #Tag");
+
+            var noteId = App.Notes.Create("Note without tag");
+
+            App.Notes.Update(noteId, "Note update with #Tag");
+
+            var tags = App.Tags.All().ToList();
+
+            Assert.Equal(new[] { "Tag" }, tags.Select(t => t.Name));
+            Assert.Equal(new[] { 2 }, tags.Select(t => t.NotesCount));
+        }
+
+        [Fact]
         public void EmptyText()
         {
             var noteId = App.Notes.Create("Buy cheese");


Added SteamServer.LogOff()

Added SteamServer.LogOff()

--- Facepunch.Steamworks/SteamServer.cs
+++ Facepunch.Steamworks/SteamServer.cs
@@ -274,6 +274,14 @@
 		}

 		/// <summary>
+		/// Log onto Steam anonymously.
+		/// </summary>
+		public static void LogOff()
+		{
+			Internal.LogOff();
+		}
+
+		/// <summary>
 		/// Returns true if the server is connected and registered with the Steam master server
 		/// You should have called LogOnAnonymous etc on startup.
 		/// </summary>


Patch for the RemoveDuplicateRecords in the CommonEngine (Sent by Christian http://www.filehelpers.com/forums/viewtopic.php?p=1671#1671)

git-svn-id: cdbd3c3453b226d8644b39c93ea790e37ea3ca1b@696 fafefce7-770d-0410-b8bf-a6f642d37c66

--- FileHelpers/Engines/CommonEngine.cs
+++ FileHelpers/Engines/CommonEngine.cs
@@ -599,7 +599,7 @@
         /// <returns>An array with the result of remove the duplicate records from the source array.</returns>
         public static IComparableRecord[] RemoveDuplicateRecords(IComparableRecord[] arr)
         {
-            if (arr == null || arr.Length == 0)
+            if (arr == null || arr.Length <= 1)
                 return arr;

             ArrayList nodup = new ArrayList();


Got rid of marhalling. Increased indices type to int because of big maps.

--- GUI/Types/Renderer/PhysSceneNode.cs
+++ GUI/Types/Renderer/PhysSceneNode.cs
@@ -2,11 +2,9 @@
 using System.Collections.Generic;
 using OpenTK.Graphics.OpenGL;
 using GUI.Utils;
-using ValveResourceFormat.Blocks;
 using ValveResourceFormat.ResourceTypes;
 using ValveResourceFormat.Serialization;
 using System.Numerics;
-using System.Runtime.InteropServices;
 using System.Linq;

 namespace GUI.Types.Renderer
@@ -27,7 +25,7 @@
             this.phys = phys;

             var verts = new List<float>();
-            var inds = new List<ushort>();
+            var inds = new List<int>();

             var parts = phys.Data.GetArray("m_parts");
             foreach (var p in parts)
@@ -78,9 +76,9 @@
                     var edges = hull.GetArray("m_Edges");
                     foreach (var e in edges)
                     {
-                        inds.Add((ushort)(vertOffset + e.GetIntegerProperty("m_nOrigin")));
+                        inds.Add((int)(vertOffset + e.GetIntegerProperty("m_nOrigin")));
                         var next = edges[e.GetIntegerProperty("m_nNext")];
-                        inds.Add((ushort)(vertOffset + next.GetIntegerProperty("m_nOrigin")));
+                        inds.Add((int)(vertOffset + next.GetIntegerProperty("m_nOrigin")));
                     }
                     //m_Faces
                     //m_Bounds
@@ -103,8 +101,11 @@
                     {
                         //KV3 has vertices as blob
                         var verticesBlob = mesh.GetArray<byte>("m_Vertices");
-                        vertices = new Vector3[verticesBlob.Length/12];
-                        verticesBlob.AsSpan().TryCopyTo(MemoryMarshal.AsBytes(vertices.AsSpan()));
+                        vertices = Enumerable.Range(0, verticesBlob.Length / 12)
+                            .Select(i => new Vector3(BitConverter.ToSingle(verticesBlob, i * 12),
+                                BitConverter.ToSingle(verticesBlob, (i * 12) + 4),
+                                BitConverter.ToSingle(verticesBlob, (i * 12) + 8)))
+                            .ToArray();
                     }

                     foreach (var v in vertices)
@@ -131,20 +132,22 @@
                         //KV3 has triangles as blob
                         var trianglesBlob = mesh.GetArray<byte>("m_Triangles");
                         triangles = new int[trianglesBlob.Length / 4];
-                        trianglesBlob.AsSpan().TryCopyTo(MemoryMarshal.AsBytes(triangles.AsSpan()));
-                    }
-
-                    for (int i = 0; i < triangles.Length; i+=3)
-                    {
-                        inds.Add((ushort)(vertOffset + triangles[i]));
-                        inds.Add((ushort)(vertOffset + triangles[i+1]));
-                        inds.Add((ushort)(vertOffset + triangles[i+1]));
-                        inds.Add((ushort)(vertOffset + triangles[i+2]));
-                        inds.Add((ushort)(vertOffset + triangles[i+2]));
-                        inds.Add((ushort)(vertOffset + triangles[i]));
+                        System.Buffer.BlockCopy(trianglesBlob, 0, triangles, 0, trianglesBlob.Length);
+                    }
+
+                    for (int i = 0; i < triangles.Length; i += 3)
+                    {
+                        inds.Add(vertOffset + triangles[i]);
+                        inds.Add(vertOffset + triangles[i + 1]);
+                        inds.Add(vertOffset + triangles[i + 1]);
+                        inds.Add(vertOffset + triangles[i + 2]);
+                        inds.Add(vertOffset + triangles[i + 2]);
+                        inds.Add(vertOffset + triangles[i]);
                     }
                 }
                 //m_CollisionAttributeIndices
+
+                //Console.WriteLine($"Phys mesh verts {verts.Count} inds {inds.Count}");
             }

             LocalBoundingBox = new AABB(-10, -10, -10, 10, 10, 10);
@@ -162,7 +165,7 @@
             iboHandle = GL.GenBuffer();
             indexCount = inds.Count;
             GL.BindBuffer(BufferTarget.ElementArrayBuffer, iboHandle);
-            GL.BufferData(BufferTarget.ElementArrayBuffer, inds.Count * sizeof(ushort), inds.ToArray(), BufferUsageHint.StaticDraw);
+            GL.BufferData(BufferTarget.ElementArrayBuffer, inds.Count * sizeof(int), inds.ToArray(), BufferUsageHint.StaticDraw);

             const int stride = sizeof(float) * 7;
             var positionAttributeLocation = GL.GetAttribLocation(shader.Program, "aVertexPosition");
@@ -176,7 +179,7 @@
             GL.BindVertexArray(0);
         }

-        private static void AddCapsule(List<float> verts, List<ushort> inds, Vector3 c0, Vector3 c1, float radius)
+        private static void AddCapsule(List<float> verts, List<int> inds, Vector3 c0, Vector3 c1, float radius)
         {
             Matrix4x4 mtx = Matrix4x4.CreateLookAt(c0, c1, Vector3.UnitY);
             mtx.Translation = Vector3.Zero;
@@ -214,19 +217,19 @@
                 verts.Add(0);
                 verts.Add(1);

-                inds.Add((ushort)(vertOffset + i * 2));
-                inds.Add((ushort)(vertOffset + i * 2 + 1));
+                inds.Add(vertOffset + i * 2);
+                inds.Add(vertOffset + i * 2 + 1);
             }
         }

-        private static void AddSphere(List<float> verts, List<ushort> inds, Vector3 center, float radius)
+        private static void AddSphere(List<float> verts, List<int> inds, Vector3 center, float radius)
         {
             AddCircle(verts, inds, center, radius, Matrix4x4.Identity);
             AddCircle(verts, inds, center, radius, Matrix4x4.CreateRotationX(MathF.PI * 0.5f));
             AddCircle(verts, inds, center, radius, Matrix4x4.CreateRotationY(MathF.PI * 0.5f));
         }

-        private static void AddCircle(List<float> verts, List<ushort> inds, Vector3 center, float radius, Matrix4x4 mtx)
+        private static void AddCircle(List<float> verts, List<int> inds, Vector3 center, float radius, Matrix4x4 mtx)
         {
             var vertOffset = verts.Count / 7;
             for (int i = 0; i < 16; i++)
@@ -246,8 +249,8 @@
                 verts.Add(0);
                 verts.Add(1);

-                inds.Add((ushort)(vertOffset + i));
-                inds.Add((ushort)(vertOffset + (i + 1) % 16));
+                inds.Add(vertOffset + i);
+                inds.Add(vertOffset + (i + 1) % 16);
             }
         }

@@ -264,7 +267,7 @@
             GL.DepthMask(false);

             GL.BindVertexArray(vaoHandle);
-            GL.DrawElements(PrimitiveType.Lines, indexCount, DrawElementsType.UnsignedShort, 0);
+            GL.DrawElements(PrimitiveType.Lines, indexCount, DrawElementsType.UnsignedInt, 0);
             GL.BindVertexArray(0);

             GL.DepthMask(true);


Fix erroneous XML Doc Comment

Fix erroneous XML Doc Comment

This commit fixes an erroneous XML Doc Comment which specified that a
ChangesetSummary was returned when, in fact, only an integer is
returned--representing a changeset ID.

Also, some extraneous trailing whitespace was removed from this same XML
Doc Comment, as well as other XML Doc Comments in the file.

Signed-off-by: Craig E. Shea <f7d0fe99b1b4f619d351ea8138e85d617724d689@gmail.com>

--- GitTfs.VsCommon/TfsHelper.Common.cs
+++ GitTfs.VsCommon/TfsHelper.Common.cs
@@ -187,7 +187,7 @@
                 if (changesets.Length > 0)
                     start = changesets[changesets.Length - 1].ChangesetId + 1;

-                // don't take the enumerator produced by a foreach statement or a yield statement, as there are references
+                // don't take the enumerator produced by a foreach statement or a yield statement, as there are references
                 // to the old (iterated) elements and thus the referenced changesets won't be disposed until all elements were iterated.
                 for (int i = 0; i < changesets.Length; i++)
                 {
@@ -451,7 +451,7 @@
         }

         /// <summary>
-        /// Gets the relevant TFS <see cref="ChangesetSummary"/> for the root changeset given a set
+        /// Gets the relevant TFS changeset ID for the root changeset given a set
         /// of <see cref="ExtendedMerge"/> objects and a given <paramref name="tfsPathParentBranch"/>.
         /// </summary>
         /// <param name="merges">An array of <see cref="ExtendedMerge"/> objects describing the a set of merges.</param>
@@ -459,12 +459,11 @@
         /// <param name="tfsPathBranchToCreate">The tfs Path Branch To Create.</param>
         /// <param name="renameFromBranch"></param>
         /// <remarks>
-        /// Each <see cref="ChangeType"/> uses the SourceChangeset, SourceItem, TargetChangeset, and TargetItem
+        /// Each <see cref="ChangeType"/> uses the SourceChangeset, SourceItem, TargetChangeset, and TargetItem
         /// properties with different semantics, depending on what it needs to describe, so the strategy to determine
         /// whether we are interested in a given ExtendedMerge summary depends on the SourceItem's <see cref="ChangeType"/>.
         /// </remarks>
-        /// <returns>the <see cref="ChangesetSummary"/> of the changeset found.
-        /// </returns>
+        /// <returns>Returns an integer representing the found changeset ID.</returns>
         private int GetRelevantChangesetBasedOnChangeType(IEnumerable<MergeInfo> merges, string tfsPathParentBranch, string tfsPathBranchToCreate, out string renameFromBranch)
         {
             renameFromBranch = null;
@@ -811,11 +810,11 @@
         }
         /// <summary>
         /// Method to help improve the process that deletes workspaces used by Git-TFS.
-        /// The the delete fails, the process pauses for 5 seconds and retry 25 times before reporting failures.
+        /// The the delete fails, the process pauses for 5 seconds and retry 25 times before reporting failures.
         /// </summary>
         /// <param name="workspace"></param>
         /// <remarks>
-        /// TFS randomly seems to report a workspace removed/deleted BUT subsequent calls by Git-TFS suggest that the delete hasn't actually been completed.
+        /// TFS randomly seems to report a workspace removed/deleted BUT subsequent calls by Git-TFS suggest that the delete hasn't actually been completed.
         /// This suggest that deletes may be queued and take a lower priority than other actions, especially if the TFS server is under load.
         /// </remarks>
         private void TryToDeleteWorkspace(Workspace workspace)
@@ -823,7 +822,7 @@
             //  Try and ensure the client and TFS Server are synchronized.
             workspace.Refresh();

-            //  When deleting a workspace we may need to allow the TFS server some time to complete existing processing or re-try the workspace delete.
+            //  When deleting a workspace we may need to allow the TFS server some time to complete existing processing or re-try the workspace delete.
             var deleteWsCompleted = Retry.Do(() => workspace.Delete(), TimeSpan.FromSeconds(5), 25);

             // Include trace information about the success of the TFS API that deletes the workspace.
@@ -1084,7 +1083,7 @@
                         throw new InvalidOperationException("You can't query ContentLength before downloading the file");
                     // It is not great solution, but at least makes the contract explicit.
                     // We can't actually save downloaded file in this class, because if nobody asks
-                    // for it - we won't know when it is safe to delete it and it will stay in the
+                    // for it - we won't know when it is safe to delete it and it will stay in the
                     // system forever, which is bad. Implementing finalizer to delete file is also bad solution:
                     // suppose process was killed in the middle of many-megabyte operation on thousands of files
                     // if we delete them as soon as they are not used - only current file will remain. Otherwise
@@ -1356,9 +1355,9 @@
         /// <summary>
         /// Try to get the value of a key beginning with the name 'startOfName'
         /// and present in the tree path 'path' in the 'Current user' registry root.
-        ///
+        ///
         /// ex:
-        ///
+        ///
         /// The value "Microsoft.VisualStudio.TeamFoundation.TeamExplorer.Extensions" for parameter 'startOfName'
         /// will find "Microsoft.VisualStudio.TeamFoundation.TeamExplorer.Extensions,14.0.24712"
         /// and "Microsoft.VisualStudio.TeamFoundation.TeamExplorer.Extensions,14.0.23102"


Simplified the logic for creating the SVG string.

--- ImageTracerNet/Svg/SvgGeneration.cs
+++ ImageTracerNet/Svg/SvgGeneration.cs
@@ -15,12 +15,12 @@
         public static string ToSvgString(this TracedImage image, SvgRendering options)
         {
             // SVG start
-            var width = (int)(image.Width * options.Scale);
-            var height = (int)(image.Height * options.Scale);
+            var scaledWidth = (int)(image.Width * options.Scale);
+            var scaledHeight = (int)(image.Height * options.Scale);

             var viewBoxOrViewPort = options.Viewbox ?
-                $"viewBox=\"0 0 {width} {height}\"" :
-                $"width=\"{width}\" height=\"{height}\"";
+                $"viewBox=\"0 0 {scaledWidth} {scaledHeight}\"" :
+                $"width=\"{scaledWidth}\" height=\"{scaledHeight}\"";
             var stringBuilder = new StringBuilder($"<svg {viewBoxOrViewPort} version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" ");
             if (options.Desc)
             {
@@ -34,7 +34,7 @@
                 .SelectMany(cs => cs.Value.Paths.Select(p =>
                 {
                     var firstSegmentStart = p.Segments.First().Start;
-                    var label = firstSegmentStart.Y * width + firstSegmentStart.X;
+                    var label = firstSegmentStart.Y * scaledWidth + firstSegmentStart.X;
                     return new ZPosition { Label = label, Color = cs.Key, Path = p };
                 })).OrderBy(z => z.Label);
             // Sorting Z-index is not required, TreeMap is sorted automatically
@@ -43,13 +43,13 @@
             // Z-index loop
             foreach (var zPosition in zSortedLayers)
             {
-                //var zValue = zPosition.Value;
                 var description = String.Empty;
                 //if (options.Desc)
                 //{
                 //    description = $"desc=\"l {zValue.Layer} p {zValue.Path}\" ";
                 //}
-                AppendPathString(stringBuilder, description, zPosition.Path.Segments, zPosition.Color.ToSvgColorString(), options);
+                var scaledSegments = zPosition.Path.Segments.Select(s => s.Scale(options.Scale)).ToList();
+                AppendPathString(stringBuilder, description, scaledSegments, zPosition.Color.ToSvgColorString(), options);
             }

             // SVG End
@@ -59,22 +59,15 @@
         }

         // Getting SVG path element string from a traced path
-        internal static void AppendPathString(StringBuilder stringBuilder, string description, IReadOnlyList<Segment> segments, string colorString, SvgRendering options)
+        internal static StringBuilder AppendPathString(StringBuilder stringBuilder, string description, IReadOnlyList<Segment> segments, string colorString, SvgRendering options)
         {
-            var scaledSegments = segments.Select(s => s.Scale(options.Scale)).ToList();
-
             // Path
-            stringBuilder.Append($"<path {description}{colorString}d=\"M {scaledSegments[0].Start.X} {scaledSegments[0].Start.Y} ");
+            stringBuilder.Append($"<path {description}{colorString}d=\"M {segments[0].Start.X} {segments[0].Start.Y} ");
             //http://stackoverflow.com/a/217814/294804
-            scaledSegments.Aggregate(stringBuilder, (current, next) => current.Append(next.ToPathString()));
-            stringBuilder.Append("Z\" />");
+            segments.Aggregate(stringBuilder, (sb, segment) => sb.Append(segment.ToPathString())).Append("Z\" />");

             // Rendering control points
-            var filteredSegments = scaledSegments.Where(s => s.Radius > 0);
-            foreach (var segment in filteredSegments)
-            {
-                stringBuilder.Append(segment.ToControlPointString());
-            }
+            return segments.Where(s => s.Radius > 0).Aggregate(stringBuilder, (sb, segment) => sb.Append(segment.ToControlPointString()));
         }

         internal static string ToSvgColorString(this ColorReference c)


Added failing tests for ordered values

Added failing tests for ordered values

--- IniSerializer/SerializationTests.cs
+++ IniSerializer/SerializationTests.cs
@@ -148,7 +148,60 @@
                 Assert.IsNull(_serializedOutput.SingleOrDefault(str => str.Contains("StringValueWithNoAttribute")));
             }
         }
-    }
+
+        private class When_the_properties_on_the_object_to_be_serialized_have_the_order_set
+        {
+            private readonly string[] _serializedOutput;
+
+            [IniSection("[Section Heading for section with ordered properties]")]
+            private class ObjectToSerialize
+            {
+                [IniValue("Item1")]
+                public string Item1 { get; set; }
+
+                [IniValue("Item2")]
+                public string Item2 { get; set; }
+
+                [IniValue("Item3")]
+                public string Item3 { get; set; }
+            }
+
+            public When_the_properties_on_the_object_to_be_serialized_have_the_order_set()
+            {
+                _serializedOutput =
+                    new IniSerializer<ObjectToSerialize>().Serialize(
+                        new ObjectToSerialize
+                        {
+                            Item1 = "Position 3",
+                            Item2 = "Position 1",
+                            Item3 = "Position 2",
+                        }).Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
+            }
+
+            [Test]
+            public void Then_the_section_name_is_output_on_the_first_line()
+            {
+                Assert.AreEqual("[Section Heading for section with ordered properties]", _serializedOutput[0]);
+            }
+
+            [Test]
+            public void Then_the_objects_are_ordered_correctly()
+            {
+                Assert.AreEqual("Item2", _serializedOutput[1]);
+                Assert.AreEqual("Item3", _serializedOutput[2]);
+                Assert.AreEqual("Item1", _serializedOutput[3]);
+            }
+        }
+    }
+
+    //public class Given_I_want_to_serialize_a_list_of_objects
+    //{
+    //    public class When_there_are_multiple_objects
+    //    {
+    //
+    //    }
+    //}
+
     public class MustImplementIniSectionAttributeException : Exception
     {
         public MustImplementIniSectionAttributeException()
@@ -156,6 +209,7 @@
         {
         }
     }
+

     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
     internal class IniSectionAttribute : Attribute


Fixed reinitialization of position in UIWindowBase

--- UI/UIWindowBase.cs
+++ UI/UIWindowBase.cs
@@ -22,6 +22,9 @@
         [ConfigOption]
         protected Vector3 pos = Vector3.zero;

+        [ConfigOption]
+        protected bool initialized;
+
         protected UIWindowBase(UIBundle bundle)
         {
             this.bundle = bundle;
@@ -35,7 +38,6 @@
             if(in_progress || Controller != null)
                 yield break;
             in_progress = true;
-            bool first_start = false;
             if(prefab == null)
             {
                 foreach(var _ in bundle.LoadAsset(prefab_name))
@@ -43,7 +45,6 @@
                 prefab = bundle.GetAsset(prefab_name);
                 if(prefab == null)
                     goto end;
-                first_start = true;
             }
             var obj = Object.Instantiate(prefab);
             Controller = obj.GetComponent<T>();
@@ -55,10 +56,10 @@
                 Object.Destroy(obj);
                 goto end;
             }
+            obj.transform.SetParent(DialogCanvasUtil.DialogCanvasRect);
             init_controller();
-            obj.transform.SetParent(DialogCanvasUtil.DialogCanvasRect);
             obj.SetActive(true);
-            if(first_start)
+            if(!initialized)
             {
                 obj.transform.localPosition = new Vector3(-Screen.width, 0);
                 Rect rect = new Rect();
@@ -68,6 +69,7 @@
                     yield return null;
                 }
                 pos = new Vector3(-rect.width / 2, rect.height / 2);
+                initialized = true;
             }
             obj.transform.localPosition = pos;
         end:


show hint for configuring proxy when network exception received

--- WakaTimePackage.cs
+++ WakaTimePackage.cs
@@ -112,6 +112,10 @@

                 Logger.Info(string.Format("Finished initializing WakaTime v{0}", WakaTimeConstants.PluginVersion));
             }
+            catch (System.Net.WebException ex)
+            {
+                Logger.Error("Are you behind a proxy? Try setting a proxy in WakaTime Settings with format https://user:pass@host:port. Exception Traceback:", ex);
+            }
             catch (Exception ex)
             {
                 Logger.Error("Error initializing Wakatime", ex);


Added WriteException

Added WriteException

--- WaterLogged/Log.cs
+++ WaterLogged/Log.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Text;
 using WaterLogged.Templating;

 namespace WaterLogged
@@ -718,5 +719,52 @@
                 }
             }
         }
+
+
+        //********************************************
+        // WriteException
+        //********************************************
+
+        public void WriteException(Exception exception)
+        {
+            WriteException(exception, false, "", false);
+        }
+
+        public void WriteException(Exception exception, bool throwException)
+        {
+            WriteException(exception, false, "", false);
+        }
+
+        public void WriteException(Exception exception, bool throwException, string tag)
+        {
+            WriteException(exception, throwException, tag, false);
+        }
+
+        public void WriteException(Exception exception, bool throwException, string tag, bool printStack)
+        {
+            var builder = new StringBuilder();
+            GetExceptionPrintout(builder, exception);
+
+            if (printStack)
+            {
+                builder.AppendLine(exception.StackTrace);
+            }
+
+            WriteTag(builder.ToString(), tag);
+            if (throwException)
+            {
+                throw exception;
+            }
+        }
+
+        private void GetExceptionPrintout(StringBuilder builder, Exception exception, string indention = "")
+        {
+            if (exception == null)
+            {
+                return;
+            }
+            builder.AppendFormat("{0}{1}: {2}{3}", indention, exception.GetType(), exception.Message, Environment.NewLine);
+            GetExceptionPrintout(builder, exception.InnerException, indention + "  ");
+        }
     }
 }