Improving test

Improving test

--- EasyActor.PipeLineTest/PipeLineTestor.cs
+++ EasyActor.PipeLineTest/PipeLineTestor.cs
@@ -15,27 +15,88 @@
     public class PipeLineTestor
     {
         private TestFunction<int, int>  _Func;
+        private TestFunction<int, int> _Func2;
+        private TestFunction<int, int> _Func3;
         private TestAction<int> _Act;
+        private TestAction<int> _Act2;

         [SetUp]
         public void SetUp()
         {
             _Func = new TestFunction<int, int>(a => a * 5);
+            _Func2 = new TestFunction<int, int>(a => a - 2);
+            _Func3 = new TestFunction<int, int>(a => a + 2);
             _Act = new TestAction<int>();
+            _Act2 = new TestAction<int>();
         }

         [Test]
         [TestCase(0, 0)]
         [TestCase(2,10)]
         [TestCase(1, 5)]
-        public async Task Should_Compute_Result_OK(int iin, int iout)
+        public async Task Create_Should_Compute_Result_OK(int iin, int iout)
         {
             var current = Thread.CurrentThread;
             var pip = PipeLine.Create<int, int>(_Func.Function).Next(_Act.Action);
             await pip.Consume(iin);

+            _Func.LastIn.Should().Be(iin);
             _Func.LastOut.Should().Be(iout);
             _Func.CallingThread.Should().NotBe(current);
+            _Act.CallingThread.Should().NotBe(current);
+            _Act.CallingThread.Should().NotBe(_Func.CallingThread);
+        }
+
+
+        [Test]
+        [TestCase(0, -2)]
+        [TestCase(2, 8)]
+        [TestCase(1, 3)]
+        public async Task Compose_Should_Compute_Result_OK(int iin, int iout)
+        {
+            var current = Thread.CurrentThread;
+            var pip = PipeLine.Create<int, int>(_Func.Function).Next(_Func2.Function).Next(_Act.Action);
+            await pip.Consume(iin);
+
+            _Func.LastIn.Should().Be(iin);
+            _Func2.LastOut.Should().Be(iout);
+            _Func2.CallingThread.Should().NotBe(current);
+            _Func2.CallingThread.Should().NotBe(_Func.CallingThread);
+            _Act.CallingThread.Should().NotBe(current);
+            _Act.CallingThread.Should().NotBe(_Func.CallingThread);
+        }
+
+
+        //                     ___ i => i * 3 -----> Console.WriteLine("1 - {0} {1}")
+        //                    /
+        //      a => a * 2 ---
+        //                    \___ i => i * 5 -----> Console.WriteLine("1 - {0} {1}")
+        [TestCase(0, 0, 2)]
+        [TestCase(1, 5, 3)]
+        [TestCase(2, 10, 4)]
+        [TestCase(10, 50, 12)]
+        [Test]
+        public async Task Compose_Parralel_Should_Compute_Result_OK(int entry, int s1, int s2)
+        {
+
+            var current = Thread.CurrentThread;
+            var finaliser1 = PipeLine.Create<int, int>(_Func.Function).Next(_Act.Action);
+            var finaliser2 = PipeLine.Create<int, int>(_Func3.Function).Next(_Act2.Action);
+
+            await PipeLine.Create<int, int>(a => a).Next(finaliser1, finaliser2).Consume(entry);
+
+
+            _Func.LastIn.Should().Be(entry);
+            _Func.LastOut.Should().Be(s1);
+
+            _Func3.LastIn.Should().Be(entry);
+            _Func3.LastOut.Should().Be(s2);
+
+            _Func3.CallingThread.Should().NotBe(current);
+            _Func3.CallingThread.Should().NotBe(_Func.CallingThread);
+
+            _Func.CallingThread.Should().NotBe(current);
+            _Func.CallingThread.Should().NotBe(_Func3.CallingThread);
         }


Brand separator is back for newer versions of Unity.

--- Editor/AGXUnityEditor/InspectorEditor.cs
+++ Editor/AGXUnityEditor/InspectorEditor.cs
@@ -122,8 +122,8 @@
       if ( Utils.KeyHandler.HandleDetectKeyOnGUI( this.targets, Event.current ) )
         return;

+      if ( IsMainEditor ) {
 #if UNITY_2019_2_OR_EARLIER
-      if ( IsMainEditor ) {
         var controlRect = EditorGUILayout.GetControlRect( false, 0.0f );
         if ( m_icon == null )
           m_icon = Resources.Load<Texture2D>( "agx_icon_small" );
@@ -133,10 +133,10 @@
         UnityEngine.GUI.DrawTexture( rect, GUI.CreateColoredTexture( 1, 1, InspectorGUI.BackgroundColor ) );
         // Draw our transparent icon.
         UnityEngine.GUI.DrawTexture( rect, m_icon );
+#endif

         InspectorGUI.BrandSeparator();
       }
-#endif

       GUILayout.BeginVertical();


import G1 functions

import G1 functions

--- ffi/cs/Program.cs
+++ ffi/cs/Program.cs
@@ -5,12 +5,9 @@
 namespace bn256 {
 	class X {
 		[DllImport("bn256_if.dll")] public static extern int BN256_setErrFile([In][MarshalAs(UnmanagedType.LPStr)] string name);
-
 		[DllImport("bn256_if.dll")] public static extern int BN256_init();
-
 		[DllImport("bn256_if.dll")] public static extern void BN256_Fr_clear([Out] Fr x);
 		[DllImport("bn256_if.dll")] public static extern void BN256_Fr_setInt([Out] Fr y, int x);
-		[DllImport("bn256_if.dll")] public static extern void BN256_Fr_copy([Out] Fr y, [In] Fr x);
 		[DllImport("bn256_if.dll")] public static extern int BN256_Fr_setStr([Out] Fr x, [In][MarshalAs(UnmanagedType.LPStr)] string s);
 		[DllImport("bn256_if.dll")] public static extern int BN256_Fr_isValid([In] Fr x);
 		[DllImport("bn256_if.dll")] public static extern int BN256_Fr_isSame([In] Fr x, [In] Fr y);
@@ -28,12 +25,22 @@
 		[DllImport("bn256_if.dll")] public static extern void BN256_Fr_mul([Out] Fr z, [In] Fr x, [In] Fr y);
 		[DllImport("bn256_if.dll")] public static extern void BN256_Fr_div([Out] Fr z, [In] Fr x, [In] Fr y);

+		[DllImport("bn256_if.dll")] public static extern void BN256_G1_clear([Out] G1 x);
+		[DllImport("bn256_if.dll")] public static extern int BN256_G1_setStr([Out] G1 x, [In][MarshalAs(UnmanagedType.LPStr)] string s);
+		[DllImport("bn256_if.dll")] public static extern int BN256_G1_isValid([In] G1 x);
+		[DllImport("bn256_if.dll")] public static extern int BN256_G1_isSame([In] G1 x, [In] G1 y);
+		[DllImport("bn256_if.dll")] public static extern int BN256_G1_isZero([In] G1 x);
+		[DllImport("bn256_if.dll")] public static extern int BN256_G1_hashAndMapTo([Out] G1 x, [In][MarshalAs(UnmanagedType.LPStr)] string s);
+		[DllImport("bn256_if.dll")] public static extern int BN256_G1_getStr([Out]StringBuilder buf, long maxBufSize, [In] G1 x);
+		[DllImport("bn256_if.dll")] public static extern void BN256_G1_neg([Out] G1 y, [In] G1 x);
+		[DllImport("bn256_if.dll")] public static extern void BN256_G1_dbl([Out] G1 y, [In] G1 x);
+		[DllImport("bn256_if.dll")] public static extern void BN256_G1_add([Out] G1 z, [In] G1 x, [In] G1 y);
+		[DllImport("bn256_if.dll")] public static extern void BN256_G1_sub([Out] G1 z, [In] G1 x, [In] G1 y);
+		[DllImport("bn256_if.dll")] public static extern void BN256_G1_mul([Out] G1 z, [In] G1 x, [In] Fr y);
+
 		[StructLayout(LayoutKind.Sequential)]
 		public class Fr {
-			private ulong v0;
-			private ulong v1;
-			private ulong v2;
-			private ulong v3;
+			private ulong v0, v1, v2, v3;
 			public void Clear()
 			{
 				BN256_Fr_clear(this);
@@ -139,6 +146,10 @@
 				return z;
 			}
 		}
+		[StructLayout(LayoutKind.Sequential)]
+		public class G1 {
+			private ulong v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11;
+		}

 		static void Main(string[] args)
 		{
@@ -148,7 +159,10 @@
 			Console.WriteLine("ret= {0}", ret);
 			ret = BN256_setErrFile("c:/tmp/abc.txt");
 			Console.WriteLine("ret= {0}", ret);
-
+			TestFr();
+		}
+		static void TestFr()
+		{
 			Fr x = new Fr();
 			x.Clear();
 			Console.WriteLine("x = {0}", x);


Fixed the unit test build

Fixed the unit test build

--- Espera.View.Tests/ArtistViewModelTest.cs
+++ Espera.View.Tests/ArtistViewModelTest.cs
@@ -2,6 +2,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using Espera.Core;
 using Xunit;

 namespace Espera.View.Tests
@@ -12,7 +13,7 @@
         public void AllArtistViewModelIsSortedFirst()
         {
             var allArtists = new ArtistViewModel("All Artists");
-            var otherArtist = new ArtistViewModel("Aaa", Enumerable.Empty<IObservable<string>>());
+            var otherArtist = new ArtistViewModel("Aaa", Enumerable.Empty<LocalSong>());

             var list = new List<ArtistViewModel> { otherArtist, allArtists };
             list.Sort();
@@ -24,12 +25,12 @@
         [Fact]
         public void CertainPrefixesAreSortedCorrectly()
         {
-            var aPrefixBig = new ArtistViewModel("A b", Enumerable.Empty<IObservable<string>>());
-            var aPrefixSmall = new ArtistViewModel("a c", Enumerable.Empty<IObservable<string>>());
-            var thePrefixBig = new ArtistViewModel("The d", Enumerable.Empty<IObservable<string>>());
-            var thePrefixSmall = new ArtistViewModel("the e", Enumerable.Empty<IObservable<string>>());
-            var firstArtist = new ArtistViewModel("Aa", Enumerable.Empty<IObservable<string>>());
-            var lastArtist = new ArtistViewModel("Zz", Enumerable.Empty<IObservable<string>>());
+            var aPrefixBig = new ArtistViewModel("A b", Enumerable.Empty<LocalSong>());
+            var aPrefixSmall = new ArtistViewModel("a c", Enumerable.Empty<LocalSong>());
+            var thePrefixBig = new ArtistViewModel("The d", Enumerable.Empty<LocalSong>());
+            var thePrefixSmall = new ArtistViewModel("the e", Enumerable.Empty<LocalSong>());
+            var firstArtist = new ArtistViewModel("Aa", Enumerable.Empty<LocalSong>());
+            var lastArtist = new ArtistViewModel("Zz", Enumerable.Empty<LocalSong>());

             var correctList = new List<ArtistViewModel> { firstArtist, aPrefixBig, aPrefixSmall, thePrefixBig, thePrefixSmall, lastArtist };


Recode JsonParser so it uses an explicit IEnumerator, and keeps track of a CurrentToken combined with a ShiftToNextForegroundToken() operator.

--- Eutherion/Shared/Text/Json/JsonParser.cs
+++ Eutherion/Shared/Text/Json/JsonParser.cs
@@ -19,7 +19,6 @@
 **********************************************************************************/
 #endregion

-using Eutherion.Utils;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -33,45 +32,28 @@
     /// </summary>
     public class JsonParser : JsonSymbolVisitor<TextElement<JsonSymbol>, JsonSyntaxNode>
     {
-        private readonly ReadOnlyList<TextElement<JsonSymbol>> Tokens;
+        private readonly IEnumerator<TextElement<JsonSymbol>> Tokens;
         private readonly int SourceLength;
         private readonly List<JsonErrorInfo> Errors = new List<JsonErrorInfo>();

-        private int CurrentTokenIndex;
-
-        public JsonParser(ReadOnlyList<TextElement<JsonSymbol>> tokens, int sourceLength)
-        {
-            Tokens = tokens ?? throw new ArgumentNullException(nameof(tokens));
+        private TextElement<JsonSymbol> CurrentToken;
+
+        public JsonParser(IEnumerable<TextElement<JsonSymbol>> tokens, int sourceLength)
+        {
+            if (tokens == null) throw new ArgumentNullException(nameof(tokens));
+            Tokens = tokens.GetEnumerator();
             SourceLength = sourceLength;
-            CurrentTokenIndex = 0;
-        }
-
-        private TextElement<JsonSymbol> PeekSkipComments()
+        }
+
+        private void ShiftToNextForegroundToken()
         {
             // Skip comments until encountering something meaningful.
-            while (CurrentTokenIndex < Tokens.Count)
-            {
-                TextElement<JsonSymbol> current = Tokens[CurrentTokenIndex];
-                if (!current.TerminalSymbol.IsBackground) return current;
-                Errors.AddRange(current.TerminalSymbol.Errors);
-                CurrentTokenIndex++;
-            }
-
-            return null;
-        }
-
-        private TextElement<JsonSymbol> ReadSkipComments()
-        {
-            // Skip comments until encountering something meaningful.
-            while (CurrentTokenIndex < Tokens.Count)
-            {
-                TextElement<JsonSymbol> current = Tokens[CurrentTokenIndex];
-                Errors.AddRange(current.TerminalSymbol.Errors);
-                CurrentTokenIndex++;
-                if (!current.TerminalSymbol.IsBackground) return current;
-            }
-
-            return null;
+            do
+            {
+                CurrentToken = Tokens.MoveNext() ? Tokens.Current : null;
+                if (CurrentToken != null) Errors.AddRange(CurrentToken.TerminalSymbol.Errors);
+            }
+            while (CurrentToken != null && CurrentToken.TerminalSymbol.IsBackground);
         }

         public override JsonSyntaxNode VisitCurlyOpen(JsonCurlyOpen curlyOpen, TextElement<JsonSymbol> visitedToken)
@@ -122,7 +104,6 @@
                 }

                 // ParseMultiValue() guarantees that the next symbol is never a ValueStartSymbol.
-                TextElement<JsonSymbol> textElement = ReadSkipComments();
                 JsonSyntaxNode parsedValueNode = default(JsonSyntaxNode);

                 // If gotValue remains false, a missing value error will be reported.
@@ -130,15 +111,15 @@

                 // Loop parsing values until encountering a non ':'.
                 bool gotColon = false;
-                while (textElement != null && textElement.TerminalSymbol is JsonColon)
+                while (CurrentToken != null && CurrentToken.TerminalSymbol is JsonColon)
                 {
                     if (gotColon)
                     {
                         // Multiple ':' without a ','.
                         Errors.Add(new JsonErrorInfo(
                             JsonErrorCode.MultiplePropertyKeySections,
-                            textElement.Start,
-                            textElement.Length));
+                            CurrentToken.Start,
+                            CurrentToken.Length));
                     }

                     gotValue |= ParseMultiValue(JsonErrorCode.MultipleValues, out parsedValueNode);
@@ -149,12 +130,11 @@
                         mapBuilder.Add(new JsonMapNodeKeyValuePair(propertyKeyNode, parsedValueNode));
                     }

-                    textElement = ReadSkipComments();
                     gotColon = true;
                 }

-                bool isComma = textElement != null && textElement.TerminalSymbol is JsonComma;
-                bool isCurlyClose = textElement != null && textElement.TerminalSymbol is JsonCurlyClose;
+                bool isComma = CurrentToken != null && CurrentToken.TerminalSymbol is JsonComma;
+                bool isCurlyClose = CurrentToken != null && CurrentToken.TerminalSymbol is JsonCurlyClose;

                 // '}' directly following a ',' should not report errors.
                 // '..., : }' however misses both a key and a value.
@@ -165,16 +145,16 @@
                     {
                         Errors.Add(new JsonErrorInfo(
                             JsonErrorCode.MissingPropertyKey,
-                            textElement.Start,
-                            textElement.Length));
+                            CurrentToken.Start,
+                            CurrentToken.Length));
                     }

                     if (!gotValue)
                     {
                         Errors.Add(new JsonErrorInfo(
                             JsonErrorCode.MissingValue,
-                            textElement.Start,
-                            textElement.Length));
+                            CurrentToken.Start,
+                            CurrentToken.Length));
                     }
                 }

@@ -182,7 +162,7 @@
                 {
                     // Assume missing closing bracket '}' on EOF or control symbol.
                     int endPosition;
-                    if (textElement == null)
+                    if (CurrentToken == null)
                     {
                         Errors.Add(new JsonErrorInfo(
                             JsonErrorCode.UnexpectedEofInObject,
@@ -195,14 +175,14 @@
                     {
                         Errors.Add(new JsonErrorInfo(
                             JsonErrorCode.ControlSymbolInObject,
-                            textElement.Start,
-                            textElement.Length));
-
-                        endPosition = textElement.Start;
+                            CurrentToken.Start,
+                            CurrentToken.Length));
+
+                        endPosition = CurrentToken.Start;
                     }
                     else
                     {
-                        endPosition = textElement.End;
+                        endPosition = CurrentToken.End;
                     }

                     int start = visitedToken.Start;
@@ -223,25 +203,24 @@
                 if (gotValue) listBuilder.Add(parsedValueNode);

                 // ParseMultiValue() guarantees that the next symbol is never a ValueStartSymbol.
-                TextElement<JsonSymbol> textElement = ReadSkipComments();
-                if (textElement != null && textElement.TerminalSymbol is JsonComma)
+                if (CurrentToken != null && CurrentToken.TerminalSymbol is JsonComma)
                 {
                     if (!gotValue)
                     {
                         // Two commas or '[,': add an empty JsonUndefinedValueSyntax.
                         Errors.Add(new JsonErrorInfo(
                             JsonErrorCode.MissingValue,
-                            textElement.Start,
-                            textElement.Length));
-
-                        listBuilder.Add(new JsonMissingValueSyntax(textElement.Start));
+                            CurrentToken.Start,
+                            CurrentToken.Length));
+
+                        listBuilder.Add(new JsonMissingValueSyntax(CurrentToken.Start));
                     }
                 }
                 else
                 {
                     // Assume missing closing bracket ']' on EOF or control symbol.
                     int endPosition;
-                    if (textElement == null)
+                    if (CurrentToken == null)
                     {
                         Errors.Add(new JsonErrorInfo(
                             JsonErrorCode.UnexpectedEofInArray,
@@ -250,18 +229,18 @@

                         endPosition = SourceLength;
                     }
-                    else if (!(textElement.TerminalSymbol is JsonSquareBracketClose))
+                    else if (!(CurrentToken.TerminalSymbol is JsonSquareBracketClose))
                     {
                         Errors.Add(new JsonErrorInfo(
                             JsonErrorCode.ControlSymbolInArray,
-                            textElement.Start,
-                            textElement.Length));
-
-                        endPosition = textElement.Start;
+                            CurrentToken.Start,
+                            CurrentToken.Length));
+
+                        endPosition = CurrentToken.Start;
                     }
                     else
                     {
-                        endPosition = textElement.End;
+                        endPosition = CurrentToken.End;
                     }

                     int start = visitedToken.Start;
@@ -299,39 +278,39 @@
         {
             firstValueNode = default(JsonSyntaxNode);

-            TextElement<JsonSymbol> textElement = PeekSkipComments();
-            if (textElement == null || !textElement.TerminalSymbol.IsValueStartSymbol) return false;
+            ShiftToNextForegroundToken();
+            if (CurrentToken == null || !CurrentToken.TerminalSymbol.IsValueStartSymbol) return false;

             bool hasValue = false;

             for (; ; )
             {
-                // Read the same symbol again but now eat it.
-                textElement = ReadSkipComments();
-
                 if (!hasValue)
                 {
-                    if (textElement.TerminalSymbol.Errors.Any()) firstValueNode = new JsonUndefinedValueSyntax(textElement);
-                    else firstValueNode = Visit(textElement.TerminalSymbol, textElement);
+                    if (CurrentToken.TerminalSymbol.Errors.Any()) firstValueNode = new JsonUndefinedValueSyntax(CurrentToken);
+                    else firstValueNode = Visit(CurrentToken.TerminalSymbol, CurrentToken);
                     hasValue = true;
                 }
-                else if (!textElement.TerminalSymbol.Errors.Any())
+                else if (!CurrentToken.TerminalSymbol.Errors.Any())
                 {
                     // Make sure consecutive symbols are parsed as if they were valid.
                     // Discard the result.
-                    Visit(textElement.TerminalSymbol, textElement);
-                }
-
-                // Peek at the next symbol.
+                    Visit(CurrentToken.TerminalSymbol, CurrentToken);
+                }
+
+                // CurrentToken may be null, e.g. unterminated objects or arrays.
+                if (CurrentToken == null) return true;
+
+                // Move to the next symbol.
                 // If IsValueStartSymbol == false in the first iteration, it means that exactly one value was parsed, as desired.
-                textElement = PeekSkipComments();
-                if (textElement == null || !textElement.TerminalSymbol.IsValueStartSymbol) return true;
+                ShiftToNextForegroundToken();
+                if (CurrentToken == null || !CurrentToken.TerminalSymbol.IsValueStartSymbol) return true;

                 // Two or more consecutive values not allowed.
                 Errors.Add(new JsonErrorInfo(
                     multipleValuesErrorCode,
-                    textElement.Start,
-                    textElement.Length));
+                    CurrentToken.Start,
+                    CurrentToken.Length));
             }
         }

@@ -339,13 +318,12 @@
         {
             bool hasRootValue = ParseMultiValue(JsonErrorCode.ExpectedEof, out rootNode);

-            TextElement<JsonSymbol> extraElement = ReadSkipComments();
-            if (extraElement != null)
+            if (CurrentToken != null)
             {
                 Errors.Add(new JsonErrorInfo(
                     JsonErrorCode.ExpectedEof,
-                    extraElement.Start,
-                    extraElement.Length));
+                    CurrentToken.Start,
+                    CurrentToken.Length));
             }

             errors = Errors;


Corrected Date.CompareTo(Object) and added Math.E and Math.PI as constants to the translator.

--- ExoWeb/JavaScriptExpressionTranslator.cs
+++ ExoWeb/JavaScriptExpressionTranslator.cs
@@ -107,8 +107,8 @@
 			{ "Date.AddSeconds(Number) as Date", new string[] {@"new Date({0}.getTime() + {1}*1000)", "", @""} },
 			{ "Date.AddTicks(Number) as Date", new string[] {@"new Date({0}.getTime() + {1}/10000)", "", @""} },
 			{ "Date.AddYears(Number) as Date", new string[] {@"Date_addYears({0}, {1})", "Date_addYears", @"function (d, y) { var r = new Date(d.getTime()); r.setFullYear(r.getFullYear() + y); return r; }"} },
-			{ "Date.CompareTo(Date) as Number", new string[] {@"Date.compareTo({0}, {1})", "", @""} },
-			{ "Date.CompareTo(Object) as Number", new string[] {@"Date.compareTo({0}, {1})", "", @""} },
+			{ "Date.CompareTo(Date) as Number", new string[] {@"{0}.getTime()=={1}.getTime() ? 0 : ({0}.getTime()>{1}.getTime() ? 1 : -1)", "", @""} },
+			{ "Date.CompareTo(Object) as Number", new string[] {@"{0}.getTime()=={1}.getTime() ? 0 : ({0}.getTime()>{1}.getTime() ? 1 : -1)", "", @""} },
 			{ "Date.Date as Date", new string[] {@"Date_date({0})", "Date_date", @"function Date_date(d) { return new Date(d.getFullYear(), d.getMonth(), d.getDate()); }"} },
 			{ "Date.Day as Number", new string[] {@"{0}.getDate()", "", @""} },
 			{ "Date.DayOfWeek as DayOfWeek", new string[] {@"[""Sunday"", ""Monday"", ""Tuesday"", ""Wednesday"", ""Thursday"", ""Friday"", ""Saturday""][{0}.getDay()]", "", @""} },
@@ -143,6 +143,7 @@
 			{ "static Math.Ceiling(Number) as Number", new string[] {@"Math.ceil({0})", "", @""} },
 			{ "static Math.Cos(Number) as Number", new string[] {@"Math.cos({0})", "", @""} },
 			{ "static Math.Cosh(Number) as Number", new string[] {@"Math_cosh({0})", "Math_cosh", @"function(n) { return (Math.exp(n) + Math.exp(-(n)))/2; }"} },
+			{ "static Math.E as Number", new string[] {@"Math.E", "", @""} },
 			{ "static Math.Exp(Number) as Number", new string[] {@"Math.exp({0})", "", @""} },
 			{ "static Math.Floor(Number) as Number", new string[] {@"Math.floor({0})", "", @""} },
 			{ "static Math.Log(Number) as Number", new string[] {@"Math.log({0})", "", @""} },
@@ -150,6 +151,7 @@
 			{ "static Math.Log10(Number) as Number", new string[] {@"Math.log({0})/Math.log(10)", "", @""} },
 			{ "static Math.Max(Number, Number) as Number", new string[] {@"Math.max({0}, {1})", "", @""} },
 			{ "static Math.Min(Number, Number) as Number", new string[] {@"Math.min({0}, {1})", "", @""} },
+			{ "static Math.PI as Number", new string[] {@"Math.PI", "", @""} },
 			{ "static Math.Pow(Number, Number) as Number", new string[] {@"Math.pow({0}, {1})", "", @""} },
 			{ "static Math.Round(Number) as Number", new string[] {@"Math.round({0})", "", @""} },
 			{ "static Math.Round(Number, Number) as Number", new string[] {@"Math.round({0}*Math.pow(10, {1}))/Math.pow(10, {1})", "", @""} },
@@ -510,7 +512,7 @@
 			{
 				var field = member as FieldInfo;
 				if (IsSupported(field.FieldType))
-					return GetTypeName(field.DeclaringType) + "." + field.Name + " as " + GetTypeName(field.FieldType);
+					return (field.IsStatic ? "static " : "") + GetTypeName(field.DeclaringType) + "." + field.Name + " as " + GetTypeName(field.FieldType);
 			}

 			// Property


Icon names must not been changed so make them readonly

--- src/AppKit/Enums.cs
+++ src/AppKit/Enums.cs
@@ -1477,9 +1477,9 @@
 	}

 	public static class NSFileTypeForHFSTypeCode {
-		public static string ComputerIcon = "root";
-		public static string DesktopIcon = "desk";
-		public static string FinderIcon = "FNDR";
+		public static readonly string ComputerIcon = "root";
+		public static readonly string DesktopIcon = "desk";
+		public static readonly string FinderIcon = "FNDR";
 	}

 	// These constants specify the possible states of a drawer.


update so it compiles

update so it compiles

--- APETest/APETest/APE.Test.cs
+++ APETest/APETest/APE.Test.cs
@@ -22,6 +22,7 @@
 using System.Drawing;
 using APE.Language;
 using APE.Capture;
+using System.Text.RegularExpressions;

 namespace APE.Test
 {
@@ -30,7 +31,7 @@
         public Form1()
         {
             InitializeComponent();
-            GUI.Log("Starting", LogItemTypeEnum.ApeContext);
+            GUI.Log("Starting", LogItemType.Information);
         }

         private void button1_Click(object sender, EventArgs e)  //Sentinel
@@ -56,7 +57,7 @@
             }

             //start sentinel
-            GUI.Log("Launch Sentinel", LogItemTypeEnum.Action);
+            GUI.Log("Launch Sentinel", LogItemType.Action);
             ProcessStartInfo SentinelStartup = new ProcessStartInfo();
             SentinelStartup.WorkingDirectory = @"C:\Program Files (x86)\LatentZero\LZ Sentinel\Client\";
             SentinelStartup.FileName = @"LzSentinel.exe";
@@ -81,10 +82,10 @@
             UserId.SetText("autosen");
             Password.SetText("quality");

-            OK.MouseSingleClick(MouseButton.Left);
+            OK.SingleClick(MouseButton.Left);

             //find main sentinel window and the status bar
-            GUI.Log("Wait for Sentinel to load", LogItemTypeEnum.Information);
+            GUI.Log("Wait for Sentinel to load", LogItemType.Information);
             GUIForm Sentinel = new GUIForm("sentinel form", new Identifier(Identifiers.Name, "CapstoneContainer"));
             GUIStatusBar SentinelStatusBar = new GUIStatusBar(Sentinel, "sentiinel form status strip", new Identifier(Identifiers.Name, "statusBar"));

@@ -121,25 +122,26 @@
             GUIDocumentContainer DocumentContainer = new GUIDocumentContainer(Sentinel, "panel tab", new Identifier(Identifiers.Name, ""), new Identifier(Identifiers.TypeNameSpace, "TD.SandDock"), new Identifier(Identifiers.TypeName, "DocumentContainer"));

             bool Exists = DocumentContainer.ItemExists("Sentinel Today");
-            int Count = DocumentContainer.ItemCount();
-            DocumentContainer.ItemSelect("Pre-trade");
-            DocumentContainer.ItemSelect("Rule Maintenance");
-            DocumentContainer.ItemSelect("Sentinel Today");
-            DocumentContainer.ItemRemove("Pre-trade");
+            int Count = DocumentContainer.ItemsCount();
+            DocumentContainer.SingleClickItem("Pre-trade");
+            DocumentContainer.SingleClickItem("Rule Maintenance");
+            DocumentContainer.SingleClickItem("Sentinel Today");
+            DocumentContainer.RemoveItem("Pre-trade");

             //Add a panel
-            int InitialItems = DocumentContainer.ItemCount();
+            int InitialItems = DocumentContainer.ItemsCount();
             int CurrentItems = 0;
-            MenuStrip.Select(@"&Panels\Pre-trade");
+            GUIToolStripMenu panelsMenu = MenuStrip.GetMenu("panels menu", new Identifier(Identifiers.Name, "PanelsMenu"));
+            panelsMenu.SingleClickItem(@"Pre-trade");

             do
             {
                 Thread.Sleep(50);

-                CurrentItems = DocumentContainer.ItemCount();
+                CurrentItems = DocumentContainer.ItemsCount();
             } while (CurrentItems != InitialItems + 1);

-            DocumentContainer.ItemSelect("Sentinel Today");
+            DocumentContainer.SingleClickItem("Sentinel Today");

@@ -178,7 +180,7 @@

-            layoutGrid.Select(group + " -> " + layout, layoutGrid.FirstVisibleColumn(), MouseButton.Left, CellClickLocation.CentreOfCell);
+            layoutGrid.SingleClickCell(group + " -> " + layout, layoutGrid.FirstVisibleColumn(), MouseButton.Left, CellClickLocation.CentreOfCell);

             timer = Stopwatch.StartNew();
             do
@@ -250,17 +252,94 @@
             GUI.AttachToProcess(p);
             GUI.SetTimeOut(5000);

+
+
+
+
+            GUIForm quote = new GUIForm("q", new Identifier(Identifiers.Name, "frmSingleQuote"));
+
+            GUIFlexgrid grid = new GUIFlexgrid(quote, "grid", new Identifier(Identifiers.Name, "fgGrid"));
+            grid.SetCellValue(1, "Counterparty", "ABN Amro");
+
+
+
+            bool exists = GUI.Exists(new Identifier(Identifiers.Name, "CapstoneContainer"));

-            GUIForm exe = new GUIForm("rel", new Identifier(Identifiers.Name, "frmSingleExecution"));
-            GUIFlexgrid grid = new GUIFlexgrid(exe, "grid", new Identifier(Identifiers.Name, "fgAmendGrid"));
-
-            string text = grid.GetAllVisibleCells(CellProperty.TextDisplay);
-
-            grid.WaitForControlToNotBeVisible();
+
+            GUIForm im = new GUIForm("im", new Identifier(Identifiers.Name, "SimpleContainer"));
+
+            GUIElementStripGrid amend = new GUIElementStripGrid(im, "amend", new Identifier(Identifiers.Name, "m_elementStripGrid"), new Identifier(Identifiers.Index, 3));
+            amend.SetCellValue(amend.Rows() - 1, "Chinese CORP BOND 2 -> Order -> Qty", "3,000.000");
+
+
+
+            //GUIDockableWindow dw = new GUIDockableWindow(im, "dw", new Identifier(Identifiers.Text, @"^Orders\ \[Count:\ 673]\[Link:]$"), new Identifier(Identifiers.TypeName, "DockableWindow"));
+
+            //GUIElementStripGrid og = new GUIElementStripGrid(im, "og", new Identifier(Identifiers.Name, "m_elementStripGrid"), new Identifier(Identifiers.ChildOf, dw));
+
+            //Thread.Sleep(3000);
+
+            //int sel = og.SelectedRow();
+            //og.SelectedRowPollForIndex(sel - 1);
+
+
+            //Thread.Sleep(5000);
+
+            GUIForm Form = new GUIForm(im, "quick execution form", new Identifier(Identifiers.Name, "frmQuickExecute"));
+            GUIFlexgrid AddGrid = new GUIFlexgrid(Form, "quick execution grid", new Identifier(Identifiers.Name, "fgAddGrid"));
+            //AddGrid.GetCell
+
+
+            AddGrid.ShowCell(1, 36);
+            AddGrid.ShowCell(1, 36);
+
+
+            AddGrid.SetCellValue(1, "Clearing Counterparty", "Cazenove");
+            AddGrid.SetCellValue(1, "Price", "123");
+
+            GUIForm rel = new GUIForm("rel", new Identifier(Identifiers.Name, "frmSingleRelease"));
+            ////GUILzNavBarGridControl c = new GUILzNavBarGridControl(rel, "c", new Identifier(Identifiers.Name, "Counterparties"));
+            //GUIFlexgrid grid = new GUIFlexgrid(rel, "grdi", new Identifier(Identifiers.Name, "fgData"));
+
+            ////Rectangle r = grid.GetCellRectangle(grid.FindRow("Global Balanced Fund 7", "Account Name"), grid.FindColumn("Account Name"));
+
+            //this.Focus()
+
+            GUIComboBox cp = new GUIComboBox(rel, "cp", new Identifier(Identifiers.Name, "cboCpties"));
+            cp.SingleClickItem("dodo");
+
+            //string ook = grid.GetCellValue(5, 0, CellProperty.RowUserDataNodeCaption);
+            Stopwatch ook = Stopwatch.StartNew();
+            //c.Select("JP Morgan", MouseButton.Left, CellClickLocation.CentreOfCell);
+            Debug.WriteLine(ook.ElapsedMilliseconds.ToString());
+            GUIForm merge = new GUIForm("merge", new Identifier(Identifiers.Name, "frmMerge"));
+
+
+            GUIButton mergeandclose = new GUIButton(merge, "m & c", new Identifier(Identifiers.Text, @"Merge\ Orders\ and\ Close"), new Identifier(Identifiers.TypeName, "Button"));
+            GUIStretchyCombo type = new GUIStretchyCombo(merge, "xxx", new Identifier(Identifiers.Name, "cmbShow"));
+            type.SingleClickItem("Executions");
+
+            Debug.WriteLine("");
+            //GUIForm exe = new GUIForm("rel", new Identifier(Identifiers.Name, "frmSingleExecution"));
+
+
+            //GUITabControl tab = new GUITabControl(exe, "tab", new Identifier(Identifiers.Name, "sftViews"));
+
+            //tab.Select("Summary");
+            //tab.Select("Carnegie 2,500 @ 128");
+            //tab.Select("ABN Amro 2,500 @ 128");
+
+            //GUILabel nativeLabel = new GUILabel(exe, "message box label", new Identifier(Identifiers.Text, @"No unfilled release(s) found, do you want to continue\?"), new Identifier(Identifiers.TechnologyType, "Windows Native"));
+
+            //GUIFlexgrid grid = new GUIFlexgrid(exe, "grid", new Identifier(Identifiers.Name, "fgAmendGrid"));
+
+            //string text = grid.GetAllVisibleCells(CellProperty.TextDisplay);
+
+            //grid.WaitForControlToNotBeVisible();

             //GUIForm asa = new GUIForm("aas", new Identifier(Identifiers.Name, "SimpleContainer"));
             //GUIElementStripGrid grid = new GUIElementStripGrid(asa, "GridColumnStylesCollection", new Identifier(Identifiers.Name, "m_elementStripGrid"), new Identifier(Identifiers.Index, 3));
-
+
             ////GUIForm exec = new GUIForm("exec", new Identifier(Identifiers.Name, "frmSingleExecution"));
             ////GUIFlexgrid execGrid = new GUIFlexgrid(exec, "grid", new Identifier(Identifiers.Name, "fgAllocations"));

@@ -488,7 +567,7 @@
             //    image.Save(@"C:\oooooooook.bmp");
             //}

-            Debug.WriteLine("");
+            //Debug.WriteLine("");

             //text = st.GetCellValue(0, col, GUIFlexgrid.CellProperty.Clip);
             //Debug.WriteLine("add row 0 CB = " + text);
@@ -969,7 +1048,7 @@
             log.Close();
         }

-        private void Log(string textToLog, LogItemTypeEnum type)
+        private void Log(string textToLog, LogItemType type)
         {
             WriteToFile(textToLog);
         }
@@ -1016,7 +1095,7 @@
                     }

                     //start
-                    GUI.Log("Launch TestApplication", LogItemTypeEnum.Action);
+                    GUI.Log("Launch TestApplication", LogItemType.Action);

                     ProcessStartInfo AppStartup = new ProcessStartInfo();
                     //AppStartup.WorkingDirectory = @"C:\Tools\TestApplication\TestApplication\bin\Debug\";
@@ -1043,7 +1122,8 @@
                     tbxContext.SetText("moo");

                     GUIMenuStrip MenuStrip = new GUIMenuStrip(TestApplication, "menu strip", new Identifier(Identifiers.TypeName, "MenuStrip"));
-                    MenuStrip.Select(@"Second\OpensPopup");
+                    GUIToolStripMenu secondMenu = MenuStrip.GetMenu("second", new Identifier(Identifiers.Name, "secondToolStripMenuItem"));
+                    secondMenu.SingleClickItem(@"OpensPopup");

                     GUIForm CustomMessageBox = new GUIForm("messagebox form", new Identifier(Identifiers.Name, "frmCustomMessageBox"));
                     CustomMessageBox.Maximise();
@@ -1057,12 +1137,12 @@
                     CustomMessageBox.Close();

                     GUITabControl tab1 = new GUITabControl(TestApplication, "tab control", new Identifier(Identifiers.Name, "tabControl1"));
-                    tab1.Select("tabPage3");
-                    tab1.Select("tabPage1");
+                    tab1.SingleClickTab("tabPage3");
+                    tab1.SingleClickTab("tabPage1");

                     GUITabControl tab2 = new GUITabControl(TestApplication, "tab control", new Identifier(Identifiers.Name, "tabControl2"));
-                    tab2.Select("tabPage4");
-                    tab2.Select("tabPage7");
+                    tab2.SingleClickTab("tabPage4");
+                    tab2.SingleClickTab("tabPage7");

                     GUIStatusStrip ssStatusBar = new GUIStatusStrip(TestApplication, "status strip", new Identifier(Identifiers.Name, "StatusStrip"));

@@ -1078,7 +1158,7 @@
                     //PanelText = ssStatusBar.PanelText(PanelIndex);
                     //PanelText = ssStatusBar.PanelText("toolStripStatusLabel5");

-                    btnStatusBar.MouseSingleClick(MouseButton.Left);
+                    btnStatusBar.SingleClick(MouseButton.Left);
                     statusBarFirstPanel.PollForText("6");
                     statusBarFirstPanel.PollForText("");
                     Stopwatch doo = Stopwatch.StartNew();
@@ -1091,7 +1171,7 @@

                     //bring up the context menu of the textbox and select the menu item
                     //TODO make this a single command??
-                    tbxContext.MouseSingleClick(MouseButton.Right);
+                    tbxContext.SingleClick(MouseButton.Right);
                     tbxContext.ContextMenuSelect(@"ConItem2\ConSubItem2");

                     CustomMessageBox = new GUIForm("messagebox form", new Identifier(Identifiers.Name, "frmCustomMessageBox"));
@@ -1101,53 +1181,53 @@
                     string labelText = EditBoxLabel.Text;

                     GUICheckBox MyCheckBox = new GUICheckBox(TestApplication, "checkbox1 checkbox", new Identifier(Identifiers.Name, "checkBox1"));
-                    MyCheckBox.MouseSingleClick(MouseButton.Left);
+                    MyCheckBox.SingleClick(MouseButton.Left);

                     GUIRadioButton MyRadioButton = new GUIRadioButton(TestApplication, "radioButton1 radio button", new Identifier(Identifiers.Name, "radioButton1"));
-                    MyRadioButton.MouseSingleClick(MouseButton.Left);
+                    MyRadioButton.SingleClick(MouseButton.Left);

                     GUIComboBox MyComboBox1 = new GUIComboBox(TestApplication, "top left combobox", new Identifier(Identifiers.Name, "comboBox1"));
                     MyComboBox1.SetText("foo");
                     MyComboBox1.SetText("bar");
-                    MyComboBox1.ItemSelect("Test31");
+                    MyComboBox1.SingleClickItem("Test31");

                     GUIComboBox MyComboBox2 = new GUIComboBox(TestApplication, "bottom left combobox", new Identifier(Identifiers.Name, "comboBox2"));
-                    MyComboBox2.ItemSelect("Test40");
+                    MyComboBox2.SingleClickItem("Test40");

                     GUIComboBox MyComboBox3 = new GUIComboBox(TestApplication, "top right combobox", new Identifier(Identifiers.Name, "comboBox3"));
-                    MyComboBox3.ItemSelect("Test50");
+                    MyComboBox3.SingleClickItem("Test50");

                     MyComboBox3 = new GUIComboBox(TestApplication, "top right combobox", new Identifier(Identifiers.Name, "comboBox3"));
-                    MyComboBox3.ItemSelect("Test25");
+                    MyComboBox3.SingleClickItem("Test25");

                     GUIListBox MyListBox = new GUIListBox(TestApplication, "bottom right listbox", new Identifier(Identifiers.Name, "listBox1"));
-                    MyListBox.ItemSelect("Test25");
+                    MyListBox.SingleClickItem("Test25");

                     GUITreeView MyTreeView1 = new GUITreeView(TestApplication, "top left treeview", new Identifier(Identifiers.Name, "treeView1"));
-                    MyTreeView1.Select(@"Node6\Node9\Node10");
+                    MyTreeView1.SingleClickItem(@"Node6\Node9\Node10");

                     GUITreeView MyTreeView2 = new GUITreeView(TestApplication, "bottom left treeview", new Identifier(Identifiers.Name, "treeView2"));
-                    MyTreeView2.Select(@"Node1\Node4\Node9");
+                    MyTreeView2.SingleClickItem(@"Node1\Node4\Node9");

                     GUITreeView MyTreeView3 = new GUITreeView(TestApplication, "top right treeview", new Identifier(Identifiers.Name, "treeView3"));
-                    MyTreeView3.Select(@"Node1\Node2\Node4444444444444444444444444444444444444444444444\Node5");
-                    MyTreeView3.Select(@"Node1\Node2\Node4444444444444444444444444444444444444444444444");
-                    MyTreeView3.Select(@"Node1\Node2\Node4444444444444444444444444444444444444444444444\Node5");
-                    MyTreeView3.Select(@"Node1\Node2\Node4444444444444444444444444444444444444444444444");
-                    MyTreeView3.Select(@"Node1\Node2\Node4444444444444444444444444444444444444444444444\Node5");
-                    MyTreeView3.Check(@"Node1\Node2\Node4444444444444444444444444444444444444444444444\Node5");
-                    MyTreeView3.Check(@"Node1\Node3");
-                    MyTreeView3.Check(@"Node1\Node2\Node4444444444444444444444444444444444444444444444");
+                    MyTreeView3.SingleClickItem(@"Node1\Node2\Node4444444444444444444444444444444444444444444444\Node5");
+                    MyTreeView3.SingleClickItem(@"Node1\Node2\Node4444444444444444444444444444444444444444444444");
+                    MyTreeView3.SingleClickItem(@"Node1\Node2\Node4444444444444444444444444444444444444444444444\Node5");
+                    MyTreeView3.SingleClickItem(@"Node1\Node2\Node4444444444444444444444444444444444444444444444");
+                    MyTreeView3.SingleClickItem(@"Node1\Node2\Node4444444444444444444444444444444444444444444444\Node5");
+                    MyTreeView3.CheckItem(@"Node1\Node2\Node4444444444444444444444444444444444444444444444\Node5");
+                    MyTreeView3.CheckItem(@"Node1\Node3");
+                    MyTreeView3.CheckItem(@"Node1\Node2\Node4444444444444444444444444444444444444444444444");

                     GUIListView MyListView1 = new GUIListView(TestApplication, "bottom left listview", new Identifier(Identifiers.Name, "listView1"));
-                    MyListView1.SelectGroup("Test Group");
-                    MyListView1.SelectGroup("<Default>");
-                    MyListView1.Select("ook5");
-                    MyListView1.Select("Test Group", "B9");
-                    MyListView1.Select("<Default>", "A6");
-
+                    MyListView1.SingleClickGroup("Test Group");
+                    MyListView1.SingleClickGroup("<Default>");
+                    MyListView1.SingleClickItem("ook5");
+                    MyListView1.SingleClickItem("Test Group", "B9");
+                    MyListView1.SingleClickItem("<Default>", "A6");
+
                     GUIListView MyListView2 = new GUIListView(TestApplication, "bottom right listview", new Identifier(Identifiers.Name, "listView2"));
-                    MyListView2.Select("9");
+                    MyListView2.SingleClickItem("9");

                     //GUI.SetTimeOuts(0);
                     //try
@@ -1182,7 +1262,17 @@

         private void btnSpamLog_Click(object sender, EventArgs e)
         {
-            GUI.Log("This is a Test!", LogItemTypeEnum.ApeContext);
+            GUI.Log("This is a Test Action!", LogItemType.Action);
+            GUI.Log("This is a Test Debug!", LogItemType.Debug);
+            GUI.Log("This is a Test Error!", LogItemType.Error);
+            GUI.Log("This is a Test Fail!", LogItemType.Fail);
+            GUI.Log("This is a Test Finish!", LogItemType.Finish);
+            GUI.Log("This is a Test Information!", LogItemType.Information);
+            GUI.Log("This is a Test Pass!", LogItemType.Pass);
+            GUI.Log("This is a Test Start!", LogItemType.Start);
+            GUI.Log("This is a Test Warning!", LogItemType.Warning);
+            GUI.Log("This is a Test Disabled!", LogItemType.Disabled);
+            GUI.Log("This is a Test NA!", LogItemType.NA);
         }

         private void button4_Click(object sender, EventArgs e)
@@ -1209,7 +1299,7 @@
                 }

                 //start
-                GUI.Log("Launch TestApplication", LogItemTypeEnum.Action);
+                GUI.Log("Launch TestApplication", LogItemType.Action);

                 ProcessStartInfo AppStartup = new ProcessStartInfo();
                 AppStartup.WorkingDirectory = @"C:\Tools\TestApplication\TestApplication\bin\Debug\";


bugfix

bugfix

--- AppMetrics/LogEvent.ashx.cs
+++ AppMetrics/LogEvent.ashx.cs
@@ -42,21 +42,12 @@
 				var filePath = GetDataFilePath(applicationKey, sessionId);
 				var fileExisted = File.Exists(filePath);

-				using (var writer = new StreamWriter(filePath, true, Encoding.UTF8))
+				using (var stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read))
 				{
-					var name = context.Request.Params["MessageName"];
-					var data = context.Request.Params["MessageData"];
-					var clientTime = context.Request.Params["MessageTime"];
-
-					if (!fileExisted)
+					using (var writer = new StreamWriter(stream, Encoding.UTF8))
 					{
-						writer.WriteLine("{0}\t{1}\t{2}", clientTime, "ClientIP", context.Request.UserHostAddress);
-						writer.WriteLine("{0}\t{1}\t{2}", clientTime, "ClientHostName", context.Request.UserHostName);
-						writer.WriteLine("{0}\t{1}\t{2}", clientTime, "ClientUserAgent", context.Request.UserAgent);
+						WriteData(writer, context, fileExisted);
 					}
-
-					data = Util.Escape(data);
-					writer.WriteLine("{0}\t{1}\t{2}", clientTime, name, data);
 				}
 			}
 			catch (Exception exc)
@@ -66,6 +57,23 @@
 				context.Response.Write(exc);
 #endif
 			}
+		}
+
+		private static void WriteData(StreamWriter writer, HttpContext context, bool fileExisted)
+		{
+			var name = context.Request.Params["MessageName"];
+			var data = context.Request.Params["MessageData"];
+			var clientTime = context.Request.Params["MessageTime"];
+
+			if (!fileExisted)
+			{
+				writer.WriteLine("{0}\t{1}\t{2}", clientTime, "ClientIP", context.Request.UserHostAddress);
+				writer.WriteLine("{0}\t{1}\t{2}", clientTime, "ClientHostName", context.Request.UserHostName);
+				writer.WriteLine("{0}\t{1}\t{2}", clientTime, "ClientUserAgent", context.Request.UserAgent);
+			}
+
+			data = Util.Escape(data);
+			writer.WriteLine("{0}\t{1}\t{2}", clientTime, name, data);
 		}

 		private static string GetDataFilePath(string applicationKey, string sessionId)


(ReadIndexV2): use Binary.GetCString instead of ArcView.ReadString.

temporary buffer allocation within ArcView.ReadString makes reading of
large indices (20000+ entries) somewhat slow.

--- ArcFormats/Escude/ArcBIN.cs
+++ ArcFormats/Escude/ArcBIN.cs
@@ -103,14 +103,21 @@
             var index = m_file.View.ReadBytes (0x14, index_size);
             if (index.Length != index_size)
                 return null;
+            uint filenames_base = 0x14 + index_size;
+            var names = m_file.View.ReadBytes (filenames_base, names_size);
+            if (names.Length != names_size)
+                return null;
             Decrypt (index);
             int index_offset = 0;
-            uint filenames_base = 0x14 + index_size;
             var dir = new List<Entry> ((int)m_count);
             for (uint i = 0; i < m_count; ++i)
             {
-                uint filename_offset = LittleEndian.ToUInt32 (index, index_offset);
-                var name = m_file.View.ReadString (filenames_base+filename_offset, names_size-filename_offset);
+                int filename_offset = LittleEndian.ToInt32 (index, index_offset);
+                if (filename_offset < 0 || filename_offset >= names.Length)
+                    return null;
+                var name = Binary.GetCString (names, filename_offset, names.Length-filename_offset);
+                if (0 == name.Length)
+                    return null;
                 var entry = FormatCatalog.Instance.Create<Entry> (name);
                 entry.Offset = LittleEndian.ToUInt32 (index, index_offset+4);
                 entry.Size   = LittleEndian.ToUInt32 (index, index_offset+8);


(WIP): added "wi0" extension.

(WIP): added "wi0" extension.

--- ArcFormats/Will/ImageWIP.cs
+++ ArcFormats/Will/ImageWIP.cs
@@ -48,7 +48,7 @@

         public WipFormat ()
         {
-            Extensions = new string[] { "wip", "msk", "mos" };
+            Extensions = new string[] { "wip", "wi0", "msk", "mos" };
         }

         public bool ApplyMask = false;


completed CompressedMesh

completed CompressedMesh

--- AssetStudio/Classes/Mesh.cs
+++ AssetStudio/Classes/Mesh.cs
@@ -955,7 +955,7 @@
                         var m_FloatColors = new PackedFloatVector(reader);
                         if (m_FloatColors.m_NumItems > 0)
                         {
-                            throw new NotImplementedException();
+                            m_Colors = m_FloatColors.UnpackFloats(1, 4);
                         }
                     }
                     #endregion
@@ -1039,7 +1039,14 @@
                         var m_Colors_Packed = new PackedIntVector(reader);
                         if (m_Colors_Packed.m_NumItems > 0)
                         {
-                            throw new NotImplementedException();
+                            m_Colors_Packed.m_NumItems *= 4;
+                            m_Colors_Packed.m_BitSize /= 4;
+                            var tempColors = m_Colors_Packed.UnpackInts();
+                            m_Colors = new float[m_Colors_Packed.m_NumItems];
+                            for (int v = 0; v < m_Colors_Packed.m_NumItems; v++)
+                            {
+                                m_Colors[v] = tempColors[v] / 255f;
+                            }
                         }
                     }
                     else


Fix Collapse

Fix Collapse

--- Assets/BioBricksCollapse.cs
+++ Assets/BioBricksCollapse.cs
@@ -21,14 +21,6 @@

         _craftDeviceSlot = this.gameObject.GetComponent<CraftDeviceSlot>();
     }
-
-	// Update is called once per frame
-	void Update () {
-	    if (Input.GetKeyDown(KeyCode.Keypad0))
-        {
-            Collapse();
-        }
-	}

     public void Collapse()
     {


use proper start/stop ordering of workers inside core daemon

--- BitSharp.Core/CoreDaemon.cs
+++ BitSharp.Core/CoreDaemon.cs
@@ -67,11 +67,11 @@
                 this, this.storageManager, this.chainStateWorker);

             this.defragWorker = new DefragWorker(
-                new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMinutes(5), maxIdleTime: TimeSpan.FromMinutes(5)),
+                new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMinutes(1), maxIdleTime: TimeSpan.FromMinutes(5)),
                 this.storageManager);

             this.gcWorker = new WorkerMethod("GC Worker", GcWorker,
-                initialNotify: true, minIdleTime: TimeSpan.FromSeconds(30), maxIdleTime: TimeSpan.FromSeconds(30));
+                initialNotify: true, minIdleTime: TimeSpan.FromSeconds(30), maxIdleTime: TimeSpan.FromMinutes(5));

             this.utxoScanWorker = new WorkerMethod("UTXO Scan Worker", UtxoScanWorker,
                 initialNotify: true, minIdleTime: TimeSpan.FromSeconds(60), maxIdleTime: TimeSpan.FromSeconds(60));
@@ -170,23 +170,23 @@
         public void Start()
         {
             // startup workers
+            //this.utxoScanWorker.Start();
+            this.gcWorker.Start();
             this.targetChainWorker.Start();
             this.chainStateWorker.Start();
             this.pruningWorker.Start();
             this.defragWorker.Start();
-            this.gcWorker.Start();
-            //this.utxoScanWorker.Start();
         }

         public void Stop()
         {
             // stop workers
+            this.defragWorker.Stop();
+            this.pruningWorker.Stop();
             this.chainStateWorker.Stop();
+            this.targetChainWorker.Stop();
+            this.gcWorker.Stop();
             this.utxoScanWorker.Stop();
-            this.pruningWorker.Stop();
-            this.targetChainWorker.Stop();
-            this.defragWorker.Stop();
-            this.gcWorker.Stop();
         }

         public void WaitForUpdate()


Validate alerts with CC to have also owner * Emails always need someon on To line

--- BugReport/Reports/Config.cs
+++ BugReport/Reports/Config.cs
@@ -5,6 +5,7 @@
 using System.Xml.Linq;
 using BugReport.Query;
 using BugReport.DataModel;
+using BugReport.Util;

 namespace BugReport.Reports
 {
@@ -178,6 +179,11 @@

                         IEnumerable<Alert.User> owners = alertNode.Descendants("owner").Select(e => FindUserOrThrow(e.Value));
                         IEnumerable<Alert.User> ccUsers = alertNode.Descendants("cc").Select(e => FindUserOrThrow(e.Value));
+
+                        if (ccUsers.Any() && owners.None())
+                        {
+                            throw new InvalidDataException($"Missing owner in alert '{alertName}'");
+                        }

                         Alert alert;
                         try


Added failing test for attaching a NEW object graph root

--- GraphDiff/GraphDiff.Tests/Tests/Tests.cs
+++ GraphDiff/GraphDiff.Tests/Tests/Tests.cs
@@ -1,13 +1,13 @@
 using System;
-using System.Text;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data.Entity;
+using System.Data.Entity.Infrastructure;
 using System.Linq;
+using System.Linq.Expressions;
+using System.Transactions;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
-using RefactorThis.GraphDiff;
-using System.Data.Entity;
-using System.Transactions;
-using System.Data.Entity.Infrastructure;
-using System.Linq.Expressions;
+using RefactorThis.GraphDiff.Tests.Models;

 namespace RefactorThis.GraphDiff.Tests
 {
@@ -1161,5 +1161,32 @@

         #endregion
+
+        #region Attach new root
+
+        [TestMethod]
+        public void EnsureNewRootsCanBeAdded()
+        {
+            var manager = new Manager
+            {
+                Key = "Some",
+                PartKey = "Boss",
+                PartKey2 = 23,
+                Employees = new Collection<Employee>()
+            };
+            var newEmployee = new Employee { Key = "Some", FirstName = "Employee", Manager = manager };
+            manager.Employees.Add(newEmployee);
+
+            using (var context = new TestDbContext())
+            {
+                context.UpdateGraph(manager, m => m.OwnedCollection(n => n.Employees));
+                context.SaveChanges();
+
+                var employee = context.Employees.Include(e => e.Manager).Single(e => e.Key == "Some");
+                Assert.IsTrue(employee.Manager.Key == manager.Key);
+            }
+        }
+
+        #endregion
     }
 }


add option -orient to dot2svg for layer orientation

Signed-off-by: Lev Nachmanson <547e21cf4741e0be725f19d6dc4faaf8564c91d1@microsoft.com>

--- GraphLayout/tools/Dot2Svg/Dot2SvgMain.cs
+++ GraphLayout/tools/Dot2Svg/Dot2SvgMain.cs
@@ -79,9 +79,10 @@
             argsParser.AddOptionWithAfterString(OutputDirOption);
             argsParser.AddAllowedOption(NoArrowheads);
             argsParser.AddAllowedOption(NoUrls);
-        }
-
-
+            argsParser.AddOptionWithAfterStringWithHelp("-orient", "one of options  TB, LR, BT, RL");
+        }
+
+
         static int Main(string[] args) {
             var p = new Dot2SvgMain(args);
             return p.DoJob();
@@ -209,7 +210,8 @@

         int ProcessDotFile(string inputFile) {
             Graph graph;
-            int i=CreateGraphFromDotFile(inputFile, out graph);
+            int i = CreateGraphFromDotFile(inputFile, out graph);
+            graph.Attr.LayerDirection = GetLayerDirection();

             if (i != 0)
                 return i;
@@ -250,6 +252,26 @@
                 WriteGeomGraph(outputFile, geomGraph);
             }
             return 0;
+        }
+
+        private LayerDirection GetLayerDirection()
+        {
+            string orientOption = argsParser.GetValueOfOptionWithAfterString("-orient");
+            if (orientOption == null)
+                return LayerDirection.TB;
+            switch (orientOption)
+            {
+                case "LR":
+                    return LayerDirection.LR;
+                case "TB":
+                    return LayerDirection.TB;
+                case "BT":
+                    return LayerDirection.BT;
+                case "RL":
+                    return LayerDirection.RL;
+                default:return LayerDirection.TB;
+            }
+
         }

         static void RemoveArrowheadsFromGraph(Graph graph) {


Add benchmark.

Add benchmark.

Just to get an idea about how things run on AppVeyor.

--- Gu.Wpf.UiAutomation.UITests/Benchmark.cs
+++ Gu.Wpf.UiAutomation.UITests/Benchmark.cs
@@ -10,6 +10,21 @@
         private static readonly string ExeFileName = Path.Combine(
             TestContext.CurrentContext.TestDirectory,
             @"..\..\TestApplications\WpfApplication\bin\WpfApplication.exe");
+
+        [OneTimeSetUp]
+        public void OneTimeSetUp()
+        {
+            using (Application.AttachOrLaunch(ExeFileName))
+            {
+                // for side effect of having the app open.
+            }
+        }
+
+        [OneTimeTearDown]
+        public void OneTimeTearDown()
+        {
+            Application.KillLaunched(ExeFileName);
+        }

         [Test]
         public void EmptyWindow()
@@ -50,5 +65,26 @@
                 Console.WriteLine($"IsChecked:    {sw.ElapsedMilliseconds - findCheckBox.TotalMilliseconds:F0} ms   ({sw.ElapsedMilliseconds:F0})");
             }
         }
+
+        [Test]
+        public void AttachOrLaunchCheckBox()
+        {
+            var sw = Stopwatch.StartNew();
+            using (var app = Application.AttachOrLaunch(ExeFileName))
+            {
+                var launch = sw.Elapsed;
+                var window = app.MainWindow;
+                var mainWindow = sw.Elapsed;
+                var checkBox = window.FindCheckBox("Test Checkbox");
+                var findCheckBox = sw.Elapsed;
+                var isChecked = checkBox.IsChecked;
+                sw.Stop();
+                Assert.AreEqual(false, isChecked);
+                Console.WriteLine($"AttachOrLaunch: {launch.TotalMilliseconds:F0} ms");
+                Console.WriteLine($"MainWindow:     {mainWindow.TotalMilliseconds - launch.TotalMilliseconds:F0} ms  ({mainWindow.TotalMilliseconds:F0})");
+                Console.WriteLine($"FindCheckBox:   {findCheckBox.TotalMilliseconds - mainWindow.TotalMilliseconds:F0} ms ({findCheckBox.TotalMilliseconds:F0})");
+                Console.WriteLine($"IsChecked:      {sw.ElapsedMilliseconds - findCheckBox.TotalMilliseconds:F0} ms  ({sw.ElapsedMilliseconds:F0})");
+            }
+        }
     }
 }


update lexeme comments

update lexeme comments

--- libraries/Pliant/Lexeme.cs
+++ libraries/Pliant/Lexeme.cs
@@ -7,7 +7,7 @@
 namespace Pliant
 {
     /// <summary>
-    /// A Lexeme is something special. It is not a production.
+    /// A Lexeme is something special. It acts like a token and a mini parser.
     /// </summary>
     public class Lexeme
     {


Remove debug code

Remove debug code

--- IntegrationEngine/EngineConfiguration.cs
+++ IntegrationEngine/EngineConfiguration.cs
@@ -56,8 +56,6 @@
             Container.Register<IntegrationEngineContext>(dbContext);
             var repository = new Repository<IntegrationEngine.Models.IntegrationJob>(dbContext);
             Container.Register<IRepository<IntegrationEngine.Models.IntegrationJob>>(repository);
-            repository.Save();
-            Console.WriteLine(repository.SelectAll().Count());
         }

         public void SetupApi()


Track player's shape

Track player's shape

--- IntelliRps/IntelliRpsLeap/HandTracker.cs
+++ IntelliRps/IntelliRpsLeap/HandTracker.cs
@@ -3,7 +3,6 @@
 using System.Linq;
 using System.Reactive.Linq;
 using IntelliRps;
-using IntelliRps.Core;
 using Reactive.Bindings;

 namespace IntelliRpsLeap
@@ -14,6 +13,8 @@

         public ReadOnlyReactiveProperty<int?> ExtendedFingersCount { get; }
         public ReadOnlyReactiveProperty<RpsShape?> HandShape { get; }
+
+        public ReactiveProperty<RpsShape?> PlayerShape { get; } = new ReactiveProperty<RpsShape?>();

         public HandTracker()
         {
@@ -26,6 +27,15 @@
                 .ToReadOnlyReactiveProperty();
         }

+        public void StartPlayerShapeTracking()
+        {
+            Observable.Repeat(HandShape.Value, 1)
+                .Merge(HandShape)
+                .Throttle(TimeSpan.FromSeconds(0.2))
+                .Take(1)
+                .Subscribe(s => PlayerShape.Value = s);
+        }
+
         static RpsShape ToShape(int fingers) =>
             fingers < 2 ? RpsShape.Rock :
             fingers < 4 ? RpsShape.Scissors :


Start string test

Start string test

--- Cascara.Test/Src/Program.cs
+++ Cascara.Test/Src/Program.cs
@@ -43,6 +43,8 @@
         {
             Console.WriteLine("==== Running Include Test ====");
             IncludeDirective();
+            Console.WriteLine("=== Running String Test ===");
+            String();
             Console.WriteLine("==== Running Gta3Save ====");
             Gta3Save();
             Console.WriteLine("==== Running UnionType ====");
@@ -241,6 +243,19 @@
             }
         }

+        private static void String()
+        {
+            string testPath = TestDataPath + "/String";
+            string binPath = testPath + "/StringTest.bin";
+            string xmlPath = testPath + "/StringTest.xml";
+
+            using (BinaryFile bFile = BinaryFile.Open(binPath))
+            {
+                LayoutFile lf = LayoutFile.Load(xmlPath);
+                bFile.SetLayout(lf);
+            }
+        }
+
         class UnionTest
         {
             public TestUnion TestUnion { get; set; }


删除update的目录

删除update的目录

--- ChromeAutoUpdate/FrmMain.cs
+++ ChromeAutoUpdate/FrmMain.cs
@@ -480,7 +480,7 @@
                 }

                 //删除目录
-                //Directory.Delete(Application.StartupPath + @"\update",true);
+                Directory.Delete(Application.StartupPath + @"\update",true);

                 File.Delete("chrome.7z");


Added relay serverevent handler

Added relay serverevent handler

--- IoTIrrigationController/MainPage.xaml.cs
+++ IoTIrrigationController/MainPage.xaml.cs
@@ -53,27 +53,9 @@

             string baseUri = "http://irrigationcontroller.azurewebsites.net/";
             client = new JsonServiceClient(baseUri);
-            seClient = new ServerEventsClient(baseUri, "relay")
-            {
-                OnConnect = e =>
-                {
-                    connectMsg = e;
-                },
-                OnCommand = e =>
-                {
-                    commands.Add(e);
-                },
-                OnMessage = e =>
-                {
-                    msgs.Add(e);
-                },
-                OnException = e =>
-                {
-                    errors.Add(e);
-                }
-            }
-            ;
-            seClient.Handlers["ZoneControl"] = HandleRelayCommand;
+            seClient = new ServerEventsClient(baseUri, "relay");
+            seClient.OnMessage = HandleRelayCommand;
+
             seClient.Start();

             InitGPIO();
@@ -181,9 +163,20 @@

         }

-        private void HandleRelayCommand(ServerEventsClient client, ServerEventMessage msg)
+        private void HandleRelayCommand(ServerEventMessage msg)
         {
+            if (msg.Target == "ZoneControl")
+            {
+                var zc = msg.Json.FromJson<ZoneControl>();
+                SetRelay((zc.RelayOn) ? GpioPinValue.High : GpioPinValue.Low);
+            }
+        }

+        private void SetRelay(GpioPinValue value)
+        {
+            if (relayPin == null) return;
+
+            relayPin.Write(value);
         }
     }
 }


git-svn-id: https://jumony.svn.codeplex.com/svn/trunk@78030 2327b42d-5241-43d6-9e2a-de5ac946f064

--- Ivony.Html/Extensions/ParserExtension.cs
+++ Ivony.Html/Extensions/ParserExtension.cs
@@ -108,8 +108,6 @@
       if ( stream == null )
         throw new ArgumentNullException( "stream" );

-      if ( uri == null )
-        throw new ArgumentNullException( "uri" );

       return LoadDocument( parser, new StreamReader( stream, true ), uri );
@@ -129,9 +127,6 @@

       if ( reader == null )
         throw new ArgumentNullException( "reader" );
-
-      if ( uri == null )
-        throw new ArgumentNullException( "uri" );

       var html = reader.ReadToEnd();


Make login user friendlier

Make login user friendlier

--- Joinrpg/Controllers/AccountController.cs
+++ Joinrpg/Controllers/AccountController.cs
@@ -73,7 +73,7 @@
       if (result == SignInStatus.Failure)
       {
         var legacyLoginResult = await _allrpgService.TryToLoginWithOldPassword(model.Email, model.Password);
-        switch (legacyLoginResult)
+        switch (legacyLoginResult)
         {
           case LegacyLoginResult.NoSuchUserOrPassword:
           case LegacyLoginResult.ImportDisabled:
@@ -140,6 +140,14 @@
     {
       if (ModelState.IsValid)
       {
+        var currentUser = await UserManager.FindByNameAsync(model.Email);
+
+        if (currentUser != null)
+        {
+          ModelState.AddModelError("", "Вы уже зарегистрировались. Если пароль не по, нажмите «Забыли пароль?»");
+          return View("Login", new LoginViewModel() {Email = model.Email});
+        }
+
         var user = new User {UserName = model.Email, Email = model.Email};
         var result = await UserManager.CreateAsync(user, model.Password);
         if (result.Succeeded)
@@ -256,8 +264,8 @@
       var user = await UserManager.FindByNameAsync(model.Email);
       if (user == null)
       {
-        // Don't reveal that the user does not exist
-        return RedirectToAction("ResetPasswordConfirmation", "Account");
+        ModelState.AddModelError("", "Email не найден");
+        return View();
       }
       var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
       if (result.Succeeded)


Fix UserConfig creating a directory instead of a file

--- Configuration/UserConfig.cs
+++ Configuration/UserConfig.cs
@@ -28,7 +28,10 @@

         public bool Save(){
             try{
-                Directory.CreateDirectory(file);
+                string directory = Path.GetDirectoryName(file);
+                if (directory == null)return false;
+
+                Directory.CreateDirectory(directory);

                 using(Stream stream = new FileStream(file,FileMode.Create,FileAccess.Write,FileShare.None)){
                     Formatter.Serialize(stream,this);


Make Color.Equals(Color) more clear

Make Color.Equals(Color) more clear

--- Corale.Colore/Core/Color.cs
+++ Corale.Colore/Core/Color.cs
@@ -354,7 +354,7 @@
         /// <returns><c>true</c> of the two are equal, false otherwise.</returns>
         public bool Equals(Color other)
         {
-            return _value.Equals(other);
+            return _value.Equals(other._value);
         }

         /// <summary>


fix Animation states

fix Animation states

--- Core/Game/Agents/LSAgent.cs
+++ Core/Game/Agents/LSAgent.cs
@@ -447,7 +447,7 @@
 			{
 				SetState(AnimState.Dying);

-				Animator.Visualize();
+				// Animator.Visualize(); // TODO: Now call in LockstepManager.LateVisualize ()
 			}
 		}

@@ -459,7 +459,7 @@
 				this.onDeactivate(this);
 			_Deactivate();

-			Immediate = true;
+			//Immediate = true; // TODO: Why ?
 			if (Immediate == false)
 			{
 				if (Animator.IsNotNull())


Added backup, removed german comments

Added backup, removed german comments

Used BackupOnClosingProject.cs as starting point

--- src/SimpleScript.cs
+++ src/SimpleScript.cs
@@ -1,15 +1,25 @@
-public class SimpleScript{
+namespace MyOtherNameSpace{
+public class ReportLib
+{
+	public string projectProperties()
+	{
+		ActionCallingContext pdfContext = new ActionCallingContext();
+		return pdfContext.ToString();
+	}

-    private string getProjectPath(int nStrippLevels){
+	public string getProjectPath(int nStrippLevels)
+	{
 		//Execute a "selectionset" action to obtain the currently selected project's full path
 		Eplan.EplApi.ApplicationFramework.ActionManager oMngr = new Eplan.EplApi.ApplicationFramework.ActionManager();
 		Eplan.EplApi.ApplicationFramework.Action oSelSetAction = oMngr.FindAction("selectionset");
 		string myPath = "";
-		if (oSelSetAction != null){
+		if (oSelSetAction != null)
+		{
 			Eplan.EplApi.ApplicationFramework.ActionCallingContext ctx = new Eplan.EplApi.ApplicationFramework.ActionCallingContext();
 			ctx.AddParameter("TYPE", "PROJECT");
 			bool bRet = oSelSetAction.Execute(ctx);
-			if (bRet){
+			if (bRet)
+			{
 				ctx.GetParameter("PROJECT", ref myPath);
 				for(int i=0;((myPath != "")&&(i<nStrippLevels));i++)
 				{
@@ -18,36 +28,32 @@
 			}
 		}
 		return myPath;
-    }
-
+	}

 	public void PDFexport(string sZielDatei)
 	{
-		//Progressbar ein
 		Eplan.EplApi.Base.Progress oProgress = new Eplan.EplApi.Base.Progress("SimpleProgress");
 		oProgress.ShowImmediately();
-
 		ActionCallingContext pdfContext = new ActionCallingContext();
-		pdfContext.AddParameter("type", "PDFPROJECTSCHEME"); //PDFPROJECTSCHEME = Projekt im PDF-Format exportieren
-		//pdfContext.AddParameter("exportscheme", "NAME_SCHEMA"); //verwendetes Schema
-		pdfContext.AddParameter("exportfile", sZielDatei); //Name export.Projekt, Vorgabewert: Projektname
-		pdfContext.AddParameter("exportmodel", "0"); //0 = keine Modelle ausgeben
-		pdfContext.AddParameter("blackwhite", "1"); //1 = PDF wird schwarz-weiss
-		pdfContext.AddParameter("useprintmargins", "1"); //1 = Druckränder verwenden
-		pdfContext.AddParameter("readonlyexport", "2"); //1 = PDF wird schreibgeschützt
-		pdfContext.AddParameter("usesimplelink", "1"); //1 = einfache Sprungfunktion
-		pdfContext.AddParameter("usezoomlevel", "1"); //Springen in Navigationsseiten
-		pdfContext.AddParameter("fastwebview", "1"); //1 = schnelle Web-Anzeige
-		pdfContext.AddParameter("zoomlevel", "1"); //wenn USEZOOMLEVEL auf 1 dann hier Zoomstufe in mm
+		pdfContext.AddParameter("type", "PDFPROJECTSCHEME");
+		pdfContext.AddParameter("exportfile", sZielDatei);
+		pdfContext.AddParameter("exportmodel", "0");
+		pdfContext.AddParameter("blackwhite", "1");
+		pdfContext.AddParameter("useprintmargins", "1");
+		pdfContext.AddParameter("readonlyexport", "2");
+		pdfContext.AddParameter("usesimplelink", "1");
+		pdfContext.AddParameter("usezoomlevel", "1");
+		pdfContext.AddParameter("fastwebview", "1");
+		pdfContext.AddParameter("zoomlevel", "1");

 		CommandLineInterpreter cmdLineItp = new CommandLineInterpreter();
 		cmdLineItp.Execute("export", pdfContext);

-		//'Progressbar aus
 		oProgress.EndPart(true);
 		return;
 	}
-    public bool generateReports()
+
+	public bool generateReports()
 	{
 		bool bResult = false;
 		string strProjectName = getProjectPath(0);
@@ -64,18 +70,71 @@
 		}
 		return bResult;
 	}
+
+	public void backup(string revisionType = "")
+	{
+	string strProjectname = PathMap.SubstitutePath("$(PROJECTNAME)");
+
+	string strFullProjectname = PathMap.SubstitutePath("$(P)");
+	if (strProjectname == "")
+	{
+		MessageBox.Show("No unique project selected", "Backup failed");
+	}
+	else
+	{
+		string strDestination = System.IO.Path.GetDirectoryName(strFullProjectname);//pealing off last folder
+		string myTime = System.DateTime.Now.ToString("yyyy_MM_dd");
+		string hour = System.DateTime.Now.Hour.ToString();
+		string minute = System.DateTime.Now.Minute.ToString();
+		Progress progress = new Progress("SimpleProgress");
+		progress.BeginPart(100, "");
+		progress.SetAllowCancel(true);
+		if (!progress.Canceled())
+		{
+			progress.BeginPart(33, "Backup");
+			ActionCallingContext backupContext = new ActionCallingContext();
+			backupContext.AddParameter("BACKUPMEDIA", "DISK");
+			backupContext.AddParameter("BACKUPMETHOD", "BACKUP");
+			backupContext.AddParameter("COMPRESSPRJ", "0");
+			backupContext.AddParameter("INCLEXTDOCS", "1");
+			backupContext.AddParameter("BACKUPAMOUNT", "BACKUPAMOUNT_ALL");
+			backupContext.AddParameter("INCLIMAGES", "1");
+			backupContext.AddParameter("LogMsgActionDone", "true");
+			backupContext.AddParameter("DESTINATIONPATH", strDestination);
+			backupContext.AddParameter("PROJECTNAME", strFullProjectname);
+			backupContext.AddParameter("TYPE", "PROJECT");
+			if (revisionType=="")
+			{
+				backupContext.AddParameter("ARCHIVENAME", strProjectname + "_" + myTime + "_" + hour + "_" + minute);//if no revision type defined, just add timestamp
+			}
+			else
+			{
+				backupContext.AddParameter("ARCHIVENAME",  strProjectname +  "_" + revisionType);//TODO: add revision number based on previus files
+			}
+			new CommandLineInterpreter().Execute("backup", backupContext);
+			progress.EndPart();
+		}
+		progress.EndPart(true);
+	}
+	return;
+	}
+}
+
+public class UtilitiesToolbar{
+	ReportLib myLib = new ReportLib();

-	 [DeclareAction("ShowMessage")]
-     public void showMessageFunction()
+	[DeclareAction("ShowMessage")]
+    public void showMessageFunction()
 	{
-		MessageBox.Show(DateTime.Now.ToString("yyyy-MM-dd"), "Useless date function");
+		MessageBox.Show(PathMap.SubstitutePath("$(P)"));
+		//MessageBox.Show(DateTime.Now.ToString("yyyy-MM-dd"), "Useless date function");
     }

 	 [DeclareAction("updateAndExportPDF")]
      public void updateAndExportPDFn()
 	 {
-		bool result = generateReports();
-	    PDFexport(getProjectPath(2) + "\\P2014-096 padde2\\" + DateTime.Now.ToString("yyyy-MM-dd") + "-export.pdf");
+		bool result = myLib.generateReports();
+	    myLib.PDFexport(myLib.getProjectPath(2) + "\\P2014-096 padde2\\" + DateTime.Now.ToString("yyyy-MM-dd") + "-export.pdf");
 		return;
      }

@@ -83,7 +142,7 @@
 	 [DeclareAction("OpenProjectFolder")]
 	 public void openProjectFolderFunction(){
 		string projectFolder = "";
-		projectFolder = getProjectPath(2);
+		projectFolder = myLib.getProjectPath(2);
 		if(projectFolder == string.Empty){
 			MessageBox.Show("Not able to open path. Select ONE project.", "ERROR");
 		}
@@ -91,12 +150,20 @@
 			System.Diagnostics.Process.Start("explorer.exe", projectFolder);
 		}
     }
+
+	[DeclareAction("backupProject")]
+	public void backupProject(){
+		myLib.backup();
+	}

 	[DeclareMenu]
 	public void SecondMenuFunction(){
            Eplan.EplApi.Gui.Menu oMenu = new Eplan.EplApi.Gui.Menu();
 		   oMenu.AddMenuItem("Custom","ShowMessage");
+		   oMenu.AddMenuItem("Back up project","backupProject");
 		   oMenu.AddMenuItem("Update and export PDFs","updateAndExportPDF");
 		   oMenu.AddMenuItem("Open project folder","OpenProjectFolder");
      }
-}+}
+}
+//User supplementary field 1 = P2014-096


Bump version to 0.9.2

Bump version to 0.9.2

--- src/SolutionInfo.cs
+++ src/SolutionInfo.cs
@@ -2,12 +2,12 @@
 using System.Reflection;

 [assembly: AssemblyProductAttribute("Journalist")]
-[assembly: AssemblyVersionAttribute("0.9.1")]
-[assembly: AssemblyInformationalVersionAttribute("0.9.1")]
-[assembly: AssemblyFileVersionAttribute("0.9.1")]
+[assembly: AssemblyVersionAttribute("0.9.2")]
+[assembly: AssemblyInformationalVersionAttribute("0.9.2")]
+[assembly: AssemblyFileVersionAttribute("0.9.2")]
 [assembly: AssemblyCompanyAttribute("Anton Mednonogov")]
 namespace System {
     internal static class AssemblyVersionInformation {
-        internal const string Version = "0.9.1";
+        internal const string Version = "0.9.2";
     }
 }


interface extracted

interface extracted

--- LoveSeat/Interfaces/IDocumentDatabase.cs
+++ LoveSeat/Interfaces/IDocumentDatabase.cs
@@ -127,5 +127,8 @@

         T GetDocument<T>(Guid id , IObjectSerializer<T> objectSerializer);
         T GetDocument<T>(Guid id);
+        string Show (string showName, string docId);
+        IListResult List(string listName, string viewName, ViewOptions options,  string designDoc);
+        IListResult List(string listName, string viewName, ViewOptions options);
     }
 }


More logging

More logging

--- MangaRipper.Core/Helpers/ParserHelper.cs
+++ MangaRipper.Core/Helpers/ParserHelper.cs
@@ -33,7 +33,7 @@
             {
                 Logger.Error("Cannot parse below content.");
                 Logger.Error(input);
-                throw new MangaRipperException("Parse content failed!");
+                throw new MangaRipperException("Parse content failed! Please check if you can access this content on your browser.");
             }

             foreach (Match match in matches)
@@ -44,7 +44,7 @@
                 list.Add(chapter);
             }
             var result = list.Distinct().ToList();
-            Logger.Info($@"Parse success. There's {result.Count()} item(s).");
+            Logger.Info($@"Parse success. There're {result.Count()} item(s).");
             return result;
         }

@@ -65,13 +65,14 @@
             {
                 Logger.Error("Cannot parse below content.");
                 Logger.Error(input);
-                throw new MangaRipperException("Parse content failed!");
+                throw new MangaRipperException("Parse content failed! Please check if you can access this content on your browser.");
             }

             var list = (from Match match in matches select match.Groups[groupName].Value.Trim()).ToList();
             var result = list.Distinct().ToList();
-            Logger.Info($@"Parse success. There's {result.Count()} item(s).");
+            Logger.Info($@"Parse success. There're {result.Count()} item(s).");
             return result;
         }
+
     }
 }