// проверка активности public void checkActivity(ActivityNode activity, ADNodesList.ADNode node) { if (activity.getName().Length == 0) { ADMistakeFactory.createMistake(Level.HARD, MistakeAdapter.toString(MISTAKES.NO_NAME), node, ALL_MISTAKES.NO_NAME); } else { // проверка на уникальность имени if (activityNames.Contains(activity.getName().ToLower())) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.REPEATED_NAME], MistakeAdapter.toString(MISTAKES.REPEATED_NAME), diagramElements.getNode(activity.getId()), ALL_MISTAKES.REPEATED_NAME); return; } else { activityNames.Add(activity.getName().ToLower()); } // проверка на заглавную букву if ((!activity.getName().Substring(0, 1).ToUpper().Equals(activity.getName().Substring(0, 1)))) { ADMistakeFactory.createMistake(Level.HARD, MistakeAdapter.toString(MISTAKES.SMALL_LETTER), node, ALL_MISTAKES.SMALL_LETTER); } // получаем первое слово существительного и проверяем, что оно не заканчивается на ь или т string firstWord = activity.getName().Split(' ')[0]; //Console.WriteLine(firstWord); if (firstWord.EndsWith("те") || firstWord.EndsWith("чи") || firstWord.EndsWith("ти") || firstWord.EndsWith("ть") || firstWord.EndsWith("чь") || firstWord.EndsWith("т")) { ADMistakeFactory.createMistake(Level.EASY, MistakeAdapter.toString(MISTAKES.NOT_NOUN), node, ALL_MISTAKES.NOT_NOUN); } } }
/** * Проверка, что элемент принадлежит какому-либо участнику */ private void checkIfInPartion(DiagramElement currentNode, string name, ADNodesList.ADNode node) { if (currentNode.getInPartition().Equals("")) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.NO_PARTION], MistakeAdapter.toString(MISTAKES.NO_PARTION), node, ALL_MISTAKES.NO_PARTION); } }
private void checkActivity(ActivityNode activity, ADNodesList.ADNode node) { activityCount++; // активность имеет больше одного выходящего перехода if (activity.outSize() >= 2) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.MORE_THAN_ONE_OUT], MistakeAdapter.toString(MISTAKES.MORE_THAN_ONE_OUT), node, ALL_MISTAKES.MORE_THAN_ONE_OUT); } }
private void checkFork(ForkNode fork, ADNodesList.ADNode node) { for (int i = 0; i < fork.outSize(); i++) { ElementType elementType = diagramElements.get(((ControlFlow)diagramElements.get(fork.getOutId(i))).getTarget()).getType(); Console.WriteLine("elementType=" + elementType); if (elementType != ElementType.ACTIVITY && elementType != ElementType.DECISION && elementType != ElementType.FORK && elementType != ElementType.MERGE) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.OUT_NOT_IN_ACT], MistakeAdapter.toString(MISTAKES.OUT_NOT_IN_ACT), node, ALL_MISTAKES.OUT_NOT_IN_ACT); } } }
/** * Создание ошибки, содержащей элемент диаграммы */ public static void createMistake(Level level, string mistake, ADNodesList.ADNode element, ALL_MISTAKES type) { if (diagram == null) { return; } var tmp = (DiagramElement)element.getValue(); string descr = tmp is DecisionNode ? ((DecisionNode)tmp).getQuestion() : tmp.getDescription(); var bbox = new BoundingBox(tmp.X, tmp.Y, tmp.Width, tmp.Height); descr = descr == ""?descr:(" '" + descr + "'"); diagram.Mistakes.Add(new Mistake(levelAdapter(level), ElementTypeAdapter.toString(tmp.getType()) + descr + ": " + mistake, bbox, type)); }
private void checkDecision(DecisionNode decision, ADNodesList.ADNode node) { bool checkAlt = true; // проверка, что альтернативы есть if (decision.alternativeSize() == 0) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.DO_NOT_HAVE_ALT], MistakeAdapter.toString(MISTAKES.DO_NOT_HAVE_ALT), node, ALL_MISTAKES.DO_NOT_HAVE_ALT); checkAlt = false; } // проверка, что альтернатив больше одной if (checkAlt) { if (decision.alternativeSize() == 1) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.ONLY_ONE_ALT], MistakeAdapter.toString(MISTAKES.ONLY_ONE_ALT), node, ALL_MISTAKES.ONLY_ONE_ALT); } } // проверка, что альтернативы не ведут в один и тот же элемент if (checkAlt) { for (int i = 0; i < decision.outSize() - 1; i++) { string targetId = ((ControlFlow)diagramElements.get(decision.getOutId(i))).getTarget(); for (int j = i + 1; j < decision.outSize(); j++) { if (targetId.Equals(((ControlFlow)diagramElements.get(decision.getOutId(j))).getTarget())) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.SAME_TARGET], MistakeAdapter.toString(MISTAKES.SAME_TARGET), node, ALL_MISTAKES.SAME_TARGET); } } if (diagramElements.get(targetId).getType() == ElementType.DECISION) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.NEXT_DECISION], MistakeAdapter.toString(MISTAKES.NEXT_DECISION), node, ALL_MISTAKES.NEXT_DECISION); } } // проверка на последовательность условных операторов string targetId2 = ((ControlFlow)diagramElements.get(decision.getOutId(decision.outSize() - 1))).getTarget(); if (diagramElements.get(targetId2).getType() == ElementType.DECISION) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.NEXT_DECISION], MistakeAdapter.toString(MISTAKES.NEXT_DECISION), node, ALL_MISTAKES.NEXT_DECISION); } } }
/** * Проверка, что имеется хотя бы один входящий\выходящий переход */ private void checkInOut(DiagramElement currentNode, string name, ADNodesList.ADNode node) { if (currentNode is MergeNode || currentNode is JoinNode) { if ((currentNode).inSize() == 1) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.HAS_1_IN], MistakeAdapter.toString(MISTAKES.HAS_1_IN), node, ALL_MISTAKES.HAS_1_IN); } } if ((currentNode).inSize() == 0) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.NO_IN], MistakeAdapter.toString(MISTAKES.NO_IN), node, ALL_MISTAKES.NO_IN); } if ((currentNode).outSize() == 0) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.NO_OUT], MistakeAdapter.toString(MISTAKES.NO_OUT), node, ALL_MISTAKES.NO_OUT); } }
private List <Token> activateJoin(ADNodesList.ADNode joinNode, List <Token> mask, List <List <Token> > resultMasks, List <int> curColors) { List <Token> newMask = copyMask(mask); List <Token> maskCur = copyMask(mask); int color = 0; int curIndex = ((DiagramElement)joinNode.getValue()).petriId; List <int> idsPrev = new List <int>(); // список ид элементов перед join List <int> newColors = new List <int>(curColors); newColors.RemoveAt(newColors.Count - 1); // подготовили список цветов для join // все предшествующие элементы должны содержать токен одного цвета for (int i = 0; i < joinNode.prevSize(); i++) { int idPrev = ((DiagramElement)joinNode.getPrev(i).getValue()).petriId; idsPrev.Add(idPrev); if (newMask[idPrev].type == NO_TOKEN) { return(null); } if (i == 0) { color = newMask[idPrev].peekLastColor(); } if (newMask[idPrev].peekLastColor() != color) { return(null); } } // если все предыдущие элементы были активны, активируем текущий // для каждой результирующей маски шага удаляем токены и добавляем токен в join foreach (int id in idsPrev) { updateStepMasks(id, curIndex, resultMasks, newColors); setNewEmptyToken(maskCur, id); // удаляем токены из маски шага } return(maskCur); }
public void check(ADNodesList adList) { Queue <List <Token> > leaves = new Queue <List <Token> >(); // необработанные маски HashSet <string> masksInUsed = new HashSet <string>(adList.getPetriElementsCount()); // использованные маски // ищем начальное состояние ADNodesList.ADNode initNode = adList.findInitial(); var finalNode = adList.findFinal(); var indexesOfFinalNode = finalNode.Select(x => ((DiagramElement)x.getValue()).petriId).ToList(); // создаем маску и добавляем ее в необработанные List <Token> maskTmp = createEmptyMask(adList.getPetriElementsCount()); setNewPaleToken(maskTmp, ((DiagramElement)initNode.getValue()).petriId); leaves.Enqueue(maskTmp); masksInUsed.Add(maskToString(maskTmp)); // добавляем в множество использованных bool canReachFinal = false; List <List <Token> > stepResultMasks = new List <List <Token> >(); // содержит маски, кот могут получиться на каждом шаге string originMaskString = ""; // главный цикл прохода по всем элементам, участвующих в проверке while (leaves.Count > 0) { List <Token> originMask = leaves.Dequeue(); // берем первую маску originMaskString = maskToString(originMask); stepResultMasks.Clear(); List <Token> stepMask = copyMask(originMask); // маска, которую будем изменять по мере деактивации токенов stepResultMasks.Add(copyMask(stepMask)); // Если список масок не изменится, то будет тупик, тк текущая маска уже добавлена в использованные int i = 0; // Console.WriteLine("Or: " + maskToString(originMask)); // проходим по всем элементам маски, находим активированные // и проверяем, можно ли активировать следующий элемент for (int stepProhod = 0; stepProhod < 2; stepProhod++) // сначала проходим по условным, затем по остальным эл-м { i = 0; while (i < stepMask.Count) { if (stepProhod == 0 && adList.getNodeByPetriIndex(i).getValue().getType() != ElementType.DECISION) { i++; continue; // интересуют только эл-ты, содержащие токены на данном шаге } if (stepProhod == 0 && adList.getNodeByPetriIndex(i).getValue().getType() == ElementType.DECISION && stepMask[i].type != TOKEN) { i++; continue; // интересуют только эл-ты, содержащие токены на данном шаге } if (stepProhod == 1 && stepMask[i].type != TOKEN) { i++; continue; // интересуют только эл-ты, содержащие токены на данном шаге } // нашли активный элемент ADNodesList.ADNode curNode = adList.getNodeByPetriIndex(i); //индекс в списке совпадает с петри ид эл-та int curNodeIndex = ((DiagramElement)curNode.getValue()).petriId; List <int> colorsCurToken = new List <int>(stepMask[curNodeIndex].colors); // особо обрабатываем ситуации, когда элемент имеет несколько выходных переходов if (curNode.nextSize() > 1) { // если эл-т разветвитель, то последующее состояние единственно, однако надо установить несколько токенов за раз if (curNode.getValue().getType() == ElementType.FORK) { colorsCurToken.Add(generateRandomColor()); // активируем все следующие элементы for (int j = 0; j < curNode.nextSize(); j++) { // сразу после форка не может быть join'a, поэтому все эл-ты будут активированы int indexOfNewToken = ((DiagramElement)curNode.getNext(j).getValue()).petriId; // проверка, что эл-т не был раннее активирован if (wasAlreadyActive(indexOfNewToken, stepResultMasks, curNode.getNext(j))) { return; } // изменяем существующие результирующие маски updateStepMasks(((DiagramElement)curNode.getValue()).petriId, indexOfNewToken, stepResultMasks, colorsCurToken); } setNewEmptyToken(stepMask, curNodeIndex); } // если это условный оператор, то он порождает несколько возможных последующих состояний else { List <List <Token> > decisionMasks = new List <List <Token> >(); // содержит все возможные маски вариантов перемещения токена bool tokenWasRemoved = false; // активируем следующие элементы по одному for (int j = 0; j < curNode.nextSize(); j++) { int indexOfNewToken = ((DiagramElement)curNode.getNext(j).getValue()).petriId; // индекс активируемого эл-та // проверка, что эл-т не был раннее активирован if (wasAlreadyActive(indexOfNewToken, stepResultMasks, curNode.getNext(j))) { return; } // Join обрабатывается с помощью reverse проверки if ((curNode.getNext(j).getValue()).getType() == ElementType.JOIN) { List <List <Token> > temp = copyMasks(stepResultMasks); List <Token> result = activateJoin(curNode.getNext(j), stepMask, temp, colorsCurToken); if (result != null) { stepMask = result; decisionMasks.AddRange(temp); tokenWasRemoved = true; } } else { // в каждой существующей результирующей маске меняем токен и сохраняем в промежуточный список // в итоге получится новый список, содержащий несколько вариантов результирующих масок, // в каждом из которых создан новый токен в зависимости от активированного следующего эл-та foreach (List <Token> resultMask in stepResultMasks) { List <Token> temp = copyMask(resultMask); setToken(temp, indexOfNewToken, NEW_TOKEN, colorsCurToken); // добавляем новый токен setNewEmptyToken(temp, curNodeIndex); // удаляем токен текущего эл-та decisionMasks.Add(temp); tokenWasRemoved = true; } } } // изменяем маску шага и список результирующих масок, если токен был удален if (tokenWasRemoved) { setNewEmptyToken(stepMask, ((DiagramElement)curNode.getValue()).petriId); // меняем результирующую маску stepResultMasks = decisionMasks; } } } else // если выходной переход один { int indexOfNewToken = ((DiagramElement)curNode.getNext(0).getValue()).petriId; // проверка, что эл-т не был раннее активирован if (wasAlreadyActive(indexOfNewToken, stepResultMasks, curNode.getNext(0))) { return; } // если следующий Join if ((curNode.getNext(0).getValue()).getType() == ElementType.JOIN) { List <Token> result = activateJoin(curNode.getNext(0), stepMask, stepResultMasks, colorsCurToken); if (result != null) { stepMask = result; } } else { updateStepMasks(((DiagramElement)curNode.getValue()).petriId, indexOfNewToken, stepResultMasks, colorsCurToken); setNewEmptyToken(stepMask, curNodeIndex); } } i++; } } // в результирующих масках заменяем NEW_Token на TOKEN foreach (List <Token> stepResultMask in stepResultMasks) { stepResultMask.ForEach(x => x.type = x.type == NEW_TOKEN ? TOKEN : x.type); //Console.WriteLine("Re: " + maskToString(stepResultMask)); if (originMaskString == maskToString(stepResultMask)) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.DEAD_ROAD], MistakeAdapter.toString(MISTAKES.DEAD_ROAD), ALL_MISTAKES.DEAD_ROAD); //Console.WriteLine("Again?: "+originMaskString); return; } } // проверяем, что новой маски нет во множестве обработанных и добавляем в необработанные в таком случае foreach (List <Token> resultMask in stepResultMasks) { if (!findInMasksInUsed(masksInUsed, resultMask)) { int indexOfFinalNode = -1; // проверяем, не достигли ли конечной маркировки (существует путь позволяющий добраться хоть до какого-н finalNode) foreach (var ind in indexesOfFinalNode) { if (resultMask[ind].type == TOKEN) { indexOfFinalNode = ind; break; } } if (indexOfFinalNode != -1) { canReachFinal = true; if (resultMask[indexOfFinalNode].peekLastColor() != NO_COLOR) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.FINAL_COLOR_TOKEN], MistakeAdapter.toString(MISTAKES.FINAL_COLOR_TOKEN), ALL_MISTAKES.FINAL_COLOR_TOKEN); return; } //Проверка, что не осталось токенов int tokenCount = 0; for (int j = 0; j < resultMask.Count && tokenCount <= 1; j++) { if (resultMask[j].type == TOKEN) { tokenCount++; } } if (tokenCount > 1) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.MANY_TOKENS_IN_END], MistakeAdapter.toString(MISTAKES.MANY_TOKENS_IN_END), ALL_MISTAKES.MANY_TOKENS_IN_END); return; } } else { leaves.Enqueue(copyMask(resultMask)); } masksInUsed.Add(maskToString(resultMask)); // добавляем полученную маску в множество обработанных } } } // проверяем, что конечное состояние было достигнуто if (!canReachFinal) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.COULD_NOT_REACH_FINAL], MistakeAdapter.toString(MISTAKES.COULD_NOT_REACH_FINAL), ALL_MISTAKES.COULD_NOT_REACH_FINAL); } }
/** * Проверка был ли данный элемент раннее активирован. Если да, то проверка завершается */ private bool wasAlreadyActive(int tokenIndex, List <List <Token> > stepResultMasks, ADNodesList.ADNode curNode) { foreach (List <Token> stepResultMask in stepResultMasks) { if (stepResultMask[tokenIndex].type != NO_TOKEN) { if (curNode.getValue().getType() != ElementType.FINAL_NODE) { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.TWO_TOKENS], MistakeAdapter.toString(MISTAKES.TWO_TOKENS), ALL_MISTAKES.TWO_TOKENS); } else { ADMistakeFactory.createMistake(MistakesSeriousness.mistakes[MISTAKES.MANY_TOKENS_IN_END], MistakeAdapter.toString(MISTAKES.MANY_TOKENS_IN_END), ALL_MISTAKES.MANY_TOKENS_IN_END); } return(true); } } return(false); }
// проверка условного перехода public void checkDecision(DecisionNode decision, ADNodesList.ADNode node) { // добавляем вопрос для перехода BaseNode flowIn = diagramElements.get(decision.getInId(0)); string quest = ((ControlFlow)flowIn).getText(); decision.setQuestion(quest.Trim()); // добавляем альтернативы -> проходим по всем выходящим переходам и получаем подписи for (int i = 0; i < decision.outSize(); i++) { BaseNode flow = diagramElements.get(decision.getOutId(i)); decision.addAlternative(((ControlFlow)flow).getText()); } // проверяем подписи альтернатив, если их больше одной bool checkAlt = decision.alternativeSize() >= 2; // поиск совпадающих названий if (checkAlt) { decision.findEqualAlternatives().ForEach(x => ADMistakeFactory.createMistake(Level.HARD, MistakeAdapter.toString(MISTAKES.REPEATED_ALT) + " - " + x, node, ALL_MISTAKES.REPEATED_ALT)); } // проверка на альтернативу без подписи if (checkAlt) { if (decision.findEmptyAlternative()) { ADMistakeFactory.createMistake(Level.HARD, MistakeAdapter.toString(MISTAKES.HAVE_EMPTY_ALT), node, ALL_MISTAKES.HAVE_EMPTY_ALT); } } // проверка, что альтернативы начинаются с заглавных букв //if (checkAlt) // for (int i = 0; i < decision.alternativeSize(); i++) // { // String alter = decision.getAlternative(i); // if (!alter.Equals("")) // if (!alter.Substring(0, 1).ToUpper().Equals(alter.Substring(0, 1))) // ADMistakeFactory.createMistake(Level.EASY, " альтернатива \"" + alter + "\"" + MistakeAdapter.toString(MISTAKES.SMALL_LETTER), node); // } bool checkQuest = true; // проверка, что имеется условие if (decision.getQuestion().Equals("")) { ADMistakeFactory.createMistake(Level.HARD, MistakeAdapter.toString(MISTAKES.HAVE_NOT_QUEST), node, ALL_MISTAKES.HAVE_NOT_QUEST); checkQuest = false; // дальнейшие проверки условия не требуются (его нет) } // проверка на заглавную букву if (checkQuest) { if ((!decision.getQuestion().Substring(0, 1).ToUpper().Equals(decision.getQuestion().Substring(0, 1)))) { ADMistakeFactory.createMistake(Level.EASY, MistakeAdapter.toString(MISTAKES.SMALL_LETTER), node, ALL_MISTAKES.SMALL_LETTER); } } // заканчивается на знак вопроса if (checkQuest) { if ((!decision.getQuestion().EndsWith("?"))) { ADMistakeFactory.createMistake(Level.EASY, MistakeAdapter.toString(MISTAKES.END_WITH_QUEST), node, ALL_MISTAKES.END_WITH_QUEST); } } }