def _shorten_capacities_to_start_from_remaining_time_entry(capacities_series, first_remaining_time): shortened_capacities = _shorten_series_to_start_from_day(capacities_series, first_remaining_time.when) # synthesize first ideal burndown entry at the time of the first remaining_time before, after = _entries_from_timeseries_nearest_to(capacities_series, first_remaining_time.when) if before is not None and after is not None: interpolated_start_capacity = Line.from_two_tupples(before, after).y_from_x(first_remaining_time.when) shortened_capacities = [(first_remaining_time.when, interpolated_start_capacity)] + shortened_capacities[1:] return shortened_capacities
def test_can_compute_points_with_datetimes(self): two_days_ago = now() - timedelta(days=2) one_day_ago = now() - timedelta(days=1) today = now() line = Line.from_two_points(Point(two_days_ago, 1), Point(one_day_ago, 2)) expected = Point(today, 3) actual = line.point_from_x(today) self.assert_equals(expected.x, actual.x) self.assert_almost_equals(expected.y, actual.y, max_delta=0.1)
def calculate(self, actual_burndown, a_datetime): if len(actual_burndown) <= 1: return [] reference_burndown = self.find_reference_burndown(actual_burndown) current_burndown = actual_burndown[-1] reference_point = Point(reference_burndown.when, reference_burndown.remaining_time) current_point = Point(current_burndown.when, current_burndown.remaining_time) trend_line = Line.from_two_points(reference_point, current_point) final_value = trend_line.y_from_x(a_datetime) return [current_burndown, burndown_entry(a_datetime, final_value)]
def _calculate_ideal_burndown_at_datetime(self, ideal_data, a_datetime): before, after = _entries_from_timeseries_nearest_to(ideal_data, a_datetime) if before is None or after is None: return 0 return Line.from_two_tupples(before, after).y_from_x(a_datetime)
def test_can_compute_ys_when_points_have_datetimes_as_x(self): two_days_ago = now() - timedelta(days=2) one_day_ago = now() - timedelta(days=1) line = Line.from_two_points(Point(two_days_ago, 1), Point(one_day_ago, 2)) self.assert_almost_equals(3, line.y_from_x(now()), max_delta=0.1)
def test_can_compute_point_at_given_y(self): line = Line(Point(20, 10), 2) self.assert_equals(Point(20, 10), line.point_from_x(20)) self.assert_equals(Point(30, 30), line.point_from_x(30)) self.assert_equals(Point(40, 50), line.point_from_x(40))
def test_can_compute_arbitrary_y_from_given_x(self): line = Line(Point(20, 10), 2) self.assert_equals(10, line.y_from_x(20)) self.assert_equals(30, line.y_from_x(30)) self.assert_equals(50, line.y_from_x(40))
def test_can_instantiate_line_with_two_points(self): first = Point(1, 1) second = Point(21, 11) actual = Line.from_two_points(first, second) self.assert_equals(first, actual.point) self.assert_almost_equals(0.5, actual.slope, max_delta=0.001)
def test_can_instantiate_line(self): point = Point(0, 0) line = Line(point, 1) self.assert_equals(point, line.point) self.assert_equals(1, line.slope)
def test_can_initialize_line_from_two_tupples(self): line = Line.from_two_tupples((0, 0), (1, 1)) self.assert_equals(Point(0, 0), line.point) self.assert_equals(1, line.slope)
def test_can_create_line_with_no_slope_from_points(self): line = Line.from_two_tupples((0, 0), (0, 10)) self.assert_equals(0, line.slope)
def test_can_create_line_with_no_slope_from_points(self): line = Line.from_two_tupples((0, 0), (0, 10)) self.assert_equals(0, line.slope) # TODO: make sure points can be instructed with times and floats