diff --git a/src/octoprint/printer/__init__.py b/src/octoprint/printer/__init__.py index a61a2cda..b19fd38d 100644 --- a/src/octoprint/printer/__init__.py +++ b/src/octoprint/printer/__init__.py @@ -384,24 +384,24 @@ class Printer(): def _estimateTotalPrintTime(self, progress, printTime): if not progress or not printTime: - #self._estimationLogger.info("{progress};{printTime};;;".format(**locals())) + #self._estimationLogger.info("{progress};{printTime};;;;".format(**locals())) return None else: newEstimate = printTime / progress - - if self._timeEstimationData.is_stable(): - #self._estimationLogger.info("{progress};{printTime};{newEstimate};;".format(**locals())) - return newEstimate - self._timeEstimationData.update(newEstimate) - #averageTotal = self._timeEstimationData.average_total - #averageDistance = self._timeEstimationData.average_distance - # - #self._estimationLogger.info("{progress};{printTime};{newEstimate};{averageTotal};{averageDistance}".format(**locals())) + result = None + if self._timeEstimationData.is_stable(): + result = self._timeEstimationData.average_total_rolling - return None + #averageTotal = self._timeEstimationData.average_total + #averageTotalRolling = self._timeEstimationData.average_total_rolling + #averageDistance = self._timeEstimationData.average_distance + + #self._estimationLogger.info("{progress};{printTime};{newEstimate};{averageTotal};{averageTotalRolling};{averageDistance}".format(**locals())) + + return result def _setProgressData(self, progress, filepos, printTime, cleanedPrintTime): estimatedTotalPrintTime = self._estimateTotalPrintTime(progress, cleanedPrintTime) @@ -420,7 +420,7 @@ class Printer(): sub_progress = 1.0 totalPrintTime = (1 - sub_progress) * statisticalTotalPrintTime + sub_progress * estimatedTotalPrintTime - #self._printTimeLogger.info("{progress};{cleanedPrintTime};{estimatedTotalPrintTime};{statisticalTotalPrintTime};{totalPrintTime}".format(**locals())) + self._printTimeLogger.info("{progress};{cleanedPrintTime};{estimatedTotalPrintTime};{statisticalTotalPrintTime};{totalPrintTime}".format(**locals())) self._progress = progress self._printTime = printTime @@ -884,6 +884,7 @@ class TimeEstimationHelper(object): def __init__(self): import collections self._distances = collections.deque([], self.__class__.STABLE_ROLLING_WINDOW) + self._totals = collections.deque([], self.__class__.STABLE_ROLLING_WINDOW) self._sum_total = 0 self._count = 0 self._stable_counter = None @@ -895,6 +896,7 @@ class TimeEstimationHelper(object): old_average_total = self.average_total self._sum_total += newEstimate + self._totals.append(newEstimate) self._count += 1 if old_average_total: @@ -915,6 +917,13 @@ class TimeEstimationHelper(object): else: return self._sum_total / self._count + @property + def average_total_rolling(self): + if not self._count or self._count < self.__class__.STABLE_ROLLING_WINDOW: + return None + else: + return sum(self._totals) / len(self._totals) + @property def average_distance(self): if not self._count or self._count < self.__class__.STABLE_ROLLING_WINDOW + 1: diff --git a/tests/printer/test_estimation.py b/tests/printer/test_estimation.py index ad43d11d..28d4ce8a 100644 --- a/tests/printer/test_estimation.py +++ b/tests/printer/test_estimation.py @@ -34,6 +34,9 @@ class EstimationTestCase(unittest.TestCase): self.assertEquals(self.estimation_helper.average_total, expected) @data( + ((1.0, 2.0), None), # not enough values, have 1, need 3 + ((1.0, 2.0, 3.0), None), # not enough values, have 2, need 3 + ((1.0, 2.0, 3.0, 4.0), 0.5), # average totals: 1.0, 1.5, 2.0, 2.5 => (3 * 0.5 / 3 = 0.5 ((1.0, 2.0, 3.0, 4.0, 5.0), 0.5), # average totals: 1.0, 1.5, 2.0, 2.5, 3.0 => (0.5 + 0.5 + 0.5) / 3 = 0.5 ((1.0, 2.0, 0.0, 1.0, 2.0), 0.7 / 3) # average totals: 1.0, 1.5, 1.0, 1.0, 1.2 => (0.5 + 0.0 + 0.2) / 3 = 0.7 / 3 ) @@ -44,6 +47,18 @@ class EstimationTestCase(unittest.TestCase): self.assertEquals(self.estimation_helper.average_distance, expected) + @data( + ((1.0, 1.0), None), + ((1.0, 1.0, 1.0), 1.0), + ((1.0, 2.0, 3.0, 4.0, 5.0), 4.0), + ) + @unpack + def test_average_total_rolling(self, estimates, expected): + for estimate in estimates: + self.estimation_helper.update(estimate) + + self.assertEquals(self.estimation_helper.average_total_rolling, expected) + @data( ((1.0, 1.0, 1.0, 1.0), False), # average totals: 1.0, 1.0, 1.0, 1.0 => 3.0 / 3 = 1.0 ((1.0, 1.0, 1.0, 1.0, 1.0), True), # average totals: 1.0, 1.0, 1.0, 1.0, 1.0 => 0.0 / 3 = 0.0