private void SortLeafFactors(List <FactorItem> leafFactorItems)
        {
            //move from the back, push factors that point to folders to the front.
            //make sure you stop before overlapping the start again
            //then reset the next items on each factor
            int idx = leafFactorItems.Count - 1;

            for (int i = leafFactorItems.Count - 1; i >= 0; --i)
            {
                if (leafFactorItems[idx].FactorComponent.Type == "folder")
                {
                    FactorItem tmp = leafFactorItems[idx];
                    leafFactorItems.RemoveAt(idx);
                    leafFactorItems.Insert(0, tmp);
                }
                else
                {
                    --idx;
                }
            }
            int iNext = 0;

            for (; iNext < leafFactorItems.Count - 1; ++iNext)
            {
                leafFactorItems[iNext].NextItem = leafFactorItems[iNext + 1];
            }
            if (iNext < leafFactorItems.Count)
            {
                leafFactorItems[iNext].NextItem = null;
            }
        }
        public List <FactorItem> BuildFactorItems(Component factorial, string SimulationPath)
        {
            //read options
            XmlNode varNode = factorial.ContentsAsXML.SelectSingleNode("//settings");

            SaveExtraInfoInFilename = false;
            if (XmlHelper.Attribute(varNode, "fn") == "1")
            {
                SaveExtraInfoInFilename = true;
            }

            TitleIsSingleLine = true;
            if (XmlHelper.Attribute(varNode, "tl") == "1")
            {
                TitleIsSingleLine = false;
            }

            useFQKeys = false;
            if (XmlHelper.Attribute(varNode, "fqKeys") == "1")
            {
                useFQKeys = true;
            }

            List <FactorItem> factorItems = new List <FactorItem>();
            List <Component>  leaves      = new List <Component>();

            FindLeaves(factorial, leaves);
            if (leaves.Count() > 0)
            {
                //leaves require a different way of calculating the factors
                //they work from the final leaf and then work back up the tree using parents
                //the difficult path is work out inheritance, so need to create the list, and then process it?
                foreach (var leaf in leaves)
                {
                    //build a list of factors for each leaf - work up through it's parents
                    bool folderlevel = true;
                    List <FactorItem> leafFactorItems = new List <FactorItem>();
                    ProcessAdvancedFactorItems(leaf, leafFactorItems, folderlevel, SimulationPath);
                    SortLeafFactors(leafFactorItems);
                    if (leafFactorItems.Count > 0)
                    {
                        factorItems.Add(leafFactorItems[0]);
                    }
                }
            }
            else
            {
                FactorItem lastItem = null;
                ProcessFactorNodes(factorial, ref lastItem, ref factorItems, SimulationPath);
            }
            return(factorItems);
        }
        public static string simulationName(bool saveExtraInfoInFilename, string rootName, SortedDictionary <string, string> factorsList, int counter, int totalCount)
        {
            string result = rootName;

            if (saveExtraInfoInFilename)
            {
                result += ";" + FactorItem.ToKVString(factorsList);
            }
            else
            {
                //write a spacer to list sims in order eg: 01 or 001 or 0001 depending on count
                string sPad = "";
                double tot  = Math.Floor(Math.Log10(totalCount) + 1);
                double file = Math.Floor(Math.Log10(counter) + 1);
                for (int i = 0; i < (int)(tot - file); ++i)
                {
                    sPad += "0";
                }

                result += "_" + sPad + counter;
            }
            return(result);
        }
        private static string CreateJobFromSimulation(Component Simulation, SortedDictionary <string, string> factorsList, bool titleIsSingleLine, string destFolder)
        {
            //add title line into simulation
            //find all components that are outputfiles... or use xml?
            List <Component> outputfiles = new List <Component>();

            AddOutputFilesToList(Simulation, outputfiles);
            foreach (Component comp in outputfiles)
            {
                // Ensure the output name is correct for this simulation
                XmlNode compNode = comp.ContentsAsXML;
                XmlNode fileNode = compNode.SelectSingleNode("//filename");
                if (fileNode != null)
                {
                    fileNode.InnerText = ComponentUtility.CalcFileName(comp);
                }
                else
                {
                    throw new Exception("Cant find an outputfile filename node!");
                }

                if (titleIsSingleLine)
                {
                    //Title node is now read only, so need to add this as a constant
                    //XmlNode titleNode = compNode.SelectSingleNode("//title");
                    //if (titleNode != null)
                    //    titleNode.InnerText = factorsList;
                    //else
                    //    throw new Exception("Cant find an outputfile title node!");
                    Component constantsComponent = null;
                    foreach (Component c in comp.ChildNodes)
                    {
                        if (c.Type == "variables")
                        {
                            constantsComponent = c;
                        }
                    }
                    if (constantsComponent == null)
                    {
                        throw new Exception("No variables in outputfile!");
                    }

                    XmlNode componentNode = constantsComponent.ContentsAsXML;
                    XmlNode constantsNode = componentNode.SelectSingleNode("//constants");
                    if (constantsNode == null)
                    {
                        constantsNode = componentNode.OwnerDocument.CreateElement("constants");
                        componentNode.AppendChild(constantsNode);
                    }
                    XmlNode factorNode = constantsNode.SelectSingleNode("//constant[@name='factors']");
                    if (factorNode == null)
                    {
                        factorNode = constantsNode.OwnerDocument.CreateElement("constant");
                        constantsNode.AppendChild(factorNode);
                    }
                    XmlHelper.SetAttribute(factorNode, "name", "factors");
                    factorNode.InnerText        = FactorItem.ToKVString(factorsList);
                    constantsComponent.Contents = componentNode.OuterXml;
                }
                else
                {
                    //Find the variables node (should be a child of the output file - it will find and use the first one
                    Component constantsComponent = null;
                    foreach (Component c in comp.ChildNodes)
                    {
                        if (c.Type == "variables")
                        {
                            constantsComponent = c;
                        }
                    }
                    if (constantsComponent == null)
                    {
                        throw new Exception("No variables in outputfile!");
                    }

                    XmlNode componentNode = constantsComponent.ContentsAsXML;
                    XmlNode constantsNode = componentNode.SelectSingleNode("//constants");
                    if (constantsNode == null)
                    {
                        constantsNode = componentNode.OwnerDocument.CreateElement("constants");
                        componentNode.AppendChild(constantsNode);
                    }
                    else
                    {
                        //clean out existing nodes - will remove existing constants
                        constantsNode.RemoveAll();
                    }

                    foreach (string factor in factorsList.Keys)
                    {
                        XmlNode factorNode = constantsNode.OwnerDocument.CreateElement("constant");
                        constantsNode.AppendChild(factorNode);
                        XmlHelper.SetAttribute(factorNode, "name", factor);
                        factorNode.InnerText = factorsList[factor];
                    }
                    constantsComponent.Contents = componentNode.OuterXml;
                }
                comp.Contents = compNode.OuterXml;
            }
            string currDirectory = Directory.GetCurrentDirectory();

            if (destFolder != "" && Directory.Exists(destFolder))
            {
                Directory.SetCurrentDirectory(destFolder);
            }

            string SimFileName = ApsimToSim.WriteSimFile(Simulation, Configuration.getArchitecture(), false);

            Directory.SetCurrentDirectory(currDirectory);

            return(SimFileName);
        }
        private void ProcessAdvancedFactorItems(Component leaf, List <FactorItem> factorItems, bool folderlevel, string simulationPath)
        {
            List <string> variableTypes = new List <string>();

            LoadVariableTypes(Types.Instance.MetaDataNode("Factor", "FactorVariables"), variableTypes);

            //add any childnodes that are factors
            var result = (from c in leaf.ChildNodes
                          where c.Type == "factor" && c.ContentsAsXML.SelectSingleNode("targets") != null
                          select c);

            foreach (var factor in result)
            {
                List <string> targets = new List <string>();
                string        spath   = simulationPath + "/";
                foreach (XmlNode node in factor.ContentsAsXML.SelectSingleNode("//targets").ChildNodes)
                {
                    if (node.InnerText.Contains(spath))
                    {
                        targets.Add(node.InnerText);
                    }
                }
                if (targets.Count > 0)
                {
                    //manager factor or normal
                    if (factor.ChildNodes.Count == 1 && variableTypes.Contains(factor.ChildNodes[0].Type.ToLower()))
                    {
                        XmlNodeList varNodes = factor.ContentsAsXML.SelectNodes("//vars/*");
                        foreach (XmlNode node in varNodes)
                        {
                            ManagerFactorItem item = new ManagerFactorItem(this);
                            item.Targets         = targets;
                            item.FactorComponent = factor;
                            item.Variable        = node;
                            string[] pars        = node.InnerText.Split(new char[] { ',' });
                            var      unique_pars = new HashSet <string>(pars.Select(x => x.Trim(new char[] { '\"', ' ' })));
                            item.Parameters = unique_pars.OrderBy(a => a).ToList <string>();
                            if ((from f in factorItems
                                 where f.getDesc() == item.getDesc()
                                 select f).Count() == 0)
                            {
                                if (factorItems.Count > 0)
                                {
                                    item.NextItem = factorItems[0];
                                }
                                factorItems.Insert(0, item);
                            }
                        }
                    }
                    else
                    {
                        FactorItem item = new FactorItem(this);
                        item.Targets         = targets;
                        item.FactorComponent = factor;
                        if ((from f in factorItems
                             where f.getDesc() == item.getDesc()
                             select f).Count() == 0)
                        {
                            if (factorItems.Count > 0)
                            {
                                item.NextItem = factorItems[0];
                            }
                            factorItems.Insert(0, item);
                        }
                    }
                }
            }
            if (leaf.Parent != null && leaf.Parent.Parent != null)
            {//PArent.Parent is to check against the root node
                if (leaf.Parent.Type == "folder" && folderlevel)
                {
                    //parent is a factorfolder
                    FactorItem item = new FactorItem(this);
                    //item.Targets = targets;
                    item.FactorComponent = leaf.Parent;
                    item.FolderLevel     = leaf.Name;
                    if ((from f in factorItems
                         where f.getDesc() == item.getDesc()
                         select f).Count() == 0)
                    {
                        if (factorItems.Count > 0)
                        {
                            item.NextItem = factorItems[0];
                        }
                        factorItems.Insert(0, item);
                    }
                }
                ProcessAdvancedFactorItems(leaf.Parent, factorItems, !folderlevel, simulationPath);
            }
        }
 public void ProcessFactorNodes(Component parentComponent, ref FactorItem lastItem, ref List <FactorItem> items, string SimulationPath)
 {
     foreach (Component comp in parentComponent.ChildNodes)
     {
         if (comp.Type == "factor")
         {
             List <string> targets = new List <string>();
             XmlNode       varNode = comp.ContentsAsXML.SelectSingleNode("//targets");
             if (varNode != null)
             {
                 foreach (XmlNode target in varNode.ChildNodes)
                 {
                     string spath = SimulationPath + "/";
                     if (target.InnerText.Contains(spath))
                     {
                         targets.Add(target.InnerText);
                     }
                 }
             }
             if (targets.Count > 0)
             {
                 List <string> variableTypes = new List <string>();
                 LoadVariableTypes(Types.Instance.MetaDataNode("Factor", "FactorVariables"), variableTypes);
                 if (comp.ChildNodes.Count == 1 && variableTypes.Contains(comp.ChildNodes[0].Type.ToLower()))
                 {//(comp.ChildNodes[0].Type == "manager" || comp.ChildNodes[0].Type == "rule" || comp.ChildNodes[0].Type == "cropui"))
                     //process variables within manager code
                     XmlNodeList varNodes = comp.ContentsAsXML.SelectNodes("//vars/*");
                     foreach (XmlNode node in varNodes)
                     {
                         ManagerFactorItem item = new ManagerFactorItem(this);
                         item.Targets         = targets;
                         item.FactorComponent = comp;
                         item.Variable        = node;
                         string[] pars = node.InnerText.Split(new char[] { ',' });
                         pars = pars.Select(x => x.Trim(new char[] { '\"', ' ' })).ToArray();
                         var unique_pars = new HashSet <string>(pars);
                         item.Parameters = unique_pars.OrderBy(a => a).ToList <string>();
                         if (lastItem == null)
                         {
                             items.Add(item);
                         }
                         else
                         {
                             lastItem.NextItem = item;
                         }
                         lastItem = item;
                     }
                 }
                 else
                 {
                     FactorItem item = new FactorItem(this);
                     item.Targets         = targets;
                     item.FactorComponent = comp;
                     if (lastItem == null)
                     {
                         items.Add(item);
                     }
                     else
                     {
                         lastItem.NextItem = item;
                     }
                     lastItem = item;
                 }
             }
         }
         else
         {
             ProcessFactorNodes(comp, ref lastItem, ref items, SimulationPath);
         }
     }
 }