def test_from_string_customized(): i1, i2, i3, i4 = '<"0"-"1">', '<!"0"-"1">', '<"0"-"1"!>', '<!"0"-"1"!>' params = { 'conv': lambda s: int(s[1:-1]), 'disj': ' or ', 'sep': '-', 'left_open': '<!', 'left_closed': '<', 'right_open': '!>', 'right_closed': '>', 'pinf': r'\+oo', 'ninf': '-oo', } assert I.from_string(i1, **params) == I.closed(0, 1) assert I.from_string(i2, **params) == I.openclosed(0, 1) assert I.from_string(i3, **params) == I.closedopen(0, 1) assert I.from_string(i4, **params) == I.open(0, 1) assert I.from_string('<!!>', **params) == I.empty() assert I.from_string('<"1">', **params) == I.singleton(1) assert I.from_string('<!-oo-"1">', **params) == I.openclosed(-I.inf, 1) assert I.from_string('<"1"-+oo!>', **params) == I.closedopen(1, I.inf) assert I.from_string('<"0"-"1"> or <"2"-"3">', **params) == I.closed(0, 1) | I.closed(2, 3)
def AbstractToGraph(obj): """Abstracts the environment to a graph so that path can be planned""" # read environmental limits xmax = obj.Environment.Dimension_x ymax = obj.Environment.Dimension_y # create graph G = nx.DiGraph(alpha=1, AUVmaxspeed=2.0) # TODO: hand over the parameters #create raw edges between coordinates raw_edges = [((x, y), (x + dx, y + dy)) for dx in [-1, 0, +1] for dy in [-1, 0, +1] for x in range(xmax + 1) for y in range(ymax + 1) if x + dx in I.closed(0, xmax) and y + dy in I.closed(0, ymax) and (dx != 0 or dy != 0)] # create nodes nodes = {(x, y): SearchNode(position=(x, y), risk=ReturnRisk(obj, (x, y)), current=ReturnCurrent(obj, (x, y)), g=np.inf, rhs=np.inf) for x in range(xmax + 1) for y in range(ymax + 1)} # make graph edges from raw edges and nodes edges = [(nodes[e[0]], nodes[e[1]]) for e in raw_edges] G.add_edges_from(edges) # identify the maxcurrent in the model G.graph['maxcurrent'] = max([n.current for n in G.nodes], key=np.linalg.norm) return G
def test_apply(): i = I.closed(0, 1) assert i.apply(lambda s: s) == i assert i.apply(lambda s: (False, -1, 2, False)) == I.open(-1, 2) assert i.apply(lambda s: I.AtomicInterval(False, -1, 2, False)) == I.open( -1, 2) assert i.apply(lambda s: I.open(-1, 2)) == I.open(-1, 2) i = I.closed(0, 1) | I.closed(2, 3) assert i.apply(lambda s: s) == i assert i.apply(lambda s: (False, -1, 2, False)) == I.open(-1, 2) assert i.apply(lambda s: (not s.left, s.lower - 1, s.upper - 1, not s.right )) == I.open(-1, 0) | I.open(1, 2) assert i.apply(lambda s: I.AtomicInterval(False, -1, 2, False)) == I.open( -1, 2) assert i.apply(lambda s: I.open(-1, 2)) == I.open(-1, 2) assert i.apply(lambda s: (s.left, s.lower, s.upper * 2, s.right)) == I.closed(0, 6) assert I.empty().apply(lambda s: (I.CLOSED, 1, 2, I.CLOSED)) == I.closed( 1, 2) with pytest.raises(TypeError): i.apply(lambda s: None) with pytest.raises(TypeError): i.apply(lambda s: 'unsupported')
def test_to_string_customized(): i1, i2, i3, i4 = I.closed(0, 1), I.openclosed(0, 1), I.closedopen(0, 1), I.open(0, 1) params = { 'disj': ' or ', 'sep': '-', 'left_open': '<!', 'left_closed': '<', 'right_open': '!>', 'right_closed': '>', 'conv': lambda s: '"{}"'.format(s), 'pinf': '+oo', 'ninf': '-oo', } assert I.to_string(i1, **params) == '<"0"-"1">' assert I.to_string(i2, **params) == '<!"0"-"1">' assert I.to_string(i3, **params) == '<"0"-"1"!>' assert I.to_string(i4, **params) == '<!"0"-"1"!>' assert I.to_string(I.empty(), **params) == '<!!>' assert I.to_string(I.singleton(1), **params) == '<"1">' assert I.to_string(I.openclosed(-I.inf, 1), **params) == '<!-oo-"1">' assert I.to_string(I.closedopen(1, I.inf), **params) == '<"1"-+oo!>' assert I.to_string(I.closed(0, 1) | I.closed(2, 3), **params) == '<"0"-"1"> or <"2"-"3">'
def is_range_intersecting_date_session(record, Record): error = None r_exp = Record.objects.filter(experiment__exact=record.experiment) for ind, r in enumerate(r_exp): inter1 = inter.closed(record.date_from, record.date_to) inter2 = inter.closed(r.date_from, r.date_to) date_inter = inter1 & inter2 if not date_inter.is_empty(): if date_inter.is_atomic( ): #could be an intersection within or on the edges # check if it is on the edges: if inter1 <= inter2 or inter1 >= inter2: #check if sessions/times overlapp error = is_range_intersecting_session(record, [r]) time_inter = inter.closed(record.time_from, record.time_to) & inter.closed( r.time_from, r.time_to) if not time_inter.is_empty(): error = time_error break else: error = dates_error break else: error = dates_error break return error
def Visible(node, p1, p2): # Test welcher Knoten welchen Kantenmittelpunkt sieht points = [] a1 = p2 - p1 for w in W: if node in w: # angrenzende Kanten ausschließen points.append([-100, -100]) else: a2 = [ V_x[w[1] - 1] - V_x[w[0] - 1], V_y[w[1] - 1] - V_y[w[0] - 1] ] b = np.array([V_x[w[0] - 1] - p1[0], V_y[w[0] - 1] - p1[1]]) A = np.array([[a1[0], -a2[0]], [a1[1], -a2[1]]]) if np.linalg.det( A) == 0: # singuläre Matrizen von Parallelen ausschließen points.append([-1000, -1000]) else: x = np.linalg.solve(A, b) points.append([round(x[0], 4), round(x[1], 4)]) flag = 1 for p in points: if p[0] in I.closed(0, 1) and p[1] in I.closed( 0, 1) and np.linalg.norm(a1 * p[0]) < np.linalg.norm(a1): flag = 0 break return flag
def test_proxy_methods(): i1, i2 = I.closed(0, 1), I.closed(2, 3) assert i1 & i2 == i1.intersection(i2) assert i1 | i2 == i1.union(i2) assert (i1 in i2) == i2.contains(i1) assert ~i1 == i1.complement() assert i1 - i2 == i1.difference(i2) with pytest.raises(TypeError): i1 & 1 with pytest.raises(TypeError): i1 | 1 with pytest.raises(TypeError): i1 - 1 i1, i2 = I.closed(0, 1).to_atomic(), I.closed(2, 3).to_atomic() assert i1 & i2 == i1.intersection(i2) assert i1 | i2 == i1.union(i2) assert (i1 in i2) == i2.contains(i1) assert ~i1 == i1.complement() assert i1 - i2 == i1.difference(i2) with pytest.raises(TypeError): i1 & 1 with pytest.raises(TypeError): i1 | 1 with pytest.raises(TypeError): i1 - 1
def test_interval_constraints(): tests = { I.closedopen(Version('1.0.0'), Version('3.0.0')): { 'strict': False, 'bounded': (True, True), 'soft': (False, True, True), 'hard': (True, True, True), }, I.closedopen(Version('1.0.0'), Version('3.0.0')) | I.singleton(Version('4.0.0')): { 'strict': False, 'bounded': (True, True), 'soft': (False, False, False), 'hard': (True, True, True), }, I.closed(Version('1.0.0'), Version('2.0.0')) | I.closedopen(Version('3.0.0'), Version('3.1.0')): { 'strict': False, 'bounded': (True, True), 'soft': (False, False, True), 'hard': (True, True, True), }, I.closed(Version('1.0.0'), Version('2.0.0')) | I.closed(Version('3.0.0'), Version('3.1.0')): { 'strict': False, 'bounded': (True, True), 'soft': (False, False, True), 'hard': (True, True, True), }, } for constraint, expected in tests.items(): assert strict(constraint) == expected['strict'] assert (lower_bounded(constraint), upper_bounded(constraint)) == expected['bounded'] assert (allows_major(constraint), allows_minor(constraint), allows_patch(constraint)) == expected['soft'] assert (allows_major(constraint, soft=False), allows_minor(constraint, soft=False), allows_patch(constraint, soft=False)) == expected['hard']
def test_atomic_comparisons(): i1, i2, i3 = I.closed(0, 1), I.closed(1, 2), I.closed(2, 3) i1, i2, i3 = i1.to_atomic(), i2.to_atomic(), i3.to_atomic() assert i1 == i1 assert i1 != i2 assert i1 != i3 assert i1 < i3 assert i1 <= i2 assert i1 <= i3 assert not (i1 < i2) assert i2 >= i1 assert i3 > i1 assert i3 >= i1 assert not (i2 > i1) assert not i1 == 1 with pytest.raises(TypeError): i1 > 1 with pytest.raises(TypeError): i1 >= 1 with pytest.raises(TypeError): i1 < 1 with pytest.raises(TypeError): i1 <= 1
def cnv_pred_true_merge(rowiter): lock.acquire() idx, row = rowiter res = [] for i_idx, i_row in true_cnv_df.iterrows(): x = I.closed(row['POS_S'], row['POS_E']) & I.closed( i_row['POS'], i_row['END']) y = I.closed(row['POS_S'], row['POS_E']) | I.closed( i_row['POS'], i_row['END']) if x.is_empty(): continue inter_len = x.upper - x.lower union_len = y.upper - y.lower if inter_len >= 0: res.append( np.concatenate((row.values, i_row.values, [x.lower, x.upper, inter_len, union_len]), axis=None)) if len(res) == 0: res.append( np.concatenate( (row.values, [np.nan] * n_true_cnv_df_cols, [-1] * 4), axis=None)) lock.release() return res
def test_intersection(): assert I.closed(0, 1) & I.closed(0, 1) == I.closed(0, 1) assert I.closed(0, 1) & I.closed(0, 1).to_atomic() == I.closed(0, 1) assert I.closed(0, 1) & I.open(0, 1) == I.open(0, 1) assert I.openclosed(0, 1) & I.closedopen(0, 1) == I.open(0, 1) assert (I.closed(0, 1) & I.closed(2, 3)).is_empty() assert I.closed(0, 1) & I.empty() == I.empty()
def conf_pred(X, Y_seen, lambda_, y_range, alpha=0.1, epsilon=1e-3, nu=1., method="lasso"): pred_set = intervals.empty() X = np.asfortranarray(X) Y_seen = np.asfortranarray(Y_seen) y_min, y_max = y_range eps_0 = epsilon / 10. if method is "lasso" else 1e-10 step_size = np.sqrt(2. * (epsilon - eps_0) / nu) # Initial fitting coef = fit_model(X[:-1], Y_seen, None, lambda_, eps_0, method)[2] y_0 = X[-1:].dot(coef)[0] coef_negative_side = coef.copy() y_0_negative_side = y_0 y_t, next_y_t = y_0, y_0 Y_t = np.array(list(Y_seen) + [y_0], order='F') # positive direction while next_y_t < y_max: next_y_t = min(y_t + step_size, y_max) Y_t[-1] = next_y_t mu, residual = fit_model(X, Y_t, coef, lambda_, eps_0, method)[:2] q_alpha = np.quantile(residual, 1 - alpha) y_intv = intervals.closed(y_t, next_y_t) mu_intv = intervals.closed(mu[-1] - q_alpha, mu[-1] + q_alpha) pred_set = pred_set.union(y_intv.intersection(mu_intv)) y_t = next_y_t coef = coef_negative_side y_0 = y_0_negative_side y_t, next_y_t = y_0, y_0 # negative direction while next_y_t > y_min: next_y_t = max(y_t - step_size, y_min) Y_t[-1] = next_y_t mu, residual = fit_model(X, Y_t, coef, lambda_, eps_0, method)[:2] q_alpha = np.quantile(residual, 1 - alpha) y_intv = intervals.closed(next_y_t, y_t) mu_intv = intervals.closed(mu[-1] - q_alpha, mu[-1] + q_alpha) pred_set = pred_set.union(y_intv.intersection(mu_intv)) y_t = next_y_t return pred_set
def test_strict_constraints(): assert strict(I.closed(Version('1.0.0'), Version('1.0.0'))) assert strict(I.closedopen(Version('1.0.0'), Version('1.0.1'))) assert strict(I.closedopen(Version('1.0.0'), Version('1.0.1'))) assert not strict(I.closed(Version('1.0.0'), Version('1.0.1'))) assert not strict(I.closed(Version('1.0.0'), Version('1.1.0'))) assert not strict(I.closed(Version('1.0.0'), Version('2.0.0'))) assert not strict(I.closed(Version('1.0.0'), I.inf))
def build_interval_draft4(self): if self.exclusiveMinimum and self.exclusiveMaximum: self.interval = I.closed(self.minimum + 1, self.maximum - 1) elif self.exclusiveMinimum: self.interval = I.closed(self.minimum + 1, self.maximum) elif self.exclusiveMaximum: self.interval = I.closed(self.minimum, self.maximum - 1) else: self.interval = I.closed(self.minimum, self.maximum)
def test_check_rules_where_incomplete_match(): part = generate_trivial_part(5) rule = nx.complete_graph(3) for node_index in range(0, 3): rule.node[node_index][interval] = i.closed(5, i.inf) rule.node[2][interval] = i.closed(6, 7) assert_false(check_apply_unambiguously(part, rule))
def test_find_maximum_part_degree(): rule = nx.complete_graph(3) rule.node[0][interval] = i.closed(5, 5) rule.node[1][interval] = i.closed(6, 6) rule.node[2][interval] = i.closed(7, i.inf) max_degree = find_maximum_part_degree([rule]) assert_equals(max_degree, 6)
def update_timed_since(self, now, state, left, right, lower, upper): if left and right: return (state & intervals.closed(self.time, intervals.inf) ) | intervals.closed(self.time + lower, self.time + upper) elif not left and right: return intervals.closed(self.time + lower, self.time + upper) elif left and not right: return (state & intervals.closed(self.time, intervals.inf)) else: return intervals.empty()
def interval_contains(a, b): """Condition used to check if an a touches b and partially covers it""" dimensions = len(a) partial = all([ (I.closed(*a[dimension]) & I.open(*b[dimension])).is_empty() == False if not I.open(*b[dimension]).is_empty() else (I.closed(*a[dimension]) & I.closed(*b[dimension])).is_empty() == False for dimension in range(dimensions) ]) return partial
def test_comparisons_of_empty(): assert I.empty() < I.empty() assert I.empty() <= I.empty() assert I.empty() > I.empty() assert I.empty() >= I.empty() assert I.empty() < I.closed(2, 3) assert I.empty() <= I.closed(2, 3) assert I.empty() > I.closed(2, 3) assert I.empty() >= I.closed(2, 3)
def test_complement(): assert ~I.closed(1, 2) == I.open(-I.inf, 1) | I.open(2, I.inf) assert ~I.open(1, 2) == I.openclosed(-I.inf, 1) | I.closedopen(2, I.inf) intervals = [I.closed(0, 1), I.open(0, 1), I.openclosed(0, 1), I.closedopen(0, 1)] for interval in intervals: assert ~(~interval) == interval assert ~I.open(1, 1) == I.open(-I.inf, I.inf) assert (~I.closed(-I.inf, I.inf)).is_empty() assert ~I.empty() == I.open(-I.inf, I.inf)
def test_branch_part(): part = generate_trivial_part(5) rule = nx.complete_graph(3) for node_index in range(0, 2): rule.node[node_index][interval] = i.closed(5, i.inf) rule.node[2][interval] = i.closed(7, i.inf) branched = list(branch(part, rule)) expected_part = generate_trivial_part(5) expected_part.node[2][interval] = i.closed(5, 6) assert_true(graph_in(branched, expected_part))
def test_hash(): assert hash(I.closed(0, 1).to_atomic()) is not None assert hash(I.closed(0, 1)) is not None # Even for unhashable bounds with pytest.raises(TypeError): hash(I.inf) with pytest.raises(TypeError): hash(-I.inf) assert hash(I.closed(-I.inf, I.inf).to_atomic()) is not None assert hash(I.closed(-I.inf, I.inf)) is not None
def is_range_intersecting_session(record, records): error = None for ind, r in enumerate(records): #check if sessions/times overlapp time_inter = inter.closed(record.time_from, record.time_to) & inter.closed( r.time_from, r.time_to) if not time_inter.is_empty(): error = time_error break return error
def test_to_string(): i1, i2, i3, i4 = I.closed(0, 1), I.openclosed(0, 1), I.closedopen(0, 1), I.open(0, 1) assert I.to_string(i1) == '[0,1]' assert I.to_string(i2) == '(0,1]' assert I.to_string(i3) == '[0,1)' assert I.to_string(i4) == '(0,1)' assert I.to_string(I.empty()) == '()' assert I.to_string(I.singleton(1)) == '[1]' assert I.to_string(I.closed(0, 1) | I.closed(2, 3)) == '[0,1] | [2,3]'
def test_creation(): assert I.closed(0, 1) == I.AtomicInterval(I.CLOSED, 0, 1, I.CLOSED) assert I.open(0, 1) == I.AtomicInterval(I.OPEN, 0, 1, I.OPEN) assert I.openclosed(0, 1) == I.AtomicInterval(I.OPEN, 0, 1, I.CLOSED) assert I.closedopen(0, 1) == I.AtomicInterval(I.CLOSED, 0, 1, I.OPEN) assert I.closed(-I.inf, I.inf) == I.open(-I.inf, I.inf) with pytest.raises(ValueError): I.closed(1, -1) assert I.singleton(2) == I.closed(2, 2) assert I.Interval() == I.open(0, 0) assert I.empty() == I.Interval()
def play(self): pygame.init() self.GameDisplay = pygame.display.set_mode((self.W, self.H), 0) self.GameDisplay.fill(self.background) self.font = pygame.font.Font('TypewriterScribbled.ttf', self.font_size) quit_game = False while not quit_game: self.time += 1 self.GameDisplay.fill(self.background) self.draw_menu() keys = pygame.key.get_pressed() self.player.move(keys) self.draw_object(self.player) if self.time % 7 == 0: mouse = pygame.mouse.get_pos() self.shoot(mouse) if self.time % 180 == 0: if self.freq > 1: self.freq -= 1 if self.time % self.freq == 0: self.blocks.append(Block(self)) for event in pygame.event.get(): if event.type == pygame.QUIT: quit_game = True pygame.quit() quit() self.blocks = [block for block in self.blocks if block.y <= self.H] for block in self.blocks: if I.closed(block.x, block.x+block.W).overlaps(I.closed(self.player.x, self.player.x+self.player.size))\ and I.closed(block.y, block.y+block.W).overlaps(I.closed(self.player.y, self.player.y+self.player.size)): quit_game = True #pygame.quit() #quit() block.move() self.draw_object(block) self.bullets = [ bullet for bullet in self.bullets if 0 <= bullet.x <= self.W and 0 <= bullet.y <= self.H ] for bullet in self.bullets: bullet.move() self.draw_object(bullet) a = copy(len(self.blocks)) self.blocks = [ block for block in self.blocks if not I.closed(block.x, block.x + block.W).overlaps( I.closed(bullet.x, bullet.x + bullet.W)) or not I.closed(block.y, block.y + block.H).overlaps( I.closed(bullet.y, bullet.y + bullet.H)) ] bullet.remove = (a != len(self.blocks)) if bullet.remove: self.points += 1 self.bullets = [ bullet for bullet in self.bullets if not bullet.remove ] pygame.display.flip() self.clock.tick(self.FPS) print(self.points)
def test_comparisons(): i1, i2, i3 = I.closed(0, 1), I.closed(1, 2), I.closed(2, 3) assert i1 == i1 assert i1 != i2 assert i1 != i3 assert i1 < i3 assert not (i1 < i2) assert i1 <= i2 assert i1 <= i3 assert not (i2 <= i1) assert i3 > i1 assert not (i2 > i1) assert i2 >= i1 assert i3 >= i1 assert not (i1 >= i2) i4 = i1 | i3 assert i4 != i2 assert not i4 < i2 assert not i4 <= i2 assert not i4 > i2 assert not i4 >= i2 assert i2 <= i4 assert i2 >= i4 i5 = I.closed(5, 6) | I.closed(7, 8) assert i4 != i5 assert i4 < i5 assert i4 <= i5 assert i5 >= i4 assert not i4 > i5 assert not i4 >= i5 assert not i5 <= i4 assert not i1 == 1 with pytest.raises(TypeError): i1 > 1 with pytest.raises(TypeError): i1 >= 1 with pytest.raises(TypeError): i1 < 1 with pytest.raises(TypeError): i1 <= 1
def test_from_string(): i1, i2, i3, i4 = '[0,1]', '(0,1]', '[0,1)', '(0,1)' assert I.from_string(i1, int) == I.closed(0, 1) assert I.from_string(i2, int) == I.openclosed(0, 1) assert I.from_string(i3, int) == I.closedopen(0, 1) assert I.from_string(i4, int) == I.open(0, 1) assert I.from_string('()', int) == I.empty() assert I.from_string('[1]', int) == I.singleton(1) assert I.from_string('[0,1] | [2,3]', int) == I.closed(0, 1) | I.closed(2, 3) with pytest.raises(Exception): I.from_string('[1,2]', None)
def start_game(self): pygame.init() self.game_display = pygame.display.set_mode((self.width, self.height)) self.font = pygame.font.Font('TypewriterScribbled.ttf', self.font_size) quit_game = False while not quit_game: self.time += 1 self.game_display.fill(self.background) pygame.draw.line(self.game_display, (0, 0, 0), (0, self.ground), (self.width, self.ground), 10) self.draw_menu() self.draw_obj(self.player) self.player.move() self.time_obs += 1 if self.time_obs > 0 else 0 self.time_obs = 0 if self.time_obs == 40 else self.time_obs if random.random() < 0.008 and self.time_obs == 0: self.obstacles.append(Obstacle(self)) self.time_obs += 1 self.obstacles = [ ob for ob in self.obstacles if ob.x > -110 and not ob.remove ] keys = pygame.key.get_pressed() if keys[pygame.K_DOWN]: self.player.crouch() for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE or event.key == pygame.K_UP: self.player.jump() if event.type == pygame.KEYUP: if event.key == pygame.K_DOWN: self.player.erect() if event.type == pygame.QUIT: quit_game = True pygame.quit() quit() pygame.display.flip() for ob in self.obstacles: self.draw_obj(ob) ob.move() if i.closed(ob.x, ob.x + ob.width).overlaps(i.closed(self.player.x, self.player.x + self.player.width)) \ and i.closed(ob.y, ob.y + ob.height).overlaps( i.closed(self.player.y, self.player.y + self.player.height)): quit_game = True pygame.quit() quit() pygame.display.flip() self.clock.tick(self.FPS)
def load_user_incident_intervals(all_oncall, participation_matchers): assert all_oncall != I.empty() since = arrow.get(all_oncall.lower) until = arrow.get(all_oncall.upper) incident_intervals = I.empty() for incident in pypd.Incident.find(since=since, until=until): # Make sure that the start time of the incident is in a waiting window incident_start = __pd_parse_time(incident['created_at']).timestamp if all_oncall.contains(incident_start): # Add this incident interval to the list of incident work times participation_start = __user_participated_at_timestamp( incident, participation_matchers, ) incident_end = __pd_parse_time( incident['last_status_change_at'] ).timestamp participation_ival = I.closed(participation_start, incident_end) incident_intervals = incident_intervals.union(participation_ival) if participation_start < I.inf: logger.debug( 'User participated in incident %s from %s - %s', incident['id'], participation_start, incident_end ) return incident_intervals
def initialise(): with open(sys.argv[1]) as file: data = file.readlines() instructions = [] for line in data: op = line.split(' ')[0] ranges = ''.join(line.split(' ')[1:]) values = [int(x) for x in re.findall(r'-{0,1}\d{1,10}', ranges)] ix = I.closed(values[0], values[1]) iy = I.closed(values[2], values[3]) iz = I.closed(values[4], values[5]) instructions.append((op, (ix, iy, iz))) return instructions
def split_into_days(activity_intervals, tz): start = I.inf end = -I.inf for _, intervals in activity_intervals: start = min(start, intervals.lower) end = max(end, intervals.upper) midnights = I.empty() day_span_range = arrow.Arrow.span_range( 'day', arrow.get(start), arrow.get(end), tz=tz, ) for midnight, _ in day_span_range: midnights = midnights.union( I.closed(midnight.timestamp, midnight.timestamp) ) logger.debug('Midnights: %s', midnights) hours_per_day = defaultdict(lambda: defaultdict(int)) for report_name, intervals in activity_intervals: if intervals == I.empty(): continue pay_interval_by_day = intervals.difference(midnights) for day_interval in pay_interval_by_day: logger.debug( 'Day interval[%s]: %s - %s', report_name, day_interval.lower, day_interval.upper, ) total_seconds = day_interval.upper - day_interval.lower interval_date = datetime.fromtimestamp(day_interval.lower).date() hours_per_day[interval_date][report_name] += total_seconds/3600 return hours_per_day
import csv import logging import sys from collections import namedtuple import intervals as I from . import report logger = logging.getLogger(__name__) SCHEDULES = { 'MonFri': I.closed(0, 4), 'SunThu': I.closed(0, 3).union(I.closed(6,6)), } Engineer = namedtuple('Engineer', [ 'pagerduty_id', 'slack_username', 'day_start_time', 'oncall_schedules', 'day_length_hours', 'workday_schedule', 'time_zone', ])
def __times_to_interval(start, end): assert end > start return I.closed(start.timestamp, end.timestamp)