more stripe logging

more stripe logging

--- src/Billing/Controllers/StripeController.cs
+++ src/Billing/Controllers/StripeController.cs
@@ -94,7 +94,7 @@
             {
                 if(!(parsedEvent.Data.Object is Subscription subscription))
                 {
-                    throw new Exception("Subscription is null.");
+                    throw new Exception("Subscription is null. " + parsedEvent.Id);
                 }

                 var ids = GetIdsFromMetaData(subscription.Metadata);
@@ -136,14 +136,14 @@
             {
                 if(!(parsedEvent.Data.Object is Invoice invoice))
                 {
-                    throw new Exception("Invoice is null.");
+                    throw new Exception("Invoice is null. " + parsedEvent.Id);
                 }

                 var subscriptionService = new SubscriptionService();
                 var subscription = await subscriptionService.GetAsync(invoice.SubscriptionId);
                 if(subscription == null)
                 {
-                    throw new Exception("Invoice subscription is null.");
+                    throw new Exception("Invoice subscription is null. " + invoice.Id);
                 }

                 string email = null;
@@ -178,7 +178,7 @@
             {
                 if(!(parsedEvent.Data.Object is Charge charge))
                 {
-                    throw new Exception("Charge is null.");
+                    throw new Exception("Charge is null. " + parsedEvent.Id);
                 }

                 var chargeTransaction = await _transactionRepository.GetByGatewayIdAsync(
@@ -288,14 +288,14 @@
             {
                 if(!(parsedEvent.Data.Object is Charge charge))
                 {
-                    throw new Exception("Charge is null.");
+                    throw new Exception("Charge is null. " + parsedEvent.Id);
                 }

                 var chargeTransaction = await _transactionRepository.GetByGatewayIdAsync(
                     GatewayType.Stripe, charge.Id);
                 if(chargeTransaction == null)
                 {
-                    throw new Exception("Cannot find refunded charge.");
+                    throw new Exception("Cannot find refunded charge. " + charge.Id);
                 }

                 var amountRefunded = charge.AmountRefunded / 100M;
@@ -342,7 +342,7 @@
             {
                 if(!(parsedEvent.Data.Object is Invoice invoice))
                 {
-                    throw new Exception("Invoice is null.");
+                    throw new Exception("Invoice is null. " + parsedEvent.Id);
                 }

                 if(invoice.AttemptCount > 1 && UnpaidAutoChargeInvoiceForSubscriptionCycle(invoice))
@@ -354,7 +354,7 @@
             {
                 if(!(parsedEvent.Data.Object is Invoice invoice))
                 {
-                    throw new Exception("Invoice is null.");
+                    throw new Exception("Invoice is null. " + parsedEvent.Id);
                 }

                 if(UnpaidAutoChargeInvoiceForSubscriptionCycle(invoice))


Prefer first acceptable encoding.  Fixes #340

--- src/Cassette.Aspnet/BundleRequestHandler.cs
+++ src/Cassette.Aspnet/BundleRequestHandler.cs
@@ -94,17 +94,18 @@
                 return stream;
             }

-            if (encoding.IndexOf("deflate", StringComparison.OrdinalIgnoreCase) >= 0)
-            {
-                response.AppendHeader("Content-Encoding", "deflate");
-                response.AppendHeader("Vary", "Accept-Encoding");
-                return new DeflateStream(stream, CompressionMode.Compress, true);
-            }
-            else if (encoding.IndexOf("gzip", StringComparison.OrdinalIgnoreCase) >= 0)
-            {
-                response.AppendHeader("Content-Encoding", "gzip");
-                response.AppendHeader("Vary", "Accept-Encoding");
-                return new GZipStream(stream, CompressionMode.Compress, true);
+            foreach (var type in encoding.Split(',')) {
+                if (type.Equals("deflate", StringComparison.OrdinalIgnoreCase)) {
+                    response.AppendHeader("Content-Encoding", "deflate");
+                    response.AppendHeader("Vary", "Accept-Encoding");
+                    return new DeflateStream(stream, CompressionMode.Compress, true);
+                }
+                else if (type.Equals("gzip", StringComparison.OrdinalIgnoreCase)) {
+                    response.AppendHeader("Content-Encoding", "gzip");
+                    response.AppendHeader("Vary", "Accept-Encoding");
+                    return new GZipStream(stream, CompressionMode.Compress, true);
+                }
+
             }
             return stream;
         }


#154 added missing string comparison type to ScriptConfigLoader hack

--- src/ConfigR/Scripting/ScriptConfigLoader.cs
+++ src/ConfigR/Scripting/ScriptConfigLoader.cs
@@ -28,7 +28,7 @@
                 new ReferenceLineProcessor(fileSystem),
                 new UsingLineProcessor(),
             };
-
+
             var filePreProcessor = new FilePreProcessor(fileSystem, scriptCsLog, lineProcessors);
             var engine = new RoslynScriptInMemoryEngine(new ConfigRScriptHostFactory(config), scriptCsLog);
             var executor = new ConfigRScriptExecutor(fileSystem, filePreProcessor, engine, scriptCsLog);
@@ -60,7 +60,8 @@
             if (result.ExecuteExceptionInfo != null)
             {
                 // HACK: waiting on https://github.com/scriptcs/scriptcs/issues/545
-                if (!result.ExecuteExceptionInfo.SourceException.StackTrace.Trim().StartsWith("at Submission#"))
+                if (!result.ExecuteExceptionInfo.SourceException.StackTrace.Trim()
+                    .StartsWith("at Submission#", StringComparison.OrdinalIgnoreCase))
                 {
                     log.Warn(
                         "Roslyn failed to execute the scripts. Any configuration in this script will not be available",


version incremented 3.5.0

version incremented 3.5.0

--- src/DynamicTranslator/ApplicationVersion.cs
+++ src/DynamicTranslator/ApplicationVersion.cs
@@ -2,7 +2,7 @@
 {
     public static class ApplicationVersion
     {
-        public const string CurrentVersion = "3.4.2";
+        public const string CurrentVersion = "3.5.0";

         public static string GetCurrentVersion()
         {


Update author information: Evgeny Zborovsky. (#532)

--- src/Firehose.Web/Authors/EvgenyZborovsky.cs
+++ src/Firehose.Web/Authors/EvgenyZborovsky.cs
@@ -4,18 +4,18 @@

 namespace Firehose.Web.Authors
 {
-    public class EvgenyZborovsky : IAmACommunityMember
+    public class EvgenyZborovsky : IAmAMicrosoftMVP
     {
         public string FirstName => "Evgeny";
         public string LastName => "Zborovsky";
         public string StateOrRegion => "Estonia";
         public string EmailAddress => "yuv4ik@gmail.com";
-        public string ShortBioOrTagLine => "Xamarin Enthusiast";
+        public string ShortBioOrTagLine => "blogs, speaks, helps others and is enthusiastic Xamarin developer.";
         public Uri WebSite => new Uri("https://smellyc0de.wordpress.com/");
         public IEnumerable<Uri> FeedUris
         {
-            get
-            {
+            get
+            {
                 yield return new Uri("https://smellyc0de.wordpress.com/tag/xamarin-forms/feed/");
                 yield return new Uri("https://smellyc0de.wordpress.com/tag/xamarin/feed/");
             }


Do not use DynamicInvoke but the much faster Invoke

--- src/Fluidity/Extensions/ObjectExtensions.cs
+++ src/Fluidity/Extensions/ObjectExtensions.cs
@@ -4,7 +4,6 @@
 // </copyright>

 using System;
-using System.Linq.Expressions;
 using System.Reflection;
 using System.Security.Cryptography;
 using System.Text;
@@ -18,7 +17,7 @@
         {
             if (config.PropertyGetter != null)
             {
-                return config.PropertyGetter.DynamicInvoke(instance);
+                return config.PropertyGetter.Invoke(instance);
             }
             else
             {
@@ -35,7 +34,7 @@
         {
             if (config.PropertySetter != null)
             {
-                config.PropertySetter.DynamicInvoke(instance, value);
+                config.PropertySetter.Invoke(instance, value);
             }
             else
             {


Work in progress

Work in progress

--- src/Framework/N2/Edit/Api/ContentHandler.cs
+++ src/Framework/N2/Edit/Api/ContentHandler.cs
@@ -78,6 +78,12 @@
 				case "POST":
 					switch (context.Request.PathInfo)
 					{
+						case "":
+							Create(context);
+							break;
+						case "/update":
+							Update(context);
+							break;
 						case "/sort":
 						case "/move":
 							Move(context, Selection.RequestValueAccessor);
@@ -102,7 +108,20 @@
 				case "DELETE":
 					Delete(context);
 					break;
-			}
+				case "PUT":
+					Update(context);
+					break;
+			}
+		}
+
+		private void Update(HttpContextBase context)
+		{
+			throw new NotImplementedException();
+		}
+
+		private void Create(HttpContextBase context)
+		{
+			throw new NotImplementedException();
 		}

 		private IEnumerable<ItemDefinition> CreateDefinitions(HttpContextBase context)


fix #544 : Close experiment popup(s) when connection is lost on unmanned vessels

--- src/Kerbalism/UI/Science/ExperimentPopup.cs
+++ src/Kerbalism/UI/Science/ExperimentPopup.cs
@@ -151,6 +151,12 @@

 		private void GetData()
 		{
+			if(!vd.Connection.linked && vd.CrewCount == 0)
+			{
+				window.Close();
+				return;
+			}
+
 			if (isProto)
 			{
 				status = Lib.Proto.GetEnum(protoModule, "status", ExpStatus.Stopped);


ImageGrid testing changes.

ImageGrid testing changes.

--- code/R3/R3.Core/Drawing/ImageGrid.cs
+++ code/R3/R3.Core/Drawing/ImageGrid.cs
@@ -1,4 +1,4 @@
-namespace HyperbolicModels
+namespace R3.Drawing
 {
 	using System.Drawing;
 	using System.Drawing.Imaging;
@@ -45,10 +45,10 @@
 		{
 			Bitmap image = new Bitmap( s.Width, s.Height );
 			Graphics g = Graphics.FromImage( image );
-			g.Clear( Color.White );
+			g.Clear( Color.Black );

-			int tileWidth = 1000;//s.Width / s.Columns;
-			int tileHeight = 1000;// s.Height / s.Rows;
+			int tileWidth = 200;//s.Width / s.Columns;
+			int tileHeight = 200;// s.Height / s.Rows;
 			int vGap = s.vGap, hGap = s.hGap;
 			Size tileSize = new Size( tileWidth, tileHeight );

@@ -56,10 +56,10 @@
 			foreach( string imageName in s.InputImages )
 			{
 				string fullFileName = Path.Combine( s.Directory, imageName );
-				Bitmap tile = new Bitmap( fullFileName );
+				Bitmap original = new Bitmap( fullFileName );

 				// Resize
-				tile = new Bitmap( tile, tileSize );
+				Bitmap tile = new Bitmap( original, tileSize );

 				// Copy to location.
 				for( int i=0; i<tile.Width; i++ )
@@ -68,6 +68,9 @@
 					Color c = tile.GetPixel( i, j );
 					image.SetPixel( currentCol * (tileWidth + hGap) + i, currentRow * (tileHeight + vGap) + j, c );
 				}
+
+				original.Dispose();
+				tile.Dispose();

 				currentCol++;
 				if( currentCol >= s.Columns )


Tests: Remove dependency on id generation algorithm for a few tests.

--- src/NHibernate.Test/Linq/MethodCallTests.cs
+++ src/NHibernate.Test/Linq/MethodCallTests.cs
@@ -38,7 +38,6 @@
 				.First();

 			Assert.That(result.Length, Is.EqualTo(3));
-			Assert.That(result[0], Is.EqualTo(1));
 			Assert.That(result[1], Is.EqualTo("ayende"));
 			Assert.That(result[2], Is.EqualTo(4));
 		}
@@ -86,7 +85,6 @@
 				.First();

 			Assert.That(result.Length, Is.EqualTo(4));
-			Assert.That(result[0], Is.EqualTo(1));
 			Assert.That(result[1], Is.EqualTo(pi));
 			Assert.That(result[2], Is.EqualTo(name));
 			Assert.That(result[3], Is.EqualTo(DateTime.MinValue));
@@ -100,7 +98,6 @@
 				.First();

 			Assert.That(result.Length, Is.EqualTo(3));
-			Assert.That(result[0], Is.EqualTo(1));
 			Assert.That(result[1], Is.EqualTo("Admin"));
 			Assert.That(result[2], Is.EqualTo("output"));
 		}


minor

minor

--- src/Net.Appclusive.PS.Client/EnterServer.cs
+++ src/Net.Appclusive.PS.Client/EnterServer.cs
@@ -69,7 +69,7 @@
         }

         /// <summary>
-        /// Specifies the base url of the Abiquo endpoint
+        /// Specifies the base URI of the Appclusive API
         /// </summary>
         [Parameter(Mandatory = true, Position = 0, ParameterSetName = ParameterSets.PLAIN)]
         [Parameter(Mandatory = true, Position = 0, ParameterSetName = ParameterSets.CREDENTIAL)]


change variable name as per review.

change variable name as per review.

--- src/Options/PackageSourcesOptionsControl.cs
+++ src/Options/PackageSourcesOptionsControl.cs
@@ -21,7 +21,7 @@
     /// Otherwise, we have a problem with synchronization with the package source provider.
     /// </remarks>
     public partial class PackageSourcesOptionsControl : UserControl {
-        private readonly PackageSource OfficialSource = new PackageSource(NuGetConstants.DefaultFeedUrl, VsResources.OfficialSourceName);
+        private readonly PackageSource _officialSource = new PackageSource(NuGetConstants.DefaultFeedUrl, VsResources.OfficialSourceName);
         private readonly IVsPackageSourceProvider _packageSourceProvider;
         private PackageSource _activeSource;
         private BindingSource _allPackageSources;
@@ -58,7 +58,7 @@
             MoveDownButton.Enabled = selectedSource != null &&
                                      PackageSourcesListBox.SelectedIndex < PackageSourcesListBox.Items.Count - 1;
             // do not allow deleting the official NuGet source
-            removeButton.Enabled = selectedSource != null && !selectedSource.Equals(OfficialSource);
+            removeButton.Enabled = selectedSource != null && !selectedSource.Equals(_officialSource);
         }

         private void MoveSelectedItem(int offset) {


Fix error in tests (I forget TearDown method)

--- src/OrigoDB.Core.UnitTests/FileStoreTest.cs
+++ src/OrigoDB.Core.UnitTests/FileStoreTest.cs
@@ -22,7 +22,7 @@
         //
         //Use ClassInitialize to run code before running the first test in the class
         [SetUp]
-        public void MyTestInitialize()
+        public void SetUp()
         {
             Directory.CreateDirectory(_path);
             _config = EngineConfiguration.Create();
@@ -44,6 +44,15 @@
             if (Directory.Exists(_path))
                 Directory.Delete(_path, true);
         }
+
+        //Use TestCleanup to run code after each test has run
+        [TearDown]
+        public void TearDown()
+        {
+            if (Directory.Exists(_path))
+                Directory.Delete(_path, true);
+        }
+

         [Test, ExpectedException(typeof(InvalidOperationException))]
 		public void JournalReadThrowsIfSequenceStartIsMissing()


Ignore processes that we don't have permission to get the name. Fixes #1024

--- src/Squirrel/UpdateManager.ApplyReleases.cs
+++ src/Squirrel/UpdateManager.ApplyReleases.cs
@@ -597,7 +597,7 @@
                 // Finally, clean up the app-X.Y.Z directories
                 await toCleanup.ForEachAsync(async x => {
                     try {
-                        if (runningProcesses.All(p => !p.Item1.StartsWith(x.FullName, StringComparison.OrdinalIgnoreCase))) {
+                        if (runningProcesses.All(p => p.Item1 == null || !p.Item1.StartsWith(x.FullName, StringComparison.OrdinalIgnoreCase))) {
                             await Utility.DeleteDirectoryOrJustGiveUp(x.FullName);
                         }


Dramatically improved performance of migrator. Added new steps for migration debugging. Fixed some bugs in the migrator.

--- Forum/Controllers/Administration.cs
+++ Forum/Controllers/Administration.cs
@@ -46,9 +46,9 @@
 		[HttpGet]
 		public async Task<IActionResult> Maintenance() {
 			return await ForumViewResult.ViewResult(this, "MultiStep", new List<string> {
-				Url.Action(nameof(RebuildTopics)),
 				Url.Action(nameof(CleanupDeletedMessages)),
 				Url.Action(nameof(ReprocessMessages)),
+				Url.Action(nameof(RebuildTopics)),
 			});
 		}

@@ -68,13 +68,20 @@
 				});
 			}

-			var topicsQuery = DbContext.Topics.Skip(input.CurrentPage * input.Take).Take(input.Take);
-
-			foreach (var topic in topicsQuery) {
-				await TopicRepository.RebuildTopic(topic);
-			}
-
-			return Ok();
+			var records = await DbContext.Topics.Where(item => item.Id > input.LastRecordId).Take(input.Take).ToListAsync();
+
+			if (input.LastRecordId < 0) {
+				records = await DbContext.Topics.Skip(input.CurrentPage * input.Take).Take(input.Take).ToListAsync();
+			}
+
+			var lastRecordId = 0;
+
+			foreach (var record in records) {
+				await TopicRepository.RebuildTopic(record);
+				lastRecordId = record.Id;
+			}
+
+			return Ok(lastRecordId);
 		}

 		[HttpPost]
@@ -115,25 +122,33 @@
 				});
 			}

-			var messages = DbContext.Messages.Skip(input.CurrentPage * input.Take).Take(input.Take);
-
-			foreach (var message in messages) {
-				var processedMessage = await MessageRepository.ProcessMessageInput(message.OriginalBody);
+			var records = await DbContext.Messages.Where(item => item.Id > input.LastRecordId).Take(input.Take).ToListAsync();
+
+			if (input.LastRecordId < 0) {
+				records = await DbContext.Messages.Skip(input.CurrentPage * input.Take).Take(input.Take).ToListAsync();
+			}
+
+			var lastRecordId = 0;
+
+			foreach (var record in records) {
+				var processedMessage = await MessageRepository.ProcessMessageInput(record.OriginalBody);

 				if (!processedMessage.Errors.Any()) {
-					message.OriginalBody = processedMessage.OriginalBody;
-					message.DisplayBody = processedMessage.DisplayBody;
-					message.ShortPreview = processedMessage.ShortPreview;
-					message.LongPreview = processedMessage.LongPreview;
-					message.Cards = processedMessage.Cards;
-
-					DbContext.Update(message);
+					record.OriginalBody = processedMessage.OriginalBody;
+					record.DisplayBody = processedMessage.DisplayBody;
+					record.ShortPreview = processedMessage.ShortPreview;
+					record.LongPreview = processedMessage.LongPreview;
+					record.Cards = processedMessage.Cards;
+
+					DbContext.Update(record);
 				}
-			}
-
-			await DbContext.SaveChangesAsync();
-
-			return Ok();
+
+				lastRecordId = record.Id;
+			}
+
+			await DbContext.SaveChangesAsync();
+
+			return Ok(lastRecordId);
 		}

 		[HttpGet]
@@ -261,6 +276,8 @@
 			return await ForumViewResult.ViewResult(this, "MultiStep", new List<string> {
 				Url.Action(nameof(CleanupDeletedMessages)),
 				Url.Action(nameof(ResetMessageTopicId)),
+				Url.Action(nameof(ResetViewLogs)),
+				Url.Action(nameof(DeleteTopics)),
 				Url.Action(nameof(MigrateTopics)),
 				Url.Action(nameof(MigrateMessages)),
 				Url.Action(nameof(MigrateViewLogs)),
@@ -268,6 +285,7 @@
 				Url.Action(nameof(MigrateParticipants)),
 				Url.Action(nameof(MigrateTopicBoards)),
 				Url.Action(nameof(ReprocessMessages)),
+				Url.Action(nameof(RebuildTopics)),
 			});
 		}

@@ -287,20 +305,95 @@
 				});
 			}

-			var pSkip = new SqlParameter("@Skip", input.CurrentPage * input.Take);
-			var pTake = new SqlParameter("@Take", input.Take);
-
-			await DbContext.Database.ExecuteSqlCommandAsync($@"
-					UPDATE [{nameof(ApplicationDbContext.Messages)}]
-					SET {nameof(DataModels.Message.TopicId)} = 0
-					WHERE {nameof(DataModels.Message.Id)}
-					IN (
-						SELECT Id
-						FROM [{nameof(ApplicationDbContext.Messages)}]
-						ORDER BY Id
-						OFFSET @Skip ROWS
-						FETCH NEXT @Take ROWS ONLY
-					)", pSkip, pTake);
+			var recordQuery = DbContext.Messages.Where(item => item.Id > input.LastRecordId).Take(input.Take);
+
+			if (input.LastRecordId < 0) {
+				recordQuery = DbContext.Messages.Skip(input.Take * input.CurrentPage).Take(input.Take);
+			}
+
+			var lastRecordId = 0;
+
+			foreach (var record in recordQuery) {
+				record.TopicId = 0;
+				lastRecordId = record.Id;
+			}
+
+			await DbContext.SaveChangesAsync();
+
+			return Ok(lastRecordId);
+		}
+
+		[HttpPost]
+		public async Task<IActionResult> ResetViewLogs(ControllerModels.Administration.Page input) {
+			var recordsQuery = DbContext.ViewLogs.Where(item => item.TargetType == EViewLogTargetType.Topic);
+
+			if (input.CurrentPage < 0) {
+				var take = 500;
+				var totalRecords = await recordsQuery.CountAsync();
+				var totalPages = Convert.ToInt32(Math.Floor(1d * totalRecords / take));
+
+				return Ok(new ControllerModels.Administration.Step {
+					ActionName = "Reset ViewLogs",
+					ActionNote = "Re-associating viewlogs back to message IDs.",
+					Take = take,
+					TotalPages = totalPages,
+					TotalRecords = totalRecords,
+				});
+			}
+
+
+			if (input.LastRecordId >= 0) {
+				recordsQuery = recordsQuery.Where(item => item.Id > input.LastRecordId).Take(input.Take);
+			}
+			else {
+				recordsQuery = recordsQuery.Skip(input.CurrentPage * input.Take).Take(input.Take);
+			}
+
+			var records = await recordsQuery.ToListAsync();
+			var topicIds = records.Select(item => item.TargetId).Distinct();
+
+			var messageIdsQuery = from topic in DbContext.Topics
+								where topicIds.Contains(topic.Id)
+								select new {
+									MessageId = topic.FirstMessageId,
+									TopicId = topic.Id
+								};
+
+			var messageIds = await messageIdsQuery.ToListAsync();
+
+			var lastRecordId = 0;
+
+			foreach (var record in records) {
+				record.TargetType = EViewLogTargetType.Message;
+				record.TargetId = messageIds.First(item => item.TopicId == record.TargetId).MessageId;
+				DbContext.Update(record);
+				lastRecordId = record.Id;
+			}
+
+			await DbContext.SaveChangesAsync();
+
+			return Ok(lastRecordId);
+		}
+
+		[HttpPost]
+		public async Task<IActionResult> DeleteTopics(ControllerModels.Administration.Page input) {
+			if (input.CurrentPage < 0) {
+				var take = 500;
+				var totalRecords = await DbContext.Topics.CountAsync();
+				var totalPages = Convert.ToInt32(Math.Floor(1d * totalRecords / take));
+
+				return Ok(new ControllerModels.Administration.Step {
+					ActionName = "Delete Topics",
+					ActionNote = "Removing all previously created topics.",
+					Take = take,
+					TotalPages = totalPages,
+					TotalRecords = totalRecords,
+				});
+			}
+
+			var records = DbContext.Topics.Take(input.Take);
+			DbContext.RemoveRange(records);
+			await DbContext.SaveChangesAsync();

 			return Ok();
 		}
@@ -325,32 +418,21 @@
 				});
 			}

-			var records = await parentMessagesQuery.Skip(input.CurrentPage * input.Take).Take(input.Take).ToListAsync();
-
-			foreach (var record in records) {
-				DataModels.Message lastMessage = null;
-
-				if (record.LastReplyId > 0) {
-					lastMessage = DbContext.Messages.Find(record.LastReplyId);
-				}
-
+			var records = parentMessagesQuery.Take(input.Take);
+
+			foreach (var record in records) {
 				DbContext.Topics.Add(new DataModels.Topic {
 					FirstMessageId = record.Id,
 					FirstMessagePostedById = record.PostedById,
 					FirstMessageTimePosted = record.TimePosted,
 					FirstMessageShortPreview = record.ShortPreview,
-					LastMessageId = lastMessage?.Id ?? record.Id,
-					LastMessagePostedById = lastMessage?.PostedById ?? record.PostedById,
-					LastMessageTimePosted = lastMessage?.TimePosted ?? record.TimePosted,
-					LastMessageShortPreview = lastMessage?.ShortPreview ?? record.ShortPreview,
 					Pinned = record.Pinned,
 					Deleted = record.Deleted,
-					ReplyCount = record.ReplyCount,
 					ViewCount = record.ViewCount
 				});
-
-				await DbContext.SaveChangesAsync();
-			}
+			}
+
+			await DbContext.SaveChangesAsync();

 			return Ok();
 		}
@@ -371,22 +453,31 @@
 				});
 			}

-			var records = await DbContext.Messages.Skip(input.CurrentPage * input.Take).Take(input.Take).ToListAsync();
+			var records = DbContext.Messages.Where(item => item.Id > input.LastRecordId).Take(input.Take);
+
+			if (input.LastRecordId < 0) {
+				records = DbContext.Messages.Skip(input.CurrentPage * input.Take).Take(input.Take);
+			}
+
+			var lastRecordId = 0;

 			foreach (var record in records) {
 				record.TopicId = DbContext.Topics.First(item => record.ParentId == 0 ? item.FirstMessageId == record.Id : item.FirstMessageId == record.ParentId).Id;
-			}
-
-			await DbContext.SaveChangesAsync();
-
-			return Ok();
+				lastRecordId = record.Id;
+			}
+
+			await DbContext.SaveChangesAsync();
+
+			return Ok(lastRecordId);
 		}

 		[HttpPost]
 		public async Task<IActionResult> MigrateViewLogs(ControllerModels.Administration.Page input) {
-			if (input.CurrentPage < 0) {
-				var take = 20;
-				var totalRecords = DbContext.Topics.Count();
+			var recordsQuery = DbContext.ViewLogs.Where(item => item.TargetType == EViewLogTargetType.Message);
+
+			if (input.CurrentPage < 0) {
+				var take = 500;
+				var totalRecords = await recordsQuery.CountAsync();
 				var totalPages = Convert.ToInt32(Math.Floor(1d * totalRecords / take));

 				return Ok(new ControllerModels.Administration.Step {
@@ -398,29 +489,37 @@
 				});
 			}

-			var topics = DbContext.Topics.Skip(input.CurrentPage * input.Take).Take(input.Take);
-
-			foreach (var topic in topics) {
-				var pTopicId = new SqlParameter("@TopicId", topic.Id);
-				var pViewLogTypeMessage = new SqlParameter("@ViewLogTypeMessage", EViewLogTargetType.Message);
-				var pViewLogTypeTopic = new SqlParameter("@ViewLogTypeTopic", EViewLogTargetType.Topic);
-				var pFirstMessageId = new SqlParameter("@FirstMessageId", topic.FirstMessageId);
-
-				await DbContext.Database.ExecuteSqlCommandAsync($@"
-					UPDATE [{nameof(ApplicationDbContext.ViewLogs)}]
-					SET {nameof(DataModels.ViewLog.TargetId)} = @TopicId,
-						{nameof(DataModels.ViewLog.TargetType)} = @ViewLogTypeTopic
-					WHERE {nameof(DataModels.ViewLog.TargetType)} = @ViewLogTypeMessage
-					AND {nameof(DataModels.ViewLog.TargetId)}
-					IN (
-						SELECT Id
-						FROM [{nameof(ApplicationDbContext.Messages)}]
-						WHERE Id = @FirstMessageId
-						OR ParentId = @FirstMessageId
-					)", pTopicId, pViewLogTypeTopic, pViewLogTypeMessage, pFirstMessageId);
-			}
-
-			return Ok();
+			if (input.LastRecordId >= 0) {
+				recordsQuery = recordsQuery.Where(item => item.Id > input.LastRecordId).Take(input.Take);
+			}
+			else {
+				recordsQuery = recordsQuery.Skip(input.CurrentPage * input.Take).Take(input.Take);
+			}
+
+			var records = await recordsQuery.ToListAsync();
+			var messageIds = records.Select(item => item.TargetId).Distinct();
+
+			var topicIdsQuery = from message in DbContext.Messages
+								where messageIds.Contains(message.Id)
+								select new {
+									MessageId = message.Id,
+									message.TopicId
+								};
+
+			var topicIds = await topicIdsQuery.ToListAsync();
+
+			var lastRecordId = 0;
+
+			foreach (var record in records) {
+				record.TargetType = EViewLogTargetType.Topic;
+				record.TargetId = topicIds.First(item => item.MessageId == record.TargetId).TopicId;
+				DbContext.Update(record);
+				lastRecordId = record.Id;
+			}
+
+			await DbContext.SaveChangesAsync();
+
+			return Ok(lastRecordId);
 		}

 		[HttpPost]
@@ -476,7 +575,13 @@
 				});
 			}

-			var records = await DbContext.Participants.Skip(input.CurrentPage * input.Take).Take(input.Take).ToListAsync();
+			var records = DbContext.Participants.Where(item => item.Id > input.LastRecordId).Take(input.Take);
+
+			if (input.LastRecordId < 0) {
+				records = DbContext.Participants.Skip(input.CurrentPage * input.Take).Take(input.Take);
+			}
+
+			var lastRecordId = 0;

 			foreach (var record in records) {
 				var message = await DbContext.Messages.FirstOrDefaultAsync(item => item.Id == record.MessageId);
@@ -487,11 +592,13 @@
 				else {
 					record.TopicId = message.TopicId;
 				}
-			}
-
-			await DbContext.SaveChangesAsync();
-
-			return Ok();
+
+				lastRecordId = record.Id;
+			}
+
+			await DbContext.SaveChangesAsync();
+
+			return Ok(lastRecordId);
 		}

 		[HttpPost]
@@ -510,11 +617,17 @@
 				});
 			}

-			var topics = await DbContext.Topics.Skip(input.CurrentPage * input.Take).Take(input.Take).ToListAsync();
-
-			foreach (var topic in topics) {
+			var records = DbContext.Topics.Where(item => item.Id > input.LastRecordId).Take(input.Take);
+
+			if (input.LastRecordId < 0) {
+				records = DbContext.Topics.Skip(input.CurrentPage * input.Take).Take(input.Take);
+			}
+
+			var lastRecordId = 0;
+
+			foreach (var record in records) {
 				var topicBoardsQuery = from topicBoard in DbContext.TopicBoards
-									   where topicBoard.MessageId == topic.FirstMessageId
+									   where topicBoard.MessageId == record.FirstMessageId
 									   select topicBoard;

 				var topicBoards = await topicBoardsQuery.ToListAsync();
@@ -535,11 +648,13 @@

 				DbContext.RemoveRange(topicBoards);
 				DbContext.AddRange(newTopicBoards);
-			}
-
-			await DbContext.SaveChangesAsync();
-
-			return Ok();
+
+				lastRecordId = record.Id;
+			}
+
+			await DbContext.SaveChangesAsync();
+
+			return Ok(lastRecordId);
 		}

 		void CheckInstallContext() {


Whitespace fix (which also forces a rebuild ;))

--- GitTfs.VsCommon/TfsHelper.Common.cs
+++ GitTfs.VsCommon/TfsHelper.Common.cs
@@ -41,6 +41,7 @@
                 _resolverInstalled = true;
             }
         }
+
         [SetterProperty]
         public Janitor Janitor { get; set; }


Add test for redundant references

Add test for redundant references

--- src/Tasks.UnitTests/CodeTaskFactoryTests.cs
+++ src/Tasks.UnitTests/CodeTaskFactoryTests.cs
@@ -1101,6 +1101,36 @@
                 FileUtilities.DeleteDirectoryNoThrow(newTempPath, true);
             }
         }
+
+        /// <summary>
+        /// Test the simple case where we have a string parameter and we want to log that.
+        /// </summary>
+        [Fact]
+        public void RedundantMSBuildReferences()
+        {
+            string projectFileContents = @"
+                    <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion='msbuilddefaulttoolsversion'>
+                        <UsingTask TaskName=`CustomTaskFromCodeFactory_RedundantMSBuildReferences` TaskFactory=`CodeTaskFactory` AssemblyFile=`$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll` >
+                         <ParameterGroup>
+                             <Text/>
+                          </ParameterGroup>
+                            <Task>
+                              <Reference Include='$(MSBuildToolsPath)\Microsoft.Build.Framework.dll' />
+                              <Reference Include='$(MSBuildToolsPath)\Microsoft.Build.Utilities.Core.dll' />
+
+                                <Code>
+                                     Log.LogMessage(MessageImportance.High, Text);
+                                </Code>
+                            </Task>
+                        </UsingTask>
+                        <Target Name=`Build`>
+                            <CustomTaskFromCodeFactory_RedundantMSBuildReferences Text=`Hello, World!` />
+                        </Target>
+                    </Project>";
+
+            MockLogger mockLogger = Helpers.BuildProjectWithNewOMExpectSuccess(projectFileContents);
+            mockLogger.AssertLogContains("Hello, World!");
+        }
     }
 #else
     public sealed class CodeTaskFactoryTests


Fix to potential null reference

Fix to potential null reference

Signed-off-by: Kelly Nelson <d2347f4ecb491a89d0c21a9b59e4b9813381f96f@farmbeltnorth.com>

--- ISOv4Plugin/Mappers/DeviceMapper.cs
+++ ISOv4Plugin/Mappers/DeviceMapper.cs
@@ -108,7 +108,11 @@
             if (isoDevice.DeviceElements.Any())
             {
                 DeviceElementMapper detMapper = new DeviceElementMapper(TaskDataMapper);
-                DataModel.Catalog.DeviceElements.AddRange(detMapper.ImportDeviceElements(isoDevice));
+                IEnumerable<DeviceElement> deviceElements = detMapper.ImportDeviceElements(isoDevice);
+                if (deviceElements != null)
+                {
+                    DataModel.Catalog.DeviceElements.AddRange(deviceElements);
+                }
             }

             return deviceModel;


Clean up formatting

Clean up formatting

--- src/TeacherPouch/Services/SiteMapService.cs
+++ src/TeacherPouch/Services/SiteMapService.cs
@@ -69,9 +69,9 @@
                 root.Add(CreateSiteMapNode(_urlHelper.TagDetails(tag)));
             }

-            using (MemoryStream ms = new MemoryStream())
+            using (var ms = new MemoryStream())
             {
-                using (StreamWriter writer = new StreamWriter(ms, Encoding.UTF8))
+                using (var writer = new StreamWriter(ms, Encoding.UTF8))
                 {
                     root.Save(writer);
                 }
@@ -82,7 +82,8 @@

         private static XElement CreateSiteMapNode(string siteRelativeUrl)
         {
-            return new XElement(RootNamespace + "url",
+            return
+                new XElement(RootNamespace + "url",
                     new XElement(RootNamespace + "loc", "{0}" + siteRelativeUrl));
         }

@@ -93,9 +94,7 @@
                     new XElement(RootNamespace + "loc", "{0}" + siteRelativeUrl),
                     new XElement(ImagesNamespace + "image",
                         new XElement(ImagesNamespace + "loc", "{0}" + photoImageUrl),
-                        new XElement(ImagesNamespace + "license", "{0}" + licenseUrl)
-                    )
-                );
+                        new XElement(ImagesNamespace + "license", "{0}" + licenseUrl)));
         }
     }
 }


[WindowBackend] fixed Invalidate()

[WindowBackend] fixed Invalidate()

--- src/Xwt.Sdl/Xwt.SdlBackend/WindowBackend.cs
+++ src/Xwt.Sdl/Xwt.SdlBackend/WindowBackend.cs
@@ -337,7 +337,9 @@
 		bool clearBackground = true;
 		public void Invalidate()
 		{
-			Invalidate (Bounds);
+			int w, h;
+			SDL.SDL_GetWindowSize (window, out w, out h);
+			Invalidate (new Rectangle(0,0, w, h));
 			clearBackground = true;
 		}


Delete GetLeverAngle.cs

Delete GetLeverAngle.cs

--- Interactions/Lever/GetLeverAngle.cs
+++ Interactions/Lever/GetLeverAngle.cs
@@ -1,109 +0,0 @@
-// Custom Action by DumbGameDev
-
-// www.dumbgamedev.com
-
-
-
-using UnityEngine;
-
-using VRTK;
-
-
-
-namespace HutongGames.PlayMaker.Actions
-
-{
-
-	[ActionCategory("VRTK Interaction")]
-
-	[Tooltip("Get the angle of a lever with the VRTK Lever Script.")]
-
-
-
-	public class  GetLeverAngle : FsmStateAction
-
-	{
-
-		[RequiredField]
-
-		[CheckForComponent(typeof(VRTK.VRTK_Lever))]
-
-		public FsmOwnerDefault gameObject;
-
-
-
-		[TitleAttribute("Lever Angle")]
-
-		public FsmFloat angle;
-
-
-
-		private	VRTK.UnityEventHelper.VRTK_Control_UnityEvents controlEvents;
-
-
-
-		public override void Reset()
-
-		{
-
-
-
-			gameObject = null;
-
-			angle = null;
-
-		}
-
-
-
-		public override void OnEnter()
-
-		{
-
-			var go = Fsm.GetOwnerDefaultTarget(gameObject);
-
-
-
-			controlEvents = go.GetComponent<VRTK.UnityEventHelper.VRTK_Control_UnityEvents>();
-
-			if (controlEvents == null)
-
-			{
-
-				controlEvents = go.AddComponent<VRTK.UnityEventHelper.VRTK_Control_UnityEvents>();
-
-			}
-
-
-
-			controlEvents.OnValueChanged.AddListener(HandleChange);
-
-
-
-		}
-
-
-
-		private void HandleChange(object sender, Control3DEventArgs e)
-
-		{
-
-			angle.Value = e.value;
-
-
-
-		}
-
-
-
-	}
-
-
-
-}
-
-
-
-
-
-


remove parameterless constructor

remove parameterless constructor

--- src/dotnet/commands/dotnet-build/Program.cs
+++ src/dotnet/commands/dotnet-build/Program.cs
@@ -15,8 +15,6 @@
     {
         private MSBuildForwardingApp _forwardingApp;

-        private BuildCommand() { }
-
         public BuildCommand(IEnumerable<string> msbuildArgs, string msbuildPath = null)
         {
             _forwardingApp = new MSBuildForwardingApp(msbuildArgs, msbuildPath);
@@ -24,8 +22,6 @@

         public static BuildCommand FromArgs(string[] args, string msbuildPath = null)
         {
-            var buildCommand = new BuildCommand();
-
             CommandLineApplication app = new CommandLineApplication(throwOnUnexpectedArg: false);
             app.Name = "dotnet build";
             app.FullName = LocalizableStrings.AppFullName;
@@ -48,9 +44,12 @@
             CommandOption noDependenciesOption = app.Option("--no-dependencies", LocalizableStrings.NoDependenciesOptionDescription, CommandOptionType.NoValue);
             CommandOption verbosityOption = MSBuildForwardingApp.AddVerbosityOption(app);

+            List<string> msbuildArgs = null;
             app.OnExecute(() =>
             {
-                List<string> msbuildArgs = new List<string>();
+                // this delayed initialization is here intentionally
+                // this code will not get run in some cases (i.e. --help)
+                msbuildArgs = new List<string>();

                 if (!string.IsNullOrEmpty(projectArgument.Value))
                 {
@@ -105,18 +104,16 @@

                 msbuildArgs.AddRange(app.RemainingArguments);

-                buildCommand._forwardingApp = new MSBuildForwardingApp(msbuildArgs, msbuildPath);
-
                 return 0;
             });

             int exitCode = app.Execute(args);
-            if (buildCommand._forwardingApp == null)
+            if (msbuildArgs == null)
             {
                 throw new CommandCreationException(exitCode);
             }

-            return buildCommand;
+            return new BuildCommand(msbuildArgs, msbuildPath);
         }

         public static int Run(string[] args)


refactor out classes, and add some new functionality, remove some stuff that is now up to DocumentSession

--- Elephanet/Store.cs
+++ Elephanet/Store.cs
@@ -6,37 +6,33 @@

 namespace Elephanet
 {
-
     public class DocumentStore : IDocumentStore
     {
         private string _connectionString;
         readonly IStoreConventions _conventions;
         readonly IStoreInfo _storeInfo;
-        private string p;
-        private IStoreInfo testStore;
+        readonly List<string> _tableNames;

         public DocumentStore(string connectionString)
         {
             _connectionString = connectionString;
             _conventions = new StoreConventions();
-            _storeInfo = new StoreInfo();
-            GetOrCreateTable();
+            _storeInfo = new StoreInfo();;
+            _tableNames = new List<string>();
         }

-        public DocumentStore(string connectionString,IStoreConventions conventions)
+        public DocumentStore(string connectionString, IStoreConventions conventions)
         {
             _connectionString = connectionString;
             _conventions = conventions;
             _storeInfo = new StoreInfo();
-            GetOrCreateTable();
         }

-        public DocumentStore(string connectionString,IStoreConventions conventions, IStoreInfo storeInfo)
+        public DocumentStore(string connectionString, IStoreConventions conventions, IStoreInfo storeInfo)
         {
             _connectionString = connectionString;
             _conventions = conventions;
             _storeInfo = storeInfo;
-            GetOrCreateTable();
         }

         public DocumentStore(string connectionString, IStoreInfo storeInfo)
@@ -44,51 +40,11 @@
             _connectionString = connectionString;
             _conventions = new StoreConventions();
             _storeInfo = storeInfo;
-            GetOrCreateTable();
         }
-
-        public void GetOrCreateTable()
-        {
-
-            object _lock = new object();
-            lock (_lock)
-            {
-                var connection = new NpgsqlConnection(_connectionString);
-                try
-                {
-                    connection.Open();
-
-                    using (var command = connection.CreateCommand())
-                    {
-                        command.CommandType = CommandType.Text;
-                        command.CommandText = String.Format(@"
-                            CREATE TABLE IF NOT EXISTS public.{0}
-                            (
-                                id uuid NOT NULL DEFAULT uuid_generate_v1(),
-                                body json NOT NULL,
-                                created time without time zone NOT NULL DEFAULT now(),
-                                row_version integer NOT NULL DEFAULT 1,
-                                CONSTRAINT pk_{0} PRIMARY KEY (id)
-                            );", _storeInfo.Name);
-                        command.ExecuteNonQuery();
-                    }
-                }
-                catch (NpgsqlException exception)
-                {
-                    throw new Exception(String.Format("Could not create table {0}; see the inner exception for more information.", _storeInfo.Name), exception);
-                }
-                finally
-                {
-                    connection.Dispose();
-                }
-            }
-        }
-
-

         public IStoreConventions Conventions { get { return _conventions; }}

-
+        public List<string> TableNames { get {return _tableNames;} }

         public IDocumentSession OpenSession()
         {
@@ -103,20 +59,51 @@
         public  IStoreInfo StoreInfo { get {return _storeInfo;}}

+        public void Destroy()
+        {
+              var connection = new NpgsqlConnection(_connectionString);
+              try
+              {
+                   connection.Open();
+                  foreach (var tablename in StoreInfo.Tables)
+                  {
+                    using (var command = connection.CreateCommand())
+                    {
+                        command.CommandType = CommandType.Text;
+                        command.CommandText = String.Format(@"drop table {0};", tablename);
+                        Console.WriteLine(command.CommandText);
+                        command.ExecuteNonQuery();
+                    }
+                  }
+              }
+
+              catch (NpgsqlException exception)
+              {
+                    throw new Exception(String.Format("Could not drop table {0}; see the inner exception for more information.", _storeInfo.Name), exception);
+              }
+
+              finally
+              {
+                    connection.Dispose();
+              }
+        }

         public void Empty()
         {
-
               var connection = new NpgsqlConnection(_connectionString);
               try
               {
-                    connection.Open();
+                   connection.Open();
+                  foreach (var tablename in StoreInfo.Tables)
+                  {
                     using (var command = connection.CreateCommand())
                     {
                         command.CommandType = CommandType.Text;
-                        command.CommandText = String.Format(@"DELETE FROM public.{0};", _storeInfo.Name);
+                        command.CommandText = String.Format(@"delete from {0};", tablename);
+                        Console.WriteLine(command.CommandText);
                         command.ExecuteNonQuery();
                     }
+                  }
               }

               catch (NpgsqlException exception)
@@ -130,39 +117,4 @@
               }
         }
     }
-
-    public interface IDocumentStore
-    {
-        IDocumentSession OpenSession();
-        string ConnectionString { get; }
-        IStoreConventions Conventions { get; }
-        IStoreInfo StoreInfo { get; }
-        void Empty();
-    }
-
-
-
-    public class StoreInfo : IStoreInfo
-    {
-        private string _name;
-        public StoreInfo()
-        {
-            _name = "store";
-        }
-
-        public StoreInfo(string storeName)
-        {
-            _name = storeName;
-        }
-
-        public string Name { get { return _name; } }
-    }
-
-
-        public interface IStoreInfo
-        {
-            string Name {get;}
-        }
-
-
 }


Change LineEndings enum so that Mixed is unique

--- Ender/EnderTool.cs
+++ Ender/EnderTool.cs
@@ -16,7 +16,7 @@
         public enum LineEnding
         {
             Auto,
-            Mixed = Auto,
+            Mixed,
             Cr,
             Lf,
             CrLf


combine HandleFilteredTypes and HandleOnlyTypes

--- console/Script.cs
+++ console/Script.cs
@@ -67,9 +67,6 @@
 			};

 			var filteredTypes = HandleFilteredTypes();
-			if (!filteredTypes.Any()) {
-				filteredTypes = HandleOnlyTypes();
-			}
 			var namesAndSchemas = HandleDataTables(DataTables);

 			try {
@@ -81,39 +78,24 @@
 		}

 		private List<string> HandleFilteredTypes() {
-			var filteredTypes = FilterTypes?.Split(',').ToList() ?? new List<string>();
+			var removeTypes = FilterTypes?.Split(',').ToList() ?? new List<string>();
+			var keepTypes = OnlyTypes?.Split(',').ToList() ?? new List<string>(Database.Dirs);

-			var anyInvalidType = false;
-			foreach (var filterType in filteredTypes) {
-				if (!Database.Dirs.Contains(filterType)) {
-					_logger.Log(TraceLevel.Warning, $"{filterType} is not a valid type.");
-					anyInvalidType = true;
+			var invalidTypes = removeTypes.Union(keepTypes).Except(Database.Dirs).ToList();
+			if (invalidTypes.Any()) {
+				var msg = invalidTypes.Count() > 1 ? " are not valid types." : " is not a valid type.";
+				_logger.Log(TraceLevel.Warning, String.Join(", ", invalidTypes.ToArray()) + msg);
+				_logger.Log(TraceLevel.Warning, $"Valid types: {Database.ValidTypes}");
+			}
+
+			var filteredTypes = new List<string>();
+			foreach (var dir in Database.Dirs) {
+				if (removeTypes.Contains(dir) || !keepTypes.Contains(dir)) {
+					filteredTypes.Add(dir);
 				}
 			}

-			if (anyInvalidType) {
-				_logger.Log(TraceLevel.Warning, $"Valid types: {Database.ValidTypes}");
-			}
-
 			return filteredTypes;
-		}
-
-		private List<string> HandleOnlyTypes() {
-			var onlyTypes = OnlyTypes?.Split(',').ToList() ?? new List<string>(Database.Dirs);
-
-			var anyInvalidType = false;
-			foreach (var onlyType in onlyTypes) {
-				if (!Database.Dirs.Contains(onlyType)) {
-					_logger.Log(TraceLevel.Warning, $"{onlyType} is not a valid type.");
-					anyInvalidType = true;
-				}
-			}
-
-			if (anyInvalidType) {
-				_logger.Log(TraceLevel.Warning, $"Valid types: {Database.ValidTypes}");
-			}
-
-			return Database.Dirs.Except(onlyTypes).ToList();
 		}

 		private Dictionary<string, string> HandleDataTables(string tableNames) {


:lipstick: Rename Map to FlatMap

:lipstick: Rename Map to FlatMap

--- src/Core/Maybe.cs
+++ src/Core/Maybe.cs
@@ -24,6 +24,6 @@
         public Maybe<TOut> Map<TOut>(Func<T, TOut> map) =>
             hasValue ? new Maybe<TOut>(map(value)) : Maybe<TOut>.Nothing();

-        public Maybe<TOut> Map<TOut>(Func<T, Maybe<TOut>> map) => hasValue ? map(value) : Maybe<TOut>.Nothing();
+        public Maybe<TOut> FlatMap<TOut>(Func<T, Maybe<TOut>> map) => hasValue ? map(value) : Maybe<TOut>.Nothing();
     }
 }


How busy was I with partying hard on Abitur that I didn't care about this.

--- phpBB-IRC-Bridge/Program.cs
+++ phpBB-IRC-Bridge/Program.cs
@@ -147,7 +147,7 @@
             // Identify when NickServ requests it
             _irc.PrivateMessaged += (s, e) =>
             {
-                if (e.From.Nickname == "ChanServ" && e.Text.Contains("This nickname is registered"))
+                if (e.From.Nickname == "NickServ" && e.Text.Contains("This nickname is registered"))
                     _irc.PrivateMessage(new IrcTarget(e.From), string.Format("IDENTIFY {0}", _config.SelectSingleNode("//configuration/nickserv/authentication").InnerText));
                     _irc.PrivateMessage(new IrcTarget("HostServ"), "ON");
             };


When the message is shown, there are times when the butler's image moves (#7)

--- JenkinsOnDesktop/MainWindow.xaml.cs
+++ JenkinsOnDesktop/MainWindow.xaml.cs
@@ -49,6 +49,7 @@

             this.messageText.MouseLeftButtonDown += (sender, e) => ShowSourceUrl();
             this.butlerImage.MouseLeftButtonDown += (sender, e) => MoveWindow();
+            this.configuration.MouseLeftButtonDown += (sender, e) => MoveWindow();
             this.exitButton.Click += (sender, e) => Exit(this.Workspace.Butler);
             this.showConfigurationButton.Click += (sender, e) => ShowConfiguration(this.Workspace.Butler);
             this.parameters.LostFocus += (sender, e) => this.businessExamplesPopup.IsOpen = false;
@@ -291,7 +292,7 @@

         private static void UpdateMessage(Border message, TextBlock messageText, Butler butler)
         {
-            message.Visibility = Visibility.Collapsed;
+            message.Visibility = Visibility.Hidden;
             if (!butler.HasMessage)
             {
                 return;
@@ -435,7 +436,7 @@
             Storyboard storyBoard = CreateFadeAnimation(element, 1.0, 0.0);
             storyBoard.Completed += (sender, e) =>
             {
-                element.Visibility = Visibility.Collapsed;
+                element.Visibility = Visibility.Hidden;
                 element.Opacity = 1.0;
                 if (action != null)
                 {


Document jquery

Document jquery

--- Joinrpg/Views/GameTools/Apis.cshtml
+++ Joinrpg/Views/GameTools/Apis.cshtml
@@ -28,6 +28,10 @@
 </script>

     Также можно подключить дефолтные стили: <var> @RouteHelper.GetFullHostName()/external/joinrpg-api.css </var>
+
+    Обратите внимание: чтобы это работало, необходимо использовать jquery. Если у вас не подключено jquery, подключите его так:
+
<script type="text/javascript" src="https://yastatic.net/jquery/3.1.1/jquery.min.js"></script>

+

Пример результата


コメントを更新

コメントを更新

--- Libraries/Views/Forms/WidgetForm.cs
+++ Libraries/Views/Forms/WidgetForm.cs
@@ -199,9 +199,10 @@
         /// </summary>
         ///
         /// <remarks>
-        /// いくつかのメソッド (メッセージ) では、カスタマイズされた非クライアント
-        /// 領域に関する不都合が存在します。そこで、CreateParams から一時的に
-        /// WS_THICKFRAME 等の値を除去する事によって、この不都合を回避します。
+        /// いくつかのメソッド (メッセージ) では、カスタマイズされた
+        /// 非クライアント領域に関する不都合が存在します。
+        /// そこで、CreateParams から一時的に WS_THICKFRAME 等の値を除去
+        /// する事によって、この不都合を回避します。
         /// </remarks>
         ///
         /* ----------------------------------------------------------------- */


Added forgotten exit timer on RiverShell

--- source/RiverShell/World/RPlayer.cs
+++ source/RiverShell/World/RPlayer.cs
@@ -215,6 +215,14 @@
                     GameMode.ObjectiveReached = true;
                     foreach (var p in All)
                         p.PlaySound(1185);
+
+                    var exitTimer = new Timer(6000, false);
+                    exitTimer.Tick += (sender, args) =>
+                    {
+                        foreach (var p in All)
+                            p.PlaySound(1186);
+                        Native.GameModeExit();
+                    };
                 }
                 else
                 {
@@ -234,6 +242,14 @@
                     GameMode.ObjectiveReached = true;
                     foreach (var p in All)
                         p.PlaySound(1185);
+
+                    var exitTimer = new Timer(6000, false);
+                    exitTimer.Tick += (sender, args) =>
+                    {
+                        foreach (var p in All)
+                            p.PlaySound(1186);
+                        Native.GameModeExit();
+                    };
                 }
                 else
                 {


- Slicer now has a new Mesh generator routine which works with submeshes. Submesh slicing will keep the original submesh and add one more for the cross section.
- This change means that cross sections are no longer generated as child GameObjects but as Submeshes. An alternative API may be added for the GameObjecrt version in the future.

--- EzySlice/Slicer.cs
+++ EzySlice/Slicer.cs
@@ -4,6 +4,14 @@

 namespace EzySlice {
 	public sealed class Slicer {
+
+		/**
+		 * An internal class for storing internal submesh values
+		 */
+		internal class SlicedSubmesh {
+			public readonly List<Triangle> upperHull = new List<Triangle>();
+			public readonly List<Triangle> lowerHull = new List<Triangle>();
+		}

 		/**
 		 * Helper function which will slice the provided object with the provided plane
@@ -86,153 +94,162 @@

 			Vector3[] ve = sharedMesh.vertices;
 			Vector2[] uv = sharedMesh.uv;
-			int[] indices = sharedMesh.triangles;
-
-			int indicesCount = indices.Length;
+
+			int submeshCount = sharedMesh.subMeshCount;
+
+			// each submesh will be sliced and placed in its own array structure
+			SlicedSubmesh[] slices = new SlicedSubmesh[submeshCount];
+			// the cross section hull is common across all submeshes
+			List<Vector3> crossHull = new List<Vector3>();

 			// we reuse this object for all intersection tests
 			IntersectionResult result = new IntersectionResult();

-			// all our buffers, as Triangles
-			List<Triangle> upperHull = new List<Triangle>();
-			List<Triangle> lowerHull = new List<Triangle>();
-			List<Vector3> crossHull = new List<Vector3>();
-
-			// loop through all the mesh vertices, generating upper and lower hulls
-			// and all intersection points
-			for (int index = 0; index < indicesCount; index += 3) {
-				int i0 = indices[index + 0];
-				int i1 = indices[index + 1];
-				int i2 = indices[index + 2];
-
-				Triangle newTri = new Triangle(ve[i0], ve[i1], ve[i2], uv[i0], uv[i1], uv[i2]);
-
-				// slice this particular triangle with the provided
-				// plane
-				if (newTri.Split(pl, result)) {
-					int upperHullCount = result.upperHullCount;
-					int lowerHullCount = result.lowerHullCount;
-					int interHullCount = result.intersectionPointCount;
-
-					for (int i = 0; i < upperHullCount; i++) {
-						upperHull.Add(result.upperHull[i]);
+			// iterate over all the submeshes individually. vertices and indices
+			// are all shared within the submesh
+			for (int submesh = 0; submesh < submeshCount; submesh++) {
+				int[] indices = sharedMesh.GetTriangles(submesh);
+				int indicesCount = indices.Length;
+
+				SlicedSubmesh mesh = new SlicedSubmesh();
+
+				// loop through all the mesh vertices, generating upper and lower hulls
+				// and all intersection points
+				for (int index = 0; index < indicesCount; index += 3) {
+					int i0 = indices[index + 0];
+					int i1 = indices[index + 1];
+					int i2 = indices[index + 2];
+
+					Triangle newTri = new Triangle(ve[i0], ve[i1], ve[i2], uv[i0], uv[i1], uv[i2]);
+
+					// slice this particular triangle with the provided
+					// plane
+					if (newTri.Split(pl, result)) {
+						int upperHullCount = result.upperHullCount;
+						int lowerHullCount = result.lowerHullCount;
+						int interHullCount = result.intersectionPointCount;
+
+						for (int i = 0; i < upperHullCount; i++) {
+							mesh.upperHull.Add(result.upperHull[i]);
+						}
+
+						for (int i = 0; i < lowerHullCount; i++) {
+							mesh.lowerHull.Add(result.lowerHull[i]);
+						}
+
+						for (int i = 0; i < interHullCount; i++) {
+							crossHull.Add(result.intersectionPoints[i]);
+						}
 					}
-
-					for (int i = 0; i < lowerHullCount; i++) {
-						lowerHull.Add(result.lowerHull[i]);
-					}
-
-					for (int i = 0; i < interHullCount; i++) {
-						crossHull.Add(result.intersectionPoints[i]);
+					else {
+						SideOfPlane side = pl.SideOf(ve[i0]);
+
+						if (side == SideOfPlane.UP || side == SideOfPlane.ON) {
+							mesh.upperHull.Add(newTri);
+						}
+						else {
+							mesh.lowerHull.Add(newTri);
+						}
 					}
 				}
-				else {
-					SideOfPlane side = pl.SideOf(ve[i0]);
-
-					if (side == SideOfPlane.UP || side == SideOfPlane.ON) {
-						upperHull.Add(newTri);
-					}
-					else {
-						lowerHull.Add(newTri);
-					}
+
+				// register into the index
+				slices[submesh] = mesh;
+			}
+
+			return CreateFrom(slices, CreateFrom(crossHull, pl.normal));
+		}
+
+		/**
+		 * Generates a single SlicedHull from a set of cut submeshes
+		 */
+		private static SlicedHull CreateFrom(SlicedSubmesh[] meshes, List<Triangle> cross) {
+			int submeshCount = meshes.Length;
+
+			int upperHullCount = 0;
+			int lowerHullCount = 0;
+
+			// get the total amount of upper, lower and intersection counts
+			for (int submesh = 0; submesh < submeshCount; submesh++) {
+				upperHullCount += meshes[submesh].upperHull.Count;
+				lowerHullCount += meshes[submesh].lowerHull.Count;
+			}
+
+			Mesh upperHull = CreateHull(meshes, upperHullCount, cross, true);
+			Mesh lowerHull = CreateHull(meshes, lowerHullCount, cross, false);
+
+			return new SlicedHull(upperHull, lowerHull);
+		}
+
+		/**
+		 * Generate a single Mesh HULL of either the UPPER or LOWER hulls.
+		 */
+		private static Mesh CreateHull(SlicedSubmesh[] meshes, int total, List<Triangle> crossSection, bool isUpper) {
+			if (total <= 0) {
+				return null;
+			}
+
+			int submeshCount = meshes.Length;
+			int crossCount = crossSection != null ? crossSection.Count : 0;
+
+			Mesh newMesh = new Mesh();
+
+			// vertices and uv's are common for all submeshes
+			Vector3[] newVertices = new Vector3[(total + crossCount) * 3];
+			Vector2[] newUvs = new Vector2[(total + crossCount) * 3];
+
+			// each index refers to our submesh triangles
+			List<int[]> triangles = new List<int[]>(submeshCount);
+
+			int vIndex = 0;
+
+			// first we generate all our vertices, uv's and triangles
+			for (int submesh = 0; submesh < submeshCount; submesh++) {
+				// pick the hull we will be playing around with
+				List<Triangle> hull = isUpper ? meshes[submesh].upperHull : meshes[submesh].lowerHull;
+				int hullCount = hull.Count;
+
+				int[] indices = new int[hullCount * 3];
+
+				// fill our mesh arrays
+				for (int i = 0, triIndex = 0; i < hullCount; i++, triIndex += 3) {
+					Triangle newTri = hull[i];
+
+					int i0 = vIndex + 0;
+					int i1 = vIndex + 1;
+					int i2 = vIndex + 2;
+
+					newVertices[i0] = newTri.positionA;
+					newVertices[i1] = newTri.positionB;
+					newVertices[i2] = newTri.positionC;
+
+					newUvs[i0] = newTri.uvA;
+					newUvs[i1] = newTri.uvB;
+					newUvs[i2] = newTri.uvC;
+
+					// triangles are returned in clocwise order from the
+					// intersector, no need to sort these
+					indices[triIndex] = i0;
+					indices[triIndex + 1] = i1;
+					indices[triIndex + 2] = i2;
+
+					vIndex += 3;
 				}
-			}
-
-			// we don't want cross sections,
-			if (!genCrossSection) {
-				// start creating our hulls
-				Mesh finalUpperHullNoCross = CreateFrom(upperHull, null);
-				Mesh finalLowerHullNoCross = CreateFrom(lowerHull, null);
-
-				return new SlicedHull(finalUpperHullNoCross, finalLowerHullNoCross);
-			}
-
-			// we need to generate the cross section if set
-			// NOTE -> This uses a MonotoneChain algorithm which will only work
-			// on cross sections which are Convex
-			List<Triangle> crossSection = CreateFrom(crossHull, pl.normal);
-
-			Mesh finalUpperHull = CreateFrom(upperHull, crossSection, true);
-			Mesh finalLowerHull = CreateFrom(lowerHull, crossSection, false);
-
-			return new SlicedHull(finalUpperHull, finalLowerHull);
-		}
-
-		/**
-		 * Generate Two Meshes (an upper and lower) cross section from a set of intersection
-		 * points and a plane normal. Intersection Points do not have to be in order.
-		 */
-		private static List<Triangle> CreateFrom(List<Vector3> intPoints, Vector3 planeNormal) {
-			List<Triangle> tris;
-
-			if (Triangulator.MonotoneChain(intPoints, planeNormal, out tris)) {
-				return tris;
-			}
-
-			return null;
-		}
-
-		/**
-		 * Generate a mesh from the provided hull made of triangles
-		 * ADDED -> Generate the Cross Section into the same mesh
-		 */
-		private static Mesh CreateFrom(List<Triangle> hull, List<Triangle> crossSection, bool isUpper = true) {
-			int count = crossSection == null ? hull.Count : (hull.Count + crossSection.Count);
-
-			if (count <= 0) {
-				return null;
-			}
-
-			Mesh newMesh = new Mesh();
-
-			int hullCount = hull.Count;
-
-			Vector3[] newVertices = new Vector3[count * 3];
-			Vector2[] newUvs = new Vector2[count * 3];
-			int[] newIndices = new int[hullCount * 3];
-
-			int addedCount = 0;
-
-			// fill our mesh arrays
-			for (int i = 0; i < hullCount; i++) {
-				Triangle newTri = hull[i];
-
-				int i0 = addedCount + 0;
-				int i1 = addedCount + 1;
-				int i2 = addedCount + 2;
-
-				newVertices[i0] = newTri.positionA;
-				newVertices[i1] = newTri.positionB;
-				newVertices[i2] = newTri.positionC;
-
-				newUvs[i0] = newTri.uvA;
-				newUvs[i1] = newTri.uvB;
-				newUvs[i2] = newTri.uvC;
-
-				// triangles are returned in clocwise order from the
-				// intersector, no need to sort these
-				newIndices[i0] = i0;
-				newIndices[i1] = i1;
-				newIndices[i2] = i2;
-
-				addedCount += 3;
-			}
-
-			int[] crossIndices = null;
-
-			// also generate our cross sections
-			if (crossSection != null) {
-				int crossCount = crossSection.Count;
-				int crossIndex = 0;
-
-				crossIndices = new int[crossCount * 3];
-
-				for (int i = 0; i < crossCount; i++) {
+
+				// add triangles to the index for later generation
+				triangles.Add(indices);
+			}
+
+			// generate the cross section required for this particular hull
+			if (crossSection != null && crossCount > 0) {
+				int[] crossIndices = new int[crossCount * 3];
+
+				for (int i = 0, triIndex = 0; i < crossCount; i++, triIndex += 3) {
 					Triangle newTri = crossSection[i];

-					int i0 = addedCount + 0;
-					int i1 = addedCount + 1;
-					int i2 = addedCount + 2;
+					int i0 = vIndex + 0;
+					int i1 = vIndex + 1;
+					int i2 = vIndex + 2;

 					newVertices[i0] = newTri.positionA;
 					newVertices[i1] = newTri.positionB;
@@ -246,38 +263,50 @@
 					// and reversed for lower hulls, to ensure the mesh
 					// is facing the right direction
 					if (isUpper) {
-						crossIndices[crossIndex] = i0;
-						crossIndices[crossIndex + 1] = i1;
-						crossIndices[crossIndex + 2] = i2;
+						crossIndices[triIndex] = i0;
+						crossIndices[triIndex + 1] = i1;
+						crossIndices[triIndex + 2] = i2;
 					}
 					else {
-						crossIndices[crossIndex] = i0;
-						crossIndices[crossIndex + 1] = i2;
-						crossIndices[crossIndex + 2] = i1;
+						crossIndices[triIndex] = i0;
+						crossIndices[triIndex + 1] = i2;
+						crossIndices[triIndex + 2] = i1;
 					}

-					addedCount += 3;
-					crossIndex += 3;
+					vIndex += 3;
 				}
-			}
-
-			newMesh.subMeshCount = 2;
+
+				// add triangles to the index for later generation
+				triangles.Add(crossIndices);
+			}
+
+			int totalTriangles = triangles.Count;
+
+			newMesh.subMeshCount = totalTriangles;
 			// fill the mesh structure
 			newMesh.vertices = newVertices;
 			newMesh.uv = newUvs;

-			// set the first group of triangles
-			newMesh.SetTriangles(newIndices, 0, false);
-
-			// set the cross indices if they exist
-			if (crossIndices != null) {
-				newMesh.SetTriangles(crossIndices, 1, false);
-			}
-
-			// consider computing this array externally instead
-			newMesh.RecalculateNormals();
+			// add the submeshes
+			for (int i = 0; i < totalTriangles; i++) {
+				newMesh.SetTriangles(triangles[i], i, false);
+			}

 			return newMesh;
+		}
+
+		/**
+		 * Generate Two Meshes (an upper and lower) cross section from a set of intersection
+		 * points and a plane normal. Intersection Points do not have to be in order.
+		 */
+		private static List<Triangle> CreateFrom(List<Vector3> intPoints, Vector3 planeNormal) {
+			List<Triangle> tris;
+
+			if (Triangulator.MonotoneChain(intPoints, planeNormal, out tris)) {
+				return tris;
+			}
+
+			return null;
 		}
 	}
 }


- Fixed a bug with normals. Seems I forgot to re-add RecalculateNormals()

--- EzySlice/Slicer.cs
+++ EzySlice/Slicer.cs
@@ -292,6 +292,8 @@
 				newMesh.SetTriangles(triangles[i], i, false);
 			}

+            newMesh.RecalculateNormals();
+
 			return newMesh;
 		}


Fix psicologia parsing (feast day)

Fix psicologia parsing (feast day)

--- LocusPocusBot.Rooms/RoomsService.cs
+++ LocusPocusBot.Rooms/RoomsService.cs
@@ -19,7 +19,7 @@
         public RoomsService(HttpClient client)
         {
             this.client = client;
-
+
             // Take the current date for Italy's timezone
             this.timezone = DateTimeZoneProviders.Tzdb["Europe/Rome"];
             this.today = SystemClock.Instance.InZone(this.timezone).GetCurrentDate();
@@ -237,12 +237,18 @@
                 int[] from = ParseTime(item["from"].ToString());
                 int[] to = ParseTime(item["to"].ToString());

+                // Easter at Psicologia and maybe other feast days
+                if (to[0] == 24 && to[1] == 00)
+                {
+                    to = new[] { 23, 59 };
+                }
+
                 LocalDateTime start = this.today.At(new LocalTime(from[0], from[1], 0));
                 LocalDateTime end = this.today.At(new LocalTime(to[0], to[1], 0));

                 Instant startInstant = start.InZoneStrictly(this.timezone).ToInstant();
                 Instant endInstant = end.InZoneStrictly(this.timezone).ToInstant();
-
+
                 Lecture lec = new Lecture(item["name"].ToString(), startInstant, endInstant);

                 string roomId = item["CodiceAula"].ToString();


test 4 resolving named dependencies in GetAll

--- Maestro.Tests/resolve_enumerable.cs
+++ Maestro.Tests/resolve_enumerable.cs
@@ -1,4 +1,5 @@
 using FluentAssertions;
+using System.Linq;
 using Xunit;

 namespace Maestro.Tests
@@ -12,5 +13,37 @@

 			enumerable.Should().BeEmpty();
 		}
+
+		[Fact]
+		public void should_try_to_get_dependencies_with_same_name_as_top_instance()
+		{
+			var @defaultDependency = "default";
+			var namedDependency = "named";
+
+			var name = "yada yada";
+			var container = new Container(x =>
+			{
+				x.Add<Foo>().As<Foo>();
+				x.Add<Foo>(name).As<Foo>();
+
+				x.Default<object>().Is(@defaultDependency);
+				x.Add<object>(name).As(namedDependency);
+			});
+
+			var foos = container.GetAll<Foo>().ToList();
+
+			foos.Should().Contain(x => x.Object == defaultDependency);
+			foos.Should().Contain(x => x.Object == namedDependency);
+		}
+
+		private class Foo
+		{
+			public Foo(object o)
+			{
+				Object = o;
+			}
+
+			public object Object { get; private set; }
+		}
 	}
 }


Removed old work-around for bad GMail BODY responses

This shouldn't be necessary anymore since ImapUtils.ParseBody()
now has more useful work-arounds.

--- MailKit/Net/Imap/ImapFolderFetch.cs
+++ MailKit/Net/Imap/ImapFolderFetch.cs
@@ -253,31 +253,9 @@

 						message.Fields |= MessageSummaryItems.References;
 					} else {
-						try {
-							format = string.Format (ImapEngine.GenericItemSyntaxErrorFormat, "BODY", "{0}");
-							message.Body = await ImapUtils.ParseBodyAsync (engine, format, string.Empty, doAsync, ic.CancellationToken).ConfigureAwait (false);
-							message.Fields |= MessageSummaryItems.Body;
-						} catch (ImapProtocolException ex) {
-							if (!ex.UnexpectedToken)
-								throw;
-
-							// Note: GMail's IMAP implementation sometimes replies with completely broken BODY values
-							// (see issue #32 for the `BODY ("ALTERNATIVE")` example), so to work around this nonsense,
-							// we need to drop the remainder of this line.
-							do {
-								token = await engine.PeekTokenAsync (doAsync, ic.CancellationToken).ConfigureAwait (false);
-
-								if (token.Type == ImapTokenType.Eoln)
-									break;
-
-								token = await engine.ReadTokenAsync (doAsync, ic.CancellationToken).ConfigureAwait (false);
-
-								if (token.Type == ImapTokenType.Literal)
-									await ReadLiteralDataAsync (engine, doAsync, ic.CancellationToken).ConfigureAwait (false);
-							} while (true);
-
-							return;
-						}
+						format = string.Format (ImapEngine.GenericItemSyntaxErrorFormat, "BODY", "{0}");
+						message.Body = await ImapUtils.ParseBodyAsync (engine, format, string.Empty, doAsync, ic.CancellationToken).ConfigureAwait (false);
+						message.Fields |= MessageSummaryItems.Body;
 					}
 					break;
 				case "ENVELOPE":


Unit test works on local but failed on CI. Try to investigate.

--- MangaRipper.Core/MangaFoxService.cs
+++ MangaRipper.Core/MangaFoxService.cs
@@ -60,6 +60,7 @@
                 new Progress<int>((count) =>
                 {
                     Trace.WriteLine("FindImanges > Count: " + count);
+                    Trace.WriteLine("FindImanges > Pages.Count: " + pages.Count);
                     var f = (float) count / pages.Count;
                     Trace.WriteLine("FindImanges > Float: " + f);
                     int i = Convert.ToInt32(f * 100);


Draw map edge guide lines in ImageLayerView

--- Mappy/UI/Controls/ImageLayerView.cs
+++ Mappy/UI/Controls/ImageLayerView.cs
@@ -244,6 +244,16 @@
                 }
             }

+            // draw guides
+            using (var guidePen = new Pen(Color.Magenta, 3.0f))
+            {
+                var horizLinePos = this.CanvasSize.Height - 128;
+                pe.Graphics.DrawLine(guidePen, 0, horizLinePos, this.CanvasSize.Width, horizLinePos);
+
+                int vertLinePos = this.CanvasSize.Width - 32;
+                pe.Graphics.DrawLine(guidePen, vertLinePos, 0, vertLinePos, this.CanvasSize.Height);
+            }
+
             // draw selection rectangles
             foreach (var i in this.selectedItems)
             {


Make TestNestedKill threadsafe

Make TestNestedKill threadsafe

--- MedallionShell.Tests/GeneralTest.cs
+++ MedallionShell.Tests/GeneralTest.cs
@@ -328,7 +328,7 @@
         [Test]
         public void TestNestedKill()
         {
-            var lines = new List<string>();
+            var lines = new SyncCollection();
             var pipeline = TestShell.Run(SampleCommand, "pipe")
                 | TestShell.Run(SampleCommand, "pipe")
                 | TestShell.Run(SampleCommand, "pipe") > lines;
@@ -342,7 +342,7 @@
                 if (lines.Count > 0) { break; }
                 Thread.Sleep(10);
             }
-            lines[0].ShouldEqual("a line");
+            lines.First().ShouldEqual("a line");

             pipeline.Task.IsCompleted.ShouldEqual(false);
             pipeline.Kill();


- Adding link to Chat service deprecation blog post

--- Mixer.Base/Services/ChatsService.cs
+++ Mixer.Base/Services/ChatsService.cs
@@ -11,6 +11,9 @@
     /// </summary>
     public class ChatsService : MixerServiceBase
     {
+        /// <summary>
+        /// https://dev.mixer.com/content/blog/chatlistdeprecations
+        /// </summary>
         private class ChatsV2Service : MixerServiceBase
         {
             /// <summary>


updated assembly info

updated assembly info

--- ModTools/Properties/AssemblyInfo.cs
+++ ModTools/Properties/AssemblyInfo.cs
@@ -5,12 +5,12 @@
 // 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("ModFramework")]
-[assembly: AssemblyDescription("")]
+[assembly: AssemblyTitle("ModTools")]
+[assembly: AssemblyDescription("Parkitect Game Modification")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("ModFramework")]
-[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyProduct("ModTools")]
+[assembly: AssemblyCopyright("Copyright © ParkitectNexus 2015, Portions Copyright © Martin 'yokumo' Kelm 2015")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]


added test to verify query syntax works with select

--- NOtherLookup.Tests/Lookup_Select.cs
+++ NOtherLookup.Tests/Lookup_Select.cs
@@ -16,6 +16,27 @@

         Because of = () =>
             filtered = lookup.Select(x => x.Where(e => e > 3));
+
+        It should_filter_out_values_according_to_predicate = () =>
+        {
+            filtered.Count.ShouldEqual(1);
+            filtered["b"].ShouldContainExactly(4);
+        };
+
+        private static ILookup<string, int> lookup, filtered;
+    }
+
+    [Subject("ILookup.Select")]
+    public class When_filtering_lookup_by_values_using_query_syntax
+    {
+        Establish context = () =>
+            lookup = Lookup.Builder
+                .WithKey("a", new[] { 1, 3 })
+                .WithKey("b", new[] { 2, 4 }).Build();
+
+        Because of = () =>
+            filtered = from x in lookup
+                       select x.Where(e => e > 3);

         It should_filter_out_values_according_to_predicate = () =>
         {


changed to version 1.1

changed to version 1.1

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


implementing TXService.appendStatements for WP8

--- src/wp8/KirinWP8/Core/TXService.cs
+++ src/wp8/KirinWP8/Core/TXService.cs
@@ -133,6 +133,41 @@
                 _Type = SQLOperationType.JSON
             };
             GetStatements(dbId, txId).Add(s);
+        }
+
+
+        public void appendStatements(int dbId, int txId, int[] returnTypes, int[] statementIds, string[] statements, string[] txParams)
+        {
+            for (int i = 0; i < returnTypes.Length; i++)
+            {
+                string[] deserParams = JsonConvert.DeserializeObject<string[]>(txParams[i]);
+                int returnType = returnTypes[i];
+                switch (returnType)
+                {
+                    case 0: // Rows
+                        appendStatementForRows(dbId, txId, statementIds[i], statements[i], deserParams);
+                        break;
+
+                    case 1: // Token
+                        appendStatementForToken(dbId, txId, statementIds[i], statements[i], deserParams);
+                        break;
+
+                    case 2: // JSON
+                        appendStatementForJSON(dbId, txId, statementIds[i], statements[i], deserParams);
+                        break;
+
+                    case 3: // Batch
+                        TXStatement s = new TXStatement()
+                        {
+                            _HasId = false,
+                            _Parameters = null,
+                            _Statement = statements[i],
+                            _Type = SQLOperationType.Batch
+                        };
+                        GetStatements(dbId, txId).Add(s);
+                        break;
+                }
+            }
         }

         public void appendBatch(int dbId, int txId, string[] batch)


Small bug in dupe detection.

Small bug in dupe detection.

--- src/PhotoStore.cs
+++ src/PhotoStore.cs
@@ -115,7 +115,7 @@
 		foreach (Photo match in md5_matches)
 		{
 			var file2 = GLib.FileFactory.NewForUri (match.DefaultVersionUri);
-			var info2 = file.QueryInfo ("standard::content-type", GLib.FileQueryInfoFlags.None, null);
+			var info2 = file2.QueryInfo ("standard::content-type", GLib.FileQueryInfoFlags.None, null);

 			// same mimetype?
 			if (info.ContentType != info2.ContentType)


Enhance NullEstateData to remember stored estate values and return them next time asked. This keeps any estate settings from being reset when the estate dialog is opened in a region with null estate storage.

--- OpenSim/Data/Null/NullEstateData.cs
+++ OpenSim/Data/Null/NullEstateData.cs
@@ -42,6 +42,22 @@

 //        private string m_connectionString;

+        private Dictionary<uint, EstateSettings> m_knownEstates = new Dictionary<uint, EstateSettings>();
+        private EstateSettings m_estate = null;
+
+        private EstateSettings GetEstate()
+        {
+            if (m_estate == null)
+            {
+                // This fools the initialization caller into thinking an estate was fetched (a check in OpenSimBase).
+                // The estate info is pretty empty so don't try banning anyone.
+                m_estate = new EstateSettings();
+                m_estate.EstateID = 1;
+                m_estate.OnSave += StoreEstateSettings;
+            }
+            return m_estate;
+        }
+
         protected virtual Assembly Assembly
         {
             get { return GetType().Assembly; }
@@ -68,21 +84,18 @@

         public EstateSettings LoadEstateSettings(UUID regionID, bool create)
         {
-            // This fools the initialization caller into thinking an estate was fetched (a check in OpenSimBase).
-            // The estate info is pretty empty so don't try banning anyone.
-            EstateSettings oneEstate = new EstateSettings();
-            oneEstate.EstateID = 1;
-            return oneEstate;
+            return GetEstate();
         }

         public void StoreEstateSettings(EstateSettings es)
         {
+            m_estate = es;
             return;
         }

         public EstateSettings LoadEstateSettings(int estateID)
         {
-            return new EstateSettings();
+            return GetEstate();
         }

         public EstateSettings CreateNewEstate()
@@ -93,13 +106,14 @@
         public List<EstateSettings> LoadEstateSettingsAll()
         {
             List<EstateSettings> allEstateSettings = new List<EstateSettings>();
-            allEstateSettings.Add(new EstateSettings());
+            allEstateSettings.Add(GetEstate());
             return allEstateSettings;
         }

         public List<int> GetEstatesAll()
         {
             List<int> result = new List<int>();
+            result.Add((int)GetEstate().EstateID);
             return result;
         }


[Feature] Trackable Race Conditions

[Feature] Trackable Race Conditions

--- src/Chinchilla/TrackableFactory.cs
+++ src/Chinchilla/TrackableFactory.cs
@@ -7,27 +7,45 @@
     public abstract class TrackableFactory<TTrackable> : IDisposable
         where TTrackable : Trackable
     {
+        private readonly object trackLock = new object();
+
         private readonly List<TTrackable> trackables = new List<TTrackable>();

         public IEnumerable<TTrackable> Tracked
         {
-            get { return trackables; }
+            get
+            {
+                lock (trackLock)
+                {
+                    return trackables.ToArray();
+                }
+            }
         }

         public bool IsTracking(TTrackable trackable)
         {
-            return trackables.Contains(trackable);
+            lock (trackLock)
+            {
+                return trackables.Contains(trackable);
+            }
         }

         protected void Track(TTrackable trackable)
         {
             trackable.Disposed += Untrack;
-            trackables.Add(trackable);
+
+            lock (trackLock)
+            {
+                trackables.Add(trackable);
+            }
         }

         private void Untrack(TTrackable trackable)
         {
-            trackables.Remove(trackable);
+            lock (trackLock)
+            {
+                trackables.Remove(trackable);
+            }
         }

         private void Untrack(object sender, EventArgs eventArgs)


Restore perspective after Generate button creates new children

- Hook meshViewer close and persist world transforms if visible
- Apply meshViewer world transforms on load if initialized
- Release event handlers on load if initialized (must occur after Close)

--- PartPreviewWindow/ViewGcodeBasic.cs
+++ PartPreviewWindow/ViewGcodeBasic.cs
@@ -167,13 +167,23 @@

 		private void CreateAndAddChildren()
 		{
-			TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory();
-			textImageButtonFactory.normalTextColor = ActiveTheme.Instance.PrimaryTextColor;
-			textImageButtonFactory.hoverTextColor = ActiveTheme.Instance.PrimaryTextColor;
-			textImageButtonFactory.disabledTextColor = ActiveTheme.Instance.PrimaryTextColor;
-			textImageButtonFactory.pressedTextColor = ActiveTheme.Instance.PrimaryTextColor;
+			var textImageButtonFactory = new TextImageButtonFactory()
+			{
+				normalTextColor = ActiveTheme.Instance.PrimaryTextColor,
+				hoverTextColor = ActiveTheme.Instance.PrimaryTextColor,
+				disabledTextColor = ActiveTheme.Instance.PrimaryTextColor,
+				pressedTextColor = ActiveTheme.Instance.PrimaryTextColor
+			};

 			CloseAllChildren();
+
+			if (meshViewerWidget != null)
+			{
+				meshViewerWidget.Closed -= MeshViewerWidget_Closed;
+				meshViewerWidget.TrackballTumbleWidget.DrawGlContent -= TrackballTumbleWidget_DrawGlContent;
+			}
+
+			meshViewerWidget = null;
 			gcodeViewWidget = null;
 			gcodeProcessingStateInfoText = null;

@@ -298,12 +308,22 @@
 			mainContainerTopToBottom.AddChild(buttonBottomPanel);
 			this.AddChild(mainContainerTopToBottom);

-			meshViewerWidget = new MeshViewerWidget(viewerVolume, bedCenter, bedShape, "".Localize());
+			meshViewerWidget = new MeshViewerWidget(viewerVolume, bedCenter, bedShape, "")
+			{
+				Visible = (activeViewMode == PartViewMode.Layers3D),
+				AllowBedRenderingWhenEmpty = true
+			};
 			meshViewerWidget.AnchorAll();
-			meshViewerWidget.AllowBedRenderingWhenEmpty = true;
 			gcodeDisplayWidget.AddChild(meshViewerWidget);
-			meshViewerWidget.Visible = (activeViewMode == PartViewMode.Layers3D);
-			meshViewerWidget.TrackballTumbleWidget.DrawGlContent += new EventHandler(TrackballTumbleWidget_DrawGlContent);
+			meshViewerWidget.TrackballTumbleWidget.DrawGlContent += TrackballTumbleWidget_DrawGlContent;
+			meshViewerWidget.Closed += MeshViewerWidget_Closed;
+
+			// Apply active world view if initialized
+			if (ApplicationController.Instance.PartPreviewState.RotationMatrix != Matrix4X4.Identity)
+			{
+				meshViewerWidget.World.RotationMatrix = ApplicationController.Instance.PartPreviewState.RotationMatrix;
+				meshViewerWidget.World.TranslationMatrix = ApplicationController.Instance.PartPreviewState.TranslationMatrix;
+			}

 			viewControls3D.ResetView += (sender, e) =>
 			{
@@ -319,10 +339,12 @@

 			viewControls3D.ActiveButton = ViewControls3DButtons.Rotate;

-			viewControlsToggle = new ViewControlsToggle(ApplicationController.Instance.Theme.ViewControlsButtonFactory, activeViewMode);
-			viewControlsToggle.HAnchor = HAnchor.ParentRight;
+			viewControlsToggle = new ViewControlsToggle(ApplicationController.Instance.Theme.ViewControlsButtonFactory, activeViewMode)
+			{
+				Visible = false,
+				HAnchor = HAnchor.ParentRight
+			};
 			AddChild(viewControlsToggle);
-			viewControlsToggle.Visible = false;

 			viewControls3D.TransformStateChanged += (s, e) =>
 			{
@@ -353,6 +375,15 @@
 			expandDisplayOptions.CheckedStateChanged += expandDisplayOptions_CheckedStateChanged;
 		}

+		private void MeshViewerWidget_Closed(object sender, ClosedEventArgs e)
+		{
+			if (meshViewerWidget.Visible)
+			{
+				ApplicationController.Instance.PartPreviewState.RotationMatrix = meshViewerWidget.World.RotationMatrix;
+				ApplicationController.Instance.PartPreviewState.TranslationMatrix = meshViewerWidget.World.TranslationMatrix;
+			}
+		}
+
 		private RenderType GetRenderType()
 		{
 			RenderType renderType = RenderType.Extrusions;


Minor DB changes...

Minor DB changes...

--- PolarisServer/Database/PolarisDB.cs
+++ PolarisServer/Database/PolarisDB.cs
@@ -51,11 +51,11 @@

         private void GenerateTables()
         {
-            new MySqlCommand("CREATE TABLE IF NOT EXISTS ServerInfo(name TEXT NOT NULL PRIMARY KEY, data BLOB)", connection).ExecuteNonQuery();
+            new MySqlCommand("CREATE TABLE IF NOT EXISTS ServerInfo(name VARCHAR(128) NOT NULL PRIMARY KEY, data TEXT)", connection).ExecuteNonQuery();
             new MySqlCommand("CREATE TABLE IF NOT EXISTS Players(PlayerID INTEGER NOT NULL, LoginID TEXT NOT NULL, " +
                 "Password TEXT NOT NULL, Nickname TEXT NOT NULL, Prefrences BLOB, PRIMARY KEY(PlayerID))", connection).ExecuteNonQuery();
             new MySqlCommand("CREATE TABLE IF NOT EXISTS Characters(CharacterID INTEGER NOT NULL, PlayerID INTEGER NOT NULL, " +
-                "Name TEXT, JobParam BLOB, LooksParam BLOB, PRIMARY KEY(CharacterID), FOREIGN KEY (PlayerID) REFRENCES Players(PlayerID))", connection).ExecuteNonQuery();
+                "Name TEXT, JobParam BLOB, LooksParam BLOB, PRIMARY KEY(CharacterID), FOREIGN KEY (PlayerID) REFERENCES Players(PlayerID))", connection).ExecuteNonQuery();
         }

         public void AddServerinfo(string name, object value)


Dump rational values from CorePhotoInfo

Dump rational values from CorePhotoInfo

--- src/CorePhotoInfo/Tiff/TiffDump.cs
+++ src/CorePhotoInfo/Tiff/TiffDump.cs
@@ -64,7 +64,7 @@
                         return TiffReader.GetInteger(entry, byteOrder).ToString();
                     else
                     {
-                        uint[] array = TiffReader.ReadIntegerArray(entry, _stream, byteOrder);
+                        var array = TiffReader.ReadIntegerArray(entry, _stream, byteOrder);
                         return ConvertArrayToString(array);
                     }
                 case TiffType.SByte:
@@ -74,11 +74,27 @@
                         return TiffReader.GetSignedInteger(entry, byteOrder).ToString();
                     else
                     {
-                        int[] array = TiffReader.ReadSignedIntegerArray(entry, _stream, byteOrder);
+                        var array = TiffReader.ReadSignedIntegerArray(entry, _stream, byteOrder);
                         return ConvertArrayToString(array);
                     }
                 case TiffType.Ascii:
                     return "\"" + TiffReader.ReadString(entry, _stream, byteOrder) + "\"";
+                case TiffType.Rational:
+                    if (entry.Count == 1)
+                        return TiffReader.ReadRational(entry, _stream, byteOrder).ToString();
+                    else
+                    {
+                        var array = TiffReader.ReadRationalArray(entry, _stream, byteOrder);
+                        return ConvertArrayToString(array);
+                    }
+                case TiffType.SRational:
+                    if (entry.Count == 1)
+                        return TiffReader.ReadSignedRational(entry, _stream, byteOrder).ToString();
+                    else
+                    {
+                        var array = TiffReader.ReadSignedRationalArray(entry, _stream, byteOrder);
+                        return ConvertArrayToString(array);
+                    }
                 default:
                     return "Unknown Type";
             }


More work around #85

More work around #85

--- PushSharp.Apple/ApplePushChannel.cs
+++ PushSharp.Apple/ApplePushChannel.cs
@@ -285,8 +285,9 @@
 					//See if anything is here to process
 					if (sentNotifications.Count > 0)
 					{
-						//Don't expire any notifications while we are in a connecting state
-						if (connected || CancelToken.IsCancellationRequested)
+						//Don't expire any notifications while we are in a connecting state, o rat least ensure all notifications have been sent
+						// in case we may have no connection because no notifications were causing a connection to be initiated
+						if ((connected || CancelToken.IsCancellationRequested) || (!connected && QueuedNotificationCount <= 0))
 						{
 							//Get the oldest sent message
 							var n = sentNotifications[0];


Fix release/debug build detection.

Fix release/debug build detection.

Change release/debug build detection from linker setting
GenerateDebugInformation to compiler RuntimeLibrary setting
(debug in case of rtMultiThreadedDebug or rtMultiThreadedDebugDLL,
release otherwise).

Task-number: QTVSADDINBUG-350
Change-Id: If698648f0a2511b0d32a2a123947fb476af518a3
Reviewed-by: Joerg Bornemann <47777b9406dbddd02a3fdca8341789a013805a11@digia.com>
Reviewed-by: Ismo Haataja <391161c82ffa2bbb3957f6ad8701582c491da8ea@digia.com>

--- Qt4VS2003/QtProjectLib/QtProject.cs
+++ Qt4VS2003/QtProjectLib/QtProject.cs
@@ -876,8 +876,9 @@

         private static bool IsDebugConfiguration(VCConfiguration conf)
         {
-            VCLinkerTool linker = (VCLinkerTool)((IVCCollection)conf.Tools).Item("VCLinkerTool");
-            if (linker != null && linker.GenerateDebugInformation == true)
+            VCCLCompilerTool compiler = (VCCLCompilerTool)((IVCCollection)conf.Tools).Item("VCCLCompilerTool");
+            if (compiler != null && (compiler.RuntimeLibrary == runtimeLibraryOption.rtMultiThreadedDebug ||
+                compiler.RuntimeLibrary == runtimeLibraryOption.rtMultiThreadedDebugDLL))
                 return true;
             return false;
         }


Added dereference Uri for CIDOC CRM

Added dereference Uri for CIDOC CRM

--- RDFSharp/Model/RDFModelUtilities.cs
+++ RDFSharp/Model/RDFModelUtilities.cs
@@ -86,8 +86,11 @@
         {
             string uriString = uri?.ToString() ?? string.Empty;

+            //Cidoc CRM (http://www.cidoc-crm.org/cidoc-crm/)
+            if (uriString.Equals(RDFVocabulary.CRM.BASE_URI))
+                uri = new Uri(RDFVocabulary.CRM.DEREFERENCE_URI);
             //DublinCore Elements (http://purl.org/dc/elements/1.1/)
-            if (uriString.Equals(RDFVocabulary.DC.BASE_URI))
+            else if (uriString.Equals(RDFVocabulary.DC.BASE_URI))
                 uri = new Uri(RDFVocabulary.DC.DEREFERENCE_URI);
             //DublinCore Abstract Model (http://purl.org/dc/dcam/)
             else if (uriString.Equals(RDFVocabulary.DC.DCAM.BASE_URI))


Fix line width for Excel export

Fix line width for Excel export

--- RdlEngine/Render/RenderExcel2007.cs
+++ RdlEngine/Render/RenderExcel2007.cs
@@ -435,7 +435,12 @@

 		public void Line(Line l, Row row)
 		{
-			float borderWidth = l.Style.BorderWidth.EvalDefault(report, row);
+			float borderWidth = 1;
+			if(l.Style.BorderWidth != null) {
+				borderWidth = l.Style.BorderWidth.EvalDefault(report, row);
+			} else if(l.Style.BorderStyle != null) {
+				borderWidth = (float)l.Style.BorderStyle.EvalDefault(report, row);
+			}
 			excelBuilder.AddLine(l, borderWidth);

 		}


Removed exception handling from the control.

--- ReClass.NET/UI/MemoryViewControl.cs
+++ ReClass.NET/UI/MemoryViewControl.cs
@@ -9,7 +9,6 @@
 using ReClassNET.Extensions;
 using ReClassNET.Memory;
 using ReClassNET.Nodes;
-using ReClassNET.Project;
 using ReClassNET.Util;

 namespace ReClassNET.UI
@@ -219,6 +218,8 @@
 			catch (Exception)
 			{
 				Debug.Assert(false);
+
+				throw;
 			}
 		}

@@ -239,149 +240,142 @@
 			{
 				if (hotSpot.Rect.Contains(e.Location))
 				{
-					try
-					{
-						var hitObject = hotSpot.Node;
-
-						if (hotSpot.Type == HotSpotType.OpenClose)
+					var hitObject = hotSpot.Node;
+
+					if (hotSpot.Type == HotSpotType.OpenClose)
+					{
+						hitObject.ToggleLevelOpen(hotSpot.Level);
+
+						invalidate = true;
+
+						break;
+					}
+					if (hotSpot.Type == HotSpotType.Click)
+					{
+						hitObject.Update(hotSpot);
+
+						invalidate = true;
+
+						break;
+					}
+					if (hotSpot.Type == HotSpotType.Select)
+					{
+						if (e.Button == MouseButtons.Left)
 						{
-							hitObject.ToggleLevelOpen(hotSpot.Level);
-
-							invalidate = true;
-
-							break;
+							if (ModifierKeys == Keys.None)
+							{
+								ClearSelection();
+
+								hitObject.IsSelected = true;
+
+								selectedNodes.Add(hotSpot);
+
+								OnSelectionChanged();
+
+								selectionAnchor = selectionCaret = hotSpot;
+							}
+							else if (ModifierKeys == Keys.Control)
+							{
+								hitObject.IsSelected = !hitObject.IsSelected;
+
+								if (hitObject.IsSelected)
+								{
+									selectedNodes.Add(hotSpot);
+								}
+								else
+								{
+									selectedNodes.Remove(selectedNodes.FirstOrDefault(c => c.Node == hitObject));
+								}
+
+								OnSelectionChanged();
+							}
+							else if (ModifierKeys == Keys.Shift)
+							{
+								if (selectedNodes.Count > 0)
+								{
+									var selectedNode = selectedNodes[0].Node;
+									if (hitObject.GetParentContainer() != null && selectedNode.GetParentContainer() != hitObject.GetParentContainer())
+									{
+										continue;
+									}
+
+									if (hotSpot.Node is BaseContainerNode)
+									{
+										continue;
+									}
+
+									var first = Utils.Min(selectedNodes[0], hotSpot, h => h.Node.Offset.ToInt32());
+									var last = first == hotSpot ? selectedNodes[0] : hotSpot;
+
+									ClearSelection();
+
+									var containerNode = selectedNode.GetParentContainer();
+									foreach (var spot in containerNode.Nodes
+										.SkipWhile(n => n != first.Node)
+										.TakeUntil(n => n == last.Node)
+										.Select(n => new HotSpot
+										{
+											Address = containerNode.Offset.Add(n.Offset),
+											Node = n,
+											Memory = first.Memory,
+											Level = first.Level
+										}))
+									{
+										spot.Node.IsSelected = true;
+										selectedNodes.Add(spot);
+									}
+
+									OnSelectionChanged();
+
+									selectionAnchor = first;
+									selectionCaret = last;
+								}
+							}
 						}
-						if (hotSpot.Type == HotSpotType.Click)
+						else if (e.Button == MouseButtons.Right)
 						{
-							hitObject.Update(hotSpot);
-
-							invalidate = true;
-
-							break;
+							// If there is only one selected node, select the node the user clicked at.
+							if (selectedNodes.Count <= 1)
+							{
+								ClearSelection();
+
+								hitObject.IsSelected = true;
+
+								selectedNodes.Add(hotSpot);
+
+								OnSelectionChanged();
+
+								selectionAnchor = selectionCaret = hotSpot;
+							}
+
+							ShowNodeContextMenu(e.Location);
 						}
-						if (hotSpot.Type == HotSpotType.Select)
-						{
-							if (e.Button == MouseButtons.Left)
-							{
-								if (ModifierKeys == Keys.None)
-								{
-									ClearSelection();
-
-									hitObject.IsSelected = true;
-
-									selectedNodes.Add(hotSpot);
-
-									OnSelectionChanged();
-
-									selectionAnchor = selectionCaret = hotSpot;
-								}
-								else if (ModifierKeys == Keys.Control)
-								{
-									hitObject.IsSelected = !hitObject.IsSelected;
-
-									if (hitObject.IsSelected)
-									{
-										selectedNodes.Add(hotSpot);
-									}
-									else
-									{
-										selectedNodes.Remove(selectedNodes.FirstOrDefault(c => c.Node == hitObject));
-									}
-
-									OnSelectionChanged();
-								}
-								else if (ModifierKeys == Keys.Shift)
-								{
-									if (selectedNodes.Count > 0)
-									{
-										var selectedNode = selectedNodes[0].Node;
-										if (hitObject.GetParentContainer() != null && selectedNode.GetParentContainer() != hitObject.GetParentContainer())
-										{
-											continue;
-										}
-
-										if (hotSpot.Node is BaseContainerNode)
-										{
-											continue;
-										}
-
-										var first = Utils.Min(selectedNodes[0], hotSpot, h => h.Node.Offset.ToInt32());
-										var last = first == hotSpot ? selectedNodes[0] : hotSpot;
-
-										ClearSelection();
-
-										var containerNode = selectedNode.GetParentContainer();
-										foreach (var spot in containerNode.Nodes
-											.SkipWhile(n => n != first.Node)
-											.TakeUntil(n => n == last.Node)
-											.Select(n => new HotSpot
-											{
-												Address = containerNode.Offset.Add(n.Offset),
-												Node = n,
-												Memory = first.Memory,
-												Level = first.Level
-											}))
-										{
-											spot.Node.IsSelected = true;
-											selectedNodes.Add(spot);
-										}
-
-										OnSelectionChanged();
-
-										selectionAnchor = first;
-										selectionCaret = last;
-									}
-								}
-							}
-							else if (e.Button == MouseButtons.Right)
-							{
-								// If there is only one selected node, select the node the user clicked at.
-								if (selectedNodes.Count <= 1)
-								{
-									ClearSelection();
-
-									hitObject.IsSelected = true;
-
-									selectedNodes.Add(hotSpot);
-
-									OnSelectionChanged();
-
-									selectionAnchor = selectionCaret = hotSpot;
-								}
-
-								ShowNodeContextMenu(e.Location);
-							}
-
-							invalidate = true;
-						}
-						else if (hotSpot.Type == HotSpotType.Drop)
-						{
-							ShowNodeContextMenu(e.Location);
-
-							break;
-						}
-						else if (hotSpot.Type == HotSpotType.Delete)
-						{
-							hotSpot.Node.GetParentContainer().RemoveNode(hotSpot.Node);
-
-							invalidate = true;
-
-							break;
-						}
-						else if (hotSpot.Type == HotSpotType.ChangeClassType || hotSpot.Type == HotSpotType.ChangeWrappedType || hotSpot.Type == HotSpotType.ChangeEnumType)
-						{
-							var handler = hotSpot.Type == HotSpotType.ChangeClassType
-								? ChangeClassTypeClick : hotSpot.Type == HotSpotType.ChangeWrappedType
-									? ChangeWrappedTypeClick : ChangeEnumTypeClick;
-
-							handler?.Invoke(this, new NodeClickEventArgs(hitObject, hotSpot.Address, hotSpot.Memory, e.Button, e.Location));
-
-							break;
-						}
-					}
-					catch (Exception ex)
-					{
-						Program.Logger.Log(ex);
+
+						invalidate = true;
+					}
+					else if (hotSpot.Type == HotSpotType.Drop)
+					{
+						ShowNodeContextMenu(e.Location);
+
+						break;
+					}
+					else if (hotSpot.Type == HotSpotType.Delete)
+					{
+						hotSpot.Node.GetParentContainer().RemoveNode(hotSpot.Node);
+
+						invalidate = true;
+
+						break;
+					}
+					else if (hotSpot.Type == HotSpotType.ChangeClassType || hotSpot.Type == HotSpotType.ChangeWrappedType || hotSpot.Type == HotSpotType.ChangeEnumType)
+					{
+						var handler = hotSpot.Type == HotSpotType.ChangeClassType
+							? ChangeClassTypeClick : hotSpot.Type == HotSpotType.ChangeWrappedType
+								? ChangeWrappedTypeClick : ChangeEnumTypeClick;
+
+						handler?.Invoke(this, new NodeClickEventArgs(hitObject, hotSpot.Address, hotSpot.Memory, e.Button, e.Location));
+
+						break;
 					}
 				}
 			}


Beefed up an Intersect test.

Beefed up an Intersect test.

--- src/Edulinq.Tests/IntersectTest.cs
+++ src/Edulinq.Tests/IntersectTest.cs
@@ -85,7 +85,11 @@
             var first = new ThrowingEnumerable();
             var second = new ThrowingEnumerable();
             // No exceptions!
-            first.Union(second);
+            var query = first.Union(second);
+            // Still no exceptions... we're not calling MoveNext.
+            using (var iterator = query.GetEnumerator())
+            {
+            }
         }

         [Test]