Repository: NREL/hescore-hpxml

Issue:
Incorrectly subtracting R-5 when using ExpandedPolystyreneSheathing element
If you have a wall like this

```xml
<Wall>
  <SystemIdentifier id="wall_right"/>
  <WallType>
    <WoodStud>
      <ExpandedPolystyreneSheathing>true</ExpandedPolystyreneSheathing>
    </WoodStud>
  </WallType>
  <Orientation>east</Orientation>
  <Siding>wood siding</Siding>
  <Insulation>
    <SystemIdentifier id="wall_right_insulation"/>
    <Layer>
      <NominalRValue>0</NominalRValue>
    </Layer>
  </Insulation>
</Wall>
```

This code

https://github.com/NREL/hescore-hpxml/blob/e5af84582b4524ad92bac0a9f153051f2d39f5eb/hescorehpxml/base.py#L186-L190

makes the R-value go negative and causes an error. 

The `ExpandedPolystyreneSheathing` element is kind of weird and should probably be removed from HPXML because the same thing can be described better with an `Insulation/Layer`. There's no R-value associated with it, so it's not clear whether we're to assume one or expect one in a layer below. Right now the translator apparently expects the R-value to be present in a layer, hence the error. 

We could just check if `wall_rvalue` goes negative and set it to zero if it does. It's kind of a kludgy fix, but avoids the error. 

Discussion:

Patch:
diff --git a/hescorehpxml/base.py b/hescorehpxml/base.py
index 6a885f3e..af079178 100644
--- a/hescorehpxml/base.py
+++ b/hescorehpxml/base.py
@@ -262,7 +262,7 @@ class HPXMLtoHEScoreTranslatorBase(object):
                         tobool(xpath(hpxmlwall, 'h:WallType/h:WoodStud/h:ExpandedPolystyreneSheathing/text()')):
                     wallconstype = 'ps'
                     # account for the rigid foam sheathing in the construction code
-                    wall_rvalue -= 5
+                    wall_rvalue = max(0, wall_rvalue - 5)
                     rvalue = wall_round_to_nearest(wall_rvalue, (0, 3, 7, 11, 13, 15, 19, 21))
                 elif tobool(xpath(hpxmlwall, 'h:WallType/h:WoodStud/h:OptimumValueEngineering/text()')):
                     wallconstype = 'ov'


Test patch:
diff --git a/tests/test_translation.py b/tests/test_translation.py
index cad28cc5..3c130677 100644
--- a/tests/test_translation.py
+++ b/tests/test_translation.py
@@ -3051,6 +3051,17 @@ class TestHEScore2021Updates(unittest.TestCase, ComparatorBase):
         self.assertEqual(res3['building']['zone']['zone_roof'][1]['zone_skylight']['skylight_code'], 'dtab')
         self.assertFalse(res3['building']['zone']['zone_roof'][1]['zone_skylight']['solar_screen'])
 
+    def test_xps_negative(self):
+        tr = self._load_xmlfile('hescore_min_v3')
+        wall = self.xpath('//h:Wall[h:SystemIdentifier/@id="wall1"]')
+        tr.xpath(wall, 'h:Insulation/h:Layer/h:NominalRValue').text = "0"
+        wood_stud = tr.xpath(wall, 'descendant::h:WoodStud')
+        xps_el = etree.Element(tr.addns('h:ExpandedPolystyreneSheathing'))
+        xps_el.text = 'true'
+        wood_stud.append(xps_el)
+        res = tr.hpxml_to_hescore()
+        self.assertEqual(res['building']['zone']['zone_wall'][0]['wall_assembly_code'], 'ewps00br')
+
 
 class TestHEScoreV3(unittest.TestCase, ComparatorBase):