# HG changeset patch # User Paul Boddie # Date 1427465352 -3600 # Node ID 115d5a16926289e8966c2fede19e544c80023bfa # Parent e3874b61af108de7cf6e2a17383f5d225eb0a625 Added initial support for events occurring on an instant in time. diff -r e3874b61af10 -r 115d5a169262 imiptools/period.py --- a/imiptools/period.py Thu Mar 26 19:15:52 2015 +0100 +++ b/imiptools/period.py Fri Mar 27 15:09:12 2015 +0100 @@ -276,11 +276,13 @@ points.sort() for point, (starting, ending) in points: + ending = set(ending) + instants = ending.intersection(starting) # Discard all active events ending at or before this start time. # Free up the position in the active list. - for t in ending: + for t in ending.difference(instants): i = active.index(t) active[i] = None @@ -301,6 +303,22 @@ slots.append((point, active[:])) + # Discard events ending at the same time as they began. + + if instants: + for t in instants: + i = active.index(t) + active[i] = None + + # Discard vacant positions from the end of the active list. + + while active and active[-1] is None: + active.pop() + + # Add another entry for the time point without "instants". + + slots.append((point, active[:])) + return slots def add_day_start_points(slots, tzid): @@ -405,19 +423,13 @@ points = [point for point, active in slots] spans = {} - for point, active in slots: + for _point, active in slots: for t in active: if t and len(t) >= 2: start, end, uid, recurrenceid, summary, organiser, key = get_freebusy_details(t) - try: - start_slot = points.index(start) - except ValueError: - start_slot = 0 - try: - end_slot = points.index(end) - except ValueError: - end_slot = len(slots) + start_slot = bisect_left(points, (start,)) + end_slot = bisect_left(points, (end,)) spans[key] = end_slot - start_slot return spans diff -r e3874b61af10 -r 115d5a169262 imipweb/calendar.py --- a/imipweb/calendar.py Thu Mar 26 19:15:52 2015 +0100 +++ b/imipweb/calendar.py Fri Mar 27 15:09:12 2015 +0100 @@ -362,25 +362,33 @@ # Construct a list of time intervals within the day. intervals = [] + + # Convert each partition to a mapping from points to active + # periods. + + partitioned[day] = day_points = {} + last = None for point, active in day_slots: columns = max(columns, len(active)) if last: intervals.append((last, point)) + + # Qualify points in the day with an extra indicator to + # handle repeated time points due to instant events. + + day_points[(point, last == point and 1 or 0)] = active + last = point if last: intervals.append((last, None)) + day_points[(point, last == point and 1 or 0)] = active if not days.has_key(day): days[day] = set() - # Convert each partition to a mapping from points to active - # periods. - - partitioned[day] = dict(day_slots) - # Record the divisions or intervals within each day. days[day].update(intervals) @@ -538,7 +546,12 @@ intervals = list(intervals) intervals.sort() + last = None + for point, endpoint in intervals: + indicator = point == last and 1 or 0 + last = point + continuation = point == get_start_of_day(point, tzid) # Some rows contain no period details and are marked as such. @@ -547,7 +560,7 @@ have_active_request = False for slots, group_type in zip(groups, group_types): - if slots and slots.get(point): + if slots and slots.get((point, indicator)): if group_type == "request": have_active_request = True else: @@ -561,13 +574,14 @@ page.tr(class_=css) page.th(class_="timeslot") - self._time_point(point, endpoint) + if indicator == 0: + self._time_point(point, endpoint) page.th.close() # Obtain slots for the time point from each group. for columns, slots, group_type in zip(group_columns, groups, group_types): - active = slots and slots.get(point) + active = slots and slots.get((point, indicator)) # Where no periods exist for the given time interval, generate # an empty cell. Where a participant provides no periods at all,