EventAggregator

Changeset

171:41f74731f672
2011-04-03 Paul Boddie raw files shortlog changelog graph Reverted various attempts to use TimespanCollection as a container for shown events, since it is not appropriate for collections of overlapping events. Reintroduced the getEventsInPeriod function, but without the resolution parameter, since it is only applicable when determining event coverage and whether events collide in a particular slot. Added a getEventLimits function to separately determine the earliest and latest event times.
EventAggregatorSupport.py (file) actions/EventAggregatorSummary.py (file) macros/EventAggregator.py (file)
     1.1 --- a/EventAggregatorSupport.py	Sun Apr 03 02:31:06 2011 +0200
     1.2 +++ b/EventAggregatorSupport.py	Sun Apr 03 18:42:04 2011 +0200
     1.3 @@ -781,14 +781,14 @@
     1.4  
     1.5      return events
     1.6  
     1.7 -def getEventsInPeriod(events, calendar_period, resolution):
     1.8 +def getEventsInPeriod(events, calendar_period):
     1.9  
    1.10      """
    1.11      Return a collection containing those of the given 'events' which occur
    1.12 -    within the given 'calendar_period' at the given 'resolution'.
    1.13 +    within the given 'calendar_period'.
    1.14      """
    1.15  
    1.16 -    all_shown_events = TimespanCollection(resolution)
    1.17 +    all_shown_events = []
    1.18  
    1.19      for event in events:
    1.20  
    1.21 @@ -799,10 +799,30 @@
    1.22              # Compare the dates to the requested calendar window, if any.
    1.23  
    1.24              if event in calendar_period:
    1.25 -                all_shown_events.insert_in_order(event)
    1.26 +                all_shown_events.append(event)
    1.27  
    1.28      return all_shown_events
    1.29  
    1.30 +def getEventLimits(events):
    1.31 +
    1.32 +    "Return the earliest and latest of the given 'events'."
    1.33 +
    1.34 +    earliest = None
    1.35 +    latest = None
    1.36 +
    1.37 +    for event in events:
    1.38 +
    1.39 +        # Test for the suitability of the event.
    1.40 +
    1.41 +        if event.as_timespan() is not None:
    1.42 +            ts = event.as_timespan()
    1.43 +            if earliest is None or ts.start < earliest:
    1.44 +                earliest = ts.start
    1.45 +            if latest is None or ts.end > latest:
    1.46 +                latest = ts.end
    1.47 +
    1.48 +    return earliest, latest
    1.49 +
    1.50  def setEventTimestamps(request, events):
    1.51  
    1.52      """
    1.53 @@ -848,12 +868,11 @@
    1.54      ordered_events.sort()
    1.55      return ordered_events
    1.56  
    1.57 -def getCalendarPeriod(calendar_start, calendar_end, resolution):
    1.58 +def getCalendarPeriod(calendar_start, calendar_end):
    1.59  
    1.60      """
    1.61 -    Return a calendar period for the given 'calendar_start' and 'calendar_end',
    1.62 -    employing the given 'resolution'. The 'calendar_start' and 'calendar_end'
    1.63 -    parameters can be given as None.
    1.64 +    Return a calendar period for the given 'calendar_start' and 'calendar_end'.
    1.65 +    These parameters can be given as None.
    1.66      """
    1.67  
    1.68      # Re-order the window, if appropriate.
    1.69 @@ -861,9 +880,7 @@
    1.70      if calendar_start is not None and calendar_end is not None and calendar_start > calendar_end:
    1.71          calendar_start, calendar_end = calendar_end, calendar_start
    1.72  
    1.73 -    # Return a timespan at the given resolution.
    1.74 -
    1.75 -    return Timespan(calendar_start, calendar_end).convert(resolution)
    1.76 +    return Timespan(calendar_start, calendar_end)
    1.77  
    1.78  def getConcretePeriod(calendar_start, calendar_end, earliest, latest):
    1.79  
    1.80 @@ -1613,8 +1630,9 @@
    1.81  class TimespanCollection:
    1.82  
    1.83      """
    1.84 -    A collection of timespans providing a list-like interface supporting
    1.85 -    membership tests at a particular resolution.
    1.86 +    A class providing a list-like interface supporting membership tests at a
    1.87 +    particular resolution in order to maintain a collection of non-overlapping
    1.88 +    timespans.
    1.89      """
    1.90  
    1.91      def __init__(self, resolution, values=None):
    1.92 @@ -1640,7 +1658,8 @@
    1.93  
    1.94      def convert(self, value):
    1.95          if isinstance(value, ActsAsTimespan):
    1.96 -            return value.as_timespan().convert(self.resolution)
    1.97 +            ts = value.as_timespan()
    1.98 +            return ts and ts.convert(self.resolution)
    1.99          else:
   1.100              return value.convert(self.resolution)
   1.101  
   1.102 @@ -1670,13 +1689,7 @@
   1.103          return self.values.pop()
   1.104  
   1.105      def insert_in_order(self, value):
   1.106 -        i = bisect.bisect_left(self, self.convert(value))
   1.107 -        self.insert(i, value)
   1.108 -
   1.109 -    def items_in_range(self, start, end):
   1.110 -        slice_start = bisect.bisect_left(self, start)
   1.111 -        slice_end = bisect.bisect_right(self, end, slice_start)
   1.112 -        return self.values[slice_start:slice_end]
   1.113 +        bisect.insort_left(self, value)
   1.114  
   1.115  def getCountry(s):
   1.116  
     2.1 --- a/actions/EventAggregatorSummary.py	Sun Apr 03 02:31:06 2011 +0200
     2.2 +++ b/actions/EventAggregatorSummary.py	Sun Apr 03 18:42:04 2011 +0200
     2.3 @@ -270,9 +270,7 @@
     2.4  
     2.5      event_pages = getPagesFromResults(getAllCategoryPages(category_names, request), request)
     2.6      events = getEventsFromPages(event_pages)
     2.7 -    calendar_period = getCalendarPeriod(calendar_start, calendar_end, resolution)
     2.8 -    all_shown_events = getEventsInPeriod(events, calendar_period, resolution)
     2.9 -
    2.10 +    all_shown_events = getEventsInPeriod(events, getCalendarPeriod(calendar_start, calendar_end))
    2.11      latest_timestamp = setEventTimestamps(request, all_shown_events)
    2.12  
    2.13      # Output summary data...
    2.14 @@ -374,12 +372,7 @@
    2.15          if latest_timestamp is not None:
    2.16              request.write('<lastBuildDate>%s</lastBuildDate>\r\n' % getHTTPTimeString(latest_timestamp))
    2.17   
    2.18 -        # Sort all_shown_events by start date, reversed:
    2.19 -        #
    2.20 -        #  * event_details are dictionaries, with the "start" entry providing
    2.21 -        #    the start date
    2.22 -        #
    2.23 -        # So we use as sorting key the "start" key from the event details.
    2.24 +        # Sort all_shown_events by start date, reversed.
    2.25  
    2.26          ordered_events = getOrderedEvents(all_shown_events)
    2.27          ordered_events.reverse()
     3.1 --- a/macros/EventAggregator.py	Sun Apr 03 02:31:06 2011 +0200
     3.2 +++ b/macros/EventAggregator.py	Sun Apr 03 18:42:04 2011 +0200
     3.3 @@ -1144,14 +1144,10 @@
     3.4  
     3.5      # Get the events according to the resolution of the calendar.
     3.6  
     3.7 -    resolution = mode == "day" and "date" or "month"
     3.8 -
     3.9      event_pages      = getPagesFromResults(getAllCategoryPages(category_names, request), request)
    3.10      events           = getEventsFromPages(event_pages)
    3.11 -    calendar_period  = getCalendarPeriod(calendar_start, calendar_end, resolution)
    3.12 -    all_shown_events = getEventsInPeriod(events, calendar_period, resolution)
    3.13 -
    3.14 -    earliest, latest = all_shown_events.as_limits()
    3.15 +    all_shown_events = getEventsInPeriod(events, getCalendarPeriod(calendar_start, calendar_end))
    3.16 +    earliest, latest = getEventLimits(all_shown_events)
    3.17  
    3.18      # Get a concrete period of time.
    3.19  
    3.20 @@ -1195,13 +1191,9 @@
    3.21          output.append(fmt.table_cell(on=0))
    3.22          output.append(fmt.table_row(on=0))
    3.23  
    3.24 -        # Get the events in order.
    3.25 -
    3.26 -        ordered_events = getOrderedEvents(all_shown_events)
    3.27 -
    3.28          # Show the events in order.
    3.29  
    3.30 -        for event in ordered_events:
    3.31 +        for event in all_shown_events:
    3.32              event_page = event.getPage()
    3.33              event_summary = event.getSummary(parent_name)
    3.34              event_details = event.getDetails()
    3.35 @@ -1308,7 +1300,7 @@
    3.36                      week_end = month.as_date(min(first_day + 6, number_of_days))
    3.37  
    3.38                      full_coverage, week_slots = getCoverage(
    3.39 -                        all_shown_events.items_in_range(week_start, week_end.next_day()))
    3.40 +                        getEventsInPeriod(all_shown_events, getCalendarPeriod(week_start, week_end)))
    3.41  
    3.42                      # Output a week, starting with the day numbers.
    3.43  
    3.44 @@ -1350,14 +1342,9 @@
    3.45  
    3.46                  output.append(fmt.bullet_list(on=1, attr={"class" : "event-month-listings"}))
    3.47  
    3.48 -                # Get the events in order.
    3.49 -
    3.50 -                ordered_events = getOrderedEvents(
    3.51 -                    all_shown_events.items_in_range(month, month.next_month()))
    3.52 -
    3.53                  # Show the events in order.
    3.54  
    3.55 -                for event in ordered_events:
    3.56 +                for event in getEventsInPeriod(all_shown_events, getCalendarPeriod(month, month)):
    3.57                      event_page = event.getPage()
    3.58                      event_details = event.getDetails()
    3.59                      event_summary = event.getSummary(parent_name)
    3.60 @@ -1423,7 +1410,7 @@
    3.61              output.append(fmt.table(on=1, attrs={"tableclass" : "event-calendar-day"}))
    3.62  
    3.63              full_coverage, day_slots = getCoverage(
    3.64 -                all_shown_events.items_in_range(date, date.next_day()), "datetime")
    3.65 +                getEventsInPeriod(all_shown_events, getCalendarPeriod(date, date)), "datetime")
    3.66  
    3.67              # Work out how many columns the day title will need.
    3.68              # Include spacers before each event column.