From ba37d5082917551fd9a2b194fa1489f1fd86f39b Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Tue, 9 Sep 2025 16:30:00 +0300 Subject: FSE Improved Statistics + Dynamic CSV Export ! --- .../Tango.FSE.Statistics/ViewModels/MainViewVM.cs | 260 ++++++++++----------- 1 file changed, 121 insertions(+), 139 deletions(-) (limited to 'Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs') diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs index e3546cb92..d7a829cda 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs @@ -518,7 +518,7 @@ namespace Tango.FSE.Statistics.ViewModels Quantity = 0 }); - jobRunProperties.Add(liquidType.Type, typeof(JobRunDTO).GetProperty(liquidType.Type.ToString() + "Quantity")); + jobRunProperties.Add(liquidType.Type, typeof(JobRunDTO).GetProperty(liquidType.Type.ToString() + "Quantity",BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance)); } foreach (var stop in Stops) @@ -709,166 +709,148 @@ namespace Tango.FSE.Statistics.ViewModels } } - private void ExportToCSV(List stops, String filePath) - { - CsvFile csvFile = new CsvFile(new CsvDestination(filePath), new CsvDefinition() + private void ExportToCSV(List stops, string filePath) + { + var csv = new CsvDynamicWriter(); + + // ===== Fixed column indices (preserve original order) ===== + const int IDX_JobIndex = 0; + const int IDX_JobName = 1; + const int IDX_JobKind = 2; + const int IDX_Thread = 3; + const int IDX_Length = 4; + const int IDX_NumberOfUnits = 5; + const int IDX_StartTime = 6; + const int IDX_Duration = 7; + const int IDX_Distance = 8; + const int IDX_StartPosition = 9; + const int IDX_EndPosition = 10; + const int IDX_Status = 11; + const int IDX_SegmentIndex = 12; + const int IDX_Offset = 13; + const int IDX_ColorSpace = 14; + + // Fine-tuning block (before inputs, matches original header order) + const int IDX_TargetL = 15; + const int IDX_TargetA = 16; + const int IDX_TargetB = 17; + const int IDX_MeasuredL = 18; + const int IDX_MeasuredA = 19; + const int IDX_MeasuredB = 20; + const int IDX_DeltaE = 21; + const int IDX_Approved = 22; + + // Fixed "Input *" (non-volume) columns + const int IDX_InputRgbR = 23; + const int IDX_InputRgbG = 24; + const int IDX_InputRgbB = 25; + const int IDX_InputLabL = 26; + const int IDX_InputLabA = 27; + const int IDX_InputLabB = 28; + const int IDX_InputCatalog = 29; + const int IDX_InputCatalogItem = 30; + + // Dynamic regions: + // - Input volumes start after IDX_InputCatalogItem + // - Outputs start immediately after the last input volume + var liquids = (LiquidTypes[])Enum.GetValues(typeof(LiquidTypes)); + const int INPUT_VOLUMES_BASE = 31; + int OUTPUT_BASE = INPUT_VOLUMES_BASE + liquids.Length; + int IDX_FailureReason = OUTPUT_BASE + liquids.Length; // last + + foreach (var stop in stops.OrderBy(x => x.JobIndex)) { - Columns = new List() - { - "Job Index", - "Job Name", - "Job Kind", - "Thread", - "Length", - "Number Of Units", - "Start Time", - "Duration", - "Distance", - "Start Position", - "End Position", - "Status", - "Segment Index", - "Offset", - "Color Space", - "Target L", - "Target A", - "Target B", - "Measured L", - "Measured A", - "Measured B", - "Delta E", - "Approved", - "Input RGB (R)", - "Input RGB (G)", - "Input RGB (B)", - "Input LAB (L)", - "Input LAB (A)", - "Input LAB (B)", - "Input Catalog", - "Input Catalog Item", - "Input Cyan", - "Input Magenta", - "Input Yellow", - "Input Black", - "Input Blue", - "Input Orange", - "Input Rubine", - "Input Navy", - "Input Violet", - "Output Cyan", - "Output Magenta", - "Output Yellow", - "Output Black", - "Output Light Cyan", - "Output Light Magenta", - "Output Light Yellow", - "Output Blue", - "Output Light Blue", - "Output Orange", - "Output Light Orange", - "Output Rubine", - "Output Light Rubine", - "Output Navy", - "Output Violet", - "Output Transparent Ink", - "Output Lubricant", - "Failure Reason", - }, - }); + // ===== Fixed fields ===== + csv.Write(stop.JobIndex.ToString(), "Job Index", "", IDX_JobIndex); + csv.Write(stop.JobRun.JobName, "Job Name", "", IDX_JobName); + csv.Write(((JobDesignations)stop.JobRun.JobDesignation).ToDescription(), + "Job Kind", "", IDX_JobKind); + csv.Write(stop.ThreadName, "Thread", "", IDX_Thread); + csv.Write(stop.LogicalLengthMeters.ToString(), "Length", "0", IDX_Length); + csv.Write(stop.JobRun.NumberOfUnits.ToString(), "Number Of Units", "0", IDX_NumberOfUnits); + csv.Write(stop.JobRun.StartDate.ToLocalTime().ToString(), "Start Time", "", IDX_StartTime); + csv.Write(stop.Duration.ToStringUnlimitedHours(), "Duration", "", IDX_Duration); + csv.Write(stop.Distance.ToString(), "Distance", "0", IDX_Distance); + csv.Write(stop.ActualStartPosition.ToString(), "Start Position", "0", IDX_StartPosition); + csv.Write(stop.ActualEndPosition.ToString(), "End Position", "0", IDX_EndPosition); + csv.Write(((JobRunStatus)stop.JobRun.Status).ToString(), "Status", "", IDX_Status); + csv.Write(stop.SegmentIndex.ToString(), "Segment Index", "0", IDX_SegmentIndex); + csv.Write(stop.StartMeters.ToString(), "Offset", "0", IDX_Offset); + csv.Write(stop.ColorSpace.ToString(), "Color Space", "", IDX_ColorSpace); + + // ===== Fine tuning (if applicable) ===== + if (stop.JobRun.JobDesignation == (int)JobDesignations.FineTuning && stop.FineTuningModel != null) + { + csv.Write(stop.FineTuningModel.FineTuningTargetL.ToString(), "Target L", "0", IDX_TargetL); + csv.Write(stop.FineTuningModel.FineTuningTargetA.ToString(), "Target A", "0", IDX_TargetA); + csv.Write(stop.FineTuningModel.FineTuningTargetB.ToString(), "Target B", "0", IDX_TargetB); - foreach (var stop in stops.OrderBy(x => x.JobIndex).ToList()) - { - CsvModel model = new CsvModel(); - model.JobIndex = stop.JobIndex.ToString(); - model.JobName = stop.JobRun.JobName; - model.JobKind = ((JobDesignations)stop.JobRun.JobDesignation).ToDescription(); - model.Thread = stop.ThreadName; - model.Length = stop.LogicalLengthMeters.ToString(); - model.NumberOfUnits = stop.JobRun.NumberOfUnits.ToString(); - model.StartTime = stop.JobRun.StartDate.ToLocalTime().ToString(); - model.Duration = stop.Duration.ToStringUnlimitedHours(); - model.Distance = stop.Distance.ToString(); - model.StartPosition = stop.ActualStartPosition.ToString(); - model.EndPosition = stop.ActualEndPosition.ToString(); - model.Status = ((JobRunStatus)stop.JobRun.Status).ToString(); - model.SegmentIndex = stop.SegmentIndex.ToString(); - model.Offset = stop.StartMeters.ToString(); - model.ColorSpace = stop.ColorSpace.ToString(); + csv.Write(stop.FineTuningModel.FineTuningMeasuredL.ToStringSafe(), "Measured L", "0", IDX_MeasuredL); + csv.Write(stop.FineTuningModel.FineTuningMeasuredA.ToStringSafe(), "Measured A", "0", IDX_MeasuredA); + csv.Write(stop.FineTuningModel.FineTuningMeasuredB.ToStringSafe(), "Measured B", "0", IDX_MeasuredB); + csv.Write(stop.FineTuningDeltaE.ToStringSafe(), "Delta E", "0", IDX_DeltaE); + csv.Write(stop.FineTuningModel.Approved.ToStringYesNo(), "Approved", "No", IDX_Approved); + } + + // ===== Inputs (color-space specific) ===== switch (stop.ColorSpace) { case ColorSpaces.RGB: - model.InputRed = stop.Red.ToString(); - model.InputGreen = stop.Green.ToString(); - model.InputBlue = stop.Blue.ToString(); + if (stop.Red > 0) csv.Write(stop.Red.ToString(), "Input RGB (R)", "0", IDX_InputRgbR); + if (stop.Green > 0) csv.Write(stop.Green.ToString(), "Input RGB (G)", "0", IDX_InputRgbG); + if (stop.Blue > 0) csv.Write(stop.Blue.ToString(), "Input RGB (B)", "0", IDX_InputRgbB); break; + case ColorSpaces.LAB: - model.InputL = stop.L.ToString(); - model.InputA = stop.A.ToString(); - model.InputB = stop.B.ToString(); + if (stop.L > 0) csv.Write(stop.L.ToString(), "Input LAB (L)", "0", IDX_InputLabL); + if (stop.A > 0) csv.Write(stop.A.ToString(), "Input LAB (A)", "0", IDX_InputLabA); + if (stop.B > 0) csv.Write(stop.B.ToString(), "Input LAB (B)", "0", IDX_InputLabB); break; + case ColorSpaces.Catalog: - model.InputCatalog = stop.Catalog; - model.InputCatalogItem = stop.CatalogItem; + if (stop.Catalog.IsNotNullOrEmpty()) + csv.Write(stop.Catalog, "Input Catalog", "", IDX_InputCatalog); + if (stop.CatalogItem.IsNotNullOrEmpty()) + csv.Write(stop.CatalogItem, "Input Catalog Item", "", IDX_InputCatalogItem); break; + case ColorSpaces.Volume: - model.InputCyan = stop.GetLiquidVolumeInputOrZero(LiquidTypes.Cyan).ToString(); - model.InputMagenta = stop.GetLiquidVolumeInputOrZero(LiquidTypes.Magenta).ToString(); - model.InputYellow = stop.GetLiquidVolumeInputOrZero(LiquidTypes.Yellow).ToString(); - model.InputBlack = stop.GetLiquidVolumeInputOrZero(LiquidTypes.Black).ToString(); - - model.InputBBlue = stop.GetLiquidVolumeInputOrZero(LiquidTypes.Blue).ToString(); - model.InputOrange = stop.GetLiquidVolumeInputOrZero(LiquidTypes.Orange).ToString(); - model.InputRubine = stop.GetLiquidVolumeInputOrZero(LiquidTypes.Rubine).ToString(); - model.InputNavy = stop.GetLiquidVolumeInputOrZero(LiquidTypes.Navy).ToString(); - model.InputViolet = stop.GetLiquidVolumeInputOrZero(LiquidTypes.Violet).ToString(); + // Dynamic input volumes by enum order + for (int i = 0; i < liquids.Length; i++) + { + var lt = liquids[i]; + var idx = INPUT_VOLUMES_BASE + i; + var col = "Input " + lt; // e.g., "Input Cyan" + var v = stop.GetLiquidVolumeInputOrZero(lt); + if (v > 0) csv.Write(v.ToString(), col, "0", idx); + } break; } - if (stop.JobRun.JobDesignation == (int)JobDesignations.FineTuning) + // ===== Outputs for all liquids (dynamic by enum order) ===== + for (int i = 0; i < liquids.Length; i++) { - if (stop.FineTuningModel != null) - { - model.TargetL = stop.FineTuningModel.FineTuningTargetL.ToString(); - model.TargetA = stop.FineTuningModel.FineTuningTargetA.ToString(); - model.TargetB = stop.FineTuningModel.FineTuningTargetB.ToString(); - - model.MeasuredL = stop.FineTuningModel.FineTuningMeasuredL.ToStringSafe(); - model.MeasuredA = stop.FineTuningModel.FineTuningMeasuredA.ToStringSafe(); - model.MeasuredB = stop.FineTuningModel.FineTuningMeasuredB.ToStringSafe(); - - model.DeltaE = stop.FineTuningDeltaE.ToStringSafe(); - model.Approved = stop.FineTuningModel.Approved.ToStringYesNo(); - } + var lt = liquids[i]; + var idx = OUTPUT_BASE + i; + var col = "Output " + lt; // e.g., "Output Cyan" + var v = stop.GetLiquidVolumeOutputOrZero(lt); + if (v > 0) csv.Write(v.ToString(), col, "0", idx); } - model.OutputCyan = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Cyan).ToString(); - model.OutputMagenta = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Magenta).ToString(); - model.OutputYellow = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Yellow).ToString(); - model.OutputBlack = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Black).ToString(); - model.OutputLightCyan = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.LightCyan).ToString(); - model.OutputLightMagenta = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.LightMagenta).ToString(); - model.OutputLightYellow = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.LightYellow).ToString(); - - model.OutputBlue = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Blue).ToString(); - model.OutputLightBlue = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.LightBlue).ToString(); - model.OutputOrange = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Orange).ToString(); - model.OutputLightOrange = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.LightOrange).ToString(); - model.OutputRubine = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Rubine).ToString(); - model.OutputLightRubine = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.LightRubine).ToString(); - model.OutputNavy = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Navy).ToString(); - model.OutputViolet = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Violet).ToString(); - - model.OutputTransparent = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Transparent).ToString(); - model.OutputLubricant = stop.GetLiquidVolumeOutputOrZero(LiquidTypes.Lubricant).ToString(); - model.FailureReason = stop.JobRun.FailedMessage; - - csvFile.Append(model); + // ===== Failure reason (last) ===== + if (stop.JobRun.FailedMessage.IsNotNullOrEmpty()) + csv.Write(stop.JobRun.FailedMessage, "Failure Reason", "", IDX_FailureReason); + + // Next row + csv.Next(); } - csvFile.Dispose(); + csv.Save(filePath); } + + #endregion #region Streaming -- cgit v1.3.1