public JobProcessorList(JobPriorityFunction priorityFunction)
        {
            _receivedJobs = new Dictionary<int, IJob>();
            _processingJobs = new Dictionary<int, IJob>();
            _processedJobs = new Dictionary<int, IJob>();

            _jobsList = new FibonacciQueue<IJob, double>(priorityFunction.CalculatePriority);
            _distanceRelaxer = DistanceRelaxers.EdgeShortestDistance;
        }
        private const int MaxIterationCount = 24*60*365*4; // 4 years of minutes
        protected IEnumerable<IScheduledJob> Solve(
            List<IShift> shifts, 
            List<IWorker> workers, 
            List<ITool> tools, 
            IEnumerable<IZone> zones, 
            IEnumerable<IJob> jobs, 
            GreedyActivityStrategy strategy,
            ShiftManager shiftManager)
        {
            _shiftManager = shiftManager;
            _strategy = strategy;
            _jobPriorityFunction = new SlackTimeRemainingJobPriorityFunction();

            if (shifts.Count > 0)
            {
                _shifts = shifts.ToArray();
                SetupWorkers(shifts, workers);
                SetupTools(shifts, tools);
            }

            SetupZones(zones);

            SetupJobs(jobs);

            _timepoints = new Dictionary<int, List<InWorkEvent>>();
            _inWorkEvents = new List<InWorkEvent>();

            int iteration = InitializeNextIteration(_shifts[0]);

            while (_jobs.Any() && iteration < MaxIterationCount)
            {
                // check to see if we have any events expiring
                ProcessCompletingJobs(iteration);
                
                // check to see if we have any new jobs we can work on
                ProcessJobs(iteration);

                // increment iteration counter
                iteration++;
            }

            // we're done!
            return BuildSchedule();
        }