Пример #1
0
        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);
        }
Пример #2
0
 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);
         }
     }
 }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        /// <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
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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);
        }