public long GetNextAvailableLong(List<long> values, bool returnZero) { if (values == null || !values.Any()) { if (returnZero) { return 0; } else { return 1; } } HashSet<long> hashSetValues = new HashSet<long>(values); long x = hashSetValues.Min(); while (hashSetValues.Any(m => m == x)) { x++; if (x == 0 && !returnZero) { x++; } } return x; }
static void Main(string[] args) { int N = int.Parse(Console.ReadLine()); HashSet<House> Houses = new HashSet<House>(); long amountOfCable = 0; for (int i = 0; i < N; i++) { string[] inputs = Console.ReadLine().Split(' '); Houses.Add(new House { X = int.Parse(inputs[0]), Y = int.Parse(inputs[1]) }); } //Core: Calculate Average House Y index double Avg = Houses.Sum(x => x.Y) / N; //Core:find the house closest to the Avg Y and use its Y coordinate int closest = Houses.OrderBy(x => Math.Abs(x.Y - Avg)).First().Y; //lay the mainline amountOfCable += (Houses.Max(x => x.X) - Houses.Min(x => x.X)); //per other House calculate distance from location to mainline foreach (var i in Houses) { amountOfCable += i.Y > closest ? i.Y - closest : closest - i.Y; } // Write an action using Console.WriteLine() // To debug: Console.Error.WriteLine("Debug messages..."); Console.WriteLine(amountOfCable); }
public void MoveLanesRight(int fromLane) { int nextGap = _gaps?.Min(lane => lane > fromLane ? lane : null) ?? int.MaxValue; if (_revisionLane >= fromLane && _revisionLane < nextGap) { ++_revisionLane; } Validates.NotNull(_segmentLanes); RevisionGraphSegment[] segmentsToBeMoved = _segmentLanes.Where(keyValue => keyValue.Value >= fromLane && keyValue.Value < nextGap) .Select(keyValue => keyValue.Key) .ToArray(); if (!segmentsToBeMoved.Any()) { return; } _gaps ??= new(); _gaps.Add(fromLane); if (nextGap < int.MaxValue) { _gaps.Remove(nextGap); } else { ++_laneCount; } foreach (RevisionGraphSegment segment in segmentsToBeMoved) { ++_segmentLanes[segment]; } }
static void Main() { var collection = new HashSet<double> { 5.2, 8, -3.14, 0, 55 }; Console.WriteLine(collection.Sum()); Console.WriteLine(collection.Product()); Console.WriteLine(collection.Min()); Console.WriteLine(collection.Max()); Console.WriteLine(collection.Average()); }
public void FullRangeHit(Int32 maximum) { var rolls = new HashSet<Int32>(); while (LoopShouldStillRun() && rolls.Count < maximum) rolls.Add(Dice.Roll().d(maximum)); Assert.That(rolls.Min(), Is.EqualTo(1)); Assert.That(rolls.Max(), Is.EqualTo(maximum)); Assert.That(rolls.Count, Is.EqualTo(maximum)); Assert.Pass("Iterations: {0}", iterations); }
public HotnessDetector(HashSet<double> allLatitudes, HashSet<double> allLongitudes) { // Get the entire list of waypoints within a single hunt // (or at least every latitude and longitude) // and determine the bounds of the playfield. // The playfield width is determined from the eastmost latitude // of the waypoints and the westmost latitude of the waypoints. // The playfield height is determined from the northernmost longitude // of the waypoints and the southernmost longitude of the waypoints. playfield = new GeoArea(allLongitudes.Min(), allLongitudes.Max(), allLatitudes.Max(), allLatitudes.Min()); }
/// <summary> /// Generic path finding. Works on any map type. /// </summary> /// <returns>A list of paths to take to move from the start node to the goal node using the minimum number of paths, or null if no such list exists.</returns> public static List<Path> Find(IGameMap map, IMapNode start, IMapNode goal) { if (start == goal) return new List<Path>(); Dictionary<IMapNode, int> distance = new Dictionary<IMapNode, int>(); Dictionary<IMapNode, Path> previous = new Dictionary<IMapNode, Path>(); ICollection<IMapNode> unvisited = new HashSet<IMapNode>(); foreach (IMapNode node in map.Nodes) { distance.Add(node, Int32.MaxValue); previous.Add(node, null); unvisited.Add(node); } distance[start] = 0; while (unvisited.Count > 0) { IMapNode currentNode = unvisited.First(x => distance[x] == unvisited.Min(y => distance[y])); unvisited.Remove(currentNode); if (currentNode == goal) break; foreach (Path p in map.GetPathsFrom(currentNode)) { IMapNode neighbor = p.To; int alternateDistance = distance[currentNode] + 1; if (alternateDistance < distance[neighbor]) { distance[neighbor] = alternateDistance; previous[neighbor] = p; } } } List<Path> path = new List<Path>(); Path prevPath = previous[goal]; do { path.Insert(0, prevPath); prevPath = previous[prevPath.From]; } while (prevPath != null); return path; }
public void FindSmallestMemberOfChain() { var chainLength = GetChainLength(402170); chainLength.Should().Be(65); var chain = new HashSet<long>(); long startingNumber = 402170; long currentNumber = startingNumber; while (!chain.Contains(currentNumber)) { chain.Add(currentNumber); var factors = FactorHelper.GetProperFactorsOf(currentNumber); var sum = factors.Sum(); currentNumber = sum; } var smallest = chain.Min(); Console.WriteLine("Smallest member of longest chain: {0}", smallest); }
protected IEnumerable <int> EnumerateLevels(int start = 99, int end = 0) { var decrementing = start > end; var increment = decrementing ? -1 : 1; var knownLevelsPopulated = KnownLevels.Any(); var maxKnown = knownLevelsPopulated ? KnownLevels.Max() : 0; var minKnown = knownLevelsPopulated ? KnownLevels.Min() : 0; for (var i = start; decrementing?i >= end : i <= end; i += increment) { if (knownLevelsPopulated && (i >= minKnown || i <= maxKnown)) { if (KnownLevels.Contains(i)) { yield return(i); } continue; } yield return(i); } }
public void Draw(IPixelSet pixelSet, IDrawingArea drawingArea) { if (!afterClick) { return; } if (allPoints == null) { this.pixelSet = pixelSet; allPoints = new HashSet <KeyValuePair <int, int> >(new Comparer()); drawingPoints = new HashSet <KeyValuePair <int, int> >(new Comparer()); this.drawingArea = drawingArea; startFill(); minY = allPoints.Min(x => x.Value); maxY = allPoints.Max(x => x.Value); ThreadPool.QueueUserWorkItem(fedos); } lock (drawingPoints) foreach (var x in drawingPoints) { pixelSet.FillCell(x.Key, x.Value); } }
private static void GetMaxAndSecondMaxUsingHashing(int[] arr) { HashSet <int> trackMax = new HashSet <int>(); int max1 = -1, max2 = -1, size = arr.Length; for (int i = 0; i < size; i++) { trackMax.Add(arr[i]); if (trackMax.Count > 2) { trackMax.Remove(trackMax.Min()); } } if (trackMax.Count == 2) { Console.WriteLine("The max two numbers are :{0}, {1}", trackMax.Max(), trackMax.Min()); } else { Console.WriteLine("The max two numbers are :{0}, {1}", trackMax.Max(), -1); } }
public override __long__[] GetDistances(int start) { var dist = GetInitializedDistances(start); var vSet = new HashSet <int>(Enumerable.Range(0, V)); while (vSet.Count > 0) { var min = vSet.Min(x => dist[x]); var from = vSet.First(x => dist[x] == min); vSet.Remove(from); if (dist[from] == Infinity) { break; } foreach (var edge in Edges[from]) { dist[edge.To] = Math.Min(dist[edge.To], dist[from] + edge.Cost); } } return(dist); }
// Проверка факта, что нумерация вершин начинается с 0 и идет по порядку. private static int CountVerteces(List <Edge> edges) { HashSet <int> uniqueLabel = new HashSet <int>(); foreach (var edge in edges) { uniqueLabel.Add(edge.V1); uniqueLabel.Add(edge.V2); } int minValue = uniqueLabel.Min(); if (minValue != 0) { throw new FormatException("Индексация вершин должна начинаться с нуля"); } int n = uniqueLabel.Max() + 1; if (n != uniqueLabel.Count) { throw new FormatException("Индексация вершин должна идти по порядку"); } return(n); }
public static int Solution(int[] A) { int totalSum = 0; var results = new HashSet <int>(); foreach (var item in A) { totalSum += item; } int prev = A[0]; int next = totalSum - prev; for (int i = 1; i < A.Length; i++) { results.Add(ReturnModulus(prev, next)); prev += A[i]; next = totalSum - prev; } return(results.Min()); }
// �������� �����, ��� ��������� ������ ���������� � 0 � ���� �� �������. private static int CountVerteces(List <Edge> edges) { HashSet <int> uniqueLabel = new HashSet <int>(); foreach (var edge in edges) { uniqueLabel.Add(edge.V1); uniqueLabel.Add(edge.V2); } int minValue = uniqueLabel.Min(); if (minValue != 0) { throw new FormatException("���������� ������ ������ ���������� � ����"); } int n = uniqueLabel.Max() + 1; if (n != uniqueLabel.Count) { throw new FormatException("���������� ������ ������ ���� �� �������"); } return(n); }
public static HashSet <short> NewSetWithMinimum(this HashSet <short> set, short value) { var minimum = set.Min(); if (value == minimum) { return(set); } set.Add(value); if (value < minimum) { var rangeToAdd = Enumerable.Range(value, minimum - value).Select(i => (short)i); set.UnionWith(rangeToAdd); } else { var rangeToSubtract = Enumerable.Range(minimum, value - minimum).Select(i => (short)i); set.ExceptWith(rangeToSubtract); } return(set); }
public IList <string> FindAllConcatenatedWordsInADict(string[] words) { var result = new List <string>(); var wordsSet = new HashSet <string>(words.Where(w => w != string.Empty)); if (wordsSet.Count == 0) { return(result); } minWordLen = wordsSet.Min(w => w.Length); maxWordLen = wordsSet.Max(w => w.Length); foreach (var w in wordsSet) { if (CheckWord(w, wordsSet)) { result.Add(w); } } return(result); }
public JObject CreatePage(Uri indexUri, List <JObject> packageDetails) { var versionSet = new HashSet <NuGetVersion>(packageDetails.Select(GetPackageVersion)); var lower = versionSet.Min().ToIdentityString().ToLowerInvariant(); var upper = versionSet.Max().ToIdentityString().ToLowerInvariant(); var json = JsonUtility.Create(indexUri, $"page/{lower}/{upper}", "catalog:CatalogPage"); json.Add("commitId", _context.CommitId.ToString().ToLowerInvariant()); json.Add("commitTimeStamp", DateTimeOffset.UtcNow.GetDateString()); json.Add("count", packageDetails.Count); json.Add("parent", indexUri.AbsoluteUri); json.Add("lower", lower); json.Add("upper", upper); // Order and add all items var itemsArray = new JArray(packageDetails.OrderBy(GetPackageVersion)); json.Add("items", itemsArray); return(JsonLDTokenComparer.Format(json, recurse: false)); }
private double TwoForThree(double currentSum, string[] items, HashSet <string> availableForDiscount, Dictionary <string, double> prices) { var validForDiscount = new HashSet <double>(); int counter = 0; for (int i = 0; i < items.Length; i++) { if (availableForDiscount.Contains(items[i])) { validForDiscount.Add(prices[items[i]]); counter++; } if (counter == 3) { currentSum = currentSum - validForDiscount.Min(); validForDiscount.Clear(); counter = 0; } } return(currentSum); }
/* * Given two int values, return whichever value is larger. * However if the two values have the same remainder when divided by 5, * then the return the smaller value. However, in all cases, if the two * values are the same, return 0. * * maxMod5(25, 15) → 15 * maxMod5(6, 2) → 6 * maxMod5(3, 3) → 0 */ public static int maxMod5(params int[] values) { HashSet <int> vals = new HashSet <int>(); HashSet <int> mods = new HashSet <int>(); foreach (int val in values) { vals.Add(val); mods.Add(val % 5); } if (vals.Count < 2) { return(0); } else if (mods.Count < 2) { return(vals.Min()); } else { return(vals.Max()); } }
public int GetId() { return(cells.Min(c => c.Id)); }
public void HashSetExtensions_Min_ThrowsExceptionIfHashSetIsEmpty() { var set = new HashSet<Int32>(); Assert.That(() => set.Min(), Throws.TypeOf<InvalidOperationException>()); }
// Returns a stack of nodes representing the path from start to goal. // Popping elements off the stack yields the correct sequence of moves // in order. public Stack<MazeNode> AStarSearch(MazeNode start, MazeNode goal) { HashSet<MazeNode> closed = new HashSet<MazeNode>(); HashSet<MazeNode> open = new HashSet<MazeNode>(); MazeNode current; ArrayList children; int GScoreEstimate; start.g = 0; start.h = start.manhattanDistance(goal); start.f = start.g + start.h; start.a_star_parent = start; open.Add(start); //While there are adjacent, unexplored nodes to search while (open.Count > 0) { current = open.Min(); //If we've reached our goal if (current == goal) { //Retrieve the path we took via a stack Stack<MazeNode> path_to_goal = new Stack<MazeNode>(); while (current.a_star_parent != current) { path_to_goal.Push(current); current = current.a_star_parent; } path_to_goal.Push(current); return path_to_goal; } //Else continue our search open.Remove(current); closed.Add(current); children = current.getAdjacentEdges(); foreach (MazeNode child in children) { // If we've visited this node already, skip it. if (closed.Contains(child)) { continue; } // g is computed as the cost it took us to get here, plus the distance between the // current node and the child we're considering. GScoreEstimate = (int)(current.g) + current.manhattanDistance(child); // If we haven't considered this node already, or our current estimate is more optimistic // than our prior estimation if (!open.Contains(child) || GScoreEstimate < child.g) { child.g = GScoreEstimate; child.f = child.g + child.manhattanDistance(goal); if (!open.Contains(child)) { open.Add(child); } child.a_star_parent = current; } } closed.Add(current); } //Search failed, no more nodes to find on open list return null; }
/// <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="selectedNotes"> The note models in current selection </param> /// <param name="currentWorkspace"> The workspace where</param> /// <param name="args"></param> internal CustomNodeWorkspaceModel Collapse( IEnumerable <NodeModel> selectedNodes, IEnumerable <NoteModel> selectedNotes, WorkspaceModel currentWorkspace, 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; Debug.WriteLine("Current workspace has {0} nodes and {1} connectors", currentWorkspace.Nodes.Count(), currentWorkspace.Connectors.Count()); 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.InPorts.Count) .Where(index => node.InPorts[index].Connectors.Any()) .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.OutPorts.Count) .Where(index => node.OutPorts[index].Connectors.Any()) .SelectMany( data => node.OutputNodes[data].Where( output => !selectedNodeSet.Contains(output.Item2)) .Select(output => Tuple.Create(node, data, output))))); #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 newNotes = new List <NoteModel>(); var newAnnotations = new List <AnnotationModel>(); // Step 4: move all nodes and notes 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.RemoveAndDisposeNode(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(); // shift nodes node.X = node.X - leftShift; node.Y = node.Y - topMost; newNodes.Add(node); } foreach (var note in selectedNotes) { undoRecorder.RecordDeletionForUndo(note); currentWorkspace.RemoveNote(note); note.GUID = Guid.NewGuid(); note.X = note.X - leftShift; note.Y = note.Y - topMost; newNotes.Add(note); } //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.Nodes = group.DeletedModelBases; newAnnotations.Add(group); } // Now all selected nodes already moved to custom workspace, // clear the selection. DynamoSelection.Instance.ClearSelection(); 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.InPorts[inputReceiverData].Name, 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 EFunction) { var func = inputReceiverNode as EFunction; 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 == Engine.FunctionType.InstanceMethod || funcDesc.Type == Engine.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.SetNameFromNodeNameAttribute(); node.Y = inputIndex * (50 + node.Height); uniqueInputSenders[key] = node; newNodes.Add(node); } ConnectorModel.Make(node, 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; outportList.Add(Tuple.Create(outputSenderNode, outputSenderData)); //Create Symbol Node var node = new Output { Symbol = outputSenderNode.OutPorts[outputSenderData].Name, X = rightMost + 75 - leftShift }; node.Y = i * (50 + node.Height); node.SetNameFromNodeNameAttribute(); 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.OutPorts.Count) .Where(index => !node.OutPorts[index].IsConnected) .Select(port => new { node, port })).Distinct()) { //Create Symbol Node var node = new Output { Symbol = hanging.node.OutPorts[hanging.port].Name, X = rightMost + 75 - leftShift }; node.Y = i * (50 + node.Height); node.SetNameFromNodeNameAttribute(); newNodes.Add(node); ConnectorModel.Make(hanging.node, node, hanging.port, 0); i++; } } #endregion var newId = Guid.NewGuid(); newWorkspace = new CustomNodeWorkspaceModel( nodeFactory, newNodes, newNotes, newAnnotations, Enumerable.Empty <PresetModel>(), currentWorkspace.ElementResolver, new WorkspaceInfo() { X = 0, Y = 0, Name = args.Name, Category = args.Category, Description = args.Description, ID = newId.ToString(), FileName = string.Empty, IsVisibleInDynamoLibrary = true }); newWorkspace.HasUnsavedChanges = true; RegisterCustomNodeWorkspace(newWorkspace); Debug.WriteLine("Collapsed workspace has {0} nodes and {1} connectors", newWorkspace.Nodes.Count(), newWorkspace.Connectors.Count()); var collapsedNode = CreateCustomNodeInstance(newId); collapsedNode.X = avgX; collapsedNode.Y = avgY; currentWorkspace.AddAndRegisterNode(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, nodeTuple.@from, 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); }
public void HashSetExtensions_Min_ThrowsExceptionIfHashSetIsEmpty() { var set = new HashSet<Int32>(); set.Min(); }
List <ILNode> ConvertToAst(List <ByteCode> body, HashSet <ExceptionHandler> ehs) { List <ILNode> ast = new List <ILNode>(); while (ehs.Any()) { ILTryCatchBlock tryCatchBlock = new ILTryCatchBlock(); // Find the first and widest scope int tryStart = ehs.Min(eh => eh.TryStart.Offset); int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset); var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList(); // Cut all instructions up to the try block { int tryStartIdx; for (tryStartIdx = 0; body[tryStartIdx].Offset != tryStart; tryStartIdx++) { ; } ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx))); } // Cut the try block { HashSet <ExceptionHandler> nestedEHs = new HashSet <ExceptionHandler>(ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd))); ehs.ExceptWith(nestedEHs); int tryEndIdx; for (tryEndIdx = 0; tryEndIdx < body.Count && body[tryEndIdx].Offset != tryEnd; tryEndIdx++) { ; } tryCatchBlock.TryBlock = new ILBlock(ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs)); } // Cut all handlers tryCatchBlock.CatchBlocks = new List <ILTryCatchBlock.CatchBlock>(); foreach (ExceptionHandler eh in handlers) { int startIndex; for (startIndex = 0; body[startIndex].Offset != eh.HandlerStart.Offset; startIndex++) { ; } int endInclusiveIndex; if (eh.HandlerEnd == null) { endInclusiveIndex = body.Count - 1; } // Note that the end(exclusive) instruction may not necessarly be in our body else { for (endInclusiveIndex = 0; body[endInclusiveIndex].Next.Offset != eh.HandlerEnd.Offset; endInclusiveIndex++) { ; } } int count = 1 + endInclusiveIndex - startIndex; HashSet <ExceptionHandler> nestedEHs = new HashSet <ExceptionHandler>(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < eh.HandlerEnd.Offset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= eh.HandlerEnd.Offset))); ehs.ExceptWith(nestedEHs); List <ILNode> handlerAst = ConvertToAst(body.CutRange(startIndex, count), nestedEHs); if (eh.HandlerType == ExceptionHandlerType.Catch) { ILTryCatchBlock.CatchBlock catchBlock = new ILTryCatchBlock.CatchBlock() { ExceptionType = eh.CatchType, Body = handlerAst }; // Handle the automatically pushed exception on the stack ByteCode ldexception = ldexceptions[eh]; if (ldexception.StoreTo.Count == 0) { throw new Exception("Exception should be consumed by something"); } else if (ldexception.StoreTo.Count == 1) { ILExpression first = catchBlock.Body[0] as ILExpression; if (first != null && first.Code == ILCode.Pop && first.Arguments[0].Code == ILCode.Ldloc && first.Arguments[0].Operand == ldexception.StoreTo[0]) { // The exception is just poped - optimize it all away; catchBlock.ExceptionVariable = null; catchBlock.Body.RemoveAt(0); } else { catchBlock.ExceptionVariable = ldexception.StoreTo[0]; } } else { ILVariable exTemp = new ILVariable() { Name = "ex_" + eh.HandlerStart.Offset.ToString("X2"), IsGenerated = true }; catchBlock.ExceptionVariable = exTemp; foreach (ILVariable storeTo in ldexception.StoreTo) { catchBlock.Body.Insert(0, new ILExpression(ILCode.Stloc, storeTo, new ILExpression(ILCode.Ldloc, exTemp))); } } tryCatchBlock.CatchBlocks.Add(catchBlock); } else if (eh.HandlerType == ExceptionHandlerType.Finally) { tryCatchBlock.FinallyBlock = new ILBlock(handlerAst); } else if (eh.HandlerType == ExceptionHandlerType.Fault) { tryCatchBlock.FaultBlock = new ILBlock(handlerAst); } else { // TODO: ExceptionHandlerType.Filter } } ehs.ExceptWith(handlers); ast.Add(tryCatchBlock); } // Add whatever is left ast.AddRange(ConvertToAst(body)); return(ast); }
static void Main(string[] args) { int offset = 100; StreamReader sr = new StreamReader("input12.txt"); List <Recipe> notes = new List <Recipe>(); string initial = sr.ReadLine(); sr.ReadLine(); //remove empty initial = initial.Substring(initial.IndexOf(':') + 2); for (int i = 0; i < initial.Length; i++) { if (initial[i] == '#') { pots.Add(i + offset); } } while (sr.Peek() != -1) { Recipe tmp = new Recipe(); tmp.mostLeft = sr.Read() == '#' ? true : false; tmp.left = sr.Read() == '#' ? true : false; tmp.current = sr.Read() == '#' ? true : false; tmp.right = sr.Read() == '#' ? true : false; tmp.mostRight = sr.Read() == '#' ? true : false; sr.Read(); sr.Read(); sr.Read(); sr.Read(); //" => " tmp.result = sr.Read() == '#' ? true : false; sr.Read(); //\n notes.Add(tmp); } //PART1 for (int i = 0; i < 20; i++) { HashSet <long> nextGenPots = new HashSet <long>(); for (int j = 2; j < 298; j++) { Recipe match = new Recipe(pVal(j - 2), pVal(j - 1), pVal(j), pVal(j + 1), pVal(j + 2), true); if (notes.Contains(match)) { nextGenPots.Add(j); } } pots = new HashSet <long>(nextGenPots); } int result = 0; foreach (int pot in pots) { result += pot - offset; } Console.WriteLine(result); //PART1 //PART2 pots = new HashSet <long>(); for (int i = 0; i < initial.Length; i++) { if (initial[i] == '#') { pots.Add(i + offset); } } List <List <int> > set = new List <List <int> >(); //every observed distribution List <int> movement = new List <int>(); //how much first plant moved comparing to previous generation long last = pots.First(); int eachMove = 0; int move = 0; long x; //need to remember when break occurs for (x = 0; x < 50000000000; x++) //should break much faster - if not, full simulation is performed(VERY SLOW) { HashSet <long> nextGenPots = new HashSet <long>(); long min = pots.Min() - 3; //minimise search range long max = pots.Max() + 3; //minimise search range List <int> currentSet = new List <int>(); bool first = false; int diff = 0; for (long j = min; j < max; j++) { Recipe match = new Recipe(pVal(j - 2), pVal(j - 1), pVal(j), pVal(j + 1), pVal(j + 2), true); if (notes.Contains(match)) { nextGenPots.Add(j); //this generation if (!first) //calculate relative difference between each plant { currentSet.Add(0); first = true; } else { currentSet.Add(diff); diff = 0; } } diff++; } pots = new HashSet <long>(nextGenPots); //update pots bool breakFor = false; foreach (List <int> s in set) { if (s.SequenceEqual(currentSet)) //ordered comparison { int lastMatch = set.IndexOf(s); move = (int)(x - lastMatch); //how many generations before the same distribution for (int k = lastMatch; k < x; k++) { eachMove += movement[k]; //how much plants moved } breakFor = true; } } if (breakFor) { break; } set.Add(currentSet); //for pattern finding movement.Add((int)(pots.First() - last)); //calcualte movement last = pots.First(); //assign new last } long result2 = 0; long diffr = (50000000000 - x - 1) * eachMove; //assuming move == 1 foreach (long pot in pots) { result2 += (pot + diffr) - offset; } Console.WriteLine(result2); //PART2 }
List<ILNode> ConvertToAst(List<ByteCode> body, HashSet<ExceptionHandler> ehs) { List<ILNode> ast = new List<ILNode>(); while (ehs.Any()) { ILTryCatchBlock tryCatchBlock = new ILTryCatchBlock(); // Find the first and widest scope int tryStart = ehs.Min(eh => eh.TryStart.Offset); int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset); var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList(); // Cut all instructions up to the try block { int tryStartIdx; for (tryStartIdx = 0; body[tryStartIdx].Offset != tryStart; tryStartIdx++); ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx))); } // Cut the try block { HashSet<ExceptionHandler> nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd))); ehs.ExceptWith(nestedEHs); int tryEndIdx; for (tryEndIdx = 0; tryEndIdx < body.Count && body[tryEndIdx].Offset != tryEnd; tryEndIdx++); tryCatchBlock.TryBlock = new ILBlock(ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs)); } // Cut all handlers tryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>(); foreach(ExceptionHandler eh in handlers) { int startIndex; for (startIndex = 0; body[startIndex].Offset != eh.HandlerStart.Offset; startIndex++); int endInclusiveIndex; // Note that the end(exclusiove) instruction may not necessarly be in our body for (endInclusiveIndex = 0; body[endInclusiveIndex].Next.Offset != eh.HandlerEnd.Offset; endInclusiveIndex++); int count = 1 + endInclusiveIndex - startIndex; HashSet<ExceptionHandler> nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < eh.HandlerEnd.Offset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= eh.HandlerEnd.Offset))); ehs.ExceptWith(nestedEHs); List<ILNode> handlerAst = ConvertToAst(body.CutRange(startIndex, count), nestedEHs); if (eh.HandlerType == ExceptionHandlerType.Catch) { tryCatchBlock.CatchBlocks.Add(new ILTryCatchBlock.CatchBlock() { ExceptionType = eh.CatchType, Body = handlerAst }); } else if (eh.HandlerType == ExceptionHandlerType.Finally) { tryCatchBlock.FinallyBlock = new ILBlock(handlerAst); } else { // TODO } } ehs.ExceptWith(handlers); ast.Add(tryCatchBlock); } // Add whatever is left ast.AddRange(ConvertToAst(body)); return ast; }
List <ILNode> ConvertToAst(List <ByteCode> body, HashSet <ExceptionHandler> ehs) { List <ILNode> ast = new List <ILNode>(); while (ehs.Any()) { ILTryCatchBlock tryCatchBlock = new ILTryCatchBlock(); // Find the first and widest scope int tryStart = ehs.Min(eh => eh.TryStart.Offset); int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset); var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).OrderBy(eh => eh.TryStart.Offset).ToList(); // Remember that any part of the body migt have been removed due to unreachability // Cut all instructions up to the try block { int tryStartIdx = 0; while (tryStartIdx < body.Count && body[tryStartIdx].Offset < tryStart) { tryStartIdx++; } ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx))); } // Cut the try block { HashSet <ExceptionHandler> nestedEHs = new HashSet <ExceptionHandler>(ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd))); ehs.ExceptWith(nestedEHs); int tryEndIdx = 0; while (tryEndIdx < body.Count && body[tryEndIdx].Offset < tryEnd) { tryEndIdx++; } tryCatchBlock.TryBlock = new ILBlock(ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs)); } // Cut all handlers tryCatchBlock.CatchBlocks = new List <ILTryCatchBlock.CatchBlock>(); foreach (ExceptionHandler eh in handlers) { int handlerEndOffset = eh.HandlerEnd == null ? methodDef.Body.CodeSize : eh.HandlerEnd.Offset; int startIdx = 0; while (startIdx < body.Count && body[startIdx].Offset < eh.HandlerStart.Offset) { startIdx++; } int endIdx = 0; while (endIdx < body.Count && body[endIdx].Offset < handlerEndOffset) { endIdx++; } HashSet <ExceptionHandler> nestedEHs = new HashSet <ExceptionHandler>(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < handlerEndOffset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= handlerEndOffset))); ehs.ExceptWith(nestedEHs); List <ILNode> handlerAst = ConvertToAst(body.CutRange(startIdx, endIdx - startIdx), nestedEHs); if (eh.HandlerType == ExceptionHandlerType.Catch) { ILTryCatchBlock.CatchBlock catchBlock = new ILTryCatchBlock.CatchBlock() { ExceptionType = eh.CatchType, Body = handlerAst }; // Handle the automatically pushed exception on the stack ByteCode ldexception = ldexceptions[eh]; if (ldexception.StoreTo == null || ldexception.StoreTo.Count == 0) { // Exception is not used catchBlock.ExceptionVariable = null; } else if (ldexception.StoreTo.Count == 1) { ILExpression first = catchBlock.Body[0] as ILExpression; if (first != null && first.Code == ILCode.Pop && first.Arguments[0].Code == ILCode.Ldloc && first.Arguments[0].Operand == ldexception.StoreTo[0]) { // The exception is just poped - optimize it all away; if (context.Settings.AlwaysGenerateExceptionVariableForCatchBlocks) { catchBlock.ExceptionVariable = new ILVariable() { Name = "ex_" + eh.HandlerStart.Offset.ToString("X2"), IsGenerated = true } } ; else { catchBlock.ExceptionVariable = null; } catchBlock.Body.RemoveAt(0); } else { catchBlock.ExceptionVariable = ldexception.StoreTo[0]; } } else { ILVariable exTemp = new ILVariable() { Name = "ex_" + eh.HandlerStart.Offset.ToString("X2"), IsGenerated = true }; catchBlock.ExceptionVariable = exTemp; foreach (ILVariable storeTo in ldexception.StoreTo) { catchBlock.Body.Insert(0, new ILExpression(ILCode.Stloc, storeTo, new ILExpression(ILCode.Ldloc, exTemp))); } } tryCatchBlock.CatchBlocks.Add(catchBlock); } else if (eh.HandlerType == ExceptionHandlerType.Finally) { tryCatchBlock.FinallyBlock = new ILBlock(handlerAst); } else if (eh.HandlerType == ExceptionHandlerType.Fault) { tryCatchBlock.FaultBlock = new ILBlock(handlerAst); } else { // TODO: ExceptionHandlerType.Filter } } ehs.ExceptWith(handlers); ast.Add(tryCatchBlock); } // Add whatever is left ast.AddRange(ConvertToAst(body)); return(ast); }
/// <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; }
public void HashSetExtensions_Min_ReturnsMinValue() { var set = new HashSet<Int32>() { 4, 5, 6, 99, 10, 1, 12, 45 }; var result = set.Min(); TheResultingValue(result).ShouldBe(1); }
private void Initialize(string[] lines) { var clayLocations = new List <(HashSet <int> X, HashSet <int> Y)>(); foreach (var line in lines) { var items = line.Split(", "); HashSet <int> x = null; HashSet <int> y = null; foreach (var item in items) { var parts = item.Split('='); if (parts[0] == "x") { x = GetRange(parts[1]); } else { y = GetRange(parts[1]); } } clayLocations.Add((x, y)); _maxX = Math.Max(_maxX, x.Max()); _minY = Math.Min(_minY, y.Min()); _maxY = Math.Max(_maxY, y.Max()); } _maxX++; _materials = new char[_maxX + 1, _maxY + 1]; for (int x = 0; x <= _maxX; x++) { for (int y = 0; y <= _maxY; y++) { _materials[x, y] = '.'; } } _materials[500, 0] = '+'; foreach (var location in clayLocations) { foreach (int x in location.X) { foreach (int y in location.Y) { _materials[x, y] = '#'; } } } HashSet <int> GetRange(string part) { var limits = part.Split(".."); int first = int.Parse(limits[0]); int last = limits.Length == 1 ? first : int.Parse(limits[1]); return(new HashSet <int>(Enumerable.Range(first, last - first + 1))); } _fallPoints.Add(new Point(500, 0)); }
public static IList<RaveDetails> GetRaveDetailsFromEventIDs(IEnumerable<Int64> eventIds) { _fb.AccessToken = _GenericAccessToken; string fields = "eid, name, pic_square, start_time, end_time, is_date_only, creator, update_time, location, venue"; string eidList = string.Join(",", eventIds.ToArray()); dynamic fqlResult = _fb.Get("fql", new { q = String.Format("SELECT {0} FROM event WHERE eid IN ({1})", fields, eidList) }); JsonArray fqlEventResults = fqlResult.data; IList<RaveDetails> eventResults = new List<RaveDetails>(); HashSet<Venue> venueResults = new HashSet<Venue>(); HashSet<Rave> raveResults = new HashSet<Rave>(); foreach (dynamic fqlEvent in fqlEventResults) { Int64? creatorId = fqlEvent.creator ?? 0; Int64? eventId = fqlEvent.eid; Int64? venueId = 0; if (fqlEvent.venue.Count > 0) { dynamic jsonVenue = (JsonObject)fqlEvent.venue; venueId = jsonVenue.id ?? 0; } Rave aRave = null; Venue aVenue = null; Owner aOwner = null; if (eventId != null) { // Get the owner; no chance for duplications aOwner = GetRaveOwnerFromUserID(creatorId); // Before querying for the Venue, make sure we haven't already queried it if (venueResults.Any(v => v.VenueID == venueId)) { aVenue = venueResults.First(v => v.VenueID == venueId); } else if (fqlEvent.venue.Count > 0) { aVenue = GetVenueFromJsonObject((JsonObject)fqlEvent.venue); if (aVenue == null) { // If no facebook page exists for this Venue, create a new negative ID // All negative ID's therefore show that the Venue does not exist on Facebook aVenue = new Venue(); using (RaveRadarContext _db = new RaveRadarContext()) { long dbMin = _db.Venues.Min(v => v.VenueID).GetValueOrDefault(0); long syncMin = venueResults.Min(v => v.VenueID).GetValueOrDefault(0); aVenue.VenueID = (dbMin <= syncMin ? dbMin : syncMin) - 1; aVenue.Name = fqlEvent.location ?? string.Empty; aVenue.GetLocationFromGoogle(fqlEvent.location ?? string.Empty); // If no location found, reset venue to null if (aVenue.GetLocation() == null) { aVenue = null; } } } if (aVenue != null) { venueResults.Add(aVenue); } } // Before querying for the Rave, make sure we haven't already queried it if (raveResults.Any(r => r.RaveID == eventId)) { aRave = raveResults.First(r => r.RaveID == eventId); } else { aRave = new Rave(); aRave.RaveID = eventId ?? 0; // Should never happen aRave.OwnerID = aOwner.OwnerID; if (aVenue == null) { aRave.VenueID = null; } else { aRave.VenueID = aVenue.VenueID; } aRave.Name = fqlEvent.name ?? string.Empty; aRave.PicURL = fqlEvent.pic_square ?? ConfigurationManager.AppSettings["DefaultRaveIcon"].ToString(); aRave.StartTime = ConvertFacebookDateToLocal(fqlEvent.start_time, fqlEvent.is_date_only); if (fqlEvent.end_time == null) { aRave.EndTime = null; } else { aRave.EndTime = ConvertFacebookDateToLocal(fqlEvent.end_time, fqlEvent.is_date_only); } aRave.IsDateOnly = fqlEvent.is_date_only; aRave.Location = fqlEvent.location ?? string.Empty; aRave.IsApproved = (aOwner == null ? false : aOwner.IsTrusted); aRave.SubmitterID = null; aRave.UpdateTime = DateTimeConvertor.FromUnixTime((double)fqlEvent.update_time); raveResults.Add(aRave); } } // Put all the details together to create one object eventResults.Add(new RaveDetails(aRave, aOwner, aVenue)); } return eventResults; }
public Value Min() => hashSet.Min();
/// <summary> /// Convert the given set of bytecodes to an Ast node list. /// Split exception handlers into Ast try/catch blocks. /// </summary> private List<AstNode> ConvertToAst(List<ByteCode> body, HashSet<ExceptionHandler> ehs, List<ByteCodeBlock> blockStarts, int nestingLevel, Dictionary<int, ByteCode> offset2ByteCode) { var ast = new List<AstNode>(); // Split body in blocks while (ehs.Any()) { var tryCatchBlock = new AstTryCatchBlock(null); // Find the first and widest scope var tryStart = ehs.Min(eh => eh.StartPc); var tryEnd = ehs.Where(eh => eh.StartPc == tryStart).Max(eh => eh.EndPc); var handlers = ehs.Where(eh => (eh.StartPc == tryStart) && (eh.EndPc == tryEnd)).OrderBy(eh => eh.HandlerPc).ToList(); // Remember that any part of the body migt have been removed due to unreachability // Cut all instructions up to the try block { var tryStartIdx = 0; while ((tryStartIdx < body.Count) && (body[tryStartIdx].Offset < tryStart)) { tryStartIdx++; } if (tryStartIdx > 0) { ast.AddRange(ConvertRangeToAst(body.CutRange(0, tryStartIdx))); // Make sure the block before the try block ends with an unconditional control flow AddUnconditionalBranchToNext(ast, body, 0); } } // Cut the try block { var nestedEHs = new HashSet<ExceptionHandler>( ehs.Where(eh => ((tryStart <= eh.StartPc) && (eh.EndPc < tryEnd)) || ((tryStart < eh.StartPc) && (eh.EndPc <= tryEnd)))); ehs.ExceptWith(nestedEHs); var tryEndIdx = 0; while ((tryEndIdx < body.Count) && (body[tryEndIdx].Offset < tryEnd)) { tryEndIdx++; } var converted = ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs, blockStarts, nestingLevel + 1, offset2ByteCode); tryCatchBlock.TryBlock = new AstBlock(converted.Select(x => x.SourceLocation).FirstOrDefault(), converted); // Make sure the try block ends with an unconditional control flow AddUnconditionalBranchToNext(tryCatchBlock.TryBlock.Body, body, 0); } // Cut all handlers tryCatchBlock.CatchBlocks.Clear(); foreach (var iterator in handlers) { var eh = iterator; var handler = offset2ByteCode[eh.HandlerPc]; // body.First(x => x.Offset == eh.HandlerPc); var catchType = eh.IsCatchAll ? typeSystem.Object : AsTypeReference(eh.CatchType, XTypeUsageFlags.CatchType); var catchBlock = new AstTryCatchBlock.CatchBlock(handler.SourceLocation, tryCatchBlock) { ExceptionType = catchType, Body = new List<AstNode>() }; // Create catch "body" (actually a jump to the handler) // Handle the automatically pushed exception on the stack var ldexception = ldexceptions[eh]; catchBlock.Body.Add(new AstExpression(handler.SourceLocation, AstCode.Br, handler.Label(true))); if (ldexception.StoreTo == null || ldexception.StoreTo.Count == 0) { // Exception is not used catchBlock.ExceptionVariable = null; } else if (ldexception.StoreTo.Count == 1) { /*var first = catchBlock.Body.FirstOrDefault() as AstExpression; if (first != null && first.Code == AstCode.Pop && first.Arguments[0].Code == AstCode.Ldloc && first.Arguments[0].Operand == ldexception.StoreTo[0]) { // The exception is just poped - optimize it all away; catchBlock.ExceptionVariable = new AstGeneratedVariable("ex_" + eh.HandlerPc.ToString("X2")); catchBlock.Body.RemoveAt(0); } else*/ { catchBlock.ExceptionVariable = ldexception.StoreTo[0]; } } else { var exTemp = new AstGeneratedVariable("ex_" + eh.HandlerPc.ToString("X2"), null); catchBlock.ExceptionVariable = exTemp; foreach (var storeTo in ldexception.StoreTo) { catchBlock.Body.Insert(0, new AstExpression(catchBlock.SourceLocation, AstCode.Stloc, storeTo, new AstExpression(catchBlock.SourceLocation, AstCode.Ldloc, exTemp))); } } tryCatchBlock.CatchBlocks.Add(catchBlock); } ehs.ExceptWith(handlers); ast.Add(tryCatchBlock); } // Add whatever is left ast.AddRange(ConvertRangeToAst(body)); return ast; }
private void Run(AOGraph mGraph, int start) { foreach (Node node in mGraph.Nodes) { this.costs.Add(node.Id, double.MaxValue); } this.opened.Add(mGraph.Nodes.ElementAt(start)); this.costs[start] = 0; while (opened.Count > 0) { /// current => is the best node to continue search from it's sub graph Node current = opened.Min(); opened.Remove(current); closed.Add(current); if (current.IsTerminal) { this.terminals.Add(current); Refresh(current.Parent); continue; } else { foreach (Operator op in current.Operators) { bool solveable = true; foreach (Node successor in op.Ends) { if (!successor.IsTerminal && (successor.Operators == null || successor.Operators.Count == 0)) { solveable = false; break; } } if (solveable) { foreach (Node successor in op.Ends) { successor.Parent = current; successor.Cost = current.Cost + G(current, successor); ///Here we must to override the comparator. if (!opened.Contains(successor) && !closed.Contains(successor)) { costs[successor.Id] = successor.Cost; opened.Add(successor); } } } else { Refresh(current); } } } } if (costs[start] >= double.MaxValue) { Console.WriteLine("No available paths from start = [{0:D}]", start); return; } Console.WriteLine("Best solution = " + this.costs[start]); foreach (Node node in mGraph.Nodes) { Console.WriteLine(node.Cost + ", " + costs[node.Id]); } }
List<AstNode> ConvertToAst(List<ByteCode> body, HashSet<ExceptionHandler> ehs) { var ast = new List<AstNode>(); while (ehs.Any()) { var tryCatchBlock = new AstTryCatchBlock(null); // Find the first and widest scope var tryStart = ehs.Min(eh => eh.TryStart.Offset); var tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset); var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).OrderBy(eh => eh.TryStart.Offset).ToList(); // Remember that any part of the body migt have been removed due to unreachability // Cut all instructions up to the try block { var tryStartIdx = 0; while (tryStartIdx < body.Count && body[tryStartIdx].Offset < tryStart) tryStartIdx++; ast.AddRange(ConvertToAst(CollectionExtensions.CutRange(body, 0, tryStartIdx))); } // Cut the try block { var nestedEHs = new HashSet<ExceptionHandler>( ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd))); ehs.ExceptWith(nestedEHs); var tryEndIdx = 0; while (tryEndIdx < body.Count && body[tryEndIdx].Offset < tryEnd) tryEndIdx++; var converted = ConvertToAst(CollectionExtensions.CutRange(body, 0, tryEndIdx), nestedEHs); tryCatchBlock.TryBlock = new AstBlock(converted.Select(x => x.SourceLocation).FirstOrDefault(), converted); } // Cut all handlers tryCatchBlock.CatchBlocks.Clear(); foreach (var eh in handlers) { var handlerEndOffset = eh.HandlerEnd == null ? methodDef.Body.CodeSize : eh.HandlerEnd.Offset; var startIdx = 0; while (startIdx < body.Count && body[startIdx].Offset < eh.HandlerStart.Offset) startIdx++; var endIdx = 0; while (endIdx < body.Count && body[endIdx].Offset < handlerEndOffset) endIdx++; var nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < handlerEndOffset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= handlerEndOffset))); ehs.ExceptWith(nestedEHs); var handlerAst = ConvertToAst(CollectionExtensions.CutRange(body, startIdx, endIdx - startIdx), nestedEHs); if (eh.HandlerType == ExceptionHandlerType.Catch) { var catchType = eh.CatchType.IsSystemObject() ? module.TypeSystem.Exception : XBuilder.AsTypeReference(module, eh.CatchType); var catchBlock = new AstTryCatchBlock.CatchBlock(handlerAst.Select(x => x.SourceLocation).FirstOrDefault(), tryCatchBlock) { ExceptionType = catchType, Body = handlerAst }; // Handle the automatically pushed exception on the stack var ldexception = ldexceptions[eh]; if (ldexception.StoreTo == null || ldexception.StoreTo.Count == 0) { // Exception is not used catchBlock.ExceptionVariable = null; } else if (ldexception.StoreTo.Count == 1) { var first = catchBlock.Body[0] as AstExpression; if (first != null && first.Code == AstCode.Pop && first.Arguments[0].Code == AstCode.Ldloc && first.Arguments[0].Operand == ldexception.StoreTo[0]) { // The exception is just poped - optimize it all away; if (context.Settings.AlwaysGenerateExceptionVariableForCatchBlocks) catchBlock.ExceptionVariable = new AstGeneratedVariable("ex_" + eh.HandlerStart.Offset.ToString("X2"), null); else catchBlock.ExceptionVariable = null; catchBlock.Body.RemoveAt(0); } else { catchBlock.ExceptionVariable = ldexception.StoreTo[0]; } } else { var exTemp = new AstGeneratedVariable("ex_" + eh.HandlerStart.Offset.ToString("X2"), null); catchBlock.ExceptionVariable = exTemp; foreach (var storeTo in ldexception.StoreTo) { catchBlock.Body.Insert(0, new AstExpression(catchBlock.SourceLocation, AstCode.Stloc, storeTo, new AstExpression(catchBlock.SourceLocation, AstCode.Ldloc, exTemp))); } } tryCatchBlock.CatchBlocks.Add(catchBlock); } else if (eh.HandlerType == ExceptionHandlerType.Finally) { tryCatchBlock.FinallyBlock = new AstBlock(handlerAst); } else if (eh.HandlerType == ExceptionHandlerType.Fault) { tryCatchBlock.FaultBlock = new AstBlock(handlerAst); } else { // TODO: ExceptionHandlerType.Filter } } ehs.ExceptWith(handlers); ast.Add(tryCatchBlock); } // Add whatever is left ast.AddRange(ConvertToAst(body)); return ast; }
protected override void OnKeyUp(KeyEventArgs e) { pressedKeys.Remove(e.KeyCode); Game.KeyPressed = pressedKeys.Any() ? pressedKeys.Min() : Keys.None; }
// A* // http://en.wikipedia.org/wiki/A*_search_algorithm // http://wiki.gamegardens.com/Path_Finding_Tutorial /// <summary> /// A* uses a best-first search and finds the least-cost path from a given initial node to one goal node (out of one or more possible goals). /// </summary> /// <param name="grid"></param> /// <param name="start"></param> /// <param name="goal"></param> /// <param name="neighbors"></param> /// <returns></returns> public static IEnumerable <Coordinate> Astar(this long[,] grid, Coordinate start, Coordinate goal, Func <long[, ], Coordinate, IEnumerable <Coordinate> > neighbors) { var closedSet = new HashSet <Coordinate>(); var openSet = new HashSet <Coordinate> { start }; var cameFrom = new Dictionary <Coordinate, Coordinate>(); var gScore = new long[grid.GetLength(0), grid.GetLength(1)]; var hScore = new long[grid.GetLength(0), grid.GetLength(1)]; var fScore = new long[grid.GetLength(0), grid.GetLength(1)]; gScore[start.Row, start.Col] = 0; hScore[start.Row, start.Col] = grid.DistanceEstimate(start, goal); fScore[start.Row, start.Col] = hScore[start.Row, start.Col]; while (openSet.Any()) { var min = openSet.Min(v => fScore[v.Row, v.Col]); var u = openSet.First(v => fScore[v.Row, v.Col] == min); if (u.Equals(goal)) { foreach (var p in ReconstitutePath(cameFrom, cameFrom[u])) { yield return(p); } yield return(goal); } openSet.Remove(u); closedSet.Add(u); foreach (var neighbor in neighbors(grid, u)) { if (closedSet.Contains(neighbor)) { continue; } var tentativeGScore = gScore[u.Row, u.Col] + grid.DistanceBetween(u, neighbor); var tentativeIsBetter = false; if (!openSet.Contains(neighbor)) { openSet.Add(neighbor); tentativeIsBetter = true; } else if (tentativeGScore < gScore[neighbor.Row, neighbor.Col]) { tentativeIsBetter = true; } if (tentativeIsBetter) { if (cameFrom.TryGetValue(neighbor, out var value)) { value = u; } else { cameFrom.Add(neighbor, u); } gScore[neighbor.Row, neighbor.Col] = tentativeGScore; hScore[neighbor.Row, neighbor.Col] = DistanceEstimate(grid, neighbor, goal); fScore[neighbor.Row, neighbor.Col] = gScore[neighbor.Row, neighbor.Col] + hScore[neighbor.Row, neighbor.Col]; } } } }
public ColorGradientWidget(GCodeFile gcodeFileTest) : base(FlowDirection.TopToBottom) { BackgroundColor = new RGBA_Bytes(0, 0, 0, 120); HashSet <float> speeds = new HashSet <float>(); PrinterMachineInstruction previousInstruction = gcodeFileTest.Instruction(0); for (int i = 1; i < gcodeFileTest.LineCount; i++) { PrinterMachineInstruction instruction = gcodeFileTest.Instruction(i); if (instruction.EPosition > previousInstruction.EPosition && (instruction.Line.IndexOf('X') != -1 || instruction.Line.IndexOf('Y') != -1)) { speeds.Add((float)instruction.FeedRate); } previousInstruction = instruction; } ExtrusionColors extrusionColors = new ExtrusionColors(); speeds.Select(speed => extrusionColors.GetColorForSpeed(speed)).ToArray(); if (speeds.Count <= 0) { // There are no paths so don't generate the rest of the widget. return; } float min = speeds.Min(); float max = speeds.Max(); int maxItems = Math.Min(7, speeds.Count()); int count = maxItems - 1; float increment = (max - min) / count; int index = 0; int[] rangeValues; if (speeds.Count < 8) { rangeValues = speeds.Select(s => (int)s).OrderBy(i => i).ToArray(); } else { rangeValues = Enumerable.Range(0, maxItems).Select(x => (int)(min + increment * index++)).ToArray(); } RGBA_Bytes[] speedColors = rangeValues.OrderBy(s => s).Select(speed => extrusionColors.GetColorForSpeed(speed)).ToArray(); for (int i = 0; i < speedColors.Length; i++) { RGBA_Bytes color = speedColors[i]; int speed = rangeValues[i]; GuiWidget colorWidget = new GuiWidget(); colorWidget.Width = 20; colorWidget.Height = 20; colorWidget.BackgroundColor = color; colorWidget.Margin = new BorderDouble(2); double feedRateToMMPerSecond = speed / 60; ColorToSpeedWidget colorToSpeedWidget = new ColorToSpeedWidget(colorWidget, feedRateToMMPerSecond); this.AddChild(colorToSpeedWidget); } Margin = new BorderDouble(5, 5, 200, 50); HAnchor |= Agg.UI.HAnchor.ParentLeft; VAnchor = Agg.UI.VAnchor.ParentTop; }
private void ConvertTimeEntriesToBlocks(List <Toggl.TogglTimeEntryView> timeEntries) { var timeStampsList = new List <(TimeStampType Type, TimeEntryBlock Block)>(); var blocks = new List <TimeEntryBlock>(); //The idea is to place all the starts and ends in sorted order and then assign an offset to each time entry block from the list: // - if it's a start time stamp, then pick up the minimum available offset, if none is available assign a new one. // - if it's an end time stamp, then release the offset which it occupied. foreach (var entry in timeEntries) { var startTime = Toggl.DateTimeFromUnix(entry.Started); var height = ConvertTimeIntervalToHeight(startTime, Toggl.DateTimeFromUnix(entry.Ended)); var block = new TimeEntryBlock() { Height = height < 2 ? 2 : height, VerticalOffset = ConvertTimeIntervalToHeight(new DateTime(startTime.Year, startTime.Month, startTime.Day), startTime), Color = entry.Color, Description = entry.Description, ProjectName = entry.ProjectLabel, ClientName = entry.ClientLabel, ShowDescription = true, Started = entry.Started, Ended = entry.Ended }; if (entry.Started != entry.Ended) { timeStampsList.Add((TimeStampType.Start, block)); timeStampsList.Add((TimeStampType.End, block)); } else { timeStampsList.Add((TimeStampType.Empty, block)); } blocks.Add(block); } //There can be a situation that next time entry starts exactly at the same moment, the previous one ended. //This situation must not be considered as overlap. So the comparison logic if time stamps are the same: // - always place the end time stamps first // - prefer empty time stamps to start time stamps // (otherwise if we discover a start then an empty, this will be considered as overlap, which we want to avoid) timeStampsList.Sort((te1, te2) => { var time1 = te1.Type == TimeStampType.End ? te1.Block.Ended : te1.Block.Started; var time2 = te2.Type == TimeStampType.End ? te2.Block.Ended : te2.Block.Started; var res = time1.CompareTo(time2); if (res == 0) { var getPriority = new Func <TimeStampType, int>(t => t == TimeStampType.End ? 0 : t == TimeStampType.Empty ? 1 : 2); return(getPriority(te1.Type) - getPriority(te2.Type)); } return(res); }); var offsets = new HashSet <double>(); var curOffset = 0; var usedNumOfOffsets = 0; foreach (var item in timeStampsList) { if (item.Type == TimeStampType.Start || item.Type == TimeStampType.Empty) { if (!offsets.Any()) { offsets.Add(curOffset); curOffset += 25; } if (usedNumOfOffsets > 0 || item.Block.Height < 20) { item.Block.ShowDescription = false; } item.Block.HorizontalOffset = offsets.Min(); offsets.Remove(offsets.Min()); usedNumOfOffsets++; } if (item.Type == TimeStampType.End || item.Type == TimeStampType.Empty) { offsets.Add(item.Block.HorizontalOffset); if (usedNumOfOffsets > 1 || item.Block.Height < 20) { item.Block.ShowDescription = false; } usedNumOfOffsets--; } } TimeEntryBlocks = null; TimeEntryBlocks = blocks; GenerateGapTimeEntryBlocks(timeEntries); }
// Condenses the outage log (i.e., reduces the overlapping outages into single outages) private void CondenseLog() { lock (m_readerWriterLock) { Dictionary <Outage, HashSet <Outage> > outageOverlaps = new Dictionary <Outage, HashSet <Outage> >(); // Detect overlapping outages foreach (Outage outage in this) { Outage a = outage; foreach (Outage overlap in this.Where(b => !ReferenceEquals(a, b) && a.StartTime <= b.EndTime && b.StartTime <= a.EndTime)) { outageOverlaps.GetOrAdd(outage, o => new HashSet <Outage>()).Add(overlap); } } // If there are any overlapping outages, we need to reduce set if (outageOverlaps.Count > 0) { bool originalPostponeState = m_postponeWriteOperations; try { // In this "fix-up" mode, we delay write subsequent log operations until process is complete m_postponeWriteOperations = true; foreach (KeyValuePair <Outage, HashSet <Outage> > overlap in outageOverlaps) { HashSet <Outage> overlaps = overlap.Value; // Add base outage to overlaps so full minimum and maximum range can be determined overlaps.Add(overlap.Key); Outage combinedOutage = new Outage(overlaps.Min(o => o.StartTime), overlaps.Max(o => o.EndTime)); bool outagesRemoved = false; // Remove each overlapping outage foreach (Outage outage in overlaps) { if (Remove(outage)) { outagesRemoved = true; } } // Add a new combined outage of the complete span, assuming any of the outages were removed (could have already been handled) if (outagesRemoved) { Add(combinedOutage); } } m_totalCondenses++; } finally { m_postponeWriteOperations = originalPostponeState; QueueWriteLog(); } } } }
/// <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(); }
/// <summary> /// Analyzes the data to compute Width, Height, DeltaX, DeltaY, Maximum and Minimum values. /// </summary> /// <param name="path"> /// Path of XYZ file. /// </param> private static DataGridDetails LoadDataDetails(string path) { HashSet <double> longitudes = new HashSet <double>(); HashSet <double> latitudes = new HashSet <double>(); HashSet <double> values = new HashSet <double>(); FileStream fileStream = null; try { fileStream = File.OpenRead(path); using (StreamReader stream = new StreamReader(fileStream)) { fileStream = null; string line = stream.ReadLine(); if (!string.IsNullOrEmpty(line)) { do { string[] parts = line.Split('\t'); double longValue = 0; double latValue = 0; double value = 0; if (!double.TryParse(parts[0], out longValue)) { longValue = 0; } if (!double.TryParse(parts[1], out latValue)) { latValue = 0; } if (!double.TryParse(parts[2], out value)) { value = 0; } longitudes.Add(longValue); latitudes.Add(latValue); values.Add(value); line = stream.ReadLine(); }while (!string.IsNullOrEmpty(line)); } } } finally { if (fileStream != null) { fileStream.Dispose(); } } // Added 1 to use the variable as an array index so that the right size is allotted int gridWidth = longitudes.Count() + 1; int gridHeight = latitudes.Count() + 1; var boundary = new Boundary(longitudes.Min(), latitudes.Min(), longitudes.Max(), latitudes.Max()); double minimumThreshold = values.Min(); double maximumThreshold = values.Max(); return(new DataGridDetails(null, gridWidth, gridHeight, boundary, minimumThreshold, maximumThreshold)); }
public ColorGradientWidget(GCodeFile gcodeFileTest) : base(FlowDirection.TopToBottom) { BackgroundColor = new RGBA_Bytes(0, 0, 0, 120); HashSet<float> speeds = new HashSet<float>(); PrinterMachineInstruction previousInstruction = gcodeFileTest.Instruction(0); for (int i = 1; i < gcodeFileTest.LineCount; i++) { PrinterMachineInstruction instruction = gcodeFileTest.Instruction(i); if (instruction.EPosition > previousInstruction.EPosition && (instruction.Line.IndexOf('X') != -1 || instruction.Line.IndexOf('Y') != -1)) { speeds.Add((float)instruction.FeedRate); } previousInstruction = instruction; } ExtrusionColors extrusionColors = new ExtrusionColors(); speeds.Select(speed => extrusionColors.GetColorForSpeed(speed)).ToArray(); if(speeds.Count <= 0) { // There are no paths so don't generate the rest of the widget. return; } float min = speeds.Min(); float max = speeds.Max(); int maxItems = Math.Min(7, speeds.Count()); int count = maxItems - 1; float increment = (max - min) / count; int index = 0; int[] rangeValues; if (speeds.Count < 8) { rangeValues = speeds.Select(s => (int)s).OrderBy(i => i).ToArray(); } else { rangeValues = Enumerable.Range(0, maxItems).Select(x => (int)(min + increment * index++)).ToArray(); } RGBA_Bytes[] speedColors = rangeValues.OrderBy(s => s).Select(speed => extrusionColors.GetColorForSpeed(speed)).ToArray(); for (int i = 0; i < speedColors.Length; i++) { RGBA_Bytes color = speedColors[i]; int speed = rangeValues[i]; GuiWidget colorWidget = new GuiWidget(); colorWidget.Width = 20; colorWidget.Height = 20; colorWidget.BackgroundColor = color; colorWidget.Margin = new BorderDouble(2); double feedRateToMMPerSecond = speed / 60; ColorToSpeedWidget colorToSpeedWidget = new ColorToSpeedWidget(colorWidget, feedRateToMMPerSecond); this.AddChild(colorToSpeedWidget); } Margin = new BorderDouble(5, 5, 200, 50); HAnchor |= Agg.UI.HAnchor.ParentLeft; VAnchor = Agg.UI.VAnchor.ParentTop; }
private static bool isPandigital(string s) { HashSet <int> t = new HashSet <int>(s.ToCharArray().Select(x => Int32.Parse(x.ToString()))); return((t.Count == 9) && (t.Min() == 1)); }
/// <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; }
static void Main(string[] args) { Console.WriteLine("Path: "); string pathToFile = Console.ReadLine(); Console.WriteLine("Weight Mode?(Y/N): "); string answer = Console.ReadLine(); List <int> input = new List <int>(); Dictionary <int, double> weights = new Dictionary <int, double>(); if (answer.ToUpper() == "Y") { int size = -1; int enter = 1; while (enter > 0) { Console.WriteLine("Please enter slice size: "); size = Convert.ToInt32(Console.ReadLine()); if (size <= 0) { enter = -1; } if (enter > 0) { Console.WriteLine("weight : "); if (!weights.ContainsKey(size) && enter > 0) { double wg = -1; wg = Convert.ToDouble(Console.ReadLine()); if (wg > 0.0) { weights.Add(size, wg); input.Add(size); } else { Console.WriteLine("set default weight 1"); weights.Add(size, 1); input.Add(size); } } } } weightsOn = true; } else { Console.WriteLine("Insert heights: "); string s = Console.ReadLine(); input = s.Split(' ').Select(t => Convert.ToInt32(t)).ToList <int>(); weightsOn = false; } HashSet <int> legitSliceHights = new HashSet <int>(input); //"C:\\Users\\VladKo\\Downloads\\bunny.obj" Bitmap3 bmp = createVoxelizedRepresentation(pathToFile); printVoxelizedRepresentation(bmp, "C:\\Users\\VladKo\\Downloads\\inputVox.obj"); if (test) { getIntersections(60, 50, bmp).ForEach(Console.WriteLine); } Tuple <Dictionary <Tuple <int, int>, int>, Dictionary <Tuple <int, int, int, int>, int> > errorAndSum = calcErrorAndSum(bmp, legitSliceHights.Max(), legitSliceHights.Min()); Dictionary <Tuple <int, int>, Tuple <int, int> > algResults = optDiscreteSlicingAlgo(errorAndSum.Item1, legitSliceHights, bmp.Dimensions.y); Tuple <int, int> startPoint = findStartPoint(algResults, bmp.Dimensions.y, legitSliceHights.Max(), legitSliceHights.Min()); List <int> path = getOptSlice(startPoint, algResults, legitSliceHights.Min(), bmp.Dimensions.y, weights); //from top to bottom Vector3i newObjDim = createVector(bmp.Dimensions.x, path.First() - path.Last(), bmp.Dimensions.z); Bitmap3 outputObj = createNewObjectForPriniting(path, errorAndSum.Item2, newObjDim, bmp); printVoxelizedRepresentation(outputObj, "C:\\Users\\VladKo\\Downloads\\outputVox.obj"); }
/// <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; } }
/// <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, nodeTuple.@from, 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; }
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); }