/// <summary>
        /// Generate a ruleset for use in a XML PTPPRJ File
        /// </summary>
        /// <param name="ruleElementName"></param>
        /// <param name="ruleSet"></param>
        /// <returns></returns>
        private XElement CreateXMLRules(string ruleElementName, RuleAttributeSet ruleSet)
        {
            XElement Rules = new XElement(ruleElementName);
            XElement Rule  = new XElement("Rule");

            Rule.SetAttributeValue("name", ruleSet.name);
            Rule.SetAttributeValue("format", ruleSet.format);
            Rule.SetAttributeValue("stop_execution", ruleSet.stop_execution);
            Rule.SetAttributeValue("disabled", ruleSet.disabled);
            Rule.SetAttributeValue("hidesm", ruleSet.hidesm);
            Rule.SetAttributeValue("boolean", ruleSet.boolean);
            Rule.SetAttributeValue("excluded", ruleSet.excluded);
            Rule.SetAttributeValue("hidden", ruleSet.hidden);
            Rule.SetAttributeValue("format_settings", ruleSet.format_settings);
            Rule.SetAttributeValue("description", ruleSet.description);
            foreach (RuleExpressionGroup eg in ruleSet.expressionGroups)
            {
                XElement PMPExpressionGroup = new XElement("ExpressionGroup");
                PMPExpressionGroup.SetAttributeValue("boolean", eg.boolean);
                foreach (RuleExpression e in eg.expressions)
                {
                    XElement RuleExpression = new XElement("Expression");
                    RuleExpression.SetAttributeValue("comparison_value", e.comparison_value);
                    RuleExpression.SetAttributeValue("predicate", e.predicate);
                    RuleExpression.SetAttributeValue("property", e.property);
                    PMPExpressionGroup.Add(RuleExpression);
                }
                Rule.Add(PMPExpressionGroup);
            }
            Rules.Add(Rule);
            return(Rules);
        }
        /// <summary>
        /// Generate the XML for the Basic PTPPRJ
        /// </summary>
        public void Generate()
        {
            // Base Project element for storing all project settings.
            _project = new XElement("Project");
            _project.SetAttributeValue("model", "MODEL_ITU");
            _project.SetAttributeValue("default_subscriber_height", _settings.SmHeight.ToString());

            // Rule used by the Link and PMP for performance issues
            var RuleAttribs = new RuleAttributeSet
            {
                name             = "Does not meet requirements",
                format           = "1",
                stop_execution   = "0",
                disabled         = "0",
                hidesm           = "0",
                boolean          = "any",
                excluded         = "0",
                hidden           = "0",
                format_settings  = "{\"colour\": \"#ff0000\"}",
                description      = "Link fails to meet performance requirements or has warnings",
                expressionGroups = new RuleExpressionGroup[] {
                    new RuleExpressionGroup {
                        boolean     = "any",
                        expressions = new RuleExpression[] {
                            new RuleExpression {
                                comparison_value = "False",
                                predicate        = "equal to",
                                property         = "link_ok"
                            }
                        }
                    }
                }
            };

            // Rule used for the AP if it has warnings
            var APRuleAttribs = new RuleAttributeSet
            {
                name             = "Has warnings",
                format           = "1",
                stop_execution   = "0",
                disabled         = "0",
                hidesm           = "0",
                boolean          = "any",
                excluded         = "0",
                hidden           = "0",
                format_settings  = "{\"colour\": \"#ff000096\", \"text_colour\": \"#ff0000\"}",
                description      = "The access point has warnings",
                expressionGroups = new RuleExpressionGroup[] {
                    new RuleExpressionGroup {
                        boolean     = "any",
                        expressions = new RuleExpression[] {
                            new RuleExpression {
                                comparison_value = "False",
                                predicate        = "equal to",
                                property         = "is_ok"
                            }
                        }
                    }
                }
            };

            // Create XML TddSyncGroups
            XElement TddSyncGroups = new XElement("TddSyncGroups", CreateXMLTddGroup(0, 0, true));

            // Setup best server settings (not 100% sure on these but this is default)
            XElement BestServer = new XElement("BestServer", CreateXMLSubVariant(0, "pmp450_qpsk_mimo_a", 10, "PMP-450"));

            // Create XML Entries for all known Towers
            XElement Towers = new XElement("Places", _towers.Select(tower => CreateXMLTowerPlaces(tower)));

            // Create XML Entries for all known Subscribers
            XElement SubscriberPlaces = new XElement("SubscriberPlaces", _subscribers.Select(sm => CreateXMLSubscriberPlaces(sm)));

            // Create XML Hubs for all
            XElement Hubs = new XElement("Hubs", _towers.Select(tower => CreateXMLHub(tower)));

            // Add elements to project
            _project.Add(
                TddSyncGroups,
                CreateXMLRules("Rules", RuleAttribs),
                CreateXMLRules("PMPRules", RuleAttribs),
                CreateXMLRules("APRule", APRuleAttribs),
                BestServer,
                Towers,
                SubscriberPlaces,
                Hubs);
        }