private static bool FillSimultaneous(PatchEntity lowerStep, List <SfcStep> targetSteps, SfcProgramData data) { switch (lowerStep.SfcStepType) { case StepType.StartingStep: case StepType.Step: targetSteps.Add(data.ControlMap[lowerStep.Key]); break; case StepType.Jump: if (data.StepMaster.ContainsStep(lowerStep.StepName)) { int reference = data.StepMaster.GetNameKey(lowerStep.StepName); targetSteps.Add(data.ControlMap[reference]); } else { return(false); } break; case StepType.Pass: SfcStep foundStep = Collector.FindLowerConnectedStep(lowerStep.Key, data); if (foundStep != null) { targetSteps.Add(foundStep); } break; case StepType.Unused: break; } return(true); }
/// <summary> /// Checks if this patch can skip the transition if it is connected to /// StepType.Pass with a upper BranchType. /// </summary> private static bool CheckPossibleTransitionSkip(Sfc2dEditorControl control, PatchEntity sourcePatch) { if (sourcePatch.ContainsTransition()) { return(false); } if (sourcePatch.ContainsRealStep()) { PatchEntity leftPatch = control.Data.SfcEntity.Lookup(sourcePatch.X - 1, sourcePatch.Y); if (HasUpperBranchConnection(sourcePatch, leftPatch)) { return(false); } if (HasLowerBranchConnection(sourcePatch, leftPatch)) { return(false); } return(FindUpperBranchConnectionsThroughPasses(control, sourcePatch)); } else if (sourcePatch.SfcStepType == StepType.Pass) { PatchEntity leftPatch = control.Data.SfcEntity.Lookup(sourcePatch.X - 1, sourcePatch.Y); return(!HasUpperBranchConnection(sourcePatch, leftPatch)); } return(false); }
private static bool HasLowerBranchConnection(PatchEntity patch, PatchEntity leftPatch) { bool hasLowerLeftConnection = leftPatch != null && leftPatch.LowerBranch != BranchType.Unused; bool hasLowerRightConnection = patch.LowerBranch != BranchType.Unused; return(hasLowerLeftConnection || hasLowerRightConnection); }
/// <summary> /// Collects all alternative branches from this step. /// If it returns only one transition is not an alternative branch but a normal transition. /// </summary> private static List <SfcTransition> CollectUpperAlternativeBranches(SfcStep source, int patchId, ProgrammableLogicController pu) { List <SfcTransition> transitions = new List <SfcTransition>(); List <int> collected = Collector.CollectHorizontal(patchId, pu.SfcProgramData, BranchType.Single, true); foreach (int step in collected) { if (pu.SfcProgramData.SfcEntity.Lookup(step).ContainsTransition()) { SfcTransition transition = CreateTransition(step, pu); transition.DependingSteps.Add(source); transitions.Add(transition); } else { int lowerStepId = step + 1; PatchEntity lowerEntry = pu.SfcProgramData.SfcEntity.Lookup(lowerStepId); if (lowerEntry != null && lowerEntry.SfcStepType == StepType.Pass) { transitions.AddRange(CollectUpperAlternativeBranches(source, lowerStepId, pu)); } } } return(transitions); }
private static SfcStep CheckAlternative(PatchEntity lowerStep, SfcProgramData data) { switch (lowerStep.SfcStepType) { case StepType.StartingStep: case StepType.Step: return(data.ControlMap[lowerStep.Key]); case StepType.Jump: int reference = data.StepMaster.GetNameKey(lowerStep.StepName); return(data.ControlMap[reference]); case StepType.Pass: SfcStep foundStep = FindAlternativeMergeTarget(lowerStep.Key, data); if (foundStep != null) { return(foundStep); } break; case StepType.Unused: break; } return(null); }
/// <summary> /// The step name must be unique to create step references /// </summary> private void EnsureUniqueStepKey(PatchEntity data) { if (_patchNameMap.ContainsKey(data.StepName)) { data.StepName += "?"; EnsureUniqueStepKey(data); } }
private void AssignActionsFrom(PatchEntity source, IProcessingData context) { _actions = new Dictionary <ActionQualifier, List <AssignmentExpression> >(); foreach (ActionQualifier qualifier in (ActionQualifier[])Enum.GetValues(typeof(ActionQualifier))) { _actions.Add(qualifier, new List <AssignmentExpression>()); } for (int i = 0; i < source.ActionEntries.Count; i++) { AssignmentExpression expression = ActionMaster.InterpretTransitionText(source.ActionEntries[i].Action, context); _actions[source.ActionEntries[i].Qualifier].Add(expression); } }
/// <summary> /// Looks for left depending steps. /// </summary> private static void CollectLeftDependingSteps(int currentId, CollectorEntity entity) { int leftId = currentId - (1 << SfcEntity.XKeyShift); PatchEntity leftStep = entity.Data.SfcEntity.Lookup(leftId); if (leftStep != null) { if ((entity.UpperBranch && leftStep.UpperBranch == entity.TargetType) || (!entity.UpperBranch && leftStep.LowerBranch == entity.TargetType)) { entity.CollectedSteps.Add(leftId); CollectLeftDependingSteps(leftId, entity); } } }
/// <summary> /// Looks for right depending steps. /// </summary> private static void CollectRightDependingSteps(int currentId, CollectorEntity entity) { PatchEntity step = entity.Data.SfcEntity.Lookup(currentId); if ((entity.UpperBranch && step.UpperBranch == entity.TargetType) || (!entity.UpperBranch && step.LowerBranch == entity.TargetType)) { int rightId = currentId + (1 << SfcEntity.XKeyShift); if (entity.Data.SfcEntity.Lookup(rightId) != null) { entity.CollectedSteps.Add(rightId); CollectRightDependingSteps(rightId, entity); } } }
/// <summary> /// Checks if this patch can connect to a existing lower patch with: /// - Incoming line left/right /// - Transition form this patch /// </summary> private static bool CheckLowerStepConnection(SfcPatchControl control, bool skippedTransition) { PatchEntity lowerPatch = control.Master.Data.SfcEntity.Lookup(control.Data.X, control.Data.Y + 1); bool hasLowerActiveStep = lowerPatch != null && lowerPatch.SfcStepType != StepType.Unused; if (!hasLowerActiveStep) { return(false); } if (skippedTransition || control.Data.ContainsTransition()) { return(true); } PatchEntity leftPatch = control.Master.Data.SfcEntity.Lookup(control.Data.X - 1, control.Data.Y); return(HasLowerBranchConnection(control.Data, leftPatch)); }
private static PatchEntity FindSimultaneousTransition(List <int> patches, SfcProgramData data) { PatchEntity transitionPatch = null; foreach (int step in patches) { transitionPatch = data.SfcEntity.Lookup(step); if (transitionPatch != null && transitionPatch.ContainsTransition()) { break; } } if (transitionPatch == null) { Godot.GD.PushError("It is not allowed wo have Simultaneous branches without one transition!"); } return(transitionPatch); }
private static SfcStep FindAlternativeMergeTarget(int holder, SfcProgramData data) { List <int> collected = Collector.CollectHorizontal(holder, data, BranchType.Single, false); foreach (int step in collected) { int subId = step + 1; PatchEntity lowerStep = data.SfcEntity.Lookup(subId); if (lowerStep != null) { SfcStep target = CheckAlternative(lowerStep, data); if (target != null) { return(target); } } } return(null); }
/// <summary> /// Collects the list of lower simultaneous branches if possible. /// Null if there is an error in the diagram /// </summary> private static List <SfcStep> CollectLowerSimultaneousBranches(int holder, SfcProgramData data) { List <int> collected = Collector.CollectHorizontal(holder, data, BranchType.Double, false); List <SfcStep> targetSteps = new List <SfcStep>(); foreach (int step in collected) { int subId = step + 1; PatchEntity lowerStep = data.SfcEntity.Lookup(subId); if (lowerStep != null) { if (!FillSimultaneous(lowerStep, targetSteps, data)) { return(null); } } } return(targetSteps); }
/// <summary> /// Traverses down along passes and tries to find a patch with upper connections but without lower ones. /// </summary> private static bool FindUpperBranchConnectionsThroughPasses(Sfc2dEditorControl control, PatchEntity currentPatch) { PatchEntity lowerPatch = control.Data.SfcEntity.Lookup(currentPatch.X, currentPatch.Y + 1); bool hasLowerTransitionStep = lowerPatch != null && lowerPatch.SfcStepType == StepType.Pass; if (!hasLowerTransitionStep) { return(false); } PatchEntity leftPatch = control.Data.SfcEntity.Lookup(lowerPatch.X - 1, lowerPatch.Y); if (HasUpperBranchConnection(lowerPatch, leftPatch)) { return(true); } if (HasLowerBranchConnection(lowerPatch, leftPatch)) { return(false); } return(FindUpperBranchConnectionsThroughPasses(control, lowerPatch)); }
/// <summary> /// Looks for a connected lower step from this patch /// </summary> public static SfcStep FindLowerConnectedStep(int id, SfcProgramData data) { int subId = id + 1; PatchEntity lowerStep = data.SfcEntity.Lookup(subId); if (lowerStep != null) { if (data.SfcEntity.Lookup(lowerStep.Key).ContainsRealStep()) { return(data.ControlMap[lowerStep.Key]); } else if (lowerStep.SfcStepType == StepType.Pass) { return(FindLowerConnectedStep(lowerStep.Key, data)); } else if (lowerStep.SfcStepType == StepType.Jump) { int reference = data.StepMaster.GetNameKey(lowerStep.StepName); return(data.ControlMap[reference]); } } return(null); }
/// <summary> /// Collects all Simultaneous branches to merge from this step. /// null if there is none. /// </summary> private static List <SfcTransition> CollectUpperSimultaneousMerge(int sourceId, ProgrammableLogicController pu) { List <int> collected = Collector.CollectHorizontal(sourceId, pu.SfcProgramData, BranchType.Double, true); if (collected.Count <= 1) { PatchEntity currentPatch = pu.SfcProgramData.SfcEntity.Lookup(sourceId); int lowerId = sourceId + 1; PatchEntity lowerPatch = pu.SfcProgramData.SfcEntity.Lookup(lowerId); if (!currentPatch.ContainsTransition() && lowerPatch != null && lowerPatch.SfcStepType == StepType.Pass) { return(CollectUpperSimultaneousMerge(lowerId, pu)); } return(null); } PatchEntity transitionPatch = FindSimultaneousTransition(collected, pu.SfcProgramData); List <SfcStep> connectedSteps = CollectConnectedSteps(collected, pu.SfcProgramData); SfcTransition transition = CreateTransition(transitionPatch.Key, pu); transition.DependingSteps = connectedSteps; return(new List <SfcTransition> { transition }); }
public SfcStep(PatchEntity source) { Id = source.Key; }