Esempio n. 1
0
        internal string getInternalName(string actionName, string exceptionStackTrace, bool processLinks = true, params string[] linksConcerned)
        {
            TransitionLink transitionLink = getTransitionLinkByTransitionLabel(actionName);

            if (transitionLink != null)
            {
                string logic = transitionLink.logic;
                // Check logic expression
                if (ExpressionParser.isValid(transitionLink))
                {
                    List <List <string> > groupAndByOr = getPossibleSetOfLinks(actionName, exceptionStackTrace);

                    // If we have to process links and linksConcerned is empty and we have at least one OR statement into logic expression (i.e. at least 2 AND groups) => problem, developer has to specify the set of links concerned by this transition.
                    if (processLinks && linksConcerned.Length == 0 && groupAndByOr.Count > 1)
                    {
                        string availableCombination = "\nAvailable combination of links:\n";
                        foreach (List <string> ands in groupAndByOr)
                        {
                            availableCombination = availableCombination + " -";
                            foreach (string token in ands)
                            {
                                availableCombination = availableCombination + " " + token;
                            }
                            availableCombination = availableCombination + "\n";
                        }
                        throw new TraceAborted("Distributed logic expression for \"" + actionName + "\" action in \"" + this.gameObject.name + "\" Game Object contains \"+\" operator. You have to specify which links are concerned to perform this game action. " + availableCombination, exceptionStackTrace);
                    }
                    else
                    {
                        string prefix     = this.gameObject.name + "_";
                        bool   linksFound = false;
                        if (groupAndByOr.Count <= 1)
                        {
                            // If logic expression is empty or contains only AND operators, linksConcerned parameter is not useful because there is no ambiguity on this transition.
                            linksFound = true;
                            if (linksConcerned.Length
                                > 0)
                            {
                                WarningException we = new WarningException("Because logic expression includes only \"*\" operators, \"linksConcerned\" parameters are ignored. You can remove them to the call.", exceptionStackTrace);
                                Debug.LogException(we);
                            }
                        }
                        else
                        {
                            if (!processLinks)
                            {
                                // Developer wants to ignore linksConcerned. So we trace the first one (From Laalys point of view this is not a problem because all or actions have the same public name).
                                prefix     = "or0_" + prefix;
                                linksFound = true;
                            }
                            else
                            {
                                // Look for links concerned into distributed logic expression
                                List <string> linksConcerned_sorted = linksConcerned.ToList();
                                linksConcerned_sorted.Sort();
                                for (int i = 0; i < groupAndByOr.Count; i++)
                                {
                                    groupAndByOr [i].Sort();

                                    if (groupAndByOr [i].SequenceEqual(linksConcerned_sorted))
                                    {
                                        if (i > 0)
                                        {
                                            prefix = "or" + (i - 1) + "_" + prefix;
                                        }
                                        linksFound = true;
                                        break;
                                    }
                                }
                            }
                        }

                        if (linksFound)
                        {
                            return(prefix + actionName + "_" + this.id);
                        }
                        else
                        {
                            string debug = "";
                            foreach (string link in linksConcerned)
                            {
                                debug = debug + " \"" + link + "\"";
                            }

                            string availableCombination = "\nAvailable combination of links:\n";
                            foreach (List <string> ands in groupAndByOr)
                            {
                                availableCombination = availableCombination + " -";
                                foreach (string token in ands)
                                {
                                    availableCombination = availableCombination + " " + token;
                                }
                                availableCombination = availableCombination + "\n";
                            }
                            throw new TraceAborted(debug + " not found into distributed logic expression for \"" + actionName + "\" action in \"" + this.gameObject.name + "\" Game Object. " + availableCombination, exceptionStackTrace);
                        }
                    }
                }
                else
                {
                    throw new TraceAborted("Logic expression for \"" + actionName + "\" action in \"" + this.gameObject.name + "\" Game Object is not valid.", exceptionStackTrace);
                }
            }
            else
            {
                throw new TraceAborted("Action \"" + actionName + "\" is not monitored by \"" + this.gameObject.name + "\" Game Object.", exceptionStackTrace);
            }
        }
        private void GeneratePNandFeatures()
        {
            // List of full Petri nets
            // Key => Petri net name defined inside monitor.fullPn
            // Value => Pair <PetriNet, offsetX>
            Dictionary <string, KeyValuePair <PetriNet, float> > petriNets = new Dictionary <string, KeyValuePair <PetriNet, float> >();

            bool abort           = false;
            MonitoringManager mm = (MonitoringManager)target;

            // Fill final PN
            foreach (ComponentMonitoring monitor in Resources.FindObjectsOfTypeAll <ComponentMonitoring> ())
            {
                // Get full Petri net for this monitor
                if (monitor.fullPnSelected >= mm.PetriNetsName.Count)
                {
                    monitor.fullPnSelected = 0;
                }
                string fullName = mm.PetriNetsName[monitor.fullPnSelected];
                if (!petriNets.ContainsKey(fullName))
                {
                    petriNets[fullName] = new KeyValuePair <PetriNet, float>(new PetriNet(), 0);
                }
                PetriNet fullPn  = petriNets[fullName].Key;
                float    offsetX = petriNets[fullName].Value;

                // Check if PN exists
                if (monitor.PetriNet != null && !abort)
                {
                    // Make a copy of local PN in order to organise it spatially without changing original PN
                    PetriNet tmpPN = new PetriNet(monitor.PetriNet, monitor.gameObject.name);
                    tmpPN.addWidth(offsetX);
                    fullPn.addSubNet(tmpPN);

                    // Process links
                    foreach (TransitionLink transitionLink in monitor.transitionLinks)
                    {
                        // Check if all links target the same fullPn
                        foreach (Link curLink in transitionLink.links)
                        {
                            if (!curLink.isCompatibleWithPnName(monitor.fullPnSelected))
                            {
                                abort = true;
                                EditorUtility.DisplayDialog("Error, building aborted", "The action \"" + transitionLink.transition.label + "\" of monitor \"" + monitor.gameObject.name + " (ref: " + monitor.id + ")\" is linked with GameObject \"" + curLink.linkedObject.name + "\" (label: \"" + curLink.label + "\"). But these two elements are not affected to the same full Petri net.\n\nPlease review your configurations and try again.", "Close");
                            }
                        }

                        // Make a copy of current transition and prefix its name with its game object name
                        Node   curTransition_copy = new Node(transitionLink.transition);
                        string publicLabel        = curTransition_copy.label + " ";
                        if (curTransition_copy.overridedLabel != null && !curTransition_copy.overridedLabel.Equals(""))
                        {
                            publicLabel = curTransition_copy.overridedLabel + " ";
                        }
                        if (monitor is FamilyMonitoring)
                        {
                            publicLabel = publicLabel + ((FamilyMonitoring)monitor).equivalentName;
                        }
                        else
                        {
                            publicLabel = publicLabel + monitor.gameObject.name;
                        }
                        curTransition_copy.label = monitor.gameObject.name + "_" + curTransition_copy.label;

                        // Add this transition to Features
                        XmlHandler.addFeature(fullName, curTransition_copy.label + "_" + monitor.id, publicLabel, transitionLink.isSystemAction, transitionLink.isEndAction);

                        Node oldTransition = curTransition_copy;
                        if (isNullOrWhiteSpace(transitionLink.logic))
                        {
                            // Default : And of all link
                            foreach (Link curLink in transitionLink.links)
                            {
                                if (curLink.linkedObject != null)
                                {
                                    // Make a copy of linked place and prefix its name with its game object name
                                    Node linkedPlace = curLink.getPlace();
                                    if (linkedPlace != null)
                                    {
                                        Node linkedPlace_copy = new Node(linkedPlace);
                                        linkedPlace_copy.label = curLink.linkedObject.name + "_" + linkedPlace_copy.label;
                                        // Define arc type
                                        ArcType arcType = curLink.type == 2 ? Arc.stringToArcType(Arc.optType.ElementAt(curLink.flagsType)) : ArcType.regular;
                                        // Create arc between Transition and linked place (depends on Get/Produce/Require diffusion state)
                                        fullPn.arcs.Add(curLink.type != 1 ? new Arc(linkedPlace_copy, curTransition_copy, arcType, curLink.weight) : new Arc(curTransition_copy, linkedPlace_copy, arcType, curLink.weight));
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (ExpressionParser.isValid(transitionLink))
                            {
                                // Logic expression is valid

                                // Distribute expression
                                string[] exp = ExpressionParser.getDistribution(transitionLink.logic);

                                int or = 0;

                                // Parse distributed expression
                                foreach (string token in exp)
                                {
                                    // Check if current token is an operator
                                    if (!token.Equals("+") && !token.Equals("*"))
                                    {
                                        // It's not an operator => we load the link
                                        Link curLink = transitionLink.getLabeledLink(token);
                                        if (curLink.linkedObject != null)
                                        {
                                            // Make a copy of linked place and prefix its name with its game object name
                                            Node linkedPlace = curLink.getPlace();
                                            if (linkedPlace != null)
                                            {
                                                Node linkedPlace_copy = new Node(linkedPlace);
                                                linkedPlace_copy.label = curLink.linkedObject.name + "_" + linkedPlace_copy.label;
                                                // Define arc type
                                                ArcType arcType = curLink.type == 2 ? Arc.stringToArcType(Arc.optType.ElementAt(curLink.flagsType)) : ArcType.regular;
                                                // Create arc between Transition and linked place (depends on Get/Produce/Require diffusion state)
                                                fullPn.arcs.Add(curLink.type != 1 ? new Arc(linkedPlace_copy, curTransition_copy, arcType, curLink.weight) : new Arc(curTransition_copy, linkedPlace_copy, arcType, curLink.weight));
                                            }
                                        }
                                    }
                                    else if (token.Equals("+"))
                                    {
                                        // We detect OR operator => add a new transition and set it as current node

                                        // Build new transition, we keep old transition to build links after
                                        // Add offset to position
                                        curTransition_copy.position.x += offsetX;
                                        curTransition_copy.position.y += 50;
                                        curTransition_copy             = new Node("or" + (or++) + "_" + oldTransition.label, curTransition_copy.id, curTransition_copy.offset, curTransition_copy.initialMarking, curTransition_copy.position);
                                        // Add this new transition to PN
                                        fullPn.transitions.Add(curTransition_copy);
                                        // and to features
                                        XmlHandler.addFeature(fullName, curTransition_copy.label + "_" + monitor.id, publicLabel, transitionLink.isSystemAction, transitionLink.isEndAction);
                                        // Duplicate arcs from old transition
                                        foreach (Arc a in tmpPN.getConcernedArcs(oldTransition))
                                        {
                                            if (a.target.label.Equals(oldTransition.label))
                                            {
                                                fullPn.arcs.Add(new Arc(a.source, curTransition_copy, a.type, a.weight));
                                            }
                                            else if (a.source.label.Equals(oldTransition.label))
                                            {
                                                fullPn.arcs.Add(new Arc(curTransition_copy, a.target, a.type, a.weight));
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                UnityEngine.Debug.LogError("Petri Net Building aborted: Logic expression of \"" + transitionLink.transition.label + "\" action from \"" + monitor.gameObject.name + "\" is not valid => \"" + transitionLink.logic + "\". Please check it from Monitor edit view.");
                            }
                        }
                    }
                    petriNets[fullName] = new KeyValuePair <PetriNet, float>(fullPn, offsetX + monitor.PetriNet.getWidth() + 50);                   // Add spaces between PN
                }
            }

            if (!abort)
            {
                // Save all Petri nets
                foreach (KeyValuePair <string, KeyValuePair <PetriNet, float> > pn in petriNets)
                {
                    PnmlParser.SaveAtPath(pn.Value.Key, pn.Key + ".pnml");
                }
                // and features
                XmlHandler.saveFeatures();

                EditorUtility.DisplayDialog("Files built", "Files have been saved into \"completeNets\" and \"features\" folders of this Unity project", "Close");
            }
        }