private void UpdateFeed(bool finalCall)
        {
            //JobWorkingTimes for interval
            var operationTasks       = _taskItems.GetValueOrDefault(JobType.OPERATION);
            var setupTasks           = _taskItems.GetValueOrDefault(JobType.SETUP);
            var archiveOperationTask = _taskArchive.GetValueOrDefault(JobType.OPERATION);
            var archiveSetupTask     = _taskArchive.GetValueOrDefault(JobType.SETUP);

            //Save last Timespan
            var tempOperationTasks = operationTasks.Where(x => x.End > lastIntervalStart).ToList();
            var tempSetupTasks     = setupTasks.Where(x => x.End > lastIntervalStart).ToList();

            //Remove All Saved for next Round.
            operationTasks.RemoveAll(op => op.End < lastIntervalStart);
            setupTasks.RemoveAll(op => op.End < lastIntervalStart);

            if (finalCall)
            {
                tempOperationTasks.AddRange(archiveOperationTask);
                tempSetupTasks.AddRange(archiveSetupTask);
                lastIntervalStart = Collector.Config.GetOption <SettlingStart>().Value;
            }

            ResourceUtilization(finalCall, tempOperationTasks, tempSetupTasks);

            var OEE = OverallEquipmentEffectiveness(resources: _resources, lastIntervalStart, Collector.Time, tempOperationTasks, tempSetupTasks);

            Collector.CreateKpi(Collector, OEE, "OEE", KpiType.Ooe, finalCall);

            archiveOperationTask.AddRange(tempOperationTasks);
            archiveSetupTask.AddRange(tempSetupTasks);

            LogToDB(writeResultsToDB: finalCall);

            lastIntervalStart = Collector.Time;
            Collector.Context.Sender.Tell(message: true, sender: Collector.Context.Self);
            Collector.messageHub.SendToAllClients(msg: "(" + Collector.Time + ") Finished Update Feed from WorkSchedule");
        }
        private void ResourceUtilization(bool finalCall, List <ISimulationTask> operationTasks, IList <ISimulationTask> setupTasks)
        {
            Collector.messageHub.SendToAllClients(msg: "(" + Collector.Time + ") Update Feed from DataCollection");

            var setupKpiType = KpiType.ResourceSetup;
            var utilKpiType  = KpiType.ResourceUtilization;

            if (finalCall)
            {
                // reset LastIntervallStart
                lastIntervalStart = Collector.Config.GetOption <SettlingStart>().Value;
                setupKpiType      = KpiType.ResourceSetupTotal;
                utilKpiType       = KpiType.ResourceUtilizationTotal;
            }

            double divisor   = Collector.Time - lastIntervalStart;
            var    tupleList = new List <Tuple <string, string> >();

            //resource to ensure entries, even the resource it not used in interval
            var resourceList = _resources.Select(selector: x => new Tuple <string, long>(x.Value.Name.Replace(" ", ""), 0));

            var lower_borders = from sw in operationTasks
                                where sw.Start <lastIntervalStart &&
                                                sw.End> lastIntervalStart &&
                                sw.Mapping != null
                                group sw by sw.Mapping
                                into rs
                                select new Tuple <string, long>(rs.Key,
                                                                rs.Sum(selector: x => x.End - lastIntervalStart));


            var upper_borders = from sw in operationTasks
                                where sw.Start <Collector.Time &&
                                                sw.End> Collector.Time &&
                                sw.Mapping != null
                                group sw by sw.Mapping
                                into rs
                                select new Tuple <string, long>(rs.Key,
                                                                rs.Sum(selector: x => Collector.Time - x.Start));


            var from_work = from sw in operationTasks
                            where sw.Start >= lastIntervalStart &&
                            sw.End <= Collector.Time &&
                            sw.Mapping != null
                            group sw by sw.Mapping
                            into rs
                            select new Tuple <string, long>(rs.Key,
                                                            rs.Sum(selector: x => x.End - x.Start));

            var merge = from_work.Union(second: lower_borders).Union(second: upper_borders).Union(second: resourceList).ToList();

            var final = from m in merge
                        group m by m.Item1
                        into mg
                        select new Tuple <string, long>(mg.Key, mg.Sum(x => x.Item2));

            foreach (var item in final.OrderBy(keySelector: x => x.Item1))
            {
                var value = Math.Round(value: item.Item2 / divisor, digits: 3).ToString(provider: _cultureInfo);
                if (value == "NaN" || value == "Infinity")
                {
                    value = "0";
                }
                tupleList.Add(new Tuple <string, string>(item.Item1, value));
                Collector.CreateKpi(agent: Collector, value: value.Replace(".", ","), name: item.Item1, kpiType: utilKpiType, finalCall);
            }


            var totalLoad = Math.Round(value: final.Sum(selector: x => x.Item2) / divisor / final.Count() * 100, digits: 3).ToString(provider: _cultureInfo);

            if (totalLoad == "NaN" || totalLoad == "Infinity")
            {
                totalLoad = "0";
            }
            Collector.CreateKpi(agent: Collector, value: totalLoad.Replace(".", ","), name: "TotalWork", kpiType: utilKpiType, finalCall);

            //ResourceSetupTimes for interval
            var setups_lower_borders = from sw in setupTasks
                                       where sw.Start <lastIntervalStart &&
                                                       sw.End> lastIntervalStart &&
                                       sw.Mapping != null
                                       group sw by sw.Mapping
                                       into rs
                                       select new Tuple <string, long>(rs.Key,
                                                                       rs.Sum(selector: x => x.End - lastIntervalStart));

            var setups_upper_borders = from sw in setupTasks
                                       where sw.Start <Collector.Time &&
                                                       sw.End> Collector.Time &&
                                       sw.Mapping != null
                                       group sw by sw.Mapping
                                       into rs
                                       select new Tuple <string, long>(rs.Key,
                                                                       rs.Sum(selector: x => Collector.Time - x.Start));

            var totalSetups = from m in setupTasks
                              where m.Start >= lastIntervalStart &&
                              m.End <= Collector.Time
                              group m by m.Mapping
                              into rs
                              select new Tuple <string, long>(rs.Key,
                                                              rs.Sum(selector: x => x.End - x.Start));

            var union = totalSetups.Union(setups_lower_borders).Union(setups_upper_borders).Union(resourceList).ToList();

            var finalSetup = from m in union
                             group m by m.Item1
                             into mg
                             select new Tuple <string, long>(mg.Key, mg.Sum(x => x.Item2));

            foreach (var resource in finalSetup.OrderBy(keySelector: x => x.Item1))
            {
                var value = Math.Round(value: resource.Item2 / divisor, digits: 3).ToString(provider: _cultureInfo);
                if (value == "NaN" || value == "Infinity")
                {
                    value = "0";
                }
                var machine   = resource.Item1.Replace(oldValue: ")", newValue: "").Replace(oldValue: "Resource(", newValue: "").Replace(oldValue: " ", newValue: "");
                var workValue = tupleList.Single(x => x.Item1 == machine).Item2;
                var all       = workValue + " " + value;
                Collector.messageHub.SendToClient(listener: machine, msg: all);
                Collector.CreateKpi(agent: Collector, value: value.Replace(".", ","), name: resource.Item1, kpiType: setupKpiType, finalCall);
            }

            var totalSetup = Math.Round(value: finalSetup.Where(x => !x.Item1.Contains("Operator")).Sum(selector: x => x.Item2) / divisor / finalSetup.Count() * 100, digits: 3).ToString(provider: _cultureInfo);

            if (totalSetup == "NaN" || totalSetup == "Infinity")
            {
                totalSetup = "0";
            }
            Collector.CreateKpi(agent: Collector, value: totalSetup.Replace(".", ","), name: "TotalSetup", kpiType: setupKpiType, finalCall);

            Collector.messageHub.SendToClient(listener: "TotalTimes", msg: JsonConvert.SerializeObject(value:
                                                                                                       new {
                Time = Collector.Time,
                Load = new { Work = totalLoad, Setup = totalSetup }
            }));
        }
        private void ResourceUtilization()
        {
            double divisor   = Collector.Time - lastIntervalStart;
            var    tupleList = new List <Tuple <string, string> >();

            Collector.messageHub.SendToAllClients(msg: "(" + Collector.Time + ") Update Feed from DataCollection");
            Collector.messageHub.SendToAllClients(msg: "(" + Collector.Time + ") Time since last Update: " + divisor + "min");

            //JobWorkingTimes for interval
            var operationTasks = _taskItems.GetValueOrDefault(JobType.OPERATION);
            var setupTasks     = _taskItems.GetValueOrDefault(JobType.SETUP);

            var lower_borders = from sw in operationTasks
                                where sw.Start <lastIntervalStart &&
                                                sw.End> lastIntervalStart &&
                                sw.Resource != null
                                group sw by sw.Resource
                                into rs
                                select new Tuple <string, long>(rs.Key,
                                                                rs.Sum(selector: x => x.End - lastIntervalStart));


            var upper_borders = from sw in operationTasks
                                where sw.Start <Collector.Time &&
                                                sw.End> Collector.Time &&
                                sw.Resource != null
                                group sw by sw.Resource
                                into rs
                                select new Tuple <string, long>(rs.Key,
                                                                rs.Sum(selector: x => Collector.Time - x.Start));


            var from_work = from sw in operationTasks
                            where sw.Start >= lastIntervalStart &&
                            sw.End <= Collector.Time &&
                            sw.Resource != null
                            group sw by sw.Resource
                            into rs
                            select new Tuple <string, long>(rs.Key,
                                                            rs.Sum(selector: x => x.End - x.Start));

            var reourceList = _resources.Select(selector: x => new Tuple <string, long>(x, 0));
            var merge       = from_work.Union(second: lower_borders).Union(second: upper_borders).Union(second: reourceList).ToList();

            var final = from m in merge
                        group m by m.Item1
                        into mg
                        select new Tuple <string, long>(mg.Key, mg.Sum(x => x.Item2));

            foreach (var item in final.OrderBy(keySelector: x => x.Item1))
            {
                var value = Math.Round(value: item.Item2 / divisor, digits: 3).ToString(provider: _cultureInfo);
                if (value == "NaN")
                {
                    value = "0";
                }
                tupleList.Add(new Tuple <string, string>(item.Item1, value));
                Collector.CreateKpi(agent: Collector, value: value.Replace(".", ","), name: item.Item1, kpiType: KpiType.ResourceUtilization);
            }


            var totalLoad = Math.Round(value: final.Sum(selector: x => x.Item2) / divisor / final.Count() * 100, digits: 3).ToString(provider: _cultureInfo);

            if (totalLoad == "NaN")
            {
                totalLoad = "0";
            }
            Collector.CreateKpi(agent: Collector, value: totalLoad.Replace(".", ","), name: "TotalWork", kpiType: KpiType.ResourceUtilization);

            //ResourceSetupTimes for interval
            var setups_lower_borders = from sw in setupTasks
                                       where sw.Start <lastIntervalStart &&
                                                       sw.End> lastIntervalStart &&
                                       sw.Resource != null
                                       group sw by sw.Resource
                                       into rs
                                       select new Tuple <string, long>(rs.Key,
                                                                       rs.Sum(selector: x => x.End - lastIntervalStart));

            var setups_upper_borders = from sw in setupTasks
                                       where sw.Start <Collector.Time &&
                                                       sw.End> Collector.Time &&
                                       sw.Resource != null
                                       group sw by sw.Resource
                                       into rs
                                       select new Tuple <string, long>(rs.Key,
                                                                       rs.Sum(selector: x => Collector.Time - x.Start));

            var totalSetups = from m in setupTasks
                              where m.Start >= lastIntervalStart &&
                              m.End <= Collector.Time
                              group m by m.Resource
                              into rs
                              select new Tuple <string, long>(rs.Key,
                                                              rs.Sum(selector: x => x.End - x.Start));

            var emptyResources = _resources.Select(selector: x => new Tuple <string, long>(x, 0));
            var union          = totalSetups.Union(setups_lower_borders).Union(setups_upper_borders).Union(emptyResources).ToList();

            var finalSetup = from m in union
                             group m by m.Item1
                             into mg
                             select new Tuple <string, long>(mg.Key, mg.Sum(x => x.Item2));

            foreach (var resource in finalSetup.OrderBy(keySelector: x => x.Item1))
            {
                var value = Math.Round(value: resource.Item2 / divisor, digits: 3).ToString(provider: _cultureInfo);
                if (value == "NaN")
                {
                    value = "0";
                }
                var machine   = resource.Item1.Replace(oldValue: ")", newValue: "").Replace(oldValue: "Resource(", newValue: "");
                var workValue = tupleList.Single(x => x.Item1 == resource.Item1).Item2;
                var all       = workValue + " " + value;
                Collector.messageHub.SendToClient(listener: machine, msg: all);
                Collector.CreateKpi(agent: Collector, value: value.Replace(".", ","), name: resource.Item1, kpiType: KpiType.ResourceSetup);
            }

            var totalSetup = Math.Round(value: finalSetup.Where(x => !x.Item1.Contains("Operator")).Sum(selector: x => x.Item2) / divisor / finalSetup.Count() * 100, digits: 3).ToString(provider: _cultureInfo);

            if (totalSetup == "NaN")
            {
                totalSetup = "0";
            }
            Collector.CreateKpi(agent: Collector, value: totalSetup.Replace(".", ","), name: "TotalSetup", kpiType: KpiType.ResourceSetup);

            Collector.messageHub.SendToClient(listener: "TotalTimes", msg: JsonConvert.SerializeObject(value:
                                                                                                       new {
                Time = Collector.Time,
                Load = new { Work = totalLoad, Setup = totalSetup }
            }));

            //Persist Jobs
            //TODO Find another way to archive list

            var tasksToArchive = operationTasks.Where(x => x.End < lastIntervalStart).ToList();

            tasksToArchive.AddRange(setupTasks.Where(op => op.End < lastIntervalStart));

            operationTasks.RemoveAll(op => op.End < lastIntervalStart);
            setupTasks.RemoveAll(op => op.End < lastIntervalStart);

            _taskArchive.AddRange(tasksToArchive);
        }