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); IEnumerable <ISOSpatialRow> isoRecords = ReadTimeLog(isoTimeLog, this.TaskDataPath); if (isoRecords != null) { isoRecords = isoRecords.ToList(); //Avoids multiple reads 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(); //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]); var workingDatas = sections != null?sections.SelectMany(x => x.GetWorkingDatas()).ToList() : new List <WorkingData>(); var sectionsSimple = sectionMapper.ConvertToBaseTypes(sections.ToList()); operationData.GetSpatialRecords = () => spatialMapper.Map(isoRecords, workingDatas); operationData.MaxDepth = sections.Count() > 0 ? sections.Select(s => s.Depth).Max() : 0; operationData.GetDeviceElementUses = x => x == 0 ? sectionsSimple : new List <DeviceElementUse>(); operationData.PrescriptionId = prescriptionID; operationData.OperationType = GetOperationTypeFromLoggingDevices(time); operationData.ProductId = GetProductIDForOperationData(loggedTask, dvc); operationData.SpatialRecordCount = isoRecords.Count(); operationDatas.Add(operationData); } return(operationDatas); } return(null); }
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); }