Example #1
0
        public void GivenTskWhenMapThenOperationDataAreMapped()
        {
            const string taskName = "TSK5";

            var existingLoggedData = new LoggedData();

            existingLoggedData.Id.UniqueIds.Add(new UniqueId {
                IdType = IdTypeEnum.String, Id = taskName, Source = UniqueIdMapper.IsoSource
            });
            _documents.LoggedData = new List <LoggedData> {
                existingLoggedData
            };

            var tlgs = new List <TLG> {
                new TLG()
            };

            _tsk.Items = tlgs.ToArray();
            _tsk.A     = taskName;

            var operationDatas = new List <OperationData>();

            _operationDataMapper.Setup(x => x.Map(tlgs, null, _dataPath, It.IsAny <int>(), _linkIds)).Returns(operationDatas);

            var result = MapSingle();

            Assert.AreSame(operationDatas, result.OperationData);
        }
Example #2
0
        private static void AreEqual(LoggedData loggedData, TSK tsk, Catalog catalog, string cardPath)
        {
            var grower = catalog.Growers.SingleOrDefault(x => x.Id.ReferenceId == loggedData.GrowerId);
            var farm   = catalog.Farms.SingleOrDefault(x => x.Id.ReferenceId == loggedData.FarmId);
            var field  = catalog.Fields.SingleOrDefault(x => x.Id.ReferenceId == loggedData.FieldId);

            if (grower != null)
            {
                Assert.AreEqual(grower.Id.FindIsoId(), tsk.C);
            }
            if (farm != null)
            {
                Assert.AreEqual(farm.Id.FindIsoId(), tsk.D);
            }
            if (field != null)
            {
                Assert.AreEqual(field.Id.FindIsoId(), tsk.E);
            }

            if (loggedData.TimeScopes != null && loggedData.TimeScopes.Any())
            {
                var tims = tsk.Items.Where(x => x.GetType() == typeof(TIM)).Cast <TIM>().ToList();
                TimAssert.AreEqual(loggedData.TimeScopes, tims);
            }

            if (loggedData.OperationData != null && loggedData.OperationData.Any())
            {
                var tlgs = tsk.Items.Where(x => x.GetType() == typeof(TLG)).Cast <TLG>().ToList();
                TlgAssert.AreEqual(loggedData.OperationData.ToList(), tlgs, catalog, cardPath);
            }
        }
Example #3
0
        private LoggedData LoadTask(XmlNode inputNode)
        {
            var task = new LoggedData();

            // Required fields. Do not proceed if they are missing
            var taskId = inputNode.GetXmlNodeValue("@A");

            if (taskId == null)
            {
                return(null);
            }

            // Optional fields
            task.Description = inputNode.GetXmlNodeValue("@B");

            LoadField(inputNode.GetXmlNodeValue("@E"), task);
            LoadFarm(inputNode.GetXmlNodeValue("@D"), task);
            LoadCustomer(inputNode.GetXmlNodeValue("@C"), task);

            LoadGuidanceAllocations(inputNode, task);
            LoadCommentAllocations(inputNode, task);
            task.Id.UniqueIds.Add(new UniqueId
            {
                Id     = taskId,
                Source = UniqueIdMapper.IsoSource,
                IdType = IdTypeEnum.String,
            });

            _taskDocument.LoadLinkedIds(taskId, task.Id);
            return(task);
        }
Example #4
0
 protected override void DoWhenAllDataIsReady()
 {
     LoggedData.Add(Provider.Data);
     //Timestamps.Add(Timestamps.LastOrDefault() + Provider.Interval);
     Timestamps.Add(Provider.RunTime);
     Intervals.Add(Provider.Interval);
 }
Example #5
0
        protected override void DoWhenAllDataIsReady()
        {
            //if (Res.DebuggingSignalFlag)
            //    Log.Debug(_tag, $"DoWhenAll: {LoggedData.Count} data pts.");
            if (AllowDataUpdates) //base.DoWhenAllDataIsReady();
            {
                LoggedData.Add(Provider.Data);
                //Timestamps.Add(Timestamps.LastOrDefault() + Provider.Interval);
                Timestamps.Add(Provider.RunTime + AccumulatedRuntime);
                Intervals.Add(Provider.Interval);
            }
            //if (SessionCTS != null && SessionCTS.IsCancellationRequested)
            //{
            //    if (DeactivationCounter == 0)
            //    {
            //        SessionCTS = null;
            //        DeactivationCounter = 10;
            //        AdditionalPointsSignal.Set();
            //    }
            //    else DeactivationCounter--;
            //}

            if (InitialInterval == TimeSpan.Zero)
            {
                InitialInterval = Provider.Interval;
            }
        }
        public static void DescribeSummaryData(ApplicationDataModel adm, LoggedData loggedData)
        {
            Console.WriteLine();
            Console.WriteLine("-----------------------");
            Console.WriteLine("Task Summary Information");
            Console.WriteLine("-----------------------");
            Console.WriteLine();

            //Each LoggedData object will map to a Summary object via the SummaryId property.
            Summary summary = adm.Documents.Summaries.SingleOrDefault(s => s.Id.ReferenceId == loggedData.SummaryId);

            if (summary != null)
            {
                //Each summary will have a start date timescope
                TimeScope timeScope = summary.TimeScopes.SingleOrDefault(t => t.DateContext == DateContextEnum.ActualStart);
                DateTime  startTime = timeScope.TimeStamp1.Value;

                //In the 2020 Plugin, we include the end date as TimeStamp2.
                DateTime endTime = timeScope.TimeStamp2.Value;

                Console.WriteLine($"The field operation started at {startTime.ToString()} and ended at {endTime.ToString()}");
                Console.WriteLine();
                Console.WriteLine($"The following are totals/averages for the field operation:");


                //The 2020 plugin will summarize all field Operation data into a single StampedMetersValues collection.
                //The ADAPT framework allows for multiple StampedMetersValues in cases where multiple timestamps govern multiple data values
                foreach (MeteredValue meteredValue in summary.SummaryData.Single().Values)
                {
                    NumericRepresentationValue representationValue = meteredValue.Value as NumericRepresentationValue;
                    string summaryValueName = representationValue.Representation.Description;
                    string uomCode          = representationValue.Value.UnitOfMeasure.Code;
                    double value            = representationValue.Value.Value;

                    Console.WriteLine($"{summaryValueName}: {value} {uomCode}");
                }

                Console.WriteLine();

                //For seed and liquid fertilizer products, the Plugin will summarize data by product

                Console.WriteLine($"The following are totals/averages by product:");
                foreach (OperationSummary operationSummary in summary.OperationSummaries)
                {
                    Product product = adm.Catalog.Products.FirstOrDefault(p => p.Id.ReferenceId == operationSummary.ProductId);
                    Console.WriteLine($"{product.Description}:");
                    foreach (MeteredValue meteredValue in operationSummary.Data.Single().Values)
                    {
                        NumericRepresentationValue representationValue = meteredValue.Value as NumericRepresentationValue;
                        string summaryValueName = representationValue.Representation.Description;
                        string uomCode          = representationValue.Value.UnitOfMeasure.Code;
                        double value            = representationValue.Value.Value;

                        Console.WriteLine($"{summaryValueName}: {value} {uomCode}");
                    }
                    Console.WriteLine();
                }
            }
        }
Example #7
0
        private void LoadGuidanceAllocations(XmlNode inputNode, LoggedData task)
        {
            var allocations = GuidanceAllocationLoader.Load(inputNode, _taskDocument);

            _taskDocument.GuidanceAllocations.AddRange(allocations);

            task.GuidanceAllocationIds = allocations.Select(x => x.Id.ReferenceId).ToList();
        }
Example #8
0
        private void LoadCustomer(string customerId, LoggedData task)
        {
            var customer = _taskDocument.Customers.FindById(customerId);

            if (customer != null)
            {
                task.GrowerId = customer.Id.ReferenceId;
            }
        }
Example #9
0
        private void LoadFarm(string farmId, LoggedData task)
        {
            var farm = _taskDocument.Farms.FindById(farmId);

            if (farm != null)
            {
                task.FarmId   = farm.Id.ReferenceId;
                task.GrowerId = farm.GrowerId;
            }
        }
Example #10
0
        private void LoadField(string fieldId, LoggedData task)
        {
            var field = _taskDocument.Fields.FindById(fieldId);

            if (field != null)
            {
                task.FieldId = field.Id.ReferenceId;
                task.FarmId  = field.FarmId;
            }
        }
Example #11
0
        public IEnumerable <LoggedData> ImportLoggedDatas(IEnumerable <ISOTask> isoLoggedTasks)
        {
            List <LoggedData> adaptLoggedDatas = new List <LoggedData>();

            foreach (ISOTask isoLoggedTask in isoLoggedTasks)
            {
                LoggedData loggedData = ImportLoggedData(isoLoggedTask);
                adaptLoggedDatas.Add(loggedData);
            }
            return(adaptLoggedDatas);
        }
Example #12
0
 protected override void DoWhenAllDataIsReady()
 {
     LoggedData.Add(new Datapoint <T1, T2>()
     {
         Value1 = (providers[0] as IProvider <T1>).Data, Value2 = (providers[1] as IProvider <T2>).Data
     });
     //if (LoggedData.All(d => d.Magnitude() < 1e-10) && LoggedData.Count > 5) throw new Exception("Caught another zero list of data... WHY???");
     //Timestamps.Add(Timestamps.LastOrDefault() + providers[0].Interval);
     Timestamps.Add(providers[0].RunTime);
     Intervals.Add(providers[0].Interval);
 }
Example #13
0
        private Summary ImportSummary(ISOTask isoLoggedTask, LoggedData loggedData)
        {
            //Per ISO11783-10:2015(E) 6.8.3, the last Time element contains the comprehensive task totals.
            //Earlier Time elements contain the task totals leading up to points where the Task was paused.
            //As such, the Summary.TimeScopes will include detail on various intermittent Timescopes,
            //and the Summary.SummaryData will contain totals from only the last time element.
            //Summary.SummaryData.Stamp will be set to a comprehensive time stamp from the beginning of the first time to the end of the last.
            Summary summary = null;
            IEnumerable <ISOTime> timeElements = isoLoggedTask.Times.Where(t => t.HasStart && t.HasType);

            if (timeElements.Any())
            {
                summary = new Summary();

                //TimeScopes
                summary.TimeScopes = new List <TimeScope>();
                foreach (ISOTime time in isoLoggedTask.Times.Where(t => t.HasStart && t.HasType)) //Nothing added without a Start and Type attribute
                {
                    TimeScope timeScope = new TimeScope();
                    timeScope.TimeStamp1 = time.Start;
                    if (time.Stop != null)
                    {
                        timeScope.TimeStamp2 = time.Stop;
                    }

                    if (time.Stop == null && time.Duration != null)
                    {
                        //Calculate the Stop time if missing and duration present
                        timeScope.TimeStamp2 = timeScope.TimeStamp1.Value.AddSeconds(time.Duration.Value);
                    }
                    timeScope.DateContext = time.Type == ISOEnumerations.ISOTimeType.Planned ? DateContextEnum.ProposedStart : DateContextEnum.ActualStart;
                    timeScope.Duration    = timeScope.TimeStamp2.GetValueOrDefault() - timeScope.TimeStamp1.GetValueOrDefault();
                    summary.TimeScopes.Add(timeScope);
                }

                //Summary Data - does not have a product reference
                summary.SummaryData = ImportSummaryData(timeElements);

                //Operation Summaries - includes a product reference
                summary.OperationSummaries = ImportOperationSummaries(isoLoggedTask);

                //Copy properties from LoggedData
                summary.GrowerId                    = loggedData.GrowerId;
                summary.FarmId                      = loggedData.FarmId;
                summary.FieldId                     = loggedData.FieldId;
                summary.CropZoneId                  = loggedData.CropZoneId;
                summary.PersonRoleIds               = loggedData.PersonRoleIds;
                summary.WorkItemIds                 = loggedData.WorkItemIds;
                summary.GuidanceAllocationIds       = loggedData.GuidanceAllocationIds;
                summary.EquipmentConfigurationGroup = loggedData.EquipmentConfigurationGroup;
            }
            return(summary);
        }
        public static void GetLoggedData(Catalog catalog, LoggedData loggedData)
        {
            Console.WriteLine("Logged Data: " + loggedData.Description);

            // Write out the grower/farm/field
            Grower grower = catalog.Growers.Find(x => x.Id.ReferenceId == loggedData.GrowerId);

            if (grower != null)
            {
                Console.WriteLine("Grower: " + grower.Name);
            }

            Farm farm = catalog.Farms.Find(x => x.Id.ReferenceId == loggedData.FarmId);

            if (farm != null)
            {
                Console.WriteLine("Farm: " + farm.Description);
            }

            Field field = catalog.Fields.Find(x => x.Id.ReferenceId == loggedData.FieldId);

            if (field != null)
            {
                Console.WriteLine("Field: " + field.Description);
            }

            foreach (OperationData opData in loggedData.OperationData)
            {
                Console.WriteLine("Operation: " + opData.OperationType);

                switch (opData.OperationType)
                {
                case OperationTypeEnum.Harvesting:
                    GetHarvestData(opData, catalog);
                    break;

                case OperationTypeEnum.SowingAndPlanting:
                    GetPlantingData(opData, catalog);
                    break;

                case OperationTypeEnum.CropProtection:
                case OperationTypeEnum.Fertilizing:
                    GetAsAppliedData(opData, catalog);
                    break;
                }
            }

            // Clean up
            loggedData.ReleaseSpatialData();

            Console.WriteLine();
        }
Example #15
0
        public void Setup()
        {
            _loggedData  = new LoggedData();
            _loggedDatas = new List <LoggedData> {
                _loggedData
            };
            _catalog            = new Catalog();
            _datacardPath       = "";
            _taskDocumentWriter = new TaskDocumentWriter();

            _timeMapperMock = new Mock <ITimeMapper>();
            _tlgMapperMock  = new Mock <ITlgMapper>();

            _taskMapper = new TaskMapper(_timeMapperMock.Object, _tlgMapperMock.Object);
        }
Example #16
0
        public void GivenTskWithNullItemWhenMapThenPrescriptionIdIsNullToOperationMapper()
        {
            var existingLoggedData = new LoggedData();

            existingLoggedData.Id.UniqueIds.Add(new UniqueId {
                IdType = IdTypeEnum.String, Id = "TSK0", Source = UniqueIdMapper.IsoSource
            });
            _documents.LoggedData = new List <LoggedData> {
                existingLoggedData
            };
            _tsk.A = "TSK0";

            MapSingle();

            _operationDataMapper.Verify(x => x.Map(It.IsAny <List <TLG> >(), null, _dataPath, existingLoggedData.Id.ReferenceId, _linkIds), Times.Once);
        }
Example #17
0
        public void readLog()
        {
            StreamReader sr       = new StreamReader("LogFile.txt");
            string       readData = String.Empty;

            LoggedData.Clear();
            while (sr.EndOfStream != true)
            {
                readData = sr.ReadLine();
                if (readData != null)
                {
                    LoggedData.Add(readData);
                }
            }

            sr.Close();
        }
        public async Task ShouldUseOnlyLogDataForFieldForOperationTotals()
        {
            var extraLogData = new LoggedData
            {
                FieldId       = 324234,
                OperationData = new List <OperationData>
                {
                    new OperationData()
                }
            };

            _dataModel.Documents.LoggedData = _dataModel.Documents.LoggedData.Concat(extraLogData);

            var operationTotals = await _operationTotalsCalculator.Calculate(_field, _dataModel);

            Assert.AreEqual(3, operationTotals.Length);
        }
        public static void DescribeCoincidentOperations(LoggedData loggedData)
        {
            Console.WriteLine();
            Console.WriteLine("-----------------------");
            Console.WriteLine("Coincident Operations");
            Console.WriteLine("-----------------------");
            Console.WriteLine();

            //The OperationData.CoincidentOperationDataIDs property contains a reference to all related OperationData objects that represent
            //parallel operations, logged at the same place and time.
            //E.g., a planter may have the capability to plant seed, apply a granular insecticide and a liquid fertilizer all in one pass.
            //This example would be represented as 3 OperationDatas coincident to one another.
            //In such case, an implementer may wish to iterate the collections in parallel or otherwise join the data.

            List <List <int> > coincidentGroupings = new List <List <int> >();

            foreach (OperationData operationData in loggedData.OperationData)
            {
                if (operationData.CoincidentOperationDataIds.Any())
                {
                    List <int> coincidentList = new List <int>()
                    {
                        operationData.Id.ReferenceId
                    };                                                                           //Add the id for the given item
                    operationData.CoincidentOperationDataIds.ForEach(i => coincidentList.Add(i));
                    if (!coincidentGroupings.Any(g => g.Contains(operationData.Id.ReferenceId)))
                    {
                        coincidentGroupings.Add(coincidentList);
                    }
                }
            }

            if (coincidentGroupings.Any())
            {
                Console.WriteLine($"The following operations are coincident to one another.");
                foreach (List <int> grouping in coincidentGroupings)
                {
                    Console.WriteLine(string.Join(",", grouping.ToArray()));
                }
            }
            else
            {
                Console.WriteLine($"There were no coincident operations.");
            }
        }
Example #20
0
        public void ClearDataOlderThan(TimeSpan span)
        {
            if (Timestamps.Count == 0)
            {
                return;
            }
            var currentTimestamp = Timestamps.Last();
            var numToSkip        = Timestamps.FindIndex(t => t + span >= currentTimestamp);

            //Log.Debug(_tag, $"At {currentTimestamp}, clearing out {numToSkip} data points, keeping as of {Timestamps.Skip(numToSkip).First()}.");
            //Provider.Deactivate();
            AllowDataUpdates = false;
            LoggedData       = LoggedData.Skip(numToSkip).ToList();
            Intervals        = Intervals.Skip(numToSkip).ToList();
            Timestamps       = Timestamps.Skip(numToSkip).ToList();
            AllowDataUpdates = true;
            //Provider.Activate();
        }
Example #21
0
        private IWriter[] MapItems(LoggedData loggedData, string datacardPath, TaskDocumentWriter taskDocumentWriter)
        {
            var times = FindAndMapTimes(loggedData.TimeScopes);
            var tlgs  = _tlgMapper.Map(loggedData.OperationData, datacardPath, taskDocumentWriter);

            var items = new List <IWriter>();

            if (times != null)
            {
                items.AddRange(times);
            }

            if (tlgs != null)
            {
                items.AddRange(tlgs);
            }

            return(items.ToArray());
        }
Example #22
0
        private TSK Map(LoggedData loggedData, Catalog catalog, string taskDataPath, int taskNumber, TaskDocumentWriter taskDocumentWriter)
        {
            var taskId = "TSK" + taskNumber;

            taskDocumentWriter.Ids.Add(taskId, loggedData.Id);

            var tsk = new TSK
            {
                A     = taskId,
                B     = loggedData.Description,
                C     = FindGrowerId(loggedData.GrowerId, catalog),
                D     = FindFarmId(loggedData.FarmId, catalog),
                E     = FindFieldId(loggedData.FieldId, catalog),
                G     = TSKG.Item4,
                Items = MapItems(loggedData, taskDataPath, taskDocumentWriter)
            };

            return(tsk);
        }
Example #23
0
        public void GivenTskWithGrdWhenMapThenPrescriptionIdFromCatalogIsPassedToOperationMapper()
        {
            var prescription = new RasterGridPrescription();

            prescription.Id.UniqueIds = new List <UniqueId>
            {
                new UniqueId
                {
                    IdType = IdTypeEnum.String,
                    Id     = "FIX1",
                    Source = "http://dictionary.isobus.net/isobus/"
                }
            };

            _catalog.Prescriptions = new List <Prescription> {
                prescription
            };


            var existingLoggedData = new LoggedData();

            existingLoggedData.Id.UniqueIds.Add(new UniqueId {
                IdType = IdTypeEnum.String, Id = "FIX1", Source = UniqueIdMapper.IsoSource
            });
            _documents.LoggedData = new List <LoggedData> {
                existingLoggedData
            };

            var grd = new GRD();

            _tsk.Items = new List <IWriter> {
                grd
            }.ToArray();
            _tsk.A = "FIX1";

            MapSingle();

            _operationDataMapper.Verify(x => x.Map(It.IsAny <List <TLG> >(), prescription.Id.ReferenceId, _dataPath, existingLoggedData.Id.ReferenceId, _linkIds), Times.Once);
        }
Example #24
0
        public async Task AddLoggedData(string deviceName, string data)
        {
            int?loggingDeviceId = await db.LoggingDevices
                                  .Where(dbLoggingDevice => dbLoggingDevice.DeviceName == deviceName)
                                  .Select(dbLoggingDevice => (int?)dbLoggingDevice.Id)
                                  .SingleOrDefaultAsync();

            if (!loggingDeviceId.HasValue)
            {
                // Can't find the device.
                throw new DeviceNotFoundException(deviceName);
            }

            // Create the logged data and save it.
            LoggedData loggedData = new LoggedData
            {
                Data            = data,
                LoggedTime      = DateTime.UtcNow,
                LoggingDeviceId = loggingDeviceId.Value
            };

            db.LoggedData.Add(loggedData);
            await db.SaveChangesAsync();
        }
Example #25
0
 public void ClearData()
 {
     LoggedData.Clear();
     Intervals.Clear();
     Timestamps.Clear();
 }
Example #26
0
 protected override T toImplicitType()
 {
     return(LoggedData.LastOrDefault());
 }
        public static void DescribeSpatialData(Catalog catalog, LoggedData loggedData)
        {
            //Coincident Operations
            DescribeCoincidentOperations(loggedData);

            Console.WriteLine();
            Console.WriteLine("-----------------------");
            Console.WriteLine("Spatial Data");
            Console.WriteLine("-----------------------");
            Console.WriteLine();

            foreach (OperationData operationData in loggedData.OperationData)
            {
                //1.  Create some collections for tracking high-level/header information on the implement devices and sensors.
                List <WorkingData>    operationDataWorkingDatas       = new List <WorkingData>();
                Dictionary <int, int> useToDeviceConfigurationMapping = new Dictionary <int, int>();

                //ADAPT models spatial data in multiple depths according to a virtual hierarchy describing the data as it relates to the physical layout of the implement.
                //In the 2020 implementation,
                //  depth 0 refers to a single device representing the entire width of the implement and any sensors reporting data across the implement.
                //  depth 1 generally refers to row-by-row data, where multiple DeviceElements representing individual rows contain one or more sensors
                //  depth 2 is present on planting data where there are multiple varieties configured in specific parts of the implement.  In that case
                //depth 1 contains a description of the varieties
                //depth 2 contains the row-level data
                for (int depth = 0; depth <= operationData.MaxDepth; depth++)  //MaxDepth defines the maximum depth of data on an OperationData
                {
                    //A DeviceElementUse is an instance of a DeviceElement/DeviceElementConfiguration within a specific OperationData.
                    //It contains the collection of all data elements (WorkingData objects) reported on that DeviceElement during the Operation.
                    IEnumerable <DeviceElementUse> deviceElementUses = operationData.GetDeviceElementUses(depth);
                    foreach (DeviceElementUse deviceElementUse in deviceElementUses)
                    {
                        //Track the DeviceConfiguration that this DeviceElementUse relates to for reconciling data values to implement offsets for precise location
                        useToDeviceConfigurationMapping.Add(deviceElementUse.Id.ReferenceId, deviceElementUse.DeviceConfigurationId);

                        //A WorkingData is essentially a Sensor.   It is the definition of some object that will report data per spatial point.
                        //List all such sensors on this DeviceElementUse within this Operation
                        IEnumerable <WorkingData> workingDatas = deviceElementUse.GetWorkingDatas();

                        //Track these in the comprehensive list
                        operationDataWorkingDatas.AddRange(workingDatas);
                    }
                }

                //2. Illustrate any multivariety data present here.
                //If an OperationData from the 2020 plugin contains a maxdepth of 2, then level 1 describes parts of the planter with specific varieties
                if (operationData.OperationType == OperationTypeEnum.SowingAndPlanting &&
                    operationData.MaxDepth == 2)
                {
                    //------------------
                    //Split Planter data
                    //-------------------
                    Console.WriteLine($"OperationData {operationData.Id.ReferenceId} is planter data containing multiple varieties assigned to specific rows:");
                    IEnumerable <DeviceElementUse> levelOneDeviceElementUses = operationData.GetDeviceElementUses(1);
                    foreach (DeviceElementUse use in levelOneDeviceElementUses)
                    {
                        //Retrieve the DeviceElementConfiguration object that matches the DeviceElementUse on this specific operation
                        DeviceElementConfiguration deviceElementConfig = catalog.DeviceElementConfigurations.First(d => d.Id.ReferenceId == use.DeviceConfigurationId);

                        //We've named the Level 1 device elements with the varieties in this situation
                        Console.WriteLine(deviceElementConfig.Description);

                        //All rows planting that variety will be children of this device element,
                        //and the level 1 DeviceElementUse will have a WorkingData called "vrProductIndex" that will map to the variety
                    }
                    Console.WriteLine();
                }
                else if (operationData.OperationType == OperationTypeEnum.SowingAndPlanting &&
                         operationData.MaxDepth == 1 &&
                         operationDataWorkingDatas.Select(w => w.Representation.Code).Any(c => c == "vrProductIndex"))
                {
                    //------------------------------------------------------
                    //vSetSelect & mSet data (variable multi-hybrid planting)
                    //------------------------------------------------------
                    Console.WriteLine($"OperationData {operationData.Id.ReferenceId} is planter data containing multiple varieties dynamically assigned to each row.");

                    //Make a dictionary of product names
                    Dictionary <int, string> productNames = new Dictionary <int, string>();
                    foreach (int productID in operationData.ProductIds)
                    {
                        List <DeviceElementUse> productDeviceElementUses = new List <DeviceElementUse>();
                        Product product = catalog.Products.First(p => p.Id.ReferenceId == productID);
                        productNames.Add(productID, product.Description);
                    }

                    Console.WriteLine($"The following varieties are planted at various points in the field: {string.Join(", ", productNames.Values)}");

                    SpatialRecord firstPoint = operationData.GetSpatialRecords().First();
                    Console.WriteLine("For example, on the first point...");

                    //Examine the content of each DeviceElementUse at the row level with a product index working data
                    foreach (DeviceElementUse deviceElementUse in operationData.GetDeviceElementUses(1)) //1 is the row level where OperationData.MaxDepth == 1.
                    {
                        foreach (WorkingData productIndexWorkingData in deviceElementUse.GetWorkingDatas().Where(w => w.Representation.Code == "vrProductIndex"))
                        {
                            NumericRepresentationValue productValue = firstPoint.GetMeterValue(productIndexWorkingData) as NumericRepresentationValue;
                            int productIndex = (int)productValue.Value.Value;
                            DeviceElementConfiguration deviceElementConfiguration = catalog.DeviceElementConfigurations.First(d => d.Id.ReferenceId == deviceElementUse.DeviceConfigurationId);
                            Console.WriteLine($"{deviceElementConfiguration.Description} planted {productNames[productIndex]}.");
                        }
                    }

                    Console.WriteLine();
                }


                //3. Read the point-by-point data
                //With the data definition of the OperationData now in-hand, we can iterate the collection of physical points on the field to read the data.
                //Rather than writing out each data value to the screen, we will assemble them into collections to summarize after iterating all data
                Dictionary <WorkingData, List <object> > operationSpatialDataValues = new Dictionary <WorkingData, List <object> >();
                Dictionary <WorkingData, string>         numericDataUnitsOfMeasure  = new Dictionary <WorkingData, string>();

                //Similarly, we will track the geospatial envelope of the data to illustrate lat/lon data present
                double maxLat = Double.MinValue;
                double minLat = Double.MaxValue;
                double maxLon = Double.MinValue;
                double minLon = Double.MaxValue;

                Console.WriteLine("Reading point-by-point data...");
                Console.WriteLine();

                //IMPORTANT
                //To effectively manage memory usage, avoid invoking the iterator multiple times or iterate the entire list in a Linq expression.
                //The linq expressions below do not necessarily take this advice as the focus here is illustrative.
                foreach (SpatialRecord spatialRecord in operationData.GetSpatialRecords())
                {
                    //2020 data will always be in point form
                    Point point = spatialRecord.Geometry as Point;

                    //Track the lat/lon to illustrate the envelope of the dataset
                    double latitude  = point.Y;
                    double longitude = point.X;
                    if (latitude < minLat)
                    {
                        minLat = latitude;
                    }
                    if (latitude > maxLat)
                    {
                        maxLat = latitude;
                    }
                    if (longitude < minLon)
                    {
                        minLon = longitude;
                    }
                    if (longitude > maxLon)
                    {
                        maxLon = longitude;
                    }

                    //Examine the actual data on the points
                    foreach (WorkingData operationWorkingData in operationDataWorkingDatas)
                    {
                        //Create a List for data values on the first encounter with this WorkingData
                        if (!operationSpatialDataValues.ContainsKey(operationWorkingData))
                        {
                            operationSpatialDataValues.Add(operationWorkingData, new List <object>());
                        }

                        //---------------
                        //Representations
                        //---------------
                        //ADAPT publishes standard representations that often equate to ISO11783-11 Data Dictionary Identifiers (DDIs)
                        //These representations define a common type of agricultural measurement.
                        //Where Precision Planting has implemented representations that are not published with ADAPT, they are marked as UserDefined
                        //and the Name describes what each is.

                        //--------------------
                        //RepresentationValues
                        //--------------------
                        //A Representation Value is a complex type that allows the value to
                        //be augmented the full representation, the unit of measure and other data.

                        RepresentationValue representationValue = spatialRecord.GetMeterValue(operationWorkingData);

                        //Values reported may be of type Numeric or Enumerated
                        if (representationValue is NumericRepresentationValue)
                        {
                            NumericRepresentationValue numericRepresentationValue = representationValue as NumericRepresentationValue;
                            operationSpatialDataValues[operationWorkingData].Add(numericRepresentationValue.Value.Value); //Value is a double

                            //--------------------
                            //Units of Measure
                            //--------------------
                            //Store the UOM on the first encounter
                            if (!numericDataUnitsOfMeasure.ContainsKey(operationWorkingData))
                            {
                                numericDataUnitsOfMeasure.Add(operationWorkingData, numericRepresentationValue.Value.UnitOfMeasure.Code);

                                //ADAPT units of measure are documented in the Resources/UnitSystem.xml that is installed in any ADAPT project
                                //They take the form of unitCode[postive exponent]unitcode[negative exponent]
                                //Where the exponents allow for complex units.   E.g.s,
                                //lb = pounds
                                //ac = acres
                                //lb1ac-1 = pounds per acre
                                //mm3m-2 = cubic millimeters per square meter
                            }
                        }
                        else if (representationValue is EnumeratedValue)
                        {
                            EnumeratedValue enumeratedValue = representationValue as EnumeratedValue;
                            operationSpatialDataValues[operationWorkingData].Add(enumeratedValue.Value.Value); //Value is a string
                        }
                    }
                }

                Console.WriteLine();
                Console.WriteLine("-----------------------");
                Console.WriteLine($"{Enum.GetName(typeof(OperationTypeEnum), operationData.OperationType)} data");
                Console.WriteLine("-----------------------");
                Console.WriteLine();

                Console.WriteLine($"Data logged within envelope bounded by {minLat},{minLon} and {maxLat},{maxLon}.");
                Console.WriteLine();

                foreach (WorkingData workingData in operationSpatialDataValues.Keys)
                {
                    //We can obtain a reference to the part of the machine that logged the data via the DeviceConfigurationId property.
                    DeviceElementConfiguration deviceElementConfig = catalog.DeviceElementConfigurations.FirstOrDefault(d => d.Id.ReferenceId == useToDeviceConfigurationMapping[workingData.DeviceElementUseId]);
                    string deviceElementName = deviceElementConfig.Description;

                    if (operationSpatialDataValues[workingData].Any())
                    {
                        if (workingData is NumericWorkingData)
                        {
                            double max     = operationSpatialDataValues[workingData].Cast <double>().Max();
                            double average = operationSpatialDataValues[workingData].Cast <double>().Average();
                            double min     = operationSpatialDataValues[workingData].Cast <double>().Min();
                            string uom     = numericDataUnitsOfMeasure[workingData];
                            Console.WriteLine($"Numeric Working Data {deviceElementConfig.Description}-{workingData.Representation.Description} had a minimum value of {min}, and average of {average} and a maximum value of {max} {uom}.");
                            Console.WriteLine();
                        }
                        else if (workingData is EnumeratedWorkingData)
                        {
                            EnumeratedWorkingData    enumeratedWorkingData    = workingData as EnumeratedWorkingData;
                            EnumeratedRepresentation enumeratedRepresentation = enumeratedWorkingData.Representation as EnumeratedRepresentation;
                            IEnumerable <string>     enumerationValues        = enumeratedRepresentation.EnumeratedMembers.Select(e => e.Value);

                            foreach (string enumerationValue in enumerationValues)
                            {
                                int count = operationSpatialDataValues[workingData].Cast <string>().Count(v => v == enumerationValue);
                                Console.WriteLine($"Enumerated Working Data {deviceElementConfig.Description}-{workingData.Representation.Description} had {count} values of {enumerationValue}.");
                                Console.WriteLine();
                            }
                        }
                    }
                }
            }
        }
Example #28
0
 protected override Datapoint <T1, T2> toImplicitType()
 {
     return(LoggedData.LastOrDefault());
 }
Example #29
0
        private ISOTask Export(LoggedData loggedData)
        {
            ISOTask task = null;

            //Try to map to a pre-existing Work Item task where appropriate
            if (loggedData.OperationData.All(o => o.PrescriptionId.HasValue) &&
                loggedData.OperationData.Select(o => o.PrescriptionId.Value).Distinct().Count() == 1)
            {
                int rxID = loggedData.OperationData.First().PrescriptionId.Value;
                if (_taskIDsByPrescription.ContainsKey(rxID))
                {
                    task = ISOTaskData.ChildElements.OfType <ISOTask>().FirstOrDefault(t => t.TaskID == _taskIDsByPrescription[rxID]);
                }
            }

            if (task == null)
            {
                task = new ISOTask();

                //Task ID
                string taskID = loggedData.Id.FindIsoId() ?? GenerateId();
                task.TaskID = taskID;
            }


            if (!ExportIDs(loggedData.Id, task.TaskID))
            {
                //Update the mapping to represent the completed task
                TaskDataMapper.InstanceIDMap.ReplaceADAPTID(task.TaskID, loggedData.Id.ReferenceId);
            }

            //Task Designator
            task.TaskDesignator = loggedData.Description;

            //Customer Ref
            if (loggedData.GrowerId.HasValue)
            {
                task.CustomerIdRef = TaskDataMapper.InstanceIDMap.GetISOID(loggedData.GrowerId.Value);
            }

            //Farm Ref
            if (loggedData.FarmId.HasValue)
            {
                task.FarmIdRef = TaskDataMapper.InstanceIDMap.GetISOID(loggedData.FarmId.Value);
            }

            //Partfield Ref
            if (loggedData.CropZoneId.HasValue)
            {
                task.PartFieldIdRef = TaskDataMapper.InstanceIDMap.GetISOID(loggedData.CropZoneId.Value);
            }
            else if (loggedData.FieldId.HasValue)
            {
                task.PartFieldIdRef = TaskDataMapper.InstanceIDMap.GetISOID(loggedData.FieldId.Value);
            }

            //Status
            task.TaskStatus = ISOEnumerations.ISOTaskStatus.Completed;

            if (loggedData.OperationData.Any())
            {
                //Time Logs
                task.TimeLogs = TimeLogMapper.ExportTimeLogs(loggedData.OperationData, TaskDataPath).ToList();

                //Connections
                IEnumerable <int> taskEquipmentConfigIDs = loggedData.OperationData.SelectMany(o => o.EquipmentConfigurationIds);
                if (taskEquipmentConfigIDs.Any())
                {
                    IEnumerable <EquipmentConfiguration> taskEquipmentConfigs = DataModel.Catalog.EquipmentConfigurations.Where(d => taskEquipmentConfigIDs.Contains(d.Id.ReferenceId));
                    task.Connections = ConnectionMapper.ExportConnections(loggedData.Id.ReferenceId, taskEquipmentConfigs).ToList();
                }
            }

            //Summaries
            if (loggedData.SummaryId.HasValue)
            {
                Summary summary = DataModel.Documents.Summaries.FirstOrDefault(s => s.Id.ReferenceId == loggedData.SummaryId.Value);
                if (summary != null)
                {
                    task.Times.AddRange(ExportSummary(summary));
                }

                List <ISOProductAllocation> productAllocations = GetProductAllocationsForSummary(summary);
                if (productAllocations != null)
                {
                    task.ProductAllocations.AddRange(productAllocations);
                }
            }

            //Comments
            if (loggedData.Notes.Any())
            {
                CommentAllocationMapper canMapper = new CommentAllocationMapper(TaskDataMapper);
                task.CommentAllocations = canMapper.ExportCommentAllocations(loggedData.Notes).ToList();
            }

            //Worker Allocations
            if (loggedData.PersonRoleIds.Any())
            {
                WorkerAllocationMapper workerAllocationMapper = new WorkerAllocationMapper(TaskDataMapper);
                List <PersonRole>      personRoles            = new List <PersonRole>();
                foreach (int id in loggedData.PersonRoleIds)
                {
                    PersonRole personRole = DataModel.Catalog.PersonRoles.FirstOrDefault(p => p.Id.ReferenceId == id);
                    if (personRole != null)
                    {
                        personRoles.Add(personRole);
                    }
                }
                task.WorkerAllocations = workerAllocationMapper.ExportWorkerAllocations(personRoles).ToList();
            }

            //Guidance Allocations
            if (loggedData.GuidanceAllocationIds.Any())
            {
                GuidanceAllocationMapper  guidanceAllocationMapper = new GuidanceAllocationMapper(TaskDataMapper);
                List <GuidanceAllocation> allocations = new List <GuidanceAllocation>();
                foreach (int id in loggedData.GuidanceAllocationIds)
                {
                    GuidanceAllocation allocation = DataModel.Documents.GuidanceAllocations.FirstOrDefault(p => p.Id.ReferenceId == id);
                    if (allocation != null)
                    {
                        allocations.Add(allocation);
                    }
                }
                task.GuidanceAllocations = guidanceAllocationMapper.ExportGuidanceAllocations(allocations).ToList();
            }

            return(task);
        }
Example #30
0
        private LoggedData ImportLoggedData(ISOTask isoLoggedTask)
        {
            LoggedData loggedData = new LoggedData();

            loggedData.OperationData = new List <OperationData>();

            //Task ID
            if (!ImportIDs(loggedData.Id, isoLoggedTask.TaskID))
            {
                //In the case where a TSK contains both TZN and TLG data, we'll store the LoggedData as the mapped Task.
                //The Prescription ID will be assigned to the OperationData objects by means of the dictionary in this class.
                TaskDataMapper.InstanceIDMap.ReplaceADAPTID(isoLoggedTask.TaskID, loggedData.Id.ReferenceId);
            }

            //Task Name
            loggedData.Description = isoLoggedTask.TaskDesignator;

            //Grower ID
            loggedData.GrowerId = TaskDataMapper.InstanceIDMap.GetADAPTID(isoLoggedTask.CustomerIdRef);

            //Farm ID
            loggedData.FarmId = TaskDataMapper.InstanceIDMap.GetADAPTID(isoLoggedTask.FarmIdRef);

            //Field ID
            int?pfdID = TaskDataMapper.InstanceIDMap.GetADAPTID(isoLoggedTask.PartFieldIdRef);

            if (pfdID.HasValue)
            {
                if (DataModel.Catalog.CropZones.Any(c => c.Id.ReferenceId == pfdID.Value))
                {
                    loggedData.CropZoneId = pfdID.Value;
                }
                else
                {
                    loggedData.FieldId = pfdID.Value;
                    if (DataModel.Catalog.CropZones.Count(c => c.FieldId == pfdID) == 1)
                    {
                        //There is a single cropZone for the field.
                        loggedData.CropZoneId = DataModel.Catalog.CropZones.Single(c => c.FieldId == pfdID).Id.ReferenceId;
                    }
                }
            }

            //Responsible Worker
            if (!string.IsNullOrEmpty(isoLoggedTask.ResponsibleWorkerIdRef))
            {
                ISOWorker worker   = ISOTaskData.ChildElements.OfType <ISOWorker>().FirstOrDefault(w => w.WorkerId == isoLoggedTask.ResponsibleWorkerIdRef);
                int?      personID = TaskDataMapper.InstanceIDMap.GetADAPTID(isoLoggedTask.ResponsibleWorkerIdRef);
                if (personID.HasValue)
                {
                    //Create a Role
                    PersonRole role = new PersonRole()
                    {
                        PersonId = personID.Value
                    };

                    //Add to Catalog
                    DataModel.Catalog.PersonRoles.Add(role);
                    if (loggedData.PersonRoleIds == null)
                    {
                        loggedData.PersonRoleIds = new List <int>();
                    }

                    //Add to Task
                    loggedData.PersonRoleIds.Add(role.Id.ReferenceId);
                }
            }

            //Worker Allocations
            if (isoLoggedTask.WorkerAllocations.Any())
            {
                WorkerAllocationMapper wanMapper   = new WorkerAllocationMapper(TaskDataMapper);
                List <PersonRole>      personRoles = wanMapper.ImportWorkerAllocations(isoLoggedTask.WorkerAllocations).ToList();

                //Add to Catalog
                DataModel.Catalog.PersonRoles.AddRange(personRoles);
                if (loggedData.PersonRoleIds == null)
                {
                    loggedData.PersonRoleIds = new List <int>();
                }

                //Add to Task
                loggedData.PersonRoleIds.AddRange(personRoles.Select(p => p.Id.ReferenceId));
            }

            //Guidance Allocations
            if (isoLoggedTask.GuidanceAllocations.Any())
            {
                GuidanceAllocationMapper  ganMapper   = new GuidanceAllocationMapper(TaskDataMapper);
                List <GuidanceAllocation> allocations = ganMapper.ImportGuidanceAllocations(isoLoggedTask.GuidanceAllocations).ToList();

                //Add to Catalog
                List <GuidanceAllocation> guidanceAllocations = DataModel.Documents.GuidanceAllocations as List <GuidanceAllocation>;
                if (guidanceAllocations != null)
                {
                    guidanceAllocations.AddRange(allocations);
                }

                //Add to Task
                if (loggedData.GuidanceAllocationIds == null)
                {
                    loggedData.GuidanceAllocationIds = new List <int>();
                }
                loggedData.GuidanceAllocationIds.AddRange(allocations.Select(p => p.Id.ReferenceId));
            }

            //Comments
            if (isoLoggedTask.CommentAllocations.Any())
            {
                CommentAllocationMapper canMapper = new CommentAllocationMapper(TaskDataMapper);
                loggedData.Notes = canMapper.ImportCommentAllocations(isoLoggedTask.CommentAllocations).ToList();
            }

            //Summaries
            if (isoLoggedTask.Times.Any(t => t.HasStart && t.HasType)) //Nothing added without a Start & Type attribute
            {
                //An ADAPT LoggedData has exactly one summary.   This is what necessitates that ISO Task maps to LoggedData and ISO TimeLog maps to one or more Operation Data objects
                Summary summary = ImportSummary(isoLoggedTask, loggedData);
                if (DataModel.Documents.Summaries == null)
                {
                    DataModel.Documents.Summaries = new List <Summary>();
                }
                (DataModel.Documents.Summaries as List <Summary>).Add(summary);
                loggedData.SummaryId = summary.Id.ReferenceId;
            }

            //Operation Data
            if (isoLoggedTask.TimeLogs.Any())
            {
                //Find ID for any Prescription that may also be tied to this task
                int?rxID = null;
                if (_rxIDsByTask.ContainsKey(isoLoggedTask.TaskID))
                {
                    rxID = _rxIDsByTask[isoLoggedTask.TaskID];
                }

                loggedData.OperationData = TimeLogMapper.ImportTimeLogs(isoLoggedTask, rxID);
            }

            //Connections
            if (isoLoggedTask.Connections.Any())
            {
                IEnumerable <EquipmentConfiguration> equipConfigs = ConnectionMapper.ImportConnections(isoLoggedTask);

                loggedData.EquipmentConfigurationGroup = new EquipmentConfigurationGroup();
                loggedData.EquipmentConfigurationGroup.EquipmentConfigurations = equipConfigs.ToList();

                //Make a reference to the IDs on the OperationData
                foreach (OperationData operationData in loggedData.OperationData)
                {
                    operationData.EquipmentConfigurationIds.AddRange(equipConfigs.Select(e => e.Id.ReferenceId));
                }

                DataModel.Catalog.EquipmentConfigurations.AddRange(equipConfigs);
            }

            return(loggedData);
        }