using LibGit2Sharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.Core;
namespace Tango.Git
{
public class GitRepositoryManager : IDisposable
{
private Repository _repo;
private String _pat;
private String _userEmail;
private String _localFolder;
public event EventHandler<TangoProgressChangedEventArgs<double>> Progress;
public GitRepositoryManager(String localFolder, String userEmail, String personalAccessToken)
{
_pat = personalAccessToken;
_userEmail = userEmail;
_localFolder = localFolder;
_repo = new Repository(_localFolder);
}
public void CreatePushTag(String name, String description, String userName)
{
var tag = _repo.ApplyTag(name, new Signature(userName, _userEmail, DateTime.Now), description);
_repo.Network.Push(_repo.Network.Remotes.First(), tag.CanonicalName, new PushOptions()
{
CredentialsProvider = new LibGit2Sharp.Handlers.CredentialsHandler(CredentialsHandlerMethod),
OnPushTransferProgress = new LibGit2Sharp.Handlers.PushTransferProgressHandler(PushTagProgressHandlerMethod)
});
}
public void Commit(String message)
{
ExecuteGitProcess($"commit -a -m \"{message}\"");
}
public void Pull()
{
ExecuteGitProcess($"pull");
}
public void Push()
{
ExecuteGitProcess($"push");
}
public void Sync()
{
Pull();
Push();
}
private bool PushTagProgressHandlerMethod(int current, int total, long bytes)
{
//TODO: Implement via TangoProgress & event...
RaiseProgress("Pushing Tag...", false, 0, total);
return true;
}
public List<GitCommit> GetOutgoingCommits()
{
List<GitCommit> commits = new List<GitCommit>();
var branch = _repo.Head.TrackedBranch;
if (branch.TrackingDetails.AheadBy != null)
{
foreach (var commit in _repo.Commits.Take(branch.TrackingDetails.AheadBy.Value))
{
commits.Add(new GitCommit()
{
Message = commit.Message
});
}
}
return commits;
}
public List<GitCommit> GetIncomingCommits()
{
List<GitCommit> commits = new List<GitCommit>();
var trackingBranch = _repo.Head.TrackedBranch;
var log = _repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = trackingBranch.Tip.Id, ExcludeReachableFrom = _repo.Head.Tip.Id });
var count = log.Count();
foreach (var commit in log)
{
commits.Add(new GitCommit()
{
Message = commit.Message
});
}
return commits;
}
public List<GitFile> GetChanges()
{
List<GitFile> files = new List<GitFile>();
var status = _repo.RetrieveStatus();
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.BL.Entities;
using Tango.Core;
using Tango.Logging;
using Tango.PMR.Printing;
namespace Tango.Integration.Operation
{
/// <summary>
/// Represents a <see cref="MachineOperator"/> job handler.
/// </summary>
/// <seealso cref="Tango.Core.ExtendedObject" />
public class JobHandler : ExtendedObject
{
protected Action _cancelAction;
protected List<Segment> _effectiveSegments;
protected String _lastStatusMessage;
protected int _last_unit;
protected bool _finalizing;
protected JobHandlerModes _mode;
protected double _last_progress;
protected const int PROGRESS_REPORT_RANGE_METERS = 5;
protected bool loggedContinueMessage;
#region Events
/// <summary>
/// Occurs when a job status has been received.
/// </summary>
public event EventHandler<RunningJobStatus> StatusChanged;
/// <summary>
/// Occurs when the job has failed.
/// </summary>
public event EventHandler<Exception> Failed;
/// <summary>
/// Occurs when the job has completed successfully.
/// </summary>
public event EventHandler Completed;
/// <summary>
/// Occurs when the job has been canceled.
/// </summary>
public event EventHandler Canceled;
/// <summary>
/// Occurs when the job has been canceled, failed or completed.
/// </summary>
public event EventHandler Stopped;
/// <summary>
/// Occurs when rolling the dryer buffer.
/// </summary>
public event EventHandler Finalizing;
/// <summary>
/// Occurs when a segment has started.
/// </summary>
public event EventHandler<Segment> SegmentStarted;
/// <summary>
/// Occurs when a segment has completed.
/// </summary>
public event EventHandler<Segment> SegmentCompleted;
/// <summary>
/// Occurs when a unit completes.
/// </summary>
public event EventHandler<int> UnitCompleted;
/// <summary>
/// Occurs when the job is set to 1 segment per spool and it's time to replace the spool.
/// </summary>
public event EventHandler<SpoolChangeRequiredEventArgs> SpoolChangeRequired;
/// <summary>
/// Occurs when <see cref="CanCancel"/> has changed.
/// </summary>
public event EventHandler CanCancelChanged;
#endregion
#region Properties
private JobStatus _jobStatus;
/// <summary>
/// Gets or sets the current job status that was used to invalidate this handler.
/// </summary>
public JobStatus JobStatus
{
get { return _jobStatus; }
set { _jobStatus = value; RaisePropertyChangedAuto(); }
}
/// <summary>
/// Gets a value indicating whether this handler job has been canceled.
/// </summary>
public bool IsCanceled { get; internal set; }
private bool _canCancel;
/// <summary>
/// Gets a value indicating whether the job can be canceled.
/// </summary>
public bool CanCancel
{
get { return _canCancel; }
internal set { _canCancel = value; RaisePropertyChangedAuto(); CanCancelChanged?.Invoke(this, new EventArgs()); }
}
/// <summary>
/// Gets the process parameters.
/// </summary>
public ProcessParametersTable ProcessParameters { get; private set; }
private RunningJobStatus _Status;
/// <summary>
/// Gets the current status.
/// </summary>
public RunningJobStatus Status
{
get { return _Status; }
internal set { _Status = value; RaisePropertyChangedAuto(); }
}
/// <summary>
/// Gets the job.
/// </summary>
public Job Job { get; private set; }
/// <summary>
/// Gets the PMR job ticket.
/// </summary>
public JobTicket JobTicket { get; private set; }
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="JobHandler"/> class.
/// </summary>
public JobHandler()
{
CanCancel = true;
}
/// <summary>
/// Initializes a new instance of the <see cref="JobHandler"/> class.
/// </summary>
/// <param name="cancelAction">The cancel action.</param>
public JobHandler(Action cancelAction, Job job, JobTicket jobTicket, ProcessParametersTable processParameters, JobHandlerModes mode) : this()
{
_mode = mode;
ProcessParameters = processParameters;
Job = job;
JobTicket = jobTicket;
foreach (var s in Job.Segments)
{
s.Started = false;
s.Completed = false;
s.RemainingTime = TimeSpan.FromSeconds(0);
}
_effectiveSegments = Job.EffectiveSegments.ToList();
_cancelAction = () => { cancelAction(); };
Status = new RunningJobStatus();
Status.TotalTime = job.GetEstimatedDuration(processParameters);
Status.RemainingUnits = job.NumberOfUnits;
Status.TotalProgress = Job.LengthIncludingNumberOfUnits + processParameters.DryerBufferLengthMeters;
Status.FinalizingTotalProgress = processParameters.DryerBufferLengthMeters;
Status.TotalProgressWithoutFinalization = Job.LengthIncludingNumberOfUnits;
Status.Progress = 0;
Status.RemainingTime = Status.TotalTime;
Status.RemainingProgress = Status.TotalProgress;
Status.CurrentUnitSegments = _effectiveSegments.ToList();
Status.SettingUpTotalProgress = processParameters.DryerBufferLengthMeters;
Status.TotalProgressMinusSettingUp = Job.LengthIncludingNumberOfUnits;
Status.IsSettingUp = true;
if (mode == JobHandlerModes.Finalization)
{
Status.CurrentUnitTotalProgress = Job.Length;
}
else
{
Status.CurrentUnitTotalProgress = Status.SettingUpTotalProgress;
}
if (Job.EnableInterSegment && Job.NumberOfUnits > 1)
{
Status.CurrentUnitSegments.Add(Job.CreateInterSegment(Job.InterSegmentLength));
}
//Create all segments
int segment_index = 1;
for (int j = 0; j < Math.Max(Job.NumberOfUnits, 1); j++)
{
for (int i = 0; i < _effectiveSegments.Count; i++)
{
Segment seg = _effectiveSegments[i].Clone();
seg.EstimatedDuration = seg.GetEstimatedDuration(processParameters);
seg.SegmentIndex = segment_index++;
Status.Segments.Add(seg);
}
if (Job.EnableInterSegment)
{
var inter_segment = Job.CreateInterSegment(Job.InterSegmentLength);
inter_segment.SegmentIndex = segment_index++;
Status.Segments.Add(inter_segment);
}
}
var last_segment = Status.Segments.Last();
if (last_segment.IsInterSegment)
{
Status.Segments.Remove(last_segment);
}
Status.CurrentSegment = Status.Segments.First();
}
#endregion
#region Internal Methods
/// <summary>
/// Raises the status received event.
/// </summary>
/// <param name="status">The status.</param>
public void RaiseStatusReceived(JobStatus status)
{
InvalidateJobProgress(status);
}
/// <summary>
/// Raises the failed event.
/// </summary>
/// <param name="ex">The ex.</param>
public void RaiseFailed(Exception ex)
{
LogManager.Log($"Job failed at position {Status.Progress}/{Status.TotalProgress}...");
Status.IsFailed = true;
RaiseStatusChanged();
RaisePropertyChanged(nameof(Status));
Failed?.Invoke(this, ex);
Stopped?.Invoke(this, new EventArgs());
}
/// <summary>
/// Raises the completed event.
/// </summary>
public void RaiseCompleted()
{
//This will compensate on any missing progress from Shlomo, but also will tell the wrong progress if job is really completed with a large progress mistake.
// Might be worth to compensate only on small drifts like the below (ProgressMinusSettingsUp)...
//InvalidateJobProgress(new JobStatus()
//{
// Progress = Status.TotalProgress,
// CurrentSegmentIndex = 0,
//});
LogManager.Log($"Job completed at position {Status.Progress}/{Status.TotalProgress}...");
//If drift is smaller than 10cm auto correct it.
if (Math.Abs(Status.TotalProgressMinusSettingUp - Status.ProgressMinusSettingUp) < 0.1)
{
LogManager.Log($"Job completed with a small drift in the progress minus setting up calculation. ({Status.ProgressMinusSettingUp}/{Status.TotalProgressMinusSettingUp}). Compensating...");
Status.ProgressMinusSettingUp = Status.TotalProgressMinusSettingUp;
}
//If the overall progress is correct? Fix the minus setting up. There is a problem with the delta calc!
else if (Status.Progress == Status.TotalProgress)
{
LogManager.Log($"Job completed with a small drift in the progress minus setting up calculation but the overall progress seems OK. ({Status.ProgressMinusSettingUp}/{Status.TotalProgressMinusSettingUp}). Compensating...");
Status.ProgressMinusSettingUp = Status.TotalProgressMinusSettingUp;
}
Status.Segments.Last().Completed = true;
Status.RemainingUnits = 0;
Status.IsFinalizing = false;
Status.IsCompleted = true;
RaiseStatusChanged();
RaisePropertyChanged(nameof(Status));
Completed?.Invoke(this, new EventArgs());
Stopped?.Invoke(this, new EventArgs());
}
/// <summary>
/// Raises the canceled event.
/// </summary>
public void RaiseCanceled()
{
LogManager.Log($"Job canceled at position {Status.Progress}/{Status.TotalProgress}...");
Status.IsCanceled = true;
RaiseStatusChanged();
RaisePropertyChanged(nameof(Status));
Canceled?.Invoke(this, new EventArgs());
Stopped?.Invoke(this, new EventArgs());
}
/// <summary>
/// Raises the spool change required event.
/// </summary>
internal void RaiseSpoolChangeRequired(Action confirmAction, Action abortAction)
{
SpoolChangeRequired?.Invoke(this, new SpoolChangeRequiredEventArgs(confirmAction, abortAction)
{
CurrentSegment = Status.CurrentSegment.SegmentIndex,
TotalSegments = Status.Segments.Count,
});
}
#endregion
#region Private Methods
//protected virtual void InvalidateJobProgress(JobStatus s)
//{
// JobStatus = s;
// bool invalidProgress = false;
// if (_last_progress != s.Progress)
// {
// if (s.Progress <= PROGRESS_REPORT_RANGE_METERS || s.Progress >= Status.TotalProgress - PROGRESS_REPORT_RANGE_METERS)
// {
// LogManager.Log($"Updating job progress {s.Progress}/{Status.TotalProgress}...");
// }
// else if (!loggedContinueMessage)
// {
// loggedContinueMessage = true;
// LogManager.Log($"Progress logging will continue {PROGRESS_REPORT_RANGE_METERS} meters before completion...");
// }
// }
// if (s.Progress < 0)
// {
// LogManager.Log($"Invalid job progress received '{s.Progress}'.", LogCategory.Error);
// invalidProgress = true;
// }
// if (s.Progress > Status.TotalProgress)
// {
// LogManager.Log($"Invalid job progress received '{s.Progress}' while total progress is '{Status.TotalProgress}'.", LogCategory.Error);
// invalidProgress = true;
// }
// if (s.Progress < _last_progress)
// {
// LogManager.Log($"Invalid job progress received '{s.Progress}' while last progress was '{_last_progress}'.");
// invalidProgress = true;
// }
// if (invalidProgress)
// {
// return;
// }
// _last_progress = s.Progress;
// //Job Status
// if (IsCanceled)
// {
// Status.IsCanceled = IsCanceled;
// RaiseStatusChanged();
// return;
// }
// List<Segment> unit_segments = new List<Segment>();
// double delta = s.Progress - Status.Progress;
// Status.Progress = s.Progress;
// Status.RemainingTime = Status.TotalTime - Job.TranslateProgressToTime(Status.Progress, ProcessParameters);
// Status.RemainingProgress = Status.TotalProgress - Status.Progress;
// if (Status.SettingUpProgress < Status.SettingUpTotalProgress)
// {
// Status.SettingUpProgress += delta;
// }
// else
// {
// if (Status.IsSettingUp && Status.Progress > 0)
// {
// Status.IsSettingUp = false;
// }
// Status.ProgressMinusSettingUp += delta;
// }
// if (s.Progress < Job.LengthIncludingNumberOfUnits || _mode == JobHandlerModes.SettingUp)
// {
// Status.ProgressWithoutFinalization += delta;
// unit_segments = _effectiveSegments.ToList();
// if (Job.EnableInterSegment && Job.NumberOfUnits > 1 && Status.RemainingUnits > 1)
// {
// unit_segments.Add(Job.CreateInterSegment(Job.InterSegmentLength));
// }
// if (unit_segments.Count != Status.CurrentUnitSegments.Count)
// {
// Status.CurrentUnitSegments = unit_segments;
// }
// Status.CurrentUnitTotalProgress = Status.RemainingUnits > 1 && Job.EnableInterSegment ? Job.Length + (Job.InterSegmentLength) : Job.Length;
// if (_mode == JobHandlerModes.Finalization)
// {
// Status.CurrentUnitProgress += delta;
// }
// else
// {
// if (!Status.IsSettingUp)
// {
// Status.CurrentUnitProgress += delta;
// }
// }
// if (Status.CurrentUnitProgress >= Status.CurrentUnitTotalProgress)
// {
// Status.CurrentUnitProgress = 0;
// Status.CurrentUnit++;
// }
// Status.RemainingUnits = Job.NumberOfUnits - Status.CurrentUnit;
// if (s.Message != _lastStatusMessage && s.Message != String.Empty)
// {
// Status.Message = s.Message;
// }
// else
// {
// Status.Message = null;
// }
// _lastStatusMessage = s.Message;
// RaiseStatusChanged();
// //Segments Completion
// if (Status.CurrentUnit > _last_unit)
// {
// foreach (var segment in Status.CurrentUnitSegments)
// {
// segment.Started = false;
// segment.Completed = false;
// }
// if (Job.NumberOfUnits > 1)
// {
// RaiseUnitCompleted(_last_unit);
// }
// }
// _last_unit = Status.CurrentUnit;
// for (int i = 0; i < Status.CurrentUnitSegments.Count; i++)
// {
// Segment segment = Status.CurrentUnitSegments[i];
// double previousSegmentsLengthWithThis = Status.CurrentUnitSegments.Take(i + 1).Sum(x => x.LengthWithFactor);
// TimeSpan segmentsDuration = Job.TranslateProgressToTime(previousSegmentsLengthWithThis, ProcessParameters);
// TimeSpan segmentRemainingTime = segmentsDuration - Job.TranslateProgressToTime(Status.CurrentUnitProgress, ProcessParameters);
// if (i == 0 && Status.CurrentUnitProgress > 0)
// {
// if (!segment.Started)
// {
// segment.Started = true;
// RaiseSegmentStarted(segment);
// }
// }
// if (Status.CurrentUnitProgress >= previousSegmentsLengthWithThis)
// {
// if (!segment.Completed)
// {
// segment.Completed = true;
// RaiseSegmentCompleted(segment);
// }
// if (i < Status.CurrentUnitSegments.Count - 1)
// {
// if (!Status.CurrentUnitSegments[i + 1].Started)
// {
// Status.CurrentUnitSegments[i + 1].Started = true;
// RaiseSegmentStarted(Status.CurrentUnitSegments[i + 1]);
// }
// }
// }
// if (segment.Started && !segment.Completed)
// {
// segment.RemainingTime = segmentRemainingTime;
// }
// }
// //Set Segment Completion for All Segments List
// for (int i = 0; i < Status.Segments.Count; i++)
// {
// Segment segment = Status.Segments[i];
// double previousSegmentsLengthWithThis = Status.Segments.Take(i + 1).Sum(x => x.LengthWithFactor);
// TimeSpan segmentsDuration = Job.TranslateProgressToTime(previousSegmentsLengthWithThis, ProcessParameters);
// TimeSpan segmentRemainingTime = segmentsDuration - Job.TranslateProgressToTime(Status.Progress, ProcessParameters);
// segment.Progress = Math.Min(Math.Max((previousSegmentsLengthWithThis - segment.Length - Status.Progress) * -1, 0), segment.Length);
// if (i == 0 && Status.Progress > 0)
// {
// if (!segment.Started)
// {
// segment.Started = true;
// Status.CurrentSegment = segment;
// }
// }
// if (Status.Progress >= previousSegmentsLengthWithThis)
// {
// if (!segment.Completed)
// {
// segment.Completed = true;
// }
// if (i < Status.Segments.Count - 1)
// {
// if (!Status.Segments[i + 1].Started)
// {
// Status.Segments[i + 1].Started = true;
// Status.CurrentSegment = Status.Segments[i + 1];
// }
// }
// }
// if (segment.Started && !segment.Completed)
// {
// segment.RemainingTime = segmentRemainingTime;
// }
// }
// }
// else
// {
// //Finalizing
// if (!_finalizing)
// {
// _finalizing = true;
// Status.IsFinalizing = true;
// var last_Segment = _effectiveSegments.Last().Clone();
// last_Segment.Length = ProcessParameters.DryerBufferLengthMeters;
// Status.CurrentUnitSegments = new List<Segment> { last_Segment };
// Status.CurrentUnitTotalProgress = last_Segment.Length;
// Status.CurrentUnitProgress = 0;
// Status.ProgressWithoutFinalization = Status.TotalProgressWithoutFinalization;
// RaiseFinalizing();
// }
// Status.CurrentUnitProgress += delta;
// Status.FinalizingProgress += delta;
// }
//}
protected virtual void InvalidateJobProgress(JobStatus s)
{
JobStatus = s;
if (_last_progress != s.Progress)
{
if (s.Progress <= PROGRESS_REPORT_RANGE_METERS || s.Progress >= Status.TotalProgress - PROGRESS_REPORT_RANGE_METERS)
{
LogManager.Log($"Updating job progress {s.Progress}/{Status.TotalProgress}...");
}
else if (!loggedContinueMessage)
{
loggedContinueMessage = true;
LogManager.Log($"Progress logging will continue {PROGRESS_REPORT_RANGE_METERS} meters before completion...");
}
}
if (s.Progress < 0)
{
LogManager.Log($"Invalid job progress received '{s.Progress}'.", LogCategory.Error);
return;
}
if (s.Progress > Status.TotalProgress)
{
LogManager.Log($"Invalid job progress received '{s.Progress}' while total progress is '{Status.TotalProgress}'.", LogCategory.Error);
return;
}
if (s.Progress < _last_progress)
{
LogManager.Log($"Invalid job progress received '{s.Progress}' while last progress was '{_last_progress}'.");
}
_last_progress = s.Progress;
List<Segment> unit_segments = new List<Segment>();
Status.Progress = s.Progress;
Status.RemainingTime = Status.TotalTime - Job.TranslateProgressToTime(Status.Progress, ProcessParameters);
Status.RemainingProgress = Status.TotalProgress - Status.Progress;
if (s.Progress < Status.SettingUpTotalProgress || Status.SettingUpProgress < Status.SettingUpTotalProgress)
{
Status.SettingUpProgress = Math.Min(s.Progress, this.Status.SettingUpTotalProgress);
Status.IsSettingUp = true;
}
if (s.Progress >= Status.SettingUpTotalProgress)
{
if (Status.IsSettingUp && Status.Progress > 0)
{
Status.IsSettingUp = false;
}
Status.ProgressMinusSettingUp = s.Progress - this.Status.SettingUpTotalProgress;
}
int units = (int)Math.Max(Job.NumberOfUnits, 1);
if (s.Progress < Job.LengthIncludingNumberOfUnits || _mode == JobHandlerModes.SettingUp)
{
Status.ProgressWithoutFinalization = s.Progress;
unit_segments = _effectiveSegments.ToList();
Status.CurrentUnitProgress = 0.0;
double previousUnitsLengthWithoutThis = 0.0;
for (int index = 0; index < units; ++index)
{
Status.CurrentUnit = index;
double unitLength = !Job.EnableInterSegment || index >= units - 1 ? Job.Length : Job.Length + Job.InterSegmentLength;
if (_mode == JobHandlerModes.Finalization)
{
if (s.Progress < unitLength + previousUnitsLengthWithoutThis)
{
Status.CurrentUnitProgress = s.Progress - previousUnitsLengthWithoutThis;
break;
}
}
else if (s.Progress <= previousUnitsLengthWithoutThis + unitLength + Status.SettingUpProgress)
{
if (!Status.IsSettingUp)
{
Status.CurrentUnitProgress = s.Progress - previousUnitsLengthWithoutThis - this.Status.SettingUpProgress;
break;
}
break;
}
previousUnitsLengthWithoutThis += unitLength;
}
Status.RemainingUnits = this.Job.NumberOfUnits - this.Status.CurrentUnit;
if (Job.EnableInterSegment && Job.NumberOfUnits > 1 && Status.RemainingUnits > 1)
{
unit_segments.Add(Job.CreateInterSegment(Job.InterSegmentLength));
}
if (unit_segments.Count != Status.CurrentUnitSegments.Count)
{
Status.CurrentUnitSegments = unit_segments;
}
Status.CurrentUnitTotalProgress = Status.RemainingUnits > 1 && Job.EnableInterSegment ? Job.Length + (Job.InterSegmentLength) : Job.Length;
if (s.Message != _lastStatusMessage && s.Message != String.Empty)
{
Status.Message = s.Message;
}
else
{
Status.Message = null;
}
_lastStatusMessage = s.Message;
RaiseStatusChanged();
//Segments Completion
if (Status.CurrentUnit > _last_unit)
{
foreach (var segment in Status.CurrentUnitSegments)
{
segment.Started = false;
segment.Completed = false;
}
if (Job.NumberOfUnits > 1)
{
RaiseUnitCompleted(_last_unit);
}
}
_last_unit = Status.CurrentUnit;
for (int i = 0; i < Status.CurrentUnitSegments.Count; i++)
{
Segment segment = Status.CurrentUnitSegments[i];
double previousSegmentsLengthWithThis = Status.CurrentUnitSegments.Take(i + 1).Sum(x => x.LengthWithFactor);
TimeSpan segmentsDuration = Job.TranslateProgressToTime(previousSegmentsLengthWithThis, ProcessParameters);
TimeSpan segmentRemainingTime = segmentsDuration - Job.TranslateProgressToTime(Status.CurrentUnitProgress, ProcessParameters);
if (i == 0 && Status.CurrentUnitProgress > 0)
{
if (!segment.Started)
{
segment.Started = true;
RaiseSegmentStarted(segment);
}
}
if (Status.CurrentUnitProgress >= previousSegmentsLengthWithThis)
{
if (!segment.Completed)
{
segment.Completed = true;
RaiseSegmentCompleted(segment);
}
if (i < Status.CurrentUnitSegments.Count - 1)
{
if (!Status.CurrentUnitSegments[i + 1].Started)
{
Status.CurrentUnitSegments[i + 1].Started = true;
RaiseSegmentStarted(Status.CurrentUnitSegments[i + 1]);
}
}
}
if (segment.Started && !segment.Completed)
{
segment.RemainingTime = segmentRemainingTime;
}
}
//Set Segment Completion for All Segments List
for (int i = 0; i < Status.Segments.Count; i++)
{
Segment segment = Status.Segments[i];
double previousSegmentsLengthWithThis = Status.Segments.Take(i + 1).Sum(x => x.LengthWithFactor);
TimeSpan segmentsDuration = Job.TranslateProgressToTime(previousSegmentsLengthWithThis, ProcessParameters);
TimeSpan segmentRemainingTime = segmentsDuration - Job.TranslateProgressToTime(Status.Progress, ProcessParameters);
segment.Progress = Math.Min(Math.Max((previousSegmentsLengthWithThis - segment.Length - Status.Progress) * -1, 0), segment.Length);
if (i == 0 && Status.Progress > 0)
{
if (!segment.Started)
{
segment.Started = true;
Status.CurrentSegment = segment;
}
}
if (Status.Progress >= previousSegmentsLengthWithThis)
{
if (!segment.Completed)
{
segment.Completed = true;
}
if (i < Status.Segments.Count - 1)
{
if (!Status.Segments[i + 1].Started)
{
Status.Segments[i + 1].Started = true;
Status.CurrentSegment = Status.Segments[i + 1];
}
}
}
if (segment.Started && !segment.Completed)
{
segment.RemainingTime = segmentRemainingTime;
}
}
}
else
{
//Finalizing
if (!_finalizing)
{
_finalizing = true;
Status.IsFinalizing = true;
var last_Segment = _effectiveSegments.Last().Clone();
last_Segment.Length = ProcessParameters.DryerBufferLengthMeters;
Status.CurrentUnitSegments = new List<Segment> { last_Segment };
Status.CurrentUnitTotalProgress = last_Segment.Length;
Status.CurrentUnitProgress = 0;
Status.ProgressWithoutFinalization = Status.TotalProgressWithoutFinalization;
RaiseFinalizing();
}
Status.CurrentUnitProgress = s.Progress - Job.LengthIncludingNumberOfUnits;
Status.FinalizingProgress = s.Progress - Status.TotalProgressWithoutFinalization;
}
}
#endregion
#region Protected Methods
protected void RaiseStatusChanged()
{
StatusChanged?.Invoke(this, Status);
}
protected void RaiseSegmentStarted(Segment segment)
{
if (segment.IsInterSegment)
{
LogManager.Log($"Inter Segment started.");
}
else
{
LogManager.Log($"Segment {segment.SegmentIndex} of unit {Status.CurrentUnit + 1} started...");
}
SegmentStarted?.Invoke(this, segment);
}
protected void RaiseSegmentCompleted(Segment segment)
{
if (segment.IsInterSegment)
{
LogManager.Log($"Inter Segment completed.");
}
else
{
LogManager.Log($"Segment {segment.SegmentIndex} of unit {Status.CurrentUnit + 1} completed.");
}
SegmentCompleted?.Invoke(this, segment);
}
protected void RaiseUnitCompleted(int unit)
{
LogManager.Log($"Unit {unit + 1} completed...");
UnitCompleted?.Invoke(this, unit);
}
protected void RaiseFinalizing()
{
LogManager.Log($"Finalizing...");
Finalizing?.Invoke(this, new EventArgs());
}
#endregion
#region Public Methods
/// <summary>
/// Cancels the associated job.
/// </summary>
public void Cancel()
{
_cancelAction();
}
#endregion
}
}