private IEnumerable<string> GetTransitiveClosure(string state)
        {
            var result = new HashSet<string> { state };
            while (result.Union(result.SelectMany(s => GetTransitions(s, null))).Distinct().Count() != result.Count)
            {
                result.SelectMany(s => GetTransitions(s, null)).ToArray().ForEach(s => result.Add(s));
            }

            return result;
        }
 private void BtnAddcheck_Click(object sender, RoutedEventArgs e)
 {
     ScanImportFolders frm = new ScanImportFolders();
     frm.Owner = GetTopParent();
     bool? result = frm.ShowDialog();
     if (result.HasValue && result.Value)
     {
         this.IsEnabled = false;
         Cursor = Cursors.Wait;
         Scan s = frm.SelectedScan;
         HashSet<int> imp=new HashSet<int>(s.ImportFolderList);
         List<VideoLocal> vl=imp.SelectMany(a=>RepoFactory.VideoLocal.GetByImportFolder(a)).Distinct().ToList();
         List<ScanFile> files=new List<ScanFile>();
         foreach (VideoLocal v in vl)
         {
             foreach (VideoLocal_Place p in v.Places.Where(a => imp.Contains(a.ImportFolderID)))
             {
                 ScanFile sfile=new ScanFile();
                 sfile.Hash = v.ED2KHash;
                 sfile.FileSize = v.FileSize;
                 sfile.FullName = p.FullServerPath;
                 sfile.ScanID = s.ScanID;
                 sfile.Status = (int) ScanFileStatus.Waiting;
                 sfile.ImportFolderID = p.ImportFolderID;
                 sfile.VideoLocal_Place_ID = p.VideoLocal_Place_ID;
                 files.Add(sfile);
             }
         }
         RepoFactory.ScanFile.Save(files);
         this.IsEnabled = true;
         Scanner.Instance.Scans.Add(s);
         comboProvider.SelectedItem = s;
         Cursor = Cursors.Arrow;
     }
 }
        private static IEnumerable<CompAir> ContiguousAirBuildings( Building root, NetLayer layer )
        {
            closedSet.Clear();
            currentSet.Clear();
            openSet.Add( root );

            do
            {
                //Move all opened to closed
                foreach (var current in openSet)
                {
                    closedSet.Add( current );
                }

                var tempSet = currentSet;
                currentSet = openSet;
                openSet = tempSet;
                openSet.Clear();

                foreach (var things in currentSet.SelectMany( openBuilding =>
                                                                  GenAdj.CellsAdjacentCardinal( openBuilding )
                                                                        .Select( openCells => openCells.GetThingList() ) )
                    )
                {
                    //All adjacent things
                    foreach (var current in things)
                    {
                        var building = current as Building;
                        var compAir = building?.TryGetComp< CompAir >();

                        //No adjacent CompAir
                        if (compAir == null)
                        {
                            continue;
                        }
                        //CompAir is not on the same layer
                        if (!compAir.IsLayerOf( layer ))
                        {
                            continue;
                        }
                        //Already swept through
                        if (openSet.Contains( building ) ||
                            currentSet.Contains( building ) ||
                            closedSet.Contains( building ))
                        {
                            continue;
                        }

                        openSet.Add( building );
                        break;
                    }
                }
            } while (openSet.Count > 0);

            return from b in closedSet
                   select b.TryGetComp< CompAir >();
        }
Example #4
0
        public string[] GetAllSequenceFileNames()
        {
            // We can't assume where all of the sequence file types will exist, so to provide
            // this functionality we will have to do the following:

            // Iterate all of the sequence type descriptors and build a set of file types.
            HashSet<string> fileTypes = new HashSet<string>();
            IEnumerable<ISequenceTypeModuleDescriptor> sequenceDescriptors =
                Modules.GetDescriptors<ISequenceTypeModuleInstance, ISequenceTypeModuleDescriptor>();
            foreach (ISequenceTypeModuleDescriptor descriptor in sequenceDescriptors) {
                fileTypes.Add(descriptor.FileExtension);
            }
            // Find all files of those types in the data branch.
            return
                fileTypes.SelectMany(x => Directory.GetFiles(Paths.DataRootPath, "*" + x, SearchOption.AllDirectories)).ToArray();
        }
Example #5
0
        public ReadOnlyCollection<IField> GetFields(bool includeInherited)
        {
            if (includeInherited && _allFields == null)
            {
                List<Field> allFields = new List<Field>(GetFields(false).Cast<Field>());

                HashSet<ReferenceType> inheritedTypes = new HashSet<ReferenceType>();
                GetInheritedTypes(this, inheritedTypes);
                allFields.AddRange(inheritedTypes.SelectMany(type => type.GetFields(false)).Cast<Field>());

                _allFields = allFields.ToArray();
            }
            else if (!includeInherited && _fields == null)
            {
                DeclaredFieldData[] fieldData;
                DebugErrorHandler.ThrowOnFailure(VirtualMachine.ProtocolService.GetFields(out fieldData, ReferenceTypeId));
                Field[] fields = Array.ConvertAll(fieldData, field => VirtualMachine.GetMirrorOf(this, field));
                _fields = fields;
            }

            return new ReadOnlyCollection<IField>(includeInherited ? _allFields : _fields);
        }
Example #6
0
        public void ProcessMap_ValidInput_AllCellsAreReachable()
        {
            var map = GenerateMap();

            var visitedCells = new HashSet<Cell>();
            var discoveredCells = new HashSet<Cell>() { map.AllCells.FirstOrDefault(cell => cell.Terrain == TerrainType.Floor) };
            while (discoveredCells.Any())
            {
                foreach (var discoveredCell in discoveredCells)
                {
                    visitedCells.Add(discoveredCell);
                }
                var newDiscoveredCells = new HashSet<Cell>();
                foreach (var newDiscoveredCell in discoveredCells.SelectMany(cell => map.GetAllAdjacentCells(cell)
                    .Where(c => c.Terrain != TerrainType.Rock && !visitedCells.Contains(c))))
                {
                    newDiscoveredCells.Add(newDiscoveredCell);
                }
                discoveredCells = newDiscoveredCells;
            }
            var unReachable = map.AllCells.Where(cell => cell.Terrain != TerrainType.Rock).Except(visitedCells).ToList();
            Assert.AreEqual(map.AllCells.Count(cell => cell.Terrain != TerrainType.Rock), visitedCells.Count);
        }
Example #7
0
        public void ProcessMap_ValidInput_AllCellsAreReachable()
        {
            var map = GenerateMap();

            var visitedCells = new HashSet<BinaryCell>();
            var discoveredCells = new HashSet<BinaryCell>() { map.GetCell(0, 0) };
            while (discoveredCells.Any())
            {
                foreach (var discoveredCell in discoveredCells)
                {
                    visitedCells.Add(discoveredCell);
                }
                var newDiscoveredCells = new HashSet<BinaryCell>();
                foreach (var newDiscoveredCell in discoveredCells.SelectMany(cell => cell.Sides
                    .Where(pair => pair.Value && !visitedCells.Contains(map.GetAdjacentCell(cell, pair.Key)))
                    .Select(pair => map.GetAdjacentCell(cell, pair.Key))))
                {
                    newDiscoveredCells.Add(newDiscoveredCell);
                }
                discoveredCells = newDiscoveredCells;
            }
            Assert.AreEqual(map.AllCells.Count(), visitedCells.Count);
        }
 public static List<CollectionElementToken> GetElements(HashSet<QueryToken> allTokens)
 {
     return allTokens
         .SelectMany(t => t.Follow(tt => tt.Parent))
         .OfType<CollectionElementToken>()
         .Where(a => a.CollectionElementType.IsElement())
         .Distinct()
         .OrderBy(a => a.FullKey().Length)
         .ToList();
 }
Example #9
0
        /// <summary>
        ///     Collapse a set of nodes in a given workspace.
        /// </summary>
        /// <param name="dynamoModel">The current DynamoModel</param>
        /// <param name="selectedNodes"> The function definition for the user-defined node </param>
        /// <param name="currentWorkspace"> The workspace where</param>
        /// <param name="args"></param>
        public static void Collapse(DynamoModel dynamoModel, IEnumerable<NodeModel> selectedNodes, WorkspaceModel currentWorkspace, FunctionNamePromptEventArgs args = null)
        {
            var selectedNodeSet = new HashSet<NodeModel>(selectedNodes);

            if (args == null || !args.Success)
            {
                args = new FunctionNamePromptEventArgs();
                dynamoModel.OnRequestsFunctionNamePrompt(null, args);

                
                if (!args.Success)
                {
                    return;
                }
            }

            // Note that undoable actions are only recorded for the "currentWorkspace", 
            // the nodes which get moved into "newNodeWorkspace" are not recorded for undo,
            // even in the new workspace. Their creations will simply be treated as part of
            // the opening of that new workspace (i.e. when a user opens a file, she will 
            // not expect the nodes that show up to be undoable).
            // 
            // After local nodes are moved into "newNodeWorkspace" as the result of 
            // conversion, if user performs an undo, new set of nodes will be created in 
            // "currentWorkspace" (not moving those nodes in the "newNodeWorkspace" back 
            // into "currentWorkspace"). In another word, undo recording is on a per-
            // workspace basis, it does not work across different workspaces.
            // 
            UndoRedoRecorder undoRecorder = currentWorkspace.UndoRecorder;
            using (undoRecorder.BeginActionGroup())
            {

                var newNodeWorkspace = new CustomNodeWorkspaceModel(
                    dynamoModel,
                    args.Name,
                    args.Category,
                    args.Description,
                    0,
                    0) { WatchChanges = false, HasUnsavedChanges = true };

                var newNodeDefinition = new CustomNodeDefinition(Guid.NewGuid())
                {
                    WorkspaceModel = newNodeWorkspace
                };

                currentWorkspace.DisableReporting();

                #region Determine Inputs and Outputs

                //Step 1: determine which nodes will be inputs to the new node
                var inputs =
                    new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
                        selectedNodeSet.SelectMany(
                            node =>
                                Enumerable.Range(0, node.InPortData.Count)
                                .Where(node.HasConnectedInput)
                                .Select(data => Tuple.Create(node, data, node.Inputs[data]))
                                .Where(input => !selectedNodeSet.Contains(input.Item3.Item2))));

                var outputs =
                    new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
                        selectedNodeSet.SelectMany(
                            node =>
                                Enumerable.Range(0, node.OutPortData.Count)
                                .Where(node.HasOutput)
                                .SelectMany(
                                    data =>
                                        node.Outputs[data].Where(
                                            output => !selectedNodeSet.Contains(output.Item2))
                                        .Select(output => Tuple.Create(node, data, output)))));

                #endregion

                #region Detect 1-node holes (higher-order function extraction)

                var curriedNodeArgs =
                    new HashSet<NodeModel>(
                        inputs.Select(x => x.Item3.Item2)
                            .Intersect(outputs.Select(x => x.Item3.Item2))).Select(
                                outerNode =>
                                {
                                    //var node = new Apply1();
                                    var node = newNodeWorkspace.AddNode<Apply1>();
                                    node.SetNickNameFromAttribute();

                                    node.DisableReporting();

                                    node.X = outerNode.X;
                                    node.Y = outerNode.Y;

                                    //Fetch all input ports
                                    // in order
                                    // that have inputs
                                    // and whose input comes from an inner node
                                    List<int> inPortsConnected =
                                        Enumerable.Range(0, outerNode.InPortData.Count)
                                            .Where(
                                                x =>
                                                    outerNode.HasInput(x)
                                                        && selectedNodeSet.Contains(
                                                            outerNode.Inputs[x].Item2))
                                            .ToList();

                                    var nodeInputs =
                                        outputs.Where(output => output.Item3.Item2 == outerNode)
                                            .Select(
                                                output =>
                                                    new
                                                    {
                                                        InnerNodeInputSender = output.Item1,
                                                        OuterNodeInPortData = output.Item3.Item1
                                                    })
                                            .ToList();

                                    nodeInputs.ForEach(_ => node.AddInput());

                                    node.RegisterAllPorts();

                                    return
                                        new
                                        {
                                            OuterNode = outerNode,
                                            InnerNode = node,
                                            Outputs =
                                                inputs.Where(
                                                    input => input.Item3.Item2 == outerNode)
                                                    .Select(input => input.Item3.Item1),
                                            Inputs = nodeInputs,
                                            OuterNodePortDataList = inPortsConnected
                                        };
                                }).ToList();

                #endregion

                #region UI Positioning Calculations

                double avgX = selectedNodeSet.Average(node => node.X);
                double avgY = selectedNodeSet.Average(node => node.Y);

                double leftMost = selectedNodeSet.Min(node => node.X);
                double topMost = selectedNodeSet.Min(node => node.Y);
                double rightMost = selectedNodeSet.Max(node => node.X + node.Width);

                #endregion

                #region Handle full selected connectors

                // Step 2: Determine all the connectors whose start/end owners are 
                // both in the selection set, and then move them from the current 
                // workspace into the new workspace.

                var fullySelectedConns =
                    new HashSet<ConnectorModel>(
                        currentWorkspace.Connectors.Where(
                            conn =>
                            {
                                bool startSelected = selectedNodeSet.Contains(conn.Start.Owner);
                                bool endSelected = selectedNodeSet.Contains(conn.End.Owner);
                                return startSelected && endSelected;
                            }));

                foreach (var ele in fullySelectedConns)
                {
                    undoRecorder.RecordDeletionForUndo(ele);
                    currentWorkspace.Connectors.Remove(ele);
                }

                #endregion

                #region Handle partially selected connectors

                // Step 3: Partially selected connectors (either one of its start 
                // and end owners is in the selection) are to be destroyed.

                var partiallySelectedConns =
                    currentWorkspace.Connectors.Where(
                        conn =>
                            selectedNodeSet.Contains(conn.Start.Owner)
                                || selectedNodeSet.Contains(conn.End.Owner)).ToList();

                foreach (ConnectorModel connector in partiallySelectedConns)
                {
                    undoRecorder.RecordDeletionForUndo(connector);
                    connector.NotifyConnectedPortsOfDeletion();
                    currentWorkspace.Connectors.Remove(connector);
                }

                #endregion

                #region Transfer nodes and connectors to new workspace

                // Step 4: move all nodes to new workspace remove from old
                // PB: This could be more efficiently handled by a copy paste, but we
                // are preservering the node 
                foreach (var ele in selectedNodeSet)
                {
                    undoRecorder.RecordDeletionForUndo(ele);
                    ele.SaveResult = false;
                    currentWorkspace.Nodes.Remove(ele);
                    ele.Workspace = newNodeWorkspace;
                }

                //  add to new
                newNodeWorkspace.Nodes.AddRange(selectedNodeSet);
                newNodeWorkspace.Connectors.AddRange(fullySelectedConns);

                foreach (var node in newNodeWorkspace.Nodes)
                    node.DisableReporting();

                double leftShift = leftMost - 250;
                foreach (NodeModel node in newNodeWorkspace.Nodes)
                {
                    node.X = node.X - leftShift;
                    node.Y = node.Y - topMost;
                }

                #endregion


                #region Process inputs

                var inConnectors = new List<Tuple<NodeModel, int>>();
                var uniqueInputSenders = new Dictionary<Tuple<NodeModel, int>, Symbol>();

                //Step 3: insert variables (reference step 1)
                foreach (var input in Enumerable.Range(0, inputs.Count).Zip(inputs, Tuple.Create))
                {
                    int inputIndex = input.Item1;

                    NodeModel inputReceiverNode = input.Item2.Item1;
                    int inputReceiverData = input.Item2.Item2;

                    NodeModel inputNode = input.Item2.Item3.Item2;
                    int inputData = input.Item2.Item3.Item1;

                    Symbol node;

                    var key = Tuple.Create(inputNode, inputData);
                    if (uniqueInputSenders.ContainsKey(key))
                    {
                        node = uniqueInputSenders[key];
                    }
                    else
                    {
                        inConnectors.Add(Tuple.Create(inputNode, inputData));

                        node = newNodeWorkspace.AddNode<Symbol>();
                        node.InputSymbol = inputReceiverNode.InPortData[inputReceiverData].NickName;

                        node.SetNickNameFromAttribute();

                        node.DisableReporting();

                        node.X = 0;
                        node.Y = inputIndex*(50 + node.Height);

                        uniqueInputSenders[key] = node;
                    }

                    var curriedNode = curriedNodeArgs.FirstOrDefault(x => x.OuterNode == inputNode);

                    if (curriedNode == null)
                    {
                        newNodeWorkspace.AddConnection(
                            node,
                            inputReceiverNode,
                            0,
                            inputReceiverData);
                    }
                    else
                    {
                        //Connect it to the applier
                        newNodeWorkspace.AddConnection(node, curriedNode.InnerNode, 0, 0);

                        //Connect applier to the inner input receive
                        newNodeWorkspace.AddConnection(
                            curriedNode.InnerNode,
                            inputReceiverNode,
                            0,
                            inputReceiverData);
                    }
                }

                #endregion

                #region Process outputs

                //List of all inner nodes to connect an output. Unique.
                var outportList = new List<Tuple<NodeModel, int>>();

                var outConnectors = new List<Tuple<NodeModel, int, int>>();

                int i = 0;
                if (outputs.Any())
                {
                    foreach (var output in outputs)
                    {
                        if (
                            outportList.All(
                                x => !(x.Item1 == output.Item1 && x.Item2 == output.Item2)))
                        {
                            NodeModel outputSenderNode = output.Item1;
                            int outputSenderData = output.Item2;
                            NodeModel outputReceiverNode = output.Item3.Item2;

                            if (curriedNodeArgs.Any(x => x.OuterNode == outputReceiverNode))
                                continue;

                            outportList.Add(Tuple.Create(outputSenderNode, outputSenderData));

                            //Create Symbol Node
                            var node = newNodeWorkspace.AddNode<Output>();
                            node.Symbol = outputSenderNode.OutPortData[outputSenderData].NickName;

                            node.SetNickNameFromAttribute();
                            node.DisableReporting();

                            node.X = rightMost + 75 - leftShift;
                            node.Y = i*(50 + node.Height);

                            newNodeWorkspace.AddConnection(
                                outputSenderNode,
                                node,
                                outputSenderData,
                                0);

                            i++;
                        }
                    }

                    //Connect outputs to new node
                    foreach (var output in outputs)
                    {
                        //Node to be connected to in CurrentWorkspace
                        NodeModel outputSenderNode = output.Item1;

                        //Port to be connected to on outPutNode_outer
                        int outputSenderData = output.Item2;

                        int outputReceiverData = output.Item3.Item1;
                        NodeModel outputReceiverNode = output.Item3.Item2;

                        var curriedNode =
                            curriedNodeArgs.FirstOrDefault(x => x.OuterNode == outputReceiverNode);

                        if (curriedNode == null)
                        {
                            // we create the connectors in the current space later
                            outConnectors.Add(
                                Tuple.Create(
                                    outputReceiverNode,
                                    outportList.FindIndex(
                                        x =>
                                            x.Item1 == outputSenderNode
                                                && x.Item2 == outputSenderData),
                                    outputReceiverData));
                        }
                        else
                        {
                            int targetPort =
                                curriedNode.Inputs.First(
                                    x => x.InnerNodeInputSender == outputSenderNode)
                                    .OuterNodeInPortData;

                            int targetPortIndex =
                                curriedNode.OuterNodePortDataList.IndexOf(targetPort);

                            //Connect it (new dynConnector)
                            newNodeWorkspace.AddConnection(
                                outputSenderNode,
                                curriedNode.InnerNode,
                                outputSenderData,
                                targetPortIndex + 1);

                        }
                    }
                }
                else
                {
                    foreach (var hanging in
                        selectedNodeSet.SelectMany(
                            node =>
                                Enumerable.Range(0, node.OutPortData.Count)
                                .Where(port => !node.HasOutput(port))
                                .Select(port => new { node, port })).Distinct())
                    {
                        //Create Symbol Node
                        var node = newNodeWorkspace.AddNode<Output>();
                        node.Symbol = hanging.node.OutPortData[hanging.port].NickName;

                        node.SetNickNameFromAttribute();

                        //store the element in the elements list
                        node.DisableReporting();

                        node.X = rightMost + 75 - leftShift;
                        node.Y = i*(50 + node.Height);

                        newNodeWorkspace.AddConnection(hanging.node, node, hanging.port, 0);

                        i++;
                    }
                }

                #endregion

                // save and load the definition from file
                newNodeDefinition.SyncWithWorkspace(dynamoModel, true, true);
                dynamoModel.Workspaces.Add(newNodeWorkspace);

                string name = newNodeDefinition.FunctionId.ToString();
                var collapsedNode = currentWorkspace.AddNode(avgX, avgY, name);
                undoRecorder.RecordCreationForUndo(collapsedNode);

                // place the node as intended, not centered
                collapsedNode.X = avgX;
                collapsedNode.Y = avgY;

                collapsedNode.DisableReporting();

                foreach (
                    var nodeTuple in
                        inConnectors.Select(
                            (x, idx) => new { node = x.Item1, from = x.Item2, to = idx }))
                {
                    var conn = currentWorkspace.AddConnection(
                        nodeTuple.node,
                        collapsedNode,
                        nodeTuple.from,
                        nodeTuple.to);

                    if (conn != null)
                    {
                        undoRecorder.RecordCreationForUndo(conn);
                    }
                }

                foreach (var nodeTuple in outConnectors)
                {

                    var conn = currentWorkspace.AddConnection(
                        collapsedNode,
                        nodeTuple.Item1,
                        nodeTuple.Item2,
                        nodeTuple.Item3);

                    if (conn != null)
                    {
                        undoRecorder.RecordCreationForUndo(conn);
                    }
                }

                collapsedNode.EnableReporting();
                currentWorkspace.EnableReporting();

                foreach (var node in newNodeWorkspace.Nodes)
                    node.EnableReporting();

                newNodeWorkspace.WatchChanges = true;
            }
        }
Example #10
0
        private static int Process(Options options)
        {
            try
            {
                Console.WriteLine("Start Process!");

                // Resolve options

                var basePath = Path.GetFullPath(options.Path ?? ".");
                var sources =
                    options.Sources.Where(p => string.IsNullOrWhiteSpace(p) == false &&
                                               p.ToLower().IndexOf(".codegen.cs") == -1)
                           .Select(p => MakeFullPath(p, basePath))
                           .ToArray();
                var references =
                    options.References.Where(p => string.IsNullOrWhiteSpace(p) == false)
                           .Select(p => MakeFullPath(p, basePath))
                           .ToArray();
                var targetDefaultPath = @".\Properties\TrackableData.CodeGen.cs";
                var targetPath = MakeFullPath(options.TargetFile ?? targetDefaultPath, basePath);

                // Parse sources and extract interfaces

                Console.WriteLine("- Parse sources");

                var syntaxTrees = sources.Select(
                    file => CSharpSyntaxTree.ParseText(File.ReadAllText(file), path: file)).ToArray();
                var interfaceDeclarations = syntaxTrees.SelectMany(
                    st => st.GetRoot().DescendantNodes().OfType<InterfaceDeclarationSyntax>()).ToArray();

                // Generate code

                Console.WriteLine("- Generate code");

                var writer = new TextCodeGenWriter();
                var relatedSourceTrees = new HashSet<SyntaxNode>();

                // TrackablePoco

                var pocoCodeGen = new TrackablePocoCodeGenerator() { Options = options };
                foreach (var idecl in interfaceDeclarations)
                {
                    var baseType = idecl.GetGenericBase("TrackableData.ITrackablePoco");
                    if (baseType != null)
                    {
                        var pocoType = baseType.TypeArgumentList.Arguments[0].ToString();
                        if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), pocoType) == false)
                        {
                            throw new Exception($"Invalid base type of ITrackablePoco<{pocoType}>");
                        }

                        pocoCodeGen.GenerateCode(idecl, writer);
                        relatedSourceTrees.Add(idecl.GetRootNode());
                    }
                }

                // TrackableContainer

                var containerCodeGen = new TrackableContainerCodeGenerator() { Options = options };
                foreach (var idecl in interfaceDeclarations)
                {
                    var baseType = idecl.GetGenericBase("TrackableData.ITrackableContainer");
                    if (baseType != null)
                    {
                        var containerType = baseType.TypeArgumentList.Arguments[0].ToString();
                        if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), containerType) == false)
                        {
                            throw new Exception($"Invalid base type of ITrackableContainer<{containerType}>");
                        }

                        containerCodeGen.GenerateCode(idecl, writer);
                        relatedSourceTrees.Add(idecl.GetRootNode());
                    }
                }

                // Resolve referenced using

                var usingDirectives = new HashSet<string>(relatedSourceTrees.SelectMany(
                    st => st.DescendantNodes().OfType<UsingDirectiveSyntax>()).Select(x => x.Name.ToString()));
                usingDirectives.Add("System");
                usingDirectives.Add("System.Collections.Generic");
                usingDirectives.Add("System.Reflection");
                usingDirectives.Add("System.Runtime.Serialization");
                usingDirectives.Add("System.Linq");
                usingDirectives.Add("System.Text");
                usingDirectives.Add("TrackableData");
                foreach (var usingDirective in usingDirectives)
                    writer.AddUsing(usingDirective);

                // Save generated code

                Console.WriteLine("- Save code");

                if (SaveFileIfChanged(targetPath, writer.ToString()) == false)
                    Console.WriteLine("Nothing changed. Skip writing.");

                return 0;
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception in processing:\n" + e);
                return 1;
            }
        }
Example #11
0
        /// <summary>
        ///     Collapse a set of nodes in a given workspace.  Has the side effects of prompting the user
        ///     first in order to obtain the name and category for the new node, 
        ///     writes the function to a dyf file, adds it to the FunctionDict, adds it to search, and compiles and 
        ///     places the newly created symbol (defining a lambda) in the Controller's FScheme Environment.  
        /// </summary>
        /// <param name="selectedNodes"> The function definition for the user-defined node </param>
        /// <param name="currentWorkspace"> The workspace where</param>
        public static void Collapse(IEnumerable<NodeModel> selectedNodes, WorkspaceModel currentWorkspace, FunctionNamePromptEventArgs args=null)
        {
            var selectedNodeSet = new HashSet<NodeModel>(selectedNodes);

            if (args == null || !args.Success)
            {
                args = new FunctionNamePromptEventArgs();
                dynSettings.Controller.DynamoModel.OnRequestsFunctionNamePrompt(null, args);

                //if (!dynSettings.Controller.DynamoViewModel.ShowNewFunctionDialog(ref newNodeName, ref newNodeCategory))
                if (!args.Success)
                {
                    return;
                }
            }

            var newNodeWorkspace = new CustomNodeWorkspaceModel(args.Name, args.Category, args.Description, 0, 0)
            {
                WatchChanges = false,
                HasUnsavedChanges = true
            };

            var newNodeDefinition = new FunctionDefinition(Guid.NewGuid())
            {
                WorkspaceModel = newNodeWorkspace
            };

            currentWorkspace.DisableReporting();

            #region Determine Inputs and Outputs

            //Step 1: determine which nodes will be inputs to the new node
            var inputs = new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
                selectedNodeSet.SelectMany(
                    node => Enumerable.Range(0, node.InPortData.Count).Where(node.HasConnectedInput)
                        .Select(data => Tuple.Create(node, data, node.Inputs[data]))
                        .Where(input => !selectedNodeSet.Contains(input.Item3.Item2))));

            var outputs = new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
                selectedNodeSet.SelectMany(
                    node => Enumerable.Range(0, node.OutPortData.Count).Where(node.HasOutput).SelectMany(
                        data => node.Outputs[data]
                                    .Where(output => !selectedNodeSet.Contains(output.Item2))
                                    .Select(output => Tuple.Create(node, data, output)))));

            #endregion

            #region Detect 1-node holes (higher-order function extraction)

            var curriedNodeArgs =
                new HashSet<NodeModel>(
                    inputs
                        .Select(x => x.Item3.Item2)
                        .Intersect(outputs.Select(x => x.Item3.Item2)))
                    .Select(
                        outerNode =>
                        {
                            var node = new Apply1();

                            //MVVM : Don't make direct reference to view here
                            //MVVM: no reference to view here
                            //dynNodeView nodeUI = node.NodeUI;

                            var elNameAttrib =
                                node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), true)[0] as
                                NodeNameAttribute;
                            if (elNameAttrib != null)
                            {
                                node.NickName = elNameAttrib.Name;
                            }

                            node.GUID = Guid.NewGuid();

                            //store the element in the elements list
                            newNodeWorkspace.Nodes.Add(node);
                            node.WorkSpace = newNodeWorkspace;

                            node.DisableReporting();

                            //MVVM : Can't set view location here

                            //dynSettings.Bench.WorkBench.Children.Add(nodeUI);

                            //Place it in an appropriate spot
                            //Canvas.SetLeft(nodeUI, Canvas.GetLeft(outerNode.NodeUI));
                            //Canvas.SetTop(nodeUI, Canvas.GetTop(outerNode.NodeUI));
                            node.X = outerNode.X;
                            node.Y = outerNode.Y;

                            //Fetch all input ports
                            // in order
                            // that have inputs
                            // and whose input comes from an inner node
                            List<int> inPortsConnected = Enumerable.Range(0, outerNode.InPortData.Count)
                                                                   .Where(
                                                                       x =>
                                                                       outerNode.HasInput(x) &&
                                                                       selectedNodeSet.Contains(
                                                                           outerNode.Inputs[x].Item2))
                                                                   .ToList();

                            var nodeInputs = outputs
                                .Where(output => output.Item3.Item2 == outerNode)
                                .Select(
                                    output =>
                                    new
                                    {
                                        InnerNodeInputSender = output.Item1,
                                        OuterNodeInPortData = output.Item3.Item1
                                    }).ToList();

                            nodeInputs.ForEach(_ => node.AddInput());

                            node.RegisterAllPorts();

                            return new
                            {
                                OuterNode = outerNode,
                                InnerNode = node,
                                Outputs = inputs.Where(input => input.Item3.Item2 == outerNode)
                                                .Select(input => input.Item3.Item1),
                                Inputs = nodeInputs,
                                OuterNodePortDataList = inPortsConnected
                            };
                        }).ToList();

            #endregion

            #region UI Positioning Calculations

            double avgX = selectedNodeSet.Average(node => node.X);
            double avgY = selectedNodeSet.Average(node => node.Y);

            double leftMost = selectedNodeSet.Min(node => node.X);
            double topMost = selectedNodeSet.Min(node => node.Y);
            double rightMost = selectedNodeSet.Max(node => node.X + node.Width);

            #endregion

            #region Move selection to new workspace

            var connectors = new HashSet<ConnectorModel>(currentWorkspace.Connectors.Where(
                                                                conn => selectedNodeSet.Contains(conn.Start.Owner)
                                                                    && selectedNodeSet.Contains(conn.End.Owner)));

            //Step 2: move all nodes to new workspace
            //  remove from old
            foreach (var ele in selectedNodeSet)
            {
                ele.SaveResult = false;
                currentWorkspace.Nodes.Remove(ele);
                ele.WorkSpace = newNodeWorkspace;
            }
            foreach (var ele in connectors)
            {
                currentWorkspace.Connectors.Remove(ele);
            }

            //  add to new
            newNodeWorkspace.Nodes.AddRange(selectedNodeSet);
            newNodeWorkspace.Connectors.AddRange(connectors);

            double leftShift = leftMost - 250;
            foreach (NodeModel node in newNodeWorkspace.Nodes)
            {
                node.X = node.X - leftShift;
                node.Y = node.Y - topMost;
            }

            #endregion

            #region Insert new node into the current workspace

            //Step 5: insert new node into original workspace
            //var collapsedNode = dynSettings.Controller.DynamoViewModel.CreateFunction(
            //    inputs.Select(x => x.Item1.InPortData[x.Item2].NickName),
            //    outputs
            //        .Where(x => !curriedNodeArgs.Any(y => y.OuterNode == x.Item3.Item2))
            //        .Select(x => x.Item1.OutPortData[x.Item2].NickName),
            //    newNodeDefinition);

            //collapsedNode.GUID = Guid.NewGuid();

            //currentWorkspace.Nodes.Add(collapsedNode);
            //collapsedNode.WorkSpace = currentWorkspace;

            //collapsedNode.X = avgX;
            //collapsedNode.Y = avgY;

            #endregion

            #region Destroy all hanging connectors

            //Step 6: connect inputs and outputs

            var removeConnectors = currentWorkspace.Connectors.Where(c =>
                                                                     selectedNodeSet.Contains(c.Start.Owner) ||
                                                                     selectedNodeSet.Contains(c.End.Owner))
                                                   .ToList();
            foreach (ConnectorModel connector in removeConnectors)
            {
                connector.NotifyConnectedPortsOfDeletion();
                currentWorkspace.Connectors.Remove(connector);
            }

            #endregion

            newNodeWorkspace.Nodes.ToList().ForEach(x => x.DisableReporting());

            var inConnectors = new List<Tuple<NodeModel, int, int>>();

            #region Process inputs

            var uniqueInputSenders = new Dictionary<Tuple<NodeModel, int>, Symbol>();

            //Step 3: insert variables (reference step 1)
            foreach (var input in Enumerable.Range(0, inputs.Count).Zip(inputs, Tuple.Create))
            {
                int inputIndex = input.Item1;

                NodeModel inputReceiverNode = input.Item2.Item1;
                int inputReceiverData = input.Item2.Item2;

                NodeModel inputNode = input.Item2.Item3.Item2;
                int inputData = input.Item2.Item3.Item1;

                Symbol node;

                var key = Tuple.Create(inputNode, inputData);
                if (uniqueInputSenders.ContainsKey(key))
                {
                    node = uniqueInputSenders[key];
                }
                else
                {
                    //MVVM : replace NodeUI reference with node
                    inConnectors.Add(Tuple.Create(inputNode, inputData, inputIndex));

                    //Create Symbol Node
                    node = new Symbol
                    {
                        InputSymbol = inputReceiverNode.InPortData[inputReceiverData].NickName
                    };

                    //MVVM : Don't make direct reference to view here
                    //dynNodeView nodeUI = node.NodeUI;

                    var elNameAttrib =
                        node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), true)[0] as NodeNameAttribute;
                    if (elNameAttrib != null)
                    {
                        node.NickName = elNameAttrib.Name;
                    }

                    node.GUID = Guid.NewGuid();

                    //store the element in the elements list
                    newNodeWorkspace.Nodes.Add(node);
                    node.WorkSpace = newNodeWorkspace;

                    node.DisableReporting();

                    node.X = 0;
                    node.Y = inputIndex * (50 + node.Height);

                    uniqueInputSenders[key] = node;
                }

                var curriedNode = curriedNodeArgs.FirstOrDefault(x => x.OuterNode == inputNode);

                if (curriedNode == null)
                {
                    var conn1 = ConnectorModel.Make(node,
                                                  inputReceiverNode,
                                                  0,
                                                  inputReceiverData,
                                                  PortType.INPUT);

                    if (conn1 != null)
                        newNodeWorkspace.Connectors.Add(conn1);
                }
                else
                {
                    //Connect it to the applier
                    var conn = ConnectorModel.Make(node,
                                                     curriedNode.InnerNode,
                                                     0,
                                                     0,
                                                     PortType.INPUT);
                    if (conn != null)
                        newNodeWorkspace.Connectors.Add(conn);

                    //Connect applier to the inner input receive
                    var conn2 = ConnectorModel.Make(
                        curriedNode.InnerNode,
                        inputReceiverNode,
                        0,
                        inputReceiverData,
                        PortType.INPUT);

                    if (conn2 != null)
                        newNodeWorkspace.Connectors.Add(conn2);
                }
            }

            #endregion

            #region Process outputs

            //List of all inner nodes to connect an output. Unique.
            var outportList = new List<Tuple<NodeModel, int>>();

            var outConnectors = new List<Tuple<NodeModel, int, int>>();

            int i = 0;
            foreach (var output in outputs)
            {
                if (outportList.All(x => !(x.Item1 == output.Item1 && x.Item2 == output.Item2)))
                {
                    NodeModel outputSenderNode = output.Item1;
                    int outputSenderData = output.Item2;
                    NodeModel outputReceiverNode = output.Item3.Item2;

                    if (curriedNodeArgs.Any(x => x.OuterNode == outputReceiverNode))
                        continue;

                    outportList.Add(Tuple.Create(outputSenderNode, outputSenderData));

                    //Create Symbol Node
                    var node = new Output
                    {
                        Symbol = outputSenderNode.OutPortData[outputSenderData].NickName
                    };

                    //dynNodeView nodeUI = node.NodeUI;

                    var elNameAttrib =
                        node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), false)[0] as NodeNameAttribute;
                    if (elNameAttrib != null)
                    {
                        node.NickName = elNameAttrib.Name;
                    }

                    node.GUID = Guid.NewGuid();

                    //store the element in the elements list
                    newNodeWorkspace.Nodes.Add(node);
                    node.WorkSpace = newNodeWorkspace;

                    node.DisableReporting();

                    node.X = rightMost + 75 - leftShift;
                    node.Y = i*(50 + node.Height);

                    var conn = ConnectorModel.Make(
                                outputSenderNode,
                                node,
                                outputSenderData,
                                0,
                                PortType.INPUT);

                    if (conn != null)
                        newNodeWorkspace.Connectors.Add(conn);

                    i++;
                }
            }

            //Connect outputs to new node
            foreach (var output in outputs)
            {
                //Node to be connected to in CurrentWorkspace
                NodeModel outputSenderNode = output.Item1;

                //Port to be connected to on outPutNode_outer
                int outputSenderData = output.Item2;

                int outputReceiverData = output.Item3.Item1;
                NodeModel outputReceiverNode = output.Item3.Item2;

                var curriedNode = curriedNodeArgs.FirstOrDefault(
                    x => x.OuterNode == outputReceiverNode);

                if (curriedNode == null)
                {
                    // we create the connectors in the current space later
            //MVVM : replaced multiple dynNodeView refrences with dynNode
                    outConnectors.Add(
                        Tuple.Create(
                            outputReceiverNode,
                            outportList.FindIndex(
                                x => x.Item1 == outputSenderNode && x.Item2 == outputSenderData),
                            outputReceiverData));
                }
                else
                {
                    int targetPort = curriedNode.Inputs
                                                .First(
                                                    x => x.InnerNodeInputSender == outputSenderNode)
                                                .OuterNodeInPortData;

                    int targetPortIndex = curriedNode.OuterNodePortDataList.IndexOf(targetPort);

                    //Connect it (new dynConnector)

                    var conn = ConnectorModel.Make(
                        outputSenderNode,
                        curriedNode.InnerNode,
                        outputSenderData,
                        targetPortIndex + 1,
                        PortType.INPUT);

                    if (conn != null)
                        newNodeWorkspace.Connectors.Add(conn);
                }
            }

            #endregion

            // save and load the definition from file
            newNodeDefinition.SyncWithWorkspace(true, true);
            dynSettings.Controller.DynamoModel.Workspaces.Add(newNodeWorkspace);

            string name = newNodeDefinition.FunctionId.ToString();
            var collapsedNode = dynSettings.Controller.DynamoModel.CreateNode(avgX, avgY, name);

            // place the node as intended, not centered
            collapsedNode.X = avgX;
            collapsedNode.Y = avgY;

            collapsedNode.DisableReporting();

            foreach (var nodeTuple in inConnectors)
            {
                var conn = ConnectorModel.Make(
                                    nodeTuple.Item1,
                                    collapsedNode,
                                    nodeTuple.Item2,
                                    nodeTuple.Item3,
                                    PortType.INPUT);

                if (conn != null)
                    currentWorkspace.Connectors.Add(conn);
            }

            foreach (var nodeTuple in outConnectors)
            {

                var conn = ConnectorModel.Make(
                                    collapsedNode,
                                    nodeTuple.Item1,
                                    nodeTuple.Item2,
                                    nodeTuple.Item3,
                                    PortType.INPUT);

                if (conn != null)
                    currentWorkspace.Connectors.Add(conn);
            }

            collapsedNode.EnableReporting();
            currentWorkspace.EnableReporting();

            newNodeWorkspace.WatchChanges = true;
        }
        private static ObservableCollection<FileEntryViewModel> ParseStfs(StfsPackage package)
        {
            var collection = new ObservableCollection<FileEntryViewModel>();
            var allocatedBlocks = new HashSet<int>();
            var blockCollisions = new HashSet<int>();
            foreach (var fileEntry in package.FlatFileList.Where(f => !f.IsDirectory).OrderBy(f => f.Name))
            {
                var blockList = package.GetFileEntryBlockList(fileEntry);
                foreach (var block in blockList.Where(b => b.Key.HasValue))
                {
                    if (!allocatedBlocks.Contains(block.Key.Value))
                        allocatedBlocks.Add(block.Key.Value);
                    else
                        blockCollisions.Add(block.Key.Value);
                }
                collection.Add(new FileEntryViewModel(fileEntry, blockList, package));
            }

            foreach (var block in blockCollisions.SelectMany(blockCollision => collection.SelectMany(vm => vm.Blocks.Where(b => b.BlockNumber == blockCollision))))
            {
                block.Health = FileBlockHealthStatus.Collision;
            }

            return collection;
        }
Example #13
0
        private static int Process(Options options)
        {
            try
            {
                Console.WriteLine("Start Process!");

                // Resolve options

                var basePath = Path.GetFullPath(options.Path ?? ".");
                var sources =
                    options.Sources.Where(p => string.IsNullOrWhiteSpace(p) == false &&
                                               p.ToLower().IndexOf(".codegen.cs") == -1)
                           .Select(p => MakeFullPath(p, basePath))
                           .ToArray();
                var references =
                    options.References.Where(p => string.IsNullOrWhiteSpace(p) == false)
                           .Select(p => MakeFullPath(p, basePath))
                           .ToArray();
                var targetDefaultPath = @".\Properties\TrackableData.CodeGen.cs";
                var targetPath = MakeFullPath(options.TargetFile ?? targetDefaultPath, basePath);

                // Parse sources and extract interfaces

                Console.WriteLine("- Parse sources");

                var syntaxTrees = sources.Select(
                    file => CSharpSyntaxTree.ParseText(File.ReadAllText(file), path: file)).ToArray();
                var interfaceDeclarations = syntaxTrees.SelectMany(
                    st => st.GetRoot().DescendantNodes().OfType<InterfaceDeclarationSyntax>()).ToArray();

                // Generate code

                Console.WriteLine("- Generate code");

                var settings = new CodeWriterSettings(CodeWriterSettings.CSharpDefault);
                settings.TranslationMapping["`"] = "\"";

                var w = new CodeWriter.CodeWriter(settings);
                var relatedSourceTrees = new HashSet<SyntaxNode>();

                w.HeadLines = new List<string>
                {
                    "// ------------------------------------------------------------------------------",
                    "// <auto-generated>",
                    "//     This code was generated by TrackableData.CodeGenerator.",
                    "//",
                    "//     Changes to this file may cause incorrect behavior and will be lost if",
                    "//     the code is regenerated.",
                    "// </auto-generated>",
                    "// ------------------------------------------------------------------------------",
                    "",
                    "using System;",
                    "using System.Collections.Generic;",
                    "using System.Reflection;",
                    "using System.Runtime.Serialization;",
                    "using System.Linq;",
                    "using System.Text;",
                    "using TrackableData;",
                    ""
                };

                // TrackablePoco

                var pocoCodeGen = new TrackablePocoCodeGenerator() { Options = options };
                foreach (var idecl in interfaceDeclarations)
                {
                    var baseType = idecl.GetGenericBase("TrackableData.ITrackablePoco");
                    if (baseType != null)
                    {
                        var pocoType = baseType.TypeArgumentList.Arguments[0].ToString();
                        if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), pocoType) == false)
                        {
                            throw new Exception($"Invalid base type of ITrackablePoco<{pocoType}>");
                        }

                        pocoCodeGen.GenerateCode(idecl, w);
                        relatedSourceTrees.Add(idecl.GetRootNode());
                    }
                }

                // TrackableContainer

                var containerCodeGen = new TrackableContainerCodeGenerator() { Options = options };
                foreach (var idecl in interfaceDeclarations)
                {
                    var baseType = idecl.GetGenericBase("TrackableData.ITrackableContainer");
                    if (baseType != null)
                    {
                        var containerType = baseType.TypeArgumentList.Arguments[0].ToString();
                        if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), containerType) == false)
                        {
                            throw new Exception($"Invalid base type of ITrackableContainer<{containerType}>");
                        }

                        containerCodeGen.GenerateCode(idecl, w);
                        relatedSourceTrees.Add(idecl.GetRootNode());
                    }
                }

                // Resolve referenced using

                var usingDirectives = new HashSet<string>(relatedSourceTrees.SelectMany(
                    st => st.DescendantNodes().OfType<UsingDirectiveSyntax>()).Select(x => x.Name.ToString()));
                foreach (var usingDirective in usingDirectives)
                    EnsureUsing(w, usingDirective);

                // Save generated code

                Console.WriteLine("- Save code");

                if (w.WriteAllText(targetPath, true) == false)
                    Console.WriteLine("Nothing changed. Skip writing.");

                return 0;
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception in processing:\n" + e);
                return 1;
            }
        }
Example #14
0
        /// <summary>
        /// Visit the given context and return a collection of the resultant contexts.
        /// </summary>
        /// <returns>Zero or more <see cref="IRenderingContext"/> instances, determined by the outcome of this visit.</returns>
        /// <param name="context">The rendering context to visit.</param>
        public override IRenderingContext[] Visit(IRenderingContext context)
        {
            if(context == null)
              {
            throw new ArgumentNullException(nameof(context));
              }

              IEnumerable<IRenderingContext>
            output = new [] { context },
            newlyExposedElements = new RenderingContext[0];

              var macroAttribute = context.Element.GetMetalAttribute(ZptConstants.Metal.DefineMacroAttribute);
              if(macroAttribute != null)
              {
            context.TalModel.AddLocal(MACRONAME, macroAttribute.Value);
              }

              foreach(var handler in _handlers)
              {
            var handlingResult = new HashSet<AttributeHandlingResult>();

            foreach(var ctx in output)
            {
              var processedBatch = handler.Handle(ctx);
              handlingResult.Add(processedBatch);
            }

            newlyExposedElements = newlyExposedElements.Union(handlingResult.SelectMany(x => x.NewlyExposedContexts));
            output = handlingResult.Where(x => x.ContinueHandling).SelectMany(x => x.Contexts).ToArray();
              }

              output = output.Union(newlyExposedElements.SelectMany(x => this.Visit(x)));

              return output.ToArray();
        }
Example #15
0
        private string ConvertToGraphvizDot(Graph graph)
        {
            Func<string, string> toName = id => id.Substring(id.LastIndexOf('.') + 1);

            var tab = "	";
            var sb = new StringBuilder();
            sb.AppendLine("digraph G {");

            int i = 0;
            var renderedMessages = new Dictionary<string, int>();
            foreach (var handler in graph.Handlers.Values.OrderByDescending(e => e.IsAggregate))
            {
                Func<string, string> correctId = id =>
                {
                    int count;
                    if (renderedMessages.TryGetValue(id, out count))
                        return id + "_" + (count + 1);
                    return id + "_1";
                };
                sb.AppendFormat(tab + "subgraph cluster_{0} {{", ++i).AppendLine();
                sb.AppendFormat(tab + tab + "label = \"{0}\";", toName(handler.Id)).AppendLine();
                sb.AppendLine(tab + tab + "node [style=filled, shape=record];");

                var links = new HashSet<Link>();
                foreach (var input in handler.Roots)
                {
                    var flow = new List<Message> { input };
                    flow.AddRange(input.Result);
                    for (int j = 0; j < flow.Count - 1; j++)
                    {
                        if (j + 1 < flow.Count)
                            links.Add(new Link { From = flow[j], To = flow[j + 1] });
                    }
                }
                foreach (var link in links)
                    sb.AppendFormat(tab + tab + "\"{0}\" -> \"{1}\"", correctId(link.From.Id), correctId(link.To.Id)).AppendLine();

                // set message colors
                var allMessages = handler.Roots.SelectMany(e => e.Result).Distinct().ToList();
                allMessages.AddRange(handler.Roots);
                foreach (var cmd in allMessages.Where(e => e.IsCommand))
                    sb.AppendFormat(tab + tab + "\"{0}\"[color=lightblue, label=\"{1}\"];", correctId(cmd.Id), toName(cmd.Id)).AppendLine();
                foreach (var evt in allMessages.Where(e => e.IsEvent))
                    sb.AppendFormat(tab + tab + "\"{0}\"[color=orange, label=\"{1}\"];", correctId(evt.Id), toName(evt.Id)).AppendLine();

                sb.AppendLine(tab + "}");

                foreach (var msg in links.SelectMany(e => new[] { e.From, e.To }).Distinct())
                {
                    int count;
                    renderedMessages.TryGetValue(msg.Id, out count);
                    renderedMessages[msg.Id] = ++count;
                }
            }

            foreach (var kv in renderedMessages.Where(kv => kv.Value > 1))
            {
                int count = kv.Value;
                for (int j = 0; j < count - 1; j++)
                    for (int k = j + 1; k < count; k++)
                        sb.AppendFormat(tab + "\"{0}_{1}\" -> \"{0}_{2}\"[style=dotted, color=grey, arrowsize=0];", kv.Key, j + 1, k + 1).AppendLine();
                //for (int j = 1; j < count; j++)
                //    sb.AppendFormat(tab + "\"{0}_1\" -> \"{0}_{1}\"[style=dotted, color=grey, arrowsize=0];", kv.Key, j + 1).AppendLine();
            }

            sb.AppendLine("}");
            return sb.ToString();
        }
    void TriangleSelectionToolbox()
    {
        if (plotter.CurrentAction != HairyPlotterActions.VertexUvEdit)
        {
            if (plotter.TriangleSelectionCount > 0)
            {
                EditorGUILayout.LabelField("Triangle Selection: " + plotter.TriangleSelectionCount, EditorStyles.boldLabel);
                EditorGUILayout.BeginHorizontal();

                GUI.color = TriangleSelectionToolbarColor;

                if (GUILayout.Button("Create Unique Vertices", EditorStyles.miniButton))
                {
                    HashSet<HairyPlotterTriangle> selectedTriangles = new HashSet<HairyPlotterTriangle>(plotter.SelectedTriangles);
                    HashSet<HairyPlotterVertex> uniqueVertices = new HashSet<HairyPlotterVertex>(selectedTriangles.SelectMany(x => x.VertexObjects).Distinct());

                    // Iterate over each vertex that the selectedTriangles use
                    foreach (HairyPlotterVertex vertex in uniqueVertices)
                    {
                        // Iterate over each triangle the vertex blongs to
                        foreach (HairyPlotterTriangle vertexTriangle in vertex.TriangleSet)
                        {
                            // If the triangle is NOT in the selected triangles
                            if (!selectedTriangles.Contains(vertexTriangle))
                            {
                                // Create a clone of the vertex
                                HairyPlotterVertex vertexClone = plotter.CreateVertex(vertex.Position, vertex.Uv);

                                // And step through each selected triangle, and switch out the shared vertex for the clone
                                foreach (HairyPlotterTriangle selectedTriangle in selectedTriangles)
                                {
                                    selectedTriangle.SwitchVertices(vertex, vertexClone);
                                }

                                // We're done
                                break;
                            }
                        }
                    }

                    plotter.Dirty = true;
                    plotter.UpdateVertexIndexes();
                }

                if (GUILayout.Button("Select Vertices", EditorStyles.miniButton))
                {
                    HashSet<HairyPlotterTriangle> selectedTriangles = new HashSet<HairyPlotterTriangle>(plotter.SelectedTriangles);
                    HashSet<HairyPlotterVertex> selectedTrianglesVertices = new HashSet<HairyPlotterVertex>(selectedTriangles.SelectMany(x => x.VertexObjects));

                    plotter.ClearVertexSelection();

                    foreach (HairyPlotterVertex vertex in selectedTrianglesVertices)
                    {
                        plotter.AddSelection(vertex);
                    }

                    // Clear triangle selection
                    plotter.ClearTriangleSelection();
                }

                if (GUILayout.Button("Clear Selection", EditorStyles.miniButton))
                {
                    plotter.ClearTriangleSelection();
                }

                if (plotter.CurrentAction == HairyPlotterActions.TriangleDelete)
                {
                    if (GUILayout.Button("Yes!", EditorStyles.miniButton))
                    {
                        foreach (HairyPlotterTriangle triangle in plotter.SelectedTriangles)
                        {
                            plotter.DestroyTriangle(triangle);
                        }

                        plotter.CurrentAction = HairyPlotterActions.None;
                    }

                    if (GUILayout.Button("No!", EditorStyles.miniButton))
                    {
                        plotter.CurrentAction = HairyPlotterActions.None;
                    }
                }
                else
                {
                    if (GUILayout.Button("Delete Selected", EditorStyles.miniButton))
                    {
                        plotter.CurrentAction = HairyPlotterActions.TriangleDelete;
                    }
                }

                GUI.color = Color.white;
                EditorGUILayout.EndHorizontal();
            }
        }
    }
Example #17
0
        internal void NodeFromSelection(IEnumerable<dynNode> selectedNodes)
        {
            var selectedNodeSet = new HashSet<dynNode>(selectedNodes);

            #region Prompt
            //First, prompt the user to enter a name
            string newNodeName, newNodeCategory;
            string error = "";

            do
            {
                var dialog = new FunctionNamePrompt(Bench.addMenuCategoryDict.Keys, error);
                if (dialog.ShowDialog() != true)
                {
                    return;
                }

                newNodeName = dialog.Text;
                newNodeCategory = dialog.Category;

                if (FunctionDict.ContainsKey(newNodeName))
                {
                    error = "A function with this name already exists.";
                }
                else if (newNodeCategory.Equals(""))
                {
                    error = "Please enter a valid category.";
                }
                else
                {
                    error = "";
                }
            }
            while (!error.Equals(""));

            var newNodeWorkspace = NewFunction(newNodeName, newNodeCategory, false);
            #endregion

            CurrentSpace.DisableReporting();

            #region UI Positioning Calculations
            var avgX = selectedNodeSet.Average(node => Canvas.GetLeft(node.NodeUI));
            var avgY = selectedNodeSet.Average(node => Canvas.GetTop(node.NodeUI));

            var leftMost = selectedNodeSet.Min(node => Canvas.GetLeft(node.NodeUI));
            var topMost = selectedNodeSet.Min(node => Canvas.GetTop(node.NodeUI));
            var rightMost = selectedNodeSet.Max(node => Canvas.GetLeft(node.NodeUI) + node.NodeUI.Width);
            #endregion

            #region Determine Inputs and Outputs
            //Step 1: determine which nodes will be inputs to the new node
            var inputs = new HashSet<Tuple<dynNode, int, Tuple<int, dynNode>>>(
                selectedNodeSet.SelectMany(
                    node => Enumerable.Range(0, node.InPortData.Count).Where(node.HasInput).Select(
                        data => Tuple.Create(node, data, node.Inputs[data])).Where(
                            input => !selectedNodeSet.Contains(input.Item3.Item2))));

            var outputs = new HashSet<Tuple<dynNode, int, Tuple<int, dynNode>>>(
                selectedNodeSet.SelectMany(
                    node => Enumerable.Range(0, node.OutPortData.Count).Where(node.HasOutput).SelectMany(
                        data => node.Outputs[data]
                            .Where(output => !selectedNodeSet.Contains(output.Item2))
                            .Select(output => Tuple.Create(node, data, output)))));
            #endregion

            #region Detect 1-node holes (higher-order function extraction)
            var curriedNodeArgs =
                new HashSet<dynNode>(
                    inputs
                        .Select(x => x.Item3.Item2)
                        .Intersect(outputs.Select(x => x.Item3.Item2)))
                .Select(
                    outerNode =>
                    {
                        var node = new dynApply1();

                        var nodeUI = node.NodeUI;

                        NodeNameAttribute elNameAttrib = node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), true)[0] as NodeNameAttribute;
                        if (elNameAttrib != null)
                        {
                            nodeUI.NickName = elNameAttrib.Name;
                        }

                        nodeUI.GUID = Guid.NewGuid();

                        //store the element in the elements list
                        newNodeWorkspace.Nodes.Add(node);
                        node.WorkSpace = newNodeWorkspace;

                        node.DisableReporting();

                        Bench.WorkBench.Children.Add(nodeUI);

                        //Place it in an appropriate spot
                        Canvas.SetLeft(nodeUI, Canvas.GetLeft(outerNode.NodeUI));
                        Canvas.SetTop(nodeUI, Canvas.GetTop(outerNode.NodeUI));

                        //Fetch all input ports
                        // in order
                        // that have inputs
                        // and whose input comes from an inner node
                        var inPortsConnected = Enumerable.Range(0, outerNode.InPortData.Count)
                            .Where(x => outerNode.HasInput(x) && selectedNodeSet.Contains(outerNode.Inputs[x].Item2))
                            .ToList();

                        var nodeInputs = outputs
                            .Where(output => output.Item3.Item2 == outerNode)
                            .Select(
                                output =>
                                    new
                                    {
                                        InnerNodeInputSender = output.Item1,
                                        OuterNodeInPortData = output.Item3.Item1
                                    }).ToList();

                        nodeInputs.ForEach(_ => node.AddInput());

                        node.NodeUI.RegisterAllPorts();

                        Bench.WorkBench.UpdateLayout();

                        return new
                        {
                            OuterNode = outerNode,
                            InnerNode = node,
                            Outputs = inputs.Where(input => input.Item3.Item2 == outerNode)
                                .Select(input => input.Item3.Item1),
                            Inputs = nodeInputs,
                            OuterNodePortDataList = inPortsConnected
                        };
                    }).ToList();
            #endregion

            #region Move selection to new workspace
            var connectors = new HashSet<dynConnector>(
                CurrentSpace.Connectors.Where(
                    conn => selectedNodeSet.Contains(conn.Start.Owner.NodeLogic)
                        && selectedNodeSet.Contains(conn.End.Owner.NodeLogic)));

            //Step 2: move all nodes to new workspace
            //  remove from old
            CurrentSpace.Nodes.RemoveAll(selectedNodeSet.Contains);
            CurrentSpace.Connectors.RemoveAll(connectors.Contains);
            //  add to new
            newNodeWorkspace.Nodes.AddRange(selectedNodeSet);
            newNodeWorkspace.Connectors.AddRange(connectors);

            var leftShift = leftMost - 250;
            foreach (var node in newNodeWorkspace.Nodes.Select(x => x.NodeUI))
            {
                Canvas.SetLeft(node, Canvas.GetLeft(node) - leftShift);
                Canvas.SetTop(node, Canvas.GetTop(node) - topMost);
            }
            #endregion

            #region Insert new node replacement into the current workspace
            //Step 5: insert new node into original workspace
            var collapsedNode = new dynFunction(
                inputs.Select(x => x.Item1.InPortData[x.Item2].NickName),
                outputs
                    .Where(x => !curriedNodeArgs.Any(y => y.OuterNode == x.Item3.Item2))
                    .Select(x => x.Item1.OutPortData[x.Item2].NickName),
                newNodeName);

            collapsedNode.NodeUI.GUID = Guid.NewGuid();

            CurrentSpace.Nodes.Add(collapsedNode);
            collapsedNode.WorkSpace = CurrentSpace;

            Bench.WorkBench.Children.Add(collapsedNode.NodeUI);

            Canvas.SetLeft(collapsedNode.NodeUI, avgX);
            Canvas.SetTop(collapsedNode.NodeUI, avgY);

            Bench.WorkBench.UpdateLayout();
            #endregion

            #region Destroy all hanging connectors
            //Step 6: connect inputs and outputs
            foreach (var connector in CurrentSpace.Connectors
                .Where(c => selectedNodeSet.Contains(c.Start.Owner.NodeLogic) && !selectedNodeSet.Contains(c.End.Owner.NodeLogic)).ToList())
            {
                connector.Kill();
            }

            foreach (var connector in CurrentSpace.Connectors
                .Where(c => !selectedNodeSet.Contains(c.Start.Owner.NodeLogic) && selectedNodeSet.Contains(c.End.Owner.NodeLogic)).ToList())
            {
                connector.Kill();
            }
            #endregion

            newNodeWorkspace.Nodes.ForEach(x => x.DisableReporting());

            #region Process inputs
            //Step 3: insert variables (reference step 1)
            foreach (var input in Enumerable.Range(0, inputs.Count).Zip(inputs, Tuple.Create))
            {
                var inputIndex = input.Item1;

                var inputReceiverNode = input.Item2.Item1;
                var inputReceiverData = input.Item2.Item2;

                var inputNode = input.Item2.Item3.Item2;
                var inputData = input.Item2.Item3.Item1;

                //Connect outside input to the node
                CurrentSpace.Connectors.Add(
                    new dynConnector(
                        inputNode.NodeUI,
                        collapsedNode.NodeUI,
                        inputData,
                        inputIndex,
                        0,
                        true));

                //Create Symbol Node
                dynSymbol node = new dynSymbol()
                {
                    Symbol = inputReceiverNode.InPortData[inputReceiverData].NickName
                };

                var nodeUI = node.NodeUI;

                NodeNameAttribute elNameAttrib = node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), true)[0] as NodeNameAttribute;
                if (elNameAttrib != null)
                {
                    nodeUI.NickName = elNameAttrib.Name;
                }

                nodeUI.GUID = Guid.NewGuid();

                //store the element in the elements list
                newNodeWorkspace.Nodes.Add(node);
                node.WorkSpace = newNodeWorkspace;

                node.DisableReporting();

                Bench.WorkBench.Children.Add(nodeUI);

                //Place it in an appropriate spot
                Canvas.SetLeft(nodeUI, 0);
                Canvas.SetTop(nodeUI, inputIndex * (50 + node.NodeUI.Height));

                Bench.WorkBench.UpdateLayout();

                var curriedNode = curriedNodeArgs.FirstOrDefault(
                    x => x.OuterNode == inputNode);

                if (curriedNode == null)
                {
                    //Connect it (new dynConnector)
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                        nodeUI,
                        inputReceiverNode.NodeUI,
                        0,
                        inputReceiverData,
                        0,
                        false));
                }
                else
                {
                    //Connect it to the applier
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                        nodeUI,
                        curriedNode.InnerNode.NodeUI,
                        0,
                        0,
                        0,
                        false));

                    //Connect applier to the inner input receiver
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                        curriedNode.InnerNode.NodeUI,
                        inputReceiverNode.NodeUI,
                        0,
                        inputReceiverData,
                        0,
                        false));
                }
            }
            #endregion

            #region Process outputs
            //List of all inner nodes to connect an output. Unique.
            var outportList = new List<Tuple<dynNode, int>>();

            int i = 0;
            foreach (var output in outputs)
            {
                if (outportList.All(x => !(x.Item1 == output.Item1 && x.Item2 == output.Item2)))
                {
                    var outputSenderNode = output.Item1;
                    var outputSenderData = output.Item2;
                    var outputReceiverNode = output.Item3.Item2;

                    if (curriedNodeArgs.Any(x => x.OuterNode == outputReceiverNode))
                        continue;

                    outportList.Add(Tuple.Create(outputSenderNode, outputSenderData));

                    //Create Symbol Node
                    var node = new dynOutput()
                    {
                        Symbol = outputSenderNode.OutPortData[outputSenderData].NickName
                    };

                    var nodeUI = node.NodeUI;

                    NodeNameAttribute elNameAttrib = node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), false)[0] as NodeNameAttribute;
                    if (elNameAttrib != null)
                    {
                        nodeUI.NickName = elNameAttrib.Name;
                    }

                    nodeUI.GUID = Guid.NewGuid();

                    //store the element in the elements list
                    newNodeWorkspace.Nodes.Add(node);
                    node.WorkSpace = newNodeWorkspace;

                    node.DisableReporting();

                    Bench.WorkBench.Children.Add(nodeUI);

                    //Place it in an appropriate spot
                    Canvas.SetLeft(nodeUI, rightMost + 75 - leftShift);
                    Canvas.SetTop(nodeUI, i * (50 + node.NodeUI.Height));

                    Bench.WorkBench.UpdateLayout();

                    newNodeWorkspace.Connectors.Add(new dynConnector(
                        outputSenderNode.NodeUI,
                        nodeUI,
                        outputSenderData,
                        0,
                        0,
                        false));

                    i++;
                }
            }

            //Connect outputs to new node
            foreach (var output in outputs)
            {
                //Node to be connected to in CurrentSpace
                var outputSenderNode = output.Item1;

                //Port to be connected to on outPutNode_outer
                var outputSenderData = output.Item2;

                var outputReceiverData = output.Item3.Item1;
                var outputReceiverNode = output.Item3.Item2;

                var curriedNode = curriedNodeArgs.FirstOrDefault(
                    x => x.OuterNode == outputReceiverNode);

                if (curriedNode == null)
                {
                    CurrentSpace.Connectors.Add(
                        new dynConnector(
                            collapsedNode.NodeUI,
                            outputReceiverNode.NodeUI,
                            outportList.FindIndex(x => x.Item1 == outputSenderNode && x.Item2 == outputSenderData),
                            outputReceiverData,
                            0,
                            true));
                }
                else
                {
                    var targetPort = curriedNode.Inputs
                        .First(
                            x => x.InnerNodeInputSender == outputSenderNode)
                        .OuterNodeInPortData;

                    var targetPortIndex = curriedNode.OuterNodePortDataList.IndexOf(targetPort);

                    //Connect it (new dynConnector)
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                        outputSenderNode.NodeUI,
                        curriedNode.InnerNode.NodeUI,
                        outputSenderData,
                        targetPortIndex + 1,
                        0));
                }
            }
            #endregion

            #region Make new workspace invisible
            //Step 4: make nodes invisible
            // and update positions
            foreach (var node in newNodeWorkspace.Nodes.Select(x => x.NodeUI))
                node.Visibility = Visibility.Hidden;

            foreach (var connector in newNodeWorkspace.Connectors)
                connector.Visible = false;
            #endregion

            newNodeWorkspace.Nodes.ForEach(x => { x.EnableReporting(); x.NodeUI.UpdateConnections(); });

            collapsedNode.EnableReporting();
            collapsedNode.NodeUI.UpdateConnections();

            CurrentSpace.EnableReporting();

            SaveFunction(newNodeWorkspace, true);
        }
Example #18
0
        /// <summary>Loop through light box, blank out any previous light data and reset all light emitting sources. The light box during initial loading is the full chunk size.</summary>
        /// <param name="x1">lower x of light box for dynamic change, 0 for initial full chunk loading</param>
        /// <param name="x2">upper x of light box for dynamic change, chunk size - 1 for initial full chunk loading</param>
        /// <param name="y1">lower y of light box for dynamic change, 0 for initial full chunk loading</param>
        /// <param name="y2">upper y of light box for dynamic change, chunk height - 1 for initial full chunk loading</param>
        /// <param name="z1">lower z of light box for dynamic change, 0 for initial loading of full chunk</param>
        /// <param name="z2">upper z of light box for dynamic change, chunk size - 1 for initial full chunk loading</param>
        /// <param name="initialChunk">chunk being loaded initially or null for dynamic changes because multiple chunks may be affected</param>
        /// <param name="skyLightMap">world sky lightmap for dynamic change and chunk sky lightmap during initial loading</param>
        /// <param name="itemLightMap">world item lightmap for dynamic change and chunk item lightmap during initial loading</param>
        internal static void ResetLightBoxSources(int x1, int x2, int y1, int y2, int z1, int z2, Chunk initialChunk, byte[, ,] skyLightMap, byte[, ,] itemLightMap)
        {
            var affectedChunks = new HashSet<Chunk>();
            if (initialChunk != null) affectedChunks.Add(initialChunk);

            for (int x = x1; x <= x2; x++)
            {
                for (int z = z1; z <= z2; z++)
                {
                    //y is the innermost loop so we only retrieve chunks when needed, this is always the supplied initial chunk during initial loading
                    Chunk chunk;
                    if (initialChunk == null) //calculate the chunk if this isnt an initial loading chunk
                    {
                        chunk = WorldData.Chunks[x / Chunk.CHUNK_SIZE, z / Chunk.CHUNK_SIZE];
                        affectedChunks.Add(chunk);
                    }
                    else
                    {
                        chunk = initialChunk;
                    }

                    for (int y = y1; y <= y2; y++)
                    {
                        //chunk relative coords are needlessly calculated on initial loading, but it doesnt noticeably affect performance and this way it doesnt affect dynamic changes at all
                        int chunkRelativeX = x % Chunk.CHUNK_SIZE;
                        int chunkRelativeZ = z % Chunk.CHUNK_SIZE;

                        if (y > chunk.HeightMap[chunkRelativeX, chunkRelativeZ])
                        {
                            //transparent block above the heightmap surface, it gets full skylight, transparent blocks cannot be light emitting sources
                            skyLightMap[x, y, z] = SkyHost.BRIGHTEST_SKYLIGHT_STRENGTH;
                            itemLightMap[x, y, z] = 0; //could be a light source item here; this gets checked later
                            continue;
                        }
                        var block = chunk.Blocks[chunkRelativeX, y, chunkRelativeZ];
                        if (!block.IsTransparent)
                        {
                            //this is a non transparent block; it will have zero sky light and only have item light if this block emits light
                            skyLightMap[x, y, z] = 0;
                            itemLightMap[x, y, z] = block.IsLightSource ? block.LightStrength : (byte)0;
                        }
                        else
                        {
                            //this is a transparent block below the heightmap
                            skyLightMap[x, y, z] = 0;
                            itemLightMap[x, y, z] = 0; //could be a light source item here; this gets checked later
                        }
                    }
                }
            }

            //light source items; more efficient to loop through each affected chunks LightSources here and set the lightbox sources accordingly (better then checking for light source matches on every transparent block)
            //note: this can redundantly set item lightmap values in these chunks that are outside the light box; this doesnt hurt anything and is probably faster than checking to prevent it
            foreach (var lightSource in affectedChunks.SelectMany(affectedChunk => affectedChunk.LightSources))
            {
                int x = lightSource.Value.Coords.Xblock;
                int z = lightSource.Value.Coords.Zblock;
                if (initialChunk != null)
                {
                    x %= Chunk.CHUNK_SIZE;
                    z %= Chunk.CHUNK_SIZE;
                }
                itemLightMap[x, lightSource.Value.Coords.Yblock, z] = lightSource.Value.LightStrength;
            }
        }
        private bool CheckMemberRestraint(Member MemberToCheck, Beam StartBeam, MEMBERCLASS MemberClass)
        {
            bool output;
            HashSet<Node> nodes;

            // Gather all nodes connected to the beam to check or any beams parallel to it
            nodes = new HashSet<Node>(BeamHelpers.GatherParallelBeams(StartBeam).SelectMany(b => new List<Node>() { b.StartNode, b.EndNode}));

            // Check if any of the connected members are class above the current member
            IEnumerable<Member> connectedMembers = nodes.SelectMany(n => n.ConnectedMembers).Where(m => m != null && m != MemberToCheck);
            if (MemberClass == MEMBERCLASS.PRIMARY)
                output = connectedMembers.Any(m => this.PrimaryMembers.Contains(m));
            else if (MemberClass == MEMBERCLASS.SECONDARY)
                output = connectedMembers.Any(m => this.PrimaryMembers.Contains(m) || this.SecondaryMembers.Contains(m));
            else if (MemberClass == MEMBERCLASS.TERTIARY)
                output = connectedMembers.Any(m => this.PrimaryMembers.Contains(m) || this.SecondaryMembers.Contains(m) || this.TertiaryMembers.Contains(m));
            else
                output = false;

            return output;
        }
        /// <summary>
        /// Event handler for the "Find Images" button.  Fetches image URL's based on the field values in 
        /// the first tab, and uses that information to set field values in the second tab.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FindImagesButton_Click(object sender, RoutedEventArgs e)
        {
            MainTabControl.SelectedItem = DownloadImagesTabItem;

            // TODO:  Refactor, and make this asynchronous so it doesn't block the main UI thread

            // Get user input from XAML fields
            string entity = EntityTextBox.Text;
            RedditEntity type = (UserEntityType.IsChecked == true) ? RedditEntity.User : RedditEntity.Subreddit;
            int maxPages;
            if (!int.TryParse(MaxPagesTextBox.Text, out maxPages)) maxPages = 1;

            // Parse Imgur image and album URL's for the given Reddit user or subuser, stopping when we
            // either run out of pages or else hit the maximum page count
            HashSet<string> imageUrls = new HashSet<string>();
            HashSet<string> albumUrls = new HashSet<string>();
            string nextPageCursor = "";
            int pageCount = 1;
            for ( ; pageCount <= maxPages && nextPageCursor != null; pageCount++)
            {
                Console.WriteLine("Processing page {0} for {1} {2}", pageCount, type.ToString().ToLower(), entity);
                Uri redditUrl = RedditUtils.BuildUrl(entity, type, "".Equals(nextPageCursor) ? null : nextPageCursor);
                RedditUtils.ParsePage(redditUrl, ref imageUrls, ref albumUrls, out nextPageCursor);
                if (nextPageCursor != null) Console.WriteLine("nextPageCursor == {0}", nextPageCursor);
            }
            Console.WriteLine("Parsed {0} image URL's and {1} album URL's from {2} pages", imageUrls.Count, albumUrls.Count, pageCount);

            // Parse out image URL's from the albums
            var imagesFromAlbums = albumUrls.SelectMany(albumUrl => ImgurUtils.ParseAlbum(new Uri(albumUrl)));
            imageUrls.UnionWith(imagesFromAlbums);
            Console.WriteLine("There are {0} total images after extracting {1} from albums", imageUrls.Count, imagesFromAlbums.ToList().Count);

            PageCountLabel.Content = pageCount;
            ImagesCountLabel.Content = imageUrls.Count;
            ImagesDataGrid.ItemsSource = imageUrls.Select(imageUrl => new ImgurUrl { URL = imageUrl });
        }
Example #21
0
        private static Graph KruskalB(Graph graph)
        {
            HashSet<Vertex> inTree = new HashSet<Vertex>();
            Graph mst = graph.Clone();
            foreach (var edge in mst.Edges)
                mst.RemoveEdge(edge);

            // Start with one random vertex
            inTree.Add(graph.Vertices[0]);
            while (mst.NumberOfEdges < graph.NumberOfVertices - 1)
            {
                // Find new edge to add to the tree.
                var candidateEdges = inTree.SelectMany(graph.GetEdgesForVertex).ToList();
                candidateEdges.Sort((x, y) => x.Cost.CompareTo(y.Cost)); // Sort from cheap to expensive
                foreach (var edge in candidateEdges)
                {
                    var v1 = edge.Either();
                    var v2 = edge.Other(v1);
                    bool v1InTree = inTree.Contains(v1);
                    bool v2InTree = inTree.Contains(v2);
                    if (v1InTree ^ v2InTree) // The ^ is a XOR
                    {
                        // One side of this edge is in the MST, the other is not
                        mst.AddEdge(edge);
                        inTree.Add(v1);
                        inTree.Add(v2);
                        break;
                    }
                }
            }

            return mst;
        }
Example #22
0
        /// <summary>
        /// Find distance of a dependency from a target package.
        /// A -> B -> C
        /// C is 2 away from A
        /// </summary>
        /// <param name="packageId">package id</param>
        /// <param name="targets">required targets</param>
        /// <param name="packages">packages in the solution, only 1 package per id should exist</param>
        /// <returns>number of levels from a target</returns>
        public static int GetLowestDistanceFromTarget(string packageId, HashSet<string> targets, IEnumerable<ResolverPackage> packages)
        {
            // start with the target packages
            var walkedPackages = new HashSet<ResolverPackage>(packages.Where(package => targets.Contains(package.Id)), PackageIdentity.Comparer);

            int level = 0;

            // walk the packages, starting with the required packages until the given packageId is found
            // this is done in the simplest possible way to avoid circular dependencies
            // after 20 levels give up, the level is no longer important for ordering
            while (level < 20 && !walkedPackages.Any(package => StringComparer.OrdinalIgnoreCase.Equals(package.Id, packageId)))
            {
                level++;

                // find the next level of dependencies
                var dependencyIds = walkedPackages.SelectMany(package => package.Dependencies.Select(dependency => dependency.Id)).ToList();

                var dependencyPackages = packages.Where(package => dependencyIds.Contains(package.Id, StringComparer.OrdinalIgnoreCase));

                // add the dependency packages
                walkedPackages.UnionWith(dependencyPackages);
            }

            return level;
        }
        public override async Task<IEnumerable<PackageDependencyInfo>> ResolvePackages(IEnumerable<PackageIdentity> packages, NuGetFramework projectFramework, bool includePrerelease, CancellationToken token)
        {
            var results = new HashSet<PackageDependencyInfo>(
                Packages.Where(e => packages.Contains(e, PackageIdentity.Comparer)),
                PackageIdentity.Comparer);

            bool complete = false;

            while (!complete)
            {
                var dependencies = results.SelectMany(e => e.Dependencies).Select(e => e.Id).Distinct(StringComparer.OrdinalIgnoreCase);

                int before = results.Count;

                results.UnionWith(Packages.Where(e => dependencies.Contains(e.Id, StringComparer.OrdinalIgnoreCase)));

                complete = before == results.Count;
            }

            return results;
        }
Example #24
0
        /// <summary>
        ///     Collapse a set of nodes in a given workspace.  Has the side effects of prompting the user
        ///     first in order to obtain the name and category for the new node, 
        ///     writes the function to a dyf file, adds it to the FunctionDict, adds it to search, and compiles and 
        ///     places the newly created symbol (defining a lambda) in the Controller's FScheme Environment.  
        /// </summary>
        /// <param name="selectedNodes"> The function definition for the user-defined node </param>
        /// <param name="currentWorkspace"> The workspace where</param>
        internal static void Collapse(IEnumerable<dynNode> selectedNodes, dynWorkspace currentWorkspace)
        {
            var selectedNodeSet = new HashSet<dynNode>(selectedNodes);

            // TODO: this code needs refactoring
            #region Prompt

            //First, prompt the user to enter a name
            string newNodeName, newNodeCategory;
            string error = "";

            do
            {
                var dialog = new FunctionNamePrompt(dynSettings.Controller.SearchViewModel.Categories, error);
                if (dialog.ShowDialog() != true)
                {
                    return;
                }

                newNodeName = dialog.Text;
                newNodeCategory = dialog.Category;

                if (dynSettings.Controller.CustomNodeLoader.Contains(newNodeName))
                {
                    error = "A function with this name already exists.";
                }
                else if (newNodeCategory.Equals(""))
                {
                    error = "Please enter a valid category.";
                }
                else
                {
                    error = "";
                }
            } while (!error.Equals(""));

            var newNodeWorkspace = new FuncWorkspace(newNodeName, newNodeCategory, 0, 0);
            var newNodeDefinition = new FunctionDefinition(Guid.NewGuid());
            newNodeDefinition.Workspace = newNodeWorkspace;

            #endregion

            currentWorkspace.DisableReporting();

            #region Determine Inputs and Outputs

            //Step 1: determine which nodes will be inputs to the new node
            var inputs = new HashSet<Tuple<dynNode, int, Tuple<int, dynNode>>>(
                    selectedNodeSet
                        .SelectMany(node => Enumerable.Range(0, node.InPortData.Count)
                            .Where(node.HasInput)
                            .Select(data => Tuple.Create(node, data, node.Inputs[data]))
                                                 .Where(input => !selectedNodeSet.Contains(input.Item3.Item2))));

            var outputs = new HashSet<Tuple<dynNode, int, Tuple<int, dynNode>>>(
                selectedNodeSet.SelectMany(
                    node => Enumerable.Range(0, node.OutPortData.Count).Where(node.HasOutput).SelectMany(
                        data => node.Outputs[data]
                                    .Where(output => !selectedNodeSet.Contains(output.Item2))
                                    .Select(output => Tuple.Create(node, data, output)))));

            #endregion

            #region Detect 1-node holes (higher-order function extraction)

            var curriedNodeArgs =
                new HashSet<dynNode>(
                    inputs
                        .Select(x => x.Item3.Item2)
                        .Intersect(outputs.Select(x => x.Item3.Item2)))
                    .Select(
                        outerNode =>
                        {
                            var node = new dynApply1();

                            dynNodeUI nodeUI = node.NodeUI;

                            var elNameAttrib =
                                node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), true)[0] as
                                NodeNameAttribute;
                            if (elNameAttrib != null)
                            {
                                nodeUI.NickName = elNameAttrib.Name;
                            }

                            nodeUI.GUID = Guid.NewGuid();

                            //store the element in the elements list
                            newNodeWorkspace.Nodes.Add(node);
                            node.WorkSpace = newNodeWorkspace;

                            node.DisableReporting();

                            dynSettings.Bench.WorkBench.Children.Add(nodeUI);

                            //Place it in an appropriate spot
                            Canvas.SetLeft(nodeUI, Canvas.GetLeft(outerNode.NodeUI));
                            Canvas.SetTop(nodeUI, Canvas.GetTop(outerNode.NodeUI));

                            //Fetch all input ports
                            // in order
                            // that have inputs
                            // and whose input comes from an inner node
                            List<int> inPortsConnected = Enumerable.Range(0, outerNode.InPortData.Count)
                                                                   .Where(
                                                                       x =>
                                                                       outerNode.HasInput(x) &&
                                                                       selectedNodeSet.Contains(
                                                                           outerNode.Inputs[x].Item2))
                                                                   .ToList();

                            var nodeInputs = outputs
                                .Where(output => output.Item3.Item2 == outerNode)
                                .Select(
                                    output =>
                                    new
                                    {
                                        InnerNodeInputSender = output.Item1,
                                        OuterNodeInPortData = output.Item3.Item1
                                    }).ToList();

                            nodeInputs.ForEach(_ => node.AddInput());

                            node.NodeUI.RegisterAllPorts();

                            dynSettings.Bench.WorkBench.UpdateLayout();

                            return new
                            {
                                OuterNode = outerNode,
                                InnerNode = node,
                                Outputs = inputs.Where(input => input.Item3.Item2 == outerNode)
                                                .Select(input => input.Item3.Item1),
                                Inputs = nodeInputs,
                                OuterNodePortDataList = inPortsConnected
                            };
                        }).ToList();

            #endregion

            #region UI Positioning Calculations

            double avgX = selectedNodeSet.Average(node => Canvas.GetLeft(node.NodeUI));
            double avgY = selectedNodeSet.Average(node => Canvas.GetTop(node.NodeUI));

            double leftMost = selectedNodeSet.Min(node => Canvas.GetLeft(node.NodeUI)) + 24;
            double topMost = selectedNodeSet.Min(node => Canvas.GetTop(node.NodeUI));
            double rightMost = selectedNodeSet.Max(node => Canvas.GetLeft(node.NodeUI) + node.NodeUI.Width);

            #endregion

            #region Move selection to new workspace

            var connectors = new HashSet<dynConnector>(
                currentWorkspace.Connectors.Where(
                    conn => selectedNodeSet.Contains(conn.Start.Owner.NodeLogic)
                            && selectedNodeSet.Contains(conn.End.Owner.NodeLogic)));

            //Step 2: move all nodes to new workspace
            //  remove from old
            currentWorkspace.Nodes.RemoveAll(selectedNodeSet.Contains);
            currentWorkspace.Connectors.RemoveAll(connectors.Contains);

            //  add to new
            newNodeWorkspace.Nodes.AddRange(selectedNodeSet);
            newNodeWorkspace.Connectors.AddRange(connectors);

            double leftShift = leftMost - 250;
            foreach (dynNodeUI node in newNodeWorkspace.Nodes.Select(x => x.NodeUI))
            {
                Canvas.SetLeft(node, Canvas.GetLeft(node) - leftShift);
                Canvas.SetTop(node, Canvas.GetTop(node) - topMost + 120);
            }

            #endregion

            #region Insert new node into the current workspace

            //Step 5: insert new node into original workspace
            var collapsedNode = new dynFunction(
                inputs.Select(x => x.Item1.InPortData[x.Item2].NickName),
                outputs
                    .Where(x => !curriedNodeArgs.Any(y => y.OuterNode == x.Item3.Item2))
                    .Select(x => x.Item1.OutPortData[x.Item2].NickName),
                newNodeDefinition);

            collapsedNode.NodeUI.GUID = Guid.NewGuid();

            currentWorkspace.Nodes.Add(collapsedNode);
            collapsedNode.WorkSpace = currentWorkspace;

            dynSettings.Bench.WorkBench.Children.Add(collapsedNode.NodeUI);

            Canvas.SetLeft(collapsedNode.NodeUI, avgX);
            Canvas.SetTop(collapsedNode.NodeUI, avgY);

            #endregion

            #region Destroy all hanging connectors

            //Step 6: connect inputs and outputs
            foreach (dynConnector connector in currentWorkspace.Connectors
                                                           .Where(
                                                               c =>
                                                               selectedNodeSet.Contains(c.Start.Owner.NodeLogic) &&
                                                               !selectedNodeSet.Contains(c.End.Owner.NodeLogic))
                                                           .ToList())
            {
                connector.Kill();
            }

            foreach (dynConnector connector in currentWorkspace.Connectors
                                                           .Where(
                                                               c =>
                                                               !selectedNodeSet.Contains(c.Start.Owner.NodeLogic) &&
                                                               selectedNodeSet.Contains(c.End.Owner.NodeLogic)).ToList()
                )
            {
                connector.Kill();
            }

            #endregion

            newNodeWorkspace.Nodes.ForEach(x => x.DisableReporting());

            var inConnectors = new List<Tuple<dynNodeUI, int, int>>();

            #region Process inputs

            //Step 3: insert variables (reference step 1)
            foreach (var input in Enumerable.Range(0, inputs.Count).Zip(inputs, Tuple.Create))
            {
                int inputIndex = input.Item1;

                dynNode inputReceiverNode = input.Item2.Item1;
                int inputReceiverData = input.Item2.Item2;

                dynNode inputNode = input.Item2.Item3.Item2;
                int inputData = input.Item2.Item3.Item1;

                inConnectors.Add(new Tuple<dynNodeUI, int, int>(inputNode.NodeUI, inputData, inputIndex));

                //Create Symbol Node
                var node = new dynSymbol
                {
                    Symbol = inputReceiverNode.InPortData[inputReceiverData].NickName
                };

                dynNodeUI nodeUI = node.NodeUI;

                var elNameAttrib =
                    node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), true)[0] as NodeNameAttribute;
                if (elNameAttrib != null)
                {
                    nodeUI.NickName = elNameAttrib.Name;
                }

                nodeUI.GUID = Guid.NewGuid();

                //store the element in the elements list
                newNodeWorkspace.Nodes.Add(node);
                node.WorkSpace = newNodeWorkspace;

                node.DisableReporting();

                dynSettings.Bench.WorkBench.Children.Add(nodeUI);

                //Place it in an appropriate spot
                Canvas.SetLeft(nodeUI, 0);
                Canvas.SetTop(nodeUI, inputIndex * (50 + node.NodeUI.Height));

                dynSettings.Bench.WorkBench.UpdateLayout();

                var curriedNode = curriedNodeArgs.FirstOrDefault(
                    x => x.OuterNode == inputNode);

                if (curriedNode == null)
                {
                    //Connect it (new dynConnector)
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                                                        nodeUI,
                                                        inputReceiverNode.NodeUI,
                                                        0,
                                                        inputReceiverData,
                                                        0,
                                                        false));
                }
                else
                {
                    //Connect it to the applier
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                                                        nodeUI,
                                                        curriedNode.InnerNode.NodeUI,
                                                        0,
                                                        0,
                                                        0,
                                                        false));

                    //Connect applier to the inner input receiver
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                                                        curriedNode.InnerNode.NodeUI,
                                                        inputReceiverNode.NodeUI,
                                                        0,
                                                        inputReceiverData,
                                                        0,
                                                        false));
                }
            }

            #endregion

            #region Process outputs

            //List of all inner nodes to connect an output. Unique.
            var outportList = new List<Tuple<dynNode, int>>();

            var outConnectors = new List<Tuple<dynNodeUI, int, int>>();

            int i = 0;
            foreach (var output in outputs)
            {
                if (outportList.All(x => !(x.Item1 == output.Item1 && x.Item2 == output.Item2)))
                {
                    dynNode outputSenderNode = output.Item1;
                    int outputSenderData = output.Item2;
                    dynNode outputReceiverNode = output.Item3.Item2;

                    if (curriedNodeArgs.Any(x => x.OuterNode == outputReceiverNode))
                        continue;

                    outportList.Add(Tuple.Create(outputSenderNode, outputSenderData));

                    //Create Symbol Node
                    var node = new dynOutput
                    {
                        Symbol = outputSenderNode.OutPortData[outputSenderData].NickName
                    };

                    dynNodeUI nodeUI = node.NodeUI;

                    var elNameAttrib =
                        node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), false)[0] as NodeNameAttribute;
                    if (elNameAttrib != null)
                    {
                        nodeUI.NickName = elNameAttrib.Name;
                    }

                    nodeUI.GUID = Guid.NewGuid();

                    //store the element in the elements list
                    newNodeWorkspace.Nodes.Add(node);
                    node.WorkSpace = newNodeWorkspace;

                    node.DisableReporting();

                    dynSettings.Bench.WorkBench.Children.Add(nodeUI);

                    //Place it in an appropriate spot
                    Canvas.SetLeft(nodeUI, rightMost + 75 - leftShift);
                    Canvas.SetTop(nodeUI, i * (50 + node.NodeUI.Height));

                    dynSettings.Bench.WorkBench.UpdateLayout();

                    newNodeWorkspace.Connectors.Add(new dynConnector(
                                                        outputSenderNode.NodeUI,
                                                        nodeUI,
                                                        outputSenderData,
                                                        0,
                                                        0,
                                                        false));

                    i++;
                }
            }

            //Connect outputs to new node
            foreach (var output in outputs)
            {
                //Node to be connected to in CurrentSpace
                dynNode outputSenderNode = output.Item1;

                //Port to be connected to on outPutNode_outer
                int outputSenderData = output.Item2;

                int outputReceiverData = output.Item3.Item1;
                dynNode outputReceiverNode = output.Item3.Item2;

                var curriedNode = curriedNodeArgs.FirstOrDefault(
                    x => x.OuterNode == outputReceiverNode);

                if (curriedNode == null)
                {
                    // we create the connectors in the current space later
                    outConnectors.Add(new Tuple<dynNodeUI, int, int>(outputReceiverNode.NodeUI,
                                                                     outportList.FindIndex(x => x.Item1 == outputSenderNode && x.Item2 == outputSenderData),
                                                                     outputReceiverData));
                }
                else
                {
                    int targetPort = curriedNode.Inputs
                                                .First(
                                                    x => x.InnerNodeInputSender == outputSenderNode)
                                                .OuterNodeInPortData;

                    int targetPortIndex = curriedNode.OuterNodePortDataList.IndexOf(targetPort);

                    //Connect it (new dynConnector)
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                                                        outputSenderNode.NodeUI,
                                                        curriedNode.InnerNode.NodeUI,
                                                        outputSenderData,
                                                        targetPortIndex + 1,
                                                        0));
                }
            }

            #endregion

            #region Make new workspace invisible

            //Step 4: make nodes invisible
            // and update positions
            foreach (dynNodeUI node in newNodeWorkspace.Nodes.Select(x => x.NodeUI))
                node.Visibility = Visibility.Hidden;

            foreach (dynConnector connector in newNodeWorkspace.Connectors)
                connector.Visible = false;

            #endregion

            //set the name on the node
            collapsedNode.NodeUI.NickName = newNodeName;

            currentWorkspace.Nodes.Remove(collapsedNode);
            dynSettings.Bench.WorkBench.Children.Remove(collapsedNode.NodeUI);

            // save and load the definition from file
            var path = dynSettings.Controller.SaveFunctionOnly(newNodeDefinition);
            dynSettings.Controller.CustomNodeLoader.SetNodeInfo(newNodeName, newNodeCategory, newNodeDefinition.FunctionId, path);
            dynSettings.Controller.SearchViewModel.Add(newNodeName, newNodeCategory, newNodeDefinition.FunctionId);

            DynamoCommands.CreateNodeCmd.Execute(new Dictionary<string, object>()
                {
                    {"name", collapsedNode.Definition.FunctionId.ToString() },
                    {"x", avgX },
                    {"y", avgY }
                });

            var newlyPlacedCollapsedNode = currentWorkspace.Nodes
                                            .Where(node => node is dynFunction)
                                            .First(node => ((dynFunction)node).Definition.FunctionId == newNodeDefinition.FunctionId);

            newlyPlacedCollapsedNode.DisableReporting();

            dynSettings.Bench.WorkBench.UpdateLayout(); // without doing this, connectors fail to be created

            foreach (var nodeTuple in inConnectors)
            {
                currentWorkspace.Connectors.Add(
                    new dynConnector(
                        nodeTuple.Item1,
                        newlyPlacedCollapsedNode.NodeUI,
                        nodeTuple.Item2,
                        nodeTuple.Item3,
                        0,
                        true));
            }

            foreach (var nodeTuple in outConnectors)
            {
                currentWorkspace.Connectors.Add(
                    new dynConnector(
                        newlyPlacedCollapsedNode.NodeUI,
                        nodeTuple.Item1,
                        nodeTuple.Item2,
                        nodeTuple.Item3,
                        0,
                        true));
            }

            newlyPlacedCollapsedNode.EnableReporting();
            currentWorkspace.EnableReporting();
        }
Example #25
0
        /// <summary>
        ///     Collapse a set of nodes in a given workspace.
        /// </summary>
        /// <param name="selectedNodes"> The function definition for the user-defined node </param>
        /// <param name="currentWorkspace"> The workspace where</param>
        /// <param name="isTestMode"></param>
        /// <param name="args"></param>
        public CustomNodeWorkspaceModel Collapse(
            IEnumerable<NodeModel> selectedNodes, WorkspaceModel currentWorkspace,
            bool isTestMode, FunctionNamePromptEventArgs args)
        {
            var selectedNodeSet = new HashSet<NodeModel>(selectedNodes);
            // Note that undoable actions are only recorded for the "currentWorkspace", 
            // the nodes which get moved into "newNodeWorkspace" are not recorded for undo,
            // even in the new workspace. Their creations will simply be treated as part of
            // the opening of that new workspace (i.e. when a user opens a file, she will 
            // not expect the nodes that show up to be undoable).
            // 
            // After local nodes are moved into "newNodeWorkspace" as the result of 
            // conversion, if user performs an undo, new set of nodes will be created in 
            // "currentWorkspace" (not moving those nodes in the "newNodeWorkspace" back 
            // into "currentWorkspace"). In another word, undo recording is on a per-
            // workspace basis, it does not work across different workspaces.
            // 
            UndoRedoRecorder undoRecorder = currentWorkspace.UndoRecorder;

            CustomNodeWorkspaceModel newWorkspace;

            using (undoRecorder.BeginActionGroup())
            {
                #region Determine Inputs and Outputs

                //Step 1: determine which nodes will be inputs to the new node
                var inputs =
                    new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
                        selectedNodeSet.SelectMany(
                            node =>
                                Enumerable.Range(0, node.InPortData.Count)
                                .Where(node.HasConnectedInput)
                                .Select(data => Tuple.Create(node, data, node.InputNodes[data]))
                                .Where(input => !selectedNodeSet.Contains(input.Item3.Item2))));

                var outputs =
                    new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
                        selectedNodeSet.SelectMany(
                            node =>
                                Enumerable.Range(0, node.OutPortData.Count)
                                .Where(node.HasOutput)
                                .SelectMany(
                                    data =>
                                        node.OutputNodes[data].Where(
                                            output => !selectedNodeSet.Contains(output.Item2))
                                        .Select(output => Tuple.Create(node, data, output)))));

                #endregion

                #region Detect 1-node holes (higher-order function extraction)

                Log(Properties.Resources.CouldNotRepairOneNodeHoles, WarningLevel.Mild);
                // http://adsk-oss.myjetbrains.com/youtrack/issue/MAGN-5603

                //var curriedNodeArgs =
                //    new HashSet<NodeModel>(
                //        inputs.Select(x => x.Item3.Item2)
                //            .Intersect(outputs.Select(x => x.Item3.Item2))).Select(
                //                outerNode =>
                //                {
                //                    //var node = new Apply1();
                //                    var node = newNodeWorkspace.AddNode<Apply1>();
                //                    node.SetNickNameFromAttribute();

                //                    node.DisableReporting();

                //                    node.X = outerNode.X;
                //                    node.Y = outerNode.Y;

                //                    //Fetch all input ports
                //                    // in order
                //                    // that have inputs
                //                    // and whose input comes from an inner node
                //                    List<int> inPortsConnected =
                //                        Enumerable.Range(0, outerNode.InPortData.Count)
                //                            .Where(
                //                                x =>
                //                                    outerNode.HasInput(x)
                //                                        && selectedNodeSet.Contains(
                //                                            outerNode.Inputs[x].Item2))
                //                            .ToList();

                //                    var nodeInputs =
                //                        outputs.Where(output => output.Item3.Item2 == outerNode)
                //                            .Select(
                //                                output =>
                //                                    new
                //                                    {
                //                                        InnerNodeInputSender = output.Item1,
                //                                        OuterNodeInPortData = output.Item3.Item1
                //                                    })
                //                            .ToList();

                //                    nodeInputs.ForEach(_ => node.AddInput());

                //                    node.RegisterAllPorts();

                //                    return
                //                        new
                //                        {
                //                            OuterNode = outerNode,
                //                            InnerNode = node,
                //                            Outputs =
                //                                inputs.Where(
                //                                    input => input.Item3.Item2 == outerNode)
                //                                    .Select(input => input.Item3.Item1),
                //                            Inputs = nodeInputs,
                //                            OuterNodePortDataList = inPortsConnected
                //                        };
                //                }).ToList();

                #endregion

                #region UI Positioning Calculations

                double avgX = selectedNodeSet.Average(node => node.X);
                double avgY = selectedNodeSet.Average(node => node.Y);

                double leftMost = selectedNodeSet.Min(node => node.X);
                double topMost = selectedNodeSet.Min(node => node.Y);
                double rightMost = selectedNodeSet.Max(node => node.X + node.Width);

                double leftShift = leftMost - 250;

                #endregion

                #region Handle full selected connectors

                // Step 2: Determine all the connectors whose start/end owners are 
                // both in the selection set, and then move them from the current 
                // workspace into the new workspace.

                var fullySelectedConns = new HashSet<ConnectorModel>(
                    currentWorkspace.Connectors.Where(
                        conn =>
                        {
                            bool startSelected = selectedNodeSet.Contains(conn.Start.Owner);
                            bool endSelected = selectedNodeSet.Contains(conn.End.Owner);
                            return startSelected && endSelected;
                        }));

                foreach (var connector in fullySelectedConns)
                {
                    undoRecorder.RecordDeletionForUndo(connector);
                    connector.Delete();
                }

                #endregion

                #region Handle partially selected connectors

                // Step 3: Partially selected connectors (either one of its start 
                // and end owners is in the selection) are to be destroyed.

                var partiallySelectedConns =
                    currentWorkspace.Connectors.Where(
                        conn =>
                            selectedNodeSet.Contains(conn.Start.Owner)
                                || selectedNodeSet.Contains(conn.End.Owner)).ToList();

                foreach (var connector in partiallySelectedConns)
                {
                    undoRecorder.RecordDeletionForUndo(connector);
                    connector.Delete();
                }

                #endregion

                #region Transfer nodes and connectors to new workspace

                var newNodes = new List<NodeModel>();
                var newAnnotations = new List<AnnotationModel>();
            
                // Step 4: move all nodes to new workspace remove from old
                // PB: This could be more efficiently handled by a copy paste, but we
                // are preservering the node 
                foreach (var node in selectedNodeSet)
                {                   
                    undoRecorder.RecordDeletionForUndo(node);
                    currentWorkspace.RemoveNode(node);

                    // Assign a new guid to this node, otherwise when node is
                    // compiled to AST, literally it is still in global scope
                    // instead of in function scope.
                    node.GUID = Guid.NewGuid();
                    node.RenderPackages.Clear();

                    // shift nodes
                    node.X = node.X - leftShift;
                    node.Y = node.Y - topMost;
                 
                    newNodes.Add(node);
                }

                //Copy the group from newNodes
                foreach (var group in DynamoSelection.Instance.Selection.OfType<AnnotationModel>())
                {
                    undoRecorder.RecordDeletionForUndo(group);
                    currentWorkspace.RemoveGroup(group);

                    group.GUID = Guid.NewGuid();
                    group.SelectedModels = group.DeletedModelBases;
                    newAnnotations.Add(group);
                }


                foreach (var conn in fullySelectedConns)
                {
                    ConnectorModel.Make(conn.Start.Owner, conn.End.Owner, conn.Start.Index, conn.End.Index);
                }

                #endregion

                #region Process inputs

                var inConnectors = new List<Tuple<NodeModel, int>>();
                var uniqueInputSenders = new Dictionary<Tuple<NodeModel, int>, Symbol>();

                //Step 3: insert variables (reference step 1)
                foreach (var input in Enumerable.Range(0, inputs.Count).Zip(inputs, Tuple.Create))
                {
                    int inputIndex = input.Item1;

                    NodeModel inputReceiverNode = input.Item2.Item1;
                    int inputReceiverData = input.Item2.Item2;

                    NodeModel inputNode = input.Item2.Item3.Item2;
                    int inputData = input.Item2.Item3.Item1;

                    Symbol node;

                    var key = Tuple.Create(inputNode, inputData);
                    if (uniqueInputSenders.ContainsKey(key))
                    {
                        node = uniqueInputSenders[key];
                    }
                    else
                    {
                        inConnectors.Add(Tuple.Create(inputNode, inputData));

                        node = new Symbol
                        {
                            InputSymbol = inputReceiverNode.InPortData[inputReceiverData].NickName,
                            X = 0
                        };

                        // Try to figure out the type of input of custom node 
                        // from the type of input of selected node. There are
                        // two kinds of nodes whose input type are available:
                        // function node and custom node. 
                        List<Library.TypedParameter> parameters = null;

                        if (inputReceiverNode is Function) 
                        {
                            var func = inputReceiverNode as Function; 
                            parameters =  func.Controller.Definition.Parameters.ToList(); 
                        }
                        else if (inputReceiverNode is DSFunctionBase)
                        {
                            var dsFunc = inputReceiverNode as DSFunctionBase;
                            var funcDesc = dsFunc.Controller.Definition;
                            parameters = funcDesc.Parameters.ToList();

                            if (funcDesc.Type == DSEngine.FunctionType.InstanceMethod ||
                                funcDesc.Type == DSEngine.FunctionType.InstanceProperty)
                            {
                                var dummyType = new ProtoCore.Type() { Name = funcDesc.ClassName };
                                var instanceParam = new TypedParameter(funcDesc.ClassName, dummyType);
                                parameters.Insert(0, instanceParam);
                            }
                        }

                        // so the input of custom node has format 
                        //    input_var_name : type
                        if (parameters != null && parameters.Count() > inputReceiverData)
                        {
                            var typeName = parameters[inputReceiverData].DisplayTypeName;
                            if (!string.IsNullOrEmpty(typeName))
                            {
                                node.InputSymbol += " : " + typeName;
                            }
                        }

                        node.SetNickNameFromAttribute();
                        node.Y = inputIndex*(50 + node.Height);

                        uniqueInputSenders[key] = node;

                        newNodes.Add(node);
                    }

                    //var curriedNode = curriedNodeArgs.FirstOrDefault(x => x.OuterNode == inputNode);

                    //if (curriedNode == null)
                    //{
                    ConnectorModel.Make(node, inputReceiverNode, 0, inputReceiverData);
                    //}
                    //else
                    //{
                    //    //Connect it to the applier
                    //    newNodeWorkspace.AddConnection(node, curriedNode.InnerNode, 0, 0);

                    //    //Connect applier to the inner input receive
                    //    newNodeWorkspace.AddConnection(
                    //        curriedNode.InnerNode,
                    //        inputReceiverNode,
                    //        0,
                    //        inputReceiverData);
                    //}
                }

                #endregion

                #region Process outputs

                //List of all inner nodes to connect an output. Unique.
                var outportList = new List<Tuple<NodeModel, int>>();

                var outConnectors = new List<Tuple<NodeModel, int, int>>();

                int i = 0;
                if (outputs.Any())
                {
                    foreach (var output in outputs)
                    {
                        if (outportList.All(x => !(x.Item1 == output.Item1 && x.Item2 == output.Item2)))
                        {
                            NodeModel outputSenderNode = output.Item1;
                            int outputSenderData = output.Item2;

                            //NodeModel outputReceiverNode = output.Item3.Item2;

                            //if (curriedNodeArgs.Any(x => x.OuterNode == outputReceiverNode))
                            //    continue;

                            outportList.Add(Tuple.Create(outputSenderNode, outputSenderData));

                            //Create Symbol Node
                            var node = new Output
                            {
                                Symbol = outputSenderNode.OutPortData[outputSenderData].NickName,
                                X = rightMost + 75 - leftShift
                            };

                            node.Y = i*(50 + node.Height);

                            node.SetNickNameFromAttribute();

                            newNodes.Add(node);
                            ConnectorModel.Make(outputSenderNode, node, outputSenderData, 0);

                            i++;
                        }
                    }

                    //Connect outputs to new node
                    outConnectors.AddRange(
                        from output in outputs
                        let outputSenderNode = output.Item1
                        let outputSenderData = output.Item2
                        let outputReceiverData = output.Item3.Item1
                        let outputReceiverNode = output.Item3.Item2
                        select
                            Tuple.Create(
                                outputReceiverNode,
                                outportList.FindIndex(
                                    x => x.Item1 == outputSenderNode && x.Item2 == outputSenderData),
                                outputReceiverData));
                }
                else
                {
                    foreach (var hanging in
                        selectedNodeSet.SelectMany(
                            node =>
                                Enumerable.Range(0, node.OutPortData.Count)
                                .Where(port => !node.HasOutput(port))
                                .Select(port => new { node, port })).Distinct())
                    {
                        //Create Symbol Node
                        var node = new Output
                        {
                            Symbol = hanging.node.OutPortData[hanging.port].NickName,
                            X = rightMost + 75 - leftShift
                        };
                        node.Y = i*(50 + node.Height);
                        node.SetNickNameFromAttribute();

                        newNodes.Add(node);
                        ConnectorModel.Make(hanging.node, node, hanging.port, 0);

                        i++;
                    }
                }

                #endregion

                var newId = Guid.NewGuid();
                newWorkspace = new CustomNodeWorkspaceModel(
                    nodeFactory,
                    newNodes,
                    Enumerable.Empty<NoteModel>(),
                    newAnnotations,
                    Enumerable.Empty<PresetModel>(),
                    new WorkspaceInfo()
                    {
                        X = 0,
                        Y = 0,
                        Name = args.Name,
                        Category = args.Category,
                        Description = args.Description,
                        ID = newId.ToString(),
                        FileName = string.Empty
                    },
                    currentWorkspace.ElementResolver);
                
                newWorkspace.HasUnsavedChanges = true;

                RegisterCustomNodeWorkspace(newWorkspace);

                var collapsedNode = CreateCustomNodeInstance(newId, isTestMode: isTestMode);
                collapsedNode.X = avgX;
                collapsedNode.Y = avgY;
                currentWorkspace.AddNode(collapsedNode, centered: false);
                undoRecorder.RecordCreationForUndo(collapsedNode);

                foreach (var connector in
                    inConnectors.Select((x, idx) => new { node = x.Item1, from = x.Item2, to = idx })
                        .Select(
                            nodeTuple =>
                                ConnectorModel.Make(
                                    nodeTuple.node,
                                    collapsedNode,
                                    [email protected],
                                    nodeTuple.to))
                        .Where(connector => connector != null))
                {
                    undoRecorder.RecordCreationForUndo(connector);
                }

                foreach (var connector in
                    outConnectors.Select(
                        nodeTuple =>
                            ConnectorModel.Make(
                                collapsedNode,
                                nodeTuple.Item1,
                                nodeTuple.Item2,
                                nodeTuple.Item3)).Where(connector => connector != null))
                {
                    undoRecorder.RecordCreationForUndo(connector);
                }
            }
            return newWorkspace;
        }
		/// <summary>
		/// Main entry point for the BuildGraph command
		/// </summary>
		public override ExitCode Execute()
		{
			// Parse the command line parameters
			string ScriptFileName = ParseParamValue("Script", null);
			string TargetNames = ParseParamValue("Target", null);
			string DocumentationFileName = ParseParamValue("Documentation", null);
			string SchemaFileName = ParseParamValue("Schema", null);
			string ExportFileName = ParseParamValue("Export", null);
			string PreprocessedFileName = ParseParamValue("Preprocess", null);
			string SharedStorageDir = ParseParamValue("SharedStorageDir", null);
			string SingleNodeName = ParseParamValue("SingleNode", null);
			string TriggerName = ParseParamValue("Trigger", null);
			string[] SkipTriggerNames = ParseParamValue("SkipTrigger", "").Split(new char[]{ '+', ';' }, StringSplitOptions.RemoveEmptyEntries).ToArray();
			bool bSkipTriggers = ParseParam("SkipTriggers");
			string TokenSignature = ParseParamValue("TokenSignature", null);
			bool bSkipTargetsWithoutTokens = ParseParam("SkipTargetsWithoutTokens");
			bool bClearHistory = ParseParam("Clean") || ParseParam("ClearHistory");
			bool bListOnly = ParseParam("ListOnly");
			bool bWriteToSharedStorage = ParseParam("WriteToSharedStorage") || CommandUtils.IsBuildMachine;
			bool bPublicTasksOnly = ParseParam("PublicTasksOnly");
			string ReportName = ParseParamValue("ReportName", null); 

			GraphPrintOptions PrintOptions = GraphPrintOptions.ShowCommandLineOptions;
			if(ParseParam("ShowDeps"))
			{
				PrintOptions |= GraphPrintOptions.ShowDependencies;
			}
			if(ParseParam("ShowNotifications"))
			{
				PrintOptions |= GraphPrintOptions.ShowNotifications;
			}

			// Parse any specific nodes to clean
			List<string> CleanNodes = new List<string>();
			foreach(string NodeList in ParseParamValues("CleanNode"))
			{
				foreach(string NodeName in NodeList.Split('+', ';'))
				{
					CleanNodes.Add(NodeName);
				}
			}

			// Set up the standard properties which build scripts might need
			Dictionary<string, string> DefaultProperties = new Dictionary<string,string>(StringComparer.InvariantCultureIgnoreCase);
			DefaultProperties["Branch"] = P4Enabled ? P4Env.BuildRootP4 : "Unknown";
			DefaultProperties["EscapedBranch"] = P4Enabled ? P4Env.BuildRootEscaped : "Unknown";
			DefaultProperties["Change"] = P4Enabled ? P4Env.Changelist.ToString() : "0";
			DefaultProperties["CodeChange"] = P4Enabled ? P4Env.CodeChangelist.ToString() : "0";
			DefaultProperties["RootDir"] = CommandUtils.RootDirectory.FullName;
			DefaultProperties["IsBuildMachine"] = IsBuildMachine ? "true" : "false";
			DefaultProperties["HostPlatform"] = HostPlatform.Current.HostEditorPlatform.ToString();

			// Attempt to read existing Build Version information
			BuildVersion Version;
			if (BuildVersion.TryRead(FileReference.Combine(CommandUtils.RootDirectory, "Engine", "Build", "Build.version").FullName, out Version))
			{
				DefaultProperties["EngineMajorVersion"] = Version.MajorVersion.ToString();
				DefaultProperties["EngineMinorVersion"] = Version.MinorVersion.ToString();
				DefaultProperties["EnginePatchVersion"] = Version.PatchVersion.ToString();
			}

			// Add any additional custom arguments from the command line (of the form -Set:X=Y)
			Dictionary<string, string> Arguments = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
			foreach (string Param in Params)
			{
				const string Prefix = "set:";
				if(Param.StartsWith(Prefix, StringComparison.InvariantCultureIgnoreCase))
				{
					int EqualsIdx = Param.IndexOf('=');
					if(EqualsIdx >= 0)
					{
						Arguments[Param.Substring(Prefix.Length, EqualsIdx - Prefix.Length)] = Param.Substring(EqualsIdx + 1);
					}
					else
					{
						LogWarning("Missing value for '{0}'", Param.Substring(Prefix.Length));
					}
				}
			}

			// Find all the tasks from the loaded assemblies
			Dictionary<string, ScriptTask> NameToTask = new Dictionary<string,ScriptTask>();
			if(!FindAvailableTasks(NameToTask, bPublicTasksOnly))
			{
				return ExitCode.Error_Unknown;
			}

			// Generate documentation
			if(DocumentationFileName != null)
			{
				GenerateDocumentation(NameToTask, new FileReference(DocumentationFileName));
				return ExitCode.Success;
			}

			// Create a schema for the given tasks
			ScriptSchema Schema = new ScriptSchema(NameToTask);
			if(SchemaFileName != null)
			{
				FileReference FullSchemaFileName = new FileReference(SchemaFileName);
				Log("Writing schema to {0}...", FullSchemaFileName.FullName);
				Schema.Export(FullSchemaFileName);
				if(ScriptFileName == null)
				{
					return ExitCode.Success;
				}
			}

			// Check there was a script specified
			if(ScriptFileName == null)
			{
				LogError("Missing -Script= parameter for BuildGraph");
				return ExitCode.Error_Unknown;
			}

			// Read the script from disk
			Graph Graph;
			if(!ScriptReader.TryRead(new FileReference(ScriptFileName), Arguments, DefaultProperties, Schema, out Graph))
			{
				return ExitCode.Error_Unknown;
			}

			// Create the temp storage handler
			DirectoryReference RootDir = new DirectoryReference(CommandUtils.CmdEnv.LocalRoot);
			TempStorage Storage = new TempStorage(RootDir, DirectoryReference.Combine(RootDir, "Engine", "Saved", "BuildGraph"), (SharedStorageDir == null)? null : new DirectoryReference(SharedStorageDir), bWriteToSharedStorage);
			if(bClearHistory)
			{
				Storage.CleanLocal();
			}
			foreach(string CleanNode in CleanNodes)
			{
				Storage.CleanLocalNode(CleanNode);
			}

			// Convert the supplied target references into nodes 
			HashSet<Node> TargetNodes = new HashSet<Node>();
			if(TargetNames == null)
			{
				if(!bListOnly)
				{
					LogError("Missing -Target= parameter for BuildGraph");
					return ExitCode.Error_Unknown;
				}
				TargetNodes.UnionWith(Graph.Agents.SelectMany(x => x.Nodes));
			}
			else
			{
				foreach(string TargetName in TargetNames.Split(new char[]{ '+', ';' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()))
				{
					Node[] Nodes;
					if(!Graph.TryResolveReference(TargetName, out Nodes))
					{
						LogError("Target '{0}' is not in graph", TargetName);
						return ExitCode.Error_Unknown;
					}
					TargetNodes.UnionWith(Nodes);
				}
			}

			// Try to acquire tokens for all the target nodes we want to build
			if(TokenSignature != null)
			{
				// Find all the lock files
				HashSet<FileReference> RequiredTokens = new HashSet<FileReference>(TargetNodes.SelectMany(x => x.RequiredTokens));

				// List out all the required tokens
				if(SingleNodeName == null)
				{
					CommandUtils.Log("Required tokens:");
					foreach(Node Node in TargetNodes)
					{
						foreach(FileReference RequiredToken in Node.RequiredTokens)
						{
							CommandUtils.Log("  '{0}' requires {1}", Node, RequiredToken);
						}
					}
				}

				// Try to create all the lock files
				List<FileReference> CreatedTokens = new List<FileReference>();
				if(!bListOnly)
				{
					CreatedTokens.AddRange(RequiredTokens.Where(x => WriteTokenFile(x, TokenSignature)));
				}

				// Find all the tokens that we don't have
				Dictionary<FileReference, string> MissingTokens = new Dictionary<FileReference, string>();
				foreach(FileReference RequiredToken in RequiredTokens)
				{
					string CurrentOwner = ReadTokenFile(RequiredToken);
					if(CurrentOwner != null && CurrentOwner != TokenSignature)
					{
						MissingTokens.Add(RequiredToken, CurrentOwner);
					}
				}

				// If we want to skip all the nodes with missing locks, adjust the target nodes to account for it
				if(MissingTokens.Count > 0)
				{
					if(bSkipTargetsWithoutTokens)
					{
						// Find all the nodes we're going to skip
						HashSet<Node> SkipNodes = new HashSet<Node>();
						foreach(IGrouping<string, FileReference> MissingTokensForBuild in MissingTokens.GroupBy(x => x.Value, x => x.Key))
						{
							Log("Skipping the following nodes due to {0}:", MissingTokensForBuild.Key);
							foreach(FileReference MissingToken in MissingTokensForBuild)
							{
								foreach(Node SkipNode in TargetNodes.Where(x => x.RequiredTokens.Contains(MissingToken) && SkipNodes.Add(x)))
								{
									Log("    {0}", SkipNode);
								}
							}
						}

						// Write a list of everything left over
						if(SkipNodes.Count > 0)
						{
							TargetNodes.ExceptWith(SkipNodes);
							Log("Remaining target nodes:");
							foreach(Node TargetNode in TargetNodes)
							{
								Log("    {0}", TargetNode);
							}
							if(TargetNodes.Count == 0)
							{
								Log("    None.");
							}
						}
					}
					else
					{
						foreach(KeyValuePair<FileReference, string> Pair in MissingTokens)
						{
							List<Node> SkipNodes = TargetNodes.Where(x => x.RequiredTokens.Contains(Pair.Key)).ToList();
							LogError("Cannot run {0} due to previous build: {1}", String.Join(", ", SkipNodes), Pair.Value);
						}
						foreach(FileReference CreatedToken in CreatedTokens)
						{
							CreatedToken.Delete();
						}
						return ExitCode.Error_Unknown;
					}
				}
			}

			// Cull the graph to include only those nodes
			Graph.Select(TargetNodes);

			// Collapse any triggers in the graph which are marked to be skipped
			HashSet<ManualTrigger> SkipTriggers = new HashSet<ManualTrigger>();
			if(bSkipTriggers)
			{
				SkipTriggers.UnionWith(Graph.NameToTrigger.Values);
			}
			else
			{
				foreach(string SkipTriggerName in SkipTriggerNames)
				{
					ManualTrigger SkipTrigger;
					if(!Graph.NameToTrigger.TryGetValue(TriggerName, out SkipTrigger))
					{
						LogError("Couldn't find trigger '{0}'", TriggerName);
						return ExitCode.Error_Unknown;
					}
					SkipTriggers.Add(SkipTrigger);
				}
			}
			Graph.SkipTriggers(SkipTriggers);

			// If a report for the whole build was requested, insert it into the graph
			if (ReportName != null)
			{
				Report NewReport = new Report(ReportName);
				NewReport.Nodes.UnionWith(Graph.Agents.SelectMany(x => x.Nodes));
				Graph.NameToReport.Add(ReportName, NewReport);
			}

			// Write out the preprocessed script
			if (PreprocessedFileName != null)
			{
				Graph.Write(new FileReference(PreprocessedFileName), (SchemaFileName != null)? new FileReference(SchemaFileName) : null);
			}

			// Find the triggers which we are explicitly running.
			ManualTrigger Trigger = null;
			if(TriggerName != null && !Graph.NameToTrigger.TryGetValue(TriggerName, out Trigger))
				{
					LogError("Couldn't find trigger '{0}'", TriggerName);
					return ExitCode.Error_Unknown;
				}

			// If we're just building a single node, find it 
			Node SingleNode = null;
			if(SingleNodeName != null && !Graph.NameToNode.TryGetValue(SingleNodeName, out SingleNode))
			{
				LogError("Node '{0}' is not in the trimmed graph", SingleNodeName);
				return ExitCode.Error_Unknown;
			}

			// If we just want to show the contents of the graph, do so and exit.
			if(bListOnly)
			{ 
				HashSet<Node> CompletedNodes = FindCompletedNodes(Graph, Storage);
				Graph.Print(CompletedNodes, PrintOptions);
				return ExitCode.Success;
			}

			// Print out all the diagnostic messages which still apply, unless we're running a step as part of a build system or just listing the contents of the file. 
			if(SingleNode == null)
			{
				IEnumerable<GraphDiagnostic> Diagnostics = Graph.Diagnostics.Where(x => x.EnclosingTrigger == Trigger);
				foreach(GraphDiagnostic Diagnostic in Diagnostics)
				{
					if(Diagnostic.EventType == LogEventType.Warning)
					{
						CommandUtils.LogWarning(Diagnostic.Message);
					}
					else
					{
						CommandUtils.LogError(Diagnostic.Message);
					}
				}
				if(Diagnostics.Any(x => x.EventType == LogEventType.Error))
				{
					return ExitCode.Error_Unknown;
				}
			}

			// Execute the command
			if(ExportFileName != null)
			{
				HashSet<Node> CompletedNodes = FindCompletedNodes(Graph, Storage);
				Graph.Print(CompletedNodes, PrintOptions);
				Graph.Export(new FileReference(ExportFileName), Trigger, CompletedNodes);
			}
			else if(SingleNode != null)
			{
				if(!BuildNode(new JobContext(this), Graph, SingleNode, Storage, bWithBanner: true))
				{
					return ExitCode.Error_Unknown;
				}
			}
			else
			{
				if(!BuildAllNodes(new JobContext(this), Graph, Storage))
				{
					return ExitCode.Error_Unknown;
				}
			}
			return ExitCode.Success;
		}