first commit

This commit is contained in:
Senad Uka
2017-11-07 09:23:57 +01:00
commit 0eee92660a
356 changed files with 747259 additions and 0 deletions

View File

@@ -0,0 +1,117 @@
import unittest
from unittest.mock import MagicMock
from helix.calculators.mechanical_bom_calculator import MechanicalBomCalculator
from helix.constants.anchor_type import AnchorType
from helix.constants.module_type import ModuleType
from helix.constants.panel_type import PanelType
from helix.constants.parts import *
from helix.constants.system_type import SystemType
from helix.models.panel import Panel
from helix.models.subarray import Subarray
from test.test_helpers import assert_dictionary_equal
class MechanicalBomCalculatorWhenDualTilt128CellTest(unittest.TestCase):
def setUp(self):
self.values = MagicMock()
self.values.system_type.return_value = SystemType.dualTilt
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip_Plus
self.values.module_type.return_value = ModuleType.Cell128
"""
Generated using the following parameters:
Building Height = 30
Building Length = 200
Building Width = 76
Parapet Height = 0
Wind Speed = 125
Exposure Category = C
Ballast Block Weight = 13
Max Allowable System Pressure = 10
System type = Dual Tilt
"""
self.panels = [
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=4, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=15, link_tray=2, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=2, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.NorthSouth, ballast=18, link_tray=2, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.EastWest, ballast=17, link_tray=2, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=12, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=1, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=9, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.EastWest, ballast=8, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Middle, ballast=2, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Corner, ballast=5, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=1, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=2, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.EastWest, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
]
self.subarrays = [
Subarray(subarray_number=0, required_seismic_anchors=4, row_count=10, column_count=2, row_counted_geometrically=True, column_counted_geometrically=True),
]
self.subject = MechanicalBomCalculator(self.values, self.panels, self.subarrays)
def build_panel_type_counts(self, corner, north_south, east_west, middle):
return {
PanelType.Corner: corner,
PanelType.NorthSouth: north_south,
PanelType.EastWest: east_west,
PanelType.Middle: middle
}
def test_compute_mechanical_bom(self):
expected_output = {
wire_clip: 80,
link_tray: 9,
left_deflector: 10,
right_deflector: 10,
anchor_plate: 12,
cross_tray_1_1: 3,
dual_tilt_chassis: 26,
dual_tilt_platform: 26,
rubber_foot: 4,
platform_bolt: 104,
front_skirt_1_1: 20,
leading_tray: 11,
ballast: 102,
anchor: 12, # 4 + the 8 seismic anchors
anchor_washer: 12,
module: 40
}
assert_dictionary_equal(self.subject.mechanical_bom(), expected_output)
def test_compute_mechanical_bom_with_fallback_used(self):
self.subarrays = [
Subarray(subarray_number=0, required_seismic_anchors=4, row_count=10, column_count=2, row_counted_geometrically=False, column_counted_geometrically=False),
]
self.subject = MechanicalBomCalculator(self.values, self.panels, self.subarrays)
expected_output = {
wire_clip: 80,
link_tray: 9,
left_deflector: 10,
right_deflector: 10,
anchor_plate: 12,
cross_tray_1_1: 3,
dual_tilt_chassis: 26,
dual_tilt_platform: 26,
rubber_foot: 4,
platform_bolt: 104,
front_skirt_1_1: 20,
leading_tray: 11.55,
ballast: 102,
anchor: 12, # 4 + the 8 seismic anchors
anchor_washer: 12,
module: 40
}
assert_dictionary_equal(self.subject.mechanical_bom(), expected_output)

View File

@@ -0,0 +1,118 @@
import unittest
from unittest.mock import MagicMock
from helix.calculators.mechanical_bom_calculator import MechanicalBomCalculator
from helix.constants.anchor_type import AnchorType
from helix.constants.module_type import ModuleType
from helix.constants.panel_type import PanelType
from helix.constants.parts import *
from helix.constants.system_type import SystemType
from helix.models.panel import Panel
from helix.models.subarray import Subarray
from test.test_helpers import assert_dictionary_equal
class MechanicalBomCalculatorWhenDualTilt96CellTest(unittest.TestCase):
def setUp(self):
self.values = MagicMock()
self.values.system_type.return_value = SystemType.dualTilt
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip_Plus
self.values.module_type.return_value = ModuleType.Cell96
"""
Generated using the following parameters:
Building Height = 30
Building Length = 200
Building Width = 76
Parapet Height = 0
Wind Speed = 125
Exposure Category = C
Ballast Block Weight = 13
Max Allowable System Pressure = 10
System type = Dual Tilt
"""
self.panels = [
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=4, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=15, link_tray=2, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=2, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.NorthSouth, ballast=18, link_tray=2, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.EastWest, ballast=17, link_tray=2, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=12, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=1, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=9, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.EastWest, ballast=8, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Middle, ballast=2, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Corner, ballast=5, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=1, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=2, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.EastWest, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
]
self.subarrays = [
Subarray(subarray_number=0, required_seismic_anchors=4, row_count=10, column_count=2, row_counted_geometrically=True, column_counted_geometrically=True)
]
self.subject = MechanicalBomCalculator(self.values, self.panels, self.subarrays)
def build_panel_type_counts(self, corner, north_south, east_west, middle):
return {
PanelType.Corner: corner,
PanelType.NorthSouth: north_south,
PanelType.EastWest: east_west,
PanelType.Middle: middle
}
def test_compute_mechanical_bom(self):
expected_output = {
wire_clip: 80,
link_tray: 9,
left_deflector: 10,
right_deflector: 10,
anchor_plate: 12,
cross_tray: 3,
dual_tilt_chassis: 26,
dual_tilt_platform: 26,
rubber_foot: 4,
platform_bolt: 104,
front_skirt: 20,
leading_tray: 11,
ballast: 102,
anchor: 12,
anchor_washer: 12,
module: 40
}
assert_dictionary_equal(self.subject.mechanical_bom(), expected_output)
def test_compute_mechanical_bom_with_fallback_used(self):
self.subarrays = [
Subarray(subarray_number=0, required_seismic_anchors=4, row_count=4, column_count=5, row_counted_geometrically=True, column_counted_geometrically=True)
]
self.subject = MechanicalBomCalculator(self.values, self.panels, self.subarrays)
expected_output = {
wire_clip: 80,
link_tray: 18,
left_deflector: 10,
right_deflector: 10,
anchor_plate: 12,
cross_tray: 3,
dual_tilt_chassis: 26,
dual_tilt_platform: 26,
rubber_foot: 4,
platform_bolt: 104,
front_skirt: 8,
leading_tray: 5,
ballast: 102,
anchor: 12,
anchor_washer: 12,
module: 40
}
assert_dictionary_equal(self.subject.mechanical_bom(), expected_output)

View File

@@ -0,0 +1,116 @@
import unittest
from unittest.mock import MagicMock
from helix.calculators.mechanical_bom_calculator import MechanicalBomCalculator
from helix.constants.anchor_type import AnchorType
from helix.constants.module_type import ModuleType
from helix.constants.panel_type import PanelType
from helix.constants.parts import *
from helix.constants.system_type import SystemType
from helix.models.panel import Panel
from helix.models.subarray import Subarray
from test.test_helpers import assert_dictionary_equal
class MechanicalBomCalculatorWhenDualTiltPSeriesTest(unittest.TestCase):
def setUp(self):
self.values = MagicMock()
self.values.system_type.return_value = SystemType.dualTilt
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip_Plus
self.values.module_type.return_value = ModuleType.PSeries
"""
Generated using the following parameters:
Building Height = 30
Building Length = 200
Building Width = 76
Parapet Height = 0
Wind Speed = 125
Exposure Category = C
Ballast Block Weight = 13
Max Allowable System Pressure = 10
System type = Dual Tilt
"""
self.panels = [
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=4, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=15, link_tray=2, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=2, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.NorthSouth, ballast=18, link_tray=2, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.EastWest, ballast=17, link_tray=2, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=12, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=1, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=9, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.EastWest, ballast=8, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Middle, ballast=2, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Corner, ballast=5, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=1, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=2, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.EastWest, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
]
self.subarrays = [
Subarray(subarray_number=0, required_seismic_anchors=4, row_count=4, column_count=5, row_counted_geometrically=True, column_counted_geometrically=True)
]
self.subject = MechanicalBomCalculator(self.values, self.panels, self.subarrays)
def build_panel_type_counts(self, corner, north_south, east_west, middle):
return {
PanelType.Corner: corner,
PanelType.NorthSouth: north_south,
PanelType.EastWest: east_west,
PanelType.Middle: middle
}
def test_compute_mechanical_bom(self):
expected_output = {
wire_clip: 80,
link_tray: 18,
left_deflector_1_1: 10,
right_deflector_1_1: 10,
anchor_plate: 12,
cross_tray_1_1: 3,
dual_tilt_chassis: 26,
dual_tilt_platform: 26,
rubber_foot: 4,
platform_bolt: 104,
front_skirt_1_1: 8,
leading_tray: 5,
ballast: 102,
anchor: 12, # 4 + the 8 seismic anchors
anchor_washer: 12,
module: 40
}
assert_dictionary_equal(self.subject.mechanical_bom(), expected_output)
def test_compute_mechanical_bom_with_fallback_used(self):
self.subarrays = [
Subarray(subarray_number=0, required_seismic_anchors=4, row_count=4, column_count=5, row_counted_geometrically=True, column_counted_geometrically=True)
]
self.subject = MechanicalBomCalculator(self.values, self.panels, self.subarrays)
expected_output = {
wire_clip: 80,
link_tray: 18,
left_deflector_1_1: 10,
right_deflector_1_1: 10,
anchor_plate: 12,
cross_tray_1_1: 3,
dual_tilt_chassis: 26,
dual_tilt_platform: 26,
rubber_foot: 4,
platform_bolt: 104,
front_skirt_1_1: 8,
leading_tray: 5,
ballast: 102,
anchor: 12, # 4 + the 8 seismic anchors
anchor_washer: 12,
module: 40
}
assert_dictionary_equal(self.subject.mechanical_bom(), expected_output)

View File

@@ -0,0 +1,110 @@
import unittest
from unittest.mock import MagicMock
from helix.calculators.mechanical_bom_calculator import MechanicalBomCalculator
from helix.constants.anchor_type import AnchorType
from helix.constants.module_type import ModuleType
from helix.constants.panel_type import PanelType
from helix.constants.parts import *
from helix.constants.system_type import SystemType
from helix.models.panel import Panel
from helix.models.subarray import Subarray
from test.test_helpers import assert_dictionary_equal
class MechanicalBomCalculatorWhenSingleTilt128CellTest(unittest.TestCase):
def setUp(self):
self.values = MagicMock()
self.values.system_type.return_value = SystemType.singleTilt
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip_Plus
self.values.module_type.return_value = ModuleType.Cell128
"""
Generated using the following parameters:
Building Height = 30
Building Length = 200
Building Width = 76
Parapet Height = 0
Wind Speed = 125
Exposure Category = C
Anchor type = OMG PowerGrip Plus
Ballast Block Weight = 13
Max Allowable System Pressure = 10
System type = Single Tilt
"""
panels = [
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=6, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=12, link_tray=1, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=14, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.EastWest, ballast=9, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Corner, ballast=14, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=10, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.EastWest, ballast=6, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Middle, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Corner, ballast=9, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=6, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=8, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.NorthSouth, ballast=6, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.EastWest, ballast=4, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=2, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=11, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=8, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=7, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=7, panel_type=PanelType.Middle, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=8, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=1),
Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=1),
Panel(wind_zone=8, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=1),
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=6, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=9, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=1),
Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=13, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=5, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=9, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=10, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=10, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=10, panel_type=PanelType.EastWest, ballast=1, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1),
Panel(wind_zone=10, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=1)
]
subarrays = [
Subarray(subarray_number=0, required_seismic_anchors=2, row_count=11, column_count=2, row_counted_geometrically=True, column_counted_geometrically=True),
Subarray(subarray_number=1, required_seismic_anchors=0, row_count=11, column_count=2, row_counted_geometrically=True, column_counted_geometrically=True)
]
self.subject = MechanicalBomCalculator(self.values, panels, subarrays)
def test_compute_mechanical_bom(self):
expected_output = {
wire_clip: 88,
single_tilt_chassis: 46.31,
following_tray: 6,
link_tray: 28,
spoiler_1_1: 44,
left_deflector: 11,
right_deflector: 11,
anchor_plate: 15,
cross_tray_1_1: 5,
rubber_foot: 4.4,
front_skirt_1_1: 4,
rear_skirt_1_1: 44,
leading_tray: 6,
ballast: 192,
anchor: 15, # 12 + the 3 seismic anchors
anchor_washer: 15,
module: 44
}
assert_dictionary_equal(self.subject.mechanical_bom(), expected_output)

View File

@@ -0,0 +1,110 @@
import unittest
from unittest.mock import MagicMock
from helix.calculators.mechanical_bom_calculator import MechanicalBomCalculator
from helix.constants.anchor_type import AnchorType
from helix.constants.module_type import ModuleType
from helix.constants.panel_type import PanelType
from helix.constants.parts import *
from helix.constants.system_type import SystemType
from helix.models.panel import Panel
from helix.models.subarray import Subarray
from test.test_helpers import assert_dictionary_equal
class MechanicalBomCalculatorWhenSingleTilt96CellTest(unittest.TestCase):
def setUp(self):
self.values = MagicMock()
self.values.system_type.return_value = SystemType.singleTilt
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip_Plus
self.values.module_type.return_value = ModuleType.Cell96
"""
Generated using the following parameters:
Building Height = 30
Building Length = 200
Building Width = 76
Parapet Height = 0
Wind Speed = 125
Exposure Category = C
Anchor type = OMG PowerGrip Plus
Ballast Block Weight = 13
Max Allowable System Pressure = 10
System type = Single Tilt
"""
panels = [
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=6, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=12, link_tray=1, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=14, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.EastWest, ballast=9, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Corner, ballast=14, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=10, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.EastWest, ballast=6, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Middle, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Corner, ballast=9, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=6, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=8, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.NorthSouth, ballast=6, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.EastWest, ballast=4, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=2, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=11, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=8, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=7, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=7, panel_type=PanelType.Middle, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=8, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=8, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=6, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=9, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=13, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=5, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=9, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=10, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=10, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=10, panel_type=PanelType.EastWest, ballast=1, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=10, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0)
]
subarrays = [
Subarray(subarray_number=0, required_seismic_anchors=2, row_count=2, column_count=24, row_counted_geometrically=True, column_counted_geometrically=True)
]
self.subject = MechanicalBomCalculator(self.values, panels, subarrays)
def test_compute_mechanical_bom(self):
expected_output = {
wire_clip: 88,
single_tilt_chassis: 46.31,
following_tray: 25,
link_tray: 28,
spoiler: 44,
left_deflector: 11,
right_deflector: 11,
anchor_plate: 15,
cross_tray: 5,
rubber_foot: 4.4,
front_skirt: 24,
rear_skirt: 44,
leading_tray: 25,
ballast: 192,
anchor: 15, # 12 + the 3 seismic anchors
anchor_washer: 15,
module: 44
}
assert_dictionary_equal(self.subject.mechanical_bom(), expected_output)

View File

@@ -0,0 +1,110 @@
import unittest
from unittest.mock import MagicMock
from helix.calculators.mechanical_bom_calculator import MechanicalBomCalculator
from helix.constants.anchor_type import AnchorType
from helix.constants.module_type import ModuleType
from helix.constants.panel_type import PanelType
from helix.constants.parts import *
from helix.constants.system_type import SystemType
from helix.models.panel import Panel
from helix.models.subarray import Subarray
from test.test_helpers import assert_dictionary_equal
class MechanicalBomCalculatorWhenSingleTiltPSeriesTest(unittest.TestCase):
def setUp(self):
self.values = MagicMock()
self.values.system_type.return_value = SystemType.singleTilt
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip_Plus
self.values.module_type.return_value = ModuleType.PSeries
"""
Generated using the following parameters:
Building Height = 30
Building Length = 200
Building Width = 76
Parapet Height = 0
Wind Speed = 125
Exposure Category = C
Anchor type = OMG PowerGrip Plus
Ballast Block Weight = 13
Max Allowable System Pressure = 10
System type = Single Tilt
"""
panels = [
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=6, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=12, link_tray=1, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=14, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.EastWest, ballast=9, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=2, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Corner, ballast=14, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=10, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.EastWest, ballast=6, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=3, panel_type=PanelType.Middle, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Corner, ballast=9, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=6, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=8, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.NorthSouth, ballast=6, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.EastWest, ballast=4, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=2, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=11, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=8, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=7, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=7, panel_type=PanelType.Middle, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=8, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=8, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=6, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=9, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=13, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=5, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=9, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=10, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=10, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=10, panel_type=PanelType.EastWest, ballast=1, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
Panel(wind_zone=10, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0)
]
subarrays = [
Subarray(subarray_number=0, required_seismic_anchors=2, row_count=2, column_count=24, row_counted_geometrically=True, column_counted_geometrically=True)
]
self.subject = MechanicalBomCalculator(self.values, panels, subarrays)
def test_compute_mechanical_bom(self):
expected_output = {
wire_clip: 88,
single_tilt_chassis: 46.31,
following_tray: 25,
link_tray: 28,
spoiler_1_1: 44,
left_deflector_1_1: 11,
right_deflector_1_1: 11,
anchor_plate: 15,
cross_tray_1_1: 5,
rubber_foot: 4.4,
front_skirt_1_1: 24,
rear_skirt_1_1: 44,
leading_tray: 25,
ballast: 192,
anchor: 15, # 12 + the 3 seismic anchors
anchor_washer: 15,
module: 44
}
assert_dictionary_equal(self.subject.mechanical_bom(), expected_output)