//Created July 2016, refactored by Chien Si Harriman.  The tolerance checks are based on percentage tolerances, not absolute.
        public static bool TestSpaceVolumes(List<XmlDocument> gbXMLDocs, List<XmlNamespaceManager> gbXMLnsm, ref CampusReport cr, Conversions.volumeUnitEnum standardUnits, Conversions.volumeUnitEnum testUnits, double testvolConversion, double standardvolConversion, DOEgbXMLTestDetail testDetails, double tolerance)
        {

            string spaceId = String.Empty;
            Dictionary<string, double> standardFileVolumeDict = new Dictionary<string, double>();
            Dictionary<string, double> testFileVolumeDict = new Dictionary<string, double>();
            bool thinWalled = false;
            try
            {
                //check to see if the test file comes from OpenStudio or Bentley (non-thick wall, or non-centerline geometry)
                XmlNamespaceManager gbXMLnstw = gbXMLnsm[0];
                XmlNode productName = gbXMLDocs[0].SelectSingleNode("/gbXMLv5:gbXML/gbXMLv5:DocumentHistory/gbXMLv5:ProgramInfo/gbXMLv5:ProductName", gbXMLnstw);
                if (productName.InnerText.ToLower().Replace(" ", String.Empty).Trim() == "openstudio") //TODO: consider a different test
                {
                    thinWalled = true;
                }
                for (int i = 0; i < gbXMLDocs.Count; i++)
                {
                    XmlDocument gbXMLTestFile = gbXMLDocs[i];
                    XmlNamespaceManager gbXMLns = gbXMLnsm[i];

                    XmlNodeList spaceNodes = gbXMLDocs[i].SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space/gbXMLv5:Volume", gbXMLnsm[i]);
                    //make lists of the areas in each project
                    foreach (XmlNode spaceNode in spaceNodes)
                    {
                        string volume = spaceNode.InnerText;
                        if (i % 2 != 0)
                        {
                            for (int n = 0; n < spaceNode.ParentNode.Attributes.Count; n++)
                            {
                                if (spaceNode.ParentNode.Attributes[n].Name == "id")
                                {
                                    spaceId = spaceNode.ParentNode.Attributes[n].Value;
                                    if (!thinWalled)
                                    {
                                        //no conversion necessary
                                        standardFileVolumeDict.Add(spaceId, (Convert.ToDouble(volume) * standardvolConversion));
                                    }
                                    else
                                    {
                                        if(testDetails.ThinWalledSpecs.Count > 0)
                                        {
                                            var twSpec = testDetails.ThinWalledSpecs.Find(x => x.SpaceName == spaceId);
                                            standardFileVolumeDict.Add(spaceId, twSpec.Volume);
                                            break;
                                        }
                                        else
                                        {
                                            //no conversion necessary
                                            standardFileVolumeDict.Add(spaceId, (Convert.ToDouble(volume) * standardvolConversion));
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            for (int n = 0; n < spaceNode.ParentNode.Attributes.Count; n++)
                            {
                                if (spaceNode.ParentNode.Attributes[n].Name == "id")
                                {
                                    spaceId = spaceNode.ParentNode.Attributes[n].Value;
                                    double convertedValue = Convert.ToDouble(volume) * testvolConversion;
                                    testFileVolumeDict.Add(spaceId, convertedValue);
                                    break;
                                }
                            }
                        }
                    }
                }
                var standardKeys = standardFileVolumeDict.Keys;
                foreach (string key in standardKeys)
                {
                    logger.Info("SPACE ID:" + key);
                    //important, we don't make a new report unless one has already been created
                    DetailedSpaceSummary ds = new DetailedSpaceSummary();
                    if (cr.SpacesReport.Count() != 0) { 
                        var result = cr.SpacesReport.Find(x => x.ID == key);
                        if (result == null)
                        {
                            ds.ID = key;
                        }
                        else
                        {
                            ds = cr.SpacesReport.Find(x => x.ID == key);
                        }
                    }
                    else
                    {
                        ds.ID = key;
                    }
                    ds.VolumeUnits = "Cubic Feet";
                    if (testFileVolumeDict.ContainsKey(key))
                    {
                        double standardFileVolume = standardFileVolumeDict[key];
                        double testFileVolume = testFileVolumeDict[key];
                        ds.TotalVolume = standardFileVolume;
                        ds.TotalTestVolume = testFileVolume;
                        

                        double pctdifference = Math.Abs(testFileVolume - standardFileVolume)/standardFileVolume;
                        if (pctdifference == 0)
                        {
                            logger.Info("TEST FILE SUCCESS:PERFECT : " + key + ".  Success finding matching space volume.");
                            ds.FoundMatch = true;
                        }
                        else if (pctdifference <= tolerance)
                        {
                            logger.Info("TEST FILE SUCCESS: " + key + ".  Success finding matching space volume.");
                            ds.FoundMatch = true;
                        }
                        else
                        {
                            //at the point of failure, the test will return with details about which volume failed.
                            logger.Info("TEST FILE FAILURE: " + key + ".  Failure to find a volume match.");
                            ds.FoundMatch = false;
                            return false;
                        }
                    }
                    else
                    {
                        logger.Info("TEST FILE FAILURE: " + key + ".  Failure to find a volume match.");
                        //at the point of failure, the test will return with details about which volume failed.
                        logger.Info("PROGRAMMER's NOTE: Test File and Standard File space names could not be matched.  SpaceId: " + key + " could not be found in the test file.");
                        ds.FoundMatch = false;
                    }
                }
                var failures = cr.SpacesReport.FindAll(x => x.FoundMatch == false);
                return (failures.Count > 0) ? false : true;
            }

            catch (Exception e)
            {
                logger.Debug(e.ToString());
                logger.Fatal(" Failed to complete the Spaces Volume Test.  See exceptions noted.");
                return false;
            }
            logger.Fatal("Fatal Spaces Volume Test Failure");
            return false;
        }
        //created July 2016 by Chien Si Harriman, Independent Contractor
        public static bool TestSpaceAreas(List<XmlDocument> gbXMLDocs, List<XmlNamespaceManager> gbXMLnsm, ref CampusReport cr, Conversions.areaUnitEnum standardUnits, Conversions.areaUnitEnum testUnits, double testareaConversion, double standardareaConversion, DOEgbXMLTestDetail testDetails, double tolerance)
        {
            

            string spaceId = "";
            Dictionary<string, double> standardFileAreaDict = new Dictionary<string, double>();
            Dictionary<string, double> testFileAreaDict = new Dictionary<string, double>();
            bool thinWalled = false;
            try
            {
                //check to see if the test file comes from OpenStudio or Bentley (non-thick wall, or non-centerline geometry)
                XmlNamespaceManager gbXMLnstw = gbXMLnsm[0];
                XmlNode productName = gbXMLDocs[0].SelectSingleNode("/gbXMLv5:gbXML/gbXMLv5:DocumentHistory/gbXMLv5:ProgramInfo/gbXMLv5:ProductName", gbXMLnstw);
                if (productName.InnerText.ToLower().Replace(" ", String.Empty).Trim() == "openstudio")//TODO: consider a different test
                {
                    thinWalled = true;
                }
                for (int i = 0; i < gbXMLDocs.Count; i++)
                {
                    XmlDocument gbXMLTestFile = gbXMLDocs[i];
                    XmlNamespaceManager gbXMLns = gbXMLnsm[i];

                    XmlNodeList spaceNodes = gbXMLDocs[i].SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space/gbXMLv5:Area", gbXMLnsm[i]);
                    //make lists of the areas in each project
                    foreach (XmlNode spaceNode in spaceNodes)
                    {
                        string area = spaceNode.InnerText;
                        if (i % 2 != 0)
                        {
                            for (int n = 0; n < spaceNode.ParentNode.Attributes.Count; n++)
                            {
                                if (spaceNode.ParentNode.Attributes[n].Name == "id")
                                {
                                    spaceId = spaceNode.ParentNode.Attributes[n].Value;
                                    if (!thinWalled)
                                    {
                                        //no conversion necessary
                                        standardFileAreaDict.Add(spaceId, Convert.ToDouble(area) * standardareaConversion);
                                    }
                                    else
                                    {
                                        if(testDetails.ThinWalledSpecs.Count > 0)
                                        {
                                            var thinwalleddef = testDetails.ThinWalledSpecs.Find(x => x.SpaceName == spaceId); //it is critical that space names match for these tests.
                                            standardFileAreaDict.Add(spaceId, thinwalleddef.FloorArea);
                                        }
                                        else
                                        {
                                            //no conversion necessary
                                            standardFileAreaDict.Add(spaceId, Convert.ToDouble(area) * standardareaConversion);
                                        }
                                    }
                                    break;
                                }
                            }

                        }
                        else
                        {
                            for (int n = 0; n < spaceNode.ParentNode.Attributes.Count; n++)
                            {
                                if (spaceNode.ParentNode.Attributes[n].Name == "id")
                                {
                                    spaceId = spaceNode.ParentNode.Attributes[n].Value;

                                    double convertedArea = Convert.ToDouble(area) * testareaConversion;
                                    testFileAreaDict.Add(spaceId, convertedArea);
                                    break;
                                }
                            }

                        }
                    }
                }
                var standardKeys = standardFileAreaDict.Keys;

                foreach (string key in standardKeys)
                {
                    logger.Info("SPACE ID: " + key);
                    //important, we don't make a new report unless one has already been created
                    DetailedSpaceSummary ds = new DetailedSpaceSummary();
                    if (cr.SpacesReport.Count() != 0) { 
                        var res = cr.SpacesReport.Find(x => x.ID == key); 
                        if(res == null)
                        {
                            ds.ID = key;
                        }
                        else
                        {
                            ds = cr.SpacesReport.Find(x => x.ID == key);
                        }
                    }
                    else
                    {
                        ds.ID = key;
                    }
                    ds.AreaUnits = "SquareFeet";
                    if (testFileAreaDict.ContainsKey(key))
                    {
                        double testFileSpaceArea = testFileAreaDict[key];
                        double standardFileSpaceArea = standardFileAreaDict[key];
                        ds.TotalSurfaceArea = standardFileSpaceArea;
                        ds.TotalTestSurfaceArea = testFileSpaceArea;

                        double difference = Math.Abs(testFileSpaceArea - standardFileSpaceArea);
                        if (difference == 0)
                        {
                            logger.Info("TEST FILE SUCCESS:PERFECT : Found matching space area with an area = " + testFileSpaceArea.ToString("#.000") +" "+standardUnits+". ");
                            ds.FoundMatch = true;
                        }
                        else if (difference < tolerance)
                        {
                            logger.Info("TEST FILE SUCCESS: Found matching space area with an area = " + testFileSpaceArea.ToString("#.000") + " " + standardUnits + ".");
                            ds.FoundMatch = true;
                        }
                        else
                        {
                            logger.Info("TEST FILE FAILURE: " + key + ".  Failure to find an space area match.");
                            ds.FoundMatch = false;
                        }
                    }
                    else
                    {
                        logger.Info("TEST FILE FAILURE: "+key +" Could not be matched");
                        //failure to match spaceIds
                        logger.Info("Test File and Standard File space names could not be matched.  SpaceId: " + key + " could not be found in the test file.");
                        ds.FoundMatch = false;
                        return false;
                    }
                    cr.SpacesReport.Add(ds);
                }
            }

            catch (Exception e)
            {
                logger.Debug(e.ToString());
                logger.Fatal("Failed to complete the Space Area Test.  See exceptions noted.");
                return false;
            }
            return true;
        }