private Process TryLoadProcessFromQueue()
        {
            if (ProcessesQueue.Count > 0)
            {
                if (Algorithm == SchedulerAlgorithm.FCFS)
                {
                    var processFromQueue = ProcessesQueue[0];


                    //Process can be loaded from queue
                    if (processFromQueue.ArrivalTime <= CurrentTime && processFromQueue.LastEnterTime == -1 ||
                        processFromQueue.LastExitTime + processFromQueue.IOTime <= CurrentTime)
                    {
                        ProcessesQueue.RemoveAt(0);
                        processFromQueue.Status        = ProcessStatus.OnCpu;
                        processFromQueue.LastEnterTime = CurrentTime;


                        return(processFromQueue);
                    }
                }
                else if (Algorithm == SchedulerAlgorithm.SJF)
                {
                    int     shortestJobAvailableDuration = int.MaxValue;
                    int     it = 0;
                    int     processFromQueuePosition = -1;
                    Process processFromQueue         = null;

                    for (; it < ProcessesQueue.Count; it++)
                    {
                        Process p = ProcessesQueue[it];
                        if (((p.ArrivalTime <= CurrentTime && p.LastEnterTime == -1) || (p.LastExitTime + p.IOTime <= CurrentTime && p.LastExitTime != -1)) &&
                            (p.BurstTime < p.RemainingDuration ? p.BurstTime : p.RemainingDuration) < shortestJobAvailableDuration)
                        {
                            processFromQueue             = CloneObject.CloneJson(p);
                            processFromQueuePosition     = it;
                            shortestJobAvailableDuration = p.BurstTime < p.RemainingDuration ? p.BurstTime : p.RemainingDuration;
                        }
                    }

                    if (processFromQueue != null)
                    {
                        ProcessesQueue.RemoveAt(processFromQueuePosition);
                        processFromQueue.Status        = ProcessStatus.OnCpu;
                        processFromQueue.LastEnterTime = CurrentTime;



                        return(processFromQueue);
                    }
                }
            }
            return(null);
        }
        //SJF = Shortest Job First
        public void solveSJF()
        {
            CurrentTime = 0;
            Status      = SchedulerStatus.On;

            ProcessesQueue = ProcessesList;
            //Queue Starts with ascending order of processes by Arrival Time.
            ProcessesQueue = ProcessesQueue.OrderBy(c => c.ArrivalTime).ThenBy(c => c.BurstTime).ToList();

            //Load first Process
            while (ProcessesQueue[0].ArrivalTime > CurrentTime)
            {
                KeyTime keyTime = new KeyTime();
                keyTime.CpuOnLoad       = false;
                keyTime.Process         = null;
                keyTime.OngoingProcess  = null;
                keyTime.OutgoingProcess = null;
                keyTime.Timestamp       = CurrentTime;
                ++CurrentTime;
                KeyTimes.Add(keyTime);
            }

            //First process comes at moment zero (special scenario)
            if (CurrentTime == 0 && ProcessesQueue[0].ArrivalTime == 0)
            {
                Process firstProcess = ProcessesQueue[0];
                ProcessesQueue.RemoveAt(0); //Remove selected process from the queue
                KeyTime keyTime = new KeyTime();
                keyTime.CpuOnLoad       = true;
                keyTime.OutgoingProcess = null;
                keyTime.Timestamp       = CurrentTime;

                firstProcess.LastEnterTime = CurrentTime;
                firstProcess.Status        = ProcessStatus.OnCpu;
                keyTime.OngoingProcess     = firstProcess;
                KeyTimes.Add(keyTime);
                ++CurrentTime;
            }

            //Continue processing
            KeyTime currentKeyTime = new KeyTime();
            KeyTime lastKeyTime    = KeyTimes[CurrentTime - 1];

            while (ProcessesQueue.Count > 0 || lastKeyTime.OngoingProcess != null || currentKeyTime.OngoingProcess != null)
            {
                currentKeyTime           = new KeyTime();
                lastKeyTime              = KeyTimes[CurrentTime - 1];
                currentKeyTime.Timestamp = CurrentTime;

                //Last process action on current moment
                var lastOngoingProcessResult = CheckForProcessContinuity(CloneObject.CloneJson(lastKeyTime.OngoingProcess));

                //Process ongoing on the CPU. No replacements actions needed
                if (lastOngoingProcessResult != null && lastOngoingProcessResult.Item2 != null)
                {
                    currentKeyTime.OutgoingProcess = null;
                    currentKeyTime.OngoingProcess  = lastOngoingProcessResult.Item2;
                    currentKeyTime.CpuOnLoad       = true;
                    if (currentKeyTime.OngoingProcess.ResponseTime == 0)
                    {
                        currentKeyTime.OngoingProcess.ResponseTime = CurrentTime;
                    }
                    ++AverageCPUUtilisation;
                }
                else
                {
                    if (lastOngoingProcessResult != null)
                    {
                        currentKeyTime.OutgoingProcess = lastOngoingProcessResult.Item1;
                    }

                    currentKeyTime.OngoingProcess = TryLoadProcessFromQueue();
                    if (currentKeyTime.OngoingProcess != null)
                    {
                        ++AverageCPUUtilisation;
                        if (currentKeyTime.OngoingProcess.ResponseTime == 0)
                        {
                            currentKeyTime.OngoingProcess.ResponseTime = CurrentTime;
                        }
                    }
                }

                KeyTimes.Add(currentKeyTime);
                AverageWaitingProcesses += ProcessesQueue.Count;
                ++CurrentTime;
            }

            Status = SchedulerStatus.Off;
        }