Clean up exports of FixIdDefinition

Clean up exports of FixIdDefinition

--- src/VisualStudio/CSharp/Impl/LanguageService/CSharpCodeCleanupFixer.cs
+++ src/VisualStudio/CSharp/Impl/LanguageService/CSharpCodeCleanupFixer.cs
@@ -1,20 +1,15 @@
 // Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

-using System;
 using System.Collections.Immutable;
 using System.ComponentModel.Composition;
 using System.IO;
-using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
-using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CodeCleanup;
 using Microsoft.CodeAnalysis.CSharp;
 using Microsoft.CodeAnalysis.CSharp.RemoveUnusedVariable;
 using Microsoft.CodeAnalysis.Diagnostics;
 using Microsoft.CodeAnalysis.Editor;
-using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
-using Microsoft.CodeAnalysis.Internal.Log;
 using Microsoft.CodeAnalysis.PooledObjects;
 using Microsoft.CodeAnalysis.Shared.Extensions;
 using Microsoft.CodeAnalysis.Shared.Utilities;
@@ -27,7 +22,7 @@
 namespace Microsoft.VisualStudio.LanguageServices.CSharp.LanguageService
 {
     [Export(typeof(CodeCleanUpFixer))]
-    [VisualStudio.Utilities.ContentType(ContentTypeNames.CSharpContentType)]
+    [ContentType(ContentTypeNames.CSharpContentType)]
     internal class CSharpCodeCleanUpFixer : CodeCleanUpFixer
     {
         private const string RemoveUnusedImportsFixId = "RemoveUnusedImportsFixId";
@@ -40,7 +35,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_implicit_explicit_type_preferences))]
-        public FixIdDefinition UseImplicitTypeDiagnosticId;
+        public static readonly FixIdDefinition UseImplicitTypeDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.UseExplicitTypeDiagnosticId)]
@@ -49,7 +44,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_implicit_explicit_type_preferences))]
-        public FixIdDefinition UseExplicitTypeDiagnosticId;
+        public static readonly FixIdDefinition UseExplicitTypeDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.AddQualificationDiagnosticId)]
@@ -58,7 +53,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_this_qualification_preferences))]
-        public FixIdDefinition AddQualificationDiagnosticId;
+        public static readonly FixIdDefinition AddQualificationDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.RemoveQualificationDiagnosticId)]
@@ -67,7 +62,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_this_qualification_preferences))]
-        public FixIdDefinition RemoveQualificationDiagnosticId;
+        public static readonly FixIdDefinition RemoveQualificationDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId)]
@@ -76,7 +71,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_language_framework_type_preferences))]
-        public FixIdDefinition PreferBuiltInOrFrameworkTypeDiagnosticId;
+        public static readonly FixIdDefinition PreferBuiltInOrFrameworkTypeDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.AddBracesDiagnosticId)]
@@ -85,7 +80,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Add_remove_braces_for_single_line_control_statements))]
-        public FixIdDefinition AddBracesDiagnosticId;
+        public static readonly FixIdDefinition AddBracesDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.AddAccessibilityModifiersDiagnosticId)]
@@ -94,7 +89,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Add_accessibility_modifiers))]
-        public FixIdDefinition AddAccessibilityModifiersDiagnosticId;
+        public static readonly FixIdDefinition AddAccessibilityModifiersDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.OrderModifiersDiagnosticId)]
@@ -103,7 +98,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Sort_accessibility_modifiers))]
-        public FixIdDefinition OrderModifiersDiagnosticId;
+        public static readonly FixIdDefinition OrderModifiersDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.MakeFieldReadonlyDiagnosticId)]
@@ -112,7 +107,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Make_private_field_readonly_when_possible))]
-        public FixIdDefinition MakeFieldReadonlyDiagnosticId;
+        public static readonly FixIdDefinition MakeFieldReadonlyDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.RemoveUnnecessaryCastDiagnosticId)]
@@ -121,7 +116,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Remove_unnecessary_casts))]
-        public FixIdDefinition RemoveUnnecessaryCastDiagnosticId;
+        public static readonly FixIdDefinition RemoveUnnecessaryCastDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.UseExpressionBodyForConstructorsDiagnosticId)]
@@ -130,7 +125,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_expression_block_body_preferences))]
-        public FixIdDefinition UseExpressionBodyForConstructorsDiagnosticId;
+        public static readonly FixIdDefinition UseExpressionBodyForConstructorsDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId)]
@@ -139,7 +134,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_expression_block_body_preferences))]
-        public FixIdDefinition UseExpressionBodyForMethodsDiagnosticId;
+        public static readonly FixIdDefinition UseExpressionBodyForMethodsDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.UseExpressionBodyForConversionOperatorsDiagnosticId)]
@@ -148,7 +143,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_expression_block_body_preferences))]
-        public FixIdDefinition UseExpressionBodyForConversionOperatorsDiagnosticId;
+        public static readonly FixIdDefinition UseExpressionBodyForConversionOperatorsDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.UseExpressionBodyForOperatorsDiagnosticId)]
@@ -157,7 +152,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_expression_block_body_preferences))]
-        public FixIdDefinition UseExpressionBodyForOperatorsDiagnosticId;
+        public static readonly FixIdDefinition UseExpressionBodyForOperatorsDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.UseExpressionBodyForPropertiesDiagnosticId)]
@@ -166,7 +161,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_expression_block_body_preferences))]
-        public FixIdDefinition UseExpressionBodyForPropertiesDiagnosticId;
+        public static readonly FixIdDefinition UseExpressionBodyForPropertiesDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.UseExpressionBodyForIndexersDiagnosticId)]
@@ -175,7 +170,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_expression_block_body_preferences))]
-        public FixIdDefinition UseExpressionBodyForIndexersDiagnosticId;
+        public static readonly FixIdDefinition UseExpressionBodyForIndexersDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.UseExpressionBodyForAccessorsDiagnosticId)]
@@ -184,7 +179,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_expression_block_body_preferences))]
-        public FixIdDefinition UseExpressionBodyForAccessorsDiagnosticId;
+        public static readonly FixIdDefinition UseExpressionBodyForAccessorsDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.InlineDeclarationDiagnosticId)]
@@ -193,7 +188,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_inline_out_variable_preferences))]
-        public FixIdDefinition InlineDeclarationDiagnosticId;
+        public static readonly FixIdDefinition InlineDeclarationDiagnosticId;

         [Export]
         [FixId(CSharpRemoveUnusedVariableCodeFixProvider.CS0168)]
@@ -202,7 +197,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Remove_unused_variables))]
-        public FixIdDefinition CS0168;
+        public static readonly FixIdDefinition CS0168;

         [Export]
         [FixId(CSharpRemoveUnusedVariableCodeFixProvider.CS0219)]
@@ -211,7 +206,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Remove_unused_variables))]
-        public FixIdDefinition CS0219;
+        public static readonly FixIdDefinition CS0219;

         [Export]
         [FixId(IDEDiagnosticIds.UseObjectInitializerDiagnosticId)]
@@ -220,7 +215,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_object_collection_initialization_preferences))]
-        public FixIdDefinition UseObjectInitializerDiagnosticId;
+        public static readonly FixIdDefinition UseObjectInitializerDiagnosticId;

         [Export]
         [FixId(IDEDiagnosticIds.UseCollectionInitializerDiagnosticId)]
@@ -229,7 +224,7 @@
         [ConfigurationKey("unused")]
         [HelpLink("https://www.microsoft.com")]
         [LocalizedName(typeof(CSharpFeaturesResources), nameof(CSharpFeaturesResources.Apply_object_collection_initialization_preferences))]
-        public FixIdDefinition UseCollectionInitializerDiagnosticId;
+        public static readonly FixIdDefinition UseCollectionInitializerDiagnosticId;

         [Export]
         [FixId(RemoveUnusedImportsFixId)]
@@ -238,7 +233,7 @@
         [HelpLink("https://www.microsoft.com")]
         [ExportMetadata("EnableByDefault", true)]
         [LocalizedName(typeof(CSharpVSResources), nameof(CSharpVSResources.Remove_unnecessary_usings))]
-        public FixIdDefinition RemoveUnusedImports;
+        public static readonly FixIdDefinition RemoveUnusedImports;

         [Export]
         [FixId(SortImportsFixId)]
@@ -248,7 +243,7 @@
         [HelpLink("https://www.microsoft.com")]
         [ExportMetadata("EnableByDefault", true)]
         [LocalizedName(typeof(CSharpVSResources), nameof(CSharpVSResources.Sort_usings))]
-        public FixIdDefinition SortImports;
+        public static readonly FixIdDefinition SortImports;

         public override Task<bool> FixAsync(ICodeCleanUpScope scope, ICodeCleanUpExecutionContext context, CancellationToken cancellationToken)
         {
@@ -294,56 +289,60 @@

         private async Task<bool> FixTextBufferAsync(TextBufferCodeCleanUpScope textBufferScope, ICodeCleanUpExecutionContext context, CancellationToken cancellationToken)
         {
-            cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(context.OperationContext.UserCancellationToken, cancellationToken).Token;
-
-            var buffer = textBufferScope.SubjectBuffer;
-            if (buffer != null)
+            using (var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(context.OperationContext.UserCancellationToken, cancellationToken))
             {
-                using (var scope = context.OperationContext.AddScope(allowCancellation: true, description: EditorFeaturesResources.Applying_changes))
+                cancellationToken = cancellationTokenSource.Token;
+
+                var buffer = textBufferScope.SubjectBuffer;
+                if (buffer != null)
                 {
-                    var progressTracker = new ProgressTracker((description, completed, total) =>
+                    using (var scope = context.OperationContext.AddScope(allowCancellation: true, description: EditorFeaturesResources.Applying_changes))
                     {
-                        if (scope != null)
+                        var progressTracker = new ProgressTracker((description, completed, total) =>
                         {
-                            scope.Description = description;
-                            scope?.Progress.Report(new ProgressInfo(completed, total));
-                        }
-                    });
-
-                    var document = buffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
-                    var codeCleanupService = document.GetLanguageService<ICodeCleanupService>();
-
-                    // TODO: enable all diagnostics for now, need to be replace by inclusion/ exclusion list from .editorconfig
-                    // https://github.com/dotnet/roslyn/issues/30163
-                    var allDiagnostics = codeCleanupService.GetAllDiagnostics();
-
-                    var enabedDiagnosticSets = ArrayBuilder<DiagnosticSet>.GetInstance();
-
-                    foreach (var diagnostic in allDiagnostics.Diagnostics)
-                    {
-                        foreach (var diagnosticId in diagnostic.DiagnosticIds)
+                            if (scope != null)
+                            {
+                                scope.Description = description;
+                                scope.Progress.Report(new ProgressInfo(completed, total));
+                            }
+                        });
+
+                        var document = buffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
+                        var codeCleanupService = document.GetLanguageService<ICodeCleanupService>();
+
+                        // TODO: enable all diagnostics for now, need to be replace by inclusion/ exclusion list from .editorconfig
+                        // https://github.com/dotnet/roslyn/issues/30163
+                        var allDiagnostics = codeCleanupService.GetAllDiagnostics();
+
+                        var enabedDiagnosticSets = ArrayBuilder<DiagnosticSet>.GetInstance();
+
+                        foreach (var diagnostic in allDiagnostics.Diagnostics)
                         {
-                            if (context.EnabledFixIds.IsFixIdEnabled(diagnosticId))
+                            foreach (var diagnosticId in diagnostic.DiagnosticIds)
                             {
-                                enabedDiagnosticSets.Add(diagnostic);
-                                break;
+                                if (context.EnabledFixIds.IsFixIdEnabled(diagnosticId))
+                                {
+                                    enabedDiagnosticSets.Add(diagnostic);
+                                    break;
+                                }
                             }
                         }
+
+                        var isRemoveUnusedUsingsEnabled = context.EnabledFixIds.IsFixIdEnabled(RemoveUnusedImportsFixId);
+                        var isSortUsingsEnabled = context.EnabledFixIds.IsFixIdEnabled(SortImportsFixId);
+                        var enabledDiagnostics = new EnabledDiagnosticOptions(enabedDiagnosticSets.ToImmutableArray(),
+                            new OrganizeUsingsSet(isRemoveUnusedUsingsEnabled, isSortUsingsEnabled));
+
+                        var newDoc = await codeCleanupService.CleanupAsync(
+                            document, enabledDiagnostics, progressTracker, cancellationToken);
+
+                        return document.Project.Solution.Workspace.TryApplyChanges(newDoc.Project.Solution, progressTracker);
                     }
-
-                    var isRemoveUnusedUsingsEnabled = context.EnabledFixIds.IsFixIdEnabled(RemoveUnusedImportsFixId);
-                    var isSortUsingsEnabled = context.EnabledFixIds.IsFixIdEnabled(SortImportsFixId);
-                    var enabledDiagnostics = new EnabledDiagnosticOptions(enabedDiagnosticSets.ToImmutableArray(),
-                        new OrganizeUsingsSet(isRemoveUnusedUsingsEnabled, isSortUsingsEnabled));
-
-                    var newDoc = await codeCleanupService.CleanupAsync(
-                        document, enabledDiagnostics, progressTracker, cancellationToken);
-
-                    return document.Project.Solution.Workspace.TryApplyChanges(newDoc.Project.Solution, progressTracker);
                 }
+
+                return false;
             }

-            return false;
         }
     }
 }


Add secondary sort by Id after DownloadCount.

--- src/VsConsole/PowerShellCmdlets/FindPackageCmdlet.cs
+++ src/VsConsole/PowerShellCmdlets/FindPackageCmdlet.cs
@@ -37,7 +37,7 @@
                 packages = packages.Where(p => p.Id.ToLower().StartsWith(Filter.ToLower()));
             }

-            packages = packages.OrderByDescending(p => p.DownloadCount);
+            packages = packages.OrderByDescending(p => p.DownloadCount).ThenBy(p => p.Id);

             return packages;
         }
@@ -48,7 +48,7 @@
             if (!String.IsNullOrEmpty(Filter)) {
                 packagesToUpdate = packagesToUpdate.Where(p => p.Id.ToLower().StartsWith(Filter.ToLower()));
             }
-            return sourceRepository.GetUpdates(packagesToUpdate).OrderByDescending(p => p.DownloadCount);
+            return sourceRepository.GetUpdates(packagesToUpdate).OrderByDescending(p => p.DownloadCount).ThenBy(p => p.Id);
         }

         protected override void Log(MessageLevel level, string formattedMessage) {


Scanner fragment was not being assigned top/bottom text for the default view on Android

--- src/ZXing.Net.Mobile/MonoForAndroid/ZxingActivity.cs
+++ src/ZXing.Net.Mobile/MonoForAndroid/ZxingActivity.cs
@@ -80,8 +80,8 @@
 			}, ScanningOptions);
 			scannerFragment.CustomOverlayView = CustomOverlayView;
 			scannerFragment.UseCustomView = UseCustomView;
-			scannerFragment.TopText = "Hold camera up to barcode to scan";
-			scannerFragment.BottomText = "Barcode will automatically scan";
+			scannerFragment.TopText = TopText;
+			scannerFragment.BottomText = BottomText;

 			SupportFragmentManager.BeginTransaction()
 				.Replace(Resource.Id.contentFrame, scannerFragment, "ZXINGFRAGMENT")


Changes for SE 1.189, part 3

Changes for SE 1.189, part 3

--- src/SEScripts/ResourceExchanger2_5_0_189/Program.cs
+++ src/SEScripts/ResourceExchanger2_5_0_189/Program.cs
@@ -30,18 +30,18 @@

         /** Default configuration *****************************************************************/

+        public bool AnyConstruct = false;
         public string DisplayLcdGroup = "Resource exchanger output";
         public string DrillsPayloadLightsGroup = "Payload indicators";
-        public bool AnyConstruct = false;
         public bool EnableDrills = true;
         public bool EnableGroups = true;
         public bool EnableOxygenGenerators = true;
         public bool EnableReactors = true;
         public bool EnableRefineries = true;
         public bool EnableTurrets = true;
-        public string ManagedBlocksGroup = "";
         public string GroupTagPattern = @"\bGR\d{1,3}\b";
         public MyItemType? LowestRefineryPriority = new MyItemType(OreType, "Stone");
+        public string ManagedBlocksGroup = "";
         public MyItemType? TopRefineryPriority = new MyItemType(OreType, "Iron");

         /** Implementation ************************************************************************/
@@ -108,7 +108,590 @@
             WriteOutput(bs, stat);
         }

-        public void ReadConfig()
+        public void Save()
+        { }
+
+        private void BalanceInventories(Statistics stat, List<InventoryWrapper> group, int networkNumber,
+            int groupNumber, string groupName, Func<MyInventoryItem, bool> filter)
+        {
+            if (group.Count < 2)
+            {
+                stat.Output.Append("Cannot balance conveyor network ").Append(networkNumber)
+                    .Append(" group ").Append(groupNumber).Append(" \"").Append(groupName).AppendLine("\"")
+                    .AppendLine("  because there is only one inventory.");
+                return; // nothing to do
+            }
+
+            if (filter != null)
+            {
+                foreach (var wrp in group)
+                    wrp.LoadVolume().FilterItems(this, stat, filter).CalculatePercent();
+            }
+            else
+            {
+                foreach (var wrp in group)
+                    wrp.LoadVolume().CalculatePercent();
+            }
+
+            InventoryWrapper min = group[0], max = group[0];
+            for (int i = 1; i < group.Count; ++i)
+            {
+                var dt = group[i];
+                if (min.Percent > dt.Percent)
+                    min = dt;
+                if (max.Percent < dt.Percent)
+                    max = dt;
+            }
+
+            if (max.CurrentVolume < SmallNumber)
+            {
+                stat.Output.Append("Cannot balance conveyor network ").Append(networkNumber)
+                    .Append(" group ").Append(groupNumber).Append(" \"").Append(groupName)
+                    .AppendLine("\"")
+                    .AppendLine("  because of lack of items in it.");
+                return; // nothing to do
+            }
+
+            stat.Output.Append("Balancing conveyor network ").Append(networkNumber)
+                .Append(" group ").Append(groupNumber)
+                .Append(" \"").Append(groupName).AppendLine("\"...");
+
+            if (min == max)
+            {
+                stat.Output.AppendLine("  nothing to do");
+                return;
+            }
+
+            decimal toMove;
+            if (min.MaxVolume == max.MaxVolume)
+            {
+                toMove = (max.CurrentVolume - min.CurrentVolume) / 2.0M;
+            }
+            else
+            {
+                toMove = (max.CurrentVolume * min.MaxVolume - min.CurrentVolume * max.MaxVolume)
+                    / (min.MaxVolume + max.MaxVolume);
+            }
+
+            stat.Output.Append("Inv. 1 vol: ").Append(min.CurrentVolume.ToString("F6")).Append("; ");
+            stat.Output.Append("Inv. 2 vol: ").Append(max.CurrentVolume.ToString("F6")).Append("; ");
+            stat.Output.Append("To move: ").Append(toMove.ToString("F6")).AppendLine();
+
+            if (toMove < 0.0M)
+                throw new InvalidOperationException("Something went wrong with calculations: volumeDiff is " + toMove);
+
+            if (toMove < SmallNumber)
+                return;
+
+            MoveVolume(stat, max, min, (VRage.MyFixedPoint)toMove, filter);
+        }
+
+        private BlockStore CollectTerminals(BlockStore bs, Statistics stat)
+        {
+            var blocks = new List<IMyTerminalBlock>();
+            Func<IMyTerminalBlock, bool> myTerminalBlockFilter = b => b.IsFunctional && (AnyConstruct || b.IsSameConstructAs(Me));
+            Func<ICollection, bool, string> countOrNA = (c, e) => e ? c.Count.ToString() : "n/a";
+
+            if (String.IsNullOrEmpty(ManagedBlocksGroup))
+            {
+                GridTerminalSystem.GetBlocksOfType(blocks, myTerminalBlockFilter);
+            }
+            else
+            {
+                var group = GridTerminalSystem.GetBlockGroupWithName(ManagedBlocksGroup);
+                if (group == null)
+                    stat.Output.Append("Error: a group ").Append(ManagedBlocksGroup).AppendLine(" has not been found");
+                else
+                    group.GetBlocksOfType(blocks, myTerminalBlockFilter);
+            }
+
+            foreach (var dt in blocks)
+                bs.Collect(dt);
+
+            if (!String.IsNullOrEmpty(DisplayLcdGroup))
+            {
+                var group = GridTerminalSystem.GetBlockGroupWithName(DisplayLcdGroup);
+                if (group != null)
+                    group.GetBlocksOfType<IMyTextPanel>(bs.DebugScreen, myTerminalBlockFilter);
+            }
+
+            if (!String.IsNullOrEmpty(DrillsPayloadLightsGroup))
+            {
+                var group = GridTerminalSystem.GetBlockGroupWithName(DrillsPayloadLightsGroup);
+                if (group != null)
+                    group.GetBlocksOfType<IMyLightingBlock>(bs.DrillsPayloadLights, myTerminalBlockFilter);
+            }
+
+            stat.Output.Append("Resource exchanger 2.5.0. Blocks managed:")
+                .Append(" reactors: ").Append(countOrNA(bs.Reactors, EnableReactors))
+                .Append(", refineries: ").Append(countOrNA(bs.Refineries, EnableRefineries)).AppendLine(",")
+                .Append("oxygen gen.: ").Append(countOrNA(bs.OxygenGenerators, EnableOxygenGenerators))
+                .Append(", drills: ").Append(countOrNA(bs.Drills, EnableDrills))
+                .Append(", turrets: ").Append(countOrNA(bs.Turrets, EnableTurrets))
+                .Append(", cargo cont.: ").Append(countOrNA(bs.CargoContainers, EnableGroups))
+                .Append(", custom groups: ").Append(countOrNA(bs.Groups, EnableGroups)).AppendLine();
+
+            return bs;
+        }
+
+        private List<InventoryGroup> DivideByBlockType(ConveyorNetwork network)
+        {
+            var groupMap = new Dictionary<string, InventoryGroup>();
+
+            foreach (var inv in network.Inventories)
+            {
+                InventoryGroup group;
+                if (!groupMap.TryGetValue(inv.GroupName, out group))
+                {
+                    group = new InventoryGroup(groupMap.Count + 1, inv.GroupName);
+                    groupMap.Add(inv.GroupName, group);
+                }
+                group.Inventories.Add(inv);
+            }
+
+            var result = new List<InventoryGroup>(groupMap.Count);
+            result.AddRange(groupMap.Values);
+            return result;
+        }
+
+        private void EnforceItemPriority(List<InventoryWrapper> group, Statistics stat, MyItemType? topPriority, MyItemType? lowestPriority)
+        {
+            if (topPriority == null && lowestPriority == null)
+                return;
+
+            foreach (var inv in group)
+            {
+                if (inv.Inventory.ItemCount < 2)
+                    continue;
+
+                var items = inv.GetItems(stat.TmpItems1, null);
+
+                if (topPriority.HasValue && !items[0].Type.Equals(topPriority.Value))
+                {
+                    for (int i = 1; i < items.Count; ++i)
+                    {
+                        var item = items[i];
+                        if (item.Type.Equals(topPriority.Value))
+                        {
+                            stat.Output.Append("Moving ").Append(topPriority.Value.SubtypeId).Append(" from ")
+                                .Append(i + 1).Append(" slot to first slot of ").AppendLine(inv.Block.CustomName);
+                            inv.MoveItem(i, 0);
+                            stat.MovementsDone += 1;
+                            break;
+                        }
+                    }
+                }
+
+                if (lowestPriority.HasValue && !items[items.Count - 1].Type.Equals(lowestPriority.Value))
+                {
+                    for (int i = items.Count - 2; i >= 0; --i)
+                    {
+                        var item = items[i];
+                        if (item.Type.Equals(lowestPriority.Value))
+                        {
+                            stat.Output.Append("Moving ").Append(lowestPriority.Value.SubtypeId).Append(" from ")
+                                .Append(i + 1).Append(" slot to last slot of ").AppendLine(inv.Block.CustomName);
+                            inv.MoveItem(i, items.Count);
+                            stat.MovementsDone += 1;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        private List<ConveyorNetwork> FindConveyorNetworks(ICollection<InventoryWrapper> inventories, HashSet<InventoryWrapper> exclude)
+        {
+            var result = new List<ConveyorNetwork>();
+
+            foreach (var wrp in inventories)
+            {
+                if (exclude != null && exclude.Contains(wrp))
+                    continue;
+
+                bool add = true;
+                foreach (var network in result)
+                {
+                    var firstInv = network.Inventories[0];
+
+                    if (wrp.Block.CustomName.StartsWith("Refinery ") && firstInv.Block.CustomName.StartsWith("Refinery "))
+                        Test(wrp, firstInv);
+
+                    if (firstInv.Inventory.IsConnectedTo(wrp.Inventory) && wrp.Inventory.IsConnectedTo(firstInv.Inventory))
+                    {
+                        network.Inventories.Add(wrp);
+                        add = false;
+                        break;
+                    }
+                }
+
+                if (add)
+                {
+                    var network = new ConveyorNetwork(result.Count + 1);
+                    network.Inventories.Add(wrp);
+                    result.Add(network);
+                }
+            }
+
+            return result;
+        }
+
+        private string FindInvGroupName(MyItemType def, IMyInventory inv)
+        {
+            const string MY_OBJECT_BUILDER = "MyObjectBuilder_";
+
+            ulong[] groupId;
+            if (_blockToGroupIdMap.TryGetValue(def, out groupId))
+                return _groupIdToNameMap[groupId];
+
+            groupId = new ulong[ItemInfo.ID_LENGTH];
+            foreach (var kv in Items.ItemInfoDict)
+            {
+                if (inv.CanItemsBeAdded(-1, kv.Key))
+                {
+                    for (int i = 0; i < ItemInfo.ID_LENGTH; ++i)
+                        groupId[i] |= kv.Value.Id[i];
+                }
+            }
+
+            string result;
+            if (_groupIdToNameMap.TryGetValue(groupId, out result))
+            {
+                _blockToGroupIdMap.Add(def, groupId);
+                return result;
+            }
+            else
+            {
+                var fullType = def.ToString();
+                result = fullType.StartsWith(MY_OBJECT_BUILDER)
+                ? '$' + fullType.Substring(MY_OBJECT_BUILDER.Length)
+                : fullType;
+
+                _groupIdToNameMap.Add(groupId, result);
+                _blockToGroupIdMap.Add(def, groupId);
+                return result;
+            }
+        }
+
+        private VRage.MyFixedPoint MoveVolume(Statistics stat, InventoryWrapper from, InventoryWrapper to,
+            VRage.MyFixedPoint volumeAmountToMove, Func<MyInventoryItem, bool> filter)
+        {
+            if (volumeAmountToMove == 0)
+                return volumeAmountToMove;
+
+            if (volumeAmountToMove < 0)
+                throw new ArgumentException("Invalid volume amount", "volumeAmount");
+
+            stat.Output.Append("Move ").Append(volumeAmountToMove).Append(" l. from ")
+                .Append(from.Block.CustomName).Append(" to ").AppendLine(to.Block.CustomName);
+            var itemsFrom = from.GetItems(stat.TmpItems1, filter);
+
+            for (int i = itemsFrom.Count - 1; i >= 0; --i)
+            {
+                MyInventoryItem item = itemsFrom[i];
+
+                var data = Items.Get(stat, item.Type);
+                if (data == null)
+                    continue;
+
+                decimal amountToMoveRaw = (decimal)volumeAmountToMove * 1000M / data.Volume;
+                VRage.MyFixedPoint amountToMove;
+
+                if (data.HasIntegralAmounts)
+                    amountToMove = (int)(amountToMoveRaw + 0.1M);
+                else
+                    amountToMove = (VRage.MyFixedPoint)amountToMoveRaw;
+
+                if (amountToMove == 0)
+                    continue;
+
+                decimal itemVolume;
+                bool success;
+                if (amountToMove <= item.Amount)
+                {
+                    itemVolume = (decimal)amountToMove * data.Volume / 1000M;
+                    success = from.TransferItem(to, i, amountToMove);
+                    stat.MovementsDone += 1;
+                    stat.Output.Append("Move ").Append(amountToMove).Append(" -> ").AppendLine(success ? "success" : "failure");
+                }
+                else
+                {
+                    itemVolume = (decimal)item.Amount * data.Volume / 1000M;
+                    success = from.TransferItem(to, i, item.Amount);
+                    stat.MovementsDone += 1;
+                    stat.Output.Append("Move all ").Append(item.Amount).Append(" -> ").AppendLine(success ? "success" : "failure");
+                }
+
+                if (success)
+                    volumeAmountToMove -= (VRage.MyFixedPoint)itemVolume;
+                if (volumeAmountToMove < (VRage.MyFixedPoint)SmallNumber)
+                    return volumeAmountToMove;
+            }
+
+            stat.Output.Append("Cannot move ").Append(volumeAmountToMove).AppendLine(" l.");
+            return volumeAmountToMove;
+        }
+
+        private void PrintOnlineStatus(BlockStore bs, Statistics stat)
+        {
+            var sb = new StringBuilder(4096);
+
+            var blocksAffected = bs.Reactors.Count
+                + bs.Refineries.Count
+                + bs.Drills.Count
+                + bs.Turrets.Count
+                + bs.OxygenGenerators.Count
+                + bs.CargoContainers.Count;
+
+            sb.Append("Grids connected: ").Append(bs.AllGrids.Count).AppendLine(AnyConstruct ? " (AC)" : " (SC)");
+            sb.Append("Conveyor networks: ").Append(stat.NumberOfNetworks).AppendLine();
+            sb.Append("Blocks affected: ").Append(blocksAffected).AppendLine();
+
+            sb.Append("reactors: ");
+            if (bs.Reactors.Count != 0)
+                sb.Append(bs.Reactors.Count);
+            else
+                sb.Append(EnableReactors ? "0" : "OFF");
+
+            sb.Append(", refineries: ");
+            if (bs.Refineries.Count != 0)
+                sb.Append(bs.Refineries.Count);
+            else
+                sb.Append(EnableRefineries ? "0" : "OFF");
+
+            sb.AppendLine().Append("drills: ");
+            if (bs.Drills.Count != 0)
+                sb.Append(bs.Drills.Count);
+            else
+                sb.Append(EnableDrills ? "0" : "OFF");
+
+            sb.Append(", turrets: ");
+            if (bs.Turrets.Count != 0)
+                sb.Append(bs.Turrets.Count);
+            else
+                sb.Append(EnableTurrets ? "0" : "OFF");
+
+            sb.Append(", o. gen.: ");
+            if (bs.OxygenGenerators.Count != 0)
+                sb.Append(bs.OxygenGenerators.Count);
+            else
+                sb.Append(EnableOxygenGenerators ? "0" : "OFF");
+
+            sb.AppendLine().Append("cargo cont.: ");
+            if (bs.CargoContainers.Count != 0)
+                sb.Append(bs.CargoContainers.Count);
+            else
+                sb.Append(EnableGroups ? "0" : "OFF");
+
+            sb.Append(", groups: ");
+            if (bs.Groups.Count != 0)
+                sb.Append(bs.Groups.Count);
+            else
+                sb.Append(EnableGroups ? "0" : "OFF");
+
+            sb.AppendLine();
+
+            if (bs.Drills.Count != 0)
+            {
+                if (stat.NotConnectedDrillsFound)
+                    sb.AppendLine("Warn: Some drills are not connected");
+
+                sb.Append("Drills payload: ").Append(stat.DrillsPayloadStr ?? "N/A");
+                if (stat.DrillsVolumeWarning)
+                    sb.AppendLine((_cycleNumber & 0x01) == 0 ? "%  !" : "% ! !");
+                else
+                    sb.AppendLine("%");
+            }
+
+            if (stat.MissingInfo.Count > 0)
+                sb.Append("Err: missing volume information for ").AppendLine(String.Join(", ", stat.MissingInfo));
+
+            _avgMovements[_cycleNumber & 0x0F] = stat.MovementsDone;
+            var samples = Math.Min(_cycleNumber + 1, 0x10);
+            double avg = 0;
+            for (int i = 0; i < samples; ++i)
+                avg += _avgMovements[i];
+            avg /= samples;
+
+            sb.Append("Avg. movements: ").Append(avg.ToString("F2")).Append(" (last ").Append(samples).AppendLine(" runs)");
+
+            float cpu = Runtime.CurrentInstructionCount * 100;
+            cpu /= Runtime.MaxInstructionCount;
+            sb.Append("Complexity limit usage: ").Append(cpu.ToString("F2")).AppendLine("%");
+
+            sb.Append("Last run time: ").Append(Runtime.LastRunTimeMs.ToString("F3")).AppendLine(" ms");
+
+            var tab = new char[42];
+            for (int i = 0; i < 42; ++i)
+            {
+                char c = ' ';
+                if (i % 21 == 1)
+                    c = '|';
+                else if (i % 7 < 4)
+                    c = '·';
+                tab[41 - (i + _cycleNumber) % 42] = c;
+            }
+            sb.AppendLine(new string(tab));
+            ++_cycleNumber;
+
+            Echo(sb.ToString());
+        }
+
+        private int ProcessBlocks(string msg, bool enable, ICollection<InventoryWrapper> blocks, Statistics stat, string invGroup = null,
+            HashSet<InventoryWrapper> exclude = null, Func<MyInventoryItem, bool> filter = null)
+        {
+            stat.Output.Append(msg);
+            if (enable)
+            {
+                if (blocks.Count >= 2)
+                {
+                    var conveyorNetworks = FindConveyorNetworks(blocks, exclude);
+                    stat.NumberOfNetworks += conveyorNetworks.Count;
+                    stat.Output.Append(": ").Append(conveyorNetworks.Count).AppendLine(" conveyor networks found");
+
+                    if (invGroup != null)
+                    {
+                        foreach (var network in conveyorNetworks)
+                            BalanceInventories(stat, network.Inventories, network.No, 1, invGroup, filter);
+                    }
+                    else
+                    {
+                        foreach (var network in conveyorNetworks)
+                            foreach (var group in DivideByBlockType(network))
+                                BalanceInventories(stat, group.Inventories, network.No, group.No, group.Name, filter);
+                    }
+
+                    return conveyorNetworks.Count;
+                }
+                else
+                {
+                    stat.Output.AppendLine(": nothing to do");
+                    return 0;
+                }
+            }
+            else
+            {
+                stat.Output.AppendLine(": disabled");
+                return -1;
+            }
+        }
+
+        private void ProcessDrillsLights(List<InventoryWrapper> drills, List<IMyLightingBlock> lights, Statistics stat)
+        {
+            VRage.MyFixedPoint warningLevelInCubicMetersLeft = 5;
+            Func<Color> step0 = () => new Color(255, 255, 255);
+            Func<Color> step1 = () => new Color(255, 255, 0);
+            Func<Color> step2 = () => new Color(255, 0, 0);
+            Func<Color> warn = () => (_cycleNumber & 0x1) == 0 ? new Color(128, 0, 128) : new Color(128, 0, 64);
+            Func<Color> err = () => (_cycleNumber & 0x1) == 0 ? new Color(0, 128, 128) : new Color(0, 64, 128);
+
+            if (lights.Count == 0)
+            {
+                stat.Output.AppendLine("Setting color of drills payload indicators. Not enough lights found. Nothing to do.");
+                return;
+            }
+
+            stat.Output.AppendLine("Setting color of drills payload indicators.");
+
+            Color color;
+            if (stat.NotConnectedDrillsFound)
+            {
+                stat.Output.AppendLine("Not all drills are connected.");
+                color = err();
+            }
+            else
+            {
+                var drillsMaxVolume = VRage.MyFixedPoint.Zero;
+                var drillsCurrentVolume = VRage.MyFixedPoint.Zero;
+                foreach (var drill in drills)
+                {
+                    drillsMaxVolume += drill.Inventory.MaxVolume;
+                    drillsCurrentVolume += drill.Inventory.CurrentVolume;
+                }
+
+                if (drillsMaxVolume > 0)
+                {
+                    var p = (float)drillsCurrentVolume * 1000.0f;
+                    p /= (float)drillsMaxVolume;
+
+                    stat.DrillsPayloadStr = (p / 10.0f).ToString("F1");
+
+                    stat.Output.Append("Drills space usage: ");
+                    stat.Output.Append(stat.DrillsPayloadStr);
+                    stat.Output.AppendLine("%");
+
+                    stat.DrillsVolumeWarning = (drillsMaxVolume - drillsCurrentVolume) < warningLevelInCubicMetersLeft;
+                    if (stat.DrillsVolumeWarning)
+                    {
+                        color = warn();
+                    }
+                    else
+                    {
+                        Color c1, c2;
+                        float m1, m2;
+
+                        if (p < 500.0f)
+                        {
+                            c1 = step0();
+                            c2 = step1();
+                            m2 = p / 500.0f;
+                            m1 = 1.0f - m2;
+                        }
+                        else
+                        {
+                            c1 = step2();
+                            c2 = step1();
+                            m1 = (p - 500.0f) / 450.0f;
+                            if (m1 > 1.0f)
+                                m1 = 1.0f;
+                            m2 = 1.0f - m1;
+                        }
+
+                        float r = c1.R * m1 + c2.R * m2;
+                        float g = c1.G * m1 + c2.G * m2;
+                        float b = c1.B * m1 + c2.B * m2;
+
+                        if (r > 255.0f)
+                            r = 255.0f;
+                        else if (r < 0.0f)
+                            r = 0.0f;
+
+                        if (g > 255.0f)
+                            g = 255.0f;
+                        else if (g < 0.0f)
+                            g = 0.0f;
+
+                        if (b > 255.0f)
+                            b = 255.0f;
+                        else if (b < 0.0f)
+                            b = 0.0f;
+
+                        color = new Color((int)r, (int)g, (int)b);
+                    }
+                }
+                else
+                {
+                    color = step0();
+                }
+            }
+
+            stat.Output.Append("Drills payload indicators lights color: ");
+            stat.Output.Append(color);
+            stat.Output.AppendLine();
+
+            foreach (IMyLightingBlock light in lights)
+            {
+                var currentColor = light.GetValue<Color>("Color");
+                if (currentColor != color)
+                    light.SetValue<Color>("Color", color);
+            }
+
+            stat.Output.Append("Color of ");
+            stat.Output.Append(lights.Count);
+            stat.Output.AppendLine(" drills payload indicators has been set.");
+        }
+
+        private void ReadConfig()
         {
             const string anyConstructComment = "\n Set to \"true\" to enable exchanging items with connected ships."
                 + "\n Keep \"false\" if blocks connected by connectors should not be affected.";
@@ -172,7 +755,7 @@
             _prevConfig = Me.CustomData = ini.ToString();
         }

-        public void ReadConfigBoolean(MyIni ini, string name, ref bool value, string comment)
+        private void ReadConfigBoolean(MyIni ini, string name, ref bool value, string comment)
         {
             var key = new MyIniKey(ConfigSection, name);
             MyIniValue val = ini.Get(key);
@@ -184,7 +767,19 @@
             ini.SetComment(key, comment);
         }

-        public void ReadConfigString(MyIni ini, string name, ref string value, string comment)
+        private void ReadConfigItemType(MyIni ini, string name, ref MyItemType? value, string comment)
+        {
+            var key = new MyIniKey(ConfigSection, name);
+            MyIniValue val = ini.Get(key);
+            string tmp;
+            if (val.TryGetString(out tmp))
+                value = String.IsNullOrEmpty(tmp) ? null : MyItemType.Parse(tmp.Trim());
+            else
+                ini.Set(key, value.HasValue ? value.Value.ToString() : String.Empty);
+            ini.SetComment(key, comment);
+        }
+
+        private void ReadConfigString(MyIni ini, string name, ref string value, string comment)
         {
             var key = new MyIniKey(ConfigSection, name);
             MyIniValue val = ini.Get(key);
@@ -196,595 +791,43 @@
             ini.SetComment(key, comment);
         }

-        public void ReadConfigItemType(MyIni ini, string name, ref MyItemType? value, string comment)
-        {
-            var key = new MyIniKey(ConfigSection, name);
-            MyIniValue val = ini.Get(key);
-            string tmp;
-            if (val.TryGetString(out tmp))
-                value = String.IsNullOrEmpty(tmp) ? null : MyItemType.Parse(tmp.Trim());
+        private void Test(InventoryWrapper ref5, InventoryWrapper ref6)
+        {
+            IMyRefinery a2, b2;
+            if (ref5 != null && ref6 != null)
+            {
+                a2 = (IMyRefinery)GridTerminalSystem.GetBlockWithName(ref5.Block.CustomName);
+                b2 = (IMyRefinery)GridTerminalSystem.GetBlockWithName(ref6.Block.CustomName);
+                var t3 = a2.EntityId == ref5.Block.EntityId;
+                Echo(t3 ? "T3 eq OK" : "T3 eq ERR");
+            }
             else
-                ini.Set(key, value.HasValue ? value.Value.ToString() : String.Empty);
-            ini.SetComment(key, comment);
-        }
-
-        public void Save()
-        { }
-
-        private void BalanceInventories(Statistics stat, List<InventoryWrapper> group, int networkNumber,
-            int groupNumber, string groupName, Func<MyInventoryItem, bool> filter)
-        {
-            if (group.Count < 2)
-            {
-                stat.Output.Append("Cannot balance conveyor network ").Append(networkNumber + 1)
-                    .Append(" group ").Append(groupNumber + 1).Append(" \"").Append(groupName).AppendLine("\"")
-                    .AppendLine("  because there is only one inventory.");
-                return; // nothing to do
-            }
-
-            if (filter != null)
-            {
-                foreach (var wrp in group)
-                    wrp.LoadVolume().FilterItems(this, stat, filter).CalculatePercent();
-            }
-            else
-            {
-                foreach (var wrp in group)
-                    wrp.LoadVolume().CalculatePercent();
-            }
-
-            InventoryWrapper min = group[0], max = group[0];
-            for (int i = 1; i < group.Count; ++i)
-            {
-                var dt = group[i];
-                if (min.Percent > dt.Percent)
-                    min = dt;
-                if (max.Percent < dt.Percent)
-                    max = dt;
-            }
-
-            if (max.CurrentVolume < SmallNumber)
-            {
-                stat.Output.Append("Cannot balance conveyor network ").Append(networkNumber + 1)
-                    .Append(" group ").Append(groupNumber + 1).Append(" \"").Append(groupName)
-                    .AppendLine("\"")
-                    .AppendLine("  because of lack of items in it.");
-                return; // nothing to do
-            }
-
-            stat.Output.Append("Balancing conveyor network ").Append(networkNumber + 1)
-                .Append(" group ").Append(groupNumber + 1)
-                .Append(" \"").Append(groupName).AppendLine("\"...");
-
-            if (min == max)
-            {
-                stat.Output.AppendLine("  nothing to do");
+            {
+                a2 = (IMyRefinery)GridTerminalSystem.GetBlockWithName("Refinery 5");
+                b2 = (IMyRefinery)GridTerminalSystem.GetBlockWithName("Refinery 6");
+            }
+
+            if (a2 == null || b2 == null)
                 return;
-            }
-
-            decimal toMove;
-            if (min.MaxVolume == max.MaxVolume)
-            {
-                toMove = (max.CurrentVolume - min.CurrentVolume) / 2.0M;
-            }
-            else
-            {
-                toMove = (max.CurrentVolume * min.MaxVolume - min.CurrentVolume * max.MaxVolume)
-                    / (min.MaxVolume + max.MaxVolume);
-            }
-
-            stat.Output.Append("Inv. 1 vol: ").Append(min.CurrentVolume.ToString("F6")).Append("; ");
-            stat.Output.Append("Inv. 2 vol: ").Append(max.CurrentVolume.ToString("F6")).Append("; ");
-            stat.Output.Append("To move: ").Append(toMove.ToString("F6")).AppendLine();
-
-            if (toMove < 0.0M)
-                throw new InvalidOperationException("Something went wrong with calculations: volumeDiff is " + toMove);
-
-            if (toMove < SmallNumber)
-                return;
-
-            MoveVolume(stat, max, min, (VRage.MyFixedPoint)toMove, filter);
-        }
-
-        private BlockStore CollectTerminals(BlockStore bs, Statistics stat)
-        {
-            var blocks = new List<IMyTerminalBlock>();
-            Func<IMyTerminalBlock, bool> myTerminalBlockFilter = b => b.IsFunctional && (AnyConstruct || b.IsSameConstructAs(Me));
-            Func<ICollection, bool, string> countOrNA = (c, e) => e ? c.Count.ToString() : "n/a";
-
-            if (String.IsNullOrEmpty(ManagedBlocksGroup))
-            {
-                GridTerminalSystem.GetBlocksOfType(blocks, myTerminalBlockFilter);
-            }
-            else
-            {
-                var group = GridTerminalSystem.GetBlockGroupWithName(ManagedBlocksGroup);
-                if (group == null)
-                    stat.Output.Append("Error: a group ").Append(ManagedBlocksGroup).AppendLine(" has not been found");
-                else
-                    group.GetBlocksOfType(blocks, myTerminalBlockFilter);
-            }
-
-            foreach (var dt in blocks)
-                bs.Collect(dt);
-
-            if (!String.IsNullOrEmpty(DisplayLcdGroup))
-            {
-                var group = GridTerminalSystem.GetBlockGroupWithName(DisplayLcdGroup);
-                if (group != null)
-                    group.GetBlocksOfType<IMyTextPanel>(bs.DebugScreen, myTerminalBlockFilter);
-            }
-
-            if (!String.IsNullOrEmpty(DrillsPayloadLightsGroup))
-            {
-                var group = GridTerminalSystem.GetBlockGroupWithName(DrillsPayloadLightsGroup);
-                if (group != null)
-                    group.GetBlocksOfType<IMyLightingBlock>(bs.DrillsPayloadLights, myTerminalBlockFilter);
-            }
-
-            stat.Output.Append("Resource exchanger 2.5.0. Blocks managed:")
-                .Append(" reactors: ").Append(countOrNA(bs.Reactors, EnableReactors))
-                .Append(", refineries: ").Append(countOrNA(bs.Refineries, EnableRefineries)).AppendLine(",")
-                .Append("oxygen gen.: ").Append(countOrNA(bs.OxygenGenerators, EnableOxygenGenerators))
-                .Append(", drills: ").Append(countOrNA(bs.Drills, EnableDrills))
-                .Append(", turrets: ").Append(countOrNA(bs.Turrets, EnableTurrets))
-                .Append(", cargo cont.: ").Append(countOrNA(bs.CargoContainers, EnableGroups))
-                .Append(", custom groups: ").Append(countOrNA(bs.Groups, EnableGroups)).AppendLine();
-
-            return bs;
-        }
-
-        private List<InventoryGroup> DivideByBlockType(ConveyorNetwork network)
-        {
-            var groupMap = new Dictionary<string, InventoryGroup>();
-
-            foreach (var inv in network.Inventories)
-            {
-                InventoryGroup group;
-                if (!groupMap.TryGetValue(inv.GroupName, out group))
-                {
-                    group = new InventoryGroup(groupMap.Count + 1, inv.GroupName);
-                    groupMap.Add(inv.GroupName, group);
-                }
-                group.Inventories.Add(inv);
-            }
-
-            var result = new List<InventoryGroup>(groupMap.Count);
-            result.AddRange(groupMap.Values);
-            return result;
-        }
-
-        private void EnforceItemPriority(List<InventoryWrapper> group, Statistics stat, MyItemType? topPriority, MyItemType? lowestPriority)
-        {
-            if (topPriority == null && lowestPriority == null)
-                return;
-
-            foreach (var inv in group)
-            {
-                if (inv.Inventory.ItemCount < 2)
-                    continue;
-
-                var items = inv.GetItems(stat.TmpItems1, null);
-
-                if (topPriority.HasValue && !items[0].Type.Equals(topPriority.Value))
-                {
-                    for (int i = 1; i < items.Count; ++i)
-                    {
-                        var item = items[i];
-                        if (item.Type.Equals(topPriority.Value))
-                        {
-                            stat.Output.Append("Moving ").Append(topPriority.Value.SubtypeId).Append(" from ")
-                                .Append(i + 1).Append(" slot to first slot of ").AppendLine(inv.Block.CustomName);
-                            inv.MoveItem(i, 0);
-                            stat.MovementsDone += 1;
-                            break;
-                        }
-                    }
-                }
-
-                if (lowestPriority.HasValue && !items[items.Count - 1].Type.Equals(lowestPriority.Value))
-                {
-                    for (int i = items.Count - 2; i >= 0; --i)
-                    {
-                        var item = items[i];
-                        if (item.Type.Equals(lowestPriority.Value))
-                        {
-                            stat.Output.Append("Moving ").Append(lowestPriority.Value.SubtypeId).Append(" from ")
-                                .Append(i + 1).Append(" slot to last slot of ").AppendLine(inv.Block.CustomName);
-                            inv.MoveItem(i, items.Count);
-                            stat.MovementsDone += 1;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        private List<ConveyorNetwork> FindConveyorNetworks(ICollection<InventoryWrapper> inventories, HashSet<InventoryWrapper> exclude)
-        {
-            var result = new List<ConveyorNetwork>();
-
-            foreach (var wrp in inventories)
-            {
-                if (exclude != null && exclude.Contains(wrp))
-                    continue;
-
-                bool add = true;
-                foreach (var network in result)
-                {
-                    if (network.Inventories[0].Inventory.IsConnectedTo(wrp.Inventory)
-                        && wrp.Inventory.IsConnectedTo(network.Inventories[0].Inventory))
-                    {
-                        network.Inventories.Add(wrp);
-                        add = false;
-                        break;
-                    }
-                }
-
-                if (add)
-                {
-                    var network = new ConveyorNetwork(result.Count + 1);
-                    network.Inventories.Add(wrp);
-                    result.Add(network);
-                }
-            }
-
-            return result;
-        }
-
-        private string FindInvGroupName(MyItemType def, IMyInventory inv)
-        {
-            const string MY_OBJECT_BUILDER = "MyObjectBuilder_";
-
-            ulong[] groupId;
-            if (_blockToGroupIdMap.TryGetValue(def, out groupId))
-                return _groupIdToNameMap[groupId];
-
-            groupId = new ulong[ItemInfo.ID_LENGTH];
-            foreach (var kv in Items.ItemInfoDict)
-            {
-                if (inv.CanItemsBeAdded(-1, kv.Key))
-                {
-                    for (int i = 0; i < ItemInfo.ID_LENGTH; ++i)
-                        groupId[i] |= kv.Value.Id[i];
-                }
-            }
-
-            string result;
-            if (_groupIdToNameMap.TryGetValue(groupId, out result))
-            {
-                _blockToGroupIdMap.Add(def, groupId);
-                return result;
-            }
-            else
-            {
-                var fullType = def.ToString();
-                result = fullType.StartsWith(MY_OBJECT_BUILDER)
-                ? '$' + fullType.Substring(MY_OBJECT_BUILDER.Length)
-                : fullType;
-
-                _groupIdToNameMap.Add(groupId, result);
-                _blockToGroupIdMap.Add(def, groupId);
-                return result;
-            }
-        }
-
-        private VRage.MyFixedPoint MoveVolume(Statistics stat, InventoryWrapper from, InventoryWrapper to,
-            VRage.MyFixedPoint volumeAmountToMove, Func<MyInventoryItem, bool> filter)
-        {
-            if (volumeAmountToMove == 0)
-                return volumeAmountToMove;
-
-            if (volumeAmountToMove < 0)
-                throw new ArgumentException("Invalid volume amount", "volumeAmount");
-
-            stat.Output.Append("Move ").Append(volumeAmountToMove).Append(" l. from ")
-                .Append(from.Block.CustomName).Append(" to ").AppendLine(to.Block.CustomName);
-            var itemsFrom = from.GetItems(stat.TmpItems1, filter);
-
-            for (int i = itemsFrom.Count - 1; i >= 0; --i)
-            {
-                MyInventoryItem item = itemsFrom[i];
-
-                var data = Items.Get(stat, item.Type);
-                if (data == null)
-                    continue;
-
-                decimal amountToMoveRaw = (decimal)volumeAmountToMove * 1000M / data.Volume;
-                VRage.MyFixedPoint amountToMove;
-
-                if (data.HasIntegralAmounts)
-                    amountToMove = (int)(amountToMoveRaw + 0.1M);
-                else
-                    amountToMove = (VRage.MyFixedPoint)amountToMoveRaw;
-
-                if (amountToMove == 0)
-                    continue;
-
-                decimal itemVolume;
-                bool success;
-                if (amountToMove <= item.Amount)
-                {
-                    itemVolume = (decimal)amountToMove * data.Volume / 1000M;
-                    success = from.TransferItem(to, i, amountToMove);
-                    stat.MovementsDone += 1;
-                    stat.Output.Append("Move ").Append(amountToMove).Append(" -> ").AppendLine(success ? "success" : "failure");
-                }
-                else
-                {
-                    itemVolume = (decimal)item.Amount * data.Volume / 1000M;
-                    success = from.TransferItem(to, i, item.Amount);
-                    stat.MovementsDone += 1;
-                    stat.Output.Append("Move all ").Append(item.Amount).Append(" -> ").AppendLine(success ? "success" : "failure");
-                }
-
-                if (success)
-                    volumeAmountToMove -= (VRage.MyFixedPoint)itemVolume;
-                if (volumeAmountToMove < (VRage.MyFixedPoint)SmallNumber)
-                    return volumeAmountToMove;
-            }
-
-            stat.Output.Append("Cannot move ").Append(volumeAmountToMove).AppendLine(" l.");
-            return volumeAmountToMove;
-        }
-
-        private void PrintOnlineStatus(BlockStore bs, Statistics stat)
-        {
-            var sb = new StringBuilder(4096);
-
-            var blocksAffected = bs.Reactors.Count
-                + bs.Refineries.Count
-                + bs.Drills.Count
-                + bs.Turrets.Count
-                + bs.OxygenGenerators.Count
-                + bs.CargoContainers.Count;
-
-            sb.Append("Grids connected: ").Append(bs.AllGrids.Count).AppendLine(AnyConstruct ? " (AC)" : " (SC)");
-            sb.Append("Conveyor networks: ").Append(stat.NumberOfNetworks).AppendLine();
-            sb.Append("Blocks affected: ").Append(blocksAffected).AppendLine();
-
-            sb.Append("reactors: ");
-            if (bs.Reactors.Count != 0)
-                sb.Append(bs.Reactors.Count);
-            else
-                sb.Append(EnableReactors ? "0" : "OFF");
-
-            sb.Append(", refineries: ");
-            if (bs.Refineries.Count != 0)
-                sb.Append(bs.Refineries.Count);
-            else
-                sb.Append(EnableRefineries ? "0" : "OFF");
-
-            sb.AppendLine().Append("drills: ");
-            if (bs.Drills.Count != 0)
-                sb.Append(bs.Drills.Count);
-            else
-                sb.Append(EnableDrills ? "0" : "OFF");
-
-            sb.Append(", turrets: ");
-            if (bs.Turrets.Count != 0)
-                sb.Append(bs.Turrets.Count);
-            else
-                sb.Append(EnableTurrets ? "0" : "OFF");
-
-            sb.Append(", o. gen.: ");
-            if (bs.OxygenGenerators.Count != 0)
-                sb.Append(bs.OxygenGenerators.Count);
-            else
-                sb.Append(EnableOxygenGenerators ? "0" : "OFF");
-
-            sb.AppendLine().Append("cargo cont.: ");
-            if (bs.CargoContainers.Count != 0)
-                sb.Append(bs.CargoContainers.Count);
-            else
-                sb.Append(EnableGroups ? "0" : "OFF");
-
-            sb.Append(", groups: ");
-            if (bs.Groups.Count != 0)
-                sb.Append(bs.Groups.Count);
-            else
-                sb.Append(EnableGroups ? "0" : "OFF");
-
-            sb.AppendLine();
-
-            if (bs.Drills.Count != 0)
-            {
-                if (stat.NotConnectedDrillsFound)
-                    sb.AppendLine("Warn: Some drills are not connected");
-
-                sb.Append("Drills payload: ").Append(stat.DrillsPayloadStr ?? "N/A");
-                if (stat.DrillsVolumeWarning)
-                    sb.AppendLine((_cycleNumber & 0x01) == 0 ? "%  !" : "% ! !");
-                else
-                    sb.AppendLine("%");
-            }
-
-            if (stat.MissingInfo.Count > 0)
-                sb.Append("Err: missing volume information for ").AppendLine(String.Join(", ", stat.MissingInfo));
-
-            _avgMovements[_cycleNumber & 0x0F] = stat.MovementsDone;
-            var samples = Math.Min(_cycleNumber + 1, 0x10);
-            double avg = 0;
-            for (int i = 0; i < samples; ++i)
-                avg += _avgMovements[i];
-            avg /= samples;
-
-            sb.Append("Avg. movements: ").Append(avg.ToString("F2")).Append(" (last ").Append(samples).AppendLine(" runs)");
-
-            float cpu = Runtime.CurrentInstructionCount * 100;
-            cpu /= Runtime.MaxInstructionCount;
-            sb.Append("Complexity limit usage: ").Append(cpu.ToString("F2")).AppendLine("%");
-
-            sb.Append("Last run time: ").Append(Runtime.LastRunTimeMs.ToString("F1")).AppendLine(" ms");
-
-            var tab = new char[42];
-            for (int i = 0; i < 42; ++i)
-            {
-                char c = ' ';
-                if (i % 21 == 1)
-                    c = '|';
-                else if (i % 7 < 4)
-                    c = '·';
-                tab[41 - (i + _cycleNumber) % 42] = c;
-            }
-            sb.AppendLine(new string(tab));
-            ++_cycleNumber;
-
-            Echo(sb.ToString());
-        }
-
-        private int ProcessBlocks(string msg, bool enable, ICollection<InventoryWrapper> blocks, Statistics stat, string invGroup = null,
-            HashSet<InventoryWrapper> exclude = null, Func<MyInventoryItem, bool> filter = null)
-        {
-            stat.Output.Append(msg);
-            if (enable)
-            {
-                if (blocks.Count >= 2)
-                {
-                    var conveyorNetworks = FindConveyorNetworks(blocks, exclude);
-                    stat.NumberOfNetworks += conveyorNetworks.Count;
-                    stat.Output.Append(": ").Append(conveyorNetworks.Count).AppendLine(" conveyor networks found");
-
-                    if (invGroup != null)
-                    {
-                        foreach (var network in conveyorNetworks)
-                            BalanceInventories(stat, network.Inventories, network.No, 0, invGroup, filter);
-                    }
-                    else
-                    {
-                        foreach (var network in conveyorNetworks)
-                            foreach (var group in DivideByBlockType(network))
-                                BalanceInventories(stat, group.Inventories, network.No, group.No, group.Name, filter);
-                    }
-
-                    return conveyorNetworks.Count;
-                }
-                else
-                {
-                    stat.Output.AppendLine(": nothing to do");
-                    return 0;
-                }
-            }
-            else
-            {
-                stat.Output.AppendLine(": disabled");
-                return -1;
-            }
-        }
-
-        private void ProcessDrillsLights(List<InventoryWrapper> drills, List<IMyLightingBlock> lights, Statistics stat)
-        {
-            VRage.MyFixedPoint warningLevelInCubicMetersLeft = 5;
-            Func<Color> step0 = () => new Color(255, 255, 255);
-            Func<Color> step1 = () => new Color(255, 255, 0);
-            Func<Color> step2 = () => new Color(255, 0, 0);
-            Func<Color> warn = () => (_cycleNumber & 0x1) == 0 ? new Color(128, 0, 128) : new Color(128, 0, 64);
-            Func<Color> err = () => (_cycleNumber & 0x1) == 0 ? new Color(0, 128, 128) : new Color(0, 64, 128);
-
-            if (lights.Count == 0)
-            {
-                stat.Output.AppendLine("Setting color of drills payload indicators. Not enough lights found. Nothing to do.");
-                return;
-            }
-
-            stat.Output.AppendLine("Setting color of drills payload indicators.");
-
-            Color color;
-            if (stat.NotConnectedDrillsFound)
-            {
-                stat.Output.AppendLine("Not all drills are connected.");
-                color = err();
-            }
-            else
-            {
-                var drillsMaxVolume = VRage.MyFixedPoint.Zero;
-                var drillsCurrentVolume = VRage.MyFixedPoint.Zero;
-                foreach (var drill in drills)
-                {
-                    drillsMaxVolume += drill.Inventory.MaxVolume;
-                    drillsCurrentVolume += drill.Inventory.CurrentVolume;
-                }
-
-                if (drillsMaxVolume > 0)
-                {
-                    var p = (float)drillsCurrentVolume * 1000.0f;
-                    p /= (float)drillsMaxVolume;
-
-                    stat.DrillsPayloadStr = (p / 10.0f).ToString("F1");
-
-                    stat.Output.Append("Drills space usage: ");
-                    stat.Output.Append(stat.DrillsPayloadStr);
-                    stat.Output.AppendLine("%");
-
-                    stat.DrillsVolumeWarning = (drillsMaxVolume - drillsCurrentVolume) < warningLevelInCubicMetersLeft;
-                    if (stat.DrillsVolumeWarning)
-                    {
-                        color = warn();
-                    }
-                    else
-                    {
-                        Color c1, c2;
-                        float m1, m2;
-
-                        if (p < 500.0f)
-                        {
-                            c1 = step0();
-                            c2 = step1();
-                            m2 = p / 500.0f;
-                            m1 = 1.0f - m2;
-                        }
-                        else
-                        {
-                            c1 = step2();
-                            c2 = step1();
-                            m1 = (p - 500.0f) / 450.0f;
-                            if (m1 > 1.0f)
-                                m1 = 1.0f;
-                            m2 = 1.0f - m1;
-                        }
-
-                        float r = c1.R * m1 + c2.R * m2;
-                        float g = c1.G * m1 + c2.G * m2;
-                        float b = c1.B * m1 + c2.B * m2;
-
-                        if (r > 255.0f)
-                            r = 255.0f;
-                        else if (r < 0.0f)
-                            r = 0.0f;
-
-                        if (g > 255.0f)
-                            g = 255.0f;
-                        else if (g < 0.0f)
-                            g = 0.0f;
-
-                        if (b > 255.0f)
-                            b = 255.0f;
-                        else if (b < 0.0f)
-                            b = 0.0f;
-
-                        color = new Color((int)r, (int)g, (int)b);
-                    }
-                }
-                else
-                {
-                    color = step0();
-                }
-            }
-
-            stat.Output.Append("Drills payload indicators lights color: ");
-            stat.Output.Append(color);
-            stat.Output.AppendLine();
-
-            foreach (IMyLightingBlock light in lights)
-            {
-                var currentColor = light.GetValue<Color>("Color");
-                if (currentColor != color)
-                    light.SetValue<Color>("Color", color);
-            }
-
-            stat.Output.Append("Color of ");
-            stat.Output.Append(lights.Count);
-            stat.Output.AppendLine(" drills payload indicators has been set.");
+
+            var t1 = a2.InputInventory.IsConnectedTo(b2.InputInventory);
+            var t2 = a2.InputInventory.CanTransferItemTo(b2.InputInventory, TopRefineryPriority.Value);
+            var s = a2.CustomName + " " + b2.CustomName;
+            Echo("T1 " + s + (t1 ? " OK" : " ERR"));
+            Echo("T2 " + s + (t2 ? " OK" : " ERR"));
+
+            //var a = wrp.Block.CustomName;
+            //var b = network.Inventories[0].Block.CustomName;
+            //if (a.StartsWith("Refinery ") && b.StartsWith("Refinery "))
+            //{
+            //    Echo(network.Inventories[0].Inventory.IsConnectedTo(wrp.Inventory) ? b + " conn " + a : b + " nc " + a);
+            //    Echo(wrp.Inventory.IsConnectedTo(network.Inventories[0].Inventory) ? a + " conn " + b : a + " nc " + b);
+            //    var a2 = (IMyRefinery)GridTerminalSystem.GetBlockWithName("Refinery 2");
+            //    var b2 = (IMyRefinery)GridTerminalSystem.GetBlockWithName("Refinery 5");
+            //    Echo(a2.InputInventory.IsConnectedTo(b2.InputInventory) ? "conn" : "notc");
+            //    if (a == "Refinery 5")
+            //        Echo(wrp.Block == a2 ? "same" : "nots");
+            //}
         }

         private void WriteOutput(BlockStore bs, Statistics stat)
@@ -886,7 +929,7 @@
                 if (!_program.EnableGroups)
                     return true;

-                var inv = InventoryWrapper.Create(_program, myCargoContainer);
+                var inv = InventoryWrapper.Create(_program, myCargoContainer, myCargoContainer.GetInventory());
                 if (inv != null)
                 {
                     CargoContainers.Add(inv);
@@ -904,7 +947,7 @@
                 if (!_program.EnableDrills || !myDrill.UseConveyorSystem)
                     return true;

-                var inv = InventoryWrapper.Create(_program, myDrill);
+                var inv = InventoryWrapper.Create(_program, myDrill, myDrill.GetInventory());
                 if (inv != null)
                 {
                     Drills.Add(inv);
@@ -923,7 +966,7 @@
                 if (!_program.EnableOxygenGenerators)
                     return true;

-                var inv = InventoryWrapper.Create(_program, myOxygenGenerator);
+                var inv = InventoryWrapper.Create(_program, myOxygenGenerator, myOxygenGenerator.GetInventory());
                 if (inv != null)
                 {
                     OxygenGenerators.Add(inv);
@@ -942,7 +985,7 @@
                 if (!_program.EnableReactors || !myReactor.UseConveyorSystem)
                     return true;

-                var inv = InventoryWrapper.Create(_program, myReactor);
+                var inv = InventoryWrapper.Create(_program, myReactor, myReactor.GetInventory());
                 if (inv != null)
                 {
                     Reactors.Add(inv);
@@ -961,7 +1004,7 @@
                 if (!_program.EnableRefineries || !myRefinery.UseConveyorSystem)
                     return true;

-                var inv = InventoryWrapper.Create(_program, myRefinery);
+                var inv = InventoryWrapper.Create(_program, myRefinery, myRefinery.InputInventory);
                 if (inv != null)
                 {
                     Refineries.Add(inv);
@@ -980,7 +1023,7 @@
                 if (!_program.EnableTurrets || myTurret is IMyLargeInteriorTurret)
                     return true;

-                var inv = InventoryWrapper.Create(_program, myTurret);
+                var inv = InventoryWrapper.Create(_program, myTurret, myTurret.GetInventory());
                 if (inv != null)
                 {
                     Turrets.Add(inv);
@@ -1027,10 +1070,9 @@
             public decimal MaxVolume;
             public decimal Percent;

-            public static InventoryWrapper Create(Program prog, IMyTerminalBlock block)
-            {
-                var inv = block.GetInventory(0);
-                if (inv != null && inv.MaxVolume > 0)
+            public static InventoryWrapper Create(Program prog, IMyTerminalBlock block, IMyInventory inv)
+            {
+                if (inv.MaxVolume > 0)
                 {
                     var result = new InventoryWrapper();
                     result.Block = block;
@@ -1045,13 +1087,6 @@
             public void CalculatePercent()
             {
                 Percent = CurrentVolume / MaxVolume;
-            }
-
-            public List<MyInventoryItem> GetItems(List<MyInventoryItem> list, Func<MyInventoryItem, bool> filter)
-            {
-                list.Clear();
-                Inventory.GetItems(list, filter);
-                return list;
             }

             public InventoryWrapper FilterItems(Program prog, Statistics stat, Func<MyInventoryItem, bool> filter)
@@ -1077,6 +1112,13 @@
                 return this;
             }

+            public List<MyInventoryItem> GetItems(List<MyInventoryItem> list, Func<MyInventoryItem, bool> filter)
+            {
+                list.Clear();
+                Inventory.GetItems(list, filter);
+                return list;
+            }
+
             public InventoryWrapper LoadVolume()
             {
                 CurrentVolume = (decimal)Inventory.CurrentVolume;
@@ -1084,15 +1126,15 @@
                 return this;
             }

+            public bool MoveItem(int sourceItemIndex, int targetItemIndex)
+            {
+                return Inventory.TransferItemTo(Inventory, sourceItemIndex, targetItemIndex, false, null);
+            }
+
             public bool TransferItem(InventoryWrapper dst, int sourceItemIndex, VRage.MyFixedPoint amount)
             {
                 return Inventory.TransferItemTo(dst.Inventory, sourceItemIndex, null, true, amount);
             }
-
-            public bool MoveItem(int sourceItemIndex, int targetItemIndex)
-            {
-                return Inventory.TransferItemTo(Inventory, sourceItemIndex, targetItemIndex, false, null);
-            }
         }

         internal class ItemDict
@@ -1102,33 +1144,6 @@
             public ItemDict()
             {
                 ItemInfoDict = new Dictionary<MyItemType, ItemInfo>();
-            }
-
-            public void Add(string mainType, string subtype, decimal mass, decimal volume, bool hasIntegralAmounts, bool isStackable)
-            {
-                var key = new MyItemType(mainType, subtype);
-                var value = new ItemInfo(ItemInfoDict.Count, mass, volume, hasIntegralAmounts, isStackable);
-                try
-                {
-                    ItemInfoDict.Add(key, value);
-                }
-                catch (ArgumentException ex)
-                {
-                    throw new InvalidOperationException("Item info for " + mainType + "/" + subtype + " already added", ex);
-                }
-            }
-
-            public ItemInfo Get(Statistics stat, MyItemType key)
-            {
-                ItemInfo data;
-                if (ItemInfoDict.TryGetValue(key, out data))
-                    return data;
-
-                stat.Output.Append("Volume to amount ratio for ");
-                stat.Output.Append(key);
-                stat.Output.AppendLine(" is not known.");
-                stat.MissingInfo.Add(key.ToString());
-                return null;
             }

             public static ItemDict BuildItemInfoDict()
@@ -1579,6 +1594,33 @@

                 return ret;
             }
+
+            public void Add(string mainType, string subtype, decimal mass, decimal volume, bool hasIntegralAmounts, bool isStackable)
+            {
+                var key = new MyItemType(mainType, subtype);
+                var value = new ItemInfo(ItemInfoDict.Count, mass, volume, hasIntegralAmounts, isStackable);
+                try
+                {
+                    ItemInfoDict.Add(key, value);
+                }
+                catch (ArgumentException ex)
+                {
+                    throw new InvalidOperationException("Item info for " + mainType + "/" + subtype + " already added", ex);
+                }
+            }
+
+            public ItemInfo Get(Statistics stat, MyItemType key)
+            {
+                ItemInfo data;
+                if (ItemInfoDict.TryGetValue(key, out data))
+                    return data;
+
+                stat.Output.Append("Volume to amount ratio for ");
+                stat.Output.Append(key);
+                stat.Output.AppendLine(" is not known.");
+                stat.MissingInfo.Add(key.ToString());
+                return null;
+            }
         }

         internal class ItemInfo


Another typo

Another typo

--- src/SFA.DAS.EAS.Web/Views/EmployerTeam/Index.cshtml
+++ src/SFA.DAS.EAS.Web/Views/EmployerTeam/Index.cshtml
@@ -61,7 +61,7 @@

Help us improve this service

-
Take our 3 minute survey so that we can improve the service.

+
Take our 3 minute survey so that we can improve this service.

Take the survey so that we can improve the service


Fixed default value comparison

Fixed default value comparison

--- src/ServiceBase/Extensions/IEnumerableExtensions.cs
+++ src/ServiceBase/Extensions/IEnumerableExtensions.cs
@@ -544,17 +544,18 @@
             var removed = new List<TSource>();
             var added = new List<TSource>();
             var updated = new List<TSource>();
+            TSource defaultOfTSource = default(TSource);

             removed = listMaster.Select(s => s).ToList();
             added = listUpdated.Select(s => s).ToList();

             for (int i = removed.Count - 1; i >= 0; i--)
             {
-                var item = removed[i];
-                var itemUpdated = listUpdated
+                TSource item = removed[i];
+                TSource itemUpdated = listUpdated
                     .FirstOrDefault(c => c.Equals(item));
-
-                if (!itemUpdated.Equals(default(TSource)))
+
+                if (!Comparison<TSource>.Equals(defaultOfTSource, itemUpdated))
                 {
                     updated.Add(itemUpdated);
                     added.Remove(item);


Min pooled array size is 2, not 16

Min pooled array size is 2, not 16

--- src/Spreads.Core/System/Buffers/DefaultArrayPool.cs
+++ src/Spreads.Core/System/Buffers/DefaultArrayPool.cs
@@ -11,7 +11,7 @@
         /// The default maximum length of each array in the pool (2^20).
         private const int DefaultMaxArrayLength = 1024 * 1024;
         /// The minimum length of an array in the pool.
-        private const int MinimumArrayLength = 16;
+        private const int MinimumArrayLength = 2;

         private readonly DefaultArrayPoolBucket<T>[] _buckets;


Consolidates calculation for streamVersion so that if long.maxvalue, reduced by one to stop possible issues with queries.

--- src/SqlStreamStore.Sqlite/SqliteStreamStore.Read.cs
+++ src/SqlStreamStore.Sqlite/SqliteStreamStore.Read.cs
@@ -18,10 +18,6 @@
         {
             GuardAgainstDisposed();
             cancellationToken.ThrowIfCancellationRequested();
-
-            // If the count is int.MaxValue, TSql will see it as a negative number.
-            // Users shouldn't be using int.MaxValue in the first place anyway.
-            var maxRecords = count == int.MaxValue ? count - 1 : count;

             using(var connection = OpenConnection())
             {
@@ -49,7 +45,7 @@
                     fromVersion,
                     prefetch,
                     readNext,
-                    maxRecords,
+                    count,
                     streamProperties.MaxAge);
             }
         }
@@ -65,9 +61,6 @@
             GuardAgainstDisposed();
             cancellationToken.ThrowIfCancellationRequested();

-            // If the count is int.MaxValue, TSql will see it as a negative number.
-            // Users shouldn't be using int.MaxValue in the first place anyway.
-            var maxRecords = count == int.MaxValue ? count - 1 : count;
             var streamVersion = fromStreamVersion == StreamVersion.End ? int.MaxValue - 1 : fromStreamVersion;
             using(var connection = OpenConnection())
             {
@@ -114,7 +107,7 @@
                     fromStreamVersion,
                     prefetch,
                     readNext,
-                    maxRecords,
+                    count,
                     streamProperties.MaxAge);
             }
         }
@@ -129,6 +122,9 @@
             int maxRecords,
             int? maxAge)
         {
+            // If the count is int.MaxValue, TSql will see it as a negative number.
+            // Users shouldn't be using int.MaxValue in the first place anyway.
+            maxRecords = maxRecords == int.MaxValue ? maxRecords - 1 : maxRecords;
             var streamVersion = fromVersion == StreamVersion.End ? int.MaxValue -1 : fromVersion;
             int nextVersion = 0;
             var stream = connection.Streams(streamId);


CircularQueue fixed overrounding

CircularQueue fixed overrounding

* fixed overrounding of enqueue pointer
* removed unneeded total counter

--- src/biz.dfch.CS.Commons/Collections/CircularQueue.cs
+++ src/biz.dfch.CS.Commons/Collections/CircularQueue.cs
@@ -28,9 +28,9 @@

         private volatile bool isInitialised;

-        private int enqueuePointer;
-        private int dequeuePointer;
-        private int enqueuedItems;
+        private volatile int enqueuePointer;
+        private volatile int dequeuePointer;
+
         private readonly int capacity;
         public int Capacity
         {
@@ -41,7 +41,7 @@

         private readonly object _lock = new object();

-        private ManualResetEventSlim manualResetEventSlim = new ManualResetEventSlim(false);
+        private readonly ManualResetEventSlim manualResetEventSlim = new ManualResetEventSlim(false);

         public CircularQueue()
             : this(CAPACITY_DEFAULT)
@@ -65,6 +65,10 @@
                 {
                     list.Add(item);

+                    // once we filled the whole list with items
+                    // we consider the list to be initialised
+                    // i.e. we do not have to add any more items
+                    // but just have to overwrite an existing item
                     isInitialised = 0 == (enqueuePointer = ++enqueuePointer % capacity);
                 }
                 else
@@ -74,7 +78,14 @@
                     enqueuePointer = ++enqueuePointer % capacity;
                 }

-                enqueuedItems++;
+                // if enqueue operations pointer "overrounds" dequeue pointer
+                // we have to increment the dequeue pointer so it reads the
+                // oldest item
+                if (enqueuePointer == dequeuePointer)
+                {
+                    dequeuePointer = ++dequeuePointer % capacity;
+                }
+
                 manualResetEventSlim.Set();
             }
         }
@@ -84,6 +95,8 @@
             var result = TryDequeue(out item);
             if (result)
             {
+                manualResetEventSlim.Reset();
+
                 return true;
             }

@@ -93,9 +106,10 @@
                 return false;
             }

+            result = TryDequeue(out item);
+
             manualResetEventSlim.Reset();

-            result = TryDequeue(out item);
             return result;
         }

@@ -103,7 +117,7 @@
         {
             lock (_lock)
             {
-                if (0 >= enqueuedItems)
+                if (enqueuePointer == dequeuePointer)
                 {
                     item = default(T);
                     return false;
@@ -113,8 +127,6 @@

                 dequeuePointer = ++dequeuePointer % capacity;

-                enqueuedItems--;
-
                 return true;
             }
         }
@@ -123,7 +135,7 @@
         {
             lock (_lock)
             {
-                if (0 >= enqueuedItems)
+                if (enqueuePointer == dequeuePointer)
                 {
                     item = default(T);
                     return false;


- centroid input points must be ordered - OpenPolyPoints ext method to return a polygon points without duplicate last,first - sort convex poly points - helper method to create lwpolyline using netdxf library from an array of poly points Vector3D or segments Line3D

--- src/Polygon.cs
+++ src/Polygon.cs
@@ -28,8 +28,9 @@
 using SearchAThing.Core;
 using static System.Math;
 using System.Collections.Generic;
-
-namespace SearchAThing.Sci
+using SearchAThing.Sci;
+
+namespace SearchAThing
 {

     public static partial class Extentions
@@ -39,7 +40,7 @@
         /// Area of a polygon (does not consider z)
         /// https://en.wikipedia.org/wiki/Centroid
         /// </summary>
-        public static double Area(this List<Vector3D> pts, double tol)
+        public static double Area(this IList<Vector3D> pts, double tol)
         {
             var lastEqualsFirst = pts[pts.Count - 1].EqualsTol(tol, pts[0]);
             double a = 0;
@@ -55,9 +56,22 @@

         /// <summary>
         /// Centroid of a polygon (does not consider z)
+        /// points must ordered
+        /// ( if have area specify the parameter to avoid recomputation )
         /// https://en.wikipedia.org/wiki/Centroid
         /// </summary>
-        public static Vector3D Centroid(this List<Vector3D> pts, double tol, double area)
+        public static Vector3D Centroid(this IList<Vector3D> pts, double tol)
+        {
+            var area = pts.Area(tol);
+            return pts.Centroid(tol, area);
+        }
+
+        /// <summary>
+        /// Centroid of a polygon (does not consider z)
+        /// points must ordered
+        /// https://en.wikipedia.org/wiki/Centroid
+        /// </summary>
+        public static Vector3D Centroid(this IList<Vector3D> pts, double tol, double area)
         {
             var lastEqualsFirst = pts[pts.Count - 1].EqualsTol(tol, pts[0]);
             double x = 0;
@@ -76,6 +90,24 @@
             }

             return new Vector3D(x / (6 * area), y / (6 * area), 0);
+        }
+
+        /// <summary>
+        /// given a set of polygon pts, returns the enumeation of all pts except the last if equals the first
+        /// </summary>
+        public static IEnumerable<Vector3D> OpenPolyPoints(this IEnumerable<Vector3D> pts, double tol)
+        {
+            Vector3D first = null;
+
+            foreach (var p in pts)
+            {
+                if (first == null)
+                    first = p;
+                else
+                    if (first.EqualsTol(tol, p)) yield break;
+
+                yield return p;
+            }
         }

         /// <summary>
@@ -104,13 +136,13 @@
             if (!prev.EqualsTol(tol, first)) yield return new Line3D(prev, first);
         }

-        /// <summary>
+        /// <summary>
         /// states if the given polygon contains the test point ( z not considered )
         /// https://en.wikipedia.org/wiki/Point_in_polygon
         /// By default check the point contained in the polygon perimeter.
         /// </summary>
         /// <param name="excludePerimeter">Exclude check point contained in the perimeter</param>
-        public static bool ContainsPoint(this List<Vector3D> pts, double tol, Vector3D pt, bool excludePerimeter = false)
+        public static bool ContainsPoint(this IList<Vector3D> pts, double tol, Vector3D pt, bool excludePerimeter = false)
         {
             var ray = new Line3D(pt, Vector3D.XAxis, Line3DConstructMode.PointAndVector);

@@ -137,6 +169,40 @@
             return intCnt % 2 != 0;
         }

+        public static IEnumerable<Vector3D> SortPoly(this IList<Vector3D> pts, double tol)
+        {
+            var c = pts.Mean();
+
+            // search non-null ref axis
+            Vector3D N = null;
+            var r = pts.First() - c;
+            foreach (var r2 in pts.Skip(1))
+            {
+                N = r.CrossProduct(r2 - c);
+                if (!N.Length.EqualsTol(tol, 0)) break;
+            }
+
+            var q = pts.Select(p => new
+            {
+                pt = p,
+                ang = r.AngleToward(tol, p - c, N)
+            });
+            var res = q.OrderBy(w => w.ang).Select(w => w.pt);
+
+            return res;
+        }
+
+        public static netDxf.Entities.LwPolyline ToLwPolyline(this IEnumerable<Vector3D> pts, double tol)
+        {
+            return new netDxf.Entities.LwPolyline(pts.OpenPolyPoints(tol).Select(r => r.ToVector2()).ToList(), true);
+        }
+
+        public static netDxf.Entities.LwPolyline ToLwPolyline(this IEnumerable<Line3D> segs, double tol)
+        {
+            var X = segs.Select(w => w.From).OpenPolyPoints(tol);
+            return new netDxf.Entities.LwPolyline(X.Select(r => r.ToVector2()).ToList(), true);
+        }
+
     }

 }


Fix Path.Join argument nullable annotation (#24719)

--- src/System.Private.CoreLib/shared/System/IO/Path.cs
+++ src/System.Private.CoreLib/shared/System/IO/Path.cs
@@ -468,7 +468,7 @@
             return Join(path1.AsSpan(), path2.AsSpan(), path3.AsSpan(), path4.AsSpan());
         }

-        public static string Join(params string[] paths)
+        public static string Join(params string?[] paths)
         {
             if (paths == null)
             {
@@ -481,7 +481,7 @@
             }

             int maxSize = 0;
-            foreach (string path in paths)
+            foreach (string? path in paths)
             {
                 maxSize += path?.Length ?? 0;
             }
@@ -493,12 +493,11 @@

             for (int i = 0; i < paths.Length; i++)
             {
-                if ((paths[i]?.Length ?? 0) == 0)
+                string? path = paths[i];
+                if (path == null || path.Length == 0)
                 {
                     continue;
                 }
-
-                string path = paths[i];

                 if (builder.Length == 0)
                 {


Removing unnecesary lines from dispose method

--- src/Take.Elephant.Kafka/PartitionedKafkaReceiver.cs
+++ src/Take.Elephant.Kafka/PartitionedKafkaReceiver.cs
@@ -154,8 +154,6 @@

         public void Dispose()
         {
-            _partitionedConsumer.Close();
-            _partitionedConsumer.Dispose();
             Dispose(true);
             GC.SuppressFinalize(this);
         }


Fixes ParameterEditor - constructs config on ctor, no overrides.

--- src/Umbraco.Core/PropertyEditors/ParameterEditor.cs
+++ src/Umbraco.Core/PropertyEditors/ParameterEditor.cs
@@ -18,6 +18,7 @@
         /// </summary>
         public ParameterEditor()
         {
+            Configuration = new Dictionary<string, object>();
             //assign properties based on the attribute if it is found
             _attribute = GetType().GetCustomAttribute<ParameterEditorAttribute>(false);
             if (_attribute != null)
@@ -50,7 +51,7 @@
         /// Allows a parameter editor to be re-used based on the configuration specified.
         /// </summary>
         [JsonProperty("config")]
-        public virtual IDictionary<string, object> Configuration { get; set; }
+        public IDictionary<string, object> Configuration { get; set; }

         [JsonIgnore]
         public ParameterValueEditor ValueEditor


use VS shell utility to get TextView

use VS shell utility to get TextView

--- src/VisualStudio/Core/Def/RoslynDocumentProvider.cs
+++ src/VisualStudio/Core/Def/RoslynDocumentProvider.cs
@@ -49,30 +49,20 @@

         private ITextView GetTextViewFromFrame(IVsWindowFrame frame)
         {
-            object documentView;
-            if (ErrorHandler.Failed(frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocView, out documentView)))
+            try
             {
-                return null;
+                var vsTextView = Shell.VsShellUtilities.GetTextView(frame);
+                if (vsTextView != null)
+                {
+                    return EditorAdaptersFactoryService.GetWpfTextView(vsTextView);
+                }
+            }
+            catch
+            {
+                // if we couldn't get view due to any reason, return null
             }

-            var vsTextView = documentView as IVsTextView;
-            if (vsTextView != null)
-            {
-                return EditorAdaptersFactoryService.GetWpfTextView(vsTextView);
-            }
-
-            var codeWindow = documentView as IVsCodeWindow;
-            if (codeWindow == null)
-            {
-                return null;
-            }
-
-            if (ErrorHandler.Failed(codeWindow.GetPrimaryView(out vsTextView)) || vsTextView == null)
-            {
-                return null;
-            }
-
-            return EditorAdaptersFactoryService.GetWpfTextView(vsTextView);
+            return null;
         }
     }
 }


Fix other async void issue

Fix other async void issue

--- src/WPF/ArcGISRuntime.WPF.Viewer/MainWindow.xaml.cs
+++ src/WPF/ArcGISRuntime.WPF.Viewer/MainWindow.xaml.cs
@@ -62,7 +62,7 @@
             }
         }

-        private void categories_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
+        private async void categories_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
         {
             var context = (e.NewValue as TreeViewItem);
             if (context == null) {return;}
@@ -76,9 +76,9 @@
             }
             else if (sample != null)
             {
-                SelectSample(sample);
                 DetailsRegion.Visibility = Visibility.Visible;
                 CategoriesRegion.Visibility = Visibility.Collapsed;
+                await SelectSample(sample);
             }
         }


Exposing ID in data

Exposing ID in data

--- src/Wikiled.Arff/Extensions/ArffDataSetExtension.cs
+++ src/Wikiled.Arff/Extensions/ArffDataSetExtension.cs
@@ -8,13 +8,13 @@
 {
     public static class ArffDataSetExtension
     {
-        public static IEnumerable<(int? Y, double[] X)> GetData(this IArffDataSet dataSet)
+        public static IEnumerable<(string Id, int? Y, double[] X)> GetData(this IArffDataSet dataSet)
         {
             var table = GetFeatureTable(dataSet);
             foreach (var dataRow in dataSet.Documents)
             {
                 var y = dataSet.Header.Class?.ReadClassIdValue(dataRow.Class);
-                yield return (y, dataRow.GetX(table));
+                yield return (dataRow.Id, y, dataRow.GetX(table));
             }
         }


more clean up. moving method arounds

more clean up. moving method arounds

--- src/Workspaces/Remote/Core/Services/AssetService.cs
+++ src/Workspaces/Remote/Core/Services/AssetService.cs
@@ -57,7 +57,8 @@
             // this only works when caller wants to get same kind of assets at once

             // bulk synchronize checksums first
-            await SynchronizeAssetsAsync(checksums, cancellationToken).ConfigureAwait(false);
+            var syncer = new ChecksumSynchronizer(this);
+            await syncer.SynchronizeAssetsAsync(checksums, cancellationToken).ConfigureAwait(false);

             var list = new List<ValueTuple<Checksum, T>>();
             foreach (var checksum in checksums)
@@ -66,14 +67,6 @@
             }

             return list;
-        }
-
-        public async Task SynchronizeAssetsAsync(IEnumerable<Checksum> checksums, CancellationToken cancellationToken)
-        {
-            // if caller wants to get different kind of assets at once, he needs to first sync asserts and use
-            // GetAssetAsync to get those.
-            var syncer = new ChecksumSynchronizer(this);
-            await syncer.SynchronizeAssetsAsync(checksums, cancellationToken).ConfigureAwait(false);
         }

         public async Task SynchronizeSolutionAssetsAsync(Checksum solutionChecksum, CancellationToken cancellationToken)
@@ -121,7 +114,7 @@
             return _assetStorage.TryGetAsset(checksum, out unused);
         }

-        private async Task SynchronizeAssetsAsync(ISet<Checksum> checksums, CancellationToken cancellationToken)
+        public async Task SynchronizeAssetsAsync(ISet<Checksum> checksums, CancellationToken cancellationToken)
         {
             using (Logger.LogBlock(FunctionId.AssetService_SynchronizeAssetsAsync, Checksum.GetChecksumsLogInfo, checksums, cancellationToken))
             {