Esempio n. 1
0
    def image(self, user):
        """Generates the current image based on the schedule."""

        # Find the current schedule entry by parsing the cron expressions.
        try:
            time = self.local_time.now(user)
        except DataError as e:
            raise ContentError(e)
        today = time.replace(hour=0, minute=0, second=0, microsecond=0)
        while True:
            entries = [(self._next(entry['start'], today, user), entry)
                       for entry in user.get('schedule')]
            if not entries:
                raise ContentError('Empty schedule')
            past_entries = list(filter(lambda x: x[0] <= time, entries))

            # Use the most recent past entry.
            if past_entries:
                latest_datetime, latest_entry = max(past_entries,
                                                    key=lambda x: x[0])
                break

            # If there were no past entries, try the previous day.
            today -= timedelta(days=1)

        # Generate the image from the current schedule entry.
        info('Using image from schedule entry: %s (%s, %s)' %
             (latest_entry['name'], latest_entry['start'],
              latest_datetime.strftime('%A %B %d %Y %H:%M:%S %Z')))
        image = self._image(latest_entry['image'], user)

        return image
Esempio n. 2
0
    def image(self, user, width, height):
        """Generates the current image based on the schedule."""

        # Find the current schedule entry by parsing the cron expressions.
        try:
            time = self._local_time.now(user)
        except DataError as e:
            raise ContentError(e)

        entries = [(self._previous(entry['start'], time, user), entry)
                   for entry in user.get('schedule')]

        if not entries:
            raise ContentError('Empty schedule')

        # Use the most recent past entry.
        latest_datetime, latest_entry = max(entries, key=lambda x: x[0])

        # Generate the image from the current schedule entry.
        info('Using image from schedule entry: %s (%s, %s)' %
             (latest_entry['name'], latest_entry['start'],
              latest_datetime.strftime('%A %B %d %Y %H:%M:%S %Z')))
        image = self._image(latest_entry['image'], user, width, height)

        return image
Esempio n. 3
0
    def _previous(self, cron, before, user):
        """Find the previous time matching the cron expression."""
        try:
            cron = self._sun.rewrite_cron(cron, before, user)
        except DataError as e:
            raise ContentError(e)

        try:
            return croniter(cron, before).get_prev(datetime)
        except ValueError as e:
            raise ContentError(e)
Esempio n. 4
0
    def _next(self, cron, after, user):
        """Find the next time matching the cron expression."""
        try:
            cron = self._sun.rewrite_cron(cron, after, user)
        except DataError as e:
            raise ContentError(e)

        try:
            return croniter(cron, after).get_next(datetime)
        except ValueError as e:
            raise ContentError(e)
Esempio n. 5
0
    def image(self, user, width, height):
        """Generates the current commute image."""

        # Extract the directions data.
        try:
            directions = self._google_maps.directions(user)
            status = directions['status']
            if status != 'OK':
                try:
                    error_message = directions['error_message']
                    raise DataError(error_message)
                except KeyError:
                    raise DataError(status)
            routes = directions['routes']
            route = routes[0]
            polyline = route['overview_polyline']['points']
            summary = route['summary']
            leg = route['legs'][0]  # Expect one leg.
            try:
                duration = leg['duration_in_traffic']['text']
            except KeyError:
                duration = leg['duration']['text']
        except (DataError, IndexError, KeyError) as e:
            raise ContentError(e)

        # Get the static map with the route as an image.
        try:
            image = self._google_maps.map_image(width,
                                                height,
                                                polyline=polyline)
        except DataError as e:
            raise ContentError(e)

        # Draw the directions text inside a centered box.
        if summary:
            directions_text = '%s via %s' % (duration, summary)
        else:
            directions_text = duration
        draw_text(directions_text,
                  font_spec=SUBVARIO_CONDENSED_MEDIUM,
                  text_color=DIRECTIONS_TEXT_COLOR,
                  anchor='center',
                  box_color=DIRECTIONS_BOX_COLOR,
                  box_padding=DIRECTIONS_BOX_PADDING,
                  border_color=DIRECTIONS_BORDER_COLOR,
                  border_width=DIRECTIONS_BORDER_WIDTH,
                  image=image)

        return image
Esempio n. 6
0
    def image(self, user, width, height):
        """Generates the current city image."""

        image = Image.new(mode='RGB', size=(width, height))
        try:
            self._draw_layers(image, self._layers(), user, width, height)
            return image
        except DataError as e:
            raise ContentError(e)
Esempio n. 7
0
    def image(self, user):
        """Generates the current city image."""

        image = Image.new(mode='RGB', size=(DISPLAY_WIDTH, DISPLAY_HEIGHT))
        try:
            self._draw_layers(image, self._layers(), user)
            return image
        except DataError as e:
            raise ContentError(e)
Esempio n. 8
0
    def image(self, user, width, height):
        """Generates a map with user locations."""

        try:
            return self._google_maps.map_image(width, height,
                                               markers=self._markers(),
                                               marker_icon=MARKER_ICON_URL)
        except DataError as e:
            raise ContentError(e)
Esempio n. 9
0
    def delay(self, user):
        """Calculate the delay in milliseconds to the next schedule entry."""
        # Find the next schedule entry by parsing the cron expressions.
        try:
            time = self._local_time.now(user)
        except DataError as e:
            raise ContentError(e)
        entries = [(self._next(entry['start'], time, user), entry)
                   for entry in user.get('schedule')]
        if not entries:
            raise ContentError('Empty schedule')
        next_datetime, next_entry = min(entries, key=lambda x: x[0])

        # Calculate the delay in milliseconds.
        seconds = (next_datetime - time).total_seconds()
        seconds += DELAY_BUFFER_S
        milliseconds = int(seconds * 1000)
        info('Using time from schedule entry: %s (%s, %s, in %d ms)' %
             (next_entry['name'], next_entry['start'],
              next_datetime.strftime('%A %B %d %Y %H:%M:%S %Z'), milliseconds))

        return milliseconds
Esempio n. 10
0
    def image(self, user, width, height):
        """Generates an image with a calendar view."""

        # Show a calendar relative to the current date.
        try:
            time = self._local_time.now(user)
        except DataError as e:
            raise ContentError(e)

        # Get the number of events per day from the API.
        event_counts = self._event_counts(time, user)

        # Create a blank image.
        image = Image.new(mode='RGB',
                          size=(width, height),
                          color=BACKGROUND_COLOR)
        draw = Draw(image)

        # Get this month's calendar.
        try:
            firstweekday = WEEK_DAYS[user.get('first_week_day')]
        except KeyError:
            firstweekday = SUNDAY
        calendar = Calendar(firstweekday=firstweekday)
        weeks = calendar.monthdayscalendar(time.year, time.month)

        # Determine the spacing of the days in the image.
        x_stride = width // (DAYS_IN_WEEK + 1)
        y_stride = height // (len(weeks) + 1)

        # Draw each week in a row.
        for week_index in range(len(weeks)):
            week = weeks[week_index]

            # Draw each day in a column.
            for day_index in range(len(week)):
                day = week[day_index]

                # Ignore days from other months.
                if day == 0:
                    continue

                # Determine the position of this day in the image.
                x = (day_index + 1) * x_stride
                y = (week_index + 1) * y_stride

                # Mark the current day with a squircle.
                if day == time.day:
                    squircle = Image.open(SQUIRCLE_FILE).convert(mode='RGBA')
                    squircle_xy = (x - squircle.width // 2,
                                   y - squircle.height // 2)
                    draw.bitmap(squircle_xy, squircle, HIGHLIGHT_COLOR)
                    number_color = TODAY_COLOR
                    event_color = TODAY_COLOR
                else:
                    number_color = NUMBER_COLOR
                    event_color = HIGHLIGHT_COLOR

                # Draw the day of the month number.
                number = str(day)
                draw_text(number,
                          SUBVARIO_CONDENSED_MEDIUM,
                          number_color,
                          xy=(x, y - NUMBER_Y_OFFSET),
                          image=image)

                # Draw a dot for each event.
                num_events = min(MAX_EVENTS, event_counts[day])
                dot = Image.open(DOT_FILE).convert(mode='RGBA')
                if num_events > 0:
                    events_width = (num_events * dot.width +
                                    (num_events - 1) * DOT_MARGIN)
                    for event_index in range(num_events):
                        event_offset = (event_index *
                                        (dot.width + DOT_MARGIN) -
                                        events_width // 2)
                        dot_xy = [
                            x + event_offset, y + DOT_OFFSET - dot.width // 2
                        ]
                        draw.bitmap(dot_xy, dot, event_color)

        return image