6 Commits

Author SHA1 Message Date
GotPPay
20a6d7b518 test fix again 2017-11-28 00:34:58 +01:00
GotPPay
49348ce8ca test fix 2017-11-28 00:34:58 +01:00
GotPPay
93f3bfdc79 scaled version 2017-11-28 00:31:35 +01:00
GotPPay
4f16a398aa . 2017-11-28 00:31:03 +01:00
Senad Uka
efb4547a37 updating master 2017-11-27 17:04:51 +01:00
Senad Uka
b4e45199b7 syncing master 2017-11-21 17:11:29 +01:00
41 changed files with 5674 additions and 280 deletions

View File

@@ -5,7 +5,90 @@
- [Production](https://helix-calculator.sunpower.com/) - [Production](https://helix-calculator.sunpower.com/)
### Setup ## 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 |
##### 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 -t -i helix /bin/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
#### macOS systems #### macOS systems

View File

@@ -1,58 +1,51 @@
machine: version: 2
python: jobs:
version: 3.5.1 build:
node: docker:
version: 6.1.0 - image: ivannnn/heroku_cedar14:2.0
environment:
dependencies: PGUSER: pivotal
pre: PGPASSWORD: password
- pip install invoke PASSWORD: password
override: environment:
- invoke install PATH: /usr/local/rvm/gems/ruby-2.3.4/bin:/usr/local/rvm/gems/ruby-2.3.4@global/bin:/usr/local/rvm/rubies/ruby-2.3.4/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/rvm/bin
- invoke update_version steps:
- checkout
database: - run:
override: name: Set up and Run tests
- createdb test command: |
- createdb pivotal source /etc/profile.d/rvm.sh
- echo "CREATE ROLE pivotal WITH UNENCRYPTED PASSWORD 'password';" | psql -U postgres rvm use 2.3.4
- echo "ALTER ROLE pivotal WITH LOGIN;" | psql -U postgres /etc/init.d/postgresql start
- echo "GRANT SELECT, UPDATE, INSERT ON ALL TABLES IN SCHEMA test.public TO pivotal;" | psql -U postgres python3.4 -m venv env
- echo "GRANT CREATE, CONNECT ON DATABASE test TO pivotal;" | psql -U postgres source env/bin/activate
- echo "GRANT SELECT, UPDATE, INSERT ON ALL TABLES IN SCHEMA pivotal.public TO pivotal;" | psql -U postgres pip install invoke
- echo "GRANT CREATE, CONNECT ON DATABASE pivotal TO pivotal;" | psql -U postgres invoke install
- PYTHONPATH=.:$PYTHONPATH alembic upgrade head npm install
invoke db_migrate
test: invoke test_ci
override: - deploy:
- invoke test_ci name: staging
command: |
deployment: invoke update_heroku_version staging
staging: "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow"
branch: master git push -f git@heroku.com:sp-helix-staging.git $CIRCLE_SHA1:refs/heads/master
commands: heroku run --app sp-helix-staging invoke db_migrate
- invoke update_heroku_version staging rake ci:deliver
- "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow" name: preprod
- git push -f git@heroku.com:sp-helix-staging.git $CIRCLE_SHA1:refs/heads/master command: |
- heroku run --app sp-helix-staging invoke db_migrate invoke update_heroku_version preprod
- rake ci:deliver "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow"
preprod: git push -f git@heroku.com:sp-helix-preprod.git $CIRCLE_SHA1:refs/heads/master
branch: preprod heroku run --app sp-helix-preprod invoke db_migrate
commands: rake ci:deliver
- invoke update_heroku_version preprod name: production
- "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow" commands: |
- git push -f git@heroku.com:sp-helix-preprod.git $CIRCLE_SHA1:refs/heads/master invoke update_heroku_version production
- heroku run --app sp-helix-preprod invoke db_migrate "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow"
- rake ci:deliver git push -f git@heroku.com:sp-helix-production.git $CIRCLE_SHA1:refs/heads/master
production: heroku run --app sp-helix-production invoke db_migrate
tag: /release-.*/ rake ci:deliver
commands: notify:
- invoke update_heroku_version production webhooks:
- "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow" - url: http://pulse.pivotallabs.com/projects/03ba990f-b8f5-4508-b4c1-19038b2cb791/status
- 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

View File

@@ -1,12 +1,19 @@
from math import ceil from math import ceil
from helix.constants.panel_type import PanelType 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): def add_parts_to_list(parts_list, parts_to_add, multiplier=1):
for part, quantity in parts_to_add.items(): for part, quantity in parts_to_add.items():
previous_value = parts_list.get(part) or 0 previous_value = parts_list.get(part) or 0
if quantity != 0: if quantity != 0 or part in PARTS_SHOWN_EVEN_WITH_0_ELEMENTS:
parts_list[part] = previous_value + quantity * multiplier parts_list[part] = previous_value + quantity * multiplier

View File

@@ -5,6 +5,8 @@ from helix.constants import ebom_parts
from helix.constants.ebom_parts import * 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.parts import wire_clip_large, cable_support, cable_support_lid, channel_nut, sunshade
from helix.constants.system_type import SystemType from helix.constants.system_type import SystemType
from helix.constants.inverter_brand import InverterBrand
from helix.forms.ebom_form import InverterBrandForm
class EbomCalculator(object): class EbomCalculator(object):
@@ -36,11 +38,25 @@ class EbomCalculator(object):
monitors = self.values.power_monitors() monitors = self.values.power_monitors()
module_type = self.values.module_type() module_type = self.values.module_type()
system_type = self.values.system_type() system_type = self.values.system_type()
is_delta=None
try:
is_delta=(self.values.inverter_brands()[0]['inverter_brand_id']==InverterBrand.DELTA.value)
except IndexError :
#Some tests are calculating bom without providing inverter brand so inverter_brands is empty
#for those tests, inverter brand is irrelevant
is_delta=False
inverter_count = 0 inverter_count = 0
total_ac_run_length = 0 total_ac_run_length = 0
panel_board_counts = [0, 0] panel_board_counts = [0, 0]
proper_monitor_controller = self.resolve_power_monitor_type() proper_monitor_controller = self.resolve_power_monitor_type()
try:
is_delta = (self.values.inverter_brands()[0]['inverter_brand_id']==InverterBrand.DELTA.value)
except IndexError:
is_delta = False
for power_station in power_stations: for power_station in power_stations:
power_station_count = power_station['power_station_quantity'] power_station_count = power_station['power_station_quantity']
total_ac_run_length += power_station['ac_run_length'] total_ac_run_length += power_station['ac_run_length']
@@ -75,6 +91,8 @@ class EbomCalculator(object):
for monitor in monitors: for monitor in monitors:
if monitor['power_source'][0] == 'Switch Gear/External': if monitor['power_source'][0] == 'Switch Gear/External':
add_parts_to_list(part_list, {proper_monitor_controller: 1}, 1) add_parts_to_list(part_list, {proper_monitor_controller: 1}, 1)
if (is_delta):
add_parts_to_list(part_list, {ethernet_plug: 2},1)
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)
@@ -84,8 +102,9 @@ class EbomCalculator(object):
add_parts_to_list(part_list, {rear_skirt: -1}, ceil(cable_supports*.38)) add_parts_to_list(part_list, {rear_skirt: -1}, ceil(cable_supports*.38))
dependent_part_list = {} dependent_part_list = {}
for part, quantity in part_list.items(): for part, quantity in part_list.items():
dependent_parts = ebom_parts.dependent_parts(module_type, system_type).get(part) dependent_parts = ebom_parts.dependent_parts(module_type, system_type,is_delta).get(part)
if dependent_parts: if dependent_parts:
add_parts_to_list(dependent_part_list, dependent_parts, quantity) add_parts_to_list(dependent_part_list, dependent_parts, quantity)

View File

@@ -18,32 +18,18 @@ class DualTiltParts(object):
} }
def __init__(self, module_type): def __init__(self, module_type):
if module_type == ModuleType.PSeries: self.corner_panel_parts = {
self.corner_panel_parts = { left_deflector_1_1: 1,
left_deflector_1_1: 1, right_deflector_1_1: 1,
right_deflector_1_1: 1, dual_tilt_chassis: 1.5,
dual_tilt_chassis: 1.5, module: 2
module: 2 }
} self.north_south_panel_parts = {
self.north_south_panel_parts = { left_deflector_1_1: 1,
left_deflector_1_1: 1, right_deflector_1_1: 1,
right_deflector_1_1: 1, dual_tilt_chassis: 1.5,
dual_tilt_chassis: 1.5, module: 2
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): def row_parts(self, module_type):
if module_type == ModuleType.Cell96: if module_type == ModuleType.Cell96:

View File

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

View File

@@ -5,8 +5,6 @@ dual_tilt_chassis = ('514056', 'BASE, CHASSIS, DUAL TILT, HELIX ROOF')
dual_tilt_platform = ('514057', 'PLATFORM, 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)') 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') front_skirt = ('515928', 'FRONT SKIRT, HELIX ROOF')
rear_skirt = ('515929', 'REAR SKIRT, HELIX ROOF') rear_skirt = ('515929', 'REAR SKIRT, HELIX ROOF')
spoiler = ('513836', 'SPOILER, SINGLE TILT, HELIX ROOF') spoiler = ('513836', 'SPOILER, SINGLE TILT, HELIX ROOF')
@@ -59,10 +57,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') mounting_back_plate = ('518331', 'MOUNTING BACK PLATE, INVERTER/PANEL BOARD, HELIX ROOF/TRACKER')
sma_12kw_inverter = ('514686', 'INVERTER, SMA, STP, 12000TL-US-10 (SPR-12000m-3 XXX), AFCI, CONNECTORIZED') 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 = ('514687', 'INVERTER, SMA, STP, 15000TL-US-10 (SPR-15000m-3 XXX), AFCI, CONNECTORIZED') 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 = ('512676', 'INVERTER, SMA, STP, 20000TL-US-10 (SPR-20000m-3 XXX), AFCI, CONNECTORIZED') 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 = ('514685', 'INVERTER, SMA, STP, 24000TL-US-10 (SPR-24000m-3 XXX), AFCI, CONNECTORIZED') sma_24kw_inverter = ('523924', 'INVERTER, SMA, STP, 15000TL-US-10 (SPR-15000m-3-H), AFCI, CONNECTORIZED, UTX XL REV D DC CONNECTORS')
delta_36kw_inverter = ('524952', 'INVERTER, DELTA, M36U_122(MC4), 10INPUT, 36KW, 3PH 480V AC,1000V DC') 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') delta_42kw_inverter = ('524969', 'INVERTER, DELTA, M42U_122(MC4), 12INPUT, 42KW, 3PH 480V AC,1000V DC')
@@ -159,8 +157,6 @@ all_parts = [
dual_tilt_chassis, dual_tilt_chassis,
dual_tilt_platform, dual_tilt_platform,
platform_bolt, platform_bolt,
left_deflector,
right_deflector,
front_skirt, front_skirt,
rear_skirt, rear_skirt,
spoiler, spoiler,

View File

@@ -18,32 +18,19 @@ class SingleTiltParts(object):
} }
def __init__(self, module_type): def __init__(self, module_type):
if module_type == ModuleType.PSeries: self.corner_panel_parts = {
self.corner_panel_parts = { module: 1,
module: 1, single_tilt_chassis: 1,
single_tilt_chassis: 1, left_deflector_1_1: 0.5,
left_deflector_1_1: 0.5, right_deflector_1_1: 0.5,
right_deflector_1_1: 0.5, }
} self.east_west_panel_parts = {
self.east_west_panel_parts = { module: 1,
module: 1, single_tilt_chassis: 1.5,
single_tilt_chassis: 1.5, left_deflector_1_1: 0.5,
left_deflector_1_1: 0.5, right_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, _): def row_parts(self, _):
return {} return {}

View File

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

View File

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

View File

@@ -122,7 +122,10 @@
this.isDualTilt = isDualTilt; this.isDualTilt = isDualTilt;
this.subarrayDisplay = subarrayDisplay; this.subarrayDisplay = subarrayDisplay;
this.buildings = buildings; this.buildings = buildings;
// Default options
this.scale = 10; this.scale = 10;
this.panels = [];
} }
_createClass(ArrayVisualization, [{ _createClass(ArrayVisualization, [{
@@ -137,7 +140,7 @@
this.stage.mouseMoveOutside = true; this.stage.mouseMoveOutside = true;
this.adjustScale(this.buildings); this.adjustScale(this.buildings);
this.drawArray(this.container, this.panelData, this.scale); this.drawArray(this.container, this.panelData);
this.container.x = 0; this.container.x = 0;
this.container.y = 0; this.container.y = 0;
this.stage.addChild(this.container); this.stage.addChild(this.container);
@@ -200,13 +203,13 @@
} }
}, { }, {
key: 'drawBuildings', key: 'drawBuildings',
value: function drawBuildings(buildings, scale) { value: function drawBuildings(buildings) {
if (!buildings) { if (!buildings || buildings.length === 0) {
console.log("No Buildings!"); console.log("No Buildings!");
return; return;
} }
if (!scale) { if (!this.scale) {
console.log("No Scale - don't know how big the buildings should be!"); console.log("No Scale - don't know how big the buildings should be!");
return; return;
} }
@@ -223,14 +226,14 @@
line.graphics.beginStroke(color); line.graphics.beginStroke(color);
line.graphics.moveTo(firstPoint.x * scale, firstPoint.y * scale); line.graphics.moveTo(firstPoint.x * this.scale, firstPoint.y * this.scale);
for (var j = 1; j < building.length; j++) { for (var j = 1; j < building.length; j++) {
nextPoint = building[j]; nextPoint = building[j];
line.graphics.lineTo(nextPoint.x * scale, nextPoint.y * scale); line.graphics.lineTo(nextPoint.x * this.scale, nextPoint.y * this.scale);
line.graphics.moveTo(nextPoint.x * scale, nextPoint.y * scale); line.graphics.moveTo(nextPoint.x * this.scale, nextPoint.y * this.scale);
} }
line.graphics.lineTo(firstPoint.x * scale, firstPoint.y * scale); line.graphics.lineTo(firstPoint.x * this.scale, firstPoint.y * this.scale);
line.graphics.endStroke(); line.graphics.endStroke();
} }
@@ -245,7 +248,7 @@
this.container.removeChild(this.panels[i]); this.container.removeChild(this.panels[i]);
} }
this.drawArray(this.container, this.panelData, this.scale); this.drawArray(this.container, this.panelData);
var selectedPanel = this.selectedPanel; var selectedPanel = this.selectedPanel;
this.selectedPanel = undefined; this.selectedPanel = undefined;
@@ -261,19 +264,15 @@
value: function drawArray(container, panels) { value: function drawArray(container, panels) {
var _this2 = this; var _this2 = this;
this.panels = [];
var treatCoordinatesAsCenterpoints = this.buildings && this.buildings.length > 0; var treatCoordinatesAsCenterpoints = this.buildings && this.buildings.length > 0;
var _loop = function _loop(i) { var _loop = function _loop(i) {
var panel = panels[i]; var box = new _panel.Panel(panels[i], _this2.isDualTilt, _this2.scale, treatCoordinatesAsCenterpoints);
var box = new _panel.Panel(panel, _this2.isDualTilt, _this2.scale, treatCoordinatesAsCenterpoints);
container.addChild(box); container.addChild(box);
_this2.panels.push(box); _this2.panels.push(box);
var self = _this2;
box.on("click", function () { box.on("click", function () {
self.selectPanel(i); _this2.selectPanel(i);
}); });
}; };

View File

@@ -8,6 +8,9 @@
<link href="//cdn.rawgit.com/noelboss/featherlight/1.7.6/release/featherlight.min.css" type="text/css" rel="stylesheet" /> <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="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/fontello.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'] %} {% if context['google_analytics_token'] %}
<script> <script>
(function (i, s, o, g, r, a, m) { (function (i, s, o, g, r, a, m) {

View File

@@ -8,7 +8,7 @@ from helix.constants.panel_type import PanelType
from helix.constants.system_type import SystemType from helix.constants.system_type import SystemType
from helix.models.coordinate import Coordinate from helix.models.coordinate import Coordinate
from helix.models.panel import PanelData, Panel from helix.models.panel import PanelData, Panel
from helix.models.sql.inverter_brands import InverterBrand
class UserValues(object): class UserValues(object):
def __init__(self, store, site): def __init__(self, store, site):
@@ -60,6 +60,9 @@ class UserValues(object):
def power_monitors(self): def power_monitors(self):
return [power_monitor.to_json() for power_monitor in self.site.power_monitors] 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): def csv(self):
csv_data = self.site.cad_file csv_data = self.site.cad_file
if not csv_data: if not csv_data:
@@ -156,4 +159,3 @@ class UserValues(object):
else: else:
return False # should not happen, but if it does rather not show the warning return False # should not happen, but if it does rather not show the warning

View File

@@ -1,5 +1,7 @@
import csv import csv
from helix.constants.file_validation_error import FileValidationError, FileValidationMessage 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): class CsvInputValidator(object):
@@ -35,7 +37,7 @@ class CsvInputValidator(object):
return FileValidationError(result, None) return FileValidationError(result, None)
return None return None
except: except Exception as inst:
return FileValidationError(FileValidationMessage.Generic, None) return FileValidationError(FileValidationMessage.Generic, None)
# Row Validators # Row Validators
@@ -78,28 +80,41 @@ class CsvInputValidator(object):
def validate_for_spacing(self, headers, rows): def validate_for_spacing(self, headers, rows):
try: try:
min_spacing = self.user_values.module_system_constants().panel_spacing
if len(headers) < 13:
return None
coordinates_calculator = CoordinatesCalculator(self.user_values)
scaling_factor = self.user_values.module_system_constants().tolerance + 1 scaling_factor = self.user_values.module_system_constants().tolerance + 1
min_spacing = (min_spacing[0]*scaling_factor, min_spacing[1]*scaling_factor) 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)
for row_index, row in enumerate(rows): 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): for row_index2, row2 in enumerate(rows):
if row_index2 <= row_index: if row_index2 <= row_index:
continue continue
x1_pos = float(row[11]) second_panel = Coordinate(float(row2[11]), float(row2[12]), float(row2[13]))
y1_pos = float(row[12]) second_panel_rotated = coordinates_calculator.rotate(second_panel)
second_panel_scaled = coordinates_calculator.scale(second_panel_rotated)
x2_pos = float(row2[11]) x_diff = round(abs(first_panel_scaled.x - second_panel_scaled.x),3)
y2_pos = float(row2[12]) y_diff = round(abs(first_panel_scaled.y - second_panel_scaled.y),3)
x_diff = abs(x1_pos-x2_pos) if (x_diff < spacing_coordinates_scaled.x) and (y_diff < spacing_coordinates_scaled.y):
y_diff = abs(y1_pos-y2_pos)
if (x_diff < min_spacing[0]) and (y_diff < min_spacing[1]):
return FileValidationMessage.PanelsTooClose return FileValidationMessage.PanelsTooClose
except: return None
except Exception as inst:
print("ERROR !!! ")
print(inst)
return FileValidationMessage.Generic return FileValidationMessage.Generic
# Helpers # Helpers

4829
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -5,4 +5,5 @@ cssselect==0.9.1
lxml==3.6.0 lxml==3.6.0
mockredispy==2.9.0.11 mockredispy==2.9.0.11
Flask-Testing==0.4.2 Flask-Testing==0.4.2
splinter[flask]
pillow==3.3.1 pillow==3.3.1

View File

@@ -13,7 +13,7 @@ requests==2.11.1
svgwrite==1.1.6 svgwrite==1.1.6
Wand==0.4.3 Wand==0.4.3
alembic==0.8.7 alembic==0.8.7
psycopg2==2.6.2 psycopg2==2.7.3
invoke==0.13.0 invoke==0.13.0
dxfgrabber==0.8.1 dxfgrabber==0.8.1
rollbar==0.13.11 rollbar==0.13.11

View File

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

View File

@@ -17,12 +17,12 @@ def test(ctx):
@task @task
def test_ci(ctx): def test_ci(ctx):
run('nosetests --with-xunit --xunit-file $CIRCLE_TEST_REPORTS/nosetests.xml') run('nosetests --nologcapture --with-xunit --xunit-file $CIRCLE_TEST_REPORTS/nosetests.xml')
test_js_ci(None) test_js_ci(ctx)
def test_js_ci(ctx): def test_js_ci(ctx):
run('karma start spec/javascripts/karma.config.js --single-run --browsers Chrome') run('./node_modules/.bin/karma start spec/javascripts/karma.config.js')
@task @task

View File

@@ -367,7 +367,6 @@ class CalculatorTest(unittest.TestCase):
) )
self.site.power_stations = [power_station_1, power_station_2] self.site.power_stations = [power_station_1, power_station_2]
assert_array_equal(self.subject.compute_bom(), expected) assert_array_equal(self.subject.compute_bom(), expected)
def test_documentation_bom(self): def test_documentation_bom(self):
@@ -426,7 +425,7 @@ class CalculatorTest(unittest.TestCase):
('512661', 2), ('512661', 2),
('512662', 4), ('512662', 4),
('512663', 2), ('512663', 2),
('512676', 0), ('523923', 0),
('512910', 1), ('512910', 1),
('513007', 50), ('513007', 50),
('513299', 0), ('513299', 0),
@@ -440,8 +439,6 @@ class CalculatorTest(unittest.TestCase):
('513832', 0), ('513832', 0),
('513833', 670), ('513833', 670),
('513836', 0), ('513836', 0),
('513841', 196),
('513842', 196),
('513843', 262), ('513843', 262),
('513844', 214), ('513844', 214),
('514056', 1000), ('514056', 1000),
@@ -455,9 +452,9 @@ class CalculatorTest(unittest.TestCase):
('514440', 0), ('514440', 0),
('514477', 2), ('514477', 2),
('514478', 0), ('514478', 0),
('514685', 0), ('523924', 0),
('514686', 1), ('523921', 1),
('514687', 0), ('523922', 0),
('514697', 1), ('514697', 1),
('514698', 1), ('514698', 1),
('514865', 50), ('514865', 50),
@@ -480,19 +477,19 @@ class CalculatorTest(unittest.TestCase):
('520306', 0), ('520306', 0),
('521031', 2), ('521031', 2),
('521363', 0), ('521363', 0),
('521794', 0),
('521795', 0),
('521797', 0), ('521797', 0),
('521798', 0), ('521798', 0),
('522020', 0), ('522020', 0),
('805615', 2), ('805615', 2),
('521794', 196),
('521795', 196),
('anchors', 262), ('anchors', 262),
('ballast', 6786), ('ballast', 6786),
('modules', 1726) ('modules', 1726)
] ]
assert_array_equal(sorted(self.subject.documentation_bom()), expected) assert_array_equal(sorted(self.subject.documentation_bom()), sorted(expected))
# Performance Tests # Performance Tests

View File

@@ -147,7 +147,7 @@ class EbomCalculatorTest(unittest.TestCase):
whip_tray: 19, whip_tray: 19,
ac_switch: 3, ac_switch: 3,
ac_splice_box: 2, ac_splice_box: 2,
ethernet_plug: 7.2, ethernet_plug: 12.600000000000001,
mounting_back_plate: 23, mounting_back_plate: 23,
sunshade_bolt: 4, sunshade_bolt: 4,
sunshade_washer: 4, sunshade_washer: 4,
@@ -206,6 +206,7 @@ class EbomCalculatorTest(unittest.TestCase):
delta_60kw_inverter: 1, delta_60kw_inverter: 1,
delta_splice_box: 2, delta_splice_box: 2,
delta_kit_inverter_mount: 3, delta_kit_inverter_mount: 3,
delta_kit_inverter_mount_dt: 0
} }
assert_dictionary_equal(self.subject.compute_ebom(), expected_output) assert_dictionary_equal(self.subject.compute_ebom(), expected_output)
@@ -223,7 +224,6 @@ class EbomCalculatorTest(unittest.TestCase):
'attachment_point': ('Switch Gear', None) 'attachment_point': ('Switch Gear', None)
}, },
] ]
self.user_values.system_type.return_value = SystemType.dualTilt self.user_values.system_type.return_value = SystemType.dualTilt
self.user_values.module_type.return_value = ModuleType.Cell96 self.user_values.module_type.return_value = ModuleType.Cell96
expected_output = { expected_output = {
@@ -237,9 +237,9 @@ class EbomCalculatorTest(unittest.TestCase):
harness_4_string_mf: 2, harness_4_string_mf: 2,
harness_4_string_fm: 2, harness_4_string_fm: 2,
delta_42kw_inverter: 1, delta_42kw_inverter: 1,
delta_kit_inverter_mount: 0,
delta_kit_inverter_mount_dt: 1, delta_kit_inverter_mount_dt: 1,
} }
assert_dictionary_equal(self.subject.compute_ebom(), expected_output) assert_dictionary_equal(self.subject.compute_ebom(), expected_output)
def test_computes_ebom_with_aux_plugs(self): def test_computes_ebom_with_aux_plugs(self):
@@ -616,6 +616,56 @@ class EbomCalculatorTest(unittest.TestCase):
assert_dictionary_equal(self.subject.compute_ebom(), expected_output) 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: 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: 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): def test_computes_ebom_with_aux_plugs_on_switchgear_on_pseries_single_tilt(self):
self.user_values.power_stations.return_value = [ self.user_values.power_stations.return_value = [
{ {
@@ -1051,3 +1101,58 @@ class EbomCalculatorTest(unittest.TestCase):
self.subject = EbomCalculator(self.user_values, 171, 98, 104) self.subject = EbomCalculator(self.user_values, 171, 98, 104)
assert_dictionary_equal(self.subject.compute_ebom(), expected_output_240_pseries) 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: 0,
monitor_controller_480_v: 1,
ethernet_plug: 2,
}
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: 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 = { expected_output = {
wire_clip: 80, wire_clip: 80,
link_tray: 9, link_tray: 9,
left_deflector: 10, left_deflector_1_1: 10,
right_deflector: 10, right_deflector_1_1: 10,
anchor_plate: 12, anchor_plate: 12,
cross_tray_1_1: 3, cross_tray_1_1: 3,
dual_tilt_chassis: 26, dual_tilt_chassis: 26,
@@ -98,8 +98,8 @@ class MechanicalBomCalculatorWhenDualTilt128CellTest(unittest.TestCase):
expected_output = { expected_output = {
wire_clip: 80, wire_clip: 80,
link_tray: 9, link_tray: 9,
left_deflector: 10, left_deflector_1_1: 10,
right_deflector: 10, right_deflector_1_1: 10,
anchor_plate: 12, anchor_plate: 12,
cross_tray_1_1: 3, cross_tray_1_1: 3,
dual_tilt_chassis: 26, dual_tilt_chassis: 26,

View File

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

View File

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

View File

@@ -93,8 +93,8 @@ class MechanicalBomCalculatorWhenSingleTilt96CellTest(unittest.TestCase):
following_tray: 25, following_tray: 25,
link_tray: 28, link_tray: 28,
spoiler: 44, spoiler: 44,
left_deflector: 11, left_deflector_1_1: 11,
right_deflector: 11, right_deflector_1_1: 11,
anchor_plate: 15, anchor_plate: 15,
cross_tray: 5, cross_tray: 5,
rubber_foot: 4.4, rubber_foot: 4.4,

View File

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

View File

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

View File

@@ -10,13 +10,10 @@
512661 BACK LEGS, INVERTER RACK, HELIX ROOF 18 512661 BACK LEGS, INVERTER RACK, HELIX ROOF 18
512662 LINK TO ARRAY, INVERTER RACK, HELIX ROOF 36 512662 LINK TO ARRAY, INVERTER RACK, HELIX ROOF 36
512663 RAIL, INVERTER RACK, HELIX ROOF 18 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 513007 BOLT, HH, 3/8-16 X 3/4, 316 SS 50
513299 COMBINER BOX, AC, 4 INPUT, NO AUX, W/ CONNECTOR 3 513299 COMBINER BOX, AC, 4 INPUT, NO AUX, W/ CONNECTOR 3
513303 COMBINER BOX, AC, 2 INPUT, NO AUX, W/ CONNECTOR 1 513303 COMBINER BOX, AC, 2 INPUT, NO AUX, W/ CONNECTOR 1
513833 TRAY, LINK, HELIX ROOF 670 513833 TRAY, LINK, HELIX ROOF 670
513841 DEFLECTOR, LH, HELIX ROOF 196
513842 DEFLECTOR, RH, HELIX ROOF 196
513843 PLATE, ANCHOR, HELIX ROOF 262 513843 PLATE, ANCHOR, HELIX ROOF 262
513844 TRAY, OPTIONAL BALLAST, HELIX ROOF 214 513844 TRAY, OPTIONAL BALLAST, HELIX ROOF 214
514056 BASE, CHASSIS, DUAL TILT, HELIX ROOF 1000 514056 BASE, CHASSIS, DUAL TILT, HELIX ROOF 1000
@@ -30,9 +27,6 @@
514440 HARNESS, DC COMBINATION, W/ FUSE, 4 STRING, MALES TO FEMALE, HELIX 15 514440 HARNESS, DC COMBINATION, W/ FUSE, 4 STRING, MALES TO FEMALE, HELIX 15
514477 HARNESS, AC, INNER, 72", HELIX ROOFTOP 8 514477 HARNESS, AC, INNER, 72", HELIX ROOFTOP 8
514478 HARNESS, AC, OUTER, 108", HELIX ROOFTOP 6 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 514697 COMM CABLE, INVERTER DAISY CHAIN, 118", HELIX ROOF 10
514865 BOLT, HH, 3/8-16 X 1/2, 18-8 SS 300 514865 BOLT, HH, 3/8-16 X 1/2, 18-8 SS 300
515059 ASSY, WHIP TRAY W/FUSE CLIPS, INVERTER, HELIX 14 515059 ASSY, WHIP TRAY W/FUSE CLIPS, INVERTER, HELIX 14
@@ -42,6 +36,12 @@
518058 CONNECTOR, ETHERNET, PLUG, RJ-45, WEATHERPROOF, SHIELDED 8 518058 CONNECTOR, ETHERNET, PLUG, RJ-45, WEATHERPROOF, SHIELDED 8
518331 MOUNTING BACK PLATE, INVERTER/PANEL BOARD, HELIX ROOF/TRACKER 18 518331 MOUNTING BACK PLATE, INVERTER/PANEL BOARD, HELIX ROOF/TRACKER 18
518477 WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS 275 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 6786 Contractor Supplied Ballast Blocks 6786
TBD Anchors 262 TBD Anchors 262
TBD Modules 1726 TBD Modules 1726
Can't render this file because it contains an unexpected character in line 28 and column 30.

View File

@@ -27,8 +27,6 @@ Part # Description Total
513832 TRAY, FOLLOWING, HELIX ROOF 210 513832 TRAY, FOLLOWING, HELIX ROOF 210
513833 TRAY, LINK, HELIX ROOF 1271 513833 TRAY, LINK, HELIX ROOF 1271
513836 SPOILER, SINGLE TILT, HELIX ROOF 1632 513836 SPOILER, SINGLE TILT, HELIX ROOF 1632
513841 DEFLECTOR, LH, HELIX ROOF 171
513842 DEFLECTOR, RH, HELIX ROOF 171
513843 PLATE, ANCHOR, HELIX ROOF 414 513843 PLATE, ANCHOR, HELIX ROOF 414
513844 TRAY, OPTIONAL BALLAST, HELIX ROOF 274 513844 TRAY, OPTIONAL BALLAST, HELIX ROOF 274
514265 FOOT, RECYCLED RUBBER, HELIX ROOF 230 514265 FOOT, RECYCLED RUBBER, HELIX ROOF 230
@@ -40,9 +38,6 @@ Part # Description Total
514440 HARNESS, DC COMBINATION, W/ FUSE, 4 STRING, MALES TO FEMALE, HELIX 11 514440 HARNESS, DC COMBINATION, W/ FUSE, 4 STRING, MALES TO FEMALE, HELIX 11
514477 HARNESS, AC, INNER, 72", HELIX ROOFTOP 12 514477 HARNESS, AC, INNER, 72", HELIX ROOFTOP 12
514478 HARNESS, AC, OUTER, 108", HELIX ROOFTOP 2 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 514697 COMM CABLE, INVERTER DAISY CHAIN, 118", HELIX ROOF 8
514698 DC SWITCH BOX, HELIX 5 514698 DC SWITCH BOX, HELIX 5
514865 BOLT, HH, 3/8-16 X 1/2, 18-8 SS 350 514865 BOLT, HH, 3/8-16 X 1/2, 18-8 SS 350
@@ -52,10 +47,15 @@ Part # Description Total
516043 AC SWITCH, CONNECTORIZED, HELIX ROOF 2 516043 AC SWITCH, CONNECTORIZED, HELIX ROOF 2
516045 AC SPLICE BOX, CONNECTORIZED, HELIX ROOF 1 516045 AC SPLICE BOX, CONNECTORIZED, HELIX ROOF 1
517871 TRAY, LEADING, HELIX ROOF, RIVETED VERSION 210 517871 TRAY, LEADING, HELIX ROOF, RIVETED VERSION 210
518058 CONNECTOR, ETHERNET, PLUG, RJ-45, WEATHERPROOF, SHIELDED 11 518058 CONNECTOR, ETHERNET, PLUG, RJ-45, WEATHERPROOF, SHIELDED 15
518331 MOUNTING BACK PLATE, INVERTER/PANEL BOARD, HELIX ROOF/TRACKER 22 518331 MOUNTING BACK PLATE, INVERTER/PANEL BOARD, HELIX ROOF/TRACKER 22
518477 WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS 425 518477 WASHER, FLAT, 3/8, 1.00 OD, 18-8 SS 425
521031 WASHER, FLAT, M10 X 20MM OD, SS 10 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 805615 SCREW, HEXAGONAL HEAD, M10X20, SS A2 10
Contractor Supplied Ballast Blocks 10150 Contractor Supplied Ballast Blocks 10150
TBD Anchors 414 TBD Anchors 414
Can't render this file because it contains an unexpected character in line 10 and column 30.

View File

@@ -0,0 +1,3 @@
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

View File

@@ -0,0 +1,4 @@
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

289
test/fixtures/invalid_too_close.txt vendored Normal file
View File

@@ -0,0 +1,289 @@
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

View File

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

View File

@@ -67,10 +67,12 @@ class PanelPresenterTest(unittest.TestCase):
def test_get_buildings_data(self): def test_get_buildings_data(self):
self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96)
buildings = [ [ Coordinate(-60,-60), Coordinate(60,-60), Coordinate(60,60), Coordinate(-60,60) ] ] # big square 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}, 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},
{'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) actual_buildings = self.subject.get_buildings(buildings)
assert_array_equal(actual_buildings,expected_buildings) assert_array_equal(actual_buildings,expected_buildings)

View File

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

View File

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

View File

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

View File

@@ -1,3 +1,4 @@
import time
from flask.ext.testing import LiveServerTestCase from flask.ext.testing import LiveServerTestCase
import mockredis import mockredis
from splinter import Browser from splinter import Browser
@@ -84,6 +85,7 @@ class PowerStationConfigurationDynamicFormTestCase(LiveServerTestCase):
eq_(self.browser.find_by_name('inverter-model').first.value, str(InverterType.SMA.default_value())) eq_(self.browser.find_by_name('inverter-model').first.value, str(InverterType.SMA.default_value()))
select_inverter_brand(self.browser, brand=InverterBrand.DELTA.value) select_inverter_brand(self.browser, brand=InverterBrand.DELTA.value)
time.sleep(1)
show_standalone_inverter_form(self.browser) show_standalone_inverter_form(self.browser)
eq_(len(self.browser.find_by_css('#inverter-model option')), 3) eq_(len(self.browser.find_by_css('#inverter-model option')), 3)

View File

@@ -5,6 +5,7 @@ from nose.tools import eq_
from helix.validators.csv_input_validator import CsvInputValidator from helix.validators.csv_input_validator import CsvInputValidator
from helix.constants.system_type import SystemType from helix.constants.system_type import SystemType
from helix.constants.module_type import ModuleType
from helix.constants.file_validation_error import FileValidationError, FileValidationMessage from helix.constants.file_validation_error import FileValidationError, FileValidationMessage
@@ -94,3 +95,12 @@ class CsvInputValidatorTest(unittest.TestCase):
self.user_values.system_type.return_value = SystemType.dualTilt self.user_values.system_type.return_value = SystemType.dualTilt
cad_input = "A\tB\tC\tD\tE\r\nhandle\tblock\tA\t3\t1\r\n" cad_input = "A\tB\tC\tD\tE\r\nhandle\tblock\tA\t3\t1\r\n"
self.should_have_error(self.subject.validate(cad_input), FileValidationMessage.PanelTypeTooFewCornersDualTilt, None) self.should_have_error(self.subject.validate(cad_input), FileValidationMessage.PanelTypeTooFewCornersDualTilt, None)
def test_reports_too_close_when_finds_panel_too_close_to_another_panel(self):
self.user_values.system_type.return_value = SystemType.dualTilt
self.user_values.module_type.return_value = ModuleType.Cell96
self.user_values.module_system_constants().tolerance = 0.1
self.user_values.module_system_constants().panel_spacing = (88.24, 62.0)
with open('test/fixtures/invalid_too_close.txt', 'r', newline='') as csv_file:
cad_input = csv_file.read()
self.should_have_error(self.subject.validate(cad_input), FileValidationMessage.PanelsTooClose , None)

16
watch.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
# Watches for changes in the files and passes to docker
# ignores the folders: node_modules, .git
cwd=$(pwd)
fswatch -0 -e node_modules -e .git -e env . | while read -d "" absPath
do
shortPath=""
shortPath=${absPath/$cwd/$shortPath}
echo "${shortPath}"
docker cp $absPath helix:project${shortPath}
done