3 Commits

Author SHA1 Message Date
GotPPay
a5fdc996b6 code refactoring 2017-11-10 16:02:56 +01:00
GotPPay
1eb55606f3 code refactor 2017-11-10 15:49:50 +01:00
GotPPay
51d49f4bcc proximity validator 2017-11-10 01:04:51 +01:00
104 changed files with 887 additions and 8103 deletions

View File

@@ -1 +1 @@
web: gunicorn -c gunicorn_config.py --pythonpath helix main:app
web: python helix/main.py

110
README.md
View File

@@ -1,6 +1,3 @@
[![CircleCI](https://circleci.com/gh/SunPower/Helix_Roof_Calculator.svg?style=svg&circle-token=aacf2ae59dae99075992ed10d1e27f119e223e75)](https://circleci.com/gh/SunPower/Helix_Roof_Calculator)
## Helix Calculator
- [Staging](https://sp-helix-staging.herokuapp.com)
@@ -8,106 +5,7 @@
- [Production](https://helix-calculator.sunpower.com/)
## Local Development and Testing with Docker
##### Dependencies
- Docker: [docs.docker.com/engine/installation](https://docs.docker.com/engine/installation/)
- CircleCi CLI: [Installing and using CircleCi locally](https://circleci.com/docs/2.0/local-jobs/#installing-the-cli-locally)
- Current CircleCi and development image:
[ivannnn/heroku-cedar14-extras:2.0](https://hub.docker.com/r/ivannnn/heroku-cedar14-extras/)
| ivannnn/heroku-cedar14-extras:2.0 |
| ------------- |
| ruby 2.3.5p376 |
| Python 3.5.4 |
| postgresql-9.5 |
| postgresql-client-9.5|
| postgresql-client-9.6 |
| postgresql-client-common |
| postgresql-common |
| postgresql-contrib-9.5 |
| postgresql-server-dev-9.6 |
| redis-server/trusty,now 2:2.8.4-2 amd64 |
| redis-tools/trusty,now 2:2.8.4-2 amd64 |
| google-chrome-stable/stable,now 62.0.3202.94-1 amd64 |
| nodejs/unknown,now 6.12.0-1nodesource1 amd64 |
##### Environment Variables
Set the environment variables for your specific environment. Use the `.env` file below as reference:
```
AWS_S3_BUCKET="..."
AWS_ACCESS_KEY_ID="..."
AWS_SECRET_ACCESS_KEY="..."
SF_BASE_URL="https://test.salesforce.com"
SFDC_ACCESS_KEY_ID="..."
SFDC_SECRET_ACCESS_KEY="..."
```
##### Set up for Develop and Testing
- Run the docker container for the 1st time
```docker run -d --name helix -p 5000:5000 --expose 5000 -t ivannnn/heroku-cedar14-extras:2.0```
- Or re start the docker conatiner
```docker container start helix```
- Copy the code to the container
```docker cp . helix:project```
- Log in the docker container
```docker exec -ti helix bash```
- Run this commands inside the docker conatiner
```
cd project && \
rm -rf env && \
gem install bundler && \
service postgresql start &&\
service redis-server start &&\
export PGPASSWORD=password &&\
export CIRCLE_TEST_REPORTS=$(pwd) &&\
python3.5 -m venv env &&\
source env/bin/activate &&\
pip install invoke &&\
invoke install &&\
npm install &&\
invoke db_migrate
```
##### Important
- Open another terminal tab, this script watches for changes and pass them
to the docker conatiner, which will restart the web server
```./watch.sh```
##### Run the server
```invoke serve_debug```
##### Test locally without CircleCi
```invoke test_ci```
##### Test locally with CircleCi
- Go to the project dir
- ```circleci build```
## OS steps wihout Docker
### Setup
#### macOS systems
@@ -386,9 +284,3 @@ docker exec -it helixroofcalculator_helix_1 invoke db_migrate
```
Debugging is possible directly from PyCharm, all code changes are transparent between host and container.
## Database schema
![Database Schema](documentation/db_schema.png)

58
circle.yml Normal file
View File

@@ -0,0 +1,58 @@
machine:
python:
version: 3.5.1
node:
version: 6.1.0
dependencies:
pre:
- pip install invoke
override:
- invoke install
- invoke update_version
database:
override:
- createdb test
- createdb pivotal
- echo "CREATE ROLE pivotal WITH UNENCRYPTED PASSWORD 'password';" | psql -U postgres
- echo "ALTER ROLE pivotal WITH LOGIN;" | psql -U postgres
- echo "GRANT SELECT, UPDATE, INSERT ON ALL TABLES IN SCHEMA test.public TO pivotal;" | psql -U postgres
- echo "GRANT CREATE, CONNECT ON DATABASE test TO pivotal;" | psql -U postgres
- echo "GRANT SELECT, UPDATE, INSERT ON ALL TABLES IN SCHEMA pivotal.public TO pivotal;" | psql -U postgres
- echo "GRANT CREATE, CONNECT ON DATABASE pivotal TO pivotal;" | psql -U postgres
- PYTHONPATH=.:$PYTHONPATH alembic upgrade head
test:
override:
- invoke test_ci
deployment:
staging:
branch: master
commands:
- invoke update_heroku_version staging
- "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow"
- git push -f git@heroku.com:sp-helix-staging.git $CIRCLE_SHA1:refs/heads/master
- heroku run --app sp-helix-staging invoke db_migrate
- rake ci:deliver
preprod:
branch: preprod
commands:
- invoke update_heroku_version preprod
- "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow"
- git push -f git@heroku.com:sp-helix-preprod.git $CIRCLE_SHA1:refs/heads/master
- heroku run --app sp-helix-preprod invoke db_migrate
- rake ci:deliver
production:
tag: /release-.*/
commands:
- invoke update_heroku_version production
- "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow"
- git push -f git@heroku.com:sp-helix-production.git $CIRCLE_SHA1:refs/heads/master
- heroku run --app sp-helix-production invoke db_migrate
- rake ci:deliver
notify:
webhooks:
- url: http://pulse.pivotallabs.com/projects/03ba990f-b8f5-4508-b4c1-19038b2cb791/status

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

BIN
dump.rdb

Binary file not shown.

View File

@@ -1,13 +0,0 @@
"""gunicorn WSGI server configuration."""
import multiprocessing
import os
bind = '0.0.0.0:' + os.getenv('PORT', '5000')
max_requests = 1000
worker_class = 'meinheld.gmeinheld.MeinheldWorker'
workers = multiprocessing.cpu_count()
timeout = os.getenv('TIMEOUT', 120)
graceful_timeout = os.getenv('TIMEOUT', 120)
keepalive = 5
daemon = False

View File

@@ -234,43 +234,24 @@ class DXFHelper(object):
node_store.add_node(node)
# Optimization: avoid creating thousands of replicated objects
graph_directions_cache = {}
for x in (0, 1, -1):
for y in (0, 1, -1):
if x == y == 0:
continue
graph_directions_cache[(x, y)] = GraphDirection((x, y))
for node in nodes:
if len(node.neighboring_nodes()) == 8:
continue
rotation = math.radians(node.coordinate.rotation)
# Optimization: Avoid replicate calculations thousands of times
x_spacing_cos_rotation = (node.x_spacing * math.cos(rotation))
y_spacing_sin_rotation = (node.y_spacing * math.sin(rotation))
x_spacing_sin_rotation = (node.x_spacing * math.sin(rotation))
y_spacing_cos_rotation = (node.y_spacing * math.cos(rotation))
for x in (0, 1, -1):
for y in (0, 1, -1):
if x == y == 0:
continue
x_spacing = (x * x_spacing_cos_rotation) - (y * y_spacing_sin_rotation)
y_spacing = (x * x_spacing_sin_rotation) + (y * y_spacing_cos_rotation)
rotation = math.radians(node.coordinate.rotation)
x_spacing = (x * node.x_spacing * math.cos(rotation)) - (y * node.y_spacing * math.sin(rotation))
y_spacing = (x * node.x_spacing * math.sin(rotation)) + (y * node.y_spacing * math.cos(rotation))
coordinate = Coordinate(node.coordinate.x + x_spacing, node.coordinate.y + y_spacing, node.coordinate.rotation)
if coordinate.x < 0 or coordinate.y < 0:
continue
# Optimization for `direction = GraphDirection((x, y))`
direction = graph_directions_cache[(x, y)]
direction = GraphDirection((x, y))
if node.has_existing_neighbor(direction):
continue
# FIXME: This is the bottleneck of the loop
# Calling this ~10000 times needs ~20 seconds
neighbor = node_store.find_coordinate(coordinate)
if neighbor:
node.add_neighbor(neighbor, direction)
@@ -436,7 +417,7 @@ class DXFHelper(object):
def __compute_segment_direction(p1, p2):
"""
Computes direction of a segment. Points taken from building outline are assumed to be in counterclockwise order.
:param p1: first point
:param p2: second point
:return: tuple representing orientation ('north', 'south', 'east', 'west') and variation in degrees from ideally
@@ -457,7 +438,7 @@ class DXFHelper(object):
def compute_corner_directions(vertex, prev, next, angle_correction):
"""
Determines if point is located in north/east corner
:param vertex: point located in the corner
:param prev: point previous to vertex, assuming counterclockwise order
:param next: point next to vertex, assuming counterclockwise order
@@ -529,7 +510,7 @@ class DXFHelper(object):
@staticmethod
def __generate_wind_zone__(buildings, scaling_factor, points_callback, panel_orientation):
"""
Important: polygons representing buildings are expected to have points in counterclockwise order
Important: polygons representing buildings are expected to have points in counterclockwise order
"""
wind_zones = []

View File

@@ -2,6 +2,9 @@ import io
import dxfgrabber
from helix.constants.file_validation_error import FileValidationMessage
from helix.models.dxf.dxf_error import OldDxfFormatException
class DXFService(object):
"""
@@ -48,7 +51,6 @@ class DXFService(object):
panels = dxf_helper.generate_panels(modules, translated_modules)
# FIXME: Building a graph with many entities is very slow
node_graph = dxf_helper.build_node_graph(panels, module_constants.panel_spacing)
subarrays = dxf_helper.detect_subarrays(node_graph, panels)
for subarray in subarrays:

View File

@@ -1,26 +0,0 @@
import boto3
import os
import uuid
def s3_upload(bytes_or_file_like, filename=None, file_extension=None):
'''
@bytes_or_file_like: bytes(), open('filepath') or io.StringIO('')
'''
if filename is None:
filename = uuid.uuid4().hex
if file_extension:
filename += file_extension
s3 = boto3.resource('s3',
aws_access_key_id=os.getenv('AWS_ACCESS_KEY_ID'),
aws_secret_access_key=os.getenv('AWS_SECRET_ACCESS_KEY'))
# Default: test environment
bucket_name = os.getenv('AWS_S3_BUCKET', 'sunpower-test-dgplatform-spectrum')
# Assuming bucket already exists
s3.Bucket(bucket_name).put_object(Key=filename, Body=bytes_or_file_like.read(), ACL='public-read')
file_url = 'https://s3.amazonaws.com/{}/{}'.format(bucket_name, filename)
print('Uploaded filename {} to S3: {}'.format(filename, file_url))
return file_url

View File

@@ -5,6 +5,7 @@ from helix.presenters.panel_presenter import ProjectPresenter
from helix.session_manager import SessionManager
from helix.constants import redis_constant, sql_constant
from helix.seismic_validator_user_values import SeismicValidatorUserValues
from helix.validators.file_validator import FileValidator
from helix.validators.seismic_anchor_validator import SeismicAnchorValidator
api = Blueprint('api', __name__, template_folder='templates')

View File

@@ -50,7 +50,7 @@ class BomCalculator(object):
row_count = sum(subarray.row_count for subarray in self.subarrays)
column_count = sum(subarray.column_count for subarray in self.subarrays)
parts_list = MechanicalBomCalculator(self.values, self.panels, self.subarrays).mechanical_bom()
ebom_parts_list = EbomCalculator(self.values, ceil(row_count), ceil(column_count), parts_list.get(module), self.subarrays).compute_ebom()
ebom_parts_list = EbomCalculator(self.values, ceil(row_count), ceil(column_count), parts_list.get(module)).compute_ebom()
add_parts_to_list(parts_list, ebom_parts_list)

View File

@@ -1,19 +1,12 @@
from math import ceil
from helix.constants.panel_type import PanelType
from helix.constants.parts import *
# This story askes for this special parts to be showed
# www.pivotaltracker.com/n/projects/1544689/stories/148016595
PARTS_SHOWN_EVEN_WITH_0_ELEMENTS = [
delta_kit_inverter_mount,
delta_kit_inverter_mount_dt
]
def add_parts_to_list(parts_list, parts_to_add, multiplier=1):
for part, quantity in parts_to_add.items():
previous_value = parts_list.get(part) or 0
if quantity != 0 or part in PARTS_SHOWN_EVEN_WITH_0_ELEMENTS:
if quantity != 0:
parts_list[part] = previous_value + quantity * multiplier

View File

@@ -1,3 +1,4 @@
from math import ceil, floor
import copy
from helix.Repositories.graph_repository import GraphRepository
from helix.calculators.ballast_calculator import BallastCalculator

View File

@@ -5,16 +5,14 @@ from helix.constants import ebom_parts
from helix.constants.ebom_parts import *
from helix.constants.parts import wire_clip_large, cable_support, cable_support_lid, channel_nut, sunshade
from helix.constants.system_type import SystemType
from helix.constants.inverter_brand import InverterBrand
class EbomCalculator(object):
def __init__(self, user_values, row_count, column_count, modules_count = None, panels = None):
def __init__(self, user_values, row_count, column_count, modules_count = None):
self.values = user_values
self.row_count = row_count
self.column_count = column_count
self.modules_count = modules_count
self.panels = panels
def resolve_power_monitor_type(self):
module_type = self.values.module_type()
@@ -30,14 +28,6 @@ class EbomCalculator(object):
else:
return monitor_controller_240_v
def resolve_is_delta(self):
if len(self.values.inverter_brands()) > 0:
return self.values.inverter_brands()[0]['inverter_brand_id'] == InverterBrand.DELTA.value
if len(self.values.standalone_inverters()) > 0:
return self.values.standalone_inverters()[0]['model'].get_type == InverterBrand.DELTA.label
# can't determine without data
return False
def compute_ebom(self):
part_list = {}
@@ -46,9 +36,6 @@ class EbomCalculator(object):
monitors = self.values.power_monitors()
module_type = self.values.module_type()
system_type = self.values.system_type()
is_delta = self.resolve_is_delta()
inverter_count = 0
total_ac_run_length = 0
panel_board_counts = [0, 0]
@@ -89,22 +76,16 @@ class EbomCalculator(object):
if monitor['power_source'][0] == 'Switch Gear/External':
add_parts_to_list(part_list, {proper_monitor_controller: 1}, 1)
if is_delta:
clips_amount = inverter_count * self.row_count * 1.15
clips_rounded = int(ceil(clips_amount / 10.0)) * 10
add_parts_to_list(part_list, {wire_clip_large: clips_rounded})
else:
add_parts_to_list(part_list, {wire_clip_large: inverter_count}, self.row_count)
add_parts_to_list(part_list, {wire_clip_large: inverter_count}, self.row_count)
add_parts_to_list(part_list, {stump: 1}, ceil(total_ac_run_length / 4.0))
cable_supports = self.calculate_cable_supports(panel_board_counts, len(standalone_inverters), is_delta)
cable_supports = self.calculate_cable_supports(panel_board_counts, len(standalone_inverters))
add_parts_to_list(part_list, {cable_support: 1, cable_support_lid: 1}, cable_supports)
add_parts_to_list(part_list, {rear_skirt_1_1: -1}, ceil(cable_supports*.38))
add_parts_to_list(part_list, {rear_skirt: -1}, ceil(cable_supports*.38))
dependent_part_list = {}
for part, quantity in part_list.items():
dependent_parts = ebom_parts.dependent_parts(module_type, system_type,is_delta).get(part)
dependent_parts = ebom_parts.dependent_parts(module_type, system_type).get(part)
if dependent_parts:
add_parts_to_list(dependent_part_list, dependent_parts, quantity)
@@ -121,37 +102,21 @@ class EbomCalculator(object):
if inverter['dc_switch']:
add_parts_to_list(part_list, dc_switch_parts, multiplier)
def calculate_cable_supports(self, panel_board_counts, standalone_inverter_count, is_delta):
# There are some tests that don't have panels
if is_delta and self.panels is None:
def calculate_cable_supports(self, panel_board_counts, standalone_inverter_count):
if sum(panel_board_counts) == 0:
return 0
if is_delta:
panels_count = len(self.panels)
if panels_count == 0:
return 0
if self.values.system_type() == SystemType.dualTilt:
Avg_Columns = self.column_count / panels_count
Col2Row_Ratio = self.column_count / self.row_count
Col2Row_Ratio = 1 if Col2Row_Ratio < 1 else Col2Row_Ratio
return ceil(standalone_inverter_count * 1.25 * Avg_Columns * Col2Row_Ratio + Avg_Columns)
else:
Avg_Rows = self.row_count / panels_count
Row2Col_Ratio = self.row_count / self.column_count
Row2Col_Ratio = 1 if Row2Col_Ratio < 1 else Row2Col_Ratio
return ceil(standalone_inverter_count * 1.25 * Avg_Rows * Row2Col_Ratio + Avg_Rows)
if self.values.system_type() == SystemType.dualTilt:
dimension1 = self.column_count
dimension2 = self.row_count
else:
if sum(panel_board_counts) == 0:
return 0
if self.values.system_type() == SystemType.dualTilt:
dimension1 = self.column_count
dimension2 = self.row_count
else:
dimension1 = self.row_count
dimension2 = self.column_count
result = (standalone_inverter_count + panel_board_counts[0] + (2 * panel_board_counts[1])) / sum(panel_board_counts)
result *= dimension1 * max(dimension1 / dimension2, 1)
result += dimension1
return ceil(result)
dimension1 = self.row_count
dimension2 = self.column_count
result = (standalone_inverter_count + panel_board_counts[0] + (2 * panel_board_counts[1])) / sum(panel_board_counts)
result *= dimension1 * max(dimension1 / dimension2, 1)
result += dimension1
return ceil(result)
def get_standalone_inverters(self, power_station):
standalone_inverters = self.values.standalone_inverters()

View File

@@ -5,7 +5,7 @@ from helix.calculators.bom_helper import add_parts_to_list, apply_fudge_factors,
from helix.calculators.subarray_helper import extract_subarray
from helix.constants.module_type import ModuleType
from helix.constants.panel_type import PanelType
from helix.constants.parts import link_tray, cross_tray, ballast, cross_tray_1_1
from helix.constants.parts import link_tray, cross_tray, ballast, cross_tray_1_1, leading_tray
from helix.constants.system_type import SystemType

View File

@@ -1,5 +1,6 @@
from math import ceil, floor
from helix.calculators.subarray_graph import SubarrayGraph
from helix.calculators.subarray_helper import extract_subarray
from helix.constants.global_constants import minimum_racking_capacity

View File

@@ -1,3 +1,4 @@
import copy
from enum import Enum
from helix.constants.system_type import SystemType

View File

@@ -18,18 +18,32 @@ class DualTiltParts(object):
}
def __init__(self, module_type):
self.corner_panel_parts = {
left_deflector_1_1: 1,
right_deflector_1_1: 1,
dual_tilt_chassis: 1.5,
module: 2
}
self.north_south_panel_parts = {
left_deflector_1_1: 1,
right_deflector_1_1: 1,
dual_tilt_chassis: 1.5,
module: 2
}
if module_type == ModuleType.PSeries:
self.corner_panel_parts = {
left_deflector_1_1: 1,
right_deflector_1_1: 1,
dual_tilt_chassis: 1.5,
module: 2
}
self.north_south_panel_parts = {
left_deflector_1_1: 1,
right_deflector_1_1: 1,
dual_tilt_chassis: 1.5,
module: 2
}
else:
self.corner_panel_parts = {
left_deflector: 1,
right_deflector: 1,
dual_tilt_chassis: 1.5,
module: 2
}
self.north_south_panel_parts = {
left_deflector: 1,
right_deflector: 1,
dual_tilt_chassis: 1.5,
module: 2
}
def row_parts(self, module_type):
if module_type == ModuleType.Cell96:

View File

@@ -128,17 +128,9 @@ def standalone_inverter_parts(inverter, system_type, module_type):
if inverter['model'] in InverterType.DELTA.all():
parts = {}
if system_type == SystemType.singleTilt:
parts = {
**parts,
delta_kit_inverter_mount: 1,
delta_kit_inverter_mount_dt: 0
}
parts = {**parts, delta_kit_inverter_mount: 1}
else:
parts = {
**parts,
delta_kit_inverter_mount: 0,
delta_kit_inverter_mount_dt: 1
}
parts = {**parts, delta_kit_inverter_mount_dt: 1}
if inverter['splice_box']:
parts = {**parts, delta_splice_box: 1}
return parts
@@ -152,7 +144,6 @@ def standalone_inverter_parts(inverter, system_type, module_type):
phillips_screw: 4 * multiplier,
ac_inverter_bracket: 1 * multiplier,
hex_bolt_1_2: 4,
ethernet_plug: 1.8,
flat_washer_6: 4,
inverter_link_short: v1_1_inverter_links,
inverter_link_long: v1_1_inverter_links,
@@ -204,30 +195,10 @@ def inverter_parts(inverter, module_type):
stump: 6,
}
def dependent_parts(module_type, system_type, is_delta):
def dependent_parts(module_type, system_type):
v1_1_inverter_links = 0
if system_type == SystemType.singleTilt and (module_type == ModuleType.Cell128 or module_type == ModuleType.PSeries):
v1_1_inverter_links = 1
if is_delta:
monitor_controller_480_v_={
monitor_power_plug: 1,
}
else:
monitor_controller_480_v_={
monitor_power_plug: 1,
flat_washer: 4,
channel_nut: 4,
hex_nut_three_eighths_16: 2,
front_legs: 1,
back_legs: 1,
inverter_link: 2,
inverter_rail: 1,
rubber_foot: 3,
hex_bolt_1_2: 9,
mounting_back_plate: 1,
}
return {
panel_board_2: {
harness_ac_inner: 2,
@@ -275,7 +246,19 @@ def dependent_parts(module_type, system_type, is_delta):
inverter_link_long: v1_1_inverter_links,
inverter_link: -2 * v1_1_inverter_links,
},
monitor_controller_480_v: monitor_controller_480_v_,
monitor_controller_480_v: {
monitor_power_plug: 1,
flat_washer: 4,
channel_nut: 4,
hex_nut_three_eighths_16: 2,
front_legs: 1,
back_legs: 1,
inverter_link: 2,
inverter_rail: 1,
rubber_foot: 3,
hex_bolt_1_2: 9,
mounting_back_plate: 1,
},
monitor_controller_240_v: {},
ac_splice_box: {
hex_bolt_1_2: 4,

View File

@@ -7,10 +7,6 @@ class InverterTypeSMA(IntEnum):
MODEL_20KW = 6
MODEL_24KW = 8
@property
def get_type(self):
return "SMA"
@property
def default_string(self):
return {
@@ -53,10 +49,6 @@ class InverterTypeDelta(IntEnum):
MODEL_60KW = 11
MODEL_80KW = 12
@property
def get_type(self):
return "Delta"
@property
def label(self):
return {

View File

@@ -60,37 +60,14 @@ class DualTilt128CellConstants(object):
return 1, 1
def base_weight(self, panel_type, tray_count):
values_per_panel_type = {
PanelType.Corner: [122.70,
124.55,
126.40,
129.55,
132.71,
135.86,
139.01][tray_count],
PanelType.NorthSouth: [121.63,
123.48,
125.33,
128.48,
131.64,
134.79,
137.94][tray_count],
PanelType.EastWest: [118.28,
120.13,
121.99,
125.14,
128.29,
131.45,
134.60][tray_count],
PanelType.Middle: [117.21,
119.06,
120.92,
124.07,
127.22,
130.38,
133.53][tray_count],
}
return values_per_panel_type.get(panel_type)
if panel_type == PanelType.Corner:
return [108.66, 110.96, 112.11, 116.44, 119.62, 122.80, 125.98][tray_count]
elif panel_type == PanelType.NorthSouth:
return [107.58, 109.88, 111.03, 114.21, 117.39, 120.57, 123.75][tray_count]
elif panel_type == PanelType.EastWest:
return [103.19, 105.49, 105.49, 108.67, 111.85, 115.03, 118.21][tray_count]
else:
return [102.11, 104.41, 104.41, 107.59, 110.77, 113.95, 117.13][tray_count]
def link_tray_thresholds(self, panel_type):
if panel_type == PanelType.Corner or panel_type == PanelType.NorthSouth:

View File

@@ -60,38 +60,23 @@ class DualTilt96CellConstants(object):
return 1, 1
def base_weight(self, panel_type, tray_count):
values_per_panel_type = {
PanelType.Corner: [92.41,
94.26,
96.12,
98.54,
100.97,
103.39,
105.82][tray_count],
PanelType.NorthSouth: [91.63,
93.48,
95.33,
97.76,
100.18,
102.61,
105.03][tray_count],
PanelType.EastWest: [88.00,
89.85,
91.70,
94.13,
96.55,
98.98,
101.40][tray_count],
PanelType.Middle: [87.21,
89.06,
90.92,
93.34,
95.77,
98.19,
100.62][tray_count],
}
return values_per_panel_type.get(panel_type)
if panel_type == PanelType.Corner or panel_type == PanelType.NorthSouth:
return [92.58,
94.31,
96.03,
98.33,
100.63,
102.93,
105.23][tray_count]
else:
return [87.11,
88.84,
89.41,
91.71,
94.01,
96.31,
98.61][tray_count]
def link_tray_thresholds(self, panel_type):
if panel_type == PanelType.Corner or panel_type == PanelType.NorthSouth:
return [7.5, 10, 15]

View File

@@ -60,37 +60,14 @@ class DualTiltPSeriesConstants(object):
return 1, 1
def base_weight(self, panel_type, tray_count):
values_per_panel_type = {
PanelType.Corner: [116.70,
118.55,
120.40,
123.55,
126.71,
129.86,
133.01][tray_count],
PanelType.NorthSouth: [115.63,
117.48,
119.33,
122.48,
125.64,
128.79,
131.94][tray_count],
PanelType.EastWest: [112.28,
114.13,
115.99,
119.14,
122.29,
125.45,
128.60][tray_count],
PanelType.Middle: [111.21,
113.06,
114.92,
118.07,
121.22,
124.38,
127.53][tray_count],
}
return values_per_panel_type.get(panel_type)
if panel_type == PanelType.Corner:
return [103.66, 105.96, 107.11, 111.44, 114.62, 117.80, 120.98][tray_count]
elif panel_type == PanelType.NorthSouth:
return [102.58, 104.88, 106.03, 109.21, 112.39, 115.57, 118.75][tray_count]
elif panel_type == PanelType.EastWest:
return [98.19, 100.49, 100.49, 103.67, 106.85, 110.03, 113.21][tray_count]
else:
return [97.11, 99.41, 99.41, 102.59, 105.77, 108.95, 112.13][tray_count]
def link_tray_thresholds(self, panel_type):
if panel_type == PanelType.Corner or panel_type == PanelType.NorthSouth:

View File

@@ -131,10 +131,14 @@ class SingleTilt128CellConstants(object):
return 1, 1
def base_weight(self, panel_type, tray_count):
return [[68.02, 68.02, 71.17, 74.32],
[65.05, 65.05, 68.20, 71.35],
[65.87, 67.73, 70.88, 74.03],
[63.26, 65.11, 68.26, 71.41]][panel_type.index()][tray_count]
if panel_type == PanelType.Corner:
return [71.91, 71.91, 75.09, 78.27][tray_count]
elif panel_type == PanelType.NorthSouth:
return [65.8, 65.8, 68.98, 72.16][tray_count]
elif panel_type == PanelType.EastWest:
return [69.75, 72.05, 75.23, 78.41][tray_count]
else:
return [65.08, 67.38, 70.56, 73.74][tray_count]
def link_tray_thresholds(self, panel_type):
return [[0, 13.0],

View File

@@ -130,10 +130,10 @@ class SingleTilt96CellConstants(object):
return 1, 1
def base_weight(self, panel_type, tray_count):
return [[51.10, 51.10, 53.52, 55.95],
[48.13, 48.13, 50.55, 52.98],
[49.24, 51.09, 53.52, 55.94],
[48.33, 50.19, 52.61, 55.04]][panel_type.index()][tray_count]
return [[54.50, 54.50, 56.80, 59.10],
[49.47, 49.47, 51.77, 54.07],
[53.42, 55.72, 58.02, 60.32],
[48.75, 51.05, 53.35, 55.65]][panel_type.index()][tray_count]
def link_tray_thresholds(self, panel_type):
return [[0, 12.0],

View File

@@ -130,10 +130,14 @@ class SingleTiltPSeriesConstants(object):
return 1, 1
def base_weight(self, panel_type, tray_count):
return [[65.02, 65.02, 68.17, 71.32],
[62.05, 62.05, 65.20, 68.35],
[62.87, 64.73, 67.88, 71.03],
[60.26, 62.11, 65.26, 68.41]][panel_type.index()][tray_count]
if panel_type == PanelType.Corner:
return [66.91, 66.91, 70.09, 73.27][tray_count]
elif panel_type == PanelType.NorthSouth:
return [60.8, 60.8, 63.98, 67.16][tray_count]
elif panel_type == PanelType.EastWest:
return [64.75, 67.05, 70.23, 73.41][tray_count]
else:
return [60.08, 62.38, 65.56, 68.74][tray_count]
def link_tray_thresholds(self, panel_type):
return [[0, 13.0],

View File

@@ -5,6 +5,8 @@ dual_tilt_chassis = ('514056', 'BASE, CHASSIS, DUAL TILT, HELIX ROOF')
dual_tilt_platform = ('514057', 'PLATFORM, CHASSIS, DUAL TILT, HELIX ROOF')
platform_bolt = ('515063', 'SCREW, CAP, SH, M6 X 1 X 12, 18-8 SS (DIN 912)')
left_deflector = ('513841', 'DEFLECTOR, LH, HELIX ROOF')
right_deflector = ('513842', 'DEFLECTOR, RH, HELIX ROOF')
front_skirt = ('515928', 'FRONT SKIRT, HELIX ROOF')
rear_skirt = ('515929', 'REAR SKIRT, HELIX ROOF')
spoiler = ('513836', 'SPOILER, SINGLE TILT, HELIX ROOF')
@@ -57,10 +59,10 @@ inverter_link_long = ('521797', 'LINK TO ARRAY, SHORT, INVERTER RACK, HELIX ROOF
mounting_back_plate = ('518331', 'MOUNTING BACK PLATE, INVERTER/PANEL BOARD, HELIX ROOF/TRACKER')
sma_12kw_inverter = ('523921', 'INVERTER, SMA, STP, 20000TL-US-10 (SPR-20000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS')
sma_15kw_inverter = ('523922', 'INVERTER, SMA, STP, 24000TL-US-10 (SPR-24000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS')
sma_20kw_inverter = ('523923', 'INVERTER, SMA, STP, 12000TL-US-10 (SPR-12000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS')
sma_24kw_inverter = ('523924', 'INVERTER, SMA, STP, 15000TL-US-10 (SPR-15000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS')
sma_12kw_inverter = ('514686', 'INVERTER, SMA, STP, 12000TL-US-10 (SPR-12000m-3 XXX), AFCI, CONNECTORIZED')
sma_15kw_inverter = ('514687', 'INVERTER, SMA, STP, 15000TL-US-10 (SPR-15000m-3 XXX), AFCI, CONNECTORIZED')
sma_20kw_inverter = ('512676', 'INVERTER, SMA, STP, 20000TL-US-10 (SPR-20000m-3 XXX), AFCI, CONNECTORIZED')
sma_24kw_inverter = ('514685', 'INVERTER, SMA, STP, 24000TL-US-10 (SPR-24000m-3 XXX), AFCI, CONNECTORIZED')
delta_36kw_inverter = ('524952', 'INVERTER, DELTA, M36U_122(MC4), 10INPUT, 36KW, 3PH 480V AC,1000V DC')
delta_42kw_inverter = ('524969', 'INVERTER, DELTA, M42U_122(MC4), 12INPUT, 42KW, 3PH 480V AC,1000V DC')
@@ -157,6 +159,8 @@ all_parts = [
dual_tilt_chassis,
dual_tilt_platform,
platform_bolt,
left_deflector,
right_deflector,
front_skirt,
rear_skirt,
spoiler,

View File

@@ -18,19 +18,32 @@ class SingleTiltParts(object):
}
def __init__(self, module_type):
self.corner_panel_parts = {
module: 1,
single_tilt_chassis: 1,
left_deflector_1_1: 0.5,
right_deflector_1_1: 0.5,
}
self.east_west_panel_parts = {
module: 1,
single_tilt_chassis: 1.5,
left_deflector_1_1: 0.5,
right_deflector_1_1: 0.5
}
if module_type == ModuleType.PSeries:
self.corner_panel_parts = {
module: 1,
single_tilt_chassis: 1,
left_deflector_1_1: 0.5,
right_deflector_1_1: 0.5,
}
self.east_west_panel_parts = {
module: 1,
single_tilt_chassis: 1.5,
left_deflector_1_1: 0.5,
right_deflector_1_1: 0.5
}
else:
self.corner_panel_parts = {
module: 1,
single_tilt_chassis: 1,
left_deflector: 0.5,
right_deflector: 0.5
}
self.east_west_panel_parts = {
module: 1,
single_tilt_chassis: 1.5,
left_deflector: 0.5,
right_deflector: 0.5
}
def row_parts(self, _):
return {}
@@ -55,7 +68,7 @@ class SingleTiltParts(object):
def module(self, module_type):
if module_type == ModuleType.Cell96:
rear_skirt_parts = rear_skirt_1_1
rear_skirt_parts = rear_skirt
spoiler_parts = spoiler
else:
rear_skirt_parts = rear_skirt_1_1

View File

@@ -1,16 +0,0 @@
import re
def convert_camel_case_to_snake_case(name):
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
def convert_dict_keys_to_snake_case(a_dict):
new_dict = {}
for old_key in a_dict.keys():
new_key = convert_camel_case_to_snake_case(old_key)
new_dict[new_key] = a_dict[old_key]
return new_dict

View File

@@ -130,14 +130,8 @@ class NodeQuadTree():
self.nodeList = toKeep
# Return a list of all possible nodes that can be near this point
# Optimization `only_quads_related = True`:
# Avoid replicate a large self.nodeList. Get only the other elements.
# Call this in complement of `self.nodeList`
def retrieve(self, nearPoint, only_quads_related=False):
if only_quads_related:
retNodes = []
else:
retNodes = self.nodeList[:] # = list(self.nodeList)
def retrieve(self, nearPoint):
retNodes = list(self.nodeList)
if self.quads[0] is not None:
index = self.getIndex(nearPoint)

View File

@@ -9,10 +9,7 @@ class ArrayVisualization {
this.isDualTilt = isDualTilt;
this.subarrayDisplay = subarrayDisplay;
this.buildings = buildings;
// Default options
this.scale = 10;
this.panels = [];
}
init() {
@@ -25,12 +22,12 @@ class ArrayVisualization {
this.stage.mouseMoveOutside = true;
this.adjustScale(this.buildings);
this.drawArray(this.container, this.panelData);
this.drawArray(this.container, this.panelData, this.scale);
this.container.x = 0;
this.container.y = 0;
this.stage.addChild(this.container);
this.drawBuildings(this.buildings, this.scale);
this.drawBuildings(this.buildings,this.scale);
this.stage.update();
@@ -79,13 +76,13 @@ class ArrayVisualization {
}
drawBuildings(buildings) {
if (!buildings || buildings.length === 0) {
drawBuildings(buildings, scale) {
if (!buildings) {
console.log("No Buildings!");
return;
}
if (!this.scale) {
if (!scale) {
console.log("No Scale - don't know how big the buildings should be!");
return;
}
@@ -102,14 +99,14 @@ class ArrayVisualization {
line.graphics.beginStroke(color);
line.graphics.moveTo(firstPoint.x * this.scale, firstPoint.y * this.scale);
line.graphics.moveTo(firstPoint.x * scale, firstPoint.y * scale);
for (let j = 1; j < building.length; j++ ) {
nextPoint = building[j];
line.graphics.lineTo(nextPoint.x * this.scale, nextPoint.y * this.scale);
line.graphics.moveTo(nextPoint.x * this.scale, nextPoint.y * this.scale);
line.graphics.lineTo(nextPoint.x * scale ,nextPoint.y * scale);
line.graphics.moveTo(nextPoint.x * scale,nextPoint.y * scale);
}
line.graphics.lineTo(firstPoint.x * this.scale, firstPoint.y * this.scale );
line.graphics.lineTo(firstPoint.x * scale, firstPoint.y * scale );
line.graphics.endStroke();
}
@@ -124,7 +121,7 @@ class ArrayVisualization {
this.container.removeChild(this.panels[i]);
}
this.drawArray(this.container, this.panelData);
this.drawArray(this.container, this.panelData, this.scale);
let selectedPanel = this.selectedPanel;
this.selectedPanel = undefined;
@@ -137,14 +134,18 @@ class ArrayVisualization {
}
drawArray(container, panels) {
this.panels = [];
let treatCoordinatesAsCenterpoints = this.buildings && this.buildings.length > 0;
for (let i = 0; i < panels.length; i++) {
let box = new Panel(panels[i], this.isDualTilt, this.scale, treatCoordinatesAsCenterpoints);
let panel = panels[i];
let box = new Panel(panel, this.isDualTilt, this.scale, treatCoordinatesAsCenterpoints);
container.addChild(box);
this.panels.push(box);
box.on("click", () => {
this.selectPanel(i);
let self = this;
box.on("click", function () {
self.selectPanel(i);
});
}
}

View File

@@ -1,26 +1,22 @@
let AutoUpload = () => {
$("#file_upload").change((e) => {
var ten_megabyte_max_upload = 10000000;
$("#error_container_txt").empty();
if (e.currentTarget.files[0].size < ten_megabyte_max_upload) {
// $('#spinner-panel').show();
$('#spinner-panel').css('width', '100%'); // Workaround for Safari issue
e.currentTarget.form.submit();
} else {
$("#error_container_txt").append('<span class="error_message centered_error" id="error_message_txt">The system configuration you have uploaded is too large. Try splitting your design into two separate text files and run the tool twice.</span>');
}
var ten_megabyte_max_upload = 10000000;
$("#error_container_txt").empty();
if(e.currentTarget.files[0].size < ten_megabyte_max_upload){
e.currentTarget.form.submit();
}else{
$("#error_container_txt").append('<span class="error_message centered_error" id="error_message_txt">The system configuration you have uploaded is too large. Try splitting your design into two separate text files and run the tool twice.</span>');
}
});
$("#dxf_upload").change((e) => {
var ten_megabyte_max_upload = 10000000;
$("#error_container_dxf").empty();
if (e.currentTarget.files[0].size < ten_megabyte_max_upload) {
// $('#spinner-panel').show();
$('#spinner-panel').css('width', '100%'); // Workaround for Safari issue
e.currentTarget.form.submit();
} else {
$("#error_container_dxf").append('<span class="error_message centered_error" id="error_message_dxf">The system configuration you have uploaded is too large. Try splitting your design into two separate text files and run the tool twice.</span>');
}
var ten_megabyte_max_upload = 10000000;
$("#error_container_dxf").empty();
if(e.currentTarget.files[0].size < ten_megabyte_max_upload){
e.currentTarget.form.submit();
}else{
$("#error_container_dxf").append('<span class="error_message centered_error" id="error_message_dxf">The system configuration you have uploaded is too large. Try splitting your design into two separate text files and run the tool twice.</span>');
}
});
};

View File

@@ -8,16 +8,13 @@ import AutoUpload from './auto_upload';
$(document).ready(function () {
AutoUpload();
if (is_csv_available) {
let subarrayDisplay = new SubarrayDisplay();
subarrayDisplay.init($('#current_anchors'), $('#needed_anchors'), $('#subarray_weight'), panel_data);
let arrayVisualization = new ArrayVisualization(panel_data, is_dual_tilt, subarrayDisplay, buildings_coordinates);
arrayVisualization.init();
new ZoomControl(arrayVisualization).init($('#zoom_control'));
new OverlayControl(arrayVisualization).init($('#overlay_control'), $('#legend_container'));
new SeismicControl(arrayVisualization, subarrayDisplay).init($('.seismic_anchor_control'), $("#seismic_save"));
window.arrayVisualization = arrayVisualization;
}
let subarrayDisplay = new SubarrayDisplay();
subarrayDisplay.init($('#current_anchors'), $('#needed_anchors'), $('#subarray_weight'), panel_data);
let arrayVisualization = new ArrayVisualization(panel_data, is_dual_tilt, subarrayDisplay, buildings_coordinates);
arrayVisualization.init();
new ZoomControl(arrayVisualization).init($('#zoom_control'));
new OverlayControl(arrayVisualization).init($('#overlay_control'), $('#legend_container'));
new SeismicControl(arrayVisualization, subarrayDisplay).init($('.seismic_anchor_control'), $("#seismic_save"));
window.arrayVisualization = arrayVisualization;
});

View File

@@ -1,16 +0,0 @@
try:
import ujson as json
except ImportError:
import json
class JsonBuilder:
def build_bom_output(self, rows):
data = []
headers = ['Part #', 'Description', 'Total']
for row in rows:
d = {}
for i, value in enumerate(row):
d[headers[i]] = value
data.append(d)
return json.dumps(data)

View File

@@ -6,10 +6,8 @@ from flask import Flask, request, make_response, session, render_template, \
redirect, url_for
from flask import got_request_exception
from flask.ext import assets
from flask_oauthlib.client import OAuth
from webassets.filter import get_filter
from helix.sales_force import tasks as sf_tasks
from helix.Services.doc_gen_service import DocGenService
from helix.Services.dxf_helper import DXFHelper
from helix.Services.dxf_service import DXFService
@@ -36,20 +34,6 @@ app.register_blueprint(api, url_prefix='/api')
app.secret_key = os.getenv('SECRET_KEY', 'verysecretkey')
app.config['PROFILE'] = True
# Sales Force integrations
oauth = OAuth()
SF_BASE_URL = os.getenv('SFDC_BASE_URL', 'https://test.salesforce.com')
sales_force = oauth.remote_app('sales_force',
consumer_key=os.getenv('SFDC_ACCESS_KEY_ID'),
consumer_secret=os.getenv('SFDC_SECRET_ACCESS_KEY'),
base_url=SF_BASE_URL,
request_token_url=None, # OAuth 2
access_token_method='POST', # Sales Force requirement
access_token_url=SF_BASE_URL + '/services/oauth2/token',
authorize_url=SF_BASE_URL + '/services/oauth2/authorize',
)
assets_env = assets.Environment(app)
assets_env.init_app(app)
assets_env.load_path = [
@@ -83,10 +67,6 @@ def init_rollbar():
got_request_exception.connect(rollbar.contrib.flask.report_exception, app)
def is_sfdc_session():
return 'SFID' in session
@app.route("/")
def index():
return redirect(url_for('site_characterization'))
@@ -129,9 +109,6 @@ def test_dxf():
# wizard steps
@app.route("/site_characterization/", methods=['GET', 'POST'])
def site_characterization():
if is_sfdc_session():
return redirect('/summary/')
db_session = sql_constant.sql_session_maker()
session_manager = SessionManager(session, redis_constant.redis_store, db_session)
site_info_form = InputForm()
@@ -159,7 +136,6 @@ def summary():
context['current_step'] = 2
if context['site_data_available']:
context['project_name'] = session_manager.site.project_name
user_values = session_manager.user_values()
calculator = Calculator(user_values, calculate_panel_data=False)
context['wind_zones'] = user_values.system_type().system_constants().wind_zones
@@ -177,9 +153,6 @@ def summary():
else:
context['no_proceed'] = True
if is_sfdc_session():
context['hide_back'] = True
db_session.close()
return render_template('site_summary.html.jinja', context=context)
@@ -226,7 +199,6 @@ def array_summary():
else:
try:
module_constants = user_values.module_system_constants()
# FIXME: parsing a file with many entities is very slow
dxf_data = DXFService().parse(file_contents,
module_constants,
user_values.system_type(),
@@ -456,70 +428,6 @@ def helix_documentation():
return render_template('helix_documentation.jinja', context=context)
# Sales Force Integration
@app.route('/sales_force_login')
def sales_force_login():
# To test it locally: https://localhost:8443/sales_force_login?SFID=a3cL00000004QsQIAU
sfid = request.args.get('SFID')
if sfid:
session.clear()
session['SFID'] = sfid
return sales_force.authorize(callback=url_for('sales_force_authorized', _external=True, SFID=sfid), SFID=sfid)
else:
return redirect('/')
@app.route('/sales_force_authorized')
def sales_force_authorized():
next_url = url_for('summary')
resp = sales_force.authorized_response()
if resp is None:
print('Unable to authenticate to SFDC.')
return redirect(next_url)
print('New Sales Force - OAuth2 login')
db_session = sql_constant.sql_session_maker()
session_manager = SessionManager(session, redis_constant.redis_store, db_session)
session['sales_force_token'] = resp['access_token']
data = sf_tasks.get_site_characterization_from_sales_force(session, resp['instance_url'])
if data:
session_manager.save_form_submission(data)
return redirect(next_url)
else:
return sales_force_logout()
# FIXME
from flask import jsonify
@app.route("/export-sfdc")
def export_sfdc():
if not is_sfdc_session():
return redirect('/')
db_session = sql_constant.sql_session_maker()
session_manager = SessionManager(session, redis_constant.redis_store, db_session)
session_id = session_manager.session['id']
data = sf_tasks.export_to_sfdc(session_id)
db_session.close()
return jsonify(data)
# return redirect('/download')
@sales_force.tokengetter
def get_sales_force_token(token=None):
return session.get('sales_force_token')
@app.route('/sales_force_logout')
def sales_force_logout():
session.pop('SFID', None)
session.pop('sales_force_token', None)
session.clear()
return redirect('/')
# End of Sales Force Integration
@app.template_filter('format_number')
def format_number(number):
return "{:,g}".format(number)
@@ -549,13 +457,8 @@ def enum():
def main():
host = '0.0.0.0'
debug = bool(os.getenv("FLASK_DEBUG", False))
if os.getenv('FLASK_DEBUG_SSL', None):
port = int(os.getenv('PORT', 8443))
app.run(host=host, port=port, debug=debug, ssl_context='adhoc')
else:
port = int(os.getenv('PORT', 5000))
app.run(host=host, port=port, debug=debug)
port = int(os.getenv('PORT', 5000))
app.run(host=host, port=port, debug=bool(os.getenv("FLASK_DEBUG", False)))
@app.route("/fail-test")

View File

@@ -25,7 +25,6 @@ class GraphNodeStore(list):
dy = node.coordinate.y - coordinate.y
return dx * dx + dy * dy
# FIXME: This is slow if called thousands of times. Do not add any overhead in this method.
def find_coordinate(self, coordinate):
# create and populate the quadtree on first request
if self.quadTree is None:
@@ -34,15 +33,9 @@ class GraphNodeStore(list):
self.quadTree.insert(node)
del self[:]
variance_square = self.variance ** 2
# Optimization: avoid creating a copy of the big list `self.quadTree.nodeList`
# Old: possibilities = self.quadTree.retrieve(coordinate)
possibilities = self.quadTree.nodeList
possibilities = self.quadTree.retrieve(coordinate)
for node in possibilities:
if self.distance_squared(node, coordinate) <= variance_square:
if self.distance_squared(node, coordinate) <= self.variance ** 2:
return node
more_possibilities = self.quadTree.retrieve(coordinate, only_quads_related=True)
for node in more_possibilities:
if self.distance_squared(node, coordinate) <= variance_square:
return node
return None
else:
return None

View File

@@ -1,3 +1,6 @@
import math
from helix.models.coordinate import Coordinate
import sys
class ProjectPresenter(object):
@@ -45,11 +48,14 @@ class ProjectPresenter(object):
# Move coordinates to reflect origin being at top-left
# (as per canvas) instead of bottom-left
height = max(map(lambda row: row['y'], table_data))
first_cell = min(map(lambda row: row['y'], table_data))
# if max_y is not passed - use the panels instead of buildings
if max_y is None:
height = max(map(lambda row: row['y'], table_data))
else:
height = max_y
self.offset = height
for panel in table_data:
panel['y'] = height - panel['y'] + first_cell
panel['y'] = height - panel['y']
return table_data
def get_buildings(self, buildings):
@@ -70,6 +76,10 @@ class ProjectPresenter(object):
point.y = point.y * spacing_y
presentable_building.append(point.__dict__)
for presentable_building in result:
for point in presentable_building:
point['y'] = self.offset - point['y']
return result
def get_max_y(self,buildings, panels):

View File

@@ -1,118 +0,0 @@
import io
import uuid
import requests
from helix.calculators.calculator import Calculator
from helix.constants import redis_constant, sql_constant
from helix.constants.system_type import SystemType
from helix.csv_builder import CsvBuilder
from helix.doc_gen_params_builder import DocGenParamsBuilder
from helix.helpers.camel_case import convert_dict_keys_to_snake_case
from helix.json_builder import JsonBuilder
from helix.presenters.image_presenter import ImagePresenter
from helix.Services.doc_gen_service import DocGenService
from helix.Services.s3_helper import s3_upload
from helix.session_manager import SessionManager
def get_site_characterization_from_sales_force(session, base_url):
'''
@base_url: Avoid URL_NOT_RESET errors
'''
access_token = session['sales_force_token']
sfid = session['SFID']
helix_id = session['id']
url = base_url + '/services/apexrest/v1/HelixRoofDetails'
headers = {'Authorization': 'Bearer {}'.format(access_token)}
result = requests.get(url, headers=headers, params={'SFID': sfid, 'helix_session_id': helix_id})
if result.status_code == 200:
data = result.json()
if data:
data = convert_sales_force_data_format_to_helix(data)
return data
else:
print('Error while getting data from Sales Force: {}'.format(result.status_code))
print(result.content)
def convert_sales_force_data_format_to_helix(data):
data = convert_dict_keys_to_snake_case(data)
if data['system_type'] == 'Single-Tilt':
data['system_type'] = SystemType.singleTilt.value
elif data['system_type'] == 'Dual-Tilt':
data['system_type'] = SystemType.dualTilt.value
data['ballast_block_weight'] = data['ballast_weight']
data['max_system_pressure'] = data['max_psf'] = data['system_pressure']
return data
# data['spectral_response_acceleration']
def export_to_sfdc(session_id):
step = 'Exporting to SFDC'
try:
# 1. Load User Values
step = 'Loading User Values'
session = {'id': session_id}
db_session = sql_constant.sql_session_maker()
session_manager = SessionManager(session, redis_constant.redis_store, db_session)
user_values = session_manager.user_values()
calculator = Calculator(user_values)
# 2. Generate BOM CSV file
step = 'Generating BOM'
bom = calculator.compute_bom()
csv_file = CsvBuilder().build_bom_output(bom)
# 2.1 Generate BOM CSV file
step = 'Generating BOM as JSON'
json_str = JsonBuilder().build_bom_output(bom)
# 3. Generate DOCUMENTATION PDF file
step = 'Generating Documentation'
image_presenter = ImagePresenter(user_values.system_type(), user_values.module_type())
doc_gen_service = DocGenService(requests, DocGenParamsBuilder(user_values, user_values.system_type(), calculator, image_presenter))
document = doc_gen_service.generate() # Call external service
# 4. Get Uploaded DXF file in the Helix system
step = 'Loading uploaded DXF'
dxf_contents = session_manager.site.dxf_file or session_manager.site.cad_file
# dxf_filename = session_manager.site.dxf_file_name
# 5. Save CSV/PDF/DXF files into AWS-S3
step = 'Uploading to S3'
filename = uuid.uuid4().hex
bom_csv_url = s3_upload(io.StringIO(csv_file), filename=filename + '.csv')
bom_json_url = s3_upload(io.StringIO(json_str), filename=filename + '.json')
doc_url = s3_upload(io.BytesIO(document), filename=filename + '.pdf')
if dxf_contents: # Optional
dxf_url = s3_upload(io.StringIO(dxf_contents), filename=filename + '.dxf')
else:
dxf_url = None
# 6. Notify SFDC system with an API request
step = 'Notifying SFDC'
SFDC_API_URL = 'https://localhost:8443/' # FIXME
data = {
'dxf_url': dxf_url,
'bom_csv_url': bom_csv_url,
'bom_json_url': bom_json_url,
'documentation_url': doc_url,
}
print(data)
# result = requests.post(SFDC_API_URL, data=data, timeout=30)
# 7. Internal logs
# if result.status_code != 200: # FIXME
# print('')
# else:
# print('')
db_session.close()
return data
# return result.status_code
except Exception as e:
msg = 'Error while {} for session {}'.format(step, session_id)
print(msg)
raise e

View File

@@ -1,85 +0,0 @@
/*
Animation example, for spinners
*/
.animate-spin {
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
-webkit-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
display: inline-block;
}
@-moz-keyframes spin {
0% {
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@-webkit-keyframes spin {
0% {
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@-o-keyframes spin {
0% {
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@-ms-keyframes spin {
0% {
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes spin {
0% {
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}

View File

@@ -1,11 +1,11 @@
@font-face {
font-family: 'fontello';
src: url('../font/fontello.eot?24283821');
src: url('../font/fontello.eot?24283821#iefix') format('embedded-opentype'),
url('../font/fontello.woff2?24283821') format('woff2'),
url('../font/fontello.woff?24283821') format('woff'),
url('../font/fontello.ttf?24283821') format('truetype'),
url('../font/fontello.svg?24283821#fontello') format('svg');
src: url('../font/fontello.eot?10976371');
src: url('../font/fontello.eot?10976371#iefix') format('embedded-opentype'),
url('../font/fontello.woff2?10976371') format('woff2'),
url('../font/fontello.woff?10976371') format('woff'),
url('../font/fontello.ttf?10976371') format('truetype'),
url('../font/fontello.svg?10976371#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
@@ -15,7 +15,7 @@
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'fontello';
src: url('../font/fontello.svg?24283821#fontello') format('svg');
src: url('../font/fontello.svg?10976371#fontello') format('svg');
}
}
*/
@@ -69,5 +69,4 @@
.icon-info:before { content: '\e80b'; } /* '' */
.icon-close:before { content: '\e80c'; } /* '' */
.icon-sunpower-logo:before { content: '\e80d'; } /* '' */
.icon-upload-cloud:before { content: '\e80e'; } /* '' */
.icon-spin6:before { content: '\e839'; } /* '' */
.icon-upload-cloud:before { content: '\e80e'; } /* '' */

View File

@@ -1023,21 +1023,3 @@ table .right_border_cell {
margin-bottom: 25px;
}
.spinner-panel {
position: fixed;
margin: 0 auto;
top: 0;
left: 0;
width: 0; /* It will be updated to 100% in JS. Workaround for Safari issue with display:none; */
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
z-index: 1;
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
color: #fff;
font-weight: bold;
font-size: 24px;
}

Binary file not shown.

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2017 by original authors @ fontello.com</metadata>
<metadata>Copyright (C) 2016 by original authors @ fontello.com</metadata>
<defs>
<font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
@@ -35,8 +35,6 @@
<glyph glyph-name="sunpower-logo" unicode="&#xe80d;" d="M466 633c-35 61-77 96-152 96-78 0-146-56-146-137 0-76 78-111 138-138l59-26c114-50 211-107 211-248 0-154-124-272-277-272-141 0-247 91-275 228l96 27c13-90 82-164 177-164 94 0 181 73 181 172 0 103-81 138-163 175l-53 24c-103 47-192 99-192 225 0 137 116 225 247 225 98 0 181-50 228-137l-79-50 0 0z m537-353c0-66-3-140 38-197 39-53 114-84 178-84 63 0 132 29 173 79 47 56 43 133 43 202l0 525 99 0 0-552c0-96-7-172-78-244-60-66-148-101-237-101-83 0-168 32-228 90-77 74-86 154-86 255l0 552 98 0 0-525 0 0z m874 562l688-720 0 683 98 0 0-922-688 720 0-680-98 0 0 919z m1255-128l36 0c114 0 230-11 230-155 0-126-92-159-201-159l-65 0 0 314 0 0z m0-405l71 0c74 0 150 9 209 58 55 46 84 119 84 190 0 78-33 155-99 201-64 44-143 47-219 47l-145 0 0-882 99 0 0 386 0 0z m1949-165l285 706 285-706 232 661 106 0-338-927-285 709-285-709-338 927 106 0 232-661z m1128 661l457 0 0-91-359 0 0-262 348 0 0-91-348 0 0-347 359 0 0-91-457 0 0 882z m886-91l29 0c118 0 225-14 225-159 0-137-113-158-224-158l-30 0 0 317 0 0z m0-404l24 0 267-387 120 0-280 395c136 12 221 108 221 244 0 198-156 243-323 243l-127 0 0-882 98 0 0 387 0 0z m-2487 53c0-257-204-453-463-453-253 0-456 205-456 451 0 249 201 454 456 454 259 0 463-195 463-452m-816-2c0-188 150-354 348-354 204 0 363 154 363 354 0 203-157 357-363 357-200 0-348-166-348-357m3755 309c0 24 6 46 18 67 12 21 29 38 50 50 21 12 43 18 67 18 24 0 47-6 68-18 21-12 37-29 49-49 12-21 18-44 18-68 0-24-6-46-17-66-12-21-28-38-49-50-21-13-44-19-69-19-24 0-47 6-68 19-21 12-37 29-49 49-12 21-18 43-18 67l0 0z m17 0c0-21 5-41 16-59 11-18 25-33 43-43 18-11 38-16 59-16 22 0 41 5 59 16 19 10 33 25 44 43 10 18 16 38 16 59 0 21-6 40-16 58-10 18-24 33-43 44-18 11-38 16-60 16-21 0-40-5-59-16-18-10-32-25-43-43-11-19-16-38-16-59l0 0z m166 33c0-9-2-17-6-25-5-7-12-12-20-17l42-70-22 0-37 65-30 0 0-65-18 0 0 158 37 0c18 0 31-4 40-11 10-8 14-19 14-35l0 0z m-73-33l20 0c11 0 19 3 25 8 7 6 10 14 10 25 0 20-12 30-36 30l-19 0 0-63 0 0z" horiz-adv-x="7828" />
<glyph glyph-name="upload-cloud" unicode="&#xe80e;" d="M760 494q100 0 170-68t70-166-70-166-170-68l-190 0 0 190 106 0-176 230-174-230 104 0 0-190-248 0q-74 0-128 52t-54 124q0 74 53 126t129 52q14 0 20-2-2 12-2 38 0 108 78 184t188 76q90 0 160-52t94-134q28 4 40 4z" horiz-adv-x="1000" />
<glyph glyph-name="spin6" unicode="&#xe839;" d="M855 9c-189-190-520-172-705 13-190 190-200 494-28 695 11 13 21 26 35 34 36 23 85 18 117-13 30-31 35-76 16-112-5-9-9-15-16-22-140-151-145-379-8-516 153-153 407-121 542 34 106 122 142 297 77 451-83 198-305 291-510 222l0 1c236 82 492-24 588-252 71-167 37-355-72-493-11-15-23-29-36-42z" horiz-adv-x="1000" />
</font>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -73,18 +73,15 @@
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
$(document).ready(function () {
(0, _auto_upload2.default)();
if (is_csv_available) {
var subarrayDisplay = new _subarray_display2.default();
subarrayDisplay.init($('#current_anchors'), $('#needed_anchors'), $('#subarray_weight'), panel_data);
var arrayVisualization = new _array_visualization2.default(panel_data, is_dual_tilt, subarrayDisplay, buildings_coordinates);
arrayVisualization.init();
new _zoom_control2.default(arrayVisualization).init($('#zoom_control'));
new _overlay_control2.default(arrayVisualization).init($('#overlay_control'), $('#legend_container'));
new _seismic_control2.default(arrayVisualization, subarrayDisplay).init($('.seismic_anchor_control'), $("#seismic_save"));
window.arrayVisualization = arrayVisualization;
}
(0, _auto_upload2.default)();
var subarrayDisplay = new _subarray_display2.default();
subarrayDisplay.init($('#current_anchors'), $('#needed_anchors'), $('#subarray_weight'), panel_data);
var arrayVisualization = new _array_visualization2.default(panel_data, is_dual_tilt, subarrayDisplay, buildings_coordinates);
arrayVisualization.init();
new _zoom_control2.default(arrayVisualization).init($('#zoom_control'));
new _overlay_control2.default(arrayVisualization).init($('#overlay_control'), $('#legend_container'));
new _seismic_control2.default(arrayVisualization, subarrayDisplay).init($('.seismic_anchor_control'), $("#seismic_save"));
window.arrayVisualization = arrayVisualization;
});
/***/ }),
@@ -125,10 +122,7 @@
this.isDualTilt = isDualTilt;
this.subarrayDisplay = subarrayDisplay;
this.buildings = buildings;
// Default options
this.scale = 10;
this.panels = [];
}
_createClass(ArrayVisualization, [{
@@ -143,7 +137,7 @@
this.stage.mouseMoveOutside = true;
this.adjustScale(this.buildings);
this.drawArray(this.container, this.panelData);
this.drawArray(this.container, this.panelData, this.scale);
this.container.x = 0;
this.container.y = 0;
this.stage.addChild(this.container);
@@ -206,13 +200,13 @@
}
}, {
key: 'drawBuildings',
value: function drawBuildings(buildings) {
if (!buildings || buildings.length === 0) {
value: function drawBuildings(buildings, scale) {
if (!buildings) {
console.log("No Buildings!");
return;
}
if (!this.scale) {
if (!scale) {
console.log("No Scale - don't know how big the buildings should be!");
return;
}
@@ -229,14 +223,14 @@
line.graphics.beginStroke(color);
line.graphics.moveTo(firstPoint.x * this.scale, firstPoint.y * this.scale);
line.graphics.moveTo(firstPoint.x * scale, firstPoint.y * scale);
for (var j = 1; j < building.length; j++) {
nextPoint = building[j];
line.graphics.lineTo(nextPoint.x * this.scale, nextPoint.y * this.scale);
line.graphics.moveTo(nextPoint.x * this.scale, nextPoint.y * this.scale);
line.graphics.lineTo(nextPoint.x * scale, nextPoint.y * scale);
line.graphics.moveTo(nextPoint.x * scale, nextPoint.y * scale);
}
line.graphics.lineTo(firstPoint.x * this.scale, firstPoint.y * this.scale);
line.graphics.lineTo(firstPoint.x * scale, firstPoint.y * scale);
line.graphics.endStroke();
}
@@ -251,7 +245,7 @@
this.container.removeChild(this.panels[i]);
}
this.drawArray(this.container, this.panelData);
this.drawArray(this.container, this.panelData, this.scale);
var selectedPanel = this.selectedPanel;
this.selectedPanel = undefined;
@@ -267,15 +261,19 @@
value: function drawArray(container, panels) {
var _this2 = this;
this.panels = [];
var treatCoordinatesAsCenterpoints = this.buildings && this.buildings.length > 0;
var _loop = function _loop(i) {
var box = new _panel.Panel(panels[i], _this2.isDualTilt, _this2.scale, treatCoordinatesAsCenterpoints);
var panel = panels[i];
var box = new _panel.Panel(panel, _this2.isDualTilt, _this2.scale, treatCoordinatesAsCenterpoints);
container.addChild(box);
_this2.panels.push(box);
var self = _this2;
box.on("click", function () {
_this2.selectPanel(i);
self.selectPanel(i);
});
};
@@ -24733,32 +24731,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
value: true
});
var AutoUpload = function AutoUpload() {
$("#file_upload").change(function (e) {
var ten_megabyte_max_upload = 10000000;
$("#error_container_txt").empty();
if (e.currentTarget.files[0].size < ten_megabyte_max_upload) {
// $('#spinner-panel').show();
$('#spinner-panel').css('width', '100%'); // Workaround for Safari issue
e.currentTarget.form.submit();
} else {
$("#error_container_txt").append('<span class="error_message centered_error" id="error_message_txt">The system configuration you have uploaded is too large. Try splitting your design into two separate text files and run the tool twice.</span>');
}
});
$("#file_upload").change(function (e) {
var ten_megabyte_max_upload = 10000000;
$("#error_container_txt").empty();
if (e.currentTarget.files[0].size < ten_megabyte_max_upload) {
e.currentTarget.form.submit();
} else {
$("#error_container_txt").append('<span class="error_message centered_error" id="error_message_txt">The system configuration you have uploaded is too large. Try splitting your design into two separate text files and run the tool twice.</span>');
}
});
$("#dxf_upload").change(function (e) {
var ten_megabyte_max_upload = 10000000;
$("#error_container_dxf").empty();
if (e.currentTarget.files[0].size < ten_megabyte_max_upload) {
// $('#spinner-panel').show();
$('#spinner-panel').css('width', '100%'); // Workaround for Safari issue
e.currentTarget.form.submit();
} else {
$("#error_container_dxf").append('<span class="error_message centered_error" id="error_message_dxf">The system configuration you have uploaded is too large. Try splitting your design into two separate text files and run the tool twice.</span>');
}
});
$("#dxf_upload").change(function (e) {
var ten_megabyte_max_upload = 10000000;
$("#error_container_dxf").empty();
if (e.currentTarget.files[0].size < ten_megabyte_max_upload) {
e.currentTarget.form.submit();
} else {
$("#error_container_dxf").append('<span class="error_message centered_error" id="error_message_dxf">The system configuration you have uploaded is too large. Try splitting your design into two separate text files and run the tool twice.</span>');
}
});
};
exports.default = AutoUpload;

View File

@@ -1,15 +1,6 @@
{% extends "layout.html.jinja" %}
{% set title = "Helix Calculator" %}
{% block contents %}
<script>
var is_csv_available = {{ context['csv_available']|tojson|safe }};
</script>
<div id="spinner-panel" class="spinner-panel">
<p>Uploading files. Please wait, this may take a while.</p>
<i class="icon-spin6 animate-spin"></i>
</div>
{% if not context['csv_available'] %}
<form action="" method="post" enctype="multipart/form-data">
{{ form.csrf_token }}

View File

@@ -1,10 +1,6 @@
{% extends "layout.html.jinja" %}
{% set title = "Helix Calculator" %}
{% block contents %}
{% for warning in context['warning_messages'] %}
<div class="summary_warning">{{ warning.value }}</div>
{% endfor %}
<div class="form_section">
<h3>Download</h3>
</div>
@@ -24,14 +20,6 @@
<button>Download BOM (.txt)</button>
</a>
</div>
{% if 'SFID' in session %}
<div class="download">
<a href="/export-sfdc">
<button>Export documents to Salesforce</button>
</a>
</div>
{% endif %}
{% else %}
Please complete previous steps first!
{% endif %}

View File

@@ -8,10 +8,6 @@
<link href="//cdn.rawgit.com/noelboss/featherlight/1.7.6/release/featherlight.min.css" type="text/css" rel="stylesheet" />
<link rel="shortcut icon" href="https://us.sunpower.com/sites/sunpower/files/favicon.ico">
<link rel="stylesheet" type="text/css" href={{ url_for('static', filename='css/fontello.css') }}>
<link rel="stylesheet" type="text/css" href={{ url_for('static', filename='css/animation.css') }}>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
{% if context['google_analytics_token'] %}
<script>
(function (i, s, o, g, r, a, m) {

View File

@@ -1,9 +1,5 @@
<div class="navigation_buttons">
{% if context['hide_back'] %}
{% else %}
<a class="back button" href="{{ context['steps'][context['current_step'] - 2][2] }}">Back</a>
{% endif %}
<a class="back button" href="{{ context['steps'][context['current_step'] - 2][2] }}">Back</a>
{% if context['steps']|length > context['current_step'] and not context.get('no_proceed') %}
{% if not form or context['override_form'] %}
<a class="button" href="{{ context['steps'][context['current_step']][2] }}" value="Next">Next</a>

View File

@@ -3,11 +3,10 @@
{% block contents %}
{% if context['site_data_available'] %}
<div class="form_section">
<h3>Summary <small>({{ context['project_name'] }})</small></h3>
<h3>Summary</h3>
{% for warning in context['warning_messages'] %}
<div class="summary_warning">{{ warning.value }}</div>
{% endfor %}
<table class="summary_table" id="summary_table">
<tr>
<td colspan="2" class="table_meta_headers">OUTPUTS</td>
@@ -81,13 +80,8 @@
</tr>
</table>
</div>
{% endif %}
{% include "navigation_buttons.html.jinja" %}
{% if 'SFID' in session %}
<small><i>Sales Force project</i> (<a href="/sales_force_logout">Logout</a>)</small>
{% endif %}
{% endblock %}

View File

@@ -60,9 +60,6 @@ class UserValues(object):
def power_monitors(self):
return [power_monitor.to_json() for power_monitor in self.site.power_monitors]
def inverter_brands(self):
return [inverter_brands.to_json() for inverter_brands in self.site.inverter_brands]
def csv(self):
csv_data = self.site.cad_file
if not csv_data:
@@ -159,3 +156,4 @@ class UserValues(object):
else:
return False # should not happen, but if it does rather not show the warning

View File

@@ -1,7 +1,5 @@
import csv
from helix.constants.file_validation_error import FileValidationError, FileValidationMessage
from helix.calculators.coordinates_calculator import CoordinatesCalculator
from helix.models.coordinate import Coordinate
class CsvInputValidator(object):
@@ -30,14 +28,14 @@ class CsvInputValidator(object):
file_validation_chain = [
CsvInputValidator.validate_file_for_panel_types,
# CsvInputValidator.validate_for_spacing, # disabling this feature for the moment
CsvInputValidator.validate_for_spacing,
]
result = self.run_validation_chain(headers, rows, file_validation_chain)
if result:
return FileValidationError(result, None)
return None
except Exception as inst:
except:
return FileValidationError(FileValidationMessage.Generic, None)
# Row Validators
@@ -80,41 +78,28 @@ class CsvInputValidator(object):
def validate_for_spacing(self, headers, rows):
try:
if len(headers) < 13:
return None
coordinates_calculator = CoordinatesCalculator(self.user_values)
min_spacing = self.user_values.module_system_constants().panel_spacing
scaling_factor = self.user_values.module_system_constants().tolerance + 1
spacing_x, spacing_y = self.user_values.module_system_constants().panel_spacing
spacing_coordinates = Coordinate(spacing_x*scaling_factor, spacing_y*scaling_factor,0)
spacing_coordinates_scaled = coordinates_calculator.scale(spacing_coordinates)
min_spacing = (min_spacing[0]*scaling_factor, min_spacing[1]*scaling_factor)
for row_index, row in enumerate(rows):
first_panel = Coordinate(float(row[11]), float(row[12]), float(row[13]))
first_panel_rotated = coordinates_calculator.rotate(first_panel)
first_panel_scaled = coordinates_calculator.scale(first_panel_rotated)
for row_index2, row2 in enumerate(rows):
if row_index2 <= row_index:
continue
second_panel = Coordinate(float(row2[11]), float(row2[12]), float(row2[13]))
second_panel_rotated = coordinates_calculator.rotate(second_panel)
second_panel_scaled = coordinates_calculator.scale(second_panel_rotated)
x1_pos = float(row[11])
y1_pos = float(row[12])
x_diff = round(abs(first_panel_scaled.x - second_panel_scaled.x),3)
y_diff = round(abs(first_panel_scaled.y - second_panel_scaled.y),3)
x2_pos = float(row2[11])
y2_pos = float(row2[12])
if (x_diff < spacing_coordinates_scaled.x) and (y_diff < spacing_coordinates_scaled.y):
x_diff = abs(x1_pos-x2_pos)
y_diff = abs(y1_pos-y2_pos)
if (x_diff < min_spacing[0]) and (y_diff < min_spacing[1]):
return FileValidationMessage.PanelsTooClose
return None
except Exception as inst:
print("ERROR !!! ")
print(inst)
except:
return FileValidationMessage.Generic
# Helpers

View File

@@ -1,3 +1,5 @@
from helix.constants.file_validation_error import FileValidationMessage, FileValidationError
class DxfInputValidator(object):
def __init__(self, _):

4829
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,9 +5,4 @@ cssselect==0.9.1
lxml==3.6.0
mockredispy==2.9.0.11
Flask-Testing==0.4.2
splinter[flask]
pillow==3.3.1
eralchemy==1.1.0
locust==0.8
pylint==1.7.4
pyopenssl==17.5.0

View File

@@ -1,5 +1,3 @@
gunicorn==19.7.1
meinheld==0.6.1
Flask==0.10.1
itsdangerous==0.24
Jinja2==2.8
@@ -15,11 +13,8 @@ requests==2.11.1
svgwrite==1.1.6
Wand==0.4.3
alembic==0.8.7
psycopg2==2.7.3
psycopg2==2.6.2
invoke==0.13.0
dxfgrabber==0.8.1
rollbar==0.13.11
blinker==1.4
Flask-OAuthlib==0.9.4
boto3==1.4.8
ujson==1.35

View File

@@ -1,19 +1,6 @@
module.exports = function (config) {
config.set({
browsers: [ 'ChromeCI' ],
customLaunchers: {
ChromeCI: {
base: 'Chrome',
flags: [
'--headless',
'--disable-gpu',
'--no-sandbox',
'--remote-debugging-port=9222'
]
}
},
singleRun: true,
// basePath: '',
browsers: ['Chrome'],
files: [
{
pattern: 'test_index.js', watched: false

View File

@@ -1,5 +1,4 @@
from invoke import run, task
import os
@task
@@ -18,12 +17,12 @@ def test(ctx):
@task
def test_ci(ctx):
run('nosetests --nologcapture --with-xunit --xunit-file $CIRCLE_TEST_REPORTS/nosetests.xml')
test_js_ci(ctx)
run('nosetests --with-xunit --xunit-file $CIRCLE_TEST_REPORTS/nosetests.xml')
test_js_ci(None)
def test_js_ci(ctx):
run('./node_modules/.bin/karma start spec/javascripts/karma.config.js')
run('karma start spec/javascripts/karma.config.js --single-run --browsers Chrome')
@task
@@ -35,10 +34,9 @@ def test_js(ctx):
def update_version(ctx):
run('echo "import os\n\n\ndef version():\n if os.getenv(\'VERSION\'):\n return os.getenv(\'VERSION\')\n return \'$(git describe --tags)\'" > helix/constants/version.py')
@task
def serve(ctx):
run('SP_DOCGEN_API_KEY=DC97-20AF-567E gunicorn -c gunicorn_config.py --pythonpath helix main:app')
run('PYTHONPATH=. SP_DOCGEN_API_KEY=DC97-20AF-567E python helix/main.py')
@task
@@ -54,23 +52,3 @@ def db_migrate(ctx):
@task
def serve_debug(ctx):
run('PYTHONPATH=. FLASK_DEBUG=1 SP_DOCGEN_API_KEY=DC97-20AF-567E python helix/main.py')
@task
def db_diagram(ctx):
db_uri = os.getenv('DATABASE_URL', 'postgres://pivotal:@localhost:5432/pivotal')
run('eralchemy -i "{}" -o documentation/db_schema.png -x temp audit'.format(db_uri))
@task
def classes_diagrams(ctx):
run('pyreverse -k -o calculators-diagram.png helix/calculators')
run('pyreverse -k -o constants-diagram.png helix/constants')
run('pyreverse -k -o forms-diagram.png helix/forms')
run('pyreverse -k -o models-diagram.png helix/models')
run('pyreverse -k -o validators-diagram.png helix/validators')
run('rm -rf packages*.png ; mv classes.*-diagram.png documentation/')
@task
def serve_ssl(ctx):
run('FLASK_DEBUG_SSL=true PORT=8443 PYTHONPATH=. FLASK_DEBUG=1 SP_DOCGEN_API_KEY=DC97-20AF-567E python helix/main.py')

View File

@@ -28,7 +28,7 @@ class BallastAndTrayCountTest(unittest.TestCase):
eq_(result.ballast_count, 0)
eq_(result.link_tray_count, 0)
eq_(result.cross_tray_count, 0)
eq_(result.system_weight, 65.87)
eq_(result.system_weight, 69.75)
eq_(result.needs_anchor, False)
def test_ballast_no_trays(self):
@@ -38,27 +38,27 @@ class BallastAndTrayCountTest(unittest.TestCase):
eq_(result.ballast_count, 4)
eq_(result.link_tray_count, 0)
eq_(result.cross_tray_count, 0)
eq_(result.system_weight, 65.87)
eq_(result.system_weight, 69.75)
eq_(result.needs_anchor, False)
def test_ballast_and_link_trays(self):
self.force_to_resist = 230
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
eq_(result.ballast_count, 9)
eq_(result.ballast_count, 8)
eq_(result.link_tray_count, 1)
eq_(result.cross_tray_count, 0)
eq_(result.system_weight, 67.73)
eq_(result.system_weight, 72.05)
eq_(result.needs_anchor, False)
def test_ballast_and_oscillate_between_0_and_1_link_trays(self):
self.force_to_resist = 210
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
eq_(result.ballast_count, 8)
eq_(result.ballast_count, 7)
eq_(result.link_tray_count, 1)
eq_(result.cross_tray_count, 0)
eq_(result.system_weight, 67.73)
eq_(result.system_weight, 72.05)
eq_(result.needs_anchor, False)
def test_ballast_and_link_tray_and_cross_tray(self):
@@ -68,17 +68,17 @@ class BallastAndTrayCountTest(unittest.TestCase):
eq_(result.ballast_count, 16)
eq_(result.link_tray_count, 1)
eq_(result.cross_tray_count, 1)
eq_(result.system_weight, 70.88)
eq_(result.system_weight, 75.23)
eq_(result.needs_anchor, False)
def test_ballast_and_link_tray_and_oscillate_between_0_and_1_cross_trays(self):
self.force_to_resist = 330
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
eq_(result.ballast_count, 14)
eq_(result.ballast_count, 13)
eq_(result.link_tray_count, 1)
eq_(result.cross_tray_count, 0)
eq_(result.system_weight, 67.73)
eq_(result.system_weight, 72.05)
eq_(result.needs_anchor, False)
def test_ballast_and_link_tray_and_2_cross_trays(self):
@@ -88,17 +88,17 @@ class BallastAndTrayCountTest(unittest.TestCase):
eq_(result.ballast_count, 25)
eq_(result.link_tray_count, 1)
eq_(result.cross_tray_count, 2)
eq_(result.system_weight, 74.03)
eq_(result.system_weight, 78.41)
eq_(result.needs_anchor, False)
def test_ballast_and_link_tray_and_at_first_2_then_1_cross_trays(self):
self.force_to_resist = 515
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
eq_(result.ballast_count, 23)
eq_(result.ballast_count, 22)
eq_(result.link_tray_count, 1)
eq_(result.cross_tray_count, 2)
eq_(result.system_weight, 74.03)
eq_(result.cross_tray_count, 1)
eq_(result.system_weight, 75.23)
eq_(result.needs_anchor, False)
def test_ballast_and_all_trays_and_anchor(self):
@@ -108,15 +108,15 @@ class BallastAndTrayCountTest(unittest.TestCase):
eq_(result.ballast_count, 35)
eq_(result.link_tray_count, 1)
eq_(result.cross_tray_count, 2)
eq_(result.system_weight, 74.03)
eq_(result.system_weight, 78.41)
eq_(result.needs_anchor, True)
def test_ballast_and_all_trays_and_at_first_anchor_then_no_anchor(self):
self.force_to_resist = 675
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
eq_(result.ballast_count, 31)
eq_(result.ballast_count, 30)
eq_(result.link_tray_count, 1)
eq_(result.cross_tray_count, 2)
eq_(result.system_weight, 74.03)
eq_(result.needs_anchor, True)
eq_(result.system_weight, 78.41)
eq_(result.needs_anchor, False)

View File

@@ -48,23 +48,23 @@ class BallastCalculatorWhenDualTiltAnd128CellTest(unittest.TestCase):
expected_value = {
PanelType.Corner: {
'anchors': [3, 2, 0, 0, 0],
'ballast blocks': [14, 13, 25, 12, 0],
'pressure': ['8.00', '7.61', '12.36', '7.16', '2.40']
'ballast blocks': [15, 14, 25, 12, 0],
'pressure': ['8.14', '7.74', '12.11', '6.88', '2.12']
},
PanelType.NorthSouth: {
'anchors': [3, 2, 0, 0, 0],
'ballast blocks': [6, 7, 21, 9, 0],
'pressure': ['4.79', '5.18', '10.72', '5.93', '2.38']
'ballast blocks': [7, 8, 22, 10, 0],
'pressure': ['4.90', '5.29', '10.83', '6.05', '2.10']
},
PanelType.EastWest: {
'anchors': [3, 2, 0, 0, 0],
'ballast blocks': [7, 7, 21, 10, 0],
'pressure': ['5.18', '5.18', '10.71', '6.29', '2.31']
'ballast blocks': [8, 8, 22, 10, 0],
'pressure': ['5.25', '5.25', '10.78', '5.97', '2.02']
},
PanelType.Middle: {
'anchors': [2, 0, 0, 0, 0],
'ballast blocks': [14, 31, 17, 7, 0],
'pressure': ['7.89', '14.66', '9.07', '5.10', '2.29']
'ballast blocks': [15, 32, 18, 8, 0],
'pressure': ['8.02', '14.73', '9.13', '5.17', '1.99']
},
}
@@ -89,19 +89,19 @@ class BallastCalculatorWhenDualTiltAnd128CellTest(unittest.TestCase):
expected_value = [
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=25, link_tray=2, cross_tray=2, wind_anchors=0,
pressure=12.360800772863891),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=21, link_tray=2, cross_tray=1, wind_anchors=0,
pressure=10.715259768140834),
pressure=12.11),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=22, link_tray=2, cross_tray=1, wind_anchors=0,
pressure=10.83),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0,
pressure=2.3107513954486905),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=14, link_tray=2, cross_tray=1, wind_anchors=3,
pressure=8.001084156290254),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=31, link_tray=2, cross_tray=3, wind_anchors=0,
pressure=14.659635036496352),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=9, link_tray=1, cross_tray=0, wind_anchors=0,
pressure=5.928870759982826),
pressure=2.02),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=15, link_tray=2, cross_tray=1, wind_anchors=3,
pressure=8.14),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=32, link_tray=2, cross_tray=3, wind_anchors=0,
pressure=14.73),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=10, link_tray=1, cross_tray=0, wind_anchors=0,
pressure=6.05),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=44, link_tray=2, cross_tray=4, wind_anchors=0,
pressure=19.907666380420782)
pressure=19.65)
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, raw_data),
@@ -120,20 +120,20 @@ class BallastCalculatorWhenDualTiltAnd128CellTest(unittest.TestCase):
self.values.ballast_block_weight.return_value = 20
expected_value = [
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=29, link_tray=2, cross_tray=2, wind_anchors=0,
pressure=13.923703, fuzzy_wind_zone=True),
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=30, link_tray=2, cross_tray=2, wind_anchors=0,
pressure=14.06, fuzzy_wind_zone=True),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=25, link_tray=2, cross_tray=2, wind_anchors=0,
pressure=12.339897, fuzzy_wind_zone=True),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0,
pressure=2.310751, fuzzy_wind_zone=True),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=9, link_tray=2, cross_tray=1, wind_anchors=4,
pressure=6.047456, fuzzy_wind_zone=True, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=36, link_tray=2, cross_tray=4, wind_anchors=0,
pressure=16.674802, fuzzy_wind_zone=True),
pressure=12.06, fuzzy_wind_zone=True),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0,
pressure=2.41, fuzzy_wind_zone=True),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=10, link_tray=2, cross_tray=1, wind_anchors=4,
pressure=6.18, fuzzy_wind_zone=True, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=37, link_tray=2, cross_tray=4, wind_anchors=0,
pressure=16.75, fuzzy_wind_zone=True),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=12, link_tray=2, cross_tray=0, wind_anchors=0,
pressure=7.137190, fuzzy_wind_zone=True),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=6, link_tray=2, cross_tray=0, wind_anchors=3,
pressure=4.813740, fuzzy_wind_zone=True)
pressure=6.86, fuzzy_wind_zone=True),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=7, link_tray=2, cross_tray=0, wind_anchors=3,
pressure=4.93, fuzzy_wind_zone=True)
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, raw_data),
@@ -155,19 +155,19 @@ class BallastCalculatorWhenDualTiltAnd128CellTest(unittest.TestCase):
expected = [
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1,
ballast=10, link_tray=2, cross_tray=0, pressure=6.376642335766423),
ballast=11, link_tray=2, cross_tray=0, pressure=6.49),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1,
ballast=6, link_tray=1, cross_tray=0, pressure=4.756693860025763),
ballast=6, link_tray=1, cross_tray=0, pressure=4.49),
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1,
ballast=0, link_tray=0, cross_tray=0, pressure=2.3107513954486905),
ballast=0, link_tray=0, cross_tray=0, pressure=2.02),
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0,
ballast=14, link_tray=2, cross_tray=1, pressure=8.001084156290254),
ballast=15, link_tray=2, cross_tray=1, pressure=8.14),
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1,
ballast=16, link_tray=2, cross_tray=1, pressure=8.675476599398884),
ballast=17, link_tray=2, cross_tray=2, pressure=8.81),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1,
ballast=0, link_tray=0, cross_tray=0, pressure=2.3761979390296264),
ballast=0, link_tray=0, cross_tray=0, pressure=2.10),
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0,
ballast=13, link_tray=2, cross_tray=1, pressure=7.610358522971233),
ballast=14, link_tray=2, cross_tray=1, pressure=7.74),
]
result = self.subject.update_ballast(self.c_p_matrix, self.q_z, panels)
@@ -211,37 +211,35 @@ class BallastCalculatorWhenDualTiltAnd128CellTest(unittest.TestCase):
]
expected_value = [
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=25, link_tray=2, cross_tray=2, wind_anchors=0, pressure=12.360800772863891),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=21, link_tray=2, cross_tray=1, wind_anchors=0, pressure=10.715259768140834),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.3107513954486905),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=14, link_tray=2, cross_tray=1, wind_anchors=3, pressure=8.001084156290254),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=31, link_tray=2, cross_tray=3, wind_anchors=0, pressure=14.659635036496352),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=9, link_tray=1, cross_tray=0, wind_anchors=0, pressure=5.928870759982826),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=13, link_tray=2, cross_tray=1, wind_anchors=2, pressure=7.610358522971233)
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=25, link_tray=2, cross_tray=2, wind_anchors=0, pressure=12.11),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=22, link_tray=2, cross_tray=1, wind_anchors=0, pressure=10.83),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.02),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=15, link_tray=2, cross_tray=1, wind_anchors=3, pressure=8.14),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=32, link_tray=2, cross_tray=3, wind_anchors=0, pressure=14.73),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=10, link_tray=1, cross_tray=0, wind_anchors=0, pressure=6.05),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=14, link_tray=2, cross_tray=1, wind_anchors=2, pressure=7.74)
]
print("===\r\n")
print(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panel_data))
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panel_data), expected_value, decimal=2)
def test_ballast_count_when_base_weight_greater_than_uplift(self):
expected = Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.289848)
expected = Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=1.99)
assert self.subject.ballast_tray_and_anchor_count(4, PanelType.Middle, 14, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=19, link_tray=2, cross_tray=2, wind_anchors=2, pressure=7.682057)
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=21, link_tray=2, cross_tray=2, wind_anchors=2, pressure=7.91)
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 14, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=14, link_tray=2, cross_tray=1, wind_anchors=2, pressure=7.894025)
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=15, link_tray=2, cross_tray=2, wind_anchors=2, pressure=8.02)
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 20, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
def test_ballast_blocks_exceeding_tray_capacity(self):
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=22, link_tray=2, cross_tray=3, wind_anchors=2, pressure=7.704719)
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=24, link_tray=2, cross_tray=3, wind_anchors=2, pressure=7.85)
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 12, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
def test_when_max_system_pressure_is_lower_than_base_weight_pressure(self):
max_system_pressure = 0
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=3, pressure=2.289848)
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=3, pressure=1.99)
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 12, max_system_pressure, self.c_p_matrix, self.q_z).almost_equal(
expected,

View File

@@ -49,22 +49,22 @@ class BallastCalculatorWhenDualTiltAnd96CellTest(unittest.TestCase):
PanelType.Corner: {
'anchors': [3, 2, 0, 0, 0],
'ballast blocks': [2, 5, 20, 10, 0],
'pressure': ['3.48', '5.03', '12.91', '7.62', '2.39']
'pressure': ['3.48', '5.03', '12.90', '7.62', '2.40']
},
PanelType.NorthSouth: {
'anchors': [2, 1, 0, 0, 0],
'ballast blocks': [12, 15, 17, 8, 0],
'pressure': ['8.75', '10.30', '11.34', '6.56', '2.37']
'ballast blocks': [11, 15, 17, 8, 0],
'pressure': ['8.24', '10.32', '11.35', '6.59', '2.40']
},
PanelType.EastWest: {
'anchors': [2, 1, 0, 0, 0],
'ballast blocks': [10, 14, 17, 8, 0],
'pressure': ['7.62', '9.69', '11.24', '6.52', '2.28']
'pressure': ['7.55', '9.63', '11.18', '6.46', '2.26']
},
PanelType.Middle: {
'anchors': [2, 0, 0, 0, 0],
'ballast blocks': [2, 22, 12, 5, 0],
'pressure': ['3.34', '13.87', '8.63', '4.85', '2.26']
'pressure': ['3.34', '13.83', '8.59', '4.85', '2.26']
},
}
@@ -90,14 +90,15 @@ class BallastCalculatorWhenDualTiltAnd96CellTest(unittest.TestCase):
# Ballast, link tray, cross tray, anchor count, psf
expected_value = [
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=20, link_tray=2, cross_tray=1, wind_anchors=0, pressure=12.910398406374503),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=17, link_tray=2, cross_tray=1, wind_anchors=0, pressure=11.336414342629482),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.2788844621513946),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=47, link_tray=2, cross_tray=4, wind_anchors=0, pressure=27.082988047808765),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=22, link_tray=2, cross_tray=2, wind_anchors=0, pressure=13.874521912350598),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=8, link_tray=1, cross_tray=0, wind_anchors=0, pressure=6.564223107569722),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=35, link_tray=2, cross_tray=3, wind_anchors=0, pressure=20.8049203187251)
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=20, link_tray=2, cross_tray=1, wind_anchors=0, pressure=12.90),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=17, link_tray=2, cross_tray=1, wind_anchors=0, pressure=11.35),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.26),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=47, link_tray=2, cross_tray=4, wind_anchors=0, pressure=27.07),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=22, link_tray=2, cross_tray=2, wind_anchors=0, pressure=13.82),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=8, link_tray=1, cross_tray=0, wind_anchors=0, pressure=6.59),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=35, link_tray=2, cross_tray=3, wind_anchors=0, pressure=20.79)
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels), expected_value, decimal=2)
def test_update_ballast(self):
@@ -115,19 +116,16 @@ class BallastCalculatorWhenDualTiltAnd96CellTest(unittest.TestCase):
]
expected_value = [
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1, ballast=5, link_tray=0, cross_tray=0, pressure=4.982729083665339),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=2, link_tray=0, cross_tray=0, pressure=3.408745019920319),
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.2788844621513946),
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0, ballast=2, link_tray=1, cross_tray=0, pressure=3.4768525896414344),
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1, ballast=7, link_tray=2, cross_tray=0, pressure=5.98),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.3728884462151396),
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0, ballast=5, link_tray=1, cross_tray=0, pressure=5.030637450199203)
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1, ballast=5, link_tray=0, cross_tray=0, pressure=4.99),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=2, link_tray=0, cross_tray=0, pressure=3.43),
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.26),
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0, ballast=2, link_tray=1, cross_tray=0, pressure=3.48),
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1, ballast=7, link_tray=2, cross_tray=0, pressure=5.94),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.40),
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0, ballast=5, link_tray=1, cross_tray=0, pressure=5.03)
]
result = self.subject.update_ballast(self.c_p_matrix, self.q_z, panels)
print("===")
print(result)
print("===")
assert_array_is_close(result, expected_value, decimal=2)
def test_update_ballast_with_fuzzy_wind_zone(self):
@@ -145,13 +143,13 @@ class BallastCalculatorWhenDualTiltAnd96CellTest(unittest.TestCase):
]
expected_value = [
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1, ballast=9, link_tray=2, cross_tray=0, pressure=7.150517928286853, fuzzy_wind_zone=True),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=5, link_tray=0, cross_tray=0, pressure=4.962529880478088, fuzzy_wind_zone=True),
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.2788844621513946, fuzzy_wind_zone=True),
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0, ballast=9, link_tray=2, cross_tray=0, pressure=7.150517928286853, fuzzy_wind_zone=True),
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1, ballast=11, link_tray=2, cross_tray=1, pressure=8.114382470119523, fuzzy_wind_zone=True),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.3728884462151396, fuzzy_wind_zone=True),
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0, ballast=11, link_tray=2, cross_tray=0, pressure=8.186374501992033, fuzzy_wind_zone=True)
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1, ballast=9, link_tray=2, cross_tray=0, pressure=7.15, fuzzy_wind_zone=True),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=5, link_tray=0, cross_tray=0, pressure=4.99, fuzzy_wind_zone=True),
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.26, fuzzy_wind_zone=True),
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0, ballast=9, link_tray=2, cross_tray=0, pressure=7.15, fuzzy_wind_zone=True),
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1, ballast=11, link_tray=2, cross_tray=1, pressure=8.07, fuzzy_wind_zone=True),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.40, fuzzy_wind_zone=True),
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0, ballast=11, link_tray=2, cross_tray=0, pressure=8.18, fuzzy_wind_zone=True)
]
result = self.subject.update_ballast(self.c_p_matrix, self.q_z, panels)
@@ -194,14 +192,15 @@ class BallastCalculatorWhenDualTiltAnd96CellTest(unittest.TestCase):
]
expected_value = [
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=20, link_tray=2, cross_tray=1, wind_anchors=0, pressure=12.910398406374503),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=17, link_tray=2, cross_tray=1, wind_anchors=0, pressure=11.336414342629482),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.2788844621513946),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=2, link_tray=1, cross_tray=0, wind_anchors=3, pressure=3.4768525896414344),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=22, link_tray=2, cross_tray=2, wind_anchors=0, pressure=13.874521912350598),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=8, link_tray=1, cross_tray=0, wind_anchors=0, pressure=6.564223107569722),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=5, link_tray=1, cross_tray=0, wind_anchors=2, pressure=5.030637450199203)
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=20, link_tray=2, cross_tray=1, wind_anchors=0, pressure=12.90),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=17, link_tray=2, cross_tray=1, wind_anchors=0, pressure=11.35),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.26),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=2, link_tray=1, cross_tray=0, wind_anchors=3, pressure=3.48),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=22, link_tray=2, cross_tray=2, wind_anchors=0, pressure=13.83),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=8, link_tray=1, cross_tray=0, wind_anchors=0, pressure=6.59),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=5, link_tray=1, cross_tray=0, wind_anchors=2, pressure=5.03)
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels), expected_value, decimal=2)
def test_ballast_count_when_base_weight_greater_than_uplift(self):
@@ -213,11 +212,11 @@ class BallastCalculatorWhenDualTiltAnd96CellTest(unittest.TestCase):
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 14, 100, self.c_p_matrix,
self.q_z).almost_equal(
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=45, link_tray=2, cross_tray=4, wind_anchors=0, pressure=18.920438),
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=45, link_tray=2, cross_tray=4, wind_anchors=0, pressure=18.87),
decimal=2)
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 20, 100, self.c_p_matrix,
self.q_z).almost_equal(
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=32, link_tray=2, cross_tray=3, wind_anchors=0, pressure=19.116474),
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=32, link_tray=2, cross_tray=3, wind_anchors=0, pressure=19.07),
decimal=2)
def test_ballast_blocks_exceeding_tray_capacity(self):

View File

@@ -48,23 +48,23 @@ class BallastCalculatorWhenDualTiltAndPSeriesTest(unittest.TestCase):
expected_value = {
PanelType.Corner: {
'anchors': [4, 3, 0, 0, 0],
'ballast blocks': [14, 10, 32, 16, 0],
'pressure': ['8.26', '6.63', '15.76', '9.08', '2.39']
'ballast blocks': [15, 10, 33, 16, 0],
'pressure': ['8.43', '6.38', '15.93', '8.83', '2.12']
},
PanelType.NorthSouth: {
'anchors': [4, 3, 0, 0, 0],
'ballast blocks': [4, 2, 27, 13, 0],
'pressure': ['4.08', '3.22', '13.63', '7.77', '2.37']
'ballast blocks': [5, 2, 28, 14, 0],
'pressure': ['4.22', '2.97', '13.77', '7.90', '2.10']
},
PanelType.EastWest: {
'anchors': [4, 3, 0, 0, 0],
'ballast blocks': [5, 2, 27, 13, 0],
'pressure': ['4.49', '3.19', '13.63', '7.76', '2.30']
'ballast blocks': [6, 3, 28, 14, 0],
'pressure': ['4.58', '3.29', '13.72', '7.86', '2.01']
},
PanelType.Middle: {
'anchors': [3, 2, 0, 0, 0],
'ballast blocks': [10, 10, 23, 11, 0],
'pressure': ['6.51', '6.51', '11.90', '6.92', '2.28']
'ballast blocks': [11, 10, 23, 11, 0],
'pressure': ['6.61', '6.20', '11.59', '6.61', '1.99']
},
}
@@ -104,28 +104,27 @@ class BallastCalculatorWhenDualTiltAndPSeriesTest(unittest.TestCase):
expected_value = {
PanelType.Corner: {
'anchors': [0, 0, 0, 0, 0],
'ballast blocks': [7, 3, 0, 0, 0],
'pressure': ['4.68', '3.37', '2.39', '2.39', '2.39']
'ballast blocks': [8, 3, 0, 0, 0],
'pressure': ['4.79', '3.11', '2.12', '2.12', '2.12']
},
PanelType.NorthSouth: {
'anchors': [0, 0, 0, 0, 0],
'ballast blocks': [3, 0, 0, 0, 0],
'pressure': ['3.35', '2.37', '2.37', '2.37', '2.37']
'pressure': ['3.08', '2.10', '2.10', '2.10', '2.10']
},
PanelType.EastWest: {
'anchors': [0, 0, 0, 0, 0],
'ballast blocks': [3, 0, 0, 0, 0],
'pressure': ['3.28', '2.30', '2.30', '2.30', '2.30']
'ballast blocks': [4, 0, 0, 0, 0],
'pressure': ['3.32', '2.01', '2.01', '2.01', '2.01']
},
PanelType.Middle: {
'anchors': [0, 0, 0, 0, 0],
'ballast blocks': [0, 0, 0, 0, 0],
'pressure': ['2.28', '2.28', '2.28', '2.28', '2.28']
'ballast blocks': [1, 0, 0, 0, 0],
'pressure': ['2.32', '1.99', '1.99', '1.99', '1.99']
},
}
received_table = self.subject.summary_table(self.c_p_matrix, self.q_z)
print("====\r\n", received_table)
eq_(received_table.keys(), expected_value.keys())
for key in expected_value.keys():
received_table[key].pop('warnings')
@@ -144,20 +143,20 @@ class BallastCalculatorWhenDualTiltAndPSeriesTest(unittest.TestCase):
self.values.ballast_block_weight.return_value = 20
expected_value = [
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=32, link_tray=2, cross_tray=3, wind_anchors=0,
pressure=15.764460),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=27, link_tray=2, cross_tray=2, wind_anchors=0,
pressure=13.630342),
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=33, link_tray=2, cross_tray=3, wind_anchors=0,
pressure=15.93),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=28, link_tray=2, cross_tray=2, wind_anchors=0,
pressure=13.77),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0,
pressure=2.299163),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=14, link_tray=2, cross_tray=1, wind_anchors=4,
pressure=8.263513, warnings=[PanelWarnings.MaxPsf]),
pressure=2.01),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=15, link_tray=2, cross_tray=1, wind_anchors=4,
pressure=8.43, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=40, link_tray=2, cross_tray=4, wind_anchors=0,
pressure=18.993076),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=13, link_tray=2, cross_tray=0, wind_anchors=0,
pressure=7.767559),
pressure=18.68),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=14, link_tray=2, cross_tray=0, wind_anchors=0,
pressure=7.90),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=10, link_tray=2, cross_tray=1, wind_anchors=3,
pressure=6.625349),
pressure=6.38),
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, raw_data),
@@ -179,19 +178,19 @@ class BallastCalculatorWhenDualTiltAndPSeriesTest(unittest.TestCase):
expected = [
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1,
ballast=17, link_tray=2, cross_tray=1, pressure=9.492135463546356),
ballast=18, link_tray=2, cross_tray=1, pressure=9.65),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1,
ballast=12, link_tray=2, cross_tray=0, pressure=7.358017551755176),
ballast=13, link_tray=2, cross_tray=0, pressure=7.50),
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1,
ballast=0, link_tray=0, cross_tray=0, pressure=2.299162916291629),
ballast=0, link_tray=0, cross_tray=0, pressure=2.01),
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=4, seismic_anchors=0,
ballast=14, link_tray=2, cross_tray=1, pressure=8.263512601260127),
ballast=15, link_tray=2, cross_tray=1, pressure=8.43),
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1,
ballast=24, link_tray=2, cross_tray=3, pressure=12.375918091809181),
ballast=25, link_tray=2, cross_tray=3, pressure=12.47),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1,
ballast=0, link_tray=0, cross_tray=0, pressure=2.3677610261026105),
ballast=0, link_tray=0, cross_tray=0, pressure=2.10),
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0,
ballast=10, link_tray=2, cross_tray=1, pressure=6.625348784878488),
ballast=10, link_tray=2, cross_tray=1, pressure=6.38),
]
result = self.subject.update_ballast(self.c_p_matrix, self.q_z, panels)
@@ -235,13 +234,13 @@ class BallastCalculatorWhenDualTiltAndPSeriesTest(unittest.TestCase):
]
expected_value = [
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=32, link_tray=2, cross_tray=3, wind_anchors=0, pressure=15.764460),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=27, link_tray=2, cross_tray=2, wind_anchors=0, pressure=13.630342),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.299163),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=14, link_tray=2, cross_tray=1, wind_anchors=4, pressure= 8.263513, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=10, link_tray=2, cross_tray=1, wind_anchors=2, pressure=6.513135),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=13, link_tray=2, cross_tray=0, wind_anchors=0, pressure=7.767559),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=10, link_tray=2, cross_tray=1, wind_anchors=3, pressure=6.625349)
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=33, link_tray=2, cross_tray=3, wind_anchors=0, pressure=15.93),
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=28, link_tray=2, cross_tray=2, wind_anchors=0, pressure=13.77),
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.01),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=15, link_tray=2, cross_tray=1, wind_anchors=4, pressure=8.43, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=10, link_tray=2, cross_tray=1, wind_anchors=2, pressure=6.20),
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=14, link_tray=2, cross_tray=0, wind_anchors=0, pressure=7.90),
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=10, link_tray=2, cross_tray=1, wind_anchors=3, pressure=6.38)
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panel_data), expected_value, decimal=2)
@@ -273,28 +272,28 @@ class BallastCalculatorWhenDualTiltAndPSeriesTest(unittest.TestCase):
self.q_z = 18.43072
self.subject = BallastCalculator(self.values)
expected = Panel(wind_zone=0, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, pressure=3.350659)
expected = Panel(wind_zone=0, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, pressure=3.08)
received = self.subject.ballast_tray_and_anchor_count(0, PanelType.NorthSouth, 16, 8, self.c_p_matrix, self.q_z)
assert received.almost_equal(expected, decimal=2)
def test_ballast_count_when_base_weight_greater_than_uplift(self):
expected = Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.277252)
expected = Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=1.99)
assert self.subject.ballast_tray_and_anchor_count(4, PanelType.Middle, 14, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=14, link_tray=2, cross_tray=2, wind_anchors=3, pressure=6.495729)
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=15, link_tray=2, cross_tray=2, wind_anchors=3, pressure=6.47)
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 14, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=10, link_tray=2, cross_tray=1, wind_anchors=3, pressure=6.513135)
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=11, link_tray=2, cross_tray=1, wind_anchors=3, pressure=6.61)
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 20, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
def test_ballast_blocks_exceeding_tray_capacity(self):
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=17, link_tray=2, cross_tray=2, wind_anchors=3, pressure=6.659545)
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=18, link_tray=2, cross_tray=2, wind_anchors=3, pressure=6.59)
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 12, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
def test_when_max_system_pressure_is_lower_than_base_weight_pressure(self):
max_system_pressure = 0
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=4, pressure=2.277252)
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=4, pressure=1.99)
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 12, max_system_pressure, self.c_p_matrix, self.q_z).almost_equal(
expected,

View File

@@ -54,23 +54,23 @@ class BallastCalculatorWhenSingleTiltAnd128CellTest(unittest.TestCase):
expected_value = {
PanelType.Corner: {
'anchors': [7, 5, 3, 3, 2, 2, 0, 2, 7, 4, 0],
'ballast blocks': [10, 15, 5, 6, 3, 1, 13, 11, 12, 9, 11],
'pressure': ['7.89', '10.77', '4.83', '5.41', '3.68', '2.53', '9.53', '8.38', '9.04', '7.23', '8.29']
'ballast blocks': [9, 14, 5, 5, 3, 1, 13, 11, 11, 8, 11],
'pressure': ['7.43', '10.31', '4.95', '4.95', '3.79', '2.64', '9.55', '8.49', '8.58', '6.76', '8.40']
},
PanelType.NorthSouth: {
'anchors': [6, 5, 3, 2, 0, 1, 0, 2, 6, 4, 0],
'ballast blocks': [14, 6, 1, 15, 19, 13, 12, 6, 12, 1, 10],
'pressure': ['10.11', '5.41', '2.45', '10.68', '12.98', '9.44', '8.87', '5.32', '8.96', '2.45', '7.62']
'pressure': ['10.13', '5.44', '2.47', '10.71', '13.01', '9.46', '8.89', '5.35', '8.98', '2.47', '7.65']
},
PanelType.EastWest: {
'anchors': [5, 4, 2, 2, 1, 0, 0, 2, 6, 1, 0],
'ballast blocks': [12, 7, 2, 1, 15, 21, 12, 6, 12, 14, 6],
'pressure': ['8.94', '6.07', '3.05', '2.47', '10.67', '14.12', '8.85', '5.40', '9.03', '10.09', '5.35']
'ballast blocks': [11, 7, 2, 1, 15, 21, 12, 6, 11, 14, 6],
'pressure': ['8.49', '6.19', '3.16', '2.58', '10.79', '14.25', '8.98', '5.52', '8.58', '10.22', '5.46']
},
PanelType.Middle: {
'anchors': [5, 4, 2, 1, 0, 0, 0, 2, 6, 1, 0],
'ballast blocks': [9, 5, 2, 15, 18, 20, 12, 5, 7, 13, 6],
'pressure': ['7.14', '4.84', '2.97', '10.59', '12.32', '13.56', '8.87', '4.75', '5.99', '9.44', '5.27']
'pressure': ['7.21', '4.91', '3.02', '10.66', '12.39', '13.63', '8.93', '4.82', '6.06', '9.51', '5.32']
},
}
@@ -96,21 +96,21 @@ class BallastCalculatorWhenSingleTiltAnd128CellTest(unittest.TestCase):
expected_value = [
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=1, link_tray=0, cross_tray=0, wind_anchors=2,
pressure=2.532134),
pressure=2.64),
Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=12, link_tray=0, cross_tray=1, wind_anchors=0,
pressure=8.866209),
pressure=8.89),
Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=6, link_tray=2, cross_tray=0, wind_anchors=2,
pressure=5.400562, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=10, link_tray=0, cross_tray=2, wind_anchors=7,
pressure=7.891559, warnings=[PanelWarnings.MaxPsf]),
pressure=5.52, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=9, link_tray=0, cross_tray=2, wind_anchors=7,
pressure=7.43, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=1, wind_anchors=6,
pressure=5.991164, warnings=[PanelWarnings.MaxPsf]),
pressure=6.06, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=1, link_tray=0, cross_tray=0, wind_anchors=4,
pressure=2.446694, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=1, wind_anchors=0,
pressure=9.527003),
pressure=2.47, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=0, wind_anchors=0,
pressure=9.55),
Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=12, link_tray=2, cross_tray=0, wind_anchors=0,
pressure=8.852688)
pressure=8.98)
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels),
@@ -169,19 +169,19 @@ class BallastCalculatorWhenSingleTiltAnd128CellTest(unittest.TestCase):
expected_value = [
Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=11, link_tray=0, cross_tray=1,
wind_anchors=2, pressure=8.376295, warnings=[PanelWarnings.MaxPsf]),
wind_anchors=2, pressure=8.49, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=6, link_tray=0, cross_tray=0,
wind_anchors=2, pressure=5.323465, warnings=[PanelWarnings.MaxPsf]),
wind_anchors=2, pressure=5.35, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=29, link_tray=2, cross_tray=2,
wind_anchors=0, pressure=18.814946),
wind_anchors=0, pressure=18.94),
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=1, link_tray=0, cross_tray=0,
wind_anchors=2, pressure=2.532134),
wind_anchors=2, pressure=2.64),
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=12, link_tray=1, cross_tray=1,
wind_anchors=0, pressure=8.867935),
wind_anchors=0, pressure=8.93),
Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=12, link_tray=0, cross_tray=2,
wind_anchors=6, pressure=8.956827, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=1,
wind_anchors=0, pressure=9.527003)
wind_anchors=6, pressure=8.98, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=0,
wind_anchors=0, pressure=9.55)
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panel_data),
@@ -213,41 +213,41 @@ class BallastCalculatorWhenSingleTiltAnd128CellTest(unittest.TestCase):
self.q_z = 18.446284
expected = Panel(wind_zone=10, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
wind_anchors=0, pressure=1.819845)
wind_anchors=0, pressure=1.87)
assert self.subject.ballast_tray_and_anchor_count(10, PanelType.Middle, 14, 1000, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
expected = Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=17, link_tray=1, cross_tray=1,
wind_anchors=0, pressure=8.810399)
expected = Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=16, link_tray=1, cross_tray=1,
wind_anchors=0, pressure=8.47)
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 14, 1000, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)
expected = Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=12, link_tray=1, cross_tray=1,
wind_anchors=0, pressure=8.867935)
wind_anchors=0, pressure=8.93)
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 20, 1000, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)
def test_ballast_blocks_exceeding_tray_capacity(self):
expected = Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=10, link_tray=0, cross_tray=2,
wind_anchors=7, pressure=7.891559, warnings=[PanelWarnings.MaxPsf])
expected = Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=9, link_tray=0, cross_tray=2,
wind_anchors=7, pressure=7.43, warnings=[PanelWarnings.MaxPsf])
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 20, 1000, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)
expected = Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=1,
wind_anchors=6, pressure=5.991164, warnings=[PanelWarnings.MaxPsf])
wind_anchors=6, pressure=6.06, warnings=[PanelWarnings.MaxPsf])
assert self.subject.ballast_tray_and_anchor_count(8, PanelType.Middle, 20, 1000, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)
def test_ballast_blocks_when_panel_exceeds_max_system_pressure(self):
expected = Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=0,
wind_anchors=1, pressure=4.692301)
wind_anchors=1, pressure=4.76)
assert self.subject.ballast_tray_and_anchor_count(5, PanelType.Middle, 14, 10, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)
expected = Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=14, link_tray=0, cross_tray=2,
wind_anchors=7, pressure=7.776488, warnings=[PanelWarnings.MaxPsf])
expected = Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=2,
wind_anchors=7, pressure=7.49, warnings=[PanelWarnings.MaxPsf])
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 14, 10, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)
@@ -255,7 +255,7 @@ class BallastCalculatorWhenSingleTiltAnd128CellTest(unittest.TestCase):
max_system_pressure = 0
expected = Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
wind_anchors=2, pressure=1.819845)
wind_anchors=2, pressure=1.87)
assert self.subject.ballast_tray_and_anchor_count(5, PanelType.Middle, 12, max_system_pressure,
self.c_p_matrix, self.q_z).almost_equal(
expected,

View File

@@ -54,23 +54,24 @@ class BallastCalculatorWhenSingleTiltAnd96CellTest(unittest.TestCase):
expected_value = {
PanelType.Corner: {
'anchors': [5, 4, 2, 2, 1, 1, 0, 2, 6, 3, 0],
'ballast blocks': [14, 10, 9, 10, 11, 10, 11, 2, 2, 9, 8],
'pressure': ['12.81', '9.67', '8.90', '9.67', '10.43', '9.58', '10.34', '3.47', '3.57', '8.90', '8.05']
'ballast blocks': [14, 10, 9, 9, 11, 10, 10, 2, 2, 9, 8],
'pressure': ['12.93', '9.79', '9.03', '9.03', '10.56', '9.70', '9.70', '3.60', '3.69', '9.03', '8.18']
},
PanelType.NorthSouth: {
'anchors': [5, 4, 2, 2, 0, 1, 0, 1, 5, 3, 0],
'ballast blocks': [5, 2, 5, 5, 15, 7, 9, 13, 3, 2, 7],
'pressure': ['5.74', '3.45', '5.74', '5.65', '13.37', '7.17', '8.79', '11.84', '4.22', '3.36', '7.17']
'pressure': ['5.79', '3.50', '5.70', '5.70', '13.41', '7.23', '8.84', '11.89', '4.26', '3.41', '7.23']
},
PanelType.EastWest: {
'anchors': [4, 3, 1, 1, 1, 0, 0, 1, 5, 1, 0],
'ballast blocks': [6, 6, 10, 9, 8, 16, 9, 13, 3, 7, 4],
'pressure': ['6.62', '6.52', '9.57', '8.81', '8.05', '14.24', '8.81', '11.96', '4.24', '7.29', '4.93']
'pressure': ['6.79', '6.70', '9.75', '8.99', '8.23', '14.42', '8.99', '12.13', '4.41', '7.46', '5.09']
},
PanelType.Middle: {
'anchors': [3, 2, 1, 0, 0, 0, 0, 1, 3, 0, 0],
'ballast blocks': [11, 13, 6, 19, 12, 13, 8, 8, 15, 18, 3],
'pressure': ['10.40', '11.92', '6.49', '16.59', '11.16', '11.92', '8.02', '8.02', '13.54', '15.73', '4.13']
'ballast blocks': [11, 13, 6, 19, 12, 13, 8, 7, 15, 18, 3],
'pressure': ['10.42', '11.95', '6.52', '16.61', '11.19', '11.95', '8.05', '7.29', '13.56', '15.76',
'4.15']
},
}
@@ -95,14 +96,14 @@ class BallastCalculatorWhenSingleTiltAnd96CellTest(unittest.TestCase):
self.values.ballast_block_weight.return_value = 20
expected_value = [
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=25, link_tray=0, cross_tray=2, wind_anchors=0, pressure=21.200142),
Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=9, link_tray=0, cross_tray=1, wind_anchors=0, pressure=8.791605),
Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=28, link_tray=2, cross_tray=2, wind_anchors=0, pressure=23.487752),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=14, link_tray=0, cross_tray=2, wind_anchors=5, pressure=12.810842, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=15, link_tray=1, cross_tray=2, wind_anchors=3, pressure=13.538805, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=2, link_tray=0, cross_tray=0, wind_anchors=3, pressure=3.360677, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=11, link_tray=0, cross_tray=0, wind_anchors=0, pressure=10.337906),
Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=9, link_tray=2, cross_tray=0, wind_anchors=0, pressure=8.812197)
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=25, link_tray=0, cross_tray=2, wind_anchors=0, pressure=21.32),
Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=9, link_tray=0, cross_tray=1, wind_anchors=0, pressure=8.84),
Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=28, link_tray=2, cross_tray=2, wind_anchors=0, pressure=23.65),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=14, link_tray=0, cross_tray=2, wind_anchors=5, pressure=12.93, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=15, link_tray=1, cross_tray=2, wind_anchors=3, pressure=13.56, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=2, link_tray=0, cross_tray=0, wind_anchors=3, pressure=3.41, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=10, link_tray=0, cross_tray=0, wind_anchors=0, pressure=9.70),
Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=9, link_tray=2, cross_tray=0, wind_anchors=0, pressure=8.99)
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels), expected_value, decimal=2)
@@ -159,13 +160,13 @@ class BallastCalculatorWhenSingleTiltAnd96CellTest(unittest.TestCase):
]
expected_value = array([
Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=2, link_tray=0, cross_tray=0, wind_anchors=2, pressure=3.473933),
Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=13, link_tray=0, cross_tray=1, wind_anchors=1, pressure=11.842260),
Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=22, link_tray=2, cross_tray=1, wind_anchors=0, pressure=18.819488),
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=25, link_tray=0, cross_tray=2, wind_anchors=0, pressure=21.200142),
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=8, link_tray=1, cross_tray=0, wind_anchors=0, pressure=8.015213),
Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=1, wind_anchors=5, pressure=4.215623, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=11, link_tray=0, cross_tray=0, wind_anchors=0, pressure=10.337906),
Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=2, link_tray=0, cross_tray=0, wind_anchors=2, pressure=3.60),
Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=13, link_tray=0, cross_tray=1, wind_anchors=1, pressure=11.89),
Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=22, link_tray=2, cross_tray=1, wind_anchors=0, pressure=18.99),
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=25, link_tray=0, cross_tray=2, wind_anchors=0, pressure=21.32),
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=8, link_tray=1, cross_tray=0, wind_anchors=0, pressure=8.05),
Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=1, wind_anchors=5, pressure=4.26, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=10, link_tray=0, cross_tray=0, wind_anchors=0, pressure=9.70),
])
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels), expected_value, decimal=2)
@@ -174,43 +175,43 @@ class BallastCalculatorWhenSingleTiltAnd96CellTest(unittest.TestCase):
assert self.subject.ballast_tray_and_anchor_count(10, PanelType.Middle, 14, 1000, self.c_p_matrix,
30.155851).almost_equal(
Panel(wind_zone=10, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
wind_anchors=0, pressure=1.842977),
wind_anchors=0, pressure=1.86),
decimal=2)
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 14, 1000, self.c_p_matrix,
self.q_z).almost_equal(
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=11, link_tray=1, cross_tray=1,
wind_anchors=0, pressure=7.878697),
wind_anchors=0, pressure=7.91),
decimal=2)
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 20, 1000, self.c_p_matrix,
self.q_z).almost_equal(
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=8, link_tray=1, cross_tray=0,
wind_anchors=0, pressure=8.015213),
wind_anchors=0, pressure=8.05),
decimal=2)
def test_ballast_blocks_exceeding_tray_capacity(self):
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 20, 1000, self.c_p_matrix,
self.q_z).almost_equal(
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=14, link_tray=0, cross_tray=2,
wind_anchors=5, pressure=12.810842, warnings=[PanelWarnings.MaxPsf]),
wind_anchors=5, pressure=12.93, warnings=[PanelWarnings.MaxPsf]),
decimal=2)
assert self.subject.ballast_tray_and_anchor_count(8, PanelType.Middle, 20, 1000, self.c_p_matrix,
self.q_z).almost_equal(
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=15, link_tray=1, cross_tray=2,
wind_anchors=3, pressure=13.538805, warnings=[PanelWarnings.MaxPsf]),
wind_anchors=3, pressure=13.56, warnings=[PanelWarnings.MaxPsf]),
decimal=2)
def test_ballast_blocks_when_panel_exceeds_max_system_pressure(self):
assert self.subject.ballast_tray_and_anchor_count(5, PanelType.Middle, 14, 10, self.c_p_matrix,
self.q_z).almost_equal(
Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
wind_anchors=1, pressure=1.842977),
wind_anchors=1, pressure=1.86),
decimal=2)
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 14, 10, self.c_p_matrix,
self.q_z).almost_equal(
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0,
wind_anchors=6, pressure=1.948606, warnings=[PanelWarnings.MaxPsf]),
wind_anchors=6, pressure=2.08, warnings=[PanelWarnings.MaxPsf]),
decimal=2)
def test_when_max_system_pressure_is_lower_than_base_weight_pressure(self):
@@ -219,7 +220,7 @@ class BallastCalculatorWhenSingleTiltAnd96CellTest(unittest.TestCase):
assert self.subject.ballast_tray_and_anchor_count(5, PanelType.Middle, 12, max_system_pressure, self.c_p_matrix,
self.q_z).almost_equal(
Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
wind_anchors=1, pressure=1.842977),
wind_anchors=1, pressure=1.86),
decimal=2)
def test_uplift(self):

View File

@@ -55,27 +55,27 @@ class BallastCalculatorWhenSingleTiltAndPSeriesTest(unittest.TestCase):
PanelType.Corner: {
'anchors': [7, 5, 3, 3, 2, 1, 0, 2, 7, 4, 0],
'ballast blocks': [5, 11, 3, 4, 2, 15, 13, 9, 7, 6, 11],
'pressure': ['5.07', '8.69', '3.77', '4.37', '3.17', '11.10', '9.80', '7.39', '6.37', '5.67', '8.59']
'pressure': ['5.13', '8.75', '3.83', '4.43', '3.22', '11.16', '9.86', '7.45', '6.33', '5.73', '8.65']
},
PanelType.NorthSouth: {
'anchors': [6, 5, 2, 2, 0, 1, 0, 2, 6, 3, 0],
'ballast blocks': [10, 3, 15, 14, 18, 12, 12, 5, 8, 14, 9],
'pressure': ['8.09', '3.78', '11.11', '10.41', '12.82', '9.20', '9.20', '4.89', '6.89', '10.50', '7.30']
'pressure': ['8.06', '3.74', '11.07', '10.37', '12.88', '9.17', '9.17', '4.85', '6.85', '10.47', '7.26']
},
PanelType.EastWest: {
'anchors': [5, 4, 2, 1, 1, 0, 0, 2, 6, 1, 0],
'ballast blocks': [8, 5, 1, 15, 14, 20, 12, 5, 8, 13, 6],
'pressure': ['6.87', '4.97', '2.50', '11.09', '10.49', '14.11', '9.19', '4.97', '6.87', '9.89', '5.51']
'pressure': ['6.94', '5.04', '2.56', '11.16', '10.56', '14.18', '9.26', '5.04', '6.94', '9.96', '5.57']
},
PanelType.Middle: {
'anchors': [5, 4, 1, 1, 0, 0, 0, 2, 6, 1, 0],
'ballast blocks': [6, 3, 15, 14, 18, 20, 11, 4, 4, 12, 6],
'pressure': ['5.59', '3.68', '11.01', '10.41', '12.82', '14.12', '8.60', '4.29', '4.38', '9.20', '5.44']
'pressure': ['5.60', '3.69', '11.02', '10.42', '12.83', '14.13', '8.51', '4.29', '4.39', '9.21', '5.43']
},
}
received_table = self.subject.summary_table(self.c_p_matrix, self.q_z)
print("===\r\n",received_table)
eq_(received_table.keys(), expected_value.keys())
for key in expected_value.keys():
received_table[key].pop('warnings')
@@ -97,21 +97,21 @@ class BallastCalculatorWhenSingleTiltAndPSeriesTest(unittest.TestCase):
expected_value = [
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=15, link_tray=0, cross_tray=1, wind_anchors=1,
pressure=11.101436),
pressure=11.16),
Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=12, link_tray=0, cross_tray=1, wind_anchors=0,
pressure=9.202700),
pressure=9.17),
Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=5, link_tray=2, cross_tray=0, wind_anchors=2,
pressure=4.967106, warnings=[PanelWarnings.MaxPsf]),
pressure=5.04, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=5, link_tray=0, cross_tray=1, wind_anchors=7,
pressure=5.070833, warnings=[PanelWarnings.MaxPsf]),
pressure=5.13, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=4, link_tray=1, cross_tray=1, wind_anchors=6,
pressure=4.380027, warnings=[PanelWarnings.MaxPsf]),
pressure=4.39, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=14, link_tray=0, cross_tray=2, wind_anchors=3,
pressure=10.503803, warnings=[PanelWarnings.MaxPsf]),
pressure=10.47, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=0, wind_anchors=0,
pressure=9.800333),
pressure=9.86),
Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=12, link_tray=2, cross_tray=0, wind_anchors=0,
pressure=9.188528)
pressure=9.26)
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels),
@@ -170,19 +170,19 @@ class BallastCalculatorWhenSingleTiltAndPSeriesTest(unittest.TestCase):
expected_value = [
Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=9, link_tray=0, cross_tray=0,
wind_anchors=2, pressure=7.388092, warnings=[PanelWarnings.MaxPsf]),
wind_anchors=2, pressure=7.44, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=5, link_tray=0, cross_tray=0,
wind_anchors=2, pressure=4.886296, warnings=[PanelWarnings.MaxPsf]),
wind_anchors=2, pressure=4.85, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=28, link_tray=2, cross_tray=2,
wind_anchors=0, pressure=19.027457),
wind_anchors=0, pressure=19.10),
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=15, link_tray=0, cross_tray=1,
wind_anchors=1, pressure=11.101436),
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=11, link_tray=1, cross_tray=1,
wind_anchors=0, pressure= 8.601449),
wind_anchors=1, pressure=11.16),
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=11, link_tray=1, cross_tray=0,
wind_anchors=0, pressure=8.51),
Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=8, link_tray=0, cross_tray=2,
wind_anchors=6, pressure=6.885441, warnings=[PanelWarnings.MaxPsf]),
wind_anchors=6, pressure=6.85, warnings=[PanelWarnings.MaxPsf]),
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=0,
wind_anchors=0, pressure=9.800333)
wind_anchors=0, pressure=9.86)
]
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panel_data),
@@ -221,22 +221,22 @@ class BallastCalculatorWhenSingleTiltAndPSeriesTest(unittest.TestCase):
def test_ballast_and_tray_count_iterates_on_link_and_cross_trays_changing_weight_and_ballast_requirements(self):
panel = self.subject.ballast_tray_and_anchor_count(3, PanelType.NorthSouth, 20, 17, self.c_p_matrix, self.q_z)
assert_almost_equal(panel.pressure, 10.408820882088209, 2)
assert_almost_equal(panel.pressure, 10.37, 2)
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
expected = Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=16, link_tray=1, cross_tray=1,
wind_anchors=0, pressure=8.722061)
wind_anchors=0, pressure=8.73)
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 14, 1000, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)
expected = Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=11, link_tray=1, cross_tray=1,
wind_anchors=0, pressure=8.601449)
expected = Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=11, link_tray=1, cross_tray=0,
wind_anchors=0, pressure=8.51)
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 20, 1000, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)
def test_ballast_blocks_exceeding_tray_capacity(self):
expected = Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=5, link_tray=0, cross_tray=1,
wind_anchors=7, pressure=5.070833, warnings=[PanelWarnings.MaxPsf])
wind_anchors=7, pressure=5.13, warnings=[PanelWarnings.MaxPsf])
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 20, 1000, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)
@@ -253,7 +253,7 @@ class BallastCalculatorWhenSingleTiltAndPSeriesTest(unittest.TestCase):
self.q_z).almost_equal(expected, decimal=2)
expected = Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=7, link_tray=0, cross_tray=1,
wind_anchors=7, pressure=5.010527, warnings=[PanelWarnings.MaxPsf])
wind_anchors=7, pressure=5.07, warnings=[PanelWarnings.MaxPsf])
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 14, 10, self.c_p_matrix,
self.q_z).almost_equal(expected, decimal=2)

View File

@@ -56,7 +56,7 @@ class CalculatorTest(unittest.TestCase):
self.subject = Calculator(self.values)
expected = [
Subarray(subarray_number=1, origin=Coordinate(0, 0), required_seismic_anchors=436, weight=170698.330000,
Subarray(subarray_number=1, origin=Coordinate(0, 0), required_seismic_anchors=435, weight=170237,
start_row=0, size=863, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=130.5, column_count=98)
]
@@ -70,43 +70,43 @@ class CalculatorTest(unittest.TestCase):
self.subject = Calculator(self.values)
expected = [
Subarray(subarray_number=1, origin=Coordinate(0, 0), required_seismic_anchors=11, weight=23804, start_row=0,
Subarray(subarray_number=1, origin=Coordinate(0, 0), required_seismic_anchors=11, weight=23783, start_row=0,
size=192, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=18, column_count=20),
Subarray(subarray_number=2, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=13271,
Subarray(subarray_number=2, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=13113,
start_row=192, size=96, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=4, column_count=24),
Subarray(subarray_number=3, origin=Coordinate(0, 0), required_seismic_anchors=110, weight=40328,
Subarray(subarray_number=3, origin=Coordinate(0, 0), required_seismic_anchors=110, weight=40406,
start_row=288, size=312, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=25, column_count=29),
Subarray(subarray_number=4, origin=Coordinate(0, 0), required_seismic_anchors=71, weight=23324,
Subarray(subarray_number=4, origin=Coordinate(0, 0), required_seismic_anchors=72, weight=23404,
start_row=600, size=168, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=22, column_count=13),
Subarray(subarray_number=5, origin=Coordinate(0, 0), required_seismic_anchors=74, weight=35170,
Subarray(subarray_number=5, origin=Coordinate(0, 0), required_seismic_anchors=75, weight=35365,
start_row=768, size=234, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=26, column_count=14),
Subarray(subarray_number=6, origin=Coordinate(0, 0), required_seismic_anchors=1, weight=11461,
Subarray(subarray_number=6, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=10897,
start_row=1002, size=96, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=10, column_count=12),
Subarray(subarray_number=7, origin=Coordinate(0, 0), required_seismic_anchors=28, weight=10865,
Subarray(subarray_number=7, origin=Coordinate(0, 0), required_seismic_anchors=29, weight=10951,
start_row=1098, size=96, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=8, column_count=16),
Subarray(subarray_number=8, origin=Coordinate(0, 0), required_seismic_anchors=12, weight=10780,
Subarray(subarray_number=8, origin=Coordinate(0, 0), required_seismic_anchors=11, weight=10596,
start_row=1194, size=96, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=15, column_count=17.5),
Subarray(subarray_number=9, origin=Coordinate(0, 0), required_seismic_anchors=0, weight= 10989,
Subarray(subarray_number=9, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=10544,
start_row=1290, size=96, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=8, column_count=16),
Subarray(subarray_number=10, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=4901,
Subarray(subarray_number=10, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=4819,
start_row=1386, size=48, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=8, column_count=6),
Subarray(subarray_number=11, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=10766,
Subarray(subarray_number=11, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=10857,
start_row=1434, size=96, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=13, column_count=13),
Subarray(subarray_number=12, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=6350,
Subarray(subarray_number=12, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=6330,
start_row=1530, size=54, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=8, column_count=8),
Subarray(subarray_number=13, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=4239,
Subarray(subarray_number=13, origin=Coordinate(0, 0), required_seismic_anchors=0, weight=4201,
start_row=1584, size=48, column_counted_geometrically=False, row_counted_geometrically=False,
row_count=6, column_count=8)
]
@@ -140,15 +140,15 @@ class CalculatorTest(unittest.TestCase):
self.subject = Calculator(self.values)
received_values = self.subject.summary_values()
expected_values = array([
{'label': 'Total System Weight (lbs)', 'value': 2694},
{'label': 'Max PSF', 'value': 7.9},
{'label': 'Avg PSF', 'value': 5.41},
{'label': 'Total System Weight (lbs)', 'value': 2684},
{'label': 'Max PSF', 'value': 8.03},
{'label': 'Avg PSF', 'value': 5.39},
{'label': 'Total Anchors', 'value': 5},
{'label': 'Total Ballast', 'value': 135},
{'label': 'Max Possible System Weight', 'value': 2792.0},
{'label': 'Max System Weight Ballast Block', 'value': 17},
{'label': 'Total Ballast', 'value': 131},
{'label': 'Max Possible System Weight', 'value': 2789.0},
{'label': 'Max System Weight Ballast Block', 'value': 16},
{'label': 'Seismic Anchor Max. Spacing', 'value': 12},
])
assert_array_equal(received_values, expected_values)
@@ -173,13 +173,13 @@ class CalculatorTest(unittest.TestCase):
received_values = self.subject.documentation_summary_values()
expected_values = {
'total_system_weight': 2694,
'max_psf': 7.9,
'ave_psf': 5.41,
'total_system_weight': 2684,
'max_psf': 8.03,
'ave_psf': 5.39,
'total_anchors': 5,
'total_ballast': 135,
'max_possible_system_weight': 2792.0,
'max_system_weight_ballast_block': 17,
'total_ballast': 131,
'max_possible_system_weight': 2789.0,
'max_system_weight_ballast_block': 16,
'seismic_anchor_max_spacing': 12
}
eq_(received_values, expected_values)
@@ -326,8 +326,6 @@ class CalculatorTest(unittest.TestCase):
expected_csv = expected_file.read()
reader = csv.reader(expected_csv.splitlines(), dialect='excel-tab')
expected = array([row for row in reader])
print("EXPECTED")
print(expected)
power_station_1 = PowerStation(
description='1',
@@ -369,8 +367,7 @@ class CalculatorTest(unittest.TestCase):
)
self.site.power_stations = [power_station_1, power_station_2]
print("COMPUTE")
print(self.subject.compute_bom())
assert_array_equal(self.subject.compute_bom(), expected)
def test_documentation_bom(self):
@@ -408,91 +405,94 @@ class CalculatorTest(unittest.TestCase):
self.site.cad_file = csv_content
self.subject = Calculator(self.values)
expected = [('521794', 196),
('521795', 196),
('514056', 1000),
('modules', 1726),
('513843', 263),
('anchors', 263),
('518477', 275),
('513833', 670),
('513844', 214),
('ballast', 6777),
('515928', 261),
('517871', 139),
('514057', 1000),
('515063', 4000),
('512200', 3480),
('514265', 179),
('513303', 1),
('512660', 2),
('512661', 2),
('512662', 4),
('512663', 2),
('518331', 2),
('518058', 2),
('104813', 50),
('107551', 50),
('514865', 50),
('106925', 50),
('523921', 1),
('514438', 2),
('514437', 2),
('512910', 1),
('805615', 2),
('521031', 2),
('512575', 1),
('514698', 1),
('513007', 50),
('114961', 50),
('107549', 100),
('107586', 100),
('512021', 9),
('512199', 140),
('512511', 196),
('512510', 196),
('515929', 0),
('514477', 2),
('515059', 2),
('514697', 1),
('513831', 0),
('513836', 0),
('520301', 0),
('520302', 0),
('520303', 0),
('520306', 0),
('513832', 0),
('514435', 0),
('514436', 0),
('514439', 0),
('514440', 0),
('523922', 0),
('523923', 0),
('523924', 0),
('513299', 0),
('513301', 0),
('514478', 0),
('513300', 0),
('513302', 0),
('513304', 0),
('519008', 0),
('518059', 0),
('105317', 0),
('111147', 0),
('107538', 0),
('516045', 0),
('516043', 0),
('513586', 0),
('507985', 0),
('522020', 0),
('521798', 0),
('521797', 0),
('521363', 0),
('517463', 0)]
expected = [
('104813', 50),
('105317', 0),
('106925', 50),
('107538', 0),
('107549', 100),
('107551', 50),
('107586', 100),
('111147', 0),
('114961', 50),
('507985', 0),
('512021', 9),
('512199', 140),
('512200', 3480),
('512510', 196),
('512511', 196),
('512575', 1),
('512660', 2),
('512661', 2),
('512662', 4),
('512663', 2),
('512676', 0),
('512910', 1),
('513007', 50),
('513299', 0),
('513300', 0),
('513301', 0),
('513302', 0),
('513303', 1),
('513304', 0),
('513586', 0),
('513831', 0),
('513832', 0),
('513833', 670),
('513836', 0),
('513841', 196),
('513842', 196),
('513843', 262),
('513844', 214),
('514056', 1000),
('514057', 1000),
('514265', 179),
('514435', 0),
('514436', 0),
('514437', 2),
('514438', 2),
('514439', 0),
('514440', 0),
('514477', 2),
('514478', 0),
('514685', 0),
('514686', 1),
('514687', 0),
('514697', 1),
('514698', 1),
('514865', 50),
('515059', 2),
('515063', 4000),
('515928', 261),
('515929', 0),
('516043', 0),
('516045', 0),
('517463', 0),
('517871', 139),
('518058', 2),
('518059', 0),
('518331', 2),
('518477', 275),
('519008', 0),
('520301', 0),
('520302', 0),
('520303', 0),
('520306', 0),
('521031', 2),
('521363', 0),
('521794', 0),
('521795', 0),
('521797', 0),
('521798', 0),
('522020', 0),
('805615', 2),
print("===")
print(self.subject.documentation_bom())
assert_array_equal(sorted(self.subject.documentation_bom()), sorted(expected))
('anchors', 262),
('ballast', 6786),
('modules', 1726)
]
assert_array_equal(sorted(self.subject.documentation_bom()), expected)
# Performance Tests

View File

@@ -118,7 +118,7 @@ class EbomCalculatorTest(unittest.TestCase):
wire_clip_large: 2907,
cable_support_lid: 368,
cable_support: 368,
rear_skirt_1_1: -140,
rear_skirt: -140,
dc_switch_bracket: 2,
front_legs: 23,
back_legs: 23,
@@ -147,7 +147,7 @@ class EbomCalculatorTest(unittest.TestCase):
whip_tray: 19,
ac_switch: 3,
ac_splice_box: 2,
ethernet_plug: 12.600000000000001,
ethernet_plug: 7.2,
mounting_back_plate: 23,
sunshade_bolt: 4,
sunshade_washer: 4,
@@ -193,10 +193,10 @@ class EbomCalculatorTest(unittest.TestCase):
self.user_values.module_type.return_value = ModuleType.Cell96
expected_output = {
stump: 65,
wire_clip_large: 590,
wire_clip_large: 513,
cable_support_lid: 0,
cable_support: 0,
rear_skirt_1_1: 0,
rear_skirt: 0,
rubber_foot: 9,
delta_inverter_leg: 9,
harness_4_string_mf: 4,
@@ -206,7 +206,6 @@ class EbomCalculatorTest(unittest.TestCase):
delta_60kw_inverter: 1,
delta_splice_box: 2,
delta_kit_inverter_mount: 3,
delta_kit_inverter_mount_dt: 0
}
assert_dictionary_equal(self.subject.compute_ebom(), expected_output)
@@ -224,22 +223,23 @@ class EbomCalculatorTest(unittest.TestCase):
'attachment_point': ('Switch Gear', None)
},
]
self.user_values.system_type.return_value = SystemType.dualTilt
self.user_values.module_type.return_value = ModuleType.Cell96
expected_output = {
stump: 0,
wire_clip_large: 200,
wire_clip_large: 171,
cable_support_lid: 0,
cable_support: 0,
rear_skirt_1_1: 0,
rear_skirt: 0,
rubber_foot: 3,
delta_inverter_leg: 3,
harness_4_string_mf: 2,
harness_4_string_fm: 2,
delta_42kw_inverter: 1,
delta_kit_inverter_mount: 0,
delta_kit_inverter_mount_dt: 1,
}
assert_dictionary_equal(self.subject.compute_ebom(), expected_output)
def test_computes_ebom_with_aux_plugs(self):
@@ -380,7 +380,7 @@ class EbomCalculatorTest(unittest.TestCase):
wire_clip_large: 2394,
cable_support: 270,
cable_support_lid: 270,
rear_skirt_1_1: -103,
rear_skirt: -103,
ethernet_plug: 7.2,
monitor_power_plug: 1,
sunshade_bolt: 12,
@@ -492,7 +492,7 @@ class EbomCalculatorTest(unittest.TestCase):
wire_clip_large: 2394,
cable_support: 270,
cable_support_lid: 270,
rear_skirt_1_1: -103,
rear_skirt: -103,
ethernet_plug: 7.2,
monitor_power_plug: 1,
sunshade_bolt: 12,
@@ -604,7 +604,7 @@ class EbomCalculatorTest(unittest.TestCase):
wire_clip_large: 2394,
cable_support: 270,
cable_support_lid: 270,
rear_skirt_1_1: -103,
rear_skirt: -103,
ethernet_plug: 7.2,
monitor_power_plug: 1,
fuseshade: 14,
@@ -616,56 +616,6 @@ class EbomCalculatorTest(unittest.TestCase):
assert_dictionary_equal(self.subject.compute_ebom(), expected_output)
def test_computes_ebom_with_power_monitor_DELTA_brand(self):
self.user_values.inverter_brands.return_value = [{'inverter_brand_id':2}]
self.user_values.power_monitors.return_value = [{
'monitor_id': 'foo',
'power_source': ('Switch Gear/External', None)
}]
self.user_values.system_type.return_value = SystemType.singleTilt
self.user_values.module_type.return_value = ModuleType.Cell96
expected_output = {
monitor_power_plug: 1,
stump: 0,
cable_support: 0,
cable_support_lid: 0,
rear_skirt_1_1: 0,
monitor_controller_480_v:1,
}
assert_dictionary_equal(self.subject.compute_ebom(), expected_output)
def test_computes_ebom_with_power_monitor_SMA_brand(self):
self.user_values.inverter_brands.return_value = [{'inverter_brand_id':1}]
self.user_values.power_monitors.return_value = [{
'monitor_id': 'foo',
'power_source': ('Switch Gear/External', None)
}]
self.user_values.system_type.return_value = SystemType.singleTilt
self.user_values.module_type.return_value = ModuleType.Cell96
expected_output = {
monitor_power_plug: 1,
stump: 0,
cable_support: 0,
cable_support_lid: 0,
rear_skirt_1_1: 0,
monitor_controller_480_v:1,
flat_washer: 4,
channel_nut: 4,
hex_nut_three_eighths_16: 2,
front_legs: 1,
back_legs: 1,
inverter_link: 2,
inverter_rail: 1,
rubber_foot: 3,
hex_bolt_1_2: 9,
mounting_back_plate: 1,
}
assert_dictionary_equal(self.subject.compute_ebom(), expected_output)
def test_computes_ebom_with_aux_plugs_on_switchgear_on_pseries_single_tilt(self):
self.user_values.power_stations.return_value = [
{
@@ -771,7 +721,7 @@ class EbomCalculatorTest(unittest.TestCase):
wire_clip_large: 2394,
cable_support: 694,
cable_support_lid: 694,
rear_skirt_1_1: -264,
rear_skirt: -264,
ethernet_plug: 7.2,
monitor_power_plug: 1,
fuseshade: 14,
@@ -922,7 +872,7 @@ class EbomCalculatorTest(unittest.TestCase):
wire_clip_large: 2394,
cable_support: 270,
cable_support_lid: 270,
rear_skirt_1_1: -103,
rear_skirt: -103,
ethernet_plug: 7.2,
monitor_power_plug: 1,
sunshade_bolt: 12,
@@ -968,7 +918,7 @@ class EbomCalculatorTest(unittest.TestCase):
wire_clip_large: 2394,
cable_support: 270,
cable_support_lid: 270,
rear_skirt_1_1: -103,
rear_skirt: -103,
ethernet_plug: 7.2,
sunshade_bolt: 12,
sunshade_washer: 12,
@@ -1027,7 +977,7 @@ class EbomCalculatorTest(unittest.TestCase):
mounting_back_plate: 1,
cable_support: 0,
cable_support_lid: 0,
rear_skirt_1_1: 0,
rear_skirt: 0,
monitor_power_plug: 1,
}
@@ -1046,7 +996,7 @@ class EbomCalculatorTest(unittest.TestCase):
mounting_back_plate: 1,
cable_support: 0,
cable_support_lid: 0,
rear_skirt_1_1: 0,
rear_skirt: 0,
monitor_power_plug: 1,
}
@@ -1055,14 +1005,14 @@ class EbomCalculatorTest(unittest.TestCase):
stump: 0,
cable_support: 0,
cable_support_lid: 0,
rear_skirt_1_1: 0
rear_skirt: 0
}
expected_output_240_pseries = {
stump: 0,
cable_support_lid: 0,
cable_support: 0,
rear_skirt_1_1: 0,
rear_skirt: 0,
monitor_controller_240_v: 1,
}
@@ -1101,53 +1051,3 @@ class EbomCalculatorTest(unittest.TestCase):
self.subject = EbomCalculator(self.user_values, 171, 98, 104)
assert_dictionary_equal(self.subject.compute_ebom(), expected_output_240_pseries)
def test_computes_ebom_with_power_monitor_DELTA_brand(self):
self.user_values.inverter_brands.return_value = [{'inverter_brand_id':2}]
self.user_values.power_monitors.return_value = [{
'monitor_id': 'foo',
'power_source': ('Switch Gear/External', None)
}]
self.user_values.system_type.return_value = SystemType.singleTilt
self.user_values.module_type.return_value = ModuleType.Cell96
expected_output = {
monitor_power_plug: 1,
stump: 0,
cable_support: 0,
cable_support_lid: 0,
rear_skirt_1_1: 0,
monitor_controller_480_v: 1,
}
assert_dictionary_equal(self.subject.compute_ebom(), expected_output)
def test_computes_ebom_with_power_monitor_SMA_brand(self):
self.user_values.inverter_brands.return_value = [{'inverter_brand_id':1}]
self.user_values.power_monitors.return_value = [{
'monitor_id': 'foo',
'power_source': ('Switch Gear/External', None)
}]
self.user_values.system_type.return_value = SystemType.singleTilt
self.user_values.module_type.return_value = ModuleType.Cell96
expected_output = {
monitor_power_plug: 1,
stump: 0,
cable_support: 0,
cable_support_lid: 0,
rear_skirt_1_1: 0,
monitor_controller_480_v:1,
flat_washer: 4,
channel_nut: 4,
hex_nut_three_eighths_16: 2,
front_legs: 1,
back_legs: 1,
inverter_link: 2,
inverter_rail: 1,
rubber_foot: 3,
hex_bolt_1_2: 9,
mounting_back_plate: 1,
}
assert_dictionary_equal(self.subject.compute_ebom(), expected_output)

View File

@@ -72,8 +72,8 @@ class MechanicalBomCalculatorWhenDualTilt128CellTest(unittest.TestCase):
expected_output = {
wire_clip: 80,
link_tray: 9,
left_deflector_1_1: 10,
right_deflector_1_1: 10,
left_deflector: 10,
right_deflector: 10,
anchor_plate: 12,
cross_tray_1_1: 3,
dual_tilt_chassis: 26,
@@ -98,8 +98,8 @@ class MechanicalBomCalculatorWhenDualTilt128CellTest(unittest.TestCase):
expected_output = {
wire_clip: 80,
link_tray: 9,
left_deflector_1_1: 10,
right_deflector_1_1: 10,
left_deflector: 10,
right_deflector: 10,
anchor_plate: 12,
cross_tray_1_1: 3,
dual_tilt_chassis: 26,

View File

@@ -73,8 +73,8 @@ class MechanicalBomCalculatorWhenDualTilt96CellTest(unittest.TestCase):
expected_output = {
wire_clip: 80,
link_tray: 9,
left_deflector_1_1: 10,
right_deflector_1_1: 10,
left_deflector: 10,
right_deflector: 10,
anchor_plate: 12,
cross_tray: 3,
dual_tilt_chassis: 26,
@@ -99,8 +99,8 @@ class MechanicalBomCalculatorWhenDualTilt96CellTest(unittest.TestCase):
expected_output = {
wire_clip: 80,
link_tray: 18,
left_deflector_1_1: 10,
right_deflector_1_1: 10,
left_deflector: 10,
right_deflector: 10,
anchor_plate: 12,
cross_tray: 3,
dual_tilt_chassis: 26,

View File

@@ -93,8 +93,8 @@ class MechanicalBomCalculatorWhenSingleTilt128CellTest(unittest.TestCase):
following_tray: 6,
link_tray: 28,
spoiler_1_1: 44,
left_deflector_1_1: 11,
right_deflector_1_1: 11,
left_deflector: 11,
right_deflector: 11,
anchor_plate: 15,
cross_tray_1_1: 5,
rubber_foot: 4.4,

View File

@@ -93,13 +93,13 @@ class MechanicalBomCalculatorWhenSingleTilt96CellTest(unittest.TestCase):
following_tray: 25,
link_tray: 28,
spoiler: 44,
left_deflector_1_1: 11,
right_deflector_1_1: 11,
left_deflector: 11,
right_deflector: 11,
anchor_plate: 15,
cross_tray: 5,
rubber_foot: 4.4,
front_skirt: 24,
rear_skirt_1_1: 44,
rear_skirt: 44,
leading_tray: 25,
ballast: 192,
anchor: 15, # 12 + the 3 seismic anchors

View File

@@ -54,8 +54,8 @@ class SummaryValuesTest(unittest.TestCase):
{'label': 'Avg PSF', 'value': 10.06},
{'label': 'Total Anchors', 'value': 7},
{'label': 'Total Ballast', 'value': 8},
{'label': 'Max Possible System Weight', 'value': 1563.0},
{'label': 'Max System Weight Ballast Block', 'value': 16},
{'label': 'Max Possible System Weight', 'value': 1568.0},
{'label': 'Max System Weight Ballast Block', 'value': 14},
{'label': 'Seismic Anchor Max. Spacing', 'value': seismic_interval}
]
eq_(result, expected)
@@ -83,8 +83,8 @@ class SummaryValuesTest(unittest.TestCase):
'ave_psf': 10.06,
'total_anchors': 7,
'total_ballast': 8,
'max_possible_system_weight': 1563.0,
'max_system_weight_ballast_block': 16,
'max_possible_system_weight': 1568.0,
'max_system_weight_ballast_block': 14,
'seismic_anchor_max_spacing': 10
}
@@ -111,7 +111,7 @@ class SummaryValuesTest(unittest.TestCase):
result = self.subject.find_max_system_weight(panels, self.c_p_matrix, self.q_z, self.ballast_calculator)
assert_almost_equal(result, (1563, 16), decimal=0)
assert_almost_equal(result, (1568, 14), decimal=0)
def test_find_max_system_weight_does_not_modify_panels_list(self):
panels = [

View File

@@ -574,12 +574,12 @@
},
{
"name" : "total_521794",
"name" : "total_513841",
"value" : "someValue"
},
{
"name" : "total_521795",
"name" : "total_513842",
"value" : "someValue"
},

View File

@@ -1,8 +1,8 @@
HANDLE BLOCKNAME WIND POS SUBARRAY PSF BAL LTRAY XTRAY ANC ID XCOORD YCOORD ANGLE
'21EEE0 *U593 C 1 1 12.91 20 2 1 - 1 0 0 0
'21EECC *U824 C 2 1 11.34 17 2 1 - 2 0 0 0
'21EEB8 *U824 E 3 1 2.28 0 1 - - 3 0 0 0
'21EEE0 *U593 C 1 1 12.9 20 2 1 - 1 0 0 0
'21EECC *U824 C 2 1 11.35 17 2 1 - 2 0 0 0
'21EEB8 *U824 E 3 1 2.26 0 1 - - 3 0 0 0
'21EEA4 *U593 A 1 1 5.55 6 2 - 2 4 0 0 0
'21E940 *U171 B 4 1 13.87 22 1 2 - 5 0 0 0
'21E940 *U171 B 4 1 13.83 22 1 2 - 5 0 0 0
'21E92C *U824 D 1 1 7.1 9 2 - - 6 0 0 0
'21E918 *U593 B 1 1 9.8 14 2 1 1 7 0 0 0
1 HANDLE BLOCKNAME WIND POS SUBARRAY PSF BAL LTRAY XTRAY ANC ID XCOORD YCOORD ANGLE
2 '21EEE0 *U593 C 1 1 12.91 12.9 20 2 1 - 1 0 0 0
3 '21EECC *U824 C 2 1 11.34 11.35 17 2 1 - 2 0 0 0
4 '21EEB8 *U824 E 3 1 2.28 2.26 0 1 - - 3 0 0 0
5 '21EEA4 *U593 A 1 1 5.55 6 2 - 2 4 0 0 0
6 '21E940 *U171 B 4 1 13.87 13.83 22 1 2 - 5 0 0 0
7 '21E92C *U824 D 1 1 7.1 9 2 - - 6 0 0 0
8 '21E918 *U593 B 1 1 9.8 14 2 1 1 7 0 0 0

View File

@@ -1,18 +0,0 @@
HANDLE BLOCKNAME WIND POS SUBARRAY PSF BAL LTRAY XTRAY ANC ID XCOORD YCOORD ANGLE
'B247D *U6006 A 1 1 2.4 0 2 - 1 1 30043.319 -61598.761 2.534306
'B245F *U6006 A 2 1 2.4 0 2 - S 2 29955.165 -61602.663 2.534306
'B2441 *U6006 A 2 1 2.4 0 2 - S 3 29867.012 -61606.565 2.534306
'B2423 *U6006 A 1 1 2.4 0 2 - 1 4 29778.858 -61610.467 2.534306
'B2405 *U6006 A 3 1 2.26 0 1 - S 5 30046.068 -61660.86 2.534306
'B23E7 *U6006 A 4 1 5.94 10 1 - - 6 29957.914 -61664.762 2.534306
'B23C9 *U6006 A 4 1 5.94 10 1 - - 7 29869.76 -61668.664 2.534306
'B23AB *U6006 A 3 1 8.9 18 1 1 - 8 29781.607 -61672.566 2.534306
'B238D *U6007 A 3 1 8.9 18 1 1 - 9 30048.816 -61722.96 2.534306
'B236F *U6007 A 4 1 5.94 10 1 - - 10 29960.663 -61726.861 2.534306
'B2351 *U6007 A 4 1 5.94 10 1 - - 11 29872.509 -61730.763 2.534306
'B2333 *U6007 A 3 1 8.9 18 1 1 - 12 29784.355 -61734.665 2.534306
'B2315 *U6007 A 1 1 2.4 0 2 - 1 13 30051.565 -61785.059 2.534306
'B22F7 *U6007 A 2 1 2.4 0 2 - S 14 29963.411 -61788.961 2.534306
'B22D9 *U6007 A 2 1 2.4 0 2 - S 15 29875.258 -61792.862 2.534306
'B22B6 *U6007 A 1 1 2.4 0 2 - 1 16 29787.104 -61796.764 2.534306

View File

@@ -1,7 +1,9 @@
Part # Description Total
512200 CLIP, WIRE FORMED, CABLE MANAGEMENT, INSIDE, 352MM ^ 2 3480
513833 TRAY, LINK, HELIX ROOF 670
513843 PLATE, ANCHOR, HELIX ROOF 263
513841 DEFLECTOR, LH, HELIX ROOF 196
513842 DEFLECTOR, RH, HELIX ROOF 196
513843 PLATE, ANCHOR, HELIX ROOF 262
513844 TRAY, OPTIONAL BALLAST, HELIX ROOF 214
514056 BASE, CHASSIS, DUAL TILT, HELIX ROOF 1000
514057 PLATFORM, CHASSIS, DUAL TILT, HELIX ROOF 1000
@@ -10,8 +12,6 @@ Part # Description Total
515928 FRONT SKIRT, HELIX ROOF 261
517871 TRAY, LEADING, HELIX ROOF, RIVETED VERSION 139
518477 WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS 275
521794 DEFLECTOR, LH, HELIX ROOF V1.1 196
521795 DEFLECTOR, RH, HELIX ROOF V1.1 196
Contractor Supplied Ballast Blocks 6777
TBD Anchors 263
Contractor Supplied Ballast Blocks 6786
TBD Anchors 262
TBD Modules 1726
1 Part # Description Total
2 512200 CLIP, WIRE FORMED, CABLE MANAGEMENT, INSIDE, 352MM ^ 2 3480
3 513833 TRAY, LINK, HELIX ROOF 670
4 513843 513841 PLATE, ANCHOR, HELIX ROOF DEFLECTOR, LH, HELIX ROOF 263 196
5 513842 DEFLECTOR, RH, HELIX ROOF 196
6 513843 PLATE, ANCHOR, HELIX ROOF 262
7 513844 TRAY, OPTIONAL BALLAST, HELIX ROOF 214
8 514056 BASE, CHASSIS, DUAL TILT, HELIX ROOF 1000
9 514057 PLATFORM, CHASSIS, DUAL TILT, HELIX ROOF 1000
12 515928 FRONT SKIRT, HELIX ROOF 261
13 517871 TRAY, LEADING, HELIX ROOF, RIVETED VERSION 139
14 518477 WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS 275
15 521794 Contractor Supplied DEFLECTOR, LH, HELIX ROOF V1.1 Ballast Blocks 196 6786
16 521795 TBD DEFLECTOR, RH, HELIX ROOF V1.1 Anchors 196 262
Contractor Supplied Ballast Blocks 6777
TBD Anchors 263
17 TBD Modules 1726

View File

@@ -10,11 +10,14 @@
512661 BACK LEGS, INVERTER RACK, HELIX ROOF 18
512662 LINK TO ARRAY, INVERTER RACK, HELIX ROOF 36
512663 RAIL, INVERTER RACK, HELIX ROOF 18
512676 INVERTER, SMA, STP, 20000TL-US-10 (SPR-20000m-3 XXX), AFCI, CONNECTORIZED 3
513007 BOLT, HH, 3/8-16 X 3/4, 316 SS 50
513299 COMBINER BOX, AC, 4 INPUT, NO AUX, W/ CONNECTOR 3
513303 COMBINER BOX, AC, 2 INPUT, NO AUX, W/ CONNECTOR 1
513833 TRAY, LINK, HELIX ROOF 670
513843 PLATE, ANCHOR, HELIX ROOF 263
513841 DEFLECTOR, LH, HELIX ROOF 196
513842 DEFLECTOR, RH, HELIX ROOF 196
513843 PLATE, ANCHOR, HELIX ROOF 262
513844 TRAY, OPTIONAL BALLAST, HELIX ROOF 214
514056 BASE, CHASSIS, DUAL TILT, HELIX ROOF 1000
514057 PLATFORM, CHASSIS, DUAL TILT, HELIX ROOF 1000
@@ -27,6 +30,9 @@
514440 HARNESS, DC COMBINATION, W/ FUSE, 4 STRING, MALES TO FEMALE, HELIX 15
514477 HARNESS, AC, INNER, 72", HELIX ROOFTOP 8
514478 HARNESS, AC, OUTER, 108", HELIX ROOFTOP 6
514685 INVERTER, SMA, STP, 24000TL-US-10 (SPR-24000m-3 XXX), AFCI, CONNECTORIZED 9
514686 INVERTER, SMA, STP, 12000TL-US-10 (SPR-12000m-3 XXX), AFCI, CONNECTORIZED 1
514687 INVERTER, SMA, STP, 15000TL-US-10 (SPR-15000m-3 XXX), AFCI, CONNECTORIZED 1
514697 COMM CABLE, INVERTER DAISY CHAIN, 118", HELIX ROOF 10
514865 BOLT, HH, 3/8-16 X 1/2, 18-8 SS 300
515059 ASSY, WHIP TRAY W/FUSE CLIPS, INVERTER, HELIX 14
@@ -36,12 +42,6 @@
518058 CONNECTOR, ETHERNET, PLUG, RJ-45, WEATHERPROOF, SHIELDED 8
518331 MOUNTING BACK PLATE, INVERTER/PANEL BOARD, HELIX ROOF/TRACKER 18
518477 WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS 275
521794 DEFLECTOR, LH, HELIX ROOF V1.1 196
521795 DEFLECTOR, RH, HELIX ROOF V1.1 196
523921 INVERTER, SMA, STP, 20000TL-US-10 (SPR-20000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS 1
523922 INVERTER, SMA, STP, 24000TL-US-10 (SPR-24000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS 1
523923 INVERTER, SMA, STP, 12000TL-US-10 (SPR-12000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS 3
523924 INVERTER, SMA, STP, 15000TL-US-10 (SPR-15000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS 9
Contractor Supplied Ballast Blocks 6777
TBD Anchors 263
Contractor Supplied Ballast Blocks 6786
TBD Anchors 262
TBD Modules 1726
Can't render this file because it contains an unexpected character in line 31 and column 30.

View File

@@ -1,20 +1,20 @@
HANDLE BLOCKNAME WIND POS SUBARRAY PSF BAL LTRAY XTRAY ANC ID XCOORD YCOORD ANGLE
'40EC39 *U5399 H 1 8 14.24 16 - 1 - 1 0 0 0
'40EC22 *U5402 H 3 8 12.72 14 2 1 - 2 0 0 0
'40EC0B *U5402 H 1 8 14.24 16 - 1 - 3 0 0 0
'40EBF4 *U5402 H 1 8 14.24 16 - 1 - 4 0 0 0
'40EBDD *U5402 H 3 8 12.72 14 2 1 - 5 0 0 0
'40EBC6 *U5402 H 3 8 12.72 14 2 1 - 6 0 0 0
'40EBAF *U5402 H 3 8 12.72 14 2 1 - 7 0 0 0
'40EB98 *U5399 H 1 8 14.24 16 - 1 - 8 0 0 0
'40EB81 *U5401 H 2 8 12.6 14 - 1 - 9 0 0 0
'40E8B8 *U5401 H 2 8 12.6 14 - 1 - 10 0 0 0
'40E8A1 *U5401 I 2 8 1.84 0 - - 2 11 0 0 0
'40E88A *U5400 H 4 8 10.4 11 1 1 - 12 0 0 0
'40E873 *U5400 H 4 8 10.4 11 1 1 - 13 0 0 0
'40E85C *U5400 H 4 8 10.4 11 1 1 - 14 0 0 0
'40E845 *U5400 H 4 8 10.4 11 1 1 - 15 0 0 0
'40E82E *U5400 H 4 8 10.4 11 1 1 - 16 0 0 0
'40E817 *U5400 H 4 8 10.4 11 1 1 - 17 0 0 0
'40E800 *U5401 H 2 8 12.6 14 - 1 - 18 0 0 0
'40E7E9 *U5401 I 2 8 1.84 0 - - 2 19 0 0 0
'40EC39 *U5399 H 1 8 14.37 16 - 1 - 1 0 0 0
'40EC22 *U5402 H 3 8 12.89 14 2 1 - 2 0 0 0
'40EC0B *U5402 H 1 8 14.37 16 - 1 - 3 0 0 0
'40EBF4 *U5402 H 1 8 14.37 16 - 1 - 4 0 0 0
'40EBDD *U5402 H 3 8 12.89 14 2 1 - 5 0 0 0
'40EBC6 *U5402 H 3 8 12.89 14 2 1 - 6 0 0 0
'40EBAF *U5402 H 3 8 12.89 14 2 1 - 7 0 0 0
'40EB98 *U5399 H 1 8 14.37 16 - 1 - 8 0 0 0
'40EB81 *U5401 H 2 8 12.65 14 - 1 - 9 0 0 0
'40E8B8 *U5401 H 2 8 12.65 14 - 1 - 10 0 0 0
'40E8A1 *U5401 I 2 8 1.89 0 - - 2 11 0 0 0
'40E88A *U5400 H 4 8 10.42 11 1 1 - 12 0 0 0
'40E873 *U5400 H 4 8 10.42 11 1 1 - 13 0 0 0
'40E85C *U5400 H 4 8 10.42 11 1 1 - 14 0 0 0
'40E845 *U5400 H 4 8 10.42 11 1 1 - 15 0 0 0
'40E82E *U5400 H 4 8 10.42 11 1 1 - 16 0 0 0
'40E817 *U5400 H 4 8 10.42 11 1 1 - 17 0 0 0
'40E800 *U5401 H 2 8 12.65 14 - 1 - 18 0 0 0
'40E7E9 *U5401 I 2 8 1.89 0 - - 2 19 0 0 0
1 HANDLE BLOCKNAME WIND POS SUBARRAY PSF BAL LTRAY XTRAY ANC ID XCOORD YCOORD ANGLE
2 '40EC39 *U5399 H 1 8 14.24 14.37 16 - 1 - 1 0 0 0
3 '40EC22 *U5402 H 3 8 12.72 12.89 14 2 1 - 2 0 0 0
4 '40EC0B *U5402 H 1 8 14.24 14.37 16 - 1 - 3 0 0 0
5 '40EBF4 *U5402 H 1 8 14.24 14.37 16 - 1 - 4 0 0 0
6 '40EBDD *U5402 H 3 8 12.72 12.89 14 2 1 - 5 0 0 0
7 '40EBC6 *U5402 H 3 8 12.72 12.89 14 2 1 - 6 0 0 0
8 '40EBAF *U5402 H 3 8 12.72 12.89 14 2 1 - 7 0 0 0
9 '40EB98 *U5399 H 1 8 14.24 14.37 16 - 1 - 8 0 0 0
10 '40EB81 *U5401 H 2 8 12.6 12.65 14 - 1 - 9 0 0 0
11 '40E8B8 *U5401 H 2 8 12.6 12.65 14 - 1 - 10 0 0 0
12 '40E8A1 *U5401 I 2 8 1.84 1.89 0 - - 2 11 0 0 0
13 '40E88A *U5400 H 4 8 10.4 10.42 11 1 1 - 12 0 0 0
14 '40E873 *U5400 H 4 8 10.4 10.42 11 1 1 - 13 0 0 0
15 '40E85C *U5400 H 4 8 10.4 10.42 11 1 1 - 14 0 0 0
16 '40E845 *U5400 H 4 8 10.4 10.42 11 1 1 - 15 0 0 0
17 '40E82E *U5400 H 4 8 10.4 10.42 11 1 1 - 16 0 0 0
18 '40E817 *U5400 H 4 8 10.4 10.42 11 1 1 - 17 0 0 0
19 '40E800 *U5401 H 2 8 12.6 12.65 14 - 1 - 18 0 0 0
20 '40E7E9 *U5401 I 2 8 1.84 1.89 0 - - 2 19 0 0 0

View File

@@ -27,7 +27,9 @@ Part # Description Total
513832 TRAY, FOLLOWING, HELIX ROOF 210
513833 TRAY, LINK, HELIX ROOF 1271
513836 SPOILER, SINGLE TILT, HELIX ROOF 1632
513843 PLATE, ANCHOR, HELIX ROOF 416
513841 DEFLECTOR, LH, HELIX ROOF 171
513842 DEFLECTOR, RH, HELIX ROOF 171
513843 PLATE, ANCHOR, HELIX ROOF 414
513844 TRAY, OPTIONAL BALLAST, HELIX ROOF 274
514265 FOOT, RECYCLED RUBBER, HELIX ROOF 230
514435 HARNESS, DC COMBINATION, W/ FUSE, 3 STRING, FEMALES TO MALE, HELIX 4
@@ -38,25 +40,23 @@ Part # Description Total
514440 HARNESS, DC COMBINATION, W/ FUSE, 4 STRING, MALES TO FEMALE, HELIX 11
514477 HARNESS, AC, INNER, 72", HELIX ROOFTOP 12
514478 HARNESS, AC, OUTER, 108", HELIX ROOFTOP 2
514685 INVERTER, SMA, STP, 24000TL-US-10 (SPR-24000m-3 XXX), AFCI, CONNECTORIZED 6
514686 INVERTER, SMA, STP, 12000TL-US-10 (SPR-12000m-3 XXX), AFCI, CONNECTORIZED 6
514687 INVERTER, SMA, STP, 15000TL-US-10 (SPR-15000m-3 XXX), AFCI, CONNECTORIZED 3
514697 COMM CABLE, INVERTER DAISY CHAIN, 118", HELIX ROOF 8
514698 DC SWITCH BOX, HELIX 5
514865 BOLT, HH, 3/8-16 X 1/2, 18-8 SS 350
515059 ASSY, WHIP TRAY W/FUSE CLIPS, INVERTER, HELIX 16
515928 FRONT SKIRT, HELIX ROOF 197
515929 REAR SKIRT, HELIX ROOF 1469
516043 AC SWITCH, CONNECTORIZED, HELIX ROOF 2
516045 AC SPLICE BOX, CONNECTORIZED, HELIX ROOF 1
517871 TRAY, LEADING, HELIX ROOF, RIVETED VERSION 210
518058 CONNECTOR, ETHERNET, PLUG, RJ-45, WEATHERPROOF, SHIELDED 15
518058 CONNECTOR, ETHERNET, PLUG, RJ-45, WEATHERPROOF, SHIELDED 11
518331 MOUNTING BACK PLATE, INVERTER/PANEL BOARD, HELIX ROOF/TRACKER 22
518477 WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS 425
520301 REAR SKIRT, HELIX ROOF V1.1 1469
521031 WASHER, FLAT, M10 X 20MM OD, SS 10
521794 DEFLECTOR, LH, HELIX ROOF V1.1 171
521795 DEFLECTOR, RH, HELIX ROOF V1.1 171
523921 INVERTER, SMA, STP, 20000TL-US-10 (SPR-20000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS 6
523922 INVERTER, SMA, STP, 24000TL-US-10 (SPR-24000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS 3
523924 INVERTER, SMA, STP, 15000TL-US-10 (SPR-15000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS 6
805615 SCREW, HEXAGONAL HEAD, M10X20, SS A2 10
Contractor Supplied Ballast Blocks 10448
TBD Anchors 416
Contractor Supplied Ballast Blocks 10150
TBD Anchors 414
TBD Modules 1632
Can't render this file because it contains an unexpected character in line 10 and column 30.

View File

@@ -1,3 +0,0 @@
HANDLE BLOCKNAME WIND POS SUBARRAY PSF BAL LTRAY XTRAY ANC ID XCOORD YCOORD ANGLE
'40EC39 *U5399 A 1 1 2.39 0 2 - 1 1 0 0 0
'40EC22 *U5402 A 1 1 2.39 0 2 - 1 2 0 0 0

View File

@@ -1,4 +0,0 @@
HANDLE BLOCKNAME WIND POS SUBARRAY PSF BAL LTRAY XTRAY ANC ID XCOORD YCOORD ANGLE
'40EC39 *U5399 A 1 1 2.4 0 2 - 1 1 0 0 0
'40EC22 *U5402 A 1 1 2.4 0 2 - 1 2 0 0 0
1 HANDLE BLOCKNAME WIND POS SUBARRAY PSF BAL LTRAY XTRAY ANC ID XCOORD YCOORD ANGLE
2 '40EC39 *U5399 A 1 1 2.4 0 2 - 1 1 0 0 0
3 '40EC22 *U5402 A 1 1 2.4 0 2 - 1 2 0 0 0

View File

@@ -1,289 +0,0 @@
HANDLE BLOCKNAME WIND POS SUBARRAY PSF BAL LTRAY XTRAY ANC ID XCOORD YCOORD ANGLE
'1A9103 *U5693 A 1 15 2.4 0 2 - 1 1 128094.142 122996.9 0.0
'1A90DD *U5695 A 3 15 10.77 23 1 2 - 2 128094.142 123059.06 0.0
'1A90B7 *U5695 A 3 15 2.26 0 1 - S 3 128094.142 123121.22 0.0
'1A9091 *U5695 A 3 15 2.26 0 1 - S 4 128094.142 123183.38 0.0
'1A906B *U5695 A 3 15 10.77 23 1 2 - 5 128094.142 123245.54 0.0
'1A9045 *U5693 A 1 15 2.4 0 2 - 1 6 128094.142 123307.7 0.0
'1A900B *U5693 A 1 17 2.4 0 2 - 1 7 125981.9 123804.98 0.0
'1A8FE2 *U5695 B 3 12 2.26 0 1 - S 8 126246.62 123804.98 0.0
'1A8FBC *U5693 B 1 12 9.43 19 2 1 - 9 126158.38 123556.34 0.0
'1A8F96 *U5693 B 1 12 2.4 0 2 - S 10 126158.38 123494.18 0.0
'1A8F70 *U5693 A 1 13 2.4 0 2 - 1 11 126438.62 124426.58 0.0
'1A8F4A *U5693 B 1 13 2.4 0 2 - S 12 126791.58 124177.94 0.0
'1A8ECF *U5693 B 1 14 9.43 19 2 1 - 13 127232.78 123059.06 0.0
'1A8EA9 *U5695 B 3 14 7.81 15 1 1 - 14 127232.78 123121.22 0.0
'1A8E83 *U5694 A 2 15 2.4 0 2 - S 15 128005.902 122996.9 0.0
'1A8E37 *U5682 A 4 15 7.81 15 2 1 - 16 128005.902 123059.06 0.0
'1A8E11 *U5693 B 1 14 9.43 19 2 1 - 17 127585.74 123680.66 0.0
'1A8DEB *U5694 B 2 14 7.93 15 2 - - 18 127497.5 123307.7 0.0
'1A8DC5 *U5693 B 1 13 9.43 19 2 1 - 19 126615.1 124240.1 0.0
'1A8D9F *U5693 B 1 13 2.4 0 2 - S 20 126615.1 124302.26 0.0
'1A8D79 *U5693 B 1 13 2.4 0 2 - S 21 126879.82 124115.78 0.0
'1A8D53 *U5695 A 3 12 2.26 0 1 - S 22 125981.9 124115.78 0.0
'1A8D2D *U5695 A 3 13 10.77 23 1 2 - 23 126438.62 124115.78 0.0
'1A8D07 *U5695 A 3 13 2.26 0 1 - S 24 126438.62 124364.42 0.0
'1A8CE1 *U5682 B 4 12 2.26 0 - - S 25 126246.62 123494.18 0.0
'1A8CBB *U5695 B 3 13 7.81 15 1 1 - 26 126438.62 123742.82 0.0
'1A8C95 *U5695 A 3 13 10.77 23 1 2 - 27 126438.62 123369.86 0.0
'1A8C6F *U5693 A 1 12 2.4 0 2 - 1 28 126246.62 122996.9 0.0
'1A8C49 *U5693 A 1 12 2.4 0 2 - 1 29 126334.86 122996.9 0.0
'1A8C23 *U5693 A 1 13 2.4 0 2 - 1 30 126438.62 122996.9 0.0
'1A8BFD *U5693 B 1 13 2.4 0 2 - S 31 126526.86 122996.9 0.0
'1A8BD7 *U5695 A 3 13 2.26 0 1 - S 32 126438.62 123059.06 0.0
'1A8BB1 *U5695 B 3 13 2.26 0 1 - S 33 126526.86 123059.06 0.0
'1A8B8B *U5695 B 3 13 7.81 15 1 1 - 34 126526.86 123121.22 0.0
'1A8B65 *U5695 A 3 13 10.77 23 1 2 - 35 126438.62 123121.22 0.0
'1A8B3F *U5682 B 4 13 5.58 9 2 - - 36 126879.82 123121.22 0.0
'1A8B19 *U5682 B 4 13 5.58 9 2 - - 37 126879.82 123369.86 0.0
'1A7874 *U5693 A 1 11 2.4 0 2 - 1 38 125962.34 122948.6 0.0
'1A784E *U5695 A 3 11 10.77 23 1 2 - 39 125962.34 123010.76 0.0
'1A7828 *U5695 A 3 11 2.26 0 1 - S 40 125962.34 123072.92 0.0
'1A7802 *U5694 A 2 11 2.4 0 2 - S 41 125874.1 122948.6 0.0
'1A77DC *U5695 A 3 11 10.77 23 1 2 - 42 125785.86 123010.76 0.0
'1A77B6 *U5695 A 3 11 10.77 23 1 2 - 43 125785.86 123072.92 0.0
'1A7790 *U5694 A 2 11 2.4 0 2 - S 44 125785.86 122948.6 0.0
'1A776A *U5693 A 1 11 2.4 0 2 - 1 45 125697.62 123321.56 0.0
'1A7744 *U5693 A 1 11 2.4 0 2 - 1 46 125962.34 123321.56 0.0
'1A771E *U5693 A 1 11 2.4 0 2 - 1 47 125697.62 122948.6 0.0
'1A76F8 *U5695 A 3 11 10.77 23 1 2 - 48 125697.62 123010.76 0.0
'1A76D2 *U5695 A 3 11 10.77 23 1 2 - 49 125697.62 123072.92 0.0
'1A7094 *U5682 B 4 13 5.58 9 2 - - 50 126879.82 123059.06 0.0
'1A706E *U5695 B 3 13 7.81 15 1 1 - 51 126791.58 123059.06 0.0
'1A7048 *U5695 B 3 13 7.81 15 1 1 - 52 126791.58 123121.22 0.0
'1A6FFC *U5695 B 3 13 7.81 15 1 1 - 53 126968.06 123059.06 0.0
'1A6FD6 *U5695 B 3 13 2.26 0 1 - S 54 126968.06 123121.22 0.0
'1A6F64 *U5693 B 1 13 2.4 0 2 - S 55 126791.58 122996.9 0.0
'1A6F3B *U5693 B 1 13 2.4 0 2 - S 56 126968.06 122996.9 0.0
'1A6F15 *U5695 A 3 12 10.77 23 1 2 - 57 126334.86 123059.06 0.0
'1A6EEF *U5695 A 3 12 10.77 23 1 2 - 58 126334.86 123121.22 0.0
'1A6EC9 *U5694 B 2 13 7.93 15 2 - - 59 126879.82 122996.9 0.0
'1A6EA3 *U5695 A 3 12 2.26 0 1 - S 60 126246.62 123059.06 0.0
'1A6E7D *U5695 A 3 12 10.77 23 1 2 - 61 126246.62 123121.22 0.0
'1A6D0B *U5695 A 3 17 10.77 23 1 2 - 62 127829.422 123494.18 0.0
'1A6CE5 *U5695 A 3 17 10.77 23 1 2 - 63 127409.26 123742.82 0.0
'1A6CBF *U5695 A 3 18 10.77 23 1 2 - 64 126158.38 123991.46 0.0
'1A6C99 *U5693 A 1 18 2.4 0 2 - 1 65 126070.14 123991.46 0.0
'1A6C73 *U5695 B 3 13 7.81 15 1 1 - 66 126791.58 124115.78 0.0
'1A6C27 *U5693 B 1 13 2.4 0 2 - S 67 126526.86 124364.42 0.0
'1A6BB5 *U5695 B 3 13 7.81 15 1 1 - 68 126968.06 123369.86 0.0
'1A6B8F *U5695 B 3 12 7.81 15 1 1 - 69 126334.86 123494.18 0.0
'1A696E *U5695 B 3 12 7.81 15 1 1 - 70 126334.86 123804.98 0.0
'1A67DF *U5693 A 1 17 2.4 0 2 - 1 71 128182.382 123307.7 0.0
'1A67B9 *U5693 A 1 18 2.4 0 2 - 1 72 126158.38 123432.02 0.0
'197EB9 *U5693 B 1 14 9.43 19 2 1 - 73 127585.74 123307.7 0.0
'194556 *U5682 A 4 15 7.81 15 2 1 - 74 128005.902 123121.22 0.0
'194530 *U5682 A 4 15 7.81 15 2 1 - 75 128005.902 123183.38 0.0
'19450A *U5682 A 4 15 7.81 15 2 1 - 76 128005.902 123245.54 0.0
'1944E4 *U5694 A 2 15 2.4 0 2 - S 77 128005.902 123307.7 0.0
'1947B6 *U5694 A 2 15 2.4 0 2 - S 78 127917.662 122996.9 0.0
'194790 *U5682 A 4 15 7.81 15 2 1 - 79 127917.662 123059.06 0.0
'19476A *U5682 A 4 15 7.81 15 2 1 - 80 127917.662 123121.22 0.0
'194744 *U5682 A 4 15 7.81 15 2 1 - 81 127917.662 123183.38 0.0
'19471E *U5682 A 4 15 7.81 15 2 1 - 82 127917.662 123245.54 0.0
'1946F8 *U5682 A 4 15 2.26 0 - - S 83 127917.662 123307.7 0.0
'1946D2 *U5695 B 3 15 7.81 15 1 1 - 84 127917.662 123369.86 0.0
'1946AC *U5693 B 1 15 2.4 0 2 - S 85 127917.662 123432.02 0.0
'194686 *U5693 A 1 15 2.4 0 2 - 1 86 127829.422 122996.9 0.0
'194660 *U5695 A 3 15 2.26 0 1 - S 87 127829.422 123059.06 0.0
'19463A *U5695 A 3 15 10.77 23 1 2 - 88 127829.422 123121.22 0.0
'194614 *U5695 A 3 15 10.77 23 1 2 - 89 127829.422 123183.38 0.0
'1945EE *U5695 A 3 15 2.26 0 1 - S 90 127829.422 123245.54 0.0
'1945C8 *U5695 A 3 15 10.77 23 1 2 - 91 127829.422 123307.7 0.0
'1945A2 *U5695 B 3 15 2.26 0 1 - S 92 127829.422 123369.86 0.0
'19457C *U5693 B 1 15 2.4 0 2 - S 93 127829.422 123432.02 0.0
'194828 *U5694 A 2 18 10.89 23 2 1 - 94 127144.54 123618.5 0.0
'194802 *U5693 B 1 14 9.43 19 2 1 - 95 127321.02 123742.82 0.0
'1947DC *U5693 B 1 14 9.43 19 2 1 - 96 127232.78 123742.82 0.0
'194874 *U5695 B 3 14 7.81 15 1 1 - 97 127232.78 123183.38 0.0
'19484E *U5695 B 3 14 7.81 15 1 1 - 98 127232.78 123245.54 0.0
'1948C0 *U5695 A 3 18 10.77 23 1 2 - 99 127144.54 123494.18 0.0
'19489A *U5693 A 1 17 2.4 0 2 - 1 100 127144.54 123556.34 0.0
'194932 *U5694 B 2 14 7.93 15 2 - - 101 127409.26 123307.7 0.0
'19490C *U5694 B 2 14 7.93 15 2 - - 102 127321.02 123307.7 0.0
'1948E6 *U5695 B 3 14 7.81 15 1 1 - 103 127232.78 123307.7 0.0
'194CE8 *U5695 B 3 14 7.81 15 1 1 - 104 127585.74 123369.86 0.0
'194CC2 *U5695 B 3 14 7.81 15 1 1 - 105 127585.74 123432.02 0.0
'194C9C *U5695 B 3 14 7.81 15 1 1 - 106 127585.74 123494.18 0.0
'194C76 *U5695 B 3 14 7.81 15 1 1 - 107 127585.74 123556.34 0.0
'194C50 *U5695 B 3 14 7.81 15 1 1 - 108 127585.74 123618.5 0.0
'194C2A *U5682 B 4 14 5.58 9 2 - - 109 127497.5 123369.86 0.0
'194C04 *U5682 B 4 14 5.58 9 2 - - 110 127497.5 123432.02 0.0
'194BDE *U5682 B 4 14 5.58 9 2 - - 111 127497.5 123494.18 0.0
'194BB8 *U5682 B 4 14 5.58 9 2 - - 112 127497.5 123556.34 0.0
'194B92 *U5682 B 4 14 5.58 9 2 - - 113 127497.5 123618.5 0.0
'194B6C *U5682 B 4 14 5.58 9 2 - - 114 127409.26 123369.86 0.0
'194B46 *U5682 B 4 14 5.58 9 2 - - 115 127409.26 123432.02 0.0
'194B20 *U5682 B 4 14 5.58 9 2 - - 116 127409.26 123494.18 0.0
'194AFA *U5682 B 4 14 5.58 9 2 - - 117 127409.26 123556.34 0.0
'194AD4 *U5682 B 4 14 5.58 9 2 - - 118 127409.26 123618.5 0.0
'194AAE *U5682 B 4 14 5.58 9 2 - - 119 127321.02 123369.86 0.0
'194A88 *U5682 B 4 14 5.58 9 2 - - 120 127321.02 123432.02 0.0
'194A62 *U5682 B 4 14 5.58 9 2 - - 121 127321.02 123494.18 0.0
'194A3C *U5682 B 4 14 5.58 9 2 - - 122 127321.02 123556.34 0.0
'194A16 *U5682 B 4 14 5.58 9 2 - - 123 127321.02 123618.5 0.0
'1949F0 *U5695 B 3 14 7.81 15 1 1 - 124 127232.78 123369.86 0.0
'1949CA *U5695 B 3 14 7.81 15 1 1 - 125 127232.78 123432.02 0.0
'1949A4 *U5695 B 3 14 7.81 15 1 1 - 126 127232.78 123494.18 0.0
'19497E *U5695 B 3 14 7.81 15 1 1 - 127 127232.78 123556.34 0.0
'194958 *U5695 B 3 14 7.81 15 1 1 - 128 127232.78 123618.5 0.0
'194D80 *U5694 B 2 14 7.93 15 2 - - 129 127497.5 123680.66 0.0
'194D5A *U5694 B 2 14 7.93 15 2 - - 130 127409.26 123680.66 0.0
'194D34 *U5682 B 4 14 5.58 9 2 - - 131 127321.02 123680.66 0.0
'194D0E *U5695 B 3 14 7.81 15 1 1 - 132 127232.78 123680.66 0.0
'194E8A *U5695 B 3 13 2.26 0 1 - S 133 126526.86 124115.78 0.0
'194F6E *U5695 B 3 13 7.81 15 1 1 - 134 126526.86 124177.94 0.0
'194F48 *U5682 B 4 13 2.26 0 - - S 135 126526.86 124240.1 0.0
'194F22 *U5682 B 4 13 5.58 9 2 - - 136 126526.86 124302.26 0.0
'194EFC *U5695 A 3 13 2.26 0 1 - S 137 126438.62 124177.94 0.0
'194ED6 *U5695 A 3 13 10.77 23 1 2 - 138 126438.62 124240.1 0.0
'194EB0 *U5695 A 3 13 10.77 23 1 2 - 139 126438.62 124302.26 0.0
'194FBA *U5695 A 3 12 10.77 23 1 2 - 140 125981.9 124053.62 0.0
'194F94 *U5695 B 3 13 2.26 0 1 - S 141 126526.86 123369.86 0.0
'195052 *U5695 B 3 13 2.26 0 1 - S 142 126526.86 123991.46 0.0
'19502C *U5695 B 3 13 7.81 15 1 1 - 143 126526.86 124053.62 0.0
'195006 *U5695 B 3 13 2.26 0 1 - S 144 126438.62 123991.46 0.0
'194FE0 *U5695 A 3 13 10.77 23 1 2 - 145 126438.62 124053.62 0.0
'195136 *U5695 B 3 13 2.26 0 1 - S 146 126526.86 123183.38 0.0
'195110 *U5695 B 3 13 2.26 0 1 - S 147 126526.86 123245.54 0.0
'1950EA *U5695 B 3 13 7.81 15 1 1 - 148 126526.86 123307.7 0.0
'1950C4 *U5695 A 3 13 10.77 23 1 2 - 149 126438.62 123183.38 0.0
'19509E *U5695 A 3 13 2.26 0 1 - S 150 126438.62 123245.54 0.0
'195078 *U5695 A 3 13 10.77 23 1 2 - 151 126438.62 123307.7 0.0
'19515C *U5695 B 3 13 2.26 0 1 - S 152 126438.62 123804.98 0.0
'1951A8 *U5695 B 3 13 2.26 0 1 - S 153 126526.86 123432.02 0.0
'195182 *U5695 A 3 13 2.26 0 1 - S 154 126438.62 123432.02 0.0
'195240 *U5695 B 3 13 7.81 15 1 1 - 155 126526.86 123618.5 0.0
'19521A *U5695 B 3 13 2.26 0 1 - S 156 126526.86 123680.66 0.0
'1951F4 *U5695 B 3 13 2.26 0 1 - S 157 126438.62 123618.5 0.0
'1951CE *U5695 B 3 13 7.81 15 1 1 - 158 126438.62 123680.66 0.0
'195266 *U5695 B 3 13 7.81 15 1 1 - 159 126526.86 123742.82 0.0
'1954A0 *U5695 B 3 13 7.81 15 1 1 - 160 126968.06 123183.38 0.0
'19547A *U5695 B 3 13 7.81 15 1 1 - 161 126968.06 123245.54 0.0
'195454 *U5695 B 3 13 2.26 0 1 - S 162 126968.06 123307.7 0.0
'19542E *U5682 B 4 13 5.58 9 2 - - 163 126879.82 123183.38 0.0
'195408 *U5682 B 4 13 5.58 9 2 - - 164 126879.82 123245.54 0.0
'1953E2 *U5682 B 4 13 5.58 9 2 - - 165 126879.82 123307.7 0.0
'1953BC *U5695 B 3 13 2.26 0 1 - S 166 126791.58 123183.38 0.0
'195396 *U5695 B 3 13 7.81 15 1 1 - 167 126791.58 123245.54 0.0
'195370 *U5695 B 3 13 7.81 15 1 1 - 168 126791.58 123307.7 0.0
'1954C6 *U5695 B 3 13 2.26 0 1 - S 169 126791.58 123369.86 0.0
'1955F6 *U5694 B 2 13 7.93 15 2 - - 170 126703.34 123494.18 0.0
'1955D0 *U5694 B 2 13 2.4 0 2 - S 171 126703.34 123556.34 0.0
'1955AA *U5694 B 2 13 2.4 0 2 - S 172 126615.1 123494.18 0.0
'195584 *U5694 B 2 13 7.93 15 2 - - 173 126615.1 123556.34 0.0
'19555E *U5682 B 4 13 2.26 0 - - S 174 126526.86 123494.18 0.0
'195538 *U5682 B 4 13 2.26 0 - - S 175 126526.86 123556.34 0.0
'195512 *U5695 B 3 13 7.81 15 1 1 - 176 126438.62 123494.18 0.0
'1954EC *U5695 B 3 13 7.81 15 1 1 - 177 126438.62 123556.34 0.0
'195830 *U5695 B 3 13 7.81 15 1 1 - 178 126968.06 123432.02 0.0
'19580A *U5695 B 3 13 2.26 0 1 - S 179 126968.06 123494.18 0.0
'1957E4 *U5695 B 3 13 7.81 15 1 1 - 180 126968.06 123556.34 0.0
'1957BE *U5695 B 3 13 7.81 15 1 1 - 181 126968.06 123618.5 0.0
'195798 *U5693 B 1 13 2.4 0 2 - S 182 126968.06 123680.66 0.0
'195772 *U5682 B 4 13 5.58 9 2 - - 183 126879.82 123432.02 0.0
'19574C *U5682 B 4 13 5.58 9 2 - - 184 126879.82 123494.18 0.0
'195726 *U5682 B 4 13 5.58 9 2 - - 185 126879.82 123556.34 0.0
'195700 *U5682 B 4 13 5.58 9 2 - - 186 126879.82 123618.5 0.0
'1956DA *U5694 B 2 13 2.4 0 2 - S 187 126879.82 123680.66 0.0
'1956B4 *U5695 B 3 13 7.81 15 1 1 - 188 126791.58 123432.02 0.0
'19568E *U5682 B 4 13 2.26 0 - - S 189 126791.58 123494.18 0.0
'195668 *U5682 B 4 13 5.58 9 2 - - 190 126791.58 123556.34 0.0
'195642 *U5695 B 3 13 2.26 0 1 - S 191 126791.58 123618.5 0.0
'19561C *U5693 B 1 13 9.43 19 2 1 - 192 126791.58 123680.66 0.0
'195856 *U5695 B 3 13 7.81 15 1 1 - 193 126526.86 123804.98 0.0
'195986 *U5694 B 2 13 7.93 15 2 - - 194 126703.34 123867.14 0.0
'195960 *U5694 B 2 13 7.93 15 2 - - 195 126703.34 123929.3 0.0
'19593A *U5694 B 2 13 2.4 0 2 - S 196 126615.1 123867.14 0.0
'195914 *U5694 B 2 13 2.4 0 2 - S 197 126615.1 123929.3 0.0
'1958EE *U5682 B 4 13 2.26 0 - - S 198 126526.86 123867.14 0.0
'1958C8 *U5682 B 4 13 5.58 9 2 - - 199 126526.86 123929.3 0.0
'1958A2 *U5695 B 3 13 7.81 15 1 1 - 200 126438.62 123867.14 0.0
'19587C *U5695 B 3 13 7.81 15 1 1 - 201 126438.62 123929.3 0.0
'195BC0 *U5693 B 1 13 2.4 0 2 - S 202 126968.06 123804.98 0.0
'195B9A *U5695 B 3 13 7.81 15 1 1 - 203 126968.06 123867.14 0.0
'195B74 *U5695 B 3 13 2.26 0 1 - S 204 126968.06 123929.3 0.0
'195B4E *U5695 B 3 13 7.81 15 1 1 - 205 126968.06 123991.46 0.0
'195B28 *U5693 B 1 13 2.4 0 2 - S 206 126968.06 124053.62 0.0
'195B02 *U5694 B 2 13 7.93 15 2 - - 207 126879.82 123804.98 0.0
'195ADC *U5682 B 4 13 5.58 9 2 - - 208 126879.82 123867.14 0.0
'195AB6 *U5682 B 4 13 5.58 9 2 - - 209 126879.82 123929.3 0.0
'195A90 *U5682 B 4 13 5.58 9 2 - - 210 126879.82 123991.46 0.0
'195A6A *U5682 B 4 13 5.58 9 2 - - 211 126879.82 124053.62 0.0
'195A44 *U5693 B 1 13 2.4 0 2 - S 212 126791.58 123804.98 0.0
'195A1E *U5682 B 4 13 2.26 0 - - S 213 126791.58 123867.14 0.0
'1959F8 *U5682 B 4 13 2.26 0 - - S 214 126791.58 123929.3 0.0
'1959D2 *U5695 B 3 13 7.81 15 1 1 - 215 126791.58 123991.46 0.0
'1959AC *U5695 B 3 13 2.26 0 1 - S 216 126791.58 124053.62 0.0
'195D88 *U5695 A 3 11 2.26 0 1 - S 217 125962.34 123135.08 0.0
'195D62 *U5695 A 3 11 10.77 23 1 2 - 218 125962.34 123197.24 0.0
'195D3C *U5695 A 3 11 2.26 0 1 - S 219 125962.34 123259.4 0.0
'195D16 *U5694 A 2 11 10.89 23 2 1 - 220 125874.1 123135.08 0.0
'195CF0 *U5682 A 4 11 7.81 15 2 1 - 221 125874.1 123197.24 0.0
'195CCA *U5694 A 2 11 2.4 0 2 - S 222 125874.1 123259.4 0.0
'195CA4 *U5682 A 4 11 7.81 15 2 1 - 223 125785.86 123135.08 0.0
'195C7E *U5682 A 4 11 7.81 15 2 1 - 224 125785.86 123197.24 0.0
'195C58 *U5694 A 2 11 2.4 0 2 - S 225 125785.86 123259.4 0.0
'195C32 *U5695 A 3 11 2.26 0 1 - S 226 125697.62 123135.08 0.0
'195C0C *U5695 A 3 11 10.77 23 1 2 - 227 125697.62 123197.24 0.0
'195BE6 *U5695 A 3 11 2.26 0 1 - S 228 125697.62 123259.4 0.0
'195F04 *U5695 A 3 12 2.26 0 1 - S 229 126334.86 123183.38 0.0
'195EDE *U5695 A 3 12 10.77 23 1 2 - 230 126334.86 123245.54 0.0
'195EB8 *U5695 A 3 12 10.77 23 1 2 - 231 126334.86 123307.7 0.0
'195E92 *U5695 A 3 12 2.26 0 1 - S 232 126334.86 123369.86 0.0
'195E6C *U5695 A 3 12 10.77 23 1 2 - 233 126334.86 123432.02 0.0
'195E46 *U5695 A 3 12 10.77 23 1 2 - 234 126246.62 123183.38 0.0
'195E20 *U5695 A 3 12 2.26 0 1 - S 235 126246.62 123245.54 0.0
'195DFA *U5695 A 3 12 2.26 0 1 - S 236 126246.62 123307.7 0.0
'195DD4 *U5695 A 3 12 10.77 23 1 2 - 237 126246.62 123369.86 0.0
'195DAE *U5695 A 3 12 2.26 0 1 - S 238 126246.62 123432.02 0.0
'19605A *U5695 B 3 12 2.26 0 1 - S 239 126334.86 123556.34 0.0
'196034 *U5695 B 3 12 7.81 15 1 1 - 240 126334.86 123618.5 0.0
'19600E *U5695 B 3 12 7.81 15 1 1 - 241 126334.86 123680.66 0.0
'195FE8 *U5695 B 3 12 2.26 0 1 - S 242 126334.86 123742.82 0.0
'195FC2 *U5682 B 4 12 5.58 9 2 - - 243 126246.62 123556.34 0.0
'195F9C *U5695 B 3 12 7.81 15 1 1 - 244 126246.62 123618.5 0.0
'195F76 *U5695 B 3 12 7.81 15 1 1 - 245 126246.62 123680.66 0.0
'195F50 *U5695 B 3 12 7.81 15 1 1 - 246 126246.62 123742.82 0.0
'196294 *U5695 A 3 12 10.77 23 1 2 - 247 125981.9 124177.94 0.0
'19626E *U5693 A 1 12 2.4 0 2 - 1 248 125981.9 124240.1 0.0
'196248 *U5682 A 4 18 7.81 15 2 1 - 249 126703.34 123804.98 0.0
'196222 *U5694 A 2 12 2.4 0 2 - S 250 125893.66 124177.94 0.0
'1961FC *U5694 A 2 12 10.89 23 2 1 - 251 125893.66 124240.1 0.0
'1961D6 *U5695 A 3 18 10.77 23 1 2 - 252 126615.1 123804.98 0.0
'1961B0 *U5694 A 2 12 2.4 0 2 - S 253 125805.42 124177.94 0.0
'19618A *U5694 A 2 12 2.4 0 2 - S 254 125805.42 124240.1 0.0
'196164 *U5694 A 2 18 10.89 23 2 1 - 255 126158.38 123804.98 0.0
'19613E *U5694 A 2 12 10.89 23 2 1 - 256 125717.18 124177.94 0.0
'196118 *U5694 A 2 12 2.4 0 2 - S 257 125717.18 124240.1 0.0
'1960F2 *U5693 A 1 18 2.4 0 2 - 1 258 126070.14 123804.98 0.0
'1960CC *U5693 A 1 12 2.4 0 2 - 1 259 125628.94 124177.94 0.0
'1960A6 *U5693 A 1 12 2.4 0 2 - 1 260 125628.94 124240.1 0.0
'196080 *U5693 A 1 16 2.4 0 2 - 1 261 126615.1 123432.02 0.0
'196306 *U5695 B 3 12 7.81 15 1 1 - 262 125981.9 123991.46 0.0
'1963EA *U5694 B 2 12 2.4 0 2 - S 263 126158.38 123867.14 0.0
'1963C4 *U5694 B 2 12 7.93 15 2 - - 264 126158.38 123929.3 0.0
'19639E *U5694 B 2 12 2.4 0 2 - S 265 126070.14 123867.14 0.0
'196378 *U5694 B 2 12 2.4 0 2 - S 266 126070.14 123929.3 0.0
'196352 *U5695 B 3 12 7.81 15 1 1 - 267 125981.9 123867.14 0.0
'19632C *U5695 B 3 12 2.26 0 1 - S 268 125981.9 123929.3 0.0
'1966E2 *U5695 B 3 12 7.81 15 1 1 - 269 126334.86 123867.14 0.0
'1966BC *U5695 B 3 12 2.26 0 1 - S 270 126334.86 123929.3 0.0
'196696 *U5695 B 3 12 7.81 15 1 1 - 271 126334.86 123991.46 0.0
'196670 *U5695 A 3 12 10.77 23 1 2 - 272 126334.86 124053.62 0.0
'19664A *U5695 A 3 12 2.26 0 1 - S 273 126334.86 124115.78 0.0
'196624 *U5695 A 3 12 10.77 23 1 2 - 274 126334.86 124177.94 0.0
'1965FE *U5693 A 1 12 2.4 0 2 - 1 275 126334.86 124240.1 0.0
'1965D8 *U5695 A 3 18 10.77 23 1 2 - 276 127144.54 123432.02 0.0
'1965B2 *U5682 A 4 18 7.81 15 2 1 - 277 126703.34 123991.46 0.0
'19658C *U5693 A 1 16 2.4 0 2 - 1 278 128182.382 123245.54 0.0
'196566 *U5682 B 4 12 5.58 9 2 - - 279 126246.62 123867.14 0.0
'196540 *U5682 B 4 12 2.26 0 - - S 280 126246.62 123929.3 0.0
'19651A *U5695 B 3 12 7.81 15 1 1 - 281 126246.62 123991.46 0.0
'1964F4 *U5695 A 3 12 2.26 0 1 - S 282 126246.62 124053.62 0.0
'1964CE *U5695 A 3 12 10.77 23 1 2 - 283 126246.62 124115.78 0.0
'1964A8 *U5695 A 3 12 10.77 23 1 2 - 284 126246.62 124177.94 0.0
'196482 *U5693 A 1 12 2.4 0 2 - 1 285 126246.62 124240.1 0.0
'19645C *U5693 A 1 18 2.4 0 2 - 1 286 126703.34 123432.02 0.0
'196436 *U5693 B 1 12 9.43 19 2 1 - 287 126615.1 123991.46 0.0
'196410 *U5693 A 1 17 2.4 0 2 - 1 288 127232.78 122996.9 0.0

File diff suppressed because it is too large Load Diff

View File

@@ -1,169 +0,0 @@
HANDLE BLOCKNAME WIND POS SUBARRAY PSF BAL LTRAY XTRAY ANC ID XCOORD YCOORD ANGLE
'1A66A5 *U5350 B 1 3 2.76 1 2 - 1 1 13906.282 -20190.065 4.124
'1A667F *U5350 B 1 3 2.76 1 2 - 1 2 13818.27 -20196.412 4.124
'1A6633 *U5350 B 1 2 2.76 1 2 - 1 3 13647.543 -20208.723 4.124
'1A6529 *U5425 B 3 3 2.26 0 1 - 1 4 13910.752 -20252.064 4.124
'1A6503 *U5425 B 3 3 2.26 0 1 - 1 5 13822.741 -20258.411 4.124
'1A64B7 *U5425 B 3 2 2.26 0 1 - 1 6 13652.014 -20270.722 4.124
'1A63AD *U5425 B 3 3 2.26 0 1 - 1 7 13915.223 -20314.063 4.124
'1A6387 *U5425 B 3 3 2.26 0 1 - 1 8 13827.212 -20320.41 4.124
'1A633B *U5425 B 3 2 2.26 0 1 - 1 9 13656.484 -20332.721 4.124
'1A6231 *U5425 C 3 3 6.36 11 1 1 - 10 13919.694 -20376.062 4.124
'1A620B *U5425 C 3 3 6.36 11 1 1 - 11 13831.682 -20382.409 4.124
'1A61BF *U5425 C 3 2 6.36 11 1 1 - 12 13660.955 -20394.72 4.124
'1A60B5 *U5425 C 3 3 6.36 11 1 1 - 13 13924.164 -20438.061 4.124
'1A608F *U5425 C 3 3 6.36 11 1 1 - 14 13836.153 -20444.408 4.124
'1A6043 *U5425 C 3 2 6.36 11 1 1 - 15 13665.426 -20456.719 4.124
'1A5F39 *U5425 C 3 3 6.36 11 1 1 - 16 13928.635 -20500.06 4.124
'1A5F13 *U5425 C 3 3 6.36 11 1 1 - 17 13840.624 -20506.407 4.124
'1A5EC7 *U5425 C 3 2 6.36 11 1 1 - 18 13669.896 -20518.718 4.124
'1A5DBD *U5425 C 3 3 6.36 11 1 1 - 19 13933.106 -20562.059 4.124
'1A5D97 *U5425 C 3 3 6.36 11 1 1 - 20 13845.094 -20568.406 4.124
'1A5D4B *U5425 C 3 2 6.36 11 1 1 - 21 13674.367 -20580.717 4.124
'1A5C41 *U5425 C 3 3 6.36 11 1 1 - 22 13937.577 -20624.058 4.124
'1A5C1B *U5425 C 3 3 6.36 11 1 1 - 23 13849.565 -20630.405 4.124
'1A5BCF *U5425 C 3 2 6.36 11 1 1 - 24 13678.838 -20642.716 4.124
'1A5AC5 *U5425 C 3 3 6.36 11 1 1 - 25 13942.047 -20686.057 4.124
'1A5A9F *U5425 C 3 3 6.36 11 1 1 - 26 13854.036 -20692.404 4.124
'1A5A53 *U5425 C 3 2 6.36 11 1 1 - 27 13683.309 -20704.715 4.124
'1A5949 *U5425 C 3 3 6.36 11 1 1 - 28 13946.518 -20748.056 4.124
'1A5923 *U5425 C 3 3 6.36 11 1 1 - 29 13858.506 -20754.403 4.124
'1A58D7 *U5425 C 3 2 6.36 11 1 1 - 30 13687.779 -20766.714 4.124
'1A57CD *U5425 C 3 3 6.36 11 1 1 - 31 13950.989 -20810.056 4.124
'1A57A7 *U5425 C 3 3 6.36 11 1 1 - 32 13862.977 -20816.402 4.124
'1A575B *U5425 C 3 2 6.36 11 1 1 - 33 13692.25 -20828.713 4.124
'1A5651 *U5425 C 3 3 6.36 11 1 1 - 34 13955.459 -20872.055 4.124
'1A562B *U5425 C 3 3 6.36 11 1 1 - 35 13867.448 -20878.401 4.124
'1A55DF *U5425 C 3 2 6.36 11 1 1 - 36 13696.721 -20890.712 4.124
'1A54D5 *U5425 C 3 3 6.36 11 1 1 - 37 13959.93 -20934.054 4.124
'1A54AF *U5425 C 3 3 6.36 11 1 1 - 38 13871.918 -20940.4 4.124
'1A5463 *U5425 C 3 2 6.36 11 1 1 - 39 13701.191 -20952.711 4.124
'1A5359 *U5350 C 1 3 8.35 16 2 1 - 40 13964.401 -20996.053 4.124
'1A5333 *U5350 C 1 3 8.35 16 2 1 - 41 13876.389 -21002.399 4.124
'1A52E7 *U5350 C 1 2 8.35 16 2 1 - 42 13705.662 -21014.71 4.124
'1A52C1 *U5424 B 2 2 2.4 0 2 - 1 43 13559.532 -20215.069 4.124
'1A529B *U5424 B 2 2 2.4 0 2 - 1 44 13471.52 -20221.416 4.124
'1A5275 *U5424 B 2 2 2.4 0 2 - 1 45 13383.509 -20227.762 4.124
'1A524F *U5424 B 2 2 2.4 0 2 - 1 46 13295.497 -20234.108 4.124
'1A5229 *U5350 B 1 2 2.76 1 2 - 1 47 13207.486 -20240.455 4.124
'1A51DD *U5350 B 1 1 2.76 1 2 - 1 48 13031.463 -20253.148 4.124
'1A51B7 *U5424 B 2 1 2.4 0 2 - 1 49 12943.451 -20259.494 4.124
'1A5191 *U5424 B 2 1 2.4 0 2 - 1 50 12855.44 -20265.84 4.124
'1A516B *U5350 B 1 1 2.76 1 2 - 1 51 12767.428 -20272.187 4.124
'1A5145 *U5349 B 4 2 5.58 9 2 - - 52 13564.002 -20277.068 4.124
'1A511F *U5349 B 4 2 5.58 9 2 - - 53 13475.991 -20283.415 4.124
'1A50F9 *U5349 B 4 2 5.58 9 2 - - 54 13387.979 -20289.761 4.124
'1A50D3 *U5349 B 4 2 5.58 9 2 - - 55 13299.968 -20296.107 4.124
'1A50AD *U5425 B 3 2 2.26 0 1 - 1 56 13211.956 -20302.454 4.124
'1A5061 *U5425 B 3 1 2.26 0 1 - 1 57 13035.933 -20315.147 4.124
'1A503B *U5349 B 4 1 5.58 9 2 - - 58 12947.922 -20321.493 4.124
'1A5015 *U5349 B 4 1 5.58 9 2 - - 59 12859.91 -20327.839 4.124
'1A4FEF *U5425 B 3 1 2.26 0 1 - 1 60 12771.899 -20334.186 4.124
'1A4FC9 *U5349 B 4 2 5.58 9 2 - - 61 13568.473 -20339.067 4.124
'1A4FA3 *U5349 B 4 2 5.58 9 2 - - 62 13480.461 -20345.414 4.124
'1A4F7D *U5349 C 4 2 3.71 4 - - - 63 13392.45 -20351.76 4.124
'1A4F57 *U5349 C 4 2 3.71 4 - - - 64 13304.439 -20358.106 4.124
'1A4F31 *U5425 C 3 2 6.36 11 1 1 - 65 13216.427 -20364.453 4.124
'1A4EE5 *U5425 B 3 1 2.26 0 1 - 1 66 13040.404 -20377.146 4.124
'1A4EBF *U5349 B 4 1 5.58 9 2 - - 67 12952.393 -20383.492 4.124
'1A4E99 *U5349 B 4 1 5.58 9 2 - - 68 12864.381 -20389.838 4.124
'1A4E73 *U5425 B 3 1 2.26 0 1 - 1 69 12776.37 -20396.185 4.124
'1A4E4D *U5349 C 4 2 3.71 4 - - - 70 13572.944 -20401.066 4.124
'1A4E27 *U5349 C 4 2 3.71 4 - - - 71 13484.932 -20407.413 4.124
'1A4E01 *U5349 C 4 2 3.71 4 - - - 72 13396.921 -20413.759 4.124
'1A4DDB *U5349 C 4 2 3.71 4 - - - 73 13308.909 -20420.105 4.124
'1A4DB5 *U5425 C 3 2 6.36 11 1 1 - 74 13220.898 -20426.452 4.124
'1A4D69 *U5425 B 3 1 2.26 0 1 - 1 75 13044.875 -20439.145 4.124
'1A4D43 *U5349 B 4 1 5.58 9 2 - - 76 12956.863 -20445.491 4.124
'1A4D1D *U5349 B 4 1 5.58 9 2 - - 77 12868.852 -20451.837 4.124
'1A4CF7 *U5425 B 3 1 2.26 0 1 - 1 78 12780.84 -20458.184 4.124
'1A4CD1 *U5349 C 4 2 3.71 4 - - - 79 13577.414 -20463.065 4.124
'1A4CAB *U5349 C 4 2 3.71 4 - - - 80 13489.403 -20469.412 4.124
'1A4C85 *U5349 C 4 2 3.71 4 - - - 81 13401.391 -20475.758 4.124
'1A4C5F *U5349 C 4 2 3.71 4 - - - 82 13313.38 -20482.104 4.124
'1A4C39 *U5425 C 3 2 6.36 11 1 1 - 83 13225.368 -20488.451 4.124
'1A4BED *U5425 B 3 1 2.26 0 1 - 1 84 13049.345 -20501.144 4.124
'1A4BC7 *U5349 B 4 1 5.58 9 2 - - 85 12961.334 -20507.49 4.124
'1A4BA1 *U5349 B 4 1 5.58 9 2 - - 86 12873.322 -20513.836 4.124
'1A4B7B *U5425 B 3 1 2.26 0 1 - 1 87 12785.311 -20520.183 4.124
'1A4B55 *U5349 C 4 2 3.71 4 - - - 88 13581.885 -20525.064 4.124
'1A4B2F *U5349 C 4 2 3.71 4 - - - 89 13493.874 -20531.411 4.124
'1A4B09 *U5349 C 4 2 3.71 4 - - - 90 13405.862 -20537.757 4.124
'1A4AE3 *U5349 C 4 2 3.71 4 - - - 91 13317.851 -20544.103 4.124
'1A4ABD *U5425 C 3 2 6.36 11 1 1 - 92 13229.839 -20550.45 4.124
'1A4A71 *U5425 B 3 1 2.26 0 1 - 1 93 13053.816 -20563.143 4.124
'1A4A4B *U5349 B 4 1 5.58 9 2 - - 94 12965.805 -20569.489 4.124
'1A4A25 *U5349 B 4 1 5.58 9 2 - - 95 12877.793 -20575.836 4.124
'1A49FF *U5425 B 3 1 2.26 0 1 - 1 96 12789.782 -20582.182 4.124
'1A49D9 *U5349 B 4 2 5.58 9 2 - - 97 13586.356 -20587.063 4.124
'1A49B3 *U5349 B 4 2 5.58 9 2 - - 98 13498.344 -20593.41 4.124
'1A498D *U5349 B 4 2 5.58 9 2 - - 99 13410.333 -20599.756 4.124
'1A4967 *U5349 B 4 2 5.58 9 2 - - 100 13322.321 -20606.102 4.124
'1A4941 *U5425 B 3 2 2.26 0 1 - 1 101 13234.31 -20612.449 4.124
'1A48F5 *U5425 B 3 1 2.26 0 1 - 1 102 13058.287 -20625.142 4.124
'1A48CF *U5349 B 4 1 5.58 9 2 - - 103 12970.275 -20631.488 4.124
'1A48A9 *U5349 B 4 1 5.58 9 2 - - 104 12882.264 -20637.835 4.124
'1A4883 *U5425 B 3 1 2.26 0 1 - 1 105 12794.252 -20644.181 4.124
'1A485D *U5349 B 4 2 5.58 9 2 - - 106 13590.826 -20649.062 4.124
'1A4837 *U5349 B 4 2 5.58 9 2 - - 107 13502.815 -20655.409 4.124
'1A4811 *U5349 B 4 2 5.58 9 2 - - 108 13414.803 -20661.755 4.124
'1A47EB *U5349 B 4 2 5.58 9 2 - - 109 13326.792 -20668.101 4.124
'1A47C5 *U5425 B 3 2 2.26 0 1 - 1 110 13238.78 -20674.448 4.124
'1A4779 *U5425 B 3 1 2.26 0 1 - 1 111 13062.757 -20687.141 4.124
'1A4753 *U5349 B 4 1 5.58 9 2 - - 112 12974.746 -20693.487 4.124
'1A472D *U5349 B 4 1 5.58 9 2 - - 113 12886.735 -20699.834 4.124
'1A4707 *U5425 B 3 1 2.26 0 1 - 1 114 12798.723 -20706.18 4.124
'1A46E1 *U5349 B 4 2 5.58 9 2 - - 115 13595.297 -20711.061 4.124
'1A46BB *U5349 B 4 2 5.58 9 2 - - 116 13507.286 -20717.408 4.124
'1A4695 *U5349 B 4 2 5.58 9 2 - - 117 13419.274 -20723.754 4.124
'1A466F *U5349 B 4 2 5.58 9 2 - - 118 13331.263 -20730.101 4.124
'1A4649 *U5425 B 3 2 2.26 0 1 - 1 119 13243.251 -20736.447 4.124
'1A45FD *U5425 B 3 1 2.26 0 1 - 1 120 13067.228 -20749.14 4.124
'1A45D7 *U5349 B 4 1 5.58 9 2 - - 121 12979.217 -20755.486 4.124
'1A45B1 *U5349 B 4 1 5.58 9 2 - - 122 12891.205 -20761.833 4.124
'1A458B *U5425 B 3 1 2.26 0 1 - 1 123 12803.194 -20768.179 4.124
'1A4565 *U5349 B 4 2 5.58 9 2 - - 124 13599.768 -20773.06 4.124
'1A453F *U5349 B 4 2 5.58 9 2 - - 125 13511.756 -20779.407 4.124
'1A4519 *U5349 B 4 2 5.58 9 2 - - 126 13423.745 -20785.753 4.124
'1A44F3 *U5349 B 4 2 5.58 9 2 - - 127 13335.733 -20792.1 4.124
'1A44CD *U5425 B 3 2 2.26 0 1 - 1 128 13247.722 -20798.446 4.124
'1A4481 *U5425 B 3 1 2.26 0 1 - 1 129 13071.699 -20811.139 4.124
'1A445B *U5349 B 4 1 5.58 9 2 - - 130 12983.687 -20817.485 4.124
'1A4435 *U5349 B 4 1 5.58 9 2 - - 131 12895.676 -20823.832 4.124
'1A440F *U5425 B 3 1 2.26 0 1 - 1 132 12807.664 -20830.178 4.124
'1A43E9 *U5349 B 4 2 5.58 9 2 - - 133 13604.238 -20835.059 4.124
'1A43C3 *U5349 B 4 2 5.58 9 2 - - 134 13516.227 -20841.406 4.124
'1A439D *U5349 B 4 2 5.58 9 2 - - 135 13428.215 -20847.752 4.124
'1A4377 *U5349 B 4 2 5.58 9 2 - - 136 13340.204 -20854.099 4.124
'1A4351 *U5425 B 3 2 2.26 0 1 - 1 137 13252.192 -20860.445 4.124
'1A4305 *U5425 B 3 1 2.26 0 1 - 1 138 13076.17 -20873.138 4.124
'1A42DF *U5349 B 4 1 5.58 9 2 - - 139 12988.158 -20879.484 4.124
'1A42B9 *U5349 B 4 1 5.58 9 2 - - 140 12900.147 -20885.831 4.124
'1A4293 *U5425 B 3 1 2.26 0 1 - 1 141 12812.135 -20892.177 4.124
'1A426D *U5349 B 4 2 5.58 9 2 - - 142 13608.709 -20897.058 4.124
'1A4247 *U5349 B 4 2 5.58 9 2 - - 143 13520.698 -20903.405 4.124
'1A4221 *U5349 B 4 2 5.58 9 2 - - 144 13432.686 -20909.751 4.124
'1A41FB *U5349 B 4 2 5.58 9 2 - - 145 13344.675 -20916.098 4.124
'1A41D5 *U5425 B 3 2 2.26 0 1 - 1 146 13256.663 -20922.444 4.124
'1A4189 *U5425 B 3 1 2.26 0 1 - 1 147 13080.64 -20935.137 4.124
'1A4163 *U5349 B 4 1 5.58 9 2 - - 148 12992.629 -20941.483 4.124
'1A413D *U5349 B 4 1 5.58 9 2 - - 149 12904.617 -20947.83 4.124
'1A4117 *U5425 B 3 1 2.26 0 1 - 1 150 12816.606 -20954.176 4.124
'1A40F1 *U5349 B 4 2 5.58 9 2 - - 151 13613.18 -20959.057 4.124
'1A40CB *U5349 B 4 2 5.58 9 2 - - 152 13525.168 -20965.404 4.124
'1A40A5 *U5349 B 4 2 5.58 9 2 - - 153 13437.157 -20971.75 4.124
'1A407F *U5349 B 4 2 5.58 9 2 - - 154 13349.145 -20978.097 4.124
'1A4059 *U5425 B 3 2 2.26 0 1 - 1 155 13261.134 -20984.443 4.124
'1A400D *U5425 B 3 1 2.26 0 1 - 1 156 13085.111 -20997.136 4.124
'1A3FE7 *U5349 B 4 1 5.58 9 2 - - 157 12997.099 -21003.482 4.124
'1A3FC1 *U5349 B 4 1 5.58 9 2 - - 158 12909.088 -21009.829 4.124
'1A3F9B *U5425 B 3 1 2.26 0 1 - 1 159 12821.076 -21016.175 4.124
'1A3F75 *U5424 B 2 2 2.4 0 2 - 1 160 13617.65 -21021.056 4.124
'1A3F4F *U5424 B 2 2 2.4 0 2 - 1 161 13529.639 -21027.403 4.124
'1A3F29 *U5424 B 2 2 2.4 0 2 - 1 162 13441.628 -21033.749 4.124
'1A3F03 *U5424 B 2 2 2.4 0 2 - 1 163 13353.616 -21040.096 4.124
'1A3EDD *U5350 B 1 2 2.76 1 2 - 1 164 13265.605 -21046.442 4.124
'1A3E91 *U5350 B 1 1 2.76 1 2 - 1 165 13089.582 -21059.135 4.124
'1A3E6B *U5424 B 2 1 2.4 0 2 - 1 166 13001.57 -21065.481 4.124
'1A3E45 *U5424 B 2 1 2.4 0 2 - 1 167 12913.559 -21071.828 4.124
'1A3E1F *U5350 B 1 1 2.76 1 2 - 1 168 12825.547 -21078.174 4.124

View File

@@ -290,7 +290,7 @@ class DocGenParamsBuilderTest(unittest.TestCase):
('513832', 0),
('513833', 790),
('513836', 0),
('521794', 196),
('513841', 196),
('anchors', 262),
('ballast', 6786),
@@ -304,7 +304,7 @@ class DocGenParamsBuilderTest(unittest.TestCase):
'total_513832': 0,
'total_513833': 790,
'total_513836': 0,
'total_521794': 196,
'total_513841': 196,
'total_anchors': 262,
'total_ballast': 6786,
'total_modules': 1726

View File

@@ -67,12 +67,10 @@ class PanelPresenterTest(unittest.TestCase):
def test_get_buildings_data(self):
self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96)
buildings = [ [ Coordinate(-60,-60), Coordinate(60,-60), Coordinate(60,60), Coordinate(-60,60) ] ] # big square
expected_buildings = [[
{'x': -60, '_Coordinate__rounded_x': -60, 'y': -60, '_Coordinate__rounded_y': -60, 'rotation': 0.0},
{'x': 60, '_Coordinate__rounded_x': 60, 'y': -60, '_Coordinate__rounded_y': -60, 'rotation': 0.0},
{'x': 60, '_Coordinate__rounded_x': 60, 'y': 60, '_Coordinate__rounded_y': 60, 'rotation': 0.0},
{'x': -60, '_Coordinate__rounded_x': -60, 'y': 60, '_Coordinate__rounded_y': 60, 'rotation': 0.0}
]]
expected_buildings = [[ {'x': -60, '_Coordinate__rounded_x': -60, 'y': 60, '_Coordinate__rounded_y': -60, 'rotation': 0.0},
{'x': 60, '_Coordinate__rounded_x': 60, 'y': 60, '_Coordinate__rounded_y': -60, 'rotation': 0.0},
{'x': 60, '_Coordinate__rounded_x': 60, 'y': -60, '_Coordinate__rounded_y': 60, 'rotation': 0.0},
{'x': -60, '_Coordinate__rounded_x': -60, 'y': -60, '_Coordinate__rounded_y': 60, 'rotation': 0.0}]]
actual_buildings = self.subject.get_buildings(buildings)
assert_array_equal(actual_buildings,expected_buildings)

View File

@@ -1,4 +1,3 @@
import time
from flask.ext.testing import LiveServerTestCase
import mockredis
from splinter import Browser
@@ -66,7 +65,6 @@ class ArraySummaryDynamicTest(LiveServerTestCase):
def test_shows_subarray_summary_table_if_user_has_uploaded_data(self):
self.fill_in_site_characterization_data()
self.upload_cad_block_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
time.sleep(3)
assert len(self.browser.find_by_css('.upload_field .error_message')) == 0
assert len(self.browser.find_by_css("#seismic_anchor_table")) > 0
eq_(len(self.browser.find_by_css("#seismic_anchor_table tr")), 4)
@@ -75,7 +73,6 @@ class ArraySummaryDynamicTest(LiveServerTestCase):
def test_shows_errors_if_user_tries_to_upload_select_invalid_data(self):
self.fill_in_site_characterization_data()
self.upload_cad_block_file('test/fixtures/invalid_wind_zone.csv')
time.sleep(3)
assert len(self.browser.find_by_id('error_message_txt')) > 0
assert len(self.browser.find_by_css("#seismic_anchor_table")) == 0
@@ -90,29 +87,30 @@ class ArraySummaryDynamicTest(LiveServerTestCase):
def test_indicates_that_user_has_already_uploaded_a_csv_file_after_uploading(self):
self.fill_in_site_characterization_data()
self.upload_cad_block_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
time.sleep(3)
assert len(self.browser.find_by_css('.upload_field .error_message')) == 0
assert 'input_single_tilt_csv_for_bom.csv' in self.browser.html
def test_adding_seismic_anchor_updates_subarray_summary(self):
self.fill_in_site_characterization_data()
self.upload_cad_block_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
time.sleep(3)
assert self.browser.is_element_visible_by_css('#arrayCanvas')
self.browser.execute_script('arrayVisualization.selectPanel(1631);')
self.browser.find_by_css('#add_seismic').click()
assert self.browser.find_by_css('#current_anchors td:nth-child(14)').text == '1'
self.browser.find_by_css('#add_seismic').click()
assert self.browser.find_by_css('#current_anchors td:nth-child(14)').text == '2'
def test_removig_seismic_anchor_updates_subarray_summary(self):
self.fill_in_site_characterization_data()
self.upload_cad_block_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
time.sleep(3)
assert self.browser.is_element_visible_by_css('#arrayCanvas')
self.browser.execute_script('arrayVisualization.selectPanel(1631);')
self.browser.find_by_css('#add_seismic').click()
assert self.browser.find_by_css('#current_anchors td:nth-child(14)').text == '1'
self.browser.find_by_css('#remove_seismic').click()
assert self.browser.find_by_css('#current_anchors td:nth-child(14)').text == '0'

View File

@@ -171,11 +171,11 @@ class ArraySummaryTest(unittest.TestCase):
def test_shows_summary_values(self):
self.fill_in_site_characterization_data()
self.upload_csv_file(file='test/fixtures/input_single_tilt_csv_for_bom.csv')
self.assert_summary_values_column_data(1, 'Total System Weight (lbs)', '217,409')
self.assert_summary_values_column_data(2, 'Max PSF', '9.36')
self.assert_summary_values_column_data(3, 'Avg PSF', '5.08')
self.assert_summary_values_column_data(4, 'Total Anchors', '422')
self.assert_summary_values_column_data(5, 'Total Ballast', '10,448')
self.assert_summary_values_column_data(1, 'Total System Weight (lbs)', '216,074')
self.assert_summary_values_column_data(2, 'Max PSF', '9.11')
self.assert_summary_values_column_data(3, 'Avg PSF', '5.05')
self.assert_summary_values_column_data(4, 'Total Anchors', '421')
self.assert_summary_values_column_data(5, 'Total Ballast', '10,150')
def test_shows_seismic_placement_interval(self):
self.fill_in_site_characterization_data(system_type=SystemType.dualTilt)
@@ -212,26 +212,26 @@ class ArraySummaryTest(unittest.TestCase):
eq_(response.content_type, "application/json")
data = json.loads(response.data.decode())
expected = [
{'data': {'ballast': 7, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 1, 'panel_type': 2, 'psf': 4.91, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 2, 'panel_type': 2, 'psf': 3.1, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 3, 'panel_type': 1, 'psf': 6.48, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 4, 'panel_type': 1, 'psf': 6.48, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 7, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 1, 'panel_type': 2, 'psf': 4.94, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 2, 'panel_type': 2, 'psf': 3.12, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 3, 'panel_type': 1, 'psf': 6.47, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 4, 'panel_type': 1, 'psf': 6.47, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 5, 'panel_type': 1, 'psf': 4.57, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 6, 'panel_type': 2, 'psf': 3.1, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 6, 'panel_type': 2, 'psf': 3.12, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 7, 'panel_type': 4, 'psf': 2.26, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 8, 'panel_type': 3, 'psf': 3.0, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 9, 'panel_type': 3, 'psf': 3.0, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 8, 'panel_type': 3, 'psf': 2.98, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 9, 'panel_type': 3, 'psf': 2.98, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 10, 'panel_type': 4, 'psf': 2.26, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 11, 'panel_type': 2, 'psf': 3.1, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 12, 'panel_type': 3, 'psf': 3.0, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 13, 'panel_type': 3, 'psf': 3.0, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 14, 'panel_type': 3, 'psf': 3.0, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 11, 'panel_type': 2, 'psf': 3.12, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 12, 'panel_type': 3, 'psf': 2.98, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 13, 'panel_type': 3, 'psf': 2.98, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 2, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 14, 'panel_type': 3, 'psf': 2.98, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 15, 'panel_type': 1, 'psf': 4.57, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 16, 'panel_type': 1, 'psf': 4.57, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 17, 'panel_type': 1, 'psf': 4.57, 'seismic_anchors': 0, 'subarray': 7, 'wind_anchors': 0, 'wind_zones': 'B'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 18, 'panel_type': 1, 'psf': 6.48, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 19, 'panel_type': 3, 'psf': 4.5, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 20, 'panel_type': 1, 'psf': 6.48, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5}
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 18, 'panel_type': 1, 'psf': 6.47, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 6, 'cross_trays': 0, 'link_trays': 1, 'panel_id': 19, 'panel_type': 3, 'psf': 4.48, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5},
{'data': {'ballast': 11, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 20, 'panel_type': 1, 'psf': 6.47, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 0, 'wind_zones': 'A'}, 'height': 1, 'width': 1.5}
]
# Removing these keys as they get calculated differently in CircleCI
@@ -290,28 +290,28 @@ class ArraySummaryTest(unittest.TestCase):
"status": "success",
"error": None,
"panel_data": [
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 1, 'panel_type': 1, 'psf': 1.95, 'seismic_anchors': 2, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 2, 'panel_type': 3, 'psf': 1.88, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 3, 'panel_type': 1, 'psf': 1.95, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 4, 'panel_type': 1, 'psf': 1.95, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 5, 'panel_type': 3, 'psf': 1.88, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 6, 'panel_type': 3, 'psf': 1.88, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 2, 'panel_id': 7, 'panel_type': 3, 'psf': 1.88, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 8, 'panel_type': 1, 'psf': 1.95, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 9, 'panel_type': 2, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 10, 'panel_type': 2, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 11, 'panel_type': 2, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'I'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 12, 'panel_type': 4, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 13, 'panel_type': 4, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 14, 'panel_type': 4, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 15, 'panel_type': 4, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 16, 'panel_type': 4, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 17, 'panel_type': 4, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 18, 'panel_type': 2, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'H'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'data': {'ballast': 0, 'cross_trays': 0, 'link_trays': 0, 'panel_id': 19, 'panel_type': 2, 'psf': 1.84, 'seismic_anchors': 0, 'subarray': 8, 'wind_anchors': 1, 'wind_zones': 'I'}, 'height': 1, 'width': 1, 'x': 0.0, 'y': 0.0},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.08, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 1, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 2, 'panel_id': 1}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.04, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 3, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 2, 'seismic_anchors': 0, 'panel_id': 2}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.08, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 1, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 3}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.08, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 1, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 4}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.04, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 3, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 2, 'seismic_anchors': 0, 'panel_id': 5}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.04, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 3, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 2, 'seismic_anchors': 0, 'panel_id': 6}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.04, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 3, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 2, 'seismic_anchors': 0, 'panel_id': 7}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 2.08, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 1, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 8}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.89, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 2, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 9}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.89, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 2, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 10}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.89, 'wind_zones': 'I', 'ballast': 0, 'panel_type': 2, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 11}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 12}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 13}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 14}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 15}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 16}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.86, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 4, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 17}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.89, 'wind_zones': 'H', 'ballast': 0, 'panel_type': 2, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 18}},
{'x': 0, 'y': 0, 'height': 1, 'width': 1, 'data': {'subarray': 8, 'psf': 1.89, 'wind_zones': 'I', 'ballast': 0, 'panel_type': 2, 'cross_trays': 0, 'wind_anchors': 1, 'link_trays': 0, 'seismic_anchors': 0, 'panel_id': 19}},
],
"subarray_data": [
{"subarray": 8, "weight": 932, "required_seismic_anchors": 0},
{"subarray": 8, "weight": 972, "required_seismic_anchors": 0},
],
}
received_result = flask.json.loads(result.data)
@@ -367,10 +367,9 @@ class ArraySummaryTest(unittest.TestCase):
expected_result = [
{"subarray": 7, "weight": 2253, "required_seismic_anchors": 4},
{"subarray": 8, "weight": 674, "required_seismic_anchors": 0},
{"subarray": 8, "weight": 673, "required_seismic_anchors": 0},
]
received_result = flask.json.loads(result.data)
eq_(received_result['subarray_data'], expected_result)
eq_(result.content_type, "application/json")
@@ -411,7 +410,7 @@ class ArraySummaryTest(unittest.TestCase):
"error": SeismicAnchorValidationError.TooFewAnchors.value,
"panel_data": None,
"subarray_data": [
{"subarray": 1, "weight": 2722, "required_seismic_anchors": 6},
{"subarray": 1, "weight": 2739, "required_seismic_anchors": 6},
],
}
eq_(flask.json.loads(result.data), expected_result)

View File

@@ -36,7 +36,9 @@ class BomIntegrationTest(unittest.TestCase):
expected = [
["512200", "CLIP, WIRE FORMED, CABLE MANAGEMENT, INSIDE, 352MM ^ 2", "510"],
["513833", "TRAY, LINK, HELIX ROOF", "78"],
["513833", "TRAY, LINK, HELIX ROOF", "78"], # TODO: should be 74 for part perfect bom
["513841", "DEFLECTOR, LH, HELIX ROOF", "30"],
["513842", "DEFLECTOR, RH, HELIX ROOF", "30"],
["513843", "PLATE, ANCHOR, HELIX ROOF", "86"],
["513844", "TRAY, OPTIONAL BALLAST, HELIX ROOF", "35"],
["514056", "BASE, CHASSIS, DUAL TILT, HELIX ROOF", "147"],
@@ -46,9 +48,7 @@ class BomIntegrationTest(unittest.TestCase):
["515928", "FRONT SKIRT, HELIX ROOF", "126"],
["517871", "TRAY, LEADING, HELIX ROOF, RIVETED VERSION", "67"],
["518477", "WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS", "100"],
["521794", "DEFLECTOR, LH, HELIX ROOF V1.1", "30"],
["521795", "DEFLECTOR, RH, HELIX ROOF V1.1", "30"],
["Contractor Supplied", "Ballast Blocks", "610"],
["Contractor Supplied", "Ballast Blocks", "608"],
["TBD", "Anchors", "86"],
["TBD", "Modules", "252"]
]
@@ -82,6 +82,8 @@ class BomIntegrationTest(unittest.TestCase):
expected = [
['512200', 'CLIP, WIRE FORMED, CABLE MANAGEMENT, INSIDE, 352MM ^ 2', '540'],
['513833', 'TRAY, LINK, HELIX ROOF', '75'], # TODO: should be 73 for part perfect bom
['513841', 'DEFLECTOR, LH, HELIX ROOF', '20'],
['513842', 'DEFLECTOR, RH, HELIX ROOF', '20'],
['513843', 'PLATE, ANCHOR, HELIX ROOF', '114'],
['513844', 'TRAY, OPTIONAL BALLAST, HELIX ROOF', '17'],
['514056', 'BASE, CHASSIS, DUAL TILT, HELIX ROOF', '148'],
@@ -91,8 +93,6 @@ class BomIntegrationTest(unittest.TestCase):
['515928', 'FRONT SKIRT, HELIX ROOF', '130'],
['517871', 'TRAY, LEADING, HELIX ROOF, RIVETED VERSION', '69'],
['518477', 'WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS', '125'],
["521794", "DEFLECTOR, LH, HELIX ROOF V1.1", "20"],
["521795", "DEFLECTOR, RH, HELIX ROOF V1.1", "20"],
['Contractor Supplied', 'Ballast Blocks', '358'],
['TBD', 'Anchors', '114'],
['TBD', 'Modules', '264']
@@ -126,6 +126,8 @@ class BomIntegrationTest(unittest.TestCase):
expected = [
['512200', 'CLIP, WIRE FORMED, CABLE MANAGEMENT, INSIDE, 352MM ^ 2', '330'],
['513833', 'TRAY, LINK, HELIX ROOF', '45'], # 45 is perfect value for this bom
['513841', 'DEFLECTOR, LH, HELIX ROOF', '36'],
['513842', 'DEFLECTOR, RH, HELIX ROOF', '36'],
['513843', 'PLATE, ANCHOR, HELIX ROOF', '67'],
['513844', 'TRAY, OPTIONAL BALLAST, HELIX ROOF', '13'],
['514056', 'BASE, CHASSIS, DUAL TILT, HELIX ROOF', '102'],
@@ -135,8 +137,6 @@ class BomIntegrationTest(unittest.TestCase):
['515928', 'FRONT SKIRT, HELIX ROOF', '88'],
['517871', 'TRAY, LEADING, HELIX ROOF, RIVETED VERSION', '53'],
['518477', 'WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS', '75'],
["521794", "DEFLECTOR, LH, HELIX ROOF V1.1", "36"],
["521795", "DEFLECTOR, RH, HELIX ROOF V1.1", "36"],
['Contractor Supplied', 'Ballast Blocks', '286'],
['TBD', 'Anchors', '67'],
['TBD', 'Modules', '160'],
@@ -171,6 +171,8 @@ class BomIntegrationTest(unittest.TestCase):
expected = [
['512200', 'CLIP, WIRE FORMED, CABLE MANAGEMENT, INSIDE, 352MM ^ 2', '510'],
['513833', 'TRAY, LINK, HELIX ROOF', '73'], # TODO: should be 70 for part perfect bom
['513841', 'DEFLECTOR, LH, HELIX ROOF', '24'],
['513842', 'DEFLECTOR, RH, HELIX ROOF', '24'],
['513843', 'PLATE, ANCHOR, HELIX ROOF', '94'],
['513844', 'TRAY, OPTIONAL BALLAST, HELIX ROOF', '28'],
['514056', 'BASE, CHASSIS, DUAL TILT, HELIX ROOF', '140'],
@@ -180,8 +182,6 @@ class BomIntegrationTest(unittest.TestCase):
['515928', 'FRONT SKIRT, HELIX ROOF', '120'],
['517871', 'TRAY, LEADING, HELIX ROOF, RIVETED VERSION', '64'],
['518477', 'WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS', '100'],
["521794", "DEFLECTOR, LH, HELIX ROOF V1.1", "24"],
["521795", "DEFLECTOR, RH, HELIX ROOF V1.1", "24"],
['Contractor Supplied', 'Ballast Blocks', '560'],
['TBD', 'Anchors', '94'],
['TBD', 'Modules', '244'],

View File

@@ -10,7 +10,6 @@ from helix.constants import sql_constant
from helix.constants.anchor_type import AnchorType
from helix.constants.inverter_type import InverterType
from helix.constants.system_type import SystemType
from helix.constants.module_type import ModuleType
from helix.constants.version import version
from helix.models.sql.power_stations import PowerStation
from test.integration.integration_test_helpers import *
@@ -126,34 +125,29 @@ class FullUserFlowTest(unittest.TestCase):
eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')
def test_downloading_coordinates_csv(self):
#with open('test/fixtures/expected_dual_tilt_big_spacing.txt', 'r', newline='') as csv_file:
with open('test/fixtures/expected_small_dual_tilt.txt', 'r', newline='') as csv_file:
csv_content = csv_file.read()
self.browser.fill('project_name', 'Test Project Name')
self.browser.fill('building_width', '450')
self.browser.fill('building_height', '35')
self.browser.fill('building_length', '500')
self.browser.fill('wind_speed', '110')
self.browser.fill('exposure_category', 'B')
self.browser.fill('ballast_block_weight', '14')
self.browser.fill('building_parapet_height', '5')
self.browser.fill('max_system_pressure', '10')
self.browser.fill('system_type', SystemType.dualTilt.value)
self.browser.fill('anchor_type', AnchorType.OMG_PowerGrip_Plus.value)
self.browser.fill('design_spectral_response', '1.5')
self.browser.fill('module_type', ModuleType.Cell96.value)
with open('test/fixtures/expected_dual_tilt_coordinates.csv', 'r', newline='') as csv_file:
csv_content = csv_file.read()
self.browser.fill('project_name', 'Test Project Name')
self.browser.fill('building_width', '450')
self.browser.fill('building_height', '35')
self.browser.fill('building_length', '500')
self.browser.fill('wind_speed', '110')
self.browser.fill('exposure_category', 'B')
self.browser.fill('ballast_block_weight', '14')
self.browser.fill('building_parapet_height', '5')
self.browser.fill('max_system_pressure', '10')
self.browser.fill('system_type', SystemType.dualTilt.value)
self.browser.fill('anchor_type', AnchorType.OMG_PowerGrip_Plus.value)
self.browser.fill('design_spectral_response', '1.5')
self.advance_n_times(1)
self.attach_file('test/fixtures/input_small_dual_tilt.csv')
self.advance_n_times(1)
self.browser.visit('/download/')
self.browser.click_link_by_partial_text('Download AutoCAD import file')
print("===")
print(self.browser.html)
eq_(self.browser.html, csv_content)
eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')
self.advance_n_times(1)
self.attach_file('test/fixtures/input_dual_tilt_coordinates.csv')
self.advance_n_times(1)
self.browser.visit('/download/')
self.browser.click_link_by_partial_text('Download AutoCAD import file')
eq_(self.browser.html, csv_content)
eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')
# def test_uploading_dxf_and_downloading_csv(self):
# self.browser.fill('project_name', 'Test Project Name')

Some files were not shown because too many files have changed in this diff Show More