private List <RxCellLookup> ImportRatesFromProducts(GridDescriptor gridDescriptor, List <int> productIds, RasterGridPrescription prescription) { var rates = new List <RxCellLookup>(); bool binaryDataMatchesDefinition = true; foreach (var productRates in gridDescriptor.ProductRates) { var lookup = new RxCellLookup { RxRates = new List <RxRate>() }; for (int productIndex = 0; productIndex < productRates.Count; productIndex++) { int adaptProductId = 0; if (productIds.Count > productIndex) { adaptProductId = productIds[productIndex]; } else if (productIds.Count > 0) { binaryDataMatchesDefinition = false; } lookup.RxRates.Add(PrescriptionMapper.ImportRate(adaptProductId, productRates[productIndex], prescription)); } rates.Add(lookup); } if (!binaryDataMatchesDefinition) { TaskDataMapper.AddError($"Binary Grid Data for Type-2 Grid {TaskDataMapper.InstanceIDMap.GetISOID(prescription.Id.ReferenceId)} does not match its definition. Product data will be omitted."); } return(rates); }
protected void ExportContextItems(List <ContextItem> contextItems, string isoIDRef, string groupName, string prefix = "") { if (contextItems.Any()) { List <string> errors = UniqueIDMapper.ExportContextItems(contextItems, isoIDRef, groupName, prefix); foreach (string error in errors) { TaskDataMapper.AddError(error); } } }
private List <ProductComponent> ImportProductComponents(ISOProduct isoProduct) { if (!isoProduct.ProductRelations.Any()) { return(null); } var productComponents = new List <ProductComponent>(); foreach (ISOProductRelation prn in isoProduct.ProductRelations) { //Find the product referenced by the relation ISOProduct isoComponent = ISOTaskData.ChildElements.OfType <ISOProduct>().FirstOrDefault(p => p.ProductId == prn.ProductIdRef); if (isoComponent != null) //Skip PRN if PRN@A doesn't resolve to a product { //Find or create the product to match the component Product adaptProduct = DataModel.Catalog.Products.FirstOrDefault(i => i.Id.FindIsoId() == isoComponent.ProductId); if (adaptProduct == null) { adaptProduct = ImportProduct(isoComponent); DataModel.Catalog.Products.Add(adaptProduct); } //Create a component for this ingredient ProductComponent component = new ProductComponent() { IngredientId = adaptProduct.Id.ReferenceId, IsProduct = true, IsCarrier = adaptProduct.Category == CategoryEnum.Carrier }; var quantityDDI = GetQuantityDDI(isoComponent.QuantityDDI, adaptProduct.Form); if (!string.IsNullOrEmpty(quantityDDI)) { component.Quantity = prn.QuantityValue.AsNumericRepresentationValue(quantityDDI, RepresentationMapper); } productComponents.Add(component); } else { TaskDataMapper.AddError($"Product relation with quantity {prn.QuantityValue} ommitted for product {isoProduct.ProductId} due to no ProductIdRef"); } } return(productComponents); }
public IEnumerable <DeviceElement> ImportDeviceElements(ISODevice isoDevice) { EnumeratedValue deviceClassification = DecodeMachineInfo(isoDevice.ClientNAME); ISODeviceElement rootDeviceElement = isoDevice.DeviceElements.SingleOrDefault(det => det.DeviceElementType == ISODeviceElementType.Device); if (rootDeviceElement == null) { //Short circuit on invalid TaskData TaskDataMapper.AddError("Missing root DeviceElement. Device will not be imported.", isoDevice.DeviceId.ToString(), "DeviceElementMapper"); return(null); } DeviceElementHierarchy rootDeviceElementHierarchy = TaskDataMapper.DeviceElementHierarchies.Items[isoDevice.DeviceId]; //Import device elements List <DeviceElement> adaptDeviceElements = new List <DeviceElement>(); //Import down the hierarchy to ensure integrity of parent references for (int i = 0; i <= rootDeviceElementHierarchy.GetMaxDepth(); i++) { IEnumerable <ISODeviceElement> isoDeviceElements = rootDeviceElementHierarchy.GetElementsAtDepth(i).Select(h => h.DeviceElement); foreach (ISODeviceElement isoDeviceElement in isoDeviceElements) { if (isoDeviceElement.DeviceElementType != ISODeviceElementType.Connector) { DeviceElement adaptDeviceElement = ImportDeviceElement(isoDeviceElement, deviceClassification, rootDeviceElementHierarchy); if (isoDeviceElement.DeviceElementType == ISODeviceElementType.Device) { //Setting the Device serial number on the root Device Element only adaptDeviceElement.SerialNumber = isoDevice.DeviceSerialNumber; } adaptDeviceElements.Add(adaptDeviceElement); DataModel.Catalog.DeviceElements.Add(adaptDeviceElement); } else { //Connectors are not represented as DeviceElements in ADAPT AddConnector(rootDeviceElementHierarchy, isoDeviceElement); } } } return(adaptDeviceElements); }
/// <summary> /// If an implementer wants to export to a custom DDI or otherwise one that doesn't map, /// the appropriate DDI may be set in the Prescription prior to exporting. /// A ISO11783_DDI representation is as such the first mapping attempted. /// </summary> /// <param name="representation"></param> /// <param name="adaptUnit"></param> /// <returns></returns> private int DetermineVariableDDI(NumericRepresentation representation, UnitOfMeasure adaptUnit) { if (representation != null) { if (representation.CodeSource == RepresentationCodeSourceEnum.ISO11783_DDI) { return(Int32.Parse(representation.Code)); } int?mappedDDI = RepresentationMapper.Map(representation); if (mappedDDI.HasValue) { return(mappedDDI.Value); } } if (adaptUnit != null && UnitFactory.DimensionToDdi.ContainsKey(adaptUnit.Dimension)) { return(UnitFactory.DimensionToDdi[adaptUnit.Dimension]); } TaskDataMapper.AddError($"Unable to determine DDI for Prescription export {representation.Code}.", $"Representation ID : {representation.Id.ReferenceId}", "PrescriptionMapper.DetermineVariableDDI()"); return(0); //Return an invalid DDI }
private ISOTreatmentZone ExportTreatmentZonesForType2(ISOTask task, RasterGridPrescription prescription) { if (prescription.ProductIds == null) { TaskDataMapper.AddError($"No Products are present for Grid Type 2 Prescription export: {prescription.Description}", prescription.Id.ReferenceId.ToString()); return(null); } var lossOfSignalTreatmentZone = new ISOTreatmentZone { TreatmentZoneDesignator = "Loss of GPS", ProcessDataVariables = new List <ISOProcessDataVariable>() }; var outOfFieldTreatmentZone = new ISOTreatmentZone { TreatmentZoneDesignator = "Out of Field", ProcessDataVariables = new List <ISOProcessDataVariable>() }; var defaultTreatmentZone = new ISOTreatmentZone { TreatmentZoneDesignator = "Default", ProcessDataVariables = new List <ISOProcessDataVariable>() }; foreach (var productId in prescription.ProductIds) { var isoUnit = DetermineIsoUnit(prescription.RxProductLookups.First(p => p.ProductId == productId).UnitOfMeasure); string isoProductId = TaskDataMapper.InstanceIDMap.GetISOID(productId) ?? string.Empty; ISOProcessDataVariable lossPDV = ExportProcessDataVariable(prescription.LossOfGpsRate, isoProductId, isoUnit); if (lossPDV != null) { lossOfSignalTreatmentZone.ProcessDataVariables.Add(lossPDV); } ISOProcessDataVariable oofPDV = ExportProcessDataVariable(prescription.OutOfFieldRate, isoProductId, isoUnit); if (oofPDV != null) { outOfFieldTreatmentZone.ProcessDataVariables.Add(oofPDV); } ISOProcessDataVariable defaultPDV = ExportProcessDataVariable(prescription.LossOfGpsRate, isoProductId, isoUnit); //ADAPT doesn't have a separate Default Rate. Using Loss of GPS Rate as a logical equivalent for a default rate. if (defaultPDV == null) { //Add 0 as the default rate so that we have at least one PDV to reference var defaultRate = new NumericRepresentationValue(null, new NumericValue(prescription.RxProductLookups.First().UnitOfMeasure, 0)); defaultPDV = ExportProcessDataVariable(defaultRate, isoProductId, isoUnit); } defaultTreatmentZone.ProcessDataVariables.Add(defaultPDV); } if (lossOfSignalTreatmentZone.ProcessDataVariables.Count > 0) { lossOfSignalTreatmentZone.TreatmentZoneCode = 253; task.TreatmentZones.Add(lossOfSignalTreatmentZone); task.PositionLostTreatmentZoneCode = lossOfSignalTreatmentZone.TreatmentZoneCode; } if (outOfFieldTreatmentZone.ProcessDataVariables.Count > 0) { outOfFieldTreatmentZone.TreatmentZoneCode = 254; task.TreatmentZones.Add(outOfFieldTreatmentZone); task.OutOfFieldTreatmentZoneCode = outOfFieldTreatmentZone.TreatmentZoneCode; } defaultTreatmentZone.TreatmentZoneCode = 1; task.TreatmentZones.Add(defaultTreatmentZone); task.DefaultTreatmentZoneCode = defaultTreatmentZone.TreatmentZoneCode; return(defaultTreatmentZone); }
public Product ImportProduct(ISOProduct isoProduct) { //First check if we've already created a matching seed product from the crop type Product product = DataModel.Catalog.Products.FirstOrDefault(p => p.ProductType == ProductTypeEnum.Variety && p.Description == isoProduct.ProductDesignator); //If not, create a new product if (product == null) { //Type switch (isoProduct.ProductType) { case ISOProductType.Mixture: case ISOProductType.TemporaryMixture: product = new MixProduct(); product.ProductType = ProductTypeEnum.Mix; break; default: product = new GenericProduct(); product.ProductType = ProductTypeEnum.Generic; break; } } //ID if (!ImportIDs(product.Id, isoProduct.ProductId)) { //Replace the CVT id with the PDT id in the mapping TaskDataMapper.InstanceIDMap.ReplaceISOID(product.Id.ReferenceId, isoProduct.ProductId); } //Description product.Description = isoProduct.ProductDesignator; //Mixes if (isoProduct.ProductRelations.Any()) { if (product.ProductComponents == null) { product.ProductComponents = new List <ProductComponent>(); } foreach (ISOProductRelation prn in isoProduct.ProductRelations) { //Find the product referenced by the relation ISOProduct isoComponent = ISOTaskData.ChildElements.OfType <ISOProduct>().FirstOrDefault(p => p.ProductId == prn.ProductIdRef); if (isoComponent != null) //Skip PRN if PRN@A doesn't resolve to a product { //Find or create the active ingredient to match the component Ingredient ingredient = DataModel.Catalog.Ingredients.FirstOrDefault(i => i.Id.FindIsoId() == isoComponent.ProductId); if (ingredient == null) { ingredient = new ActiveIngredient(); ingredient.Description = isoComponent.ProductDesignator; DataModel.Catalog.Ingredients.Add(ingredient); } //Create a component for this ingredient ProductComponent component = new ProductComponent() { IngredientId = ingredient.Id.ReferenceId }; if (!string.IsNullOrEmpty(isoComponent.QuantityDDI)) { component.Quantity = prn.QuantityValue.AsNumericRepresentationValue(isoComponent.QuantityDDI, RepresentationMapper); } product.ProductComponents.Add(component); } else { TaskDataMapper.AddError($"Product relation with quantity {prn.QuantityValue} ommitted for product {isoProduct.ProductId} due to no ProductIdRef"); } } //Total Mix quantity if (isoProduct.MixtureRecipeQuantity.HasValue) { MixProduct mixProduct = product as MixProduct; mixProduct.TotalQuantity = isoProduct.MixtureRecipeQuantity.Value.AsNumericRepresentationValue(isoProduct.QuantityDDI, RepresentationMapper); } } //Density if (isoProduct.DensityMassPerCount.HasValue) { product.Density = isoProduct.DensityMassPerCount.Value.AsNumericRepresentationValue("007A", RepresentationMapper); } else if (isoProduct.DensityMassPerVolume.HasValue) { product.Density = isoProduct.DensityMassPerVolume.Value.AsNumericRepresentationValue("0079", RepresentationMapper); } else if (isoProduct.DensityVolumePerCount.HasValue) { product.Density = isoProduct.DensityVolumePerCount.Value.AsNumericRepresentationValue("007B", RepresentationMapper); } return(product); }
private ISOTreatmentZone ExportTreatmentZonesForType2(ISOTask task, RasterGridPrescription prescription) { if (prescription.ProductIds == null) { TaskDataMapper.AddError($"No Products are present for Grid Type 2 Prescription export: {prescription.Description}", prescription.Id.ReferenceId.ToString()); return(null); } var lossOfSignalTreatmentZone = new ISOTreatmentZone { TreatmentZoneDesignator = "Loss of GPS", ProcessDataVariables = new List <ISOProcessDataVariable>() }; var outOfFieldTreatmentZone = new ISOTreatmentZone { TreatmentZoneDesignator = "Out of Field", ProcessDataVariables = new List <ISOProcessDataVariable>() }; var defaultTreatmentZone = new ISOTreatmentZone { TreatmentZoneDesignator = "Default", ProcessDataVariables = new List <ISOProcessDataVariable>() }; foreach (var productId in prescription.ProductIds) { var isoUnit = DetermineIsoUnit(prescription.RxProductLookups.First(p => p.ProductId == productId).UnitOfMeasure); string isoProductId = TaskDataMapper.InstanceIDMap.GetISOID(productId) ?? string.Empty; RxProductLookup productLookup = prescription.RxProductLookups.FirstOrDefault(p => p.ProductId == productId); ISOProcessDataVariable lossPDV = ExportProcessDataVariable(productLookup?.LossOfGpsRate ?? prescription.LossOfGpsRate, isoProductId, isoUnit); if (lossPDV != null) { lossOfSignalTreatmentZone.ProcessDataVariables.Add(lossPDV); } ISOProcessDataVariable oofPDV = ExportProcessDataVariable(productLookup?.OutOfFieldRate ?? prescription.OutOfFieldRate, isoProductId, isoUnit); if (oofPDV != null) { outOfFieldTreatmentZone.ProcessDataVariables.Add(oofPDV); } NumericRepresentation defaultRepresentation = productLookup?.LossOfGpsRate.Representation; //We can reuse the loss of gps representation here if it exists if (defaultRepresentation == null) { //Determine the representation based on the unit of the product to be applied var unitDimension = isoUnit.ToAdaptUnit().Dimension; if (UnitFactory.DimensionToDdi.ContainsKey(unitDimension)) { int ddi = UnitFactory.DimensionToDdi[unitDimension]; RepresentationMapper representationMapper = new RepresentationMapper(); var representation = representationMapper.Map(ddi) as NumericRepresentation; if (representation == null) { representation = new NumericRepresentation { Code = ddi.ToString(), CodeSource = RepresentationCodeSourceEnum.ISO11783_DDI }; } } else { TaskDataMapper.AddError($"Unable to identify a default representation: {prescription.Description}", prescription.Id.ReferenceId.ToString()); return(null); } } //Add 0 as the default rate in the PDV; actual values are in the binary var defaultRate = new NumericRepresentationValue(defaultRepresentation, new NumericValue(prescription.RxProductLookups.First(p => p.ProductId == productId).UnitOfMeasure, 0d)); ISOProcessDataVariable defaultPDV = ExportProcessDataVariable(defaultRate, isoProductId, isoUnit); defaultTreatmentZone.ProcessDataVariables.Add(defaultPDV); } if (lossOfSignalTreatmentZone.ProcessDataVariables.Count > 0) { lossOfSignalTreatmentZone.TreatmentZoneCode = 253; task.TreatmentZones.Add(lossOfSignalTreatmentZone); task.PositionLostTreatmentZoneCode = lossOfSignalTreatmentZone.TreatmentZoneCode; } if (outOfFieldTreatmentZone.ProcessDataVariables.Count > 0) { outOfFieldTreatmentZone.TreatmentZoneCode = 254; task.TreatmentZones.Add(outOfFieldTreatmentZone); task.OutOfFieldTreatmentZoneCode = outOfFieldTreatmentZone.TreatmentZoneCode; } defaultTreatmentZone.TreatmentZoneCode = 1; task.TreatmentZones.Add(defaultTreatmentZone); task.DefaultTreatmentZoneCode = defaultTreatmentZone.TreatmentZoneCode; return(defaultTreatmentZone); }
private IEnumerable <OperationData> ImportTimeLog(ISOTask loggedTask, ISOTimeLog isoTimeLog, int?prescriptionID) { WorkingDataMapper workingDataMapper = new WorkingDataMapper(new EnumeratedMeterFactory(), TaskDataMapper); SectionMapper sectionMapper = new SectionMapper(workingDataMapper, TaskDataMapper); SpatialRecordMapper spatialMapper = new SpatialRecordMapper(new RepresentationValueInterpolator(), sectionMapper, workingDataMapper, TaskDataMapper); IEnumerable <ISOSpatialRow> isoRecords = ReadTimeLog(isoTimeLog, this.TaskDataPath); bool useDeferredExecution = false; if (isoRecords != null) { try { if (TaskDataMapper.Properties != null) { //Set this property to override the default behavior of pre-iterating the data bool.TryParse(TaskDataMapper.Properties.GetProperty("SpatialRecordDeferredExecution"), out useDeferredExecution); } if (!useDeferredExecution) { isoRecords = isoRecords.ToList(); //Avoids multiple reads } //Set a UTC "delta" from the first record where possible. We set only one per data import. if (!TaskDataMapper.GPSToLocalDelta.HasValue) { var firstRecord = isoRecords.FirstOrDefault(); if (firstRecord != null && firstRecord.GpsUtcDateTime.HasValue) { //Local - UTC = Delta. This value will be rough based on the accuracy of the clock settings but will expose the ability to derive the UTC times from the exported local times. TaskDataMapper.GPSToLocalDelta = (firstRecord.TimeStart - firstRecord.GpsUtcDateTime.Value).TotalHours; } } } catch (Exception ex) { TaskDataMapper.AddError($"Timelog file {isoTimeLog.Filename} is invalid. Skipping.", ex.Message, null, ex.StackTrace); return(null); } ISOTime time = isoTimeLog.GetTimeElement(this.TaskDataPath); //Identify unique devices represented in this TimeLog data IEnumerable <string> deviceElementIDs = time.DataLogValues.Where(d => d.ProcessDataDDI != "DFFF" && d.ProcessDataDDI != "DFFE").Select(d => d.DeviceElementIdRef); Dictionary <ISODevice, HashSet <string> > loggedDeviceElementsByDevice = new Dictionary <ISODevice, HashSet <string> >(); foreach (string deviceElementID in deviceElementIDs) { ISODeviceElement isoDeviceElement = TaskDataMapper.DeviceElementHierarchies.GetISODeviceElementFromID(deviceElementID); if (isoDeviceElement != null) { ISODevice device = isoDeviceElement.Device; if (!loggedDeviceElementsByDevice.ContainsKey(device)) { loggedDeviceElementsByDevice.Add(device, new HashSet <string>()); } loggedDeviceElementsByDevice[device].Add(deviceElementID); } } //Split all devices in the same TimeLog into separate OperationData objects to handle multi-implement scenarios //This will ensure implement geometries/DeviceElementUse Depths & Orders do not get confused between implements List <OperationData> operationDatas = new List <OperationData>(); foreach (ISODevice dvc in loggedDeviceElementsByDevice.Keys) { OperationData operationData = new OperationData(); //Determine products Dictionary <string, List <ISOProductAllocation> > productAllocations = GetProductAllocationsByDeviceElement(loggedTask, dvc); List <int> productIDs = GetDistinctProductIDs(TaskDataMapper, productAllocations); //This line will necessarily invoke a spatial read in order to find //1)The correct number of CondensedWorkState working datas to create //2)Any Widths and Offsets stored in the spatial data IEnumerable <DeviceElementUse> sections = sectionMapper.Map(time, isoRecords, operationData.Id.ReferenceId, loggedDeviceElementsByDevice[dvc], productAllocations); var workingDatas = sections != null?sections.SelectMany(x => x.GetWorkingDatas()).ToList() : new List <WorkingData>(); operationData.GetSpatialRecords = () => spatialMapper.Map(isoRecords, workingDatas, productAllocations); operationData.MaxDepth = sections.Count() > 0 ? sections.Select(s => s.Depth).Max() : 0; operationData.GetDeviceElementUses = x => sectionMapper.ConvertToBaseTypes(sections.Where(s => s.Depth == x).ToList()); operationData.PrescriptionId = prescriptionID; operationData.OperationType = GetOperationTypeFromLoggingDevices(time); operationData.ProductIds = productIDs; operationData.SpatialRecordCount = isoRecords.Count(); operationDatas.Add(operationData); } //Set the CoincidentOperationDataIds property identifying Operation Datas from the same TimeLog. operationDatas.ForEach(o => o.CoincidentOperationDataIds = operationDatas.Where(o2 => o2.Id.ReferenceId != o.Id.ReferenceId).Select(o3 => o3.Id.ReferenceId).ToList()); return(operationDatas); } return(null); }