/// <summary> /// Return projected string for some item. /// </summary> /// <param name="cachingGraph"></param> /// <param name="item">Iitem to be projected.</param> /// <param name="left">Item is on left side of dependency</param> /// <returns>Projected item; or <c>null</c> if item does not /// match projection</returns> public Item Match(WorkingGraph cachingGraph, [NotNull] Item item, bool left) { if (left && !_forLeftSide || !left && !_forRightSide) { return(null); } else { var matchResultGroups = ItemMatch.Matches(item); if (!matchResultGroups.Success) { return(null); } else { IEnumerable <string> targets = _targetSegments; for (int i = 0; i < matchResultGroups.Groups.Length; i++) { int matchResultIndex = i; targets = targets.Select(s => s.Replace("\\" + (matchResultIndex + 1), matchResultGroups.Groups[matchResultIndex])); } _matchCount++; return(cachingGraph.CreateItem(_targetItemType, targets.Select(t => GlobalContext.ExpandHexChars(t)).ToArray())); } } }
public void Traverse(IEnumerable <TDependency> dependencies, ItemMatch pathAnchor, bool pathAnchorIsCountMatch, AbstractPathMatch <TDependency, TItem>[] expectedPathMatches) { Dictionary <TItem, TDependency[]> incidentDependencies = _backwards ? AbstractItem <TItem> .CollectIncomingDependenciesMap(dependencies) : AbstractItem <TItem> .CollectOutgoingDependenciesMap(dependencies); _seenInnerPathStarts.Clear(); Paths.Clear(); Counts.Clear(); _onPath.Clear(); TItem[] uniqueStartItems = (pathAnchor == null ? incidentDependencies.Keys : incidentDependencies.Keys.Where(i => pathAnchor.Matches(i).Success)).ToArray(); AbstractPathMatch <TDependency, TItem> endMatch; AbstractPathMatch <TDependency, TItem>[] innerMatches; int n = expectedPathMatches.Length; if (n == 0) { endMatch = null; innerMatches = expectedPathMatches; } else { endMatch = expectedPathMatches[n - 1]; innerMatches = expectedPathMatches.Take(n - 1).ToArray(); } foreach (var item in uniqueStartItems.OrderBy(i => i.Name)) { if (_seenInnerPathStarts.Add(item)) { List <PathNode <TItem, TDependency> > up = Traverse(root: item, incidentDependencies: incidentDependencies, expectedInnerPathMatches: innerMatches, endMatch: endMatch, down: new DownInfo(pathAnchorIsCountMatch ? item : null)); if (up != null) { Paths.Add(item, up); } } } }
public override bool IsMatch(TDependency nextDep, TItem newTail) { return(_itemMatch.Matches(newTail).Success); }
protected override void PlaceObjects([NotNull, ItemNotNull] IEnumerable <Dependency> dependencies) { // ASCII-art sketch of what I want to accomplish: // +-----+ // | |--------------------------------------------->| // | VKF |--------->| | // +-----+ | | // | | // +-----+ | | // | |--------------------------------------------->| // | WLG |--------------------->| | // +-----+ | | | // | | | // +-----+ | | | // | |--------------------------------->| | // | KST |--------------------->| | | // | |--------->| | | | // +-----+ | | | | // +-------+ +-------+ +-------+ +-------+ // | IMP.A | | IMP.B | | IMP.C | | IMP.D | // +-------+ +-------+ +-------+ +-------+ // // The itemtype is expected to have 1 or 2 fields Name[:HtmlRef] // In the example diagram above, we would have items about like the following: // BAC: // WLG: // KST: // IMP.A: // IMP.B: // IMP.C: // IMP.D: Arrow(F(0, 0), F(100, 0), 1, Color.Chartreuse, "100px", textFont: _lineFont); Box(F(-20, -20), _title + "(" + DateTime.Now + ")", boxAnchoring: BoxAnchoring.UpperRight); List <Item> yItems = dependencies.Select(e => e.UsingItem).Distinct().ToList(); List <Item> xItems = dependencies.Select(e => e.UsedItem).Distinct(). Where(i => _bottomItemMatch == null || _bottomItemMatch.Matches(i).Success). ToList(); Dependency[] relevantDependencies = dependencies.Where(d => yItems.Contains(d.UsingItem) && xItems.Contains(d.UsedItem)).ToArray(); if (_showOnlyReferencedOnBottom) { xItems.RemoveAll(ix => !relevantDependencies.Any(d => d.UsedItem.Equals(ix))); } if (_showOnlyReferencingOnLeft) { yItems.RemoveAll(iy => !relevantDependencies.Any(d => d.UsingItem.Equals(iy))); } _orderSupport.SortWithEdgeCount(xItems, relevantDependencies, (i, d) => d.UsedItem.Equals(i)); _orderSupport.SortWithEdgeCount(yItems, relevantDependencies, (i, d) => d.UsingItem.Equals(i)); double x = 100; var xBoxes = new Dictionary <Item, IBox>(); foreach (var ix in xItems) { string name = GetName(ix); var xPos = new VariableVector(name + ".POS", Solver); IBox box = Box(xPos, boxAnchoring: BoxAnchoring.LowerLeft, text: name, borderWidth: 3, boxColor: Color.LemonChiffon, boxTextPlacement: BoxTextPlacement.LeftUp, textFont: _boxFont, drawingOrder: 1, fixingOrder: 4, htmlRef: GetXHtmlRef(ix)); xPos.SetX(x).SetY(-box.TextBox.Y); xBoxes[ix] = box; x += 40; } const int DELTA_Y_MAIN = 12; NumericVariable y = Solver.CreateConstant("y", 10); foreach (var iy in yItems) { string name = GetName(iy); var yPos = new VariableVector(name + ".POS", Solver); IBox box = Box(yPos, boxAnchoring: BoxAnchoring.LowerRight, text: name, borderWidth: 3, boxColor: Color.Coral, boxTextPlacement: BoxTextPlacement.Left, textFont: _boxFont, drawingOrder: 1, fixingOrder: 4, htmlRef: GetYHtmlRef(iy) ?? GetXHtmlRef(iy)); yPos.SetX(0).SetY(y); double minBoxHeight = 45; foreach (var d in relevantDependencies.Where(d => iy.Equals(d.UsingItem))) { IBox usedBox = xBoxes[d.UsedItem]; yPos += F(0, 3); Arrow(yPos, new VariableVector(name + "->...", usedBox.LowerLeft.X, yPos.Y), width: 2, color: d.NotOkCt > 0 ? Color.Red : d.QuestionableCt > 0 ? Color.Blue : Color.Black, text: "#=" + d.Ct, placement: LineTextPlacement.Left, textLocation: -85, edgeInfo: d.ExampleInfo, drawingOrder: 1); usedBox.UpperRight.MinY(yPos.Y + 5); yPos += F(0, DELTA_Y_MAIN); minBoxHeight += DELTA_Y_MAIN; box.UpperRight.MinY(yPos.Y); } box.Diagonal.MinY(minBoxHeight); //Console.WriteLine(name + ".LR.Y=" + y + " .H>=" + minBoxHeight + " H.ShortName=" + box.Diagonal.Y.ShortName); y += minBoxHeight + 10; } //string countText = "\n<" + SumAsString(dependencies, d => d.UsingItem.Equals(i) && !d.UsedItem.Equals(i)) // + " =" + SumAsString(dependencies, d => d.UsingItem.Equals(i) && d.UsedItem.Equals(i)) // + " >" + SumAsString(dependencies, d => !d.UsingItem.Equals(i) && d.UsedItem.Equals(i)); // TODO: Add option and computation to split this into .,?,! }