1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)# Copyright 2014 The Chromium Authors. All rights reserved.
2a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch# Use of this source code is governed by a BSD-style license that can be
3a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch# found in the LICENSE file.
4a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
5a3f7b4e666c476898878fa745f637129375cd889Ben Murdochclass Bounds(object):
6a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  """Represents a min-max bounds."""
7a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def __init__(self):
8a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.is_empty_ = True
9a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.min_ = None
10a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.max_ = None
11a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  @staticmethod
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  def CreateFromEvent(event):
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bounds = Bounds()
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bounds.AddEvent(event)
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return bounds
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  def __repr__(self):
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if self.is_empty_:
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "Bounds()"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else:
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "Bounds(min=%s,max=%s)" % (self.min_, self.max_)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @property
25a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def is_empty(self):
26a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return self.is_empty_
27a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
28a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @property
29a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def min(self):
30a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if self.is_empty_:
31a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      return None
32a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return self.min_
33a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
34a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @property
35a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def max(self):
36a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if self.is_empty_:
37a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      return None
38a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return self.max_
39a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
40a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @property
41a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def bounds(self):
42a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if self.is_empty_:
43a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      return None
44a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return self.max_ - self.min_
45a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
46a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @property
47a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def center(self):
48a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return (self.min_ + self.max_) * 0.5
49a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  def Contains(self, other):
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if self.is_empty or other.is_empty:
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return False
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return self.min <= other.min and self.max >= other.max
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  def ContainsInterval(self, start, end):
56a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return self.min <= start and self.max >= end
57a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  def Intersects(self, other):
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if self.is_empty or other.is_empty:
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return False
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return not (other.max < self.min or other.min > self.max)
62a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
63a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def Reset(self):
64a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.is_empty_ = True
65a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.min_ = None
66a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.max_ = None
67a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
68a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def AddBounds(self, bounds):
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if bounds.is_empty:
70a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      return
71a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.AddValue(bounds.min_)
72a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.AddValue(bounds.max_)
73a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
74a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def AddValue(self, value):
75a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if self.is_empty_:
76a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      self.max_ = value
77a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      self.min_ = value
78a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      self.is_empty_ = False
79a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      return
80a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
81a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.max_ = max(self.max_, value)
82a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.min_ = min(self.min_, value)
83a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  def AddEvent(self, event):
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    self.AddValue(event.start)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    self.AddValue(event.start + event.duration)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
88a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  @staticmethod
89a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  def CompareByMinTimes(a, b):
90a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if not a.is_empty and not b.is_empty:
91a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      return a.min_ - b.min_
92a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
93a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if a.is_empty and not b.is_empty:
94a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      return -1
95a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
96a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if not a.is_empty and b.is_empty:
97a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      return 1
98a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
99a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return 0
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  @staticmethod
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def GetOverlapBetweenBounds(first_bounds, second_bounds):
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Compute the overlap duration between first_bounds and second_bounds."""
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return Bounds.GetOverlap(first_bounds.min_, first_bounds.max_,
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             second_bounds.min_, second_bounds.max_)
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  @staticmethod
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def GetOverlap(first_bounds_min, first_bounds_max,
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 second_bounds_min, second_bounds_max):
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    assert first_bounds_min <= first_bounds_max
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    assert second_bounds_min <= second_bounds_max
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    overlapped_range_start = max(first_bounds_min, second_bounds_min)
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    overlapped_range_end = min(first_bounds_max, second_bounds_max)
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return max(overlapped_range_end - overlapped_range_start, 0)
115