public static CampusReport UploadTest(HttpContext context)
        {
            var r = context;
            CampusReport c = new CampusReport();
            //if there is a file
            //valadate it by pass in input stream as xmlreader

            return c;
        }
        public void StartTest(XmlReader xmldoc, string testToRun, ref gbXMLReport gbr, string username = "******")
        {
            
            log4net.Config.XmlConfigurator.Configure();

            TestToRun = testToRun;
            globalMatchObject = new gbXMLMatches();
            globalMatchObject.Init();

            //first create a list of lists that is indexed identically to the drop down list the user selects
            TestDetail = new DOEgbXMLTestDetail();
            //then populate the list of lists.  All indexing is done "by hand" in InitializeTestResultStrings()
            TestDetail.InitializeTestResultStrings();

            //create report list reportlist will store all the test result
            ReportList = new List<DOEgbXMLReportingObj>();

            //Load an XML File for the test at hand
            gbXMLTestFile = new XmlDocument();
            gbXMLTestFile.Load(xmldoc);

            gbXMLStandardFile = new XmlDocument();
            gbXMLStandardFile.Load(filepaths[TestToRun]);
            
            
            if (!TestFileIsAvailable())
            {
                //TODO:  update browser json with something to indicate there is a problem
                return;
            }
                

            //Define the namespace
            XmlNamespaceManager gbXMLns1 = new XmlNamespaceManager(gbXMLTestFile.NameTable);
            gbXMLns1.AddNamespace("gbXMLv5", "http://www.gbxml.org/schema");
            XmlNamespaceManager gbXMLns2 = new XmlNamespaceManager(gbXMLStandardFile.NameTable);
            gbXMLns2.AddNamespace("gbXMLv5", "http://www.gbxml.org/schema");

            List<XmlDocument> gbXMLdocs = new List<XmlDocument>();
            gbXMLdocs.Add(gbXMLTestFile);
            gbXMLdocs.Add(gbXMLStandardFile);
            List<XmlNamespaceManager> gbXMLnsm = new List<XmlNamespaceManager>();
            gbXMLnsm.Add(gbXMLns1);
            gbXMLnsm.Add(gbXMLns2);
            
            //standardizing all tests on US-IP
            Conversions c = new Conversions();
            Conversions.volumeUnitEnum testVol = Conversions.volumeUnitEnum.CubicFeet;
            Conversions.volumeUnitEnum validatorVol = Conversions.volumeUnitEnum.CubicFeet;
            Conversions.areaUnitEnum testArea = Conversions.areaUnitEnum.SquareFeet;
            Conversions.areaUnitEnum validatorArea = Conversions.areaUnitEnum.SquareFeet;
            Conversions.lengthUnitEnum testLength = Conversions.lengthUnitEnum.Feet;
            Conversions.lengthUnitEnum validatorLength = Conversions.lengthUnitEnum.Feet;

            Conversions.lengthUnitEnum standardLength = Conversions.lengthUnitEnum.Feet;
            Conversions.areaUnitEnum standardArea = Conversions.areaUnitEnum.SquareFeet;
            Conversions.volumeUnitEnum standardVol = Conversions.volumeUnitEnum.CubicFeet;

            //standardize all units to feet, square feet, and cubic feet
            double testlengthConversion = 1;
            double testareaConversion = 1;
            double testvolumeConversion = 1;
            double standardlengthConversion = 1;
            double standardareaConversion = 1;
            double standardvolConversion = 1;

            bool mustBePlanar = false;

            for(int ns=0; ns< gbXMLnsm.Count; ns++)
            {
                if (ns == 0)
                {
                    XmlNodeList nodes = gbXMLdocs[ns].SelectNodes("/gbXMLv5:gbXML", gbXMLnsm[ns]);
                    StandardizeToUSIP(nodes, c, ref testlengthConversion, ref testareaConversion, ref testvolumeConversion, ref testLength, ref testArea, ref testVol);
                }
                else
                {
                    XmlNodeList nodes = gbXMLdocs[ns].SelectNodes("/gbXMLv5:gbXML", gbXMLnsm[ns]);
                    StandardizeToUSIP(nodes, c, ref standardlengthConversion, ref standardareaConversion, ref standardvolConversion, ref standardLength, ref standardArea, ref standardVol);
                }
            }
            
           //TODO:  Add a summary of the Unit of Measures stuff above to the final result

            //Create a Log file that logs the success or failure of each test.
            //Eventually maybe I want to create a little HTML factory

            output = "";
            log = "";
            table += "<div class='container'>" +
                    "<h3>" + "Test Sections" + "</h3>";
            table += "<table class='table table-bordered'>";
            table += "<tr class='info'>" +
                                   "<td>" + "Test Section Name" + "</td>" +
                                   "<td>" + "Standard Result" + "</td>" +
                                   "<td>" + "Test File Result" + "</td>" +
                                   "<td>" + "Tolerances" + "</td>" +
                                   "<td>" + "Pass/Fail" + "</td>" +
                                   "</tr>";

            string units;
            DOEgbXMLReportingObj report = new DOEgbXMLReportingObj();
            CampusReport camprep = new CampusReport();

            //this string I can manipulate to produce the final test output
            string menujson = JsonConvert.SerializeXmlNode(gbXMLStandardFile);
            //prepare json for view
            menujson = MakeViewJson(menujson);

            gbr.menu = menujson;
            gbr.CampusReport = camprep;

            report.standResult = new List<string>();
            report.testResult = new List<string>();
            report.idList = new List<string>();
            report.MessageList = new List<string>();
            report.TestPassedDict = new Dictionary<string, bool>();

            //Set up the Global Pass/Fail criteria for the test case file
            TestCriteria = new DOEgbXMLTestCriteriaObject();
            TestCriteria.InitializeTestCriteriaWithTestName(testToRun);
            //needed specially for area and volume tests
            DOEgbXMLTestDetail afile = TestDetail.TestDetailList.Find(x => x.testName == TestToRun);

            BuildingSummary bs = new BuildingSummary();
            bs.FileType = "Standard";
            camprep.BuildingSummary.Add(bs);
            BuildingSummary bst = new BuildingSummary();
            bst.FileType = "Test";
            camprep.BuildingSummary.Add(bst);
            //Test 2 execute
            //report.tolerance = DOEgbXMLBasics.Tolerances.AreaTolerance;
            //report.testType = TestType.Building_Area;
            //units = DOEgbXMLBasics.MeasurementUnits.sqft.ToString();
            //report = GetBuildingArea(gbXMLdocs, gbXMLnsm, report, validatorArea, testArea, testareaConversion, standardareaConversion);
            logger.Info("START: BUILDING AREA TEST");
            var baresult = GetBuildingArea(gbXMLdocs, gbXMLnsm, ref camprep, validatorArea, testArea, testareaConversion, standardareaConversion, DOEgbXMLBasics.Tolerances.AreaPercentageTolerance, afile );
            if(!baresult)
            {
                camprep.BuildingSummary.Find(x => x.FileType == "Standard").PassedAllTests = false;
            }
            logger.Info("END: BUILDING AREA TEST");

            //GetBuildingArea(gbXMLdocs,gbXMLnsm,)
            //AddToOutPut("Building Area Test Passed: ", report, true);

            //Test 3 execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.SpaceCountTolerance;
            //report.testType = TestType.Space_Count;
            //units = DOEgbXMLBasics.MeasurementUnits.spaces.ToString();
            //report = GetBuildingSpaceCount(gbXMLdocs, gbXMLnsm, report, units);
            logger.Info("START: BUILDING SPACE COUNT TEST");
            SpacesSummary ssm = new SpacesSummary();
            ssm.FileType = "Standard";
            camprep.SpacesSummary.Add(ssm);
            SpacesSummary ssmt = new SpacesSummary();
            ssmt.FileType = "Test";
            camprep.SpacesSummary.Add(ssmt);
            var spctResult = GetBuildingSpaceCount(gbXMLdocs, gbXMLnsm, "", DOEgbXMLBasics.Tolerances.SpaceCountTolerance, ref camprep);
            if(!spctResult)
            {
                camprep.BuildingSummary.Find(x => x.FileType == "Standard").PassedAllTests = false;
                camprep.SpacesSummary.Find(x => x.FileType == "Standard").PassedAllTests = false;
            }
            logger.Info("END: BUILDING SPACE COUNT TEST");
            //AddToOutPut("Building Space Quantity Count Test Passed: ", report, true);

            // Building Stories Tests....
            ////Test 4 execute
            //report.Clear();
            report.tolerance = DOEgbXMLBasics.Tolerances.LevelCountTolerance;
            //report.testType = TestType.Building_Story_Count;
            //units = DOEgbXMLBasics.MeasurementUnits.levels.ToString();
            //report = GetBuildingStoryCount(gbXMLdocs, gbXMLnsm, report, units);
            logger.Info("START: Building Storey Count Test");
            var blstctresult = GetBuildingStoryCount(gbXMLdocs, gbXMLnsm, ref camprep, DOEgbXMLBasics.Tolerances.LevelCountTolerance);
            if(!blstctresult)
            {
                camprep.BuildingSummary.Find(x => x.FileType == "Standard").PassedAllTests = false;
                //TODO: Need a Building Story Summary Field
            }
            logger.Info("END: Building Storey Count Test");
            //AddToOutPut("Building Story Count Test Passed: ", report, true);


            //Test 5 execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.LevelHeightTolerance;
            //report.testType = TestType.Building_Story_Z_Height;
            //units = DOEgbXMLBasics.MeasurementUnits.ft.ToString();
            report = GetStoryHeights(gbXMLdocs, gbXMLnsm, report, validatorLength, testLength, testlengthConversion, standardlengthConversion);
            logger.Info("START: Building Storey Height Test");
            var storyHeightsres = GetStoryHeights(gbXMLdocs, gbXMLnsm, ref camprep, validatorLength, testLength, testlengthConversion, standardlengthConversion, DOEgbXMLBasics.Tolerances.LevelHeightTolerance);
            if (!storyHeightsres)
            {
                camprep.BuildingSummary.Find(x => x.FileType == "Standard").PassedAllTests = false;
                //TODO: Need a Building Story Summary Field
            }
            logger.Info("END: Building Storey Height Test");
            //AddToOutPut("Building Story Z-Height Test: ", report, true);


            //Test 6 execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.VectorAngleTolerance;
            //report.testType = TestType.Building_Story_PolyLoop_RHR;
            //units = "degrees";
            //report = TestBuildingStoryRHR(gbXMLdocs, gbXMLnsm, report, units);
            logger.Info("START: Building Story Right Hand Rule Test.");
            var blstRHResult = TestBuildingStoryRHR(gbXMLdocs, gbXMLnsm, ref camprep);
            if(!blstRHResult)
            {
                //this method has no bearing on the overall pass or fail tests.
                //camprep.BuildingSummary.Find(x => x.FileType == "Standard").PassedAllTests = false;
                //TODO: Need a Building Story Summary Field
            }
            logger.Info("END: Building Story Right Hand Rule Test.");
            //AddToOutPut("Building Story PolyLoop Right Hand Rule Test Result:", report, true);


            //String spShellGeometrySurfaceNum = TestShellGeomSurfaceNum(gbXMLTestFile, gbXMLns);

            //Space Tests .............................................................
            //Test 7 execute
            //only needs to test the test file
            //report.Clear();
            //report.testType = TestType.SpaceId_Match_Test;
            logger.Info("START: UNIQUE SPACE ID TEST");
            var spaceIDresults = UniqueSpaceIdTest(gbXMLdocs, gbXMLnsm, ref camprep);
            if(!spaceIDresults)
            {
                camprep.SpacesSummary.Find(x => x.FileType == "Standard").PassedAllTests = false;
            }
            logger.Info("END: UNIQUE SPACE ID TEST");
            //AddToOutPut("SpaceId Match Test: ", report, true);

            
            //Test 8 execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.SpaceAreaTolerance;
            //report.testType = TestType.Space_Area;
            //units = DOEgbXMLBasics.MeasurementUnits.sqft.ToString();
            logger.Info("START: SPACE AREAS TEST");
            //report = TestSpaceAreas(gbXMLdocs, gbXMLnsm, report, validatorArea, testArea, testareaConversion,standardareaConversion,afile);
            var result = TestSpaceAreas(gbXMLdocs, gbXMLnsm, ref camprep, validatorArea, testArea, testareaConversion, standardareaConversion, afile, DOEgbXMLBasics.Tolerances.SpaceAreaTolerance);
            if(!result)
            {
                camprep.SpacesSummary.Find(x => x.FileType == "Standard").PassedAllTests = false;
                //gbxml detailed compliance results?
            }
            logger.Info("END: SPACE AREAS TEST");
            //AddToOutPut("Space Areas Test: ", report, true);


            //Test 9 execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.VolumeTolerance;
            //report.testType = TestType.Space_Volume;
            //units = DOEgbXMLBasics.MeasurementUnits.cubicft.ToString();
            logger.Info("START: SPACE VOLUMES TEST");
            //report = TestSpaceVolumes(gbXMLdocs, gbXMLnsm, report, validatorVol, testVol, testvolumeConversion,standardvolConversion,afile);
            var volresult = TestSpaceVolumes(gbXMLdocs, gbXMLnsm, ref camprep, validatorVol, testVol, testvolumeConversion, standardvolConversion, afile, DOEgbXMLBasics.Tolerances.VolumePercentageTolerance);
            logger.Info("END: SPACE VOLUMES TEST");
            if (!volresult)
            {
                camprep.SpacesSummary.Find(x => x.FileType == "Standard").PassedAllTests = false;
                //gbxml detailed compliance results?
            }
            //AddToOutPut("Space Volumes Test: ", report, true);


            //Test 10 Execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.VectorAngleTolerance;
            //report.testType = TestType.Shell_Geom_RHR;
            //units = "degrees";
            //report = TestShellGeomPLRHR(gbXMLdocs, gbXMLnsm, report, units);
            //AddToOutPut("Shell Geometry RHR Test: ",report);

            //Surface Element tests
            //deprecating all counts tests as criteria for passing and failing.  Use this now only to indicate counts in the surfaces summary
            ////Test 11 Execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.SurfaceCountTolerance;
            //report.testType = TestType.Total_Surface_Count;
            //units = "";
            //report = GetSurfaceCount(gbXMLdocs, gbXMLnsm, report, units);
            //AddToOutPut("Surface Count Test Result: ", report, true);


            ////Surface Element tests
            ////Test 12 Execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.ExteriorWallCountTolerance;
            //report.testType = TestType.Exterior_Wall_Surface_Count;
            //units = "";
            SurfaceSummary ss = new SurfaceSummary();
            ss.FileType = "Standard";
            camprep.SurfacesSummary.Add(ss);
            SurfaceSummary sst = new SurfaceSummary();
            sst.FileType = "Test";
            camprep.SurfacesSummary.Add(sst); //initialization of summaries complete
            logger.Info("START: EXTERIOR WALL COUNT");
            //report = GetEWSurfaceCount(gbXMLdocs, gbXMLnsm, report, units);
            var ewctresult = GetEWSurfaceCount(gbXMLdocs, gbXMLnsm, ref camprep);
            logger.Info("END: EXTERIOR WALL COUNT");
            if (!ewctresult)
            {
                //do nothing, it has no consequence for now
                //gbxml detailed compliance results?
            }
            //AddToOutPut("Exterior Wall Surface Count Test Result: ", report, true);

            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.SurfaceCountTolerance;
            //report.testType = TestType.Underground_Surface_Count;
            //units = "";
            //report = GetUGSurfaceCount(gbXMLdocs, gbXMLnsm, report, units);
            logger.Info("START: UNDERGROUND WALL COUNT");
            var ugwctresult = GetUGSurfaceCount(gbXMLdocs, gbXMLnsm, ref camprep);
            if (!ugwctresult)
            {
                //do nothing, it has no consequence for now
                //gbxml detailed compliance results?
            }
            logger.Info("END: UNDERGROUND WALL COUNT");
            //AddToOutPut("Underground Wall Count Test Result: ", report, true);

            logger.Info("START: SLABONGRADE COUNT");
            var sogctresult = GetSOGSurfaceCount(gbXMLdocs, gbXMLnsm, ref camprep);
            if (!sogctresult)
            {
                //do nothing, it has no consequence for now
                //gbxml detailed compliance results?
            }
            logger.Info("END: SLABONGRADE WALL COUNT");

            ////Surface Element tests
            ////Test 13 Execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.InteriorWallCountTolerance;
            //report.testType = TestType.Interior_Wall_Surface_Count;
            //units = "";
            logger.Info("START: INTERIOR WALL COUNT");
            //report = GetIWSurfaceCount(gbXMLdocs, gbXMLnsm, report, units);
            var iwctresult = GetIWSurfaceCount(gbXMLdocs, gbXMLnsm, ref camprep);
            if (!iwctresult)
            {
                //do nothing, it has no consequence for now
                //gbxml detailed compliance results?
            }
            logger.Info("END: INTERIOR WALL COUNT");
            //AddToOutPut("Interior Wall Surface Count Test Result: ", report, true);

            ////Surface Element tests
            ////Test 13 Execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.InteriorFloorCountTolerance;
            //report.testType = TestType.Interior_Floor_Surface_Count;
            //units = "";
            //report = GetIFSurfaceCount(gbXMLdocs, gbXMLnsm, report, units);
            logger.Info("START: INTERIOR FLOOR/CEILING COUNT");
            var ifctresult = GetIFSurfaceCount(gbXMLdocs, gbXMLnsm, ref camprep);
            if (!ifctresult)
            {
                //do nothing, it has no consequence for now
                //gbxml detailed compliance results?
            }
            logger.Info("END: INTERIOR FLOOR/CEILING COUNT");

            //AddToOutPut("Interior Floor Surface Count Test Result: ", report, true);


            ////Surface Element tests
            ////Test 14 Execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.InteriorWallCountTolerance;
            //report.testType = TestType.Roof_Surface_Count;
            //units = "";
            //report = GetRoofSurfaceCount(gbXMLdocs, gbXMLnsm, report, units);
            logger.Info("START: ROOF COUNT");
            var irctresult = GetRoofSurfaceCount(gbXMLdocs, gbXMLnsm, ref camprep);
            if (!irctresult)
            {
                //do nothing, it has no consequence for now
                //gbxml detailed compliance results?
            }
            logger.Info("END: ROOF COUNT");
            //AddToOutPut("Roof Surface Count Test Result: ", report, true);


            ////Surface Element tests
            ////Test 15 Execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.InteriorWallCountTolerance;
            //report.testType = TestType.Shading_Surface_Count;
            //units = "";
            //report = GetShadeSurfaceCount(gbXMLdocs, gbXMLnsm, report, units);
            logger.Info("START: SHADING DEVICE COUNT");
            var shadectresult = GetShadeSurfaceCount(gbXMLdocs, gbXMLnsm, ref camprep);
            if (!shadectresult)
            {
                //do nothing, it has no consequence for now
                //gbxml detailed compliance results?
            }
            //AddToOutPut("Shading Surface Count Test Result: ", report, true);
            logger.Info("END: SHADING DEVICE COUNT");

            ////Test 16 Execute
            //report.Clear();
            //report.tolerance = DOEgbXMLBasics.Tolerances.AirWallCountTolerance;
            //report.testType = TestType.Air_Surface_Count;
            //units = "";
            //report = GetAirSurfaceCount(gbXMLdocs, gbXMLnsm, report, units);
            logger.Info("START: AIR SURFACE COUNT");
            var asctresult = GetAirSurfaceCount(gbXMLdocs, gbXMLnsm, ref camprep);
            if (!asctresult)
            {
                //do nothing, it has no consequence for now
                //gbxml detailed compliance results?
            }
            logger.Info("END: AIR SURFACE COUNT");
            //AddToOutPut("Air Surface Count Test Result: ", report, true);


            #region surface detailed test
            //Jan 31-2012:  We may not want to perform these if the surface counts fail, but for now, we will include these tests
            //Detailed Surface Checks
            //Store Surface Element Information
            List<SurfaceDefinitions> TestSurfaces = new List<SurfaceDefinitions>();
            XmlDocument TestFile = gbXMLdocs[0];
            XmlNamespaceManager TestNSM = gbXMLnsm[0];
            List<SurfaceDefinitions> StandardSurfaces = new List<SurfaceDefinitions>();
            XmlDocument StandardFile = gbXMLdocs[1];
            XmlNamespaceManager StandardNSM = gbXMLnsm[1];
            TestSurfaces = GetFileSurfaceDefs(TestFile, TestNSM);
            StandardSurfaces = GetFileSurfaceDefs(StandardFile, StandardNSM);
            string TestSurfaceTable = " <div class='container'><table class='table table-bordered'>";
            TestSurfaceTable += "<tr class='info'>" +
                                   "<td>" + "Test Section Name" + "</td>" +
                                   "<td>" + "Stand Surface ID" + "</td>" +
                                   "<td>" + "Test Surface ID" + "</td>" +
                                   "<td>" + "Stand Surface Tilt" + "</td>" +
                                   "<td>" + "Test Surface Tilt" + "</td>" +
                                   "<td>" + "Stand Surface Azimuth" + "</td>" +
                                   "<td>" + "Test Surface Azimuth" + "</td>" +
                                    "<td>" + "Stand Surface Height" + "</td>" +
                                   "<td>" + "Test Surface Height" + "</td>" +
                                    "<td>" + "Stand Surface Width" + "</td>" +
                                   "<td>" + "Test Surface Width" + "</td>" +
                                   "<td>" + "Pass/Fail" + "</td>" +
                                   "</tr>";
            //Test Surfaces Planar Test
            //all polyloops must be such that the surface defined by the coordinates is planar
            //report.Clear();
            //report.testType = TestType.Surface_Planar_Test;
            logger.Info("START: SURFACE PLANARITY TEST");
            //report = TestSurfacePlanarTest(TestSurfaces, report);
            var planarityResult = TestSurfacePlanarTest(TestSurfaces,ref camprep);
            if (!planarityResult)
            {
                camprep.SurfacesSummary.Find(x => x.FileType == "Standard").PassedAllTests = false;
                //gbxml detailed compliance results?
            }
            logger.Info("END: SURFACE PLANARITY TEST");

            //if (!report.passOrFail && mustBePlanar)
            //{
            //    AddToOutPut("Test File Planar Surface Check: ", report, true);
            //    report.Clear();
            //}


            //only run detailed surface checks if the surfaces are planar
            if(planarityResult)
            {
                //<For each surface in the Standard File, try to find a match for this surface in the test file>
                //Written Jan 31, 2013 by Chien Si Harriman, Senior Product Manager, Carmel Software Corporation
                //Execute Tests


                //  globalMatchObject.MatchedSurfaceIds = new Dictionary<string, List<string>>();
                int i = 1;

                foreach (SurfaceDefinitions surface in StandardSurfaces)
                {
                    report.Clear();
                    DetailedSurfaceSummary ssSummary = new DetailedSurfaceSummary();
                    //multiple tolerances used
                    report.testType = TestType.Detailed_Surface_Checks;
                    report.subTestIndex = i;
                    if (surface.SurfaceId == "su-zone_5_Srf_7" || surface.SurfaceId == "su-zone_0_Srf_0")
                    {
                        var d = 1;
                    }
                    logger.Info("START: DETAILED SURFACE TEST");
                    GetSurfaceMatches(surface, TestSurfaces, ref ssSummary, validatorLength, testLength, testlengthConversion, standardlengthConversion, validatorArea, testArea, testareaConversion, standardareaConversion);
                    logger.Info("END: DETAILED SURFACE TEST");
                    camprep.SurfacesReport.Add(ssSummary);
                    
                }
            #endregion
                

                


                #region opending detailed test
                //openings detailed tests
                List<OpeningDefinitions> TestOpenings = new List<OpeningDefinitions>();
                XmlDocument testFile = gbXMLdocs[0];
                XmlNamespaceManager testNSM = gbXMLnsm[0];
                List<OpeningDefinitions> StandardOpenings = new List<OpeningDefinitions>();
                XmlDocument standardFile = gbXMLdocs[1];
                XmlNamespaceManager standardNSM = gbXMLnsm[1];
                TestOpenings = GetFileOpeningDefs(TestFile, TestNSM);
                StandardOpenings = GetFileOpeningDefs(StandardFile, StandardNSM);

                string TestOpeningTable = "";
                report.Clear();
                report.testType = TestType.Opening_Planar_Test;
                report = TestOpeningPlanarTest(TestOpenings, report);

                if (!report.passOrFail)
                {
                    AddToOutPut("Test File Planar Opening Check: ", report, true);
                    report.Clear();
                }
                //only run detailed opening checks if the opening are planar
                else
                {
                    TestOpeningTable = "<div class='container'><table class='table table-bordered'>";
                    TestOpeningTable += "<tr class='info'>" +
                                           "<td>" + "Test Section Name" + "</td>" +
                                            "<td>" + "Standard Opening Id" + "</td>" +
                                            "<td>" + "Test Opening Id" + "</td>" +
                                            "<td>" + "Standard Parent Surface Id" + "</td>" +
                                            "<td>" + "Test Parent Surface Id" + "</td>" +
                                            "<td>" + "Standard Parent Azimuth" + "</td>" +
                                            "<td>" + "Test Parent Azimuth" + "</td>" +
                                            "<td>" + "Standard Parent Tilt" + "</td>" +
                                            "<td>" + "Test Parent Tilt" + "</td>" +
                                            "<td>" + "Standard Surface Area" + "</td>" +
                                            "<td>" + "Test Surface Area" + "</td>" +
                                            "<td>" + "Pass/Fail" + "</td>" +
                                           "</tr>";

                    globalMatchObject.MatchedOpeningIds = new Dictionary<string, List<string>>();
                    int j = 1;
                    //if no openings remove the table.
                    if (StandardOpenings.Count < 1)
                        TestOpeningTable = "";
                    //compare the openings
                    foreach (OpeningDefinitions opening in StandardOpenings)
                    {
                        report.Clear();

                        report.testType = TestType.Detailed_Opening_Checks;
                        report.subTestIndex = j;

                        report = GetPossibleOpeningMatches(opening, TestOpenings, report);

                        AddToOutPut("Test 17 for Opening number " + j + " Result: ", report, false);

                        foreach (OpeningDefinitions to in TestOpenings)
                        {
                            if (globalMatchObject.MatchedOpeningIds.ContainsKey(opening.OpeningId))
                            {
                                foreach (string id in globalMatchObject.MatchedOpeningIds[opening.OpeningId])
                                {
                                    if (to.OpeningId == id)
                                    {
                                        if (report.passOrFail)
                                            TestOpeningTable += "<tr class='success'>" +
                                                "<td>" + "<a href='TestDetailPage.aspx?type=" + (int)report.testType + "&subtype=" + report.subTestIndex + "' target='_blank'>" +
                                                "Detailed Opening Checks " + report.subTestIndex + "</a>" + "</td>" +
                                               "<td>" + opening.OpeningId + "</td>" +
                                                "<td>" + to.OpeningId + "</td>" +
                                                "<td>" + opening.ParentSurfaceId + "</td>" +
                                                "<td>" + to.ParentSurfaceId + "</td>" +
                                                "<td>" + String.Format("{0:#,0.00}", opening.ParentAzimuth) + "</td>" +
                                                "<td>" + String.Format("{0:#,0.00}", to.ParentAzimuth) + "</td>" +
                                                "<td>" + String.Format("{0:#,0.00}", opening.ParentTilt) + "</td>" +
                                                "<td>" + String.Format("{0:#,0.00}", to.ParentTilt) + "</td>" +
                                                "<td>" + String.Format("{0:#,0.00}", opening.surfaceArea) + "</td>" +
                                                "<td>" + String.Format("{0:#,0.00}", to.surfaceArea) + "</td>" +
                                                "<td>" + "Pass" + "</td>" +
                                                "</tr>";
                                    }

                                }

                            }
                        }
                        //if didn't find match means it failed the test
                        if (!report.passOrFail)
                            TestOpeningTable += "<tr class='error'>" +
                                              "<td>" + "<a href='TestDetailPage.aspx?type=" + (int)report.testType + "&subtype=" + report.subTestIndex + "' target='_blank'>" +
                                              "Detailed Opening Checks " + report.subTestIndex + "</a>" + "</td>" +
                                              "<td>" + opening.OpeningId + "</td>" +
                                              "<td>" + "---" + "</td>" +
                                                "<td>" + opening.ParentSurfaceId + "</td>" +
                                                "<td>" + "---" + "</td>" +
                                                "<td>" + String.Format("{0:#,0.00}", opening.ParentAzimuth) + "</td>" +
                                                "<td>" + "---" + "</td>" +
                                                 "<td>" + String.Format("{0:#,0.00}", opening.ParentTilt) + "</td>" +
                                                "<td>" + "---" + "</td>" +
                                                 "<td>" + String.Format("{0:#,0.00}", opening.surfaceArea) + "</td>" +
                                                "<td>" + "---" + "</td>" +
                                              "<td>" + "Fail" + "</td>" +
                                              "</tr>";
                        j += 1;

                    }
                }
                TestOpeningTable += "</table></div><br/>";
                #endregion

                //close table
                table += "</table></div><br/>";
                //add TestSurfaceTable
                table += TestSurfaceTable + TestOpeningTable;

                
            }
            //CreateSummaryTable();
            ((FileAppender)LogManager.GetCurrentLoggers()[0].Logger.Repository.GetAppenders()[0]).Close();

        }
        public static bool GetAirSurfaceCount(List<XmlDocument> gbXMLDocs, List<XmlNamespaceManager> gbXMLnsm, ref CampusReport cr)
        {


            //assuming that this will be plenty large for now
            string[] resultsArray = new string[50];
            int nodecount = 0;
            for (int i = 0; i < gbXMLDocs.Count; i++)
            {
                nodecount = 0;
                try
                {
                    XmlDocument gbXMLTestFile = gbXMLDocs[i];
                    XmlNamespaceManager gbXMLns = gbXMLnsm[i];

                    XmlNodeList nodes = gbXMLTestFile.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Surface", gbXMLns);
                    foreach (XmlNode surfaceNode in nodes)
                    {
                        XmlAttributeCollection spaceAtts = surfaceNode.Attributes;
                        foreach (XmlAttribute at in spaceAtts)
                        {
                            if (at.Name == "surfaceType")
                            {
                                string type = at.Value;
                                if (type == "Air")
                                {
                                    nodecount++;
                                }
                                break;
                            }
                        }
                    }

                    if (i % 2 == 0) //this should never fail, but it will if orders are reversed.  Have to be careful.
                    {
                        cr.SurfacesSummary.Find(x => x.FileType == "Test").NumberOfAirSurfaces = nodecount;
                    }
                    else
                    {
                        cr.SurfacesSummary.Find(x => x.FileType == "Standard").NumberOfAirSurfaces = nodecount;
                    }
                    if (i % 2 != 0)
                    {

                        double difference = Math.Abs(Convert.ToInt32(resultsArray[i]) - Convert.ToInt32(resultsArray[(i - 1)]));
                        if (difference == 0)
                        {
                            logger.Info("PROGRAMMER'S NOTE:  The Test File's Air surfaces count matches the Standard File exactly, the difference is zero.");
                        }
                        else
                        {
                            logger.Info("PROGRAMMER'S NOTE:  The Test File's Air surfaces count does not match the Standard File exactly.");
                        }

                    }
                    else { continue; }

                }
                catch (Exception e)
                {
                    logger.Debug(e.ToString());
                    logger.Fatal(" Failed to complete Air surfaces Count.");
                    return false;
                }
            }
            return true;
        }
        //Written July 2016 by Chien Si Harriman
        public static bool GetEWSurfaceCount(List<XmlDocument> gbXMLDocs, List<XmlNamespaceManager> gbXMLnsm, ref CampusReport cr)
        {

            //assuming that this will be plenty large for now
            string[] resultsArray = new string[500];
            int nodecount = 0;
            for (int i = 0; i < gbXMLDocs.Count; i++)
            {
                nodecount = 0;
                try
                {
                    XmlDocument gbXMLTestFile = gbXMLDocs[i];
                    XmlNamespaceManager gbXMLns = gbXMLnsm[i];

                    XmlNodeList nodes = gbXMLTestFile.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Surface", gbXMLns);
                    foreach (XmlNode surfaceNode in nodes)
                    {
                        XmlAttributeCollection spaceAtts = surfaceNode.Attributes;
                        foreach (XmlAttribute at in spaceAtts)
                        {
                            if (at.Name == "surfaceType")
                            {
                                string type = at.Value;
                                if (type == "ExteriorWall")
                                {
                                    nodecount++;
                                }
                                break;
                            }
                        }
                    }
                    if (i % 2 == 0)
                    {
                        cr.SurfacesSummary.Find(x => x.FileType == "Test").NumberOfExternalWalls = nodecount;
                    }
                    else
                    {
                        cr.SurfacesSummary.Find(x => x.FileType == "Standard").NumberOfExternalWalls = nodecount;
                    }
                    //need to test for accuracy of result if accurate then pass, if not, how much inaccuracy and return this result 
                    resultsArray[i] = nodecount.ToString();
                    if (i % 2 != 0)
                    {

                        double difference = Math.Abs(Convert.ToInt32(resultsArray[i]) - Convert.ToInt32(resultsArray[(i - 1)]));
                        if (difference == 0)
                        {
                            logger.Info("PROGRAMMER'S NOTE:  The Test File's Exterior Wall count matches the Standard File exactly, the difference is zero.");
                        }
                        else
                        {
                            logger.Info("PROGRAMMER'S NOTE:  The Test File's Exterior Wall does not match the Standard File exactly.");
                        }

                    }
                    else { continue; }

                }
                catch (Exception e)
                {
                    logger.Debug(e.ToString());
                    logger.Fatal(" Failed to complete the Exterior Wall Count Procedure.");
                    return false;
                }
            }
            return true;
        }
        //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;
        }
        public static bool UniqueSpaceIdTest(List<XmlDocument> gbXMLDocs, List<XmlNamespaceManager> gbXMLnsm, ref CampusReport cr)
        {
            //report.testSummary = "This test reviews the test file's Space id values, and ensures that they are all unique.  If there are any duplicate Space id values, then this test will fail.  If there are duplicates, the remainder of the tests in the testbed are not executed and the test will end here until the test file is properly updated.  Each Space id must be unique for the test bed to successfully execute.  If you have failed this test, please review the documents for this test and resubmit the test.";

            //report.MessageList = new List<string>();
            //report.TestPassedDict = new Dictionary<string, bool>();
            List<string> standardIdList = new List<string>();
            List<string> testIDList = new List<string>();
            //report.standResult = new List<string>();
            //report.testResult = new List<string>();
            //report.idList = new List<string>();
            // report.testType = "UniqueId";
            try
            {
                for (int i = 0; i < gbXMLDocs.Count; i++)
                {
                    XmlDocument gbXMLTestFile = gbXMLDocs[i];
                    XmlNamespaceManager gbXMLns = gbXMLnsm[i];

                    XmlNodeList nodes = gbXMLTestFile.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space", gbXMLns);
                    foreach (XmlNode node in nodes)
                    {
                        //looks to see if the spaceId is already included in the list of space IDs being generated
                        string spaceId;
                        if (i % 2 != 0)
                        {
                            for (int n = 0; n < node.Attributes.Count; n++)
                            {
                                if (node.Attributes[n].Name == "id")
                                {
                                    spaceId = node.Attributes[n].Value.ToString();
                                    standardIdList.Add(spaceId);
                                }
                            }

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

                                }
                            }
                        }
                    }
                }
                //now that I have all of the spaceIds, I will loop through and make sure I have perfect matches
                //the order of the spaces is not enforced
                //create a list that holds the index of the standardIdList when a match is found
                //the list should be the same length as standardIdlist and each value should be unique
                List<int> indexFound = new List<int>();
                for (int j = 0; j < standardIdList.Count; j++)
                {
                    string standardId = standardIdList[j];
                    foreach (string testspaceId in testIDList)
                    {
                        if (testspaceId == standardId)
                        {
                            indexFound.Add(j);
                            logger.Info("PROGRAMMER'S NOTE:  The standard file space id: " + standardId + "has found a spaceId match in the test file.");
                        }
                    }
                }
                //search the list to make sure that it is unique and has the proper count
                if (indexFound.Count == standardIdList.Count)
                {
                    logger.Info("TEST FILE SUCCESS:  The standard file has found a match only once in the test file.  All spaceIds have been matched.");
                    var stsum = cr.SpacesSummary.Find(x => x.FileType == "Standard");
                    stsum.spaceIDs_unique = true;
                    var testsum = cr.SpacesSummary.Find(x => x.FileType == "Test");
                    testsum.spaceIDs_unique = true;
                    return true;
                }
                else
                {
                    logger.Info("TEST FILE FAILURE:  The standard file has found a duplicate space ID.");
                    var stsum = cr.SpacesSummary.Find(x => x.FileType == "Standard");
                    stsum.spaceIDs_unique = false;
                    var testsum = cr.SpacesSummary.Find(x => x.FileType == "Test");
                    testsum.spaceIDs_unique = false;
                    stsum.PassedAllTests = false;
                    return false;
                }

                
            }
            catch (Exception e)
            {
                logger.Fatal(e.ToString());
                return false;
            }
        }
        public static bool TestBuildingStoryRHR(List<XmlDocument> gbXMLDocs, List<XmlNamespaceManager> gbXMLnsm, ref CampusReport cr)
        {
            

            
            //stores the list of z heights for both files
            List<List<string>> fileLevelZz = new List<List<string>>();
            //stores the RHR x product and the corresonding z height for a level
            Dictionary<string, VectorMath.Vector.CartVect> levelVct = new Dictionary<string, VectorMath.Vector.CartVect>();
            

            VectorMath.Vector.CartVect vector = new VectorMath.Vector.CartVect();

            int errorCount = 0;
            for (int i = 0; i < gbXMLDocs.Count; i++)
            {
                try
                {
                    //refresh
                    //stores the level's z heights
                    List<string> LevelZs = new List<string>();
                    //stores a list of the RHR x product and corresponding z height for both files
                    List<Dictionary<string, VectorMath.Vector.CartVect>> fileLevelVct = new List<Dictionary<string, VectorMath.Vector.CartVect>>();

                    XmlDocument gbXMLTestFile = gbXMLDocs[i];
                    XmlNamespaceManager gbXMLns = gbXMLnsm[i];
                    //maybe it would be good if the test result spits out the name of the story?  TBD
                    XmlNodeList PlanarGeometry = gbXMLTestFile.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:BuildingStorey/gbXMLv5:PlanarGeometry", gbXMLns);
                    XmlNodeList PolyLoops = gbXMLTestFile.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:BuildingStorey/gbXMLv5:PlanarGeometry/gbXMLv5:PolyLoop", gbXMLns);
                    int nodecount = PolyLoops.Count;
                    //get the normals for each level in the Standard File
                    //get the z-coordinate for each level (we assume that the levels are going to be parallel to Z
                    LevelZs = GetLevelZs(PlanarGeometry, LevelZs);
                    if (LevelZs.Count == 0)
                    {
                        logger.Info("PROGRAMMER's NOTE: No level polyloops found in this file.  Level polyloop checks are being ignored.");
                        return false;
                    }
                    foreach (string level in LevelZs)
                    {
                        //a simple attempt to filter out exceptions, which could be returned in some instances
                        if (level.Length < 10)
                        {
                            vector = GetPolyLoopXProduct(PlanarGeometry, level);
                            string levelValue = level;
                            //if (i == 0) { levelValue += "-T"; }
                            //else { levelValue += "-S"; }
                            levelVct.Add(levelValue, vector);
                        }
                    }
                    fileLevelZz.Add(LevelZs);
                    fileLevelVct.Add(levelVct);

                    //reporting 
                    if (i % 2 != 0)
                    {
                        if(fileLevelVct[0].Count > 0)
                        {
                            Dictionary<string, VectorMath.Vector.CartVect> standDict = fileLevelVct[1];
                            Dictionary<string, VectorMath.Vector.CartVect> testDict = fileLevelVct[0];
                            foreach (KeyValuePair<string, VectorMath.Vector.CartVect> pair in standDict)
                            {

                                if (testDict.ContainsKey(pair.Key))
                                {
                                    logger.Info("PROGRAMMERS NOTE: While searching for matching building levels, there has been a Successful match.  Building Story Level " + pair.Key + " in the Standard file found a match in the Test File.");
                                    //perform cross product again of the two vectors in question.  The result should be a zero since they should be parallel
                                    VectorMath.Vector.CartVect rhrTestVector = VectorMath.Vector.CrossProduct(testDict[pair.Key], standDict[pair.Key]);
                                    if (Math.Abs(rhrTestVector.X) <= 0.1 && Math.Abs(rhrTestVector.Y) == 0.1 && Math.Abs(rhrTestVector.Z) == 0.1)
                                    {
                                        logger.Info("TEST FILE SUCCESS: For this level match, there is Normal Vector Test Success.  The right hand rule test identified a parallel normal vector for Level " + pair.Key + " in both the Standard and Test gbXML Files.");
                                    }
                                    else
                                    {
                                        logger.Info("TEST FILE FAILURE: For this level match, there not Normal Vector Test Success.  The right hand rule test shows the vectors are not parallel for Level " + pair.Key + " in both the Standard and Test gbXML Files.");
                                    }

                                }
                                else
                                {
                                    logger.Fatal("The right hand rule test for Level " + pair.Key + " in the Standard File could not be completed.  A match for this level could not be found in the test file.");
                                    return false;
                                }
                            }
                        }

                    }
                    else { continue; }

                    //need to comapre and have if then statement depending on the outcome of the accuracy tests
                    if (errorCount == 0)
                    {
                        logger.Info("TEST FILE SUCCESS:  Building Stories RHR in the Test File match the RHR in the Standard File for all Levels.");
                    }
                    else
                    {
                        logger.Info("TEST FILE FAILURE: Not all levels in the Standard File found equivalent levels and normal vectors in the Test File.");
                        return false;
                    }
                    
                }
                catch (Exception e)
                {
                    logger.Debug(e.ToString());
                    logger.Fatal(" Failed to complete RHR Test for the Building Storey Nodes.  Exception noted.");
                    return false;
                }
            }
            return true;
        }
        //Created July 2016, Chien Si Harriman
        public static bool GetStoryHeights(List<XmlDocument> gbXMLDocs, List<XmlNamespaceManager> gbXMLnsm, ref CampusReport cr, Conversions.lengthUnitEnum standardLength, Conversions.lengthUnitEnum testLength, double testlengthConversion, double standardlengthConversion, double tolerance)
        {

            //small dictionaries I make to keep track of the story level names and heights
            //standard file
            Dictionary<string, double> standardStoryHeight = new Dictionary<string, double>();
            //Test File
            Dictionary<string, double> testStoryHeight = new Dictionary<string, double>();
            string key = null;
            string val = null;
            string standLevel = "";


            for (int i = 0; i < gbXMLDocs.Count; i++)
            {
                try
                {
                    //assuming that this will be plenty large for now
                    XmlDocument gbXMLTestFile = gbXMLDocs[i];
                    XmlNamespaceManager gbXMLns = gbXMLnsm[i];
                    XmlNodeList nodes = gbXMLTestFile.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:BuildingStorey", gbXMLns);
                    int nodecount = nodes.Count;
                    foreach (XmlNode node in nodes)
                    {
                        XmlNodeList childNodes = node.ChildNodes;
                        foreach (XmlNode childNode in childNodes)
                        {
                            if (childNode.Name.ToString() == "Level") { val = childNode.InnerText; }
                            else if (childNode.Name.ToString() == "Name") { key = childNode.InnerText; }
                            else { continue; }
                            if (i % 2 != 0)
                            {
                                if (key != null && val != null)
                                {
                                    double standardlevelvalue = Convert.ToDouble(val) * standardlengthConversion;
                                    standardStoryHeight.Add(key, standardlevelvalue);
                                    key = null;
                                    val = null;
                                }
                                else
                                {

                                }
                            }
                            else
                            {
                                if (key != null && val != null)
                                {
                                    double testlevelvalue = Convert.ToDouble(val) * testlengthConversion;
                                    testStoryHeight.Add(key, testlevelvalue);
                                    key = null;
                                    val = null;
                                }
                                else
                                {

                                }
                            }
                        }
                    }

                    //reporting 
                    if (i % 2 != 0)
                    {
                        if (standardStoryHeight.Count == 0)
                        {
                            logger.Info("TEST FILE FAILURE: Test cannot be completed.  Standard File Level Count returns Zero.");
                            return false;
                        }
                        else if (testStoryHeight.Count == 0)
                        {
                            logger.Info("TEST FILE FAILURE: Test cannot be completed.  Test File Level Count returns Zero.");
                            return false;
                        }
                        else
                        {
                            //set pass to true
                            int count = 0;
                            foreach (KeyValuePair<string, double> standardPair2 in standardStoryHeight)
                            {
                                count++;
                                double difference;
                                StoryHeightMin = 10000;
                                string equivLevel = "";
                                if (testStoryHeight.ContainsKey(standardPair2.Key))
                                {
                                    double matchkeydiff = Math.Abs(standardPair2.Value - testStoryHeight[standardPair2.Key]);
                                    if (matchkeydiff == 0)
                                    {
                                        logger.Info("TEST FILE SUCCESS: Matched Standard File's " + standardPair2.Value + " with Test File's " + testStoryHeight[standardPair2.Key] + " @ " + standardPair2.Key +" Exactly");
                                        continue;
                                    }
                                    else if (matchkeydiff < tolerance)
                                    {
                                        logger.Info("TEST FILE SUCCESS: Matched Standard File's " + standardPair2.Value + " with Test File's " + testStoryHeight[standardPair2.Key] + " @ " + standardPair2.Key + " within allowable tolerance.");
      
                                        continue;
                                    }
                                    else
                                    {
                                        logger.Info("TEST FILE FAILURE: Did NOT Match Standard File's " + standardPair2.Value + " with Test File's " + testStoryHeight[standardPair2.Key] + " @ " + standardPair2.Key+ " within allowable tolerance.");
                                        return false;
                                    }

                                }
                                foreach (KeyValuePair<string, double> testPair in testStoryHeight)
                                {
                                    difference = Math.Abs(Convert.ToDouble(standardPair2.Key) * standardlengthConversion - Convert.ToDouble(testPair.Key) * testlengthConversion);
                                    //store all levels and the difference between them
                                    if (StoryHeightMin > difference)
                                    {
                                        StoryHeightMin = difference;
                                        standLevel = standardPair2.Value.ToString();
                                    }
                                }
                                if (StoryHeightMin < tolerance)
                                {
                                    logger.Info("TEST FILE SUCCESS: Matched Standard File's " + standardPair2.Value + " @ " + standardPair2.Key + " within the Tolerance allowed");
                                }
                                else
                                {
                                    logger.Info("Standard File's " + standardPair2.Value + " equivalent was not found in the test file.  The closest level in the test file was found at " + equivLevel + " in the test file.  The difference in heights was " + StoryHeightMin.ToString());
                                }

                            }
                        }
                    }
                }

                catch (Exception e)
                {
                    logger.Info(e.ToString());
                    logger.Info(" Failed to complete Building Story Level test in the XML file.");
                    return false;
                }

            }
            return true;
        }
        //Created July 2016, Chien Si Harriman
        public static bool GetBuildingStoryCount(List<XmlDocument> gbXMLDocs, List<XmlNamespaceManager> gbXMLnsm, ref CampusReport cr, int tolerance)
        {
            //assuming that this will be plenty large for now
            string[] resultsArray = new string[50];
            for (int i = 0; i < gbXMLDocs.Count; i++)
            {
                try
                {
                    XmlDocument gbXMLTestFile = gbXMLDocs[i];
                    XmlNamespaceManager gbXMLns = gbXMLnsm[i];

                    XmlNodeList nodes = gbXMLTestFile.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:BuildingStorey", gbXMLns);
                    int nodecount = nodes.Count;
                    //need to test for accuracy of result if accurate then pass, if not, how much inaccuracy and return this result 
                    resultsArray[i] = nodecount.ToString();
                    if (i % 2 != 0)
                    {
                        double difference = Math.Abs(Convert.ToInt32(resultsArray[i]) - Convert.ToInt32(resultsArray[(i - 1)]));
                        if (difference == 0)
                        {
                            logger.Info("TEST FILE SUCCESS:PERFECT : The test file's Building Storey Count matches the standard file exactly.");
                        }
                        else if (difference <= tolerance)
                        {
                            logger.Info("TEST FILE SUCCESS: The test file's Building Storey Count matches the standard file.");
                        }
                        else
                        {
                            logger.Info("TEST FILE FAILURE: The test file's Building Storey Count does not match the standard file's .");
                            return false;
                        }
                    }
                    else { continue; }
                }
                catch (Exception e)
                {
                    logger.Debug(e.ToString());
                    logger.Fatal("Failed to complete building storey count test in the XML file.");
                    return false;
                }
            }
            return true;
        }
        public static bool GetBuildingSpaceCount(List<XmlDocument> gbXMLDocs, List<XmlNamespaceManager> gbXMLnsm, string Units, int spaceCountTol, ref CampusReport cr)
        {

            //TODO:  This could be improved.  It will fail when the space count exceeds 500.  ssuming that this will be plenty large for now
            int[] resultsArray = new int[500];
            for (int i = 0; i < gbXMLDocs.Count; i++)
            {
                try
                {
                    XmlDocument gbXMLTestFile = gbXMLDocs[i];
                    XmlNamespaceManager gbXMLns = gbXMLnsm[i];

                    XmlNodeList nodes = gbXMLTestFile.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space", gbXMLns);
                    int nodecount = nodes.Count;
                    //need to test for accuracy of result if accurate then pass, if not, how much inaccuracy and return this result 
                    resultsArray[i] = nodecount;
                    if (i % 2 != 0)
                    {
                        //setup standard result and test result
                        logger.Debug("There are " + resultsArray[i]+" Spaces in the standard file");
                        logger.Debug("There are " + resultsArray[i-1] + " Spaces in the uploaded test file");


                        cr.SpacesSummary.Find(x => x.FileType == "Standard").Count = resultsArray[i]; //TODO: Remove
                        cr.SpacesSummary.Find(x => x.FileType == "Test").Count = resultsArray[i-1]; //TODO: Remove

                        cr.BuildingSummary.Find(x => x.FileType == "Standard").NumberOfSpaces = resultsArray[i];
                        cr.BuildingSummary.Find(x => x.FileType == "Test").NumberOfSpaces = resultsArray[i-1];
                        

                        double difference = Math.Abs(Convert.ToInt32(resultsArray[i]) - Convert.ToInt32(resultsArray[(i - 1)]));
                        if (difference == 0)
                        {
                            logger.Info("TEST FILE SUCCESS: The test file's Space Count matches the standard file exactly.");
                        }
                        else if (difference <= spaceCountTol)
                        {
                            logger.Info("TEST FILE SUCCESS: The test file's Space Count matches the standard file, the difference was within tolerance = " + spaceCountTol + " " + Units);
                        }
                        else
                        {
                            logger.Info("TEST FILE FAILURE:  The test file's Space Count is not within the allowable tolerance of " + spaceCountTol + " " + Units + " The difference between the standard and test file is " + difference.ToString() + " " + Units);
                            return false;
                        }
                    }
                    else { continue; }
                }
                catch (Exception e)
                {
                    logger.Fatal(" Failed to locate Building in the XML file.");
                    return false;
                }
            }
            return true;
        }
        //Created July 2016, Chien Si Harriman
        //note we made a change to this method where the tolerance is now based on a percentage to the standard, and is not absolute.
        public static bool GetBuildingArea(List<XmlDocument> gbXMLDocs, List<XmlNamespaceManager> gbXMLnsm, ref CampusReport cr, Conversions.areaUnitEnum standardUnits, Conversions.areaUnitEnum testUnits, double testareaConversion, double standardareaConversion, double tolerance, DOEgbXMLTestDetail t)
        {
            
            //assuming that this will be plenty large for now, all test cases only have one building currently.
            string[] resultsArray = new string[50];
            bool thinWalled = false;
            for (int i = 0; i < gbXMLDocs.Count; i++)
            {
                try
                {
                    XmlNode productName = gbXMLDocs[0].SelectSingleNode("/gbXMLv5:gbXML/gbXMLv5:DocumentHistory/gbXMLv5:ProgramInfo/gbXMLv5:ProductName", gbXMLnsm[i]);
                    if (productName.InnerText.ToLower().Replace(" ",String.Empty).Trim() == "openstudio") //TODO:  Consider a different test.
                    {
                        thinWalled = true;
                    }
                    XmlDocument gbXMLTestFile = gbXMLDocs[i];
                    XmlNamespaceManager gbXMLns = gbXMLnsm[i];

                    var node = gbXMLDocs[i].SelectSingleNode("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Area", gbXMLnsm[i]);
                    string area = node.InnerText;
                    //need to test for accuracy of result if accurate then pass, if not, how much inaccuracy and return this result 
                    resultsArray[i] = area;
                    if (i % 2 != 0)
                    {
                        //setup standard result and test result
                        if (testareaConversion != 1) { logger.Info("PROGRAMMER'S NOTE: Converted the test file building area units."); }
                        //apply the conversion factor on the test file always, regardless.
                        double standardArea = Convert.ToDouble(resultsArray[i]) * standardareaConversion;
                        double testArea = Convert.ToDouble(resultsArray[(i - 1)]) * testareaConversion;
                        if (thinWalled)
                        {
                            //no conversion necessary, it was already accounted for when it was entered by the administrator.
                            if (Math.Abs(testArea - t.thinWalledExpectedBuildingArea)/t.thinWalledAltBuildingArea < tolerance) { testArea = t.thinWalledAltBuildingArea; }
                            else
                            {
                                logger.Info("TEST FILE FAILURE:  The test file's Building Area  is not within the allowable tolerance of " + tolerance.ToString() + ".");
                                return false;
                            }
                        }
                        
                        logger.Info("Standard Building Area: "+String.Format("{0:#,0.00}", standardArea.ToString()));
                        logger.Info("Test Building Area: "+String.Format("{0:#,0.00}", testArea.ToString()));

                        cr.BuildingSummary.Find(x => x.FileType == "Standard").BuildingArea = new Area(standardArea,"Square Feet");
                        cr.BuildingSummary.Find(x => x.FileType == "Test").BuildingArea = new Area(testArea, "Square Feet");

                        double difference = Math.Abs(standardArea - testArea)/standardArea;
                        if (difference == 0)
                        {
                            logger.Info("TEST FILE SUCCESS:PERFECT: The test file's Building Area matches the standard file Building Area exactly.");
                        }

                        else if (difference <= tolerance)
                        {
                            logger.Info("TEST FILE SUCCESS: The test file's Building Area is within the allowable tolerance of = " + tolerance.ToString());
                        }
                        else
                        {
                            logger.Info("TEST FILE FAILURE:  The test file's Building Area  is not within the allowable tolerance of " + tolerance.ToString() + ".");
                            return false;
                        }
                    }
                    else { continue; }
                }
                catch (Exception e)
                {
                    logger.Debug(e.ToString());
                    logger.Fatal(" Failed to locate Building Area in the XML file.");
                    return false;
                }
            }

            return true;
        }
        private bool TestSurfacePlanarTest(List<SurfaceDefinitions> TestSurfaces, ref CampusReport cr)
        {
            //ensure that each set of RHR tests result in parallel or anti-parallel resultant vectors, or else fail the test

            foreach (SurfaceDefinitions ts in TestSurfaces)
            {
                Dictionary<string, List<Vector.CartVect>> surfaceXProducts = new Dictionary<string, List<Vector.CartVect>>();
                List<Vector.CartVect> xProducts = new List<Vector.CartVect>();
                for (int i = 0; i < ts.PlCoords.Count - 2; i++)
                {
                    //Get the Cross Product
                    VectorMath.Vector.CartVect v1 = VectorMath.Vector.CreateVector(ts.PlCoords[i], ts.PlCoords[i + 1]);
                    VectorMath.Vector.CartVect v2 = VectorMath.Vector.CreateVector(ts.PlCoords[i + 1], ts.PlCoords[i + 2]);
                    Vector.CartVect xProd = Vector.CrossProduct(v1, v2);
                    xProd = Vector.UnitVector(xProd);
                    xProducts.Add(xProd);
                }
                surfaceXProducts.Add(ts.SurfaceId, xProducts);
                for (int j = 0; j < xProducts.Count - 1; j++)
                {
                    //parallel and anti parallel
                    if (xProducts[j].X == xProducts[j + 1].X && xProducts[j].Y == xProducts[j + 1].Y && xProducts[j].Z == xProducts[j + 1].Z)
                    {
                        continue;
                    }
                    //anti-parallel
                    else if (xProducts[j].X == -1 * xProducts[j + 1].X && xProducts[j].Y == -1 * xProducts[j + 1].Y && xProducts[j].Z == -1 * xProducts[j + 1].Z)
                    {
                        continue;
                    }
                    else if (Math.Abs(xProducts[j].X) - Math.Abs(xProducts[j + 1].X) < .0001 && Math.Abs(xProducts[j].Y) - Math.Abs(xProducts[j + 1].Y) < .0001 &&
                        Math.Abs(xProducts[j].Z) - Math.Abs(xProducts[j + 1].Z) < 0.0001)
                    {
                        continue;
                    }
                    else
                    {
                        logger.Info("TEST FILE FAILURE: " + ts.SurfaceId + " has polyLoop coordinates that do not form a planar surface.  This fails the detailed surface tests and will not continue.");
                        cr.SurfacesSummary.Find(x => x.FileType == "Test").SurfacesArePlanar = false;
                        return false;
                    }
                }
            }
            logger.Info("TEST FILE SUCCESS: All test file's surfaces have polyloop descriptions that describe a planar surface.  Planar surface test succeeded.");
            return true;

        }