using Google.Protobuf;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using Tango.BL.ActionLogs;
using Tango.BL.Builders;
using Tango.BL.Enumerations;
using Tango.BL.FineTuning;
using Tango.BL.Interfaces;
using Tango.BL.ValueObjects;
using Tango.Core;
using Tango.Core.ExtensionMethods;
using Tango.Logging;
using Tango.PMR.Exports;
namespace Tango.BL.Entities
{
public partial class Job : JobBase
{
private double _lastLength;
#region Constructors
///
/// Initializes a new instance of the class.
///
public Job() : base()
{
VectorFineTuningRunModel = new VectorFineTuningRunModel();
}
///
/// Initializes a new instance of the class.
///
public Job(DateTime creationDate) : this()
{
CreationDate = creationDate;
}
#endregion
#region Events
///
/// Occurs when the job total segments length has changed.
///
public event EventHandler LengthChanged;
#endregion
#region Properties
///
/// Gets the total job segments length.
///
[NotMapped]
[JsonIgnore]
public double Length
{
get
{
_lastLength = GetLength();
return _lastLength;
}
}
///
/// Gets the total job segments length multiplied by number of units if it is an embroidery job.
///
[NotMapped]
[JsonIgnore]
public double LengthIncludingNumberOfUnits
{
get
{
_lastLength = GetLength();
var l = _lastLength * Math.Max(NumberOfUnits, 1);
if (EnableInterSegment && NumberOfUnits > 1)
{
l += ((NumberOfUnits - 1) * InterSegmentLength);
}
return l;
}
}
[NotMapped]
[JsonIgnore]
public double LengthIncludingNumberOfUnitsAndSpools
{
get
{
if (Machine.Type == MachineTypes.Eureka)
{
if (NumberOfSpools >= 4)
{
return LengthIncludingNumberOfUnits * NumberOfSpools;
}
}
return LengthIncludingNumberOfUnits;
}
}
[NotMapped]
[JsonIgnore]
public double WeightIncludingNumberOfUnits
{
get
{
if (Rml == null)
return 0;
var gramPerlength = Rml.GetGramPer1000mLength;
var weight = (LengthIncludingNumberOfUnits * gramPerlength) / (1000);//(g)
return weight;
}
}
[NotMapped]
[JsonIgnore]
public double WeightIncludingNumberOfUnitsAndSpools
{
get
{
if (Machine.Type == MachineTypes.Eureka)
{
if (NumberOfSpools >= 4)
{
return WeightIncludingNumberOfUnits * NumberOfSpools;
}
}
return WeightIncludingNumberOfUnits;
}
}
[NotMapped]
[JsonIgnore]
public Int32 NumberOfUnitsMultipliedBySpools
{
get
{
if (Machine.Type == MachineTypes.Eureka)
{
if (NumberOfSpools >= 4)
{
return NumberOfUnits * NumberOfSpools;
}
}
return NumberOfUnits;
}
}
[NotMapped]
[JsonIgnore]
public double WeightNumberOfUnits
{
get
{
_lastLength = GetLength();
var l = _lastLength * Math.Max(NumberOfUnits, 1);
if (EnableInterSegment && NumberOfUnits > 1)
{
l += ((NumberOfUnits - 1) * InterSegmentLength);
}
return l;
}
}
///
/// Gets or sets the job property as enum instead of int.
///
[NotMapped]
[JsonIgnore]
public JobStatuses JobStatus
{
get { return (JobStatuses)Status; }
set { Status = value.ToInt32(); RaisePropertyChangedAuto(); }
}
///
/// Gets or sets the origin of the job.
///
[NotMapped]
[JsonIgnore]
public JobSource JobSource
{
get { return (JobSource)Source; }
set { Source = value.ToInt32(); RaisePropertyChangedAuto(); }
}
///
/// Gets or sets the job property as enum instead of int.
///
[NotMapped]
[JsonIgnore]
public JobTypes JobType
{
get { return (JobTypes)Type; }
set { Type = value.ToInt32(); RaisePropertyChangedAuto(); }
}
///
/// Gets or sets the job property as a property.
///
[NotMapped]
[JsonIgnore]
public bool IsAllSegmentsPerSpool
{
get { return ((SpoolsDistributions)SpoolsDistribution) == SpoolsDistributions.AllSegments; }
set
{
SpoolsDistribution = value ? SpoolsDistributions.AllSegments.ToInt32() : SpoolsDistributions.SingleSegment.ToInt32();
RaisePropertyChangedAuto();
}
}
///
/// Gets or sets the effective segments.
///
[NotMapped]
[JsonIgnore]
public ObservableCollection EffectiveSegments
{
get
{
var segments = OrderedSegmentsWithGroups;
if (EnableInterSegment && IsAllSegmentsPerSpool)
{
//int max = Segments.Max(x => x.SegmentIndex);
int max = segments.Max(x => x.SegmentIndex);
ObservableCollection effectiveSegments = new ObservableCollection();
foreach (var s in segments)
{
if (s is Segment)
{
Segment segment = s as Segment;
effectiveSegments.Add(segment);
if (s.SegmentIndex != max)
{
effectiveSegments.Add(CreateInterSegment(InterSegmentLength));
}
}
else if (s is SegmentsGroup)
{
SegmentsGroup segmentsGroup = s as SegmentsGroup;
List groupSegments = segmentsGroup.Segments.ToList();
for (int repeats = 0; repeats < segmentsGroup.Repeats; repeats++)
{
for (int i = 0; i < groupSegments.Count; i++)
{
if (repeats > 0)
{
effectiveSegments.Add(groupSegments[i].Clone());
}
else
effectiveSegments.Add(groupSegments[i]);
if (EnableInterSegment && !(repeats == (segmentsGroup.Repeats - 1) && i == (groupSegments.Count - 1)))
{
effectiveSegments.Add(CreateInterSegment(InterSegmentLength));
}
}
}
if (EnableInterSegment && segmentsGroup.SegmentIndex != max)
{
effectiveSegments.Add(CreateInterSegment(InterSegmentLength));
}
}
}
//foreach (var s in Segments.ToList().OrderBy(x => x.SegmentIndex))
//{
// effectiveSegments.Add(s);
// if (s.SegmentIndex != max)
// {
// effectiveSegments.Add(CreateInterSegment(InterSegmentLength));
// }
//}
return effectiveSegments;
}
else
{
ObservableCollection effectiveSegments = new ObservableCollection();
foreach (var s in segments)
{
if (s is Segment)
{
effectiveSegments.Add(s as Segment);
}
else if (s is SegmentsGroup)
{
SegmentsGroup segmentsGroup = s as SegmentsGroup;
List groupSegments = segmentsGroup.Segments.ToList();
for (int repeats = 0; repeats < segmentsGroup.Repeats; repeats++)
{
for (int i = 0; i < groupSegments.Count; i++)
{
if (repeats > 0)
{
effectiveSegments.Add(groupSegments[i].Clone());
}
else
effectiveSegments.Add(groupSegments[i]);
}
}
}
}
return effectiveSegments;
//return Segments.OrderBy(x => x.SegmentIndex).ToObservableCollection();
}
}
}
///
/// Gets the ordered segments.
///
[NotMapped]
[JsonIgnore]
public ObservableCollection OrderedSegments
{
get
{
return Segments.OrderBy(x => x.SegmentIndex).ToObservableCollection();
}
}
///
/// Gets the ordered segments and groups
///
[NotMapped]
[JsonIgnore]
public ObservableCollection OrderedSegmentsWithGroups
{
get
{
if (Segments == null)
return null;
List orderedSegmentsWithGroups = new List();
orderedSegmentsWithGroups.AddRange(Segments.Where(x => x.SegmentsGroupGuid == null));
orderedSegmentsWithGroups.AddRange(SegmentsGroups);
return orderedSegmentsWithGroups.OrderBy(x => x.SegmentIndex).ToObservableCollection();
// return Segments.OrderBy(x => x.SegmentIndex).ToObservableCollection();
}
}
///
/// Gets or sets the job fine tuning status.
///
[NotMapped]
[JsonIgnore]
public FineTuningStatuses JobFineTuningStatus
{
get { return (FineTuningStatuses)FineTuningStatus; }
set { FineTuningStatus = value.ToInt32(); RaisePropertyChangedAuto(); }
}
///
/// Gets or sets the job sample dye status.
///
[NotMapped]
[JsonIgnore]
public SampleDyeStatuses JobSampleDyeStatus
{
get { return (SampleDyeStatuses)SampleDyeStatus; }
set { SampleDyeStatus = value.ToInt32(); RaisePropertyChangedAuto(); }
}
private JobDesignations _designation;
///
/// Gets or sets the designation.
///
[NotMapped]
[JsonIgnore]
public JobDesignations Designation
{
get { return _designation; }
set { _designation = value; RaisePropertyChangedAuto(); }
}
///
/// Gets or sets the state of the job editing.
///
[NotMapped]
[JsonIgnore]
public EditingStates JobEditingState
{
get { return (EditingStates)EditingState; }
set { EditingState = value.ToInt32(); RaisePropertyChangedAuto(); }
}
[NotMapped]
[JsonIgnore]
public double GramPerLength { get; set; }
[NotMapped]
[JsonIgnore]
public String ThreadName
{
get { return Rml == null ? "" : Rml.DisplayName; }
}
#endregion
#region Unmapped Fine Tuning
[NotMapped]
[JsonIgnore]
public VectorFineTuningRunModel VectorFineTuningRunModel { get; set; }
[NotMapped]
[JsonIgnore]
public double ResumeStartPosition { get; set; }
#endregion
#region Event Handlers
///
/// Handles the CollectionChanged event of the Segments collection.
///
/// The source of the event.
/// The instance containing the event data.
private void Segments_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
foreach (var segment in Segments.ToList())
{
segment.PropertyChanged -= Segment_PropertyChanged;
segment.PropertyChanged += Segment_PropertyChanged;
}
OnLengthChanged();
RaisePropertyChanged(nameof(EffectiveSegments));
}
///
/// Handles the PropertyChanged event of all job segments.
///
/// The source of the event.
/// The instance containing the event data.
private void Segment_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Segment.Length))
{
OnLengthChanged();
}
else if (e.PropertyName == nameof(Segment.SegmentIndex))
{
RaisePropertyChanged(nameof(EffectiveSegments));
}
}
#endregion
#region Virtual Methods
///
/// Called when the property has been changed
///
protected virtual void OnLengthChanged()
{
if (_lastLength != GetLength())
{
RaisePropertyChanged(nameof(Length));
RaisePropertyChanged(nameof(LengthIncludingNumberOfUnits));
LengthChanged?.Invoke(this, new EventArgs());
}
}
protected override void OnRmlChanged(Rml rml)
{
base.OnRmlChanged(rml);
if (rml != null)
{
GramPerLength = Rml.GetGramPer1000mLength;
}
else
GramPerLength = 0;
RaisePropertyChanged(nameof(ThreadName));
}
#endregion
#region Override Methods
///
/// Raises the property changed event.
///
/// Name of the property.
protected override void RaisePropertyChanged(string propName)
{
base.RaisePropertyChanged(propName);
if (propName == nameof(Segments))
{
if (Segments != null)
{
Segments.CollectionChanged -= Segments_CollectionChanged;
Segments.CollectionChanged += Segments_CollectionChanged;
OnLengthChanged();
RaisePropertyChanged(nameof(EffectiveSegments));
}
}
if (propName == nameof(InterSegmentLength) || propName == nameof(EnableInterSegment) || propName == nameof(SpoolsDistribution))
{
OnLengthChanged();
RaisePropertyChanged(nameof(EffectiveSegments));
}
if (propName == nameof(ColorSpace))
{
//Make all brush stops the same color space if job color space is not null!
if (ColorSpace != null)
{
Segments.SelectMany(x => x.BrushStops).ToList().ForEach(x => x.ColorSpace = ColorSpace);
}
}
if (propName == nameof(NumberOfUnits))
{
LengthChanged?.Invoke(this, new EventArgs());
}
if (propName == nameof(LengthPercentageFactor))
{
OnLengthChanged();
Segments.ToList().ForEach(x => x.RaiseLengthWithFactorChanged());
}
if (InterSegmentLength < 1)
{
InterSegmentLength = 1;
}
}
public override Job Clone()
{
Job cloned = base.Clone();
string copy = " - Copy";
int index = 1;
string baseName = Name;
if (this.Name.Contains(copy))
{
int last = this.Name.LastIndexOf(copy);
baseName = this.Name.Substring(0, last);
string index_str = this.Name.Substring(last + copy.Length);
if (!String.IsNullOrEmpty(index_str))
{
int result;
if (int.TryParse(index_str, out result))
index = result + 1;
}
}
cloned.Name = baseName + copy + index;
cloned.CreationDate = DateTime.UtcNow;
cloned.IsSynchronized = false;
cloned.LastRun = null;
cloned.ColorSpace = ColorSpace;
cloned.Customer = Customer;
cloned.Rml = Rml;
cloned.SpoolType = SpoolType;
cloned.WindingMethod = WindingMethod;
cloned.JobStatus = JobStatuses.Draft;
cloned.Segments = Segments.Where(x => x.SegmentsGroupGuid == null).Select(x => x.Clone(cloned)).ToSynchronizedObservableCollection();
cloned.SegmentsGroups = SegmentsGroups.Select(x => x.Clone(cloned)).ToSynchronizedObservableCollection();
foreach (var segment in cloned.Segments)
{
segment.JobGuid = cloned.Guid;
segment.Job = cloned;
}
return cloned;
}
#endregion
#region Private Methods
private double GetLength()
{
var segments = OrderedSegmentsWithGroups;
if (segments == null || segments.Count == 0)
return 0;
double length = 0;
int max = segments.Max(x => x.SegmentIndex);
foreach (var s in segments)
{
if (s is Segment segment)
{
length += segment.LengthWithFactor + ((EnableInterSegment && IsAllSegmentsPerSpool && segment.SegmentIndex != max) ? InterSegmentLength : 0);
}
else if (s is SegmentsGroup segmentsGroup)
{
List groupSegments = segmentsGroup.Segments.ToList();
if (EnableInterSegment && IsAllSegmentsPerSpool)
{
for (int repeats = 0; repeats < segmentsGroup.Repeats; repeats++)
{
for (int i = 0; i < groupSegments.Count; i++)
{
length += groupSegments[i].LengthWithFactor;
if (EnableInterSegment && !(repeats == (segmentsGroup.Repeats - 1) && i == (groupSegments.Count - 1)))
{
length += InterSegmentLength;
}
}
}
if (EnableInterSegment && segmentsGroup.SegmentIndex != max)
{
length += InterSegmentLength;
}
}
else
{
length += (segmentsGroup.Segments.Sum(x => x.LengthWithFactor) * segmentsGroup.Repeats);
}
}
}
return length;
}
private double GetWeigth()
{
if (Rml == null)
return 0;
double length = GetLength();
var weight = (length * GramPerLength) / (1000);//length in m, return value in g
return weight;
}
#endregion
#region Public Methods
public BitmapSource CreateSegmentsPie(double width, double height)
{
try
{
Bitmap bmp = new Bitmap((int)width, (int)height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Transparent);
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
int fromAngle = -90;
double totalLength = 0;//Segments.Sum(x => x.Length); //Excluding inter segment.
foreach (var isegm in OrderedSegmentsWithGroups)
{
if (isegm is SegmentsGroup group)
{
foreach (var innerSegment in group.Segments)
{
totalLength += innerSegment.Length * group.Repeats;
}
}
else if (isegm is Segment segment)
{
totalLength += segment.Length;
}
}
foreach (var segm in OrderedSegmentsWithGroups)
{
if (segm is SegmentsGroup group)
{
for (int i = 0; i < group.Repeats; i++)
{
foreach (var innerSegment in group.Segments)
{
int toAngle = (int)((innerSegment.Length / totalLength) * 360d);
Rectangle rect = new Rectangle(0, 0, bmp.Width - 2, bmp.Height - 2);
g.FillPie(innerSegment.CreateGdiBrush(bmp.Width - 2, bmp.Height - 2), rect, fromAngle, toAngle);
Pen pen = new Pen(Color.Gainsboro);
g.DrawEllipse(pen, rect);
pen.Dispose();
fromAngle += toAngle;
}
}
}
else if (segm is Segment segment)
{
int toAngle = (int)((segment.Length / totalLength) * 360d);
Rectangle rect = new Rectangle(0, 0, bmp.Width - 2, bmp.Height - 2);
g.FillPie(segment.CreateGdiBrush(bmp.Width - 2, bmp.Height - 2), rect, fromAngle, toAngle);
Pen pen = new Pen(Color.Gainsboro);
g.DrawEllipse(pen, rect);
pen.Dispose();
fromAngle += toAngle;
}
}
}
var source = bmp.ToBitmapSource();
bmp.Dispose();
return source;
}
catch (Exception ex)
{
LogManager.Log(ex, $"Error occurred while trying to create job pie image for job '{Name}'.");
return null;
}
}
///
/// Adds a new solid segment.
///
public Segment AddSolidSegment()
{
return AddSolidSegment(null);
}
///
/// Adds a new solid segment.
///
public Segment AddSolidSegment(System.Windows.Media.Color? color)
{
return AddSolidSegment(color, 10);
}
///
/// Adds a new solid segment.
///
public Segment AddSolidSegment(double length)
{
return AddSolidSegment(null, length);
}
///
/// Adds a new solid segment.
///
public Segment AddSolidSegment(System.Windows.Media.Color? color, double length)
{
Segment segment = new Segment();
segment.Name = "Standard Segment";
if (OrderedSegmentsWithGroups.Count > 0)
{
segment.SegmentIndex = OrderedSegmentsWithGroups.Max(x => x.SegmentIndex) + 1;
}
else
{
segment.SegmentIndex = 1;
}
segment.Length = length;
segment.Job = this;
var stop = segment.AddBrushStop();
if (color != null)
{
stop.Color = color.Value;
}
Segments.Add(segment);
return segment;
}
///
/// Adds a new gradient segment.
///
public Segment AddGradientSegment()
{
return AddGradientSegment(10);
}
///
/// Adds a new gradient segment.
///
public Segment AddGradientSegment(double length)
{
var segment = AddSolidSegment(length);
//segment.BrushStops.Last().Color = System.Windows.Media.Colors.White;
segment.AddBrushStop();
//segment.BrushStops.Last().Color = System.Windows.Media.Colors.White;
return segment;
}
///
/// Gets the duration estimation for this job.
///
/// The process parameters.
///
public TimeSpan GetEstimatedDuration(ProcessParametersTable processParameters)
{
if (processParameters.DyeingSpeed == 0)
{
throw new ArgumentException("Process parameters dying speed cannot be zero.");
}
return TimeSpan.FromSeconds((LengthIncludingNumberOfUnits + processParameters.DryerBufferLengthMeters) / (processParameters.DyeingSpeed / 100d));
}
/////
///// Gets the duration estimation for this job.
/////
/////
//public Task GetEstimatedDuration()
//{
// return Task.Factory.StartNew(() =>
// {
// var process = GetRecommendedProcessParameters().Result;
// return GetEstimatedDuration(process);
// });
//}
///
/// Translates the job progress to time.
///
/// The progress.
/// The process parameters.
///
public static TimeSpan TranslateProgressToTime(double progress, ProcessParametersTable processParameters)
{
return TimeSpan.FromSeconds(progress / (processParameters.DyeingSpeed / 100d));
}
///
/// Creates an inter segment.
///
/// The length.
///
public static Segment CreateInterSegment(double length)
{
return new Segment()
{
IsInterSegment = true,
Length = length,
Name = "Inter Segment",
BrushStops = new SynchronizedObservableCollection()
{
new BrushStop()
{
ColorSpace = new ColorSpace() { Name = "Volume" },
Color = System.Windows.Media.Colors.White,
Red = 255,
Green = 255,
Blue = 255,
L = 100,
}
},
};
}
//public Task GetRecommendedProcessParameters()
//{
// return Task.Factory.StartNew(() =>
// {
// try
// {
// int index = ColorConversion.TangoColorConverter.GetLeastCommonProcessParametersTableIndex(Segments.SelectMany(x => x.BrushStops));
// if (index < Rml.GetActiveProcessGroup().ProcessParametersTables.Count)
// {
// return Rml.GetActiveProcessGroup().ProcessParametersTables[index];
// }
// else
// {
// return Rml.GetActiveProcessGroup().ProcessParametersTables[0];
// }
// }
// catch (Exception ex)
// {
// throw new InvalidOperationException("Could not calculate the recommended process parameters for the job.", ex);
// }
// });
//}
///
/// Creates a PMR job file from the this job based on its database data.
///
///
public Task ToJobFile()
{
return Task.Factory.StartNew(() =>
{
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
var job = new JobBuilder(db).Set(Guid).WithUser().WithRML().WithSegments().WithBrushStops().WithSegmentsGroups().Build();
var machine = new MachineBuilder(db).Set(job.MachineGuid).WithConfiguration().Build();
return CreateJobFile(job, machine);
}
});
}
///
/// Creates a PMR job file based on the current state of the object.
///
///
public JobFile ToJobFileWhenLoaded()
{
return CreateJobFile(this, Machine);
}
private static JobFile CreateJobFile(Job job, Machine machine)
{
var jobFile = new JobFile();
jobFile.ColorSpaceGuid = job.ColorSpaceGuid.ToStringOrEmpty();
jobFile.Customer = job.Customer != null ? job.Customer.Name : String.Empty;
jobFile.Description = job.Description.ToStringOrEmpty();
if (job.HasEmbroideryFile)
{
jobFile.HasEmbroideryFile = job.HasEmbroideryFile;
jobFile.EmbroideryFileData = ByteString.CopyFrom(job.EmbroideryFileData);
jobFile.EmbroideryFileName = job.EmbroideryFileName;
jobFile.EmbroideryJpeg = ByteString.CopyFrom(job.EmbroideryJpeg);
}
jobFile.EnableInterSegment = job.EnableInterSegment;
jobFile.EnableLubrication = job.EnableLubrication;
jobFile.InterSegmentLength = job.InterSegmentLength;
jobFile.LengthPercentageFactor = job.LengthPercentageFactor;
jobFile.Name = job.Name.ToStringOrEmpty();
jobFile.NumberOfUnits = job.NumberOfUnits;
jobFile.RmlGuid = job.RmlGuid;
jobFile.SampleUnitsOrMeters = job.SampleUnitsOrMeters;
jobFile.SpoolsDistribution = job.SpoolsDistribution;
jobFile.SpoolTypeGuid = job.SpoolTypeGuid;
jobFile.Type = job.Type;
jobFile.WindingMethodGuid = job.WindingMethodGuid;
jobFile.ColorCatalogGuid = job.ColorCatalogGuid.ToStringOrEmpty();
jobFile.NumberOfSpools = job.NumberOfSpools;
jobFile.Version = job.Version;
foreach (var segm in job.OrderedSegmentsWithGroups)
{
JobFileSegment s = new JobFileSegment();
if (segm is SegmentsGroup group)
{
s.Repeats = group.Repeats;
foreach (var innerSegment in group.Segments)
{
JobFileSegment innerFileSegment = new JobFileSegment();
innerFileSegment.Length = innerSegment.Length;
innerFileSegment.Name = innerSegment.Name.ToStringOrEmpty();
FillFileSegmentStops(innerFileSegment, innerSegment, machine);
s.Segments.Add(innerFileSegment);
}
}
else if (segm is Segment segment)
{
s.Length = segment.Length;
s.Name = segment.Name.ToStringOrEmpty();
FillFileSegmentStops(s, segment, machine);
}
jobFile.Segments.Add(s);
}
return jobFile;
}
private static void FillFileSegmentStops(JobFileSegment s, Segment segment, Machine machine)
{
foreach (var stop in segment.BrushStops.OrderBy(x => x.StopIndex))
{
JobFileBrushStop st = new JobFileBrushStop();
stop.MapPropertiesTo(st, MappingFlags.NoReferenceTypes | MappingFlags.NoNullStrings);
st.ColorCatalogItemGuid = stop.ColorCatalogsItemGuid.ToStringOrEmpty();
st.BestMatchR = stop.BestMatchR.HasValue ? stop.BestMatchR.Value : 0;
st.BestMatchG = stop.BestMatchG.HasValue ? stop.BestMatchG.Value : 0;
st.BestMatchB = stop.BestMatchB.HasValue ? stop.BestMatchB.Value : 0;
foreach (var idsPack in machine.Configuration.NoneEmptyIdsPacks)
{
try
{
var volume = stop.GetVolume(idsPack.PackIndex);
st.LiquidVolumes.Add(new JobFileLiquidVolume()
{
LiquidTypeName = idsPack.LiquidType.Name,
Volume = volume,
});
}
catch (Exception ex)
{
throw new InvalidOperationException($"Error extracting liquid volume from ids pack {idsPack.PackIndex}", ex);
}
}
s.BrushStops.Add(st);
}
}
public static Task FromJobFile(JobFile jobFile, String machineGuid, String userGuid)
{
return Task.Factory.StartNew(() =>
{
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
Machine machine;
var job = new Job();
job.MachineGuid = machineGuid;
job.UserGuid = userGuid;
job.CreationDate = DateTime.UtcNow;
try
{
machine = new MachineBuilder(db).Set(machineGuid).WithConfiguration().Build();
}
catch
{
throw new ArgumentException("Error loading the machine details.");
}
if (!String.IsNullOrEmpty(jobFile.ColorSpaceGuid))
{
var job_color_space = db.ColorSpaces.SingleOrDefault(x => x.Guid == jobFile.ColorSpaceGuid);
if (job_color_space == null) throw new ArgumentException("Could not load the specified job file. Job color space could not be located on database.");
job.ColorSpaceGuid = jobFile.ColorSpaceGuid;
}
if (!String.IsNullOrEmpty(jobFile.ColorCatalogGuid))
{
var job_color_catalog = db.ColorCatalogs.SingleOrDefault(x => x.Guid == jobFile.ColorCatalogGuid);
if (job_color_catalog == null) throw new ArgumentException("Could not load the specified job file. Job color catalog could not be located on database.");
job.ColorCatalogGuid = jobFile.ColorCatalogGuid;
}
var job_customer = db.Customers.FirstOrDefault(x => x.Name == jobFile.Customer);
if (job_customer != null)
{
job.CustomerGuid = job_customer.Guid;
}
job.Description = jobFile.Description.ToNullIfEmpty();
if (jobFile.HasEmbroideryFile)
{
job.HasEmbroideryFile = jobFile.HasEmbroideryFile;
job.EmbroideryFileData = jobFile.EmbroideryFileData.ToByteArray();
job.EmbroideryFileName = jobFile.EmbroideryFileName;
job.EmbroideryJpeg = jobFile.EmbroideryJpeg.ToByteArray();
}
job.EnableInterSegment = jobFile.EnableInterSegment;
job.EnableLubrication = jobFile.EnableLubrication;
job.InterSegmentLength = jobFile.InterSegmentLength;
job.LengthPercentageFactor = jobFile.LengthPercentageFactor;
job.Name = jobFile.Name.ToNullIfEmpty();
job.NumberOfUnits = jobFile.NumberOfUnits;
job.NumberOfSpools = jobFile.NumberOfSpools;
job.Version = jobFile.Version;
var job_rml = db.Rmls.SingleOrDefault(x => x.Guid == jobFile.RmlGuid);
if (job_rml == null) throw new ArgumentException("Could not load the specified job file. Job media type could not be located on database.");
job.RmlGuid = jobFile.RmlGuid;
job.SampleUnitsOrMeters = jobFile.SampleUnitsOrMeters;
job.SpoolsDistribution = jobFile.SpoolsDistribution;
var job_spool_type = db.SpoolTypes.SingleOrDefault(x => x.Guid == jobFile.SpoolTypeGuid);
if (job_spool_type == null) throw new ArgumentException("Could not load the specified job file. Job spool type could not be located on database.");
job.SpoolTypeGuid = jobFile.SpoolTypeGuid;
job.Type = jobFile.Type;
var job_winding_method = db.WindingMethods.Single(x => x.Guid == jobFile.WindingMethodGuid);
if (job_winding_method == null) throw new ArgumentException("Could not load the specified job file. Job winding method could not be located on database.");
job.WindingMethodGuid = jobFile.WindingMethodGuid;
for (int i = 0; i < jobFile.Segments.Count; i++)
{
var segment = jobFile.Segments[i];
if (segment.IsGroup())
{
SegmentsGroup group = new SegmentsGroup();
group.JobGuid = job.Guid;
group.SegmentIndex = i + 1;
group.Repeats = segment.Repeats;
job.SegmentsGroups.Add(group);
for (int innerSegmentIndex = 0; innerSegmentIndex < segment.Segments.Count; innerSegmentIndex++)
{
var innerSegment = segment.Segments[innerSegmentIndex];
Segment s = new Segment();
s.JobGuid = job.Guid;
s.Name = innerSegment.Name.ToNullIfEmpty();
s.Length = innerSegment.Length;
s.SegmentIndex = innerSegmentIndex + 1;
group.Segments.Add(s);
FillSegmentStops(innerSegment, s, db, machine);
}
}
else
{
Segment s = new Segment();
s.JobGuid = job.Guid;
s.Name = segment.Name.ToNullIfEmpty();
s.Length = segment.Length;
s.SegmentIndex = i + 1;
job.Segments.Add(s);
FillSegmentStops(segment, s, db, machine);
}
}
return job;
}
});
}
private static void FillSegmentStops(JobFileSegment segment, Segment s, ObservablesContext db, Machine machine)
{
for (int j = 0; j < segment.BrushStops.Count; j++)
{
var stop = segment.BrushStops[j];
var stop_color_space = db.ColorSpaces.SingleOrDefault(x => x.Guid == stop.ColorSpaceGuid);
if (stop_color_space == null) throw new ArgumentException("Could not load the specified job file. Job brush stop color space could not be located on database.");
BrushStop st = new BrushStop();
st.StopIndex = stop.StopIndex;
st.SegmentGuid = s.Guid;
stop.MapPropertiesTo(st, MappingFlags.NoReferenceTypes | MappingFlags.NoNullStrings);
foreach (var volume in stop.LiquidVolumes)
{
var idsPack = machine.Configuration.NoneEmptyIdsPacks.SingleOrDefault(x => x.LiquidType.Name == volume.LiquidTypeName);
if (idsPack == null)
{
throw new InvalidOperationException($"Liquid type '{volume.LiquidTypeName}' is not configured on the target machine.");
}
st.SetVolume(idsPack.PackIndex, volume.Volume);
}
if (!String.IsNullOrWhiteSpace(stop.ColorCatalogGuid))
{
var stop_color_catalog = db.ColorCatalogs.SingleOrDefault(x => x.Guid == stop.ColorCatalogGuid);
if (stop_color_catalog == null) throw new ArgumentException("Could not load the specified job file. Job brush stop color catalog could not be located on database.");
stop.ColorCatalogGuid = stop_color_catalog.Guid;
}
if (!String.IsNullOrWhiteSpace(stop.ColorCatalogItemGuid))
{
var stop_color_catalog_item = db.ColorCatalogsItems.SingleOrDefault(x => x.Guid == stop.ColorCatalogItemGuid);
if (stop_color_catalog_item == null) throw new ArgumentException("Could not load the specified job file. Job brush stop catalog color could not be located on database.");
st.ColorCatalogsItemGuid = stop.ColorCatalogItemGuid;
}
s.BrushStops.Add(st);
}
s.UpdateMiddleColorBrush();
}
///
/// Removes this entity and all dependent entities from the specified db context.
///
/// The context.
public override void Delete(ObservablesContext context)
{
base.Delete(context);
Segments.ToList().ForEach(x => x.Delete(context));
SegmentsGroups.ToList().ForEach(x => x.Delete(context));
context.Jobs.Remove(this);
}
#endregion
#region Validation
protected override void OnValidating(ObservablesContext context)
{
base.OnValidating(context);
if (String.IsNullOrWhiteSpace(Name))
{
InsertError(nameof(Name), "Job name is required");
}
if (Name != null && Name.Length > 100)
{
InsertError(nameof(Name), "The job name exceeds the maximum allowed characters.");
}
}
#endregion
}
}