first commit
This commit is contained in:
92
helix/validators/csv_input_validator.py
Normal file
92
helix/validators/csv_input_validator.py
Normal file
@@ -0,0 +1,92 @@
|
||||
import csv
|
||||
from helix.constants.file_validation_error import FileValidationError, FileValidationMessage
|
||||
|
||||
|
||||
class CsvInputValidator(object):
|
||||
|
||||
def __init__(self, user_values):
|
||||
self.user_values = user_values
|
||||
|
||||
def validate(self, csv_input):
|
||||
try:
|
||||
headers, rows = self.parse_cad_input(csv_input)
|
||||
|
||||
if len(headers) < 5:
|
||||
return FileValidationError(FileValidationMessage.InvalidHeaders, 0)
|
||||
if len(rows) == 0:
|
||||
return FileValidationError(FileValidationMessage.InvalidRowCount, 0)
|
||||
|
||||
for row_index, row in enumerate(rows):
|
||||
chain = [
|
||||
CsvInputValidator.validate_for_csv,
|
||||
CsvInputValidator.validate_for_wind_zones,
|
||||
CsvInputValidator.validate_for_panel_type,
|
||||
]
|
||||
result = self.run_validation_chain(headers, row, chain)
|
||||
if result:
|
||||
return FileValidationError(result, row_index + 1)
|
||||
|
||||
file_validation_chain = [
|
||||
CsvInputValidator.validate_file_for_panel_types,
|
||||
]
|
||||
result = self.run_validation_chain(headers, rows, file_validation_chain)
|
||||
if result:
|
||||
return FileValidationError(result, None)
|
||||
|
||||
return None
|
||||
except:
|
||||
return FileValidationError(FileValidationMessage.Generic, None)
|
||||
|
||||
# Row Validators
|
||||
|
||||
def validate_for_csv(self, headers, row):
|
||||
if len(row) != len(headers):
|
||||
return FileValidationMessage.Generic
|
||||
return None
|
||||
|
||||
def validate_for_wind_zones(self, headers, row):
|
||||
valid_wind_zones = self.user_values.system_type().system_constants().wind_zones
|
||||
if row[2] not in valid_wind_zones:
|
||||
return FileValidationMessage.invalid_wind_zones(self.user_values.system_type())
|
||||
return None
|
||||
|
||||
def validate_for_panel_type(self, headers, row):
|
||||
valid_panel_types = range(1, 5)
|
||||
if int(row[3]) not in valid_panel_types:
|
||||
return FileValidationMessage.PanelTypeOutOfBounds
|
||||
return None
|
||||
|
||||
# File Validators
|
||||
|
||||
def validate_file_for_panel_types(self, headers, rows):
|
||||
panel_type_counts_per_subarray = {}
|
||||
for row in rows:
|
||||
subarray = int(row[4])
|
||||
panel_type_counts = panel_type_counts_per_subarray.get(subarray) or {}
|
||||
panel_type = int(row[3])
|
||||
count = panel_type_counts.get(panel_type) or 0
|
||||
panel_type_counts[panel_type] = count + 1
|
||||
panel_type_counts_per_subarray[subarray] = panel_type_counts
|
||||
|
||||
minimum_module_count = self.user_values.system_type().system_constants().minimum_corner_module_count
|
||||
|
||||
for panel_type_counts in panel_type_counts_per_subarray.values():
|
||||
if (panel_type_counts.get(1) or 0) < minimum_module_count:
|
||||
return FileValidationMessage.panel_type_too_few_corners(self.user_values.system_type())
|
||||
return None
|
||||
|
||||
# Helpers
|
||||
|
||||
def run_validation_chain(self, headers, data, chain):
|
||||
result = None
|
||||
chain = list(chain)
|
||||
while not result and len(chain) > 0:
|
||||
method = chain.pop()
|
||||
result = method(self, headers, data)
|
||||
return result
|
||||
|
||||
def parse_cad_input(self, cad_input):
|
||||
reader = csv.reader(cad_input.splitlines(), dialect='excel-tab')
|
||||
headers = next(reader)
|
||||
rows = [row for row in reader]
|
||||
return headers, rows
|
||||
Reference in New Issue
Block a user