diff options
| author | Roy Ben Shabat <roy.mail.net@gmail.com> | 2025-09-12 17:39:45 +0300 |
|---|---|---|
| committer | Roy Ben Shabat <roy.mail.net@gmail.com> | 2025-09-12 17:39:45 +0300 |
| commit | 7eb361c1201381c6ad88efa0ebed2c6595b45d13 (patch) | |
| tree | 005c5e210d9352d3b26cbb8ab1f80139279b1898 /Software/Visual_Studio | |
| parent | 8e15f292e2950cac71282923adc357f2abf8b306 (diff) | |
| download | Tango-7eb361c1201381c6ad88efa0ebed2c6595b45d13.tar.gz Tango-7eb361c1201381c6ad88efa0ebed2c6595b45d13.zip | |
Fixed FSE Gateway service with production slot cookie.
Implemented FSE dynamic csv job upload. extra inks.
Implemented PPC dynamic csv job read. extra inks.
Diffstat (limited to 'Software/Visual_Studio')
13 files changed, 488 insertions, 469 deletions
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/GatewayService.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/GatewayService.cs index f7c603fe2..3d315f45d 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/GatewayService.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/GatewayService.cs @@ -43,6 +43,7 @@ namespace Tango.FSE.BL.Services using (HttpClient http = new HttpClient()) { + http.DefaultRequestHeaders.TryAddWithoutValidation("Cookie", "x-ms-routing-name=self"); GatewayClient client = new GatewayClient(ConfigurationManager.AppSettings.Get("GatewayUrl"), http); var list = client.GetEnvironments(new EnvironmentsRequest()).Environments.OrderBy(x => x.DisplayIndex).ToList(); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadView.xaml index c806be854..f159cadc9 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadView.xaml @@ -7,7 +7,7 @@ xmlns:local="clr-namespace:Tango.FSE.UI.Dialogs" xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls" mc:Ignorable="d" - Width="400" Height="500" d:DataContext="{d:DesignInstance Type=local:JobUploadViewVM, IsDesignTimeCreatable=False}" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}"> + MinWidth="400" Width="Auto" Height="500" d:DataContext="{d:DesignInstance Type=local:JobUploadViewVM, IsDesignTimeCreatable=False}" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}"> <DockPanel Margin="10"> <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> @@ -36,7 +36,22 @@ <mahapps:NumericUpDown Margin="0 5 0 0" Padding="5 0 0 0" Minimum="1" Maximum="1000000" HasDecimals="False" Style="{StaticResource FSE_NumericUpDown_Flat_Dark}" HideUpDownButtons="True" Value="{Binding Length}"></mahapps:NumericUpDown> </StackPanel> - <UniformGrid Columns="4" Height="100"> + <ItemsControl ItemsSource="{Binding Volumes}" Height="100"> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <UniformGrid Columns="{Binding Volumes.Count}" /> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> + <ItemsControl.ItemTemplate> + <DataTemplate> + <StackPanel> + <TextBlock HorizontalAlignment="Center" Foreground="{Binding LiquidType.LiquidTypeBrush}" Text="{Binding LiquidType.ShortName}"></TextBlock> + <mahapps:NumericUpDown Loaded="NumericUpDown_Loaded" PreviewKeyDown="Num_PreviewKeyDown" Minimum="0" Maximum="200" Margin="0 5 0 0" BorderBrush="{Binding LiquidType.LiquidTypeBrush}" BorderThickness="1" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20" Height="60" HasDecimals="True" Style="{StaticResource FSE_NumericUpDown_Flat_Dark}" HideUpDownButtons="True" Value="{Binding Volume}"></mahapps:NumericUpDown> + </StackPanel> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + <!--<UniformGrid Columns="4" Height="100"> <StackPanel> <TextBlock HorizontalAlignment="Center" Foreground="Cyan">C</TextBlock> <mahapps:NumericUpDown x:Name="numC" PreviewKeyDown="Num_PreviewKeyDown" Minimum="0" Maximum="200" Margin="0 5 0 0" BorderBrush="Cyan" BorderThickness="1" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20" Height="60" HasDecimals="True" Style="{StaticResource FSE_NumericUpDown_Flat_Dark}" HideUpDownButtons="True" Value="{Binding C}"></mahapps:NumericUpDown> @@ -56,7 +71,7 @@ <TextBlock HorizontalAlignment="Center" Foreground="Black">K</TextBlock> <mahapps:NumericUpDown x:Name="numK" PreviewKeyDown="Num_PreviewKeyDown" Minimum="0" Maximum="200" Margin="0 5 0 0" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20" Height="60" HasDecimals="True" Style="{StaticResource FSE_NumericUpDown_Flat_Dark}" HideUpDownButtons="True" Value="{Binding K}"></mahapps:NumericUpDown> </StackPanel> - </UniformGrid> + </UniformGrid>--> </DockPanel> </Grid> </DockPanel> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadView.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadView.xaml.cs index 98d1d8878..f0dcffa65 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadView.xaml.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadView.xaml.cs @@ -28,10 +28,6 @@ namespace Tango.FSE.UI.Dialogs { InitializeComponent(); nums = new List<NumericUpDown>(); - nums.Add(numC); - nums.Add(numM); - nums.Add(numY); - nums.Add(numK); } private void Num_PreviewKeyDown(object sender, KeyEventArgs e) @@ -70,5 +66,11 @@ namespace Tango.FSE.UI.Dialogs } } } + + private void NumericUpDown_Loaded(object sender, RoutedEventArgs e) + { + NumericUpDown num = sender as NumericUpDown; + nums.Add(num); + } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadViewVM.cs index f12e4edf1..896175400 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/JobUploadViewVM.cs @@ -4,15 +4,23 @@ using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; +using Tango.BL.Entities; using Tango.Core.DI; using Tango.FSE.Common; using Tango.FSE.Common.Build; +using Tango.FSE.Common.Connection; using Tango.PPC.Shared.Statistics; namespace Tango.FSE.UI.Dialogs { public class JobUploadViewVM : FSEDialogViewVM { + public class LiquidVolume + { + public LiquidType LiquidType { get; set; } + public double Volume { get; set; } + } + private String _name; public String Name { @@ -24,21 +32,18 @@ namespace Tango.FSE.UI.Dialogs public ThreadFilterData SelectedRML { get; set; } - public int Length { get; set; } - - public double C { get; set; } - - public double M { get; set; } + public List<LiquidVolume> Volumes { get; set; } - public double Y { get; set; } - - public double K { get; set; } + public int Length { get; set; } - public JobUploadViewVM() + public JobUploadViewVM(IMachineProvider machineProvider) { Rmls = new List<ThreadFilterData>(); - TangoIOC.Default.Inject(this); + Volumes = machineProvider.Machine.Configuration.NoneEmptyIdsPacks.OrderBy(x => x.LiquidType.PreferredIndex).Where(x => x.LiquidType.AvailableForStandardUser).Select(x => new LiquidVolume() + { + LiquidType = x.LiquidType + }).ToList(); OKText = "UPLOAD"; CancelText = "CANCEL"; diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs index 33297d103..c7b52df81 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs @@ -387,35 +387,34 @@ namespace Tango.FSE.UI.ViewModels var lastSelectedRml = data.Rmls.FirstOrDefault(x => x.Guid == Settings.LastJobUploadThreadGuid); if (lastSelectedRml == null) lastSelectedRml = data.Rmls.FirstOrDefault(); - var vm = await NotificationProvider.ShowDialog(new JobUploadViewVM() { Rmls = data.Rmls, SelectedRML = lastSelectedRml }); + var vm = await NotificationProvider.ShowDialog(new JobUploadViewVM(MachineProvider) { Rmls = data.Rmls, SelectedRML = lastSelectedRml }); if (vm.DialogResult) { - TemporaryFile tmpFile = TemporaryManager.CreateFile(".csv"); + TemporaryFile tmpFile = TemporaryManager.CreateImaginaryFile(".csv"); try { Settings.LastJobUploadThreadGuid = vm.SelectedRML.Guid; Settings.Save(); - SegmentCsvModel model = new SegmentCsvModel(); - List<string> columnNames = model.GetType().GetProperties().Select(x => x.Name).ToList(); - CsvFile<SegmentCsvModel> csvFile = new CsvFile<SegmentCsvModel>(new CsvDestination(tmpFile), new CsvDefinition() - { - Columns = columnNames - }); + CsvDynamicWriter csv = new CsvDynamicWriter(); + + int cIndex = 0; - model.Index = "1"; - model.ThreadName = vm.SelectedRML.Name; - model.ColorSpace = ColorSpaces.Volume.ToDescription(); - model.Length = vm.Length.ToString(); - model.Cyan1 = vm.C.ToString(); - model.Magenta1 = vm.M.ToString(); - model.Yellow1 = vm.Y.ToString(); - model.Black1 = vm.K.ToString(); + csv.Write(1, "Index", 0, cIndex++); + csv.Write(vm.SelectedRML.Name, "ThreadName", "", cIndex++); + csv.Write(vm.Length, "Length", 0, cIndex++); + csv.Write(ColorSpaces.Volume, "ColorSpace", ColorSpaces.Volume, cIndex++); + foreach (var liquidVolume in vm.Volumes) + { + if (liquidVolume.Volume > 0) + { + csv.Write(liquidVolume.Volume, liquidVolume.LiquidType.DisplayName, 0, cIndex); + } + } - csvFile.Append(model); - csvFile.Dispose(); + csv.Save(tmpFile); } catch (Exception ex) { diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/Models/JobModel.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/Models/JobModel.cs index 283c051e8..1b5562a59 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/Models/JobModel.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/Models/JobModel.cs @@ -394,12 +394,12 @@ namespace Tango.PPC.Jobs.Models [JsonIgnore] public int NumberSpools { - get { return _numberSpools; } + get { return Math.Max(_numberSpools, 1); } set { if (_numberSpools != value) { - _numberSpools = value; + _numberSpools = Math.Max(value, 1); RaisePropertyChangedAuto(); OnNumberOfSpoolsChanged(); OnUpdateLengthhWeight(); diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/ViewModels/JobsViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/ViewModels/JobsViewVM.cs index 67a4cf972..db75b5e34 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/ViewModels/JobsViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/ViewModels/JobsViewVM.cs @@ -960,6 +960,7 @@ namespace Tango.PPC.Jobs.ViewModels job.Name = vm.Name; job.NumberOfHeads = 1; job.NumberOfUnits = 1; + job.NumberOfSpools = BuildProvider.MachineType == MachineTypes.Eureka ? 4 : 1; job.SampleUnitsOrMeters = 1; job.CreationDate = DateTime.UtcNow; job.JobStatus = JobStatuses.Draft; @@ -1045,6 +1046,7 @@ namespace Tango.PPC.Jobs.ViewModels job.NumberOfHeads = 1; job.NumberOfUnits = 1; job.SampleUnitsOrMeters = 1; + job.NumberOfSpools = BuildProvider.MachineType == MachineTypes.Eureka ? 4 : 1; job.CreationDate = DateTime.UtcNow; job.JobStatus = JobStatuses.Draft; job.JobType = JobTypes.Knitting; @@ -1056,18 +1058,6 @@ namespace Tango.PPC.Jobs.ViewModels job.WindingMethodGuid = Adapter.WindingMethods.FirstOrDefault().Guid; job.SpoolTypeGuid = Settings.SpoolTypeGuid != null ? Settings.SpoolTypeGuid : Adapter.SpoolTypes.FirstOrDefault().Guid; - if (BuildProvider.IsEureka) - { - job.EnableInterSegment = false; - job.InterSegmentLength = 0; - - if (BuildProvider.MachineType == MachineTypes.Eureka) - { - job.NumberOfSpools = 4; - } - job.NumberOfUnits = 1; - } - foreach (var segment in segments) { diff --git a/Software/Visual_Studio/Tango.BL/Entities/Configuration.cs b/Software/Visual_Studio/Tango.BL/Entities/Configuration.cs index 62c20bcce..ae48b52c9 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/Configuration.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/Configuration.cs @@ -32,6 +32,11 @@ namespace Tango.BL.Entities get { return IdsPacks.OrderBy(x => x.PackIndex).ToList(); } } + public IdsPack GetIdsPackByColorMatch(String name) + { + return NoneEmptyIdsPacks.Where(x => x.LiquidType.AvailableForStandardUser).FirstOrDefault(x => x.LiquidType.Type.ToString().ToLower().Contains(name.ToLower())); + } + /// <summary> /// Gets a collection of this configuration IDS packs where packs are not 'empty' and are supported by the specified <see cref="Rml"/>. /// </summary> diff --git a/Software/Visual_Studio/Tango.BL/Helpers/SegmentsCsvHelper.cs b/Software/Visual_Studio/Tango.BL/Helpers/SegmentsCsvHelper.cs index 28c227a8d..ebc466bb7 100644 --- a/Software/Visual_Studio/Tango.BL/Helpers/SegmentsCsvHelper.cs +++ b/Software/Visual_Studio/Tango.BL/Helpers/SegmentsCsvHelper.cs @@ -27,114 +27,11 @@ namespace Tango.BL.Helpers } } - public class SegmentCsvModel - { - [CsvOrder(0)] - public String Index { get; set; } - - [CsvOrder(1)] - public String ThreadName { get; set; } - - [CsvOrder(2)] - public String ColorSpace { get; set; } - - [CsvOrder(3)] - public String Length { get; set; } - - [CsvOrder(4)] - public String CatalogName1 { get; set; } - - [CsvOrder(5)] - public String CatalogItem1 { get; set; } - - [CsvOrder(6)] - public String Red1 { get; set; } - [CsvOrder(7)] - public String Green1 { get; set; } - [CsvOrder(8)] - public String Blue1 { get; set; } - - [CsvOrder(9)] - public String L1 { get; set; } - [CsvOrder(10)] - public String A1 { get; set; } - [CsvOrder(11)] - public String B1 { get; set; } - - - - [CsvOrder(12)] - public String Cyan1 { get; set; } - [CsvOrder(13)] - public String Magenta1 { get; set; } - [CsvOrder(14)] - public String Yellow1 { get; set; } - [CsvOrder(15)] - public String Black1 { get; set; } - - [CsvOrder(16)] - public String CatalogName2 { get; set; } - [CsvOrder(17)] - public String CatalogItem2 { get; set; } - - [CsvOrder(18)] - public String Red2 { get; set; } - [CsvOrder(19)] - public String Green2 { get; set; } - [CsvOrder(20)] - public String Blue2 { get; set; } - - [CsvOrder(21)] - public String L2 { get; set; } - [CsvOrder(22)] - public String A2 { get; set; } - [CsvOrder(23)] - public String B2 { get; set; } - - - [CsvOrder(24)] - public String Cyan2 { get; set; } - [CsvOrder(25)] - public String Magenta2 { get; set; } - [CsvOrder(26)] - public String Yellow2 { get; set; } - [CsvOrder(27)] - public String Black2 { get; set; } - - public bool IsRgb2NullOrEqual() - { - if (String.IsNullOrWhiteSpace(Red2) || String.IsNullOrWhiteSpace(Green2) || String.IsNullOrWhiteSpace(Blue2)) return true; - if (Red1 == Red2 && Green1 == Green2 && Blue1 == Blue2) return true; - return false; - } - - internal bool IsVolumeNullOrEqual() - { - if (String.IsNullOrWhiteSpace(Cyan2) || String.IsNullOrWhiteSpace(Magenta2) || String.IsNullOrWhiteSpace(Yellow2) || String.IsNullOrWhiteSpace(Black2)) return true; - if (Cyan1 == Cyan2 && Magenta1 == Magenta2 && Yellow1 == Yellow2 && Black1 == Black2) return true; - return false; - } - - internal bool IsCatalogNameNullOrEqual() - { - if (String.IsNullOrWhiteSpace(CatalogName2) || String.IsNullOrEmpty(CatalogItem2)) return true; - if (CatalogName1 == CatalogName2 && CatalogItem1 == CatalogItem2) return true; - return false; - } - - internal bool IsLab2NullOrEqual() - { - if (String.IsNullOrWhiteSpace(L2) || String.IsNullOrWhiteSpace(A2) || String.IsNullOrWhiteSpace(B2)) return true; - if (L1 == L2 && A1 == A2 && B1 == B2) return true; - return false; - } - } - public static Task<SegmentsCsvResult> FromFile(String filePath, Machine machine, ObservablesContext context) { return Task.Factory.StartNew(() => { - List<SegmentCsvModel> rows = CsvFile.Read<SegmentCsvModel>(new CsvSource(filePath)).ToList(); + var csv = new CsvDynamicReader(filePath); List<Segment> segments = new List<Segment>(); @@ -148,9 +45,20 @@ namespace Tango.BL.Helpers String threadName = null; - if (rows.Count > 0) + if (csv.Rows.Count > 0) { - threadName = rows.First().ThreadName; + if (csv.Rows.First().Exists("ThreadName")) + { + threadName = csv.Rows.First().Read("ThreadName", String.Empty); + } + else if (csv.Rows.First().Exists("Thread")) + { + threadName = csv.Rows.First().Read("Thread", String.Empty); + } + else if (csv.Rows.First().Exists("RML")) + { + threadName = csv.Rows.First().Read("RML", String.Empty); + } } Rml rml = null; @@ -169,200 +77,69 @@ namespace Tango.BL.Helpers } } - var idsPacks = machine.Configuration.NoneEmptyIdsPacks.ToList(); - - var cyanIdsPack = idsPacks.FirstOrDefault(x => x.LiquidType.Type == LiquidTypes.Cyan); - var magentaIdsPack = idsPacks.FirstOrDefault(x => x.LiquidType.Type == LiquidTypes.Magenta); - var yellowIdsPack = idsPacks.FirstOrDefault(x => x.LiquidType.Type == LiquidTypes.Yellow); - var blackIdsPack = idsPacks.FirstOrDefault(x => x.LiquidType.Type == LiquidTypes.Black); - int lineCount = 0; - foreach (var row in rows) + foreach (var row in csv.Rows) { lineCount++; try { + //Name Segment segment = new Segment(); segment.Name = "Standard Segment"; - double length; - if (!double.TryParse(row.Length, out length)) + //Length and Index + segment.Length = row.Read("Length", 100); + segment.SegmentIndex = row.Read("Index", lineCount); + + //Color Space + ColorSpaces space = row.Read("ColorSpace", ColorSpaces.Volume); + ColorSpace colorSpace = colorSpaces.SingleOrDefault(x => x.Space == space); + + BrushStop stop = new BrushStop(); + stop.StopIndex = 1; + stop.ColorSpace = colorSpace; + stop.OffsetPercent = 0; + stop.Segment = segment; + segment.BrushStops.Add(stop); + + //RGB + if (space == ColorSpaces.RGB) { - continue; //Ignore none indexed rows. Maybe there are many empty rows at the end to the document... + stop.Red = row.Read("RGB R", 0); + stop.Green = row.Read("RGB G", 0); + stop.Blue = row.Read("RGB B", 0); } - int segmentIndex; - if (!int.TryParse(row.Index, out segmentIndex)) + //LAB + if (space == ColorSpaces.LAB) { - throw new InvalidOperationException($"Value Index '{row.Index}' should be a number on line'{lineCount}'."); + stop.L = row.Read("L", 0); + stop.A = row.Read("A", 0); + stop.B = row.Read("B", 0); } - segment.Length = length; - segment.SegmentIndex = segmentIndex; - - ColorSpace colorSpace = colorSpaces.SingleOrDefault(x => x.Name == row.ColorSpace); - - if (colorSpace == null) throw new InvalidOperationException($"Color space '{row.ColorSpace}' not found on line '{lineCount}'."); - - BrushStop stop1 = new BrushStop(); - stop1.StopIndex = 1; - stop1.ColorSpace = colorSpace; - stop1.OffsetPercent = 0; - stop1.Segment = segment; - segment.BrushStops.Add(stop1); - - if (colorSpace.Space == ColorSpaces.RGB) + //Volumes + if (space == ColorSpaces.Volume) { - int red1; - if (!int.TryParse(row.Red1, out red1)) - { - throw new InvalidOperationException($"Value Red1 '{row.Red1}' should be a number on line'{lineCount}'."); - } - stop1.Red = red1; - if (stop1.Red < 0 || stop1.Red > 255) throw new InvalidOperationException($"Value red1 '{row.Red1}' is out of range on line '{lineCount}'."); - - int green1; - if (!int.TryParse(row.Green1, out green1)) - { - throw new InvalidOperationException($"Value Green1 '{row.Green1}' should be a number on line'{lineCount}'."); - } - stop1.Green = green1; - if (stop1.Green < 0 || stop1.Green > 255) throw new InvalidOperationException($"Value green1 '{row.Green1}' is out of range on line '{lineCount}'."); - - int blue1; - if (!int.TryParse(row.Blue1, out blue1)) - { - throw new InvalidOperationException($"Value Blue1 '{row.Blue1}' should be a number on line'{lineCount}'."); - } - stop1.Blue = blue1; - if (stop1.Blue < 0 || stop1.Blue > 255) throw new InvalidOperationException($"Value blue1 '{row.Blue1}' is out of range on line '{lineCount}'."); - - if (!row.IsRgb2NullOrEqual()) + foreach (var idsPack in machine.Configuration.NoneEmptyIdsPacks.Where(x => x.LiquidType.AvailableForStandardUser)) { - BrushStop stop2 = new BrushStop(); - stop2.StopIndex = 2; - stop2.ColorSpace = stop1.ColorSpace; - stop2.OffsetPercent = 100; - - int red2; - if (!int.TryParse(row.Red2, out red2)) - { - throw new InvalidOperationException($"Value Red2 '{row.Red2}' should be a number on line'{lineCount}'."); - } - stop2.Red = red2; - if (stop2.Red < 0 || stop2.Red > 255) throw new InvalidOperationException($"Value red2 '{row.Red2}' is out of range on line '{lineCount}'."); - - int green2; - if (!int.TryParse(row.Green2, out green2)) - { - throw new InvalidOperationException($"Value Green2 '{row.Green2}' should be a number on line'{lineCount}'."); - } - stop2.Green = green2; - if (stop2.Green < 0 || stop2.Green > 255) throw new InvalidOperationException($"Value green2 '{row.Green2}' is out of range on line '{lineCount}'."); - - int blue2; - if (!int.TryParse(row.Blue2, out blue2)) - { - throw new InvalidOperationException($"Value Blue2 '{row.Blue2}' should be a number on line'{lineCount}'."); - } - stop2.Blue = blue2; - if (stop2.Blue < 0 || stop2.Blue > 255) throw new InvalidOperationException($"Value blue2 '{row.Blue2}' is out of range on line '{lineCount}'."); - - segment.BrushStops.Add(stop2); - stop2.Segment = segment; + var volume = row.Read(idsPack.LiquidType.DisplayName, 0); + stop.SetVolume(idsPack.PackIndex, volume); } } - else if (colorSpace.Space == ColorSpaces.Volume) - { - double cyan1; - if (!double.TryParse(row.Cyan1, out cyan1)) - { - throw new InvalidOperationException($"Value Cyan1 '{row.Cyan1}' should be a number on line'{lineCount}.'!"); - } - if (cyan1 < 0 || cyan1 > MAX_VOLUME) throw new InvalidOperationException($"Value Cyan1 '{row.Cyan1}' is out of range on line '{lineCount}.'!"); - stop1.SetVolume(cyanIdsPack.PackIndex, cyan1); - double magenta1; - if (!double.TryParse(row.Magenta1, out magenta1)) - { - throw new InvalidOperationException($"Value Magenta1 '{row.Magenta1}' should be a number on line'{lineCount}.'!"); - } - if (magenta1 < 0 || magenta1 > MAX_VOLUME) throw new InvalidOperationException($"Value Magenta1 '{row.Magenta1}' is out of range on line '{lineCount}.'!"); - - stop1.SetVolume(magentaIdsPack.PackIndex, magenta1); - - double yellow1 = double.Parse(row.Yellow1); - if (!double.TryParse(row.Yellow1, out yellow1)) - { - throw new InvalidOperationException($"Value Yellow1 '{row.Yellow1}' should be a number on line'{lineCount}.'!"); - } - if (yellow1 < 0 || yellow1 > MAX_VOLUME) throw new InvalidOperationException($"Value Yellow1 '{row.Yellow1}' is out of range on line '{lineCount}.'!"); - - stop1.SetVolume(yellowIdsPack.PackIndex, yellow1); - - double black1 = double.Parse(row.Black1); - if (!double.TryParse(row.Black1, out black1)) - { - throw new InvalidOperationException($"Value Black1 '{row.Black1}' should be a number on line'{lineCount}.'!"); - } - if (black1 < 0 || black1 > MAX_VOLUME) throw new InvalidOperationException($"Value Black1 '{row.Black1}' is out of range on line '{lineCount}.'!"); - - stop1.SetVolume(blackIdsPack.PackIndex, black1); - - if (!row.IsVolumeNullOrEqual()) - { - BrushStop stop2 = new BrushStop(); - stop2.StopIndex = 2; - stop2.ColorSpace = stop1.ColorSpace; - stop2.OffsetPercent = 100; - - double cyan2; - if (!double.TryParse(row.Cyan2, out cyan2)) - { - throw new InvalidOperationException($"Value Cyan2 '{row.Cyan2}' should be a number on line'{lineCount}.'!"); - } - if (cyan2 < 0 || cyan2 > MAX_VOLUME) throw new InvalidOperationException($"Value Cyan2 '{row.Cyan2}' is out of range on line '{lineCount}.'!"); - stop2.SetVolume(cyanIdsPack.PackIndex, cyan2); - - double magenta2; - if (!double.TryParse(row.Magenta2, out magenta2)) - { - throw new InvalidOperationException($"Value Magenta2 '{row.Magenta2}' should be a number on line'{lineCount}.'!"); - } - if (magenta2 < 0 || magenta2 > MAX_VOLUME) throw new InvalidOperationException($"Value Magenta2 '{row.Magenta2}' is out of range on line '{lineCount}.'!"); - - stop2.SetVolume(magentaIdsPack.PackIndex, magenta2); - - double yellow2 = double.Parse(row.Yellow2); - if (!double.TryParse(row.Yellow2, out yellow2)) - { - throw new InvalidOperationException($"Value Yellow2 '{row.Yellow2}' should be a number on line'{lineCount}.'!"); - } - if (yellow2 < 0 || yellow2 > MAX_VOLUME) throw new InvalidOperationException($"Value Yellow2 '{row.Yellow2}' is out of range on line '{lineCount}.'!"); - - stop2.SetVolume(yellowIdsPack.PackIndex, yellow2); - - double black2 = double.Parse(row.Black2); - if (!double.TryParse(row.Black2, out black2)) - { - throw new InvalidOperationException($"Value Black2 '{row.Black2}' should be a number on line'{lineCount}.'!"); - } - if (black2 < 0 || black2 > MAX_VOLUME) throw new InvalidOperationException($"Value Black2 '{row.Black2}' is out of range on line '{lineCount}.'!"); - - stop2.SetVolume(blackIdsPack.PackIndex, black2); - - segment.BrushStops.Add(stop2); - stop2.Segment = segment; - } - } - else if (colorSpace.Space == ColorSpaces.Catalog) + //Catalog + if (space == ColorSpaces.Catalog) { - var catalog = catalogs.FirstOrDefault(x => x.Name == row.CatalogName1); + var catalogName = row.Read("Catalog", String.Empty); + var catalogItemName = row.Read("Catalog Item", String.Empty); + + var catalog = catalogs.FirstOrDefault(x => x.Name == catalogName); if (catalog == null) { - throw new InvalidOperationException($"Catalog '{row.CatalogName1}' not found on line '{lineCount}'."); + throw new InvalidOperationException($"Catalog '{catalogName}' not found on line '{lineCount}'."); } if (machine.SiteGuid != null) @@ -373,93 +150,17 @@ namespace Tango.BL.Helpers } } - var item = catalog.ColorCatalogsGroups.SelectMany(x => x.ColorCatalogsItems).FirstOrDefault(x => x.Name == row.CatalogItem1); + var item = catalog.ColorCatalogsGroups.SelectMany(x => x.ColorCatalogsItems).FirstOrDefault(x => x.Name == catalogItemName); if (item == null) { - throw new InvalidOperationException($"Catalog item '{row.CatalogItem1}' not found on catalog '{catalog.Name}' on line '{lineCount}'."); + throw new InvalidOperationException($"Catalog item '{catalogItemName}' not found on catalog '{catalog.Name}' on line '{lineCount}'."); } - stop1.ColorCatalog = catalog; - stop1.ColorCatalogsItem = item; - stop1.Color = item.Color; - if (!row.IsCatalogNameNullOrEqual()) - { - var catalog2 = catalogs.FirstOrDefault(x => x.Name == row.CatalogName2); - if (catalog2 == null) - { - throw new InvalidOperationException($"Catalog '{row.CatalogName2}' not found on line '{lineCount}'."); - } - - if (machine.SiteGuid != null) - { - if (!context.SitesCatalogs.Any(x => x.SiteGuid == machine.SiteGuid && x.ColorCatalogGuid == catalog2.Guid)) - { - throw new InvalidOperationException($"Catalog '{catalog2.Name}' is not assigned for this machine's site."); - } - } - - var item2 = catalog2.ColorCatalogsGroups.SelectMany(x => x.ColorCatalogsItems).FirstOrDefault(x => x.Name == row.CatalogItem2); - if (item2 == null) - { - throw new InvalidOperationException($"Catalog item '{row.CatalogItem2}' not found on catalog '{catalog2.Name}' on line '{lineCount}'."); - } - BrushStop stop2 = new BrushStop(); - stop2.StopIndex = 2; - stop2.ColorSpace = stop1.ColorSpace; - stop2.ColorCatalog = catalog2; - stop2.ColorCatalogsItem = item2; - stop2.Color = item2.Color; - stop2.OffsetPercent = 100; - segment.BrushStops.Add(stop2); - stop2.Segment = segment; - } + stop.ColorCatalog = catalog; + stop.ColorCatalogsItem = item; + stop.Color = item.Color; } - else if (colorSpace.Space == ColorSpaces.LAB) - { - double number; - if (!double.TryParse(row.L1, out number)) - throw new InvalidOperationException($"Value L1 '{row.L1}' should be a number on line'{lineCount}'."); - stop1.L = number; - if (stop1.L < 0 || stop1.L > 100) throw new InvalidOperationException($"Value L1 '{row.L1}' is out of range on line '{lineCount}'."); - - if (!double.TryParse(row.A1, out number)) - throw new InvalidOperationException($"Value A1 '{row.A1}' should be a number on line'{lineCount}'."); - stop1.A = number; - if (stop1.A < -128 || stop1.A > 128) throw new InvalidOperationException($"Value A1 '{row.A1}' is out of range on line '{lineCount}'."); - - if (!double.TryParse(row.B1, out number)) - throw new InvalidOperationException($"Value B1 '{row.B1}' should be a number on line'{lineCount}'."); - stop1.B = number; - if (stop1.B < -128 || stop1.B > 128) throw new InvalidOperationException($"Value B1 '{row.B1}' is out of range on line '{lineCount}'."); - if (!row.IsLab2NullOrEqual()) - { - BrushStop stop2 = new BrushStop(); - stop2.StopIndex = 2; - stop2.ColorSpace = stop1.ColorSpace; - stop2.OffsetPercent = 100; - double l2; - if (!double.TryParse(row.L2, out l2)) - throw new InvalidOperationException($"Value L2 '{row.L2}' should be a number on line'{lineCount}'."); - stop2.L = l2; - if (stop2.L < 0 || stop2.L > 100) throw new InvalidOperationException($"Value L2 '{row.L2}' is out of range on line '{lineCount}'."); - - double a2; - if (!double.TryParse(row.A2, out a2)) - throw new InvalidOperationException($"Value A2 '{row.A2}' should be a number on line'{lineCount}'."); - stop2.A = a2; - if (stop2.A < -128 || stop2.A > 128) throw new InvalidOperationException($"Value A2 '{row.A2}' is out of range on line '{lineCount}'."); - - double b2; - if (!double.TryParse(row.B2, out b2)) - throw new InvalidOperationException($"Value B2 '{row.B2}' should be a number on line'{lineCount}'."); - stop2.B = b2; - if (stop2.B < -128 || stop2.B > 128) throw new InvalidOperationException($"Value B2 '{row.B2}' is out of range on line '{lineCount}'."); - - segment.BrushStops.Add(stop2); - stop2.Segment = segment; - } - } segments.Add(segment); } catch (Exception ex) @@ -480,79 +181,49 @@ namespace Tango.BL.Helpers { await Task.Factory.StartNew(() => { - SegmentCsvModel model = new SegmentCsvModel(); - List<string> columnNames = model.GetType().GetProperties().Select(x => x.Name).ToList(); - CsvFile<SegmentCsvModel> csvFile = new CsvFile<SegmentCsvModel>(new CsvDestination(filePath), new CsvDefinition() - { - Columns = columnNames - }); + CsvDynamicWriter csv = new CsvDynamicWriter(); + + int cIndex = 0; + foreach (var segment in segments) { - SegmentCsvModel csvmodel = new SegmentCsvModel(); - csvmodel.Index = segment.SegmentIndex.ToString(); - csvmodel.Length = segment.Length.ToString(); - if (segment.BrushStops.Count > 2) throw new InvalidOperationException($"Cannot save more than two brush stops!"); + csv.Write(segment.SegmentIndex, "Index", 0, cIndex++); + csv.Write(segment.Length, "Length", 0, cIndex++); + //save first brush stop - if (segment.BrushStops.Count > 0) + var stop = segment.BrushStops[0]; + + csv.Write(stop.ColorSpace.Space, "ColorSpace", ColorSpaces.Volume, cIndex++); + + if (stop.BrushColorSpace == ColorSpaces.RGB) { - var brushStop1 = segment.BrushStops[0]; - csvmodel.ColorSpace = brushStop1.ColorSpace.Name; - if (csvmodel.ColorSpace == ColorSpaces.RGB.ToDescription()) - { - csvmodel.Red1 = brushStop1.Red.ToString(); - csvmodel.Green1 = brushStop1.Green.ToString(); - csvmodel.Blue1 = brushStop1.Blue.ToString(); - } - else if (csvmodel.ColorSpace == ColorSpaces.Volume.ToDescription()) - { - csvmodel.Cyan1 = brushStop1.GetVolume(LiquidTypes.Cyan).ToString(); - csvmodel.Magenta1 = brushStop1.GetVolume(LiquidTypes.Magenta).ToString(); - csvmodel.Yellow1 = brushStop1.GetVolume(LiquidTypes.Yellow).ToString(); - csvmodel.Black1 = brushStop1.GetVolume(LiquidTypes.Black).ToString(); - } - else if (csvmodel.ColorSpace == ColorSpaces.Catalog.ToDescription()) - { - csvmodel.CatalogName1 = brushStop1.ColorCatalog.Name; - csvmodel.CatalogItem1 = brushStop1.ColorCatalogsItem.Name; - } - else if (csvmodel.ColorSpace == ColorSpaces.LAB.ToDescription()) - { - csvmodel.L1 = brushStop1.L.ToString(); - csvmodel.A1 = brushStop1.A.ToString(); - csvmodel.B1 = brushStop1.B.ToString(); - } + csv.Write(stop.Red, "RGB R", 0, cIndex++); + csv.Write(stop.Green, "RGB G", 0, cIndex++); + csv.Write(stop.Blue, "RGB B", 0, cIndex++); } - if (segment.BrushStops.Count > 1) + else if (stop.BrushColorSpace == ColorSpaces.LAB) { - var brushStop2 = segment.BrushStops[1]; - if (csvmodel.ColorSpace == ColorSpaces.RGB.ToDescription()) - { - csvmodel.Red2 = brushStop2.Red.ToString(); - csvmodel.Green2 = brushStop2.Green.ToString(); - csvmodel.Blue2 = brushStop2.Blue.ToString(); - } - else if (csvmodel.ColorSpace == ColorSpaces.Volume.ToDescription()) - { - csvmodel.Cyan2 = brushStop2.GetVolume(LiquidTypes.Cyan).ToString(); - csvmodel.Magenta2 = brushStop2.GetVolume(LiquidTypes.Magenta).ToString(); - csvmodel.Yellow2 = brushStop2.GetVolume(LiquidTypes.Yellow).ToString(); - csvmodel.Black2 = brushStop2.GetVolume(LiquidTypes.Black).ToString(); - } - else if (csvmodel.ColorSpace == ColorSpaces.Catalog.ToDescription()) - { - csvmodel.CatalogName2 = brushStop2.ColorCatalog.Name; - csvmodel.CatalogItem2 = brushStop2.ColorCatalogsItem.Name; - } - else if (csvmodel.ColorSpace == ColorSpaces.LAB.ToDescription()) + csv.Write(stop.L, "L", 0, cIndex++); + csv.Write(stop.A, "A", 0, cIndex++); + csv.Write(stop.B, "B", 0, cIndex++); + } + else if (stop.BrushColorSpace == ColorSpaces.Catalog) + { + csv.Write(stop.ColorCatalog.Name, "Catalog", String.Empty, cIndex++); + csv.Write(stop.ColorCatalogsItem.Name, "Catalog Item", String.Empty, cIndex++); + } + else + { + foreach (var liquidVolume in stop.LiquidVolumesOrderedPigmentedForStandardUser) { - csvmodel.L2 = brushStop2.L.ToString(); - csvmodel.A2 = brushStop2.A.ToString(); - csvmodel.B2 = brushStop2.B.ToString(); + csv.Write(liquidVolume.Volume, liquidVolume.IdsPack.LiquidType.DisplayName, 0, cIndex++); } } - csvFile.Append(csvmodel); + csv.Next(); } + + csv.Save(filePath); }); } } diff --git a/Software/Visual_Studio/Tango.CSV/CsvDynamicReader.cs b/Software/Visual_Studio/Tango.CSV/CsvDynamicReader.cs new file mode 100644 index 000000000..33ba859eb --- /dev/null +++ b/Software/Visual_Studio/Tango.CSV/CsvDynamicReader.cs @@ -0,0 +1,310 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; + +namespace Tango.CSV +{ + /// <summary> + /// CSV reader that supports unknown schemas and typed access with defaults. + /// - Case-insensitive column lookup + /// - Robust CSV parsing (RFC-4180 style: quotes, commas, escaped quotes) + /// - Typed Read with defaults: string, int, double, bool, and enums + /// </summary> + public sealed class CsvDynamicReader + { + private readonly Dictionary<string, int> _colIndex; + private readonly List<Row> _rows; + + public IReadOnlyList<Row> Rows => _rows; + + public char Delimiter { get; } + + public CsvDynamicReader(string path, char delimiter = ',') + { + if (path == null) throw new ArgumentNullException(nameof(path)); + if (!File.Exists(path)) throw new FileNotFoundException("CSV file not found.", path); + + Delimiter = delimiter; + _colIndex = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); + _rows = new List<Row>(); + + using (var sr = new StreamReader(path)) + { + // Read to first non-empty line for headers + string headerLine; + do + { + headerLine = sr.ReadLine(); + if (headerLine == null) + throw new InvalidDataException("CSV file has no header row."); + } while (string.IsNullOrWhiteSpace(headerLine)); + + var headers = ParseCsvLine(headerLine, Delimiter); + for (int i = 0; i < headers.Count; i++) + { + var clean = CleanHeader(headers[i]); + if (!_colIndex.ContainsKey(clean)) + _colIndex.Add(clean, i); + // If duplicate header name appears, first one wins. + } + + // Read all rows + string line; + while ((line = sr.ReadLine()) != null) + { + if (line.Length == 0) continue; // skip empty + var fields = ParseCsvLine(line, Delimiter).ToArray(); + _rows.Add(new Row(this, fields)); + } + } + } + + internal bool TryGetIndex(string columnName, out int index) + { + if (columnName == null) { index = -1; return false; } + return _colIndex.TryGetValue(columnName.Trim(), out index); + } + + private static string CleanHeader(string s) + { + if (string.IsNullOrEmpty(s)) return string.Empty; + // Trim quotes if header was quoted + var t = s.Trim(); + if (t.Length >= 2 && t[0] == '"' && t[t.Length - 1] == '"') + { + t = t.Substring(1, t.Length - 2).Replace("\"\"", "\""); + } + // Remove BOM if present + t = t.Trim('\uFEFF').Trim(); + return t; + } + + /// <summary> + /// RFC-4180-ish CSV line parser: supports quoted fields, commas, escaped quotes (""). + /// </summary> + private static List<string> ParseCsvLine(string line, char delimiter) + { + var result = new List<string>(); + if (line == null) + { + result.Add(string.Empty); + return result; + } + + var sb = new System.Text.StringBuilder(line.Length); + bool inQuotes = false; + + for (int i = 0; i < line.Length; i++) + { + var c = line[i]; + + if (inQuotes) + { + if (c == '"') + { + // Escaped quote? + if (i + 1 < line.Length && line[i + 1] == '"') + { + sb.Append('"'); + i++; // skip next + } + else + { + inQuotes = false; + } + } + else + { + sb.Append(c); + } + } + else + { + if (c == '"') + { + inQuotes = true; + } + else if (c == delimiter) + { + result.Add(sb.ToString()); + sb.Clear(); + } + else + { + sb.Append(c); + } + } + } + + result.Add(sb.ToString()); + return result; + } + + // ------- Row -------- + + public sealed class Row + { + private readonly CsvDynamicReader _reader; + private readonly string[] _values; + + internal Row(CsvDynamicReader reader, string[] values) + { + _reader = reader; + _values = values ?? new string[0]; + } + + public bool Exists(string columnName) + { + int idx; + return _reader.TryGetIndex(columnName, out idx); + } + + /// <summary> + /// Typed read with a default fallback. Works for string, int, double, bool, and enums. + /// Usage: var v = row.Read("Col", 0); var s = row.Read("Col","def"); var b = row.Read("Flag", false); + /// </summary> + public T Read<T>(string columnName, T defaultValue) + { + int idx; + if (!_reader.TryGetIndex(columnName, out idx)) + return defaultValue; + + var raw = (idx >= 0 && idx < _values.Length) ? _values[idx] : null; + return ConvertValue(raw, defaultValue); + } + + // -------- Conversion helpers -------- + + private static T ConvertValue<T>(string raw, T defaultValue) + { + if (typeof(T) == typeof(string)) + { + // For strings return raw as-is (trim optional) + object s = raw ?? (object)defaultValue ?? string.Empty; + return (T)s; + } + + if (string.IsNullOrWhiteSpace(raw)) + return defaultValue; + + var trimmed = raw.Trim(); + + // int + if (typeof(T) == typeof(int)) + { + int v; + if (int.TryParse(trimmed, NumberStyles.Integer, CultureInfo.InvariantCulture, out v)) + return (T)(object)v; + return defaultValue; + } + + // double + if (typeof(T) == typeof(double)) + { + double v; + if (double.TryParse(trimmed, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out v)) + return (T)(object)v; + return defaultValue; + } + + // bool (accepts true/false, 1/0, yes/no, y/n) + if (typeof(T) == typeof(bool)) + { + bool bv; + if (TryParseBool(trimmed, out bv)) + return (T)(object)bv; + return defaultValue; + } + + // Enums (case-insensitive; also accept underlying numeric) + var t = typeof(T); + if (t.IsEnum) + { + try + { + // Numeric? + var underlying = Enum.GetUnderlyingType(t); + object numericObj; + if (TryParseNumeric(trimmed, underlying, out numericObj)) + { + var boxed = Enum.ToObject(t, numericObj); + return (T)boxed; + } + + T parsed; + if (TryParseEnum(trimmed, out parsed)) + return parsed; + } + catch { /* fall through to default */ } + + return defaultValue; + } + + // Fallback: try ChangeType + try + { + object any = System.Convert.ChangeType(trimmed, typeof(T), CultureInfo.InvariantCulture); + return (T)any; + } + catch + { + return defaultValue; + } + } + + private static bool TryParseBool(string s, out bool value) + { + // Standard + if (bool.TryParse(s, out value)) return true; + + // Common variants + switch (s.Trim().ToLowerInvariant()) + { + case "1": + case "yes": + case "y": + case "true": + case "t": + value = true; return true; + case "0": + case "no": + case "n": + case "false": + case "f": + value = false; return true; + } + value = false; return false; + } + + private static bool TryParseNumeric(string s, Type numericType, out object boxed) + { + if (numericType == typeof(byte)) { byte v; if (byte.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out v)) { boxed = v; return true; } } + if (numericType == typeof(sbyte)) { sbyte v; if (sbyte.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out v)) { boxed = v; return true; } } + if (numericType == typeof(short)) { short v; if (short.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out v)) { boxed = v; return true; } } + if (numericType == typeof(ushort)) { ushort v; if (ushort.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out v)) { boxed = v; return true; } } + if (numericType == typeof(int)) { int v; if (int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out v)) { boxed = v; return true; } } + if (numericType == typeof(uint)) { uint v; if (uint.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out v)) { boxed = v; return true; } } + if (numericType == typeof(long)) { long v; if (long.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out v)) { boxed = v; return true; } } + if (numericType == typeof(ulong)) { ulong v; if (ulong.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out v)) { boxed = v; return true; } } + + boxed = null; + return false; + } + + private static bool TryParseEnum<T>(string s, out T value) + { + try + { + value = (T)Enum.Parse(typeof(T), s, ignoreCase: true); + return true; + } + catch + { + value = default(T); + return false; + } + } + } + } +} diff --git a/Software/Visual_Studio/Tango.CSV/CsvDynamicWriter.cs b/Software/Visual_Studio/Tango.CSV/CsvDynamicWriter.cs index 1c460d5e3..70024954e 100644 --- a/Software/Visual_Studio/Tango.CSV/CsvDynamicWriter.cs +++ b/Software/Visual_Studio/Tango.CSV/CsvDynamicWriter.cs @@ -24,6 +24,26 @@ namespace Tango.CSV private readonly List<Dictionary<string, string>> _rows = new List<Dictionary<string, string>>(); private Dictionary<string, string> _currentRow = new Dictionary<string, string>(); + public void Write(int value, string columnName, int defaultValue, int index) + { + Write(value.ToString(), columnName, defaultValue.ToString(), index); + } + + public void Write(double value, string columnName, double defaultValue, int index) + { + Write(value.ToString(), columnName, defaultValue.ToString(), index); + } + + public void Write(bool value, string columnName, bool defaultValue, int index) + { + Write(value.ToString(), columnName, defaultValue.ToString(), index); + } + + public void Write(Enum value, string columnName, Enum defaultValue, int index) + { + Write(value.ToString(), columnName, defaultValue.ToString(), index); + } + /// <summary> /// Writes a value to the specified column in the current row. /// If the column does not exist, it is created with the given default value and index. diff --git a/Software/Visual_Studio/Tango.CSV/Tango.CSV.csproj b/Software/Visual_Studio/Tango.CSV/Tango.CSV.csproj index 0fc1948a4..5674c1c56 100644 --- a/Software/Visual_Studio/Tango.CSV/Tango.CSV.csproj +++ b/Software/Visual_Studio/Tango.CSV/Tango.CSV.csproj @@ -90,6 +90,7 @@ <Compile Include="CsvSource.cs" /> <Compile Include="DynamicCsvFile.cs" /> <Compile Include="DynamicCsvFileColumn.cs" /> + <Compile Include="CsvDynamicReader.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs index 2ce4dcaa1..e8185c3d5 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs @@ -24,4 +24,4 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("3.0.26.0")] +[assembly: AssemblyVersion("3.0.27.0")] |
