private void ShowWires(CompositionResult cmp) { TreeViewItem_Nodes.Items.Clear(); for (int boardNum = 0; boardNum < cmp.BoardsElements.Count; boardNum++) { var boardItem = new TreeViewItem(); boardItem.Header = $"Узел {boardNum + 1}"; var boardElements = new TreeViewItem(); boardElements.Header = "Элементы"; foreach (var element in cmp.BoardsElements[boardNum]) { var boardElement = new TreeViewItem(); if (element != 0) { boardElement.Header = $"D{element}"; } else { boardElement.Header = "X"; } boardElements.Items.Add(boardElement); } boardElements.IsExpanded = true; boardItem.Items.Add(boardElements); var boardWires = new TreeViewItem(); boardWires.Header = "Провода"; int wireIterator = 1; foreach (var wire in cmp.BoardsWires[boardNum]) { var itemWire = new TreeViewItem(); itemWire.Header = $"Провод {wireIterator}"; foreach (var contact in wire) { var itemContact = new TreeViewItem(); if (contact.ElementNumber != 0) { itemContact.Header = $"D{contact.ElementNumber}.{contact.ElementContact}"; } else { itemContact.Header = "X"; } itemWire.Items.Add(itemContact); } boardWires.Items.Add(itemWire); wireIterator++; } boardWires.IsExpanded = true; boardItem.Items.Add(boardWires); TreeViewItem_Nodes.Items.Add(boardItem); } }
private void OnExportsChanging(object sender, ExportsChangeEventArgs e) { CompositionResult result = CompositionResult.SucceededResult; // Prepare for the recomposition effort by minimizing the amount of work we'll have to do later AtomicComposition atomicComposition = e.AtomicComposition; IEnumerable <PartManager> affectedParts = this._recompositionManager.GetAffectedParts(e.ChangedContractNames); // When in a atomicComposition account for everything that isn't yet reflected in the // index if (atomicComposition != null) { EngineContext engineContext; if (atomicComposition.TryGetValue(this, out engineContext)) { // always added the new part managers to see if they will also be // affected by these changes affectedParts = affectedParts.ConcatAllowingNull(engineContext.GetAddedPartManagers()) .Except(engineContext.GetRemovedPartManagers()); } } var changedExports = e.AddedExports.ConcatAllowingNull(e.RemovedExports); foreach (var partManager in affectedParts) { result = result.MergeResult(this.TryRecomposeImports(partManager, changedExports, atomicComposition)); } result.ThrowOnErrors(atomicComposition); }
internal static void AreEqual(CompositionResult expected, CompositionResult actual) { Assert.AreEqual(expected.Succeeded, actual.Succeeded); EnumerableAssert.AreSequenceEqual(expected.Errors, actual.Errors, (index, expectedError, actualError) => { AreEqual(expectedError, actualError); }); }
/// <summary> /// Raises the <see cref="ExportsChanging"/> event. /// </summary> /// <param name="e"> /// An <see cref="ExportsChangeEventArgs"/> containing the data for the event. /// </param> protected virtual void OnExportsChanging(ExportsChangeEventArgs e) { EventHandler<ExportsChangeEventArgs> changingEvent = this.ExportsChanging; if (changingEvent != null) { CompositionResult result = CompositionServices.TryFire(changingEvent, this, e); result.ThrowOnErrors(e.AtomicComposition); } }
public static List <StepPlacementLog> Place(CompositionResult cmp, Matrix <int> R, out string errMsg) { // если в методе произошла какая-то критическая ошибка, записывайте её в эту переменную и делайте return null errMsg = ""; // считываем результат компоновки, в нём хранится список элементов для каждого узла var boardsElements = cmp.BoardsElements; // создаём класс для логирования (обязательно) var log = new List <StepPlacementLog>(); // создаём список с матрицами для каждого узла var boards = new List <Matrix <int> >(); // тестовый алгоритм просто последовательно размещает все элементы на плату // запускаем цикл по платам, в каждой плате резмещаем элементы, а потом переходим к следующей foreach (var boardElements in boardsElements) { // определяем размер платы (3х3, 4х4, 5х5) основываясь на количестве элементов, которые необходимо на ней расположить var size = Convert.ToInt32(Math.Ceiling(Math.Sqrt(boardElements.Count))); // создаём матрицу просчитанного размера var boardMatr = new Matrix <int>(size, size); // заполняем "-1" матрицу boardMatr.Fill(-1); // добавляем в общий список плат новую матрицу платы, в которую будем на этом шаге заносить элементы boards.Add(boardMatr); // определяет в какую позицию будет поставлен элемент int pos = 0; // запускаем цикл по элементам, которые должны быть размещены на плате foreach (var element in boardElements) { // добавляем в последнюю плату элемент на определённую позицию. позиция тут задаётся от 1 до 9. нумерация немного не такая как в идз: // 1 4 7 // 2 5 8 // 3 6 9 (для платы 3х3) boards.Last().setValueByPlatePos(pos, element); pos++; // записываем результат string msg = "Поместили элемент D" + element + " на " + boards.Count + " плату"; // пишем сообщение чё произошло на этом шаге var step = new StepPlacementLog(boards, msg); log.Add(step); } } // возвращаем список шагов return(log); }
public void Constructor3_ValuesAsErrorsArgument_ShouldSetErrorsProperty() { var errors = Expectations.GetCompositionErrors(); foreach (var e in errors) { var result = new CompositionResult(e); EnumerableAssert.AreEqual(e, result.Errors); } }
internal static CompositionResult TryFire <TEventArgs>(EventHandler <TEventArgs> _delegate, object sender, TEventArgs e) where TEventArgs : EventArgs { CompositionResult result = CompositionResult.SucceededResult; foreach (EventHandler <TEventArgs> _subscriber in _delegate.GetInvocationList()) { try { _subscriber.Invoke(sender, e); } catch (CompositionException ex) { result = result.MergeErrors(ex.Errors); } } return(result); }
/// <summary> /// Метод для записи результатов компоновки в файл (сериализация) /// </summary> public static void WriteComposition(CompositionResult cmp, out string errWrite) { errWrite = ""; if (FileName != "") { try { using (StreamWriter file = File.CreateText(FileName + ".cmp")) { JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(file, cmp); } } catch (Exception exc) { errWrite = $"При записи в файл компоновки произошла ошибка: {exc.Message}"; } } }
/// <summary> /// Метод для чтения результатов компоновки в файл (десериализация) /// </summary> public static CompositionResult ReadComposition(out string msg) { msg = ""; CompositionResult cmp = null; if (IsFileExists(".cmp", out msg)) { try { using (StreamReader file = File.OpenText(FileName + ".cmp")) { JsonSerializer serializer = new JsonSerializer(); cmp = (CompositionResult)serializer.Deserialize(file, typeof(CompositionResult)); } } catch (Exception exp) { msg = $"Произошла ошибка при попытке чтения файла {FileName}.cmp: {exp.Message}"; } } return(cmp); }
private CompositionResult TrySatisfyImportSubset(PartManager partManager, IEnumerable <ImportDefinition> imports, AtomicComposition atomicComposition) { CompositionResult result = CompositionResult.SucceededResult; var part = partManager.Part; foreach (ImportDefinition import in imports) { var exports = partManager.GetSavedImport(import); if (exports == null) { CompositionResult <IEnumerable <Export> > exportsResult = TryGetExports( this._sourceProvider, part, import, atomicComposition); if (!exportsResult.Succeeded) { result = result.MergeResult(exportsResult.ToResult()); continue; } exports = exportsResult.Value.AsArray(); } if (atomicComposition == null) { result = result.MergeResult( partManager.TrySetImport(import, exports)); } else { partManager.SetSavedImport(import, exports, atomicComposition); } } return(result); }
private List <StepCompositionLog> DoComposition() { var steps = new List <StepCompositionLog>(); string err_msg = ""; switch (ComboBox_Method.SelectedIndex) { case 0: steps = PosledGypergraph.Compose(tbCountOfElements.Value ?? 10, tbLimitsOfWires.Value ?? 100, out err_msg); break; case 1: steps = PosledMultigraph.Compose(tbCountOfElements.Value ?? 10, tbLimitsOfWires.Value ?? 100, out err_msg); break; case 2: steps = IterGypergraph.Compose(out err_msg); break; case 3: steps = IterMultigraphNew.Compose(out err_msg); break; case 4: steps = TestComposition.Compose(tbCountOfElements.Value ?? 10, tbLimitsOfWires.Value ?? 100, out err_msg); break; } // если не было ошибки - сериализуем результат if (err_msg == "") { if (steps.Count != 0) { var result = new CompositionResult(); result.BoardsElements = steps.Last().BoardsList; var sch = ApplicationData.ReadScheme(out err_msg); if (err_msg != "") { MessageBox.Show(err_msg, "Revolution CAD", MessageBoxButton.OK, MessageBoxImage.Error); return(null); } result.CreateBoardsWires(sch, out err_msg); if (err_msg != "") { MessageBox.Show(err_msg, "Revolution CAD", MessageBoxButton.OK, MessageBoxImage.Error); return(null); } // формируем новую матрицу R на основе сформированных проводов, которые были разделены по платам result.MatrixR_AfterComposition = ApplicationData.CreateMatrixR(result.BoardsWires, sch.MatrixR.RowsCount, sch.MatrixR.ColsCount); ApplicationData.WriteComposition(result, out err_msg); if (err_msg != "") { MessageBox.Show(err_msg, "Revolution CAD", MessageBoxButton.OK, MessageBoxImage.Error); return(null); } string msg; if (ApplicationData.IsFileExists(".plc", out msg)) { File.Delete($"{ApplicationData.FileName}.plc"); } if (ApplicationData.IsFileExists(".trs", out msg)) { File.Delete($"{ApplicationData.FileName}.trs"); } if (ApplicationData.IsFileExists(".lay", out msg)) { File.Delete($"{ApplicationData.FileName}.lay"); } mw.MatrControl.UpdateMatrices(); mw.PlaceControl.Update(); mw.TraceControl.Update(); mw.LayerControl.Update(); } } if (err_msg != "") { MessageBox.Show(err_msg, "Revolution CAD", MessageBoxButton.OK, MessageBoxImage.Error); } return(steps); }
public void Compose(CompositionBatch batch) { ThrowIfDisposed(); EnsureRunning(); Requires.NotNull(batch, nameof(batch)); // Quick exit test can be done prior to cloning since it's just an optimization, not a // change in behavior if ((batch.PartsToAdd.Count == 0) && (batch.PartsToRemove.Count == 0)) { return; } CompositionResult result = CompositionResult.SucceededResult; // Get updated parts list and a cloned batch var newParts = GetUpdatedPartsList(ref batch); // Allow only recursive calls from the import engine to see the changes until // they've been verified ... using (var atomicComposition = new AtomicComposition()) { // Don't allow reentrant calls to compose during previewing to prevent // corrupted state. if (_currentlyComposing) { throw new InvalidOperationException(SR.ReentrantCompose); } _currentlyComposing = true; try { // In the meantime recursive calls need to be able to see the list as well atomicComposition.SetValue(this, newParts); // Recompose any existing imports effected by the these changes first so that // adapters, resurrected parts, etc. can all play their role in satisfying // imports for added parts Recompose(batch, atomicComposition); // Ensure that required imports can be satisfied foreach (ComposablePart part in batch.PartsToAdd) { // collect the result of previewing all the adds in the batch try { ImportEngine.PreviewImports(part, atomicComposition); } catch (ChangeRejectedException ex) { result = result.MergeResult(new CompositionResult(ex.Errors)); } } result.ThrowOnErrors(atomicComposition); // Complete the new parts since they passed previewing.` using (_lock.LockStateForWrite()) { _parts = newParts; } atomicComposition.Complete(); } finally { _currentlyComposing = false; } } // Satisfy Imports // - Satisfy imports on all newly added component parts foreach (ComposablePart part in batch.PartsToAdd) { result = result.MergeResult(CompositionServices.TryInvoke(() => ImportEngine.SatisfyImports(part))); } // return errors result.ThrowOnErrors(); }
/// Generates the code that loads the supplied value on the stack /// This is not as simple as it seems, as different instructions need to be generated depending /// on its type. /// We support: /// 1. All primitive types /// 2. Strings /// 3. Enums /// 4. typeofs /// 5. nulls /// 6. Enumerables /// 7. Delegates on static functions or any of the above /// Everything else cannot be represented as literals /// <param name="ilGenerator"></param> /// <param name="item"></param> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public static void LoadValue(this ILGenerator ilGenerator, object value) { Assumes.NotNull(ilGenerator); CompositionResult result = CompositionResult.SucceededResult; // // Get nulls out of the way - they are basically typeless, so we just load null // if (value == null) { ilGenerator.LoadNull(); return; } // // Prepare for literal loading - decide whether we should box, and handle enums properly // Type valueType = value.GetType(); object rawValue = value; if (valueType.IsEnum) { // enums are special - we need to load the underlying constant on the stack rawValue = Convert.ChangeType(value, Enum.GetUnderlyingType(valueType), null); valueType = rawValue.GetType(); } // // Generate IL depending on the valueType - this is messier than it should ever be, but sadly necessary // if (valueType == GenerationServices.StringType) { // we need to check for strings before enumerables, because strings are IEnumerable<char> ilGenerator.LoadString((string)rawValue); } else if (GenerationServices.TypeType.IsAssignableFrom(valueType)) { ilGenerator.LoadTypeOf((Type)rawValue); } else if (GenerationServices.IEnumerableType.IsAssignableFrom(valueType)) { // NOTE : strings and dictionaries are also enumerables, but we have already handled those ilGenerator.LoadEnumerable((IEnumerable)rawValue); } else if ( (valueType == GenerationServices.CharType) || (valueType == GenerationServices.BooleanType) || (valueType == GenerationServices.ByteType) || (valueType == GenerationServices.SByteType) || (valueType == GenerationServices.Int16Type) || (valueType == GenerationServices.UInt16Type) || (valueType == GenerationServices.Int32Type) ) { // NOTE : Everything that is 32 bit or less uses ldc.i4. We need to pass int32, even if the actual types is shorter - this is IL memory model // direct casting to (int) won't work, because the value is boxed, thus we need to use Convert. // Sadly, this will not work for all cases - namely large uint32 - because they can't semantically fit into 32 signed bits // We have a special case for that next ilGenerator.LoadInt((int)Convert.ChangeType(rawValue, typeof(int), CultureInfo.InvariantCulture)); } else if (valueType == GenerationServices.UInt32Type) { // NOTE : This one is a bit tricky. Ldc.I4 takes an Int32 as an argument, although it really treats it as a 32bit number // That said, some UInt32 values are larger that Int32.MaxValue, so the Convert call above will fail, which is why // we need to treat this case individually and cast to uint, and then - unchecked - to int. ilGenerator.LoadInt(unchecked ((int)((uint)rawValue))); } else if (valueType == GenerationServices.Int64Type) { ilGenerator.LoadLong((long)rawValue); } else if (valueType == GenerationServices.UInt64Type) { // NOTE : This one is a bit tricky. Ldc.I8 takes an Int64 as an argument, although it really treats it as a 64bit number // That said, some UInt64 values are larger that Int64.MaxValue, so the direct case we use above (or Convert, for that matter)will fail, which is why // we need to treat this case individually and cast to ulong, and then - unchecked - to long. ilGenerator.LoadLong(unchecked ((long)((ulong)rawValue))); } else if (valueType == GenerationServices.SingleType) { ilGenerator.LoadFloat((float)rawValue); } else if (valueType == GenerationServices.DoubleType) { ilGenerator.LoadDouble((double)rawValue); } else { throw new InvalidOperationException( string.Format(CultureInfo.CurrentCulture, Strings.InvalidMetadataValue, value.GetType().FullName)); } }
public static List <StepPlacementLog> Place(CompositionResult cmp, Matrix <int> R, out string errMsg) { matrR = R; // если в методе произошла какая-то критическая ошибка, записывайте её в эту переменную и делайте return null errMsg = ""; // считываем результат компоновки, в нём хранится список элементов для каждого узла var boardsElements = cmp.BoardsElements; // создаём класс для логирования (обязательно) var log = new List <StepPlacementLog>(); // создаём список с матрицами для каждого узла var boards = new List <Matrix <int> >(); // запускаем цикл по платам, в каждой плате резмещаем элементы, а потом переходим к следующей foreach (var boardElements in boardsElements) { // определяем размер платы (3х3, 4х4, 5х5) основываясь на количестве элементов, которые необходимо на ней расположить var size = Convert.ToInt32(Math.Ceiling(Math.Sqrt(boardElements.Count))); // создаём матрицу просчитанного размера var boardMatr = new Matrix <int>(size, size); // заполняем "-1" матрицу boardMatr.Fill(-1); // добавляем в общий список плат новую матрицу платы, в которую будем на этом шаге заносить элементы boards.Add(boardMatr); // начальная позиция - условные координаты разъема var pos = new Position(-1, -1); // таким способом копируем список всех элементов в список неразмещённых List <int> unplacedElements = boardElements.Select(x => x).ToList(); // в списке размещённых по умолчанию только разъём List <int> placedElements = new List <int>(); placedElements.Add(0); // запускаем цикл, пока не разместим все элементы while (unplacedElements.Count > 0) { // список с количеством связей с ранее размещёнными элементами ещё неразмещённых // позиция в списке совпадает с позицией в списке неразмещённых номеров элементов var countRelationWithPlaced = new List <int>(); // с помощью метода получаем список количества связей для каждого неразмещённого элемента countRelationWithPlaced = countRelations(unplacedElements, placedElements); // определяем максимальное число связей var maxRelations = countRelationWithPlaced.Max(); // определяем позицию, в которой находится элемент с максимальным количеством связей var elementPosMaxRelations = countRelationWithPlaced.IndexOf(maxRelations); // получаем номер элемента по позиции в списке var elementNumberMaxRelations = unplacedElements[elementPosMaxRelations]; string msg = "Количество связей с размещёнными элементами неразмещённых: "; for (int i = 0; i < unplacedElements.Count; i++) { msg += $"D{unplacedElements[i]}={countRelationWithPlaced[i]}; "; } msg += "\n"; msg += $"Максимальное количество c размещёнными элементами у элемента D{elementNumberMaxRelations}\n"; msg += $"Найдём оптимальную позицию:\n"; // получаем список незанятых соседних ячеек на основе позиции элемента размещённого на предыдущем шаге var neighbors = getNeigbors(boardMatr, pos); // начинаем определение оптимальной позиции для размещения элемента Position minLpos = null; int minL = int.MaxValue; // запускаем цикл по всем соседям foreach (var neighbor in neighbors) { msg += $"D{elementNumberMaxRelations} -> {boardMatr.getRelativePosByAbsolute(neighbor)}; L="; List <string> operations = new List <string>(); int L = 0; // запускаем цикл по всем элементам for (int j = 0; j < matrR.ColsCount; j++) { // если этот элемент был размещён if (placedElements.Contains(j)) { // если у размещаемого элемента есть связи с текущим рассматриваемым if (matrR[elementNumberMaxRelations, j] != 0) { // количество связей определяем по матрице R int countRelationsWithElement = matrR[elementNumberMaxRelations, j]; // получаем расстояние между элементами int length = getLength(neighbor, getPosByElementNumber(boardMatr, j)); operations.Add($"{countRelationsWithElement}*{length}"); // суммируем длину умноженную на количество связей в L L += countRelationsWithElement * length; } } } msg += String.Join("+", operations); msg += $"={L}\n"; // если подсчитанное L меньше просчитанного на предыдущих шагах if (L < minL) { minL = L; // принимаем эту позицию как оптимальную minLpos = neighbor.Clone(); } } int minLposRelative = boardMatr.getRelativePosByAbsolute(minLpos); msg += $"Минимальное значение L в {minLposRelative} позиции\n"; pos = minLpos.Clone(); // устанавливаем элемент в оптимальную позицию boards.Last().setValueByPlatePos(minLposRelative, elementNumberMaxRelations); // начинаем логирование действия msg += $"Помещаем его в {minLposRelative} позицию на {boards.Count} плату"; var step = new StepPlacementLog(boards, msg); log.Add(step); // закончили логирование // убираем из списка неразмещённых элемент, который только что разместили unplacedElements.Remove(elementNumberMaxRelations); // и добавляем в список размещённых placedElements.Add(elementNumberMaxRelations); } } return(log); }
public void Constructor3_EmptyAsErrorsArgument_ShouldSetSucceededPropertyToTrue() { var result = new CompositionResult(Enumerable.Empty<CompositionError>()); Assert.IsTrue(result.Succeeded); }
public void Constructor3_ValuesAsErrorsArgument_ShouldSetSucceededPropertyToTrueIfThereAreErrors() { var errors = Expectations.GetCompositionErrors(); foreach (var e in errors) { var result = new CompositionResult(e); if (e.Count() > 0) { Assert.IsFalse(result.Succeeded); } else { Assert.IsTrue(result.Succeeded); } } }
} // список плат, в котором хранится список проводов по 2 контакта для каждой платы public void CreateBoardsDRPs(CompositionResult cmp, List <int> dips, out string err) { err = ""; var elInBoards = cmp.BoardsElements; var boardsWires = cmp.BoardsWires; if (BoardsMatrices == null) { err = "Список плат пустой"; return; } if (BoardsMatrices.Count == 0) { err = "Список плат пустой"; return; } // список в котором будет хранится размер разъёма для каждой платы var BoardsCountContactsConnector = new List <int>(); BoardsElementsContactsPos = new List <Dictionary <int, List <Position> > >(); BoardsDRPs = new List <Matrix <Cell> >(); // запускаем цикл для формирования своего дрп для каждого узла for (int numBoard = 0; numBoard < BoardsMatrices.Count; numBoard++) { int countContactsConnector = 0; countContactsConnector = boardsWires[numBoard].Count(x => x.Any(y => y.ElementNumber == 0)); BoardsCountContactsConnector.Add(countContactsConnector); // расчёт размера ДРП платы int drpHeight = 0; int drpWidth = 0; var brdMatr = BoardsMatrices[numBoard]; // подсчитываем необходимую высоту платы // запускаем цикл по столбцам, и определяем его высоту суммируя размер для каждого элемента for (int j = 0; j < brdMatr.ColsCount; j++) { int currentColHeight = 0; for (int i = 0; i < brdMatr.RowsCount; i++) { int elementNumber = brdMatr[i, j]; if (elementNumber != -1) // пропускаем пустые места { int elementDip = dips[elementNumber]; int pinsInColumn = elementDip / 2; currentColHeight += ApplicationData.ElementsDistance + pinsInColumn + (ApplicationData.PinDistance * pinsInColumn) - ApplicationData.PinDistance; } } if (currentColHeight > drpHeight) { drpHeight = currentColHeight; } } // подсчитываем необходимую ширину платы for (int i = 0; i < brdMatr.RowsCount; i++) { int currentRowWidth = 0; for (int j = 0; j < brdMatr.ColsCount; j++) { int elementNumber = brdMatr[i, j]; if (elementNumber != -1) // пропускаем пустые места { int elementDip = dips[elementNumber]; currentRowWidth += ApplicationData.ElementsDistance + 2 + ApplicationData.RowDistance; } } if (currentRowWidth > drpWidth) { drpWidth = currentRowWidth; } } drpHeight += ApplicationData.ElementsDistance; drpWidth += ApplicationData.ElementsDistance + 2; // ширина + 2, чтобы учесть разъём // создаём итоговое дрп на базе расчётов var boardDRP = new Matrix <Cell>(drpHeight, drpWidth); // заполняем его пустыми ячейками for (int drpRow = 0; drpRow < boardDRP.RowsCount; drpRow++) { for (int drpCol = 0; drpCol < boardDRP.ColsCount; drpCol++) { boardDRP[drpRow, drpCol] = new Cell(); } } // создаём словарь координат контактов разъёма и элементов var ElementsContactsPos = new Dictionary <int, List <Position> >(); // переходим к размещению разъёма var heightConnector = BoardsCountContactsConnector.Last(); int startRowConnector = drpHeight / 2 - heightConnector / 2; var ConnectorContactsPos = new List <Position>(); for (int r = 0; r < heightConnector; r++) { boardDRP[startRowConnector + r, r % 2].State = CellState.Contact; ConnectorContactsPos.Add(new Position(startRowConnector + r, r % 2)); } ElementsContactsPos.Add(0, ConnectorContactsPos); Position startPos = new Position(ApplicationData.ElementsDistance, ApplicationData.ElementsDistance + 2); Position currentPos = new Position(ApplicationData.ElementsDistance, ApplicationData.ElementsDistance + 2); // запускаем цикл по столбцам матрицы, в которой хранятся номера элементов for (int j = 0; j < brdMatr.ColsCount; j++) { // запускаем цикл по строкам матрицы, в которой хранятся номера элементов for (int i = 0; i < brdMatr.RowsCount; i++) { // узнаём номер элемента в позиции int elementNumber = brdMatr[i, j]; // если -1 - значит место не занято if (elementNumber != -1) // пропускаем пустые места { // список координат каждого контакта var ElementContactsPos = new List <Position>(); // добавляем заглушку, т.к. нумерация ножек начинается с 1, а у нас список и 0 элемент должен существовать ElementContactsPos.Add(new Position(-1, -1)); int elementNumberLabelRow = currentPos.Row; int elementNumberLabelColumn = currentPos.Column + (int)Math.Ceiling((double)ApplicationData.RowDistance / 2); boardDRP[elementNumberLabelRow, elementNumberLabelColumn].Description = $"D{elementNumber}"; // узнаём номер дипа int elementDip = dips[elementNumber]; // количество контактов в столбце = номер дипа / 2 int pinsInColumn = elementDip / 2; int offsetRow = 0; // сначала формируем первый ряд контактов элемента сверху вниз boardDRP[currentPos.Row + offsetRow, currentPos.Column].Description = "(X)"; while (offsetRow < (pinsInColumn * (ApplicationData.PinDistance + 1)) - ApplicationData.PinDistance) { boardDRP[currentPos.Row + offsetRow, currentPos.Column].State = CellState.Contact; // записываем текущую координату в список координат контактов ElementContactsPos.Add(new Position(currentPos.Row + offsetRow, currentPos.Column)); offsetRow += 1 + ApplicationData.PinDistance; } offsetRow -= 1 + ApplicationData.PinDistance; // сдвигаемся вправо на расстояние в клетках от первого ряда контактов currentPos.Column += ApplicationData.RowDistance + 1; // теперь идём обратно вверх while (offsetRow >= 0) { boardDRP[currentPos.Row + offsetRow, currentPos.Column].State = CellState.Contact; // записываем текущую координату в список координат контактов ElementContactsPos.Add(new Position(currentPos.Row + offsetRow, currentPos.Column)); offsetRow -= 1 + ApplicationData.PinDistance; } // добавляем сформированный список координат каждого контакта ElementsContactsPos.Add(elementNumber, ElementContactsPos); // возвращаемся опять в позицию для печати первого ряда контактов, но уже следующего элемента currentPos.Column -= ApplicationData.RowDistance + 1; // пропускаем ячейки с уже размещённым элементом currentPos.Row += (pinsInColumn * (ApplicationData.PinDistance + 1)) - ApplicationData.PinDistance; currentPos.Row += ApplicationData.ElementsDistance; } else { // если позиция пустая, то нужно пропустить определённое количество клеточек // формула приблизительная currentPos.Row += drpHeight / (brdMatr.RowsCount + 1); } } // возвращаемся к начальной точке размещения элементов currentPos.Row = startPos.Row; currentPos.Column = startPos.Column; // пропускаем определённое количество столбцов, которое определяется по количеству уже размещённых умноженное на отступы currentPos.Column += ((j + 1) * (ApplicationData.RowDistance + 2)) + ((j + 1) * ApplicationData.ElementsDistance); } BoardsDRPs.Add(boardDRP); BoardsElementsContactsPos.Add(ElementsContactsPos); } return; }
public void Compose(CompositionBatch batch) { this.ThrowIfDisposed(); this.EnsureRunning(); Requires.NotNull(batch, "batch"); // Quick exit test can be done prior to cloning since it's just an optimization, not a // change in behavior if ((batch.PartsToAdd.Count == 0) && (batch.PartsToRemove.Count == 0)) { return; } CompositionResult result = CompositionResult.SucceededResult; // Clone the batch, so that the external changes wouldn't happen half-way thorugh compose // NOTE : this does not guarantee the atomicity of cloning, which is not the goal anyway, // rather the fact that all subsequent calls will deal with an unchanging batch batch = new CompositionBatch(batch.PartsToAdd, batch.PartsToRemove); var newParts = GetUpdatedPartsList(batch); // Allow only recursive calls from the import engine to see the changes until // they've been verified ... using (var atomicComposition = new AtomicComposition()) { // Don't allow reentrant calls to compose during previewing to prevent // corrupted state. if (this._currentlyComposing) { throw new InvalidOperationException(Strings.ReentrantCompose); } this._currentlyComposing = true; try { // In the meantime recursive calls need to be able to see the list as well atomicComposition.SetValue(this, newParts); // Recompose any existing imports effected by the these changes first so that // adapters, resurrected parts, etc. can all play their role in satisfying // imports for added parts this.Recompose(batch, atomicComposition); // Ensure that required imports can be satisfied foreach (ComposablePart part in batch.PartsToAdd) { // collect the result of previewing all the adds in the batch try { this._importEngine.PreviewImports(part, atomicComposition); } catch (ChangeRejectedException ex) { result = result.MergeResult(new CompositionResult(ex.Errors)); } } result.ThrowOnErrors(atomicComposition); // Complete the new parts since they passed previewing.` using (this._lock.LockStateForWrite()) { this._parts = newParts; } atomicComposition.Complete(); } finally { this._currentlyComposing = false; } } // Satisfy Imports // - Satisfy imports on all newly added component parts foreach (ComposablePart part in batch.PartsToAdd) { result = result.MergeResult(CompositionServices.TryInvoke(() => this._importEngine.SatisfyImports(part))); } // return errors result.ThrowOnErrors(); }
public void Constructor1_ShouldSetErrorsPropertyToEmptyEnumerable() { var result = new CompositionResult(); EnumerableAssert.IsEmpty(result.Errors); }
public void Constructor3_NullAsErrorsArgument_ShouldSetErrorsPropertyToEmptyEnumerable() { var result = new CompositionResult((IEnumerable<CompositionError>)null); EnumerableAssert.IsEmpty(result.Errors); }
public void Constructor2_NullAsErrorsArgument_ShouldSetSucceededPropertyToTrue() { var result = new CompositionResult((CompositionError[])null); Assert.IsTrue(result.Succeeded); }
public void Constructor1_ShouldSetSucceededPropertyToTrue() { var result = new CompositionResult(); Assert.IsTrue(result.Succeeded); }
public void Constructor3_EmptyAsErrorsArgument_ShouldSetErrorsPropertyToEmptyEnumerable() { var result = new CompositionResult(Enumerable.Empty<CompositionError>()); EnumerableAssert.IsEmpty(result.Errors); }